Commit Graph

74 Commits

Author SHA1 Message Date
Mitchell Hashimoto
714420409b libghostty: add placement_rect and centralize opaque typedefs
Expose Placement.rect() from the Zig kitty graphics storage as a new
C API function ghostty_kitty_graphics_placement_rect(). It takes the
terminal, image handle, and a positioned placement iterator, and
writes the bounding grid rectangle into a GhosttySelection out param.
Virtual placements return GHOSTTY_NO_VALUE.

Move all opaque handle typedefs (GhosttyTerminal, GhosttyKittyGraphics,
GhosttyRenderState, GhosttySgrParser, GhosttyFormatter, GhosttyOsc*)
into types.h so they are available everywhere without circular includes
and Doxygen renders them in the correct @ingroup sections.
2026-04-06 09:58:32 -07:00
Mitchell Hashimoto
46a69ea63d libghostty: add kitty graphics image lookup API
Add a GhosttyKittyGraphicsImage opaque type and API for looking up
images by ID and querying their properties. This complements the
existing placement iterator by allowing direct image introspection.

The new ghostty_kitty_graphics_image() function looks up an image by
its ID from the storage, returning a borrowed opaque handle. Properties
are queried via ghostty_kitty_image_get() using the new
GhosttyKittyGraphicsImageData enum, which exposes id, number, width,
height, format, compression, and a borrowed data pointer with length.

Format and compression are exposed as their own C enum types
(GhosttyKittyImageFormat and GhosttyKittyImageCompression) rather
than raw integers.
2026-04-06 09:27:51 -07:00
Mitchell Hashimoto
9033f6f8ce libghostty: add kitty graphics placement iterator API
Add a C API for iterating over Kitty graphics placements via the
new GhosttyKittyGraphics opaque handle. The API follows the same
pattern as the render state row iterator: allocate an iterator with
ghostty_kitty_graphics_placement_iterator_new, populate it from a
graphics handle via ghostty_kitty_graphics_get with the
PLACEMENT_ITERATOR data kind, advance with
ghostty_kitty_graphics_placement_next, and query per-placement
fields with ghostty_kitty_graphics_placement_get.
2026-04-06 09:15:26 -07:00
Mitchell Hashimoto
d7fa92088c libghostty: expose sys interface to C API
The terminal sys module provides runtime-swappable function pointers
for operations that depend on external implementations (e.g. PNG
decoding). This exposes that functionality through the C API via a
ghostty_sys_set() function, modeled after the ghostty_terminal_set()
enum-based option pattern.

Embedders can install a PNG decode callback to enable Kitty Graphics
Protocol PNG support. The callback receives a userdata pointer
(set via GHOSTTY_SYS_OPT_USERDATA) and a GhosttyAllocator that must
be used to allocate the returned pixel data, since the library takes
ownership of the buffer. Passing NULL clears the callback and
disables the feature.
2026-04-06 07:45:16 -07:00
Mitchell Hashimoto
29e3de737e terminal: make wuffs runtime-swappable, enable Kitty graphics for libvt
Introduce terminal/sys.zig which provides runtime-swappable function
pointers for operations that depend on external implementations. This
allows embedders of the terminal package to swap out implementations
at startup without hard dependencies on specific libraries.

The first function exposed is decode_png, which defaults to a wuffs
implementation. The kitty graphics image loader now calls through
sys.decode_png instead of importing wuffs directly.

This allows us to enable Kitty graphics support in libghostty-vt
for all targets except wasm32-freestanding.
2026-04-04 22:01:38 -07:00
Mitchell Hashimoto
b9a241d1e2 libghostty: add hyperlink URI accessor to grid_ref API
Add ghostty_grid_ref_hyperlink_uri to extract the OSC 8 hyperlink
URI from a cell at a grid reference position. Follows the same
buffer pattern as ghostty_grid_ref_graphemes: callers pass a buffer
and get back the byte length, or GHOSTTY_OUT_OF_SPACE with the
required size if the buffer is too small. Cells without a hyperlink
return success with length 0.
2026-04-04 20:28:13 -07:00
Mitchell Hashimoto
2e827cc39d vt: add ghostty_type_json for struct layout metadata
Add a new C API function that returns a comptime-generated JSON string
describing the size, alignment, and field layout of every C API extern
struct. This lets FFI consumers (particularly WASM) construct structs
by byte offset without hardcoding platform-specific layout.

The JSON is built at comptime using std.json.Stringify via a
StructInfo type that holds per-struct metadata and implements
jsonStringify. A StaticStringMap keyed by C struct name provides
lookup by name as well as iteration for the JSON serialization.

The function is declared in types.h alongside the other common types
and exported as ghostty_type_json.
2026-03-30 10:16:19 -07:00
Mitchell Hashimoto
11574c35a2 libghostty: expose paste encode to C API
Add ghostty_paste_encode() which encodes paste data for writing to
the terminal pty. It strips unsafe control bytes, wraps in bracketed
paste sequences when requested, and replaces newlines with carriage
returns for unbracketed mode. The input buffer is modified in place
and the encoded result is written to a caller-provided output buffer,
following the same buffer/out_written pattern as the other encode
functions like ghostty_size_report_encode.

Update the c-vt-paste example with an encode_example() demonstrating
the new function and add corresponding @snippet references in the
header documentation.
2026-03-26 11:28:23 -07:00
Mitchell Hashimoto
b91cc867a8 vt: add ghostty_terminal_set for configuring effects callbacks
Add a typed option setter ghostty_terminal_set() following the
existing setopt pattern used by the key encoder and render state
APIs. This is the first step toward exposing stream_terminal
Handler.Effects through the C API.

The initial implementation includes a write_pty callback and a
shared userdata pointer. The write_pty callback is invoked
synchronously during ghostty_terminal_vt_write() when the terminal
needs to send a response back to the pty, such as DECRQM mode
reports or device status responses.

Trampolines are always installed at terminal creation time and
no-op when no C callback is set, so callers can configure
callbacks at any point without reinitializing the stream. The C
callback state is grouped into an internal Effects struct on the
TerminalWrapper to simplify adding more callbacks in the future.
2026-03-24 11:11:07 -07:00
Mitchell Hashimoto
67db6b8960 libghostty: add ghostty_free for cross-runtime memory safety (#11785)
## What

On Windows, calling `free()` on memory allocated by libghostty crashes
because Zig and MSVC use separate heaps.

This adds `ghostty_free()` so consumers can free library-allocated
memory safely on all platforms.

## Why

When Zig builds a DLL on Windows with `link_libc = true`, it does not
link the Windows C runtime (`ucrtbase.dll`). Instead it uses its own
libc built on top of `KERNEL32.dll`. So `builtin.link_libc` is true and
`c_allocator` is selected, but Zig's `malloc` and MSVC's `malloc` are
different implementations with different heaps. 💥

On Linux/macOS this is not a problem because Zig links the system libc
and everyone shares the same heap. On Windows, `free(buf)` from MSVC
tries to free memory from Zig's heap and you get a debug assertion
failure or undefined behavior.

The `format_alloc` docs said "the buffer can be freed with `free()`" but
that is only true when the library and consumer share the same C
runtime, which is not the case on Windows.

## How

- Add `ghostty_free(allocator, ptr, len)` that frees through the same
allocator that did the allocation
- Update `format_alloc` docs to point to `ghostty_free()` instead of
`free()`
- Update all 3 examples to use `ghostty_free(NULL, buf, len)`

The signature takes an allocator because raw buffers (unlike objects
like terminals or formatters) do not store their allocator internally.
The caller already has all three values: the allocator they passed, the
pointer, and the length they got back.

I went back and forth on the naming. Other options I considered:
`ghostty_alloc_free(allocator, ptr, len)` or returning a `GhosttyBuffer`
wrapper with its own `_free`. Happy to change the naming if there is a
preference.

No impact on Linux/macOS. `ghostty_free()` works correctly there too, it
just happens to call the same `free()` the consumer would have called
anyway.

## Verified

- `zig build test-lib-vt` passes on Windows, macOS arm64, Linux x86_64
(exit 0)
- `zig build test` passes on Windows (2575/2619 passed, 1 pre-existing
font sprite failure) and macOS (exit 0)
- cmake shared example builds, links, and runs correctly on Windows with
`ghostty_free()` (no more heap crash)

## What I Learnt

- What I wrote in Why
- Zig allocators require the length to free (no hidden metadata headers
like C's malloc). This is a deliberate design choice for explicit
control.
- The standard pattern for C libraries on Windows is "whoever allocates,
frees" (like `curl_free()`, `SDL_free()`). This avoids cross-runtime
heap issues entirely.
2026-03-23 16:23:10 -07:00
Mitchell Hashimoto
b819ce0e20 vt: add ghostty_alloc for buffer allocation
Add a ghostty_alloc function that pairs with the existing
ghostty_free, giving embedders a symmetric malloc/free-style
API for buffer allocation through the libghostty allocator
interface. Returns NULL on allocation failure.
2026-03-23 16:12:29 -07:00
Mitchell Hashimoto
7039f566bb vt: move free_alloc to dedicated allocator.zig
Extract the inline free_alloc function from main.zig into a new
allocator.zig module in the C API layer. The function is renamed
to alloc_free in main.zig (and free in allocator.zig) for
consistency with the other C API naming conventions. Add tests
for null pointer, allocated memory, and null allocator fallback.
2026-03-23 16:08:32 -07:00
Mitchell Hashimoto
67d8d86efd terminal: rename ReadonlyStream to TerminalStream
Rename stream_readonly.zig to stream_terminal.zig and its exported
types from ReadonlyStream/ReadonlyHandler to TerminalStream. The
"readonly" name is now wrong since the handler now supports
settable effects callbacks. The new name better reflects that this
is a stream handler for updating terminal state.
2026-03-23 14:17:10 -07:00
Alessandro De Blasis
c1e616c6cd libghostty: add ghostty_free for cross-runtime memory safety
On Windows, Zig's built-in libc and MSVC's CRT maintain separate
heaps, so calling free() on memory allocated by the library causes
undefined behavior. Add ghostty_free() that frees through the same
allocator that performed the allocation, making it safe on all
platforms.

Update format_alloc docs and all examples to use ghostty_free()
instead of free().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 20:52:02 +01:00
Mitchell Hashimoto
c3b7fd8477 vt: add ghostty_build_info API for querying build configuration
Add a new C API function ghostty_build_info() that exposes compile-time
build options to library consumers. This allows callers to query whether
SIMD, Kitty graphics protocol, and tmux control mode support were
enabled at build time.
2026-03-21 07:22:18 -07:00
Mitchell Hashimoto
6ae17a02af vt: add cell-level iteration and data access to render state row cells
Add next, select, and get functions to the render state row cells
API, mirroring the row iterator pattern. row_cells_next advances to
the next cell sequentially, row_cells_select jumps to a specific
column index with bounds validation, and row_cells_get queries data
for the current cell position.

The get function supports querying raw cell values (GhosttyCell),
resolved styles (GhosttyStyle), grapheme codepoint counts, and
writing grapheme codepoints into a caller-provided buffer.

Also add Cell.C and Cell.cval() to page.zig, matching the existing
Row.C/Row.cval() pattern, so the render state can convert cells to
the C ABI type without a raw bitCast.
2026-03-20 08:53:45 -07:00
Mitchell Hashimoto
75b49051a3 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.
2026-03-20 07:25:52 -07:00
Mitchell Hashimoto
33e81ffb75 vt: use get/set pattern for row iterator data access
Replace ghostty_render_state_row_dirty_get and
ghostty_render_state_row_dirty_set with generic
ghostty_render_state_row_get and ghostty_render_state_row_set
functions using enum-dispatched data/option kinds.
2026-03-20 07:17:00 -07:00
Mitchell Hashimoto
459583a6c3 vt: use get/set pattern for render state data access
Replace the individual ghostty_render_state_size_get,
ghostty_render_state_dirty_get, and ghostty_render_state_dirty_set
functions with generic ghostty_render_state_get and
ghostty_render_state_set functions that use enum-dispatched data
kinds and option kinds, following the same InType/OutType pattern
used by the terminal and mouse encoder C APIs.
2026-03-20 07:00:14 -07:00
Mitchell Hashimoto
2147b9d65c vt: row dirty tracking 2026-03-19 20:13:14 -07:00
Mitchell Hashimoto
f610d7e00f vt: add render_row_iterator_next 2026-03-19 20:13:14 -07:00
Mitchell Hashimoto
ad0e47ebac vt: cover c row iterator new/free
Add a C ABI row-iterator handle for render state with
ghostty_render_state_row_iterator_new and
ghostty_render_state_row_iterator_free, and wire them through
src/terminal/c/main.zig, src/lib_vt.zig, and
include/ghostty/vt/render.h. The header now documents only the
currently exported iterator API.
2026-03-19 20:13:14 -07:00
Mitchell Hashimoto
b35f8ed16e vt: expose render state colors in C API
Add a C-facing GhosttyRenderStateColors sized struct and a
ghostty_render_state_colors_get accessor so renderers can read
background, foreground, cursor color state, and palette data directly
from the render state.
2026-03-19 20:13:14 -07:00
Mitchell Hashimoto
b830a0ee1d vt: add size getter for render state
Add ghostty_render_state_size_get() to return cols and rows from the
current render state using out pointers. The C wrapper validates null
inputs, the symbol is wired through the C API export layers, and tests
cover success and invalid-value paths.
2026-03-19 20:13:14 -07:00
Mitchell Hashimoto
2876fb7a55 vt: expose dirty state in C API
Switch RenderState.Dirty to lib.Enum so it uses C-compatible enum
backing when building the C ABI target. Add GhosttyRenderStateDirty and
new ghostty_render_state_dirty_get/set declarations to the render header,
then wire both functions through src/terminal/c/main.zig and the lib_vt
export table.
2026-03-19 20:13:14 -07:00
Mitchell Hashimoto
a0d738697e vt: add c render state api and example
Introduce the first public C render-state surface for libghostty-vt.
Before this change, the render-state path was only available in Zig,
so C embedders had no direct way to create and update that cache.

Add an opaque GhosttyRenderState type with new, update, and free
entry points, then wire those symbols through the C API bridge and
library exports. Keep the surface intentionally minimal for now so
ownership and update behavior are established before adding read
accessors.
2026-03-19 20:13:14 -07:00
Mitchell Hashimoto
549824842d vt: add style and grapheme accessors
Add ghostty_grid_ref_style and ghostty_grid_ref_graphemes to the grid
ref C API, allowing callers to extract the full style and grapheme
cluster directly from a grid reference without manually resolving
the page internals.
2026-03-19 19:48:16 -07:00
Mitchell Hashimoto
df8813bf1b vt: replace ghostty_terminal_cell with GhosttyGridRef API 2026-03-19 19:40:53 -07:00
Mitchell Hashimoto
0400de28b4 vt: add ghostty_terminal_cell for point-based cell lookup
Add a new C API function ghostty_terminal_cell that retrieves the
opaque cell and row values at a given point in the terminal grid.
The point is a tagged union supporting active, viewport, screen, and
history coordinate systems.
2026-03-19 15:16:55 -07:00
Mitchell Hashimoto
5c8b9f3f43 vt: add GhosttyCell and GhosttyRow C API with data getters
Add opaque GhosttyCell (uint64_t) and GhosttyRow (uint64_t) types that
bitcast to the internal packed Cell and Row structs from page.zig. Each
type has a corresponding data enum and getter function following the
same pattern as ghostty_terminal_get.

ghostty_cell_get supports extracting codepoint, content tag, wide
property, has_text, has_styling, style_id, has_hyperlink, protected,
and semantic_content. ghostty_row_get supports wrap, wrap_continuation,
grapheme, styled, hyperlink, semantic_prompt, kitty_virtual_placeholder,
and dirty.

The cell and row types and functions live in a new screen.h header,
separate from terminal.h, with terminal.h including screen.h for
convenience.
2026-03-19 13:15:45 -07:00
Mitchell Hashimoto
7f36e8bd43 vt: add style C API
Expose the terminal Style struct to the C API as GhosttyStyle, a
sized struct with foreground, background, and underline colors
(as tagged unions) plus boolean text decoration flags.

Add ghostty_style_default() to obtain the default style and
ghostty_style_is_default() to check whether a style has all
default values. Wire both through c/style.zig, main.zig, and
lib_vt.zig with the corresponding header in vt/style.h.
2026-03-19 12:02:03 -07:00
Mitchell Hashimoto
f168b3c098 vt: add ghostty_terminal_get for reading terminal state
Add a typed data query API to the terminal C interface, following
the same OutType pattern used by the OSC command data API. The new
ghostty_terminal_get function takes a GhosttyTerminalData tag and
an output pointer, returning GhosttyResult.

Currently exposes cols, rows, cursor x/y position, and cursor
pending wrap state. The GhosttyTerminalData enum is placed with the
other types in the header (before functions) per the ordering
convention.
2026-03-19 11:47:55 -07:00
Mitchell Hashimoto
7bf89740dd vt: expose size_report encoding in the C API
Add ghostty_size_report_encode() to libghostty-vt, following the
same pattern as focus encoding: a single stateless function that
writes a terminal size report escape sequence into a caller-provided
buffer.

The size_report.zig Style enum and Size struct now use lib.Enum and
lib.Struct so the types are automatically C-compatible when building
with c_abi, eliminating the need for duplicate type definitions in
the C wrapper. The C wrapper in c/size_report.zig re-exports these
types directly and provides the callconv(.c) encode entry point.

Supports mode 2048 in-band reports and XTWINOPS responses (CSI 14 t,
CSI 16 t, CSI 18 t).
2026-03-17 16:33:57 -07:00
Mitchell Hashimoto
a460743b2a vt: add mode report encoding to C API
Add ghostty_mode_report_encode() which encodes a DECRPM response
sequence into a caller-provided buffer. The function takes a mode
tag, a report state integer, an output buffer, and writes the
appropriate CSI sequence (with ? prefix for DEC private modes).

The Zig-side ReportState is a non-exhaustive c_int enum that uses
std.meta.intToEnum for safe conversion to the internal type,
returning GHOSTTY_INVALID_VALUE on overflow. The C header exposes
a GhosttyModeReportState enum with named constants for the five
standard DECRPM state values.
2026-03-16 16:10:25 -07:00
Mitchell Hashimoto
1c03770e2b vt: expose terminal modes to C API
Add modes.h with GhosttyModeTag (uint16_t) matching the Zig ModeTag
packed struct layout, along with inline helpers for constructing and
inspecting mode tags. Provide GHOSTTY_MODE_* macros for all 39
built-in modes (4 ANSI, 35 DEC), parenthesized for safety.

Add ghostty_terminal_mode_get and ghostty_terminal_mode_set to
terminal.h, both returning GhosttyResult so that null terminals
and unknown mode tags return GHOSTTY_INVALID_VALUE. The get function
writes its result through a bool out-parameter.

Add a note in the Zig mode entries reminding developers to update
modes.h when adding new modes.
2026-03-16 16:01:53 -07:00
Mitchell Hashimoto
bed9d92f04 vt: expose focus encoding in C and Zig APIs
Add focus event encoding (CSI I / CSI O) to the libghostty-vt public
API, following the same patterns as key and mouse encoding.

The focus Event enum uses lib.Enum for C ABI compatibility. The C API
provides ghostty_focus_encode() which writes into a caller-provided
buffer and returns GHOSTTY_OUT_OF_SPACE with the required size when
the buffer is too small.

Also update key and mouse encoders to return GHOSTTY_OUT_OF_SPACE
instead of GHOSTTY_OUT_OF_MEMORY for buffer-too-small errors,
reserving OUT_OF_MEMORY for actual allocation failures. Update all
corresponding header documentation.
2026-03-16 14:38:19 -07:00
Mitchell Hashimoto
de87456a9b lib/vt: export mouse encoding API
Export mouse_encode types and functions through the lib_vt public
input API, mirroring the existing key encoding exports. This adds
MouseAction, MouseButton, MouseEncodeOptions, MouseEncodeEvent,
and encodeMouse so that consumers of the Zig module can encode
mouse events without reaching into internal packages.
2026-03-15 20:16:00 -07:00
Mitchell Hashimoto
9b35c2bb65 vt: add mouse encoding C API
Expose the internal mouse encoding functionality through the C API,
following the same pattern as the existing key encoding API. This
allows external consumers of libvt to encode mouse events into
terminal escape sequences (X10, UTF-8, SGR, URxvt, SGR-Pixels).

The API is split into two opaque handle types: GhosttyMouseEvent
for building normalized mouse events (action, button, modifiers,
position) and GhosttyMouseEncoder for converting those events into
escape sequences. The encoder is configured via a setopt interface
supporting tracking mode, output format, renderer geometry, button
state, and optional motion deduplication by last cell.

Encoder state can also be bulk-configured from a terminal handle
via ghostty_mouse_encoder_setopt_from_terminal. Failed encodes due
to insufficient buffer space report the required size without
mutating deduplication state.
2026-03-15 20:09:54 -07:00
Mitchell Hashimoto
943d3d2e89 vt: add setopt_from_terminal to C API
Expose the key encoder Options.fromTerminal function to the C API as
ghostty_key_encoder_setopt_from_terminal. This lets C callers sync all
terminal-derived encoding options (cursor key application mode, keypad
mode, alt escape prefix, modifyOtherKeys, and Kitty flags) in a single
call instead of setting each option individually.
2026-03-15 07:05:07 -07:00
Mitchell Hashimoto
3c8feda118 vt: add format_alloc to C API formatter
Rename the existing format function to format_buf to clarify that it
writes into a caller-provided buffer. Add a new format_alloc variant
that allocates the output buffer internally using the provided
allocator (or the default if NULL). The caller receives the allocated
pointer and length and is responsible for freeing it.

This is useful for consumers that do not know the required buffer size
ahead of time and want to avoid the two-pass query-then-format pattern
needed with format_buf.
2026-03-14 14:59:41 -07:00
Mitchell Hashimoto
b5fb7ecaaa vt: wip formatter api 2026-03-14 14:16:44 -07:00
Mitchell Hashimoto
aa3e6e23a2 vt: ghostty_terminal_reset 2026-03-13 19:55:43 -07:00
Mitchell Hashimoto
fe6e7fbc6b vt: ghostty_terminal_resize 2026-03-13 19:54:20 -07:00
Mitchell Hashimoto
8b9afe35a7 vt: ghostty_terminal_scroll_viewport 2026-03-13 19:51:04 -07:00
Mitchell Hashimoto
18fdc15357 vt: ghostty_terminal_vt_write 2026-03-13 19:37:26 -07:00
Mitchell Hashimoto
302e68fd3d vt: expose ghostty_terminal_new/free 2026-03-13 14:10:57 -07:00
Mitchell Hashimoto
e081a4abb4 fuzz/vt-stream 2026-03-01 14:55:07 -08:00
Mitchell Hashimoto
adbb432930 test/fuzz-libghostty: basic afl++-based fuzzer for libghostty 2026-02-28 21:14:51 -08:00
Mitchell Hashimoto
ec5bdf1a5a terminal: highlights 2025-11-24 19:55:27 -08:00
Mitchell Hashimoto
3283f57fd2 lib-vt: expose RenderState API 2025-11-21 16:01:22 -08:00