aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/include
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-07-16 23:28:05 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-07-16 23:29:28 +0300
commit4a3302d19a2baa3a33e910e0088c24e780905b90 (patch)
treedcaf76fae1c82102d933c9225b17ca7ac5d3a847 /vendor/libghostty-vt/include
parent550e9f8cc085f428429f5cf2da0bb2dba897e8b8 (diff)
chore: update vendored libghostty-vt
refs #276
Diffstat (limited to 'vendor/libghostty-vt/include')
-rw-r--r--vendor/libghostty-vt/include/ghostty.h1
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt.h9
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/color.h432
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/color_scheme.h73
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/kitty_graphics.h89
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/render.h66
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/sgr.h7
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/terminal.h351
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/unicode.h154
9 files changed, 1144 insertions, 38 deletions
diff --git a/vendor/libghostty-vt/include/ghostty.h b/vendor/libghostty-vt/include/ghostty.h
index fbfe3ee2..72bbb57a 100644
--- a/vendor/libghostty-vt/include/ghostty.h
+++ b/vendor/libghostty-vt/include/ghostty.h
@@ -934,6 +934,7 @@ typedef enum {
GHOSTTY_ACTION_CONFIG_CHANGE,
GHOSTTY_ACTION_CLOSE_WINDOW,
GHOSTTY_ACTION_RING_BELL,
+ GHOSTTY_ACTION_SELECTION_CHANGED,
GHOSTTY_ACTION_UNDO,
GHOSTTY_ACTION_REDO,
GHOSTTY_ACTION_CHECK_FOR_UPDATES,
diff --git a/vendor/libghostty-vt/include/ghostty/vt.h b/vendor/libghostty-vt/include/ghostty/vt.h
index 94a85033..5606f169 100644
--- a/vendor/libghostty-vt/include/ghostty/vt.h
+++ b/vendor/libghostty-vt/include/ghostty/vt.h
@@ -34,6 +34,7 @@
* - @ref osc "OSC Parser" - Parse OSC (Operating System Command) sequences
* - @ref sgr "SGR Parser" - Parse SGR (Select Graphic Rendition) sequences
* - @ref paste "Paste Utilities" - Validate paste data safety
+ * - @ref unicode "Unicode Utilities" - Codepoint properties for text layout
* - @ref build_info "Build Info" - Query compile-time build configuration
* - @ref allocator "Memory Management" - Memory management and custom allocators
* - @ref wasm "WebAssembly Utilities" - WebAssembly convenience functions
@@ -55,6 +56,7 @@
* - @ref c-vt-formatter/src/main.c - Terminal formatter example
* - @ref c-vt-grid-traverse/src/main.c - Grid traversal example using grid refs
* - @ref c-vt-grid-ref-tracked/src/main.c - Tracked grid ref example
+ * - @ref c-vt-compression/src/main.c - Idle scrollback compression example
*
*/
@@ -104,6 +106,11 @@
* detect when it loses its value, and move it to a new point.
*/
+/** @example c-vt-compression/src/main.c
+ * This example demonstrates how to schedule incremental scrollback compression
+ * after compression-relevant terminal activity becomes idle.
+ */
+
/** @example c-vt-selection-gesture/src/main.c
* This example demonstrates how to use synthetic selection gesture events to
* derive drag and deep-press selection snapshots.
@@ -125,6 +132,7 @@ extern "C" {
#include <ghostty/vt/allocator.h>
#include <ghostty/vt/build_info.h>
#include <ghostty/vt/color.h>
+#include <ghostty/vt/color_scheme.h>
#include <ghostty/vt/device.h>
#include <ghostty/vt/focus.h>
#include <ghostty/vt/formatter.h>
@@ -145,6 +153,7 @@ extern "C" {
#include <ghostty/vt/screen.h>
#include <ghostty/vt/selection.h>
#include <ghostty/vt/size_report.h>
+#include <ghostty/vt/unicode.h>
#include <ghostty/vt/wasm.h>
#ifdef __cplusplus
diff --git a/vendor/libghostty-vt/include/ghostty/vt/color.h b/vendor/libghostty-vt/include/ghostty/vt/color.h
index 9dc21864..f5f7f9c4 100644
--- a/vendor/libghostty-vt/include/ghostty/vt/color.h
+++ b/vendor/libghostty-vt/include/ghostty/vt/color.h
@@ -7,6 +7,114 @@
#ifndef GHOSTTY_VT_COLOR_H
#define GHOSTTY_VT_COLOR_H
+/** @defgroup color Color Utilities
+ *
+ * Color parsing, palette generation, color math, and X11 color name
+ * utilities shared by libghostty-vt.
+ *
+ * These APIs expose Ghostty's color semantics directly to embedders. Use
+ * them when an application needs to parse the same color strings as Ghostty
+ * config and theme files, generate the same 256-color palette used by the
+ * terminal, list supported X11 color names, or make UI decisions from
+ * luminance and contrast values.
+ *
+ * ## Parsing Colors
+ *
+ * ghostty_color_parse() accepts the flexible syntax used by Ghostty for
+ * terminal colors:
+ *
+ * - X11 color names, matched ASCII case-insensitively.
+ * - 3- or 6-digit hex colors, with or without a leading `#`.
+ * - 9- or 12-digit hex colors, with a leading `#`.
+ * - XParseColor-style `rgb:<red>/<green>/<blue>` values.
+ * - XParseColor-style `rgbi:<red>/<green>/<blue>` values.
+ *
+ * Leading and trailing spaces and tabs are ignored. Use
+ * ghostty_color_parse_x11() when only X11 names should be accepted.
+ *
+ * @code{.c}
+ * GhosttyColorRgb color;
+ *
+ * if (ghostty_color_parse(
+ * "ForestGreen",
+ * sizeof("ForestGreen") - 1,
+ * &color) != GHOSTTY_SUCCESS) {
+ * // Handle invalid color input.
+ * }
+ *
+ * ghostty_color_parse("#abc", sizeof("#abc") - 1, &color);
+ * ghostty_color_parse("rgb:12/34/56", sizeof("rgb:12/34/56") - 1, &color);
+ * @endcode
+ *
+ * ## Palette Entries
+ *
+ * ghostty_color_parse_palette_entry() parses a single Ghostty palette
+ * override in `INDEX=COLOR` form. The index may be decimal or use a `0x`,
+ * `0o`, or `0b` prefix. The color side uses ghostty_color_parse().
+ *
+ * @code{.c}
+ * GhosttyColorRgb palette[256];
+ * ghostty_color_palette_default(palette);
+ *
+ * uint8_t index;
+ * GhosttyColorRgb rgb;
+ *
+ * if (ghostty_color_parse_palette_entry(
+ * "0x10=#282c34",
+ * sizeof("0x10=#282c34") - 1,
+ * &index,
+ * &rgb) == GHOSTTY_SUCCESS) {
+ * palette[index] = rgb;
+ * }
+ * @endcode
+ *
+ * ## Palette Generation
+ *
+ * ghostty_color_palette_generate() derives the 216-color cube and grayscale
+ * ramp from a base palette, background, and foreground. Set bits in
+ * GhosttyColorPaletteMask preserve specific indices from the base palette.
+ * The output may alias the base input.
+ *
+ * @code{.c}
+ * GhosttyColorRgb palette[256];
+ * ghostty_color_palette_default(palette);
+ *
+ * GhosttyColorPaletteMask skip = {0};
+ * GHOSTTY_COLOR_PALETTE_MASK_SET(&skip, 16);
+ *
+ * GhosttyColorRgb background = {40, 44, 52};
+ * GhosttyColorRgb foreground = {220, 223, 228};
+ *
+ * ghostty_color_palette_generate(
+ * palette,
+ * &skip,
+ * &background,
+ * &foreground,
+ * true,
+ * palette);
+ * @endcode
+ *
+ * ## X11 Color Names
+ *
+ * The X11 name table is static program-lifetime memory. Entries are in
+ * rgb.txt order and are terminated by an entry with `name == NULL`.
+ * ghostty_color_x11_name_count() returns the number of non-terminator
+ * entries.
+ *
+ * @code{.c}
+ * const GhosttyColorX11Entry* names = ghostty_color_x11_names();
+ * size_t count = ghostty_color_x11_name_count();
+ *
+ * for (size_t i = 0; i < count; i++) {
+ * // names[i].name and names[i].color are valid here.
+ * }
+ * @endcode
+ *
+ * @{
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
#include <stdint.h>
#include <ghostty/vt/types.h>
@@ -17,7 +125,7 @@ extern "C" {
/**
* RGB color value.
*
- * @ingroup sgr
+ * @ingroup color
*/
typedef struct {
uint8_t r; /**< Red component (0-255) */
@@ -28,49 +136,128 @@ typedef struct {
/**
* Palette color index (0-255).
*
- * @ingroup sgr
+ * @ingroup color
*/
typedef uint8_t GhosttyColorPaletteIndex;
-/** @addtogroup sgr
- * @{
+/**
+ * A 256-bit mask of palette indices.
+ *
+ * Index i is set iff `(bits[i >> 6] >> (i & 63)) & 1` is 1.
+ * The mask is typically initialized to zero and then populated with
+ * GHOSTTY_COLOR_PALETTE_MASK_SET().
+ *
+ * @code{.c}
+ * GhosttyColorPaletteMask mask = {0};
+ * GHOSTTY_COLOR_PALETTE_MASK_SET(&mask, 20);
+ * if (GHOSTTY_COLOR_PALETTE_MASK_IS_SET(&mask, 20)) {
+ * // Index 20 will be preserved.
+ * }
+ * @endcode
+ *
+ * @ingroup color
*/
+typedef struct {
+ uint64_t bits[4];
+} GhosttyColorPaletteMask;
+
+/**
+ * An entry in Ghostty's X11 color name table.
+ *
+ * @ingroup color
+ */
+typedef struct {
+ /** Null-terminated color name. NULL marks the end of the table. */
+ const char* name;
+ /** The RGB value of the color. */
+ GhosttyColorRgb color;
+} GhosttyColorX11Entry;
+
+/**
+ * Return the storage word for a palette mask index.
+ *
+ * @param index The palette index (0-255)
+ *
+ * @ingroup color
+ */
+#define GHOSTTY_COLOR_PALETTE_MASK_WORD(index) ((index) >> 6)
+
+/**
+ * Return the storage bit for a palette mask index.
+ *
+ * @param index The palette index (0-255)
+ *
+ * @ingroup color
+ */
+#define GHOSTTY_COLOR_PALETTE_MASK_BIT(index) (UINT64_C(1) << ((index) & 63))
-/** Black color (0) @ingroup sgr */
+/**
+ * Set a palette mask index.
+ *
+ * @param mask Pointer to a GhosttyColorPaletteMask
+ * @param index The palette index (0-255)
+ *
+ * @ingroup color
+ */
+#define GHOSTTY_COLOR_PALETTE_MASK_SET(mask, index) \
+ ((mask)->bits[GHOSTTY_COLOR_PALETTE_MASK_WORD(index)] |= GHOSTTY_COLOR_PALETTE_MASK_BIT(index))
+
+/**
+ * Clear a palette mask index.
+ *
+ * @param mask Pointer to a GhosttyColorPaletteMask
+ * @param index The palette index (0-255)
+ *
+ * @ingroup color
+ */
+#define GHOSTTY_COLOR_PALETTE_MASK_UNSET(mask, index) \
+ ((mask)->bits[GHOSTTY_COLOR_PALETTE_MASK_WORD(index)] &= ~GHOSTTY_COLOR_PALETTE_MASK_BIT(index))
+
+/**
+ * Test whether a palette mask index is set.
+ *
+ * @param mask Pointer to a GhosttyColorPaletteMask
+ * @param index The palette index (0-255)
+ * @return true if the palette index is set, false otherwise
+ *
+ * @ingroup color
+ */
+#define GHOSTTY_COLOR_PALETTE_MASK_IS_SET(mask, index) \
+ (((mask)->bits[GHOSTTY_COLOR_PALETTE_MASK_WORD(index)] & GHOSTTY_COLOR_PALETTE_MASK_BIT(index)) != 0)
+
+/** Black color (0) @ingroup color */
#define GHOSTTY_COLOR_NAMED_BLACK 0
-/** Red color (1) @ingroup sgr */
+/** Red color (1) @ingroup color */
#define GHOSTTY_COLOR_NAMED_RED 1
-/** Green color (2) @ingroup sgr */
+/** Green color (2) @ingroup color */
#define GHOSTTY_COLOR_NAMED_GREEN 2
-/** Yellow color (3) @ingroup sgr */
+/** Yellow color (3) @ingroup color */
#define GHOSTTY_COLOR_NAMED_YELLOW 3
-/** Blue color (4) @ingroup sgr */
+/** Blue color (4) @ingroup color */
#define GHOSTTY_COLOR_NAMED_BLUE 4
-/** Magenta color (5) @ingroup sgr */
+/** Magenta color (5) @ingroup color */
#define GHOSTTY_COLOR_NAMED_MAGENTA 5
-/** Cyan color (6) @ingroup sgr */
+/** Cyan color (6) @ingroup color */
#define GHOSTTY_COLOR_NAMED_CYAN 6
-/** White color (7) @ingroup sgr */
+/** White color (7) @ingroup color */
#define GHOSTTY_COLOR_NAMED_WHITE 7
-/** Bright black color (8) @ingroup sgr */
+/** Bright black color (8) @ingroup color */
#define GHOSTTY_COLOR_NAMED_BRIGHT_BLACK 8
-/** Bright red color (9) @ingroup sgr */
+/** Bright red color (9) @ingroup color */
#define GHOSTTY_COLOR_NAMED_BRIGHT_RED 9
-/** Bright green color (10) @ingroup sgr */
+/** Bright green color (10) @ingroup color */
#define GHOSTTY_COLOR_NAMED_BRIGHT_GREEN 10
-/** Bright yellow color (11) @ingroup sgr */
+/** Bright yellow color (11) @ingroup color */
#define GHOSTTY_COLOR_NAMED_BRIGHT_YELLOW 11
-/** Bright blue color (12) @ingroup sgr */
+/** Bright blue color (12) @ingroup color */
#define GHOSTTY_COLOR_NAMED_BRIGHT_BLUE 12
-/** Bright magenta color (13) @ingroup sgr */
+/** Bright magenta color (13) @ingroup color */
#define GHOSTTY_COLOR_NAMED_BRIGHT_MAGENTA 13
-/** Bright cyan color (14) @ingroup sgr */
+/** Bright cyan color (14) @ingroup color */
#define GHOSTTY_COLOR_NAMED_BRIGHT_CYAN 14
-/** Bright white color (15) @ingroup sgr */
+/** Bright white color (15) @ingroup color */
#define GHOSTTY_COLOR_NAMED_BRIGHT_WHITE 15
-/** @} */
-
/**
* Get the RGB color components.
*
@@ -78,20 +265,215 @@ typedef uint8_t GhosttyColorPaletteIndex;
* from a GhosttyColorRgb value. Primarily useful in WebAssembly environments
* where accessing struct fields directly is difficult.
*
- * @param color The RGB color value
+ * @param color Pointer to the RGB color value
* @param r Pointer to store the red component (0-255)
* @param g Pointer to store the green component (0-255)
* @param b Pointer to store the blue component (0-255)
*
- * @ingroup sgr
+ * @ingroup color
*/
-GHOSTTY_API void ghostty_color_rgb_get(GhosttyColorRgb color,
+GHOSTTY_API void ghostty_color_rgb_get(const GhosttyColorRgb* color,
uint8_t* r,
uint8_t* g,
uint8_t* b);
+/**
+ * Parse an X11 color name.
+ *
+ * The color name is resolved from Ghostty's embedded rgb.txt table.
+ * Leading and trailing spaces and tabs are trimmed, and matching is
+ * ASCII case-insensitive. Hex values are not accepted by this function.
+ *
+ * @param name The color name bytes (must not be NULL)
+ * @param len The length of @p name in bytes
+ * @param[out] out The parsed RGB color
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if no color
+ * matches or @p name is NULL
+ *
+ * @ingroup color
+ */
+GHOSTTY_API GhosttyResult ghostty_color_parse_x11(
+ const char* name,
+ size_t len,
+ GhosttyColorRgb* out);
+
+/**
+ * Parse a flexible Ghostty color value.
+ *
+ * Accepts Ghostty's terminal color syntax: X11 color names, hex colors
+ * in 3-, 6-, 9-, or 12-digit form (the leading # is optional for 3- and
+ * 6-digit values), and rgb:<red>/<green>/<blue> or
+ * rgbi:<red>/<green>/<blue> specifications. Leading and trailing spaces
+ * and tabs are trimmed.
+ *
+ * @param value The color value bytes (must not be NULL)
+ * @param len The length of @p value in bytes
+ * @param[out] out The parsed RGB color
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if parsing
+ * fails or @p value is NULL
+ *
+ * @ingroup color
+ */
+GHOSTTY_API GhosttyResult ghostty_color_parse(
+ const char* value,
+ size_t len,
+ GhosttyColorRgb* out);
+
+/**
+ * Parse a Ghostty palette entry.
+ *
+ * Accepts Ghostty palette config syntax: N=COLOR. N is a palette index
+ * from 0 to 255 in decimal or in 0x, 0o, or 0b-prefixed form. Spaces and
+ * tabs around N and COLOR are ignored. COLOR accepts the same syntax as
+ * ghostty_color_parse().
+ *
+ * @param value The palette entry bytes (must not be NULL)
+ * @param len The length of @p value in bytes
+ * @param[out] out_index The parsed palette index
+ * @param[out] out_rgb The parsed RGB color
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE on any
+ * failure, including index overflow
+ *
+ * @ingroup color
+ */
+GHOSTTY_API GhosttyResult ghostty_color_parse_palette_entry(
+ const char* value,
+ size_t len,
+ uint8_t* out_index,
+ GhosttyColorRgb* out_rgb);
+
+/**
+ * Get Ghostty's built-in default 256-color palette.
+ *
+ * Writes exactly 256 entries: Ghostty's base16 defaults, the xterm
+ * 6x6x6 color cube, and the grayscale ramp.
+ *
+ * @param[out] out The output palette, an array of exactly 256
+ * GhosttyColorRgb values
+ *
+ * @ingroup color
+ */
+GHOSTTY_API void ghostty_color_palette_default(GhosttyColorRgb* out);
+
+/**
+ * Generate a 256-color palette from base colors.
+ *
+ * The base palette supplies indices 0-15, which are always preserved.
+ * If @p base is NULL, Ghostty's default palette is used. If @p skip is
+ * NULL, no extra indices are skipped. Set bits in @p skip preserve those
+ * indices from @p base. The 216-color cube at indices 16-231 is generated
+ * with trilinear CIELAB interpolation, and the grayscale ramp at indices
+ * 232-255 is interpolated from the background to the foreground.
+ *
+ * For light themes, @p harmonious controls whether the generated palette
+ * keeps the background-to-foreground orientation. When false, Ghostty
+ * swaps the light background and dark foreground so the cube and ramp run
+ * dark-to-light. The output palette may be the same pointer as @p base.
+ *
+ * @param base The base palette, an array of exactly 256 GhosttyColorRgb
+ * values, or NULL to use Ghostty's default palette
+ * @param skip The palette indices to preserve from @p base, or NULL for
+ * an empty mask
+ * @param bg The terminal background color (must not be NULL)
+ * @param fg The terminal foreground color (must not be NULL)
+ * @param harmonious Whether light themes keep background-to-foreground
+ * orientation
+ * @param[out] out The output palette, an array of exactly 256
+ * GhosttyColorRgb values
+ *
+ * @ingroup color
+ */
+GHOSTTY_API void ghostty_color_palette_generate(
+ const GhosttyColorRgb* base,
+ const GhosttyColorPaletteMask* skip,
+ const GhosttyColorRgb* bg,
+ const GhosttyColorRgb* fg,
+ bool harmonious,
+ GhosttyColorRgb* out);
+
+/**
+ * Calculate W3C relative luminance for an RGB color.
+ *
+ * Returns a normalized value from 0.0 for black to 1.0 for white.
+ * See https://www.w3.org/TR/WCAG20/#relativeluminancedef.
+ *
+ * @param color The RGB color (must not be NULL)
+ * @return Relative luminance in the range 0.0 to 1.0
+ *
+ * @ingroup color
+ */
+GHOSTTY_API double ghostty_color_luminance(const GhosttyColorRgb* color);
+
+/**
+ * Calculate perceived luminance for an RGB color.
+ *
+ * Returns a normalized value from 0.0 for black to 1.0 for white.
+ * Ghostty treats a background color as light when this exceeds 0.5.
+ * This is not the metric used internally by
+ * ghostty_color_palette_generate(), which uses CIELAB lightness.
+ *
+ * @param color The RGB color (must not be NULL)
+ * @return Perceived luminance in the range 0.0 to 1.0
+ *
+ * @ingroup color
+ */
+GHOSTTY_API double ghostty_color_perceived_luminance(const GhosttyColorRgb* color);
+
+/**
+ * Calculate the WCAG contrast ratio between two RGB colors.
+ *
+ * The contrast ratio is symmetric and ranges from 1.0 for identical
+ * colors to 21.0 for black and white.
+ *
+ * @param a The first RGB color (must not be NULL)
+ * @param b The second RGB color (must not be NULL)
+ * @return WCAG contrast ratio in the range 1.0 to 21.0
+ *
+ * @ingroup color
+ */
+GHOSTTY_API double ghostty_color_contrast(const GhosttyColorRgb* a,
+ const GhosttyColorRgb* b);
+
+/**
+ * Get Ghostty's X11 color name table.
+ *
+ * The returned pointer references static memory valid for the program
+ * lifetime and is never NULL. Entries are in rgb.txt order and are
+ * terminated by an entry with name == NULL. Aliases are separate entries,
+ * such as "medium spring green" and "MediumSpringGreen". Names are the
+ * exact supported spellings from rgb.txt; ghostty_color_parse_x11() also
+ * matches them case-insensitively.
+ *
+ * @code{.c}
+ * for (const GhosttyColorX11Entry* e = ghostty_color_x11_names();
+ * e->name != NULL;
+ * e++) {
+ * // e->name and e->color are valid here.
+ * }
+ * @endcode
+ *
+ * @return Pointer to the first X11 color entry
+ *
+ * @ingroup color
+ */
+GHOSTTY_API const GhosttyColorX11Entry* ghostty_color_x11_names(void);
+
+/**
+ * Get the number of X11 color name entries.
+ *
+ * The returned count excludes the NULL terminator and is provided so
+ * bindings can preallocate storage before reading ghostty_color_x11_names().
+ *
+ * @return Number of X11 color name entries
+ *
+ * @ingroup color
+ */
+GHOSTTY_API size_t ghostty_color_x11_name_count(void);
+
#ifdef __cplusplus
}
#endif
+/** @} */
+
#endif /* GHOSTTY_VT_COLOR_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/color_scheme.h b/vendor/libghostty-vt/include/ghostty/vt/color_scheme.h
new file mode 100644
index 00000000..d028ec08
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/color_scheme.h
@@ -0,0 +1,73 @@
+/**
+ * @file color_scheme.h
+ *
+ * Color scheme report encoding - encode terminal color scheme reports into
+ * escape sequences.
+ */
+
+#ifndef GHOSTTY_VT_COLOR_SCHEME_H
+#define GHOSTTY_VT_COLOR_SCHEME_H
+
+/** @defgroup color_scheme Color Scheme Report Encoding
+ *
+ * Utilities for encoding color scheme reports into terminal escape
+ * sequences for color scheme reporting mode (mode 2031).
+ *
+ * ## Basic Usage
+ *
+ * Use ghostty_color_scheme_report_encode() to encode a color scheme report
+ * into a caller-provided buffer. If the buffer is too small, the function
+ * returns GHOSTTY_OUT_OF_SPACE and sets the required size in the output
+ * parameter.
+ *
+ * ## Example
+ *
+ * @snippet c-vt-color-scheme/src/main.c color-scheme-report-encode
+ *
+ * @{
+ */
+
+#include <stddef.h>
+#include <ghostty/vt/types.h>
+#include <ghostty/vt/device.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Encode a color scheme report into an escape sequence.
+ *
+ * Encodes a color scheme report into the provided buffer. Dark color schemes
+ * emit ESC [ ? 997 ; 1 n, and light color schemes emit ESC [ ? 997 ; 2 n.
+ * The encoded bytes are identical to the terminal's internal CSI ? 996 n
+ * query response.
+ *
+ * Hosts should gate unsolicited sends on GHOSTTY_MODE_COLOR_SCHEME_REPORT
+ * (mode 2031) being set, which can be checked via the mode getters.
+ *
+ * If the buffer is too small, the function returns GHOSTTY_OUT_OF_SPACE
+ * and writes the required buffer size to @p out_written. The caller can
+ * then retry with a sufficiently sized buffer.
+ *
+ * @param scheme The color scheme to encode
+ * @param buf Output buffer to write the encoded sequence into (may be NULL)
+ * @param buf_len Size of the output buffer in bytes
+ * @param[out] out_written On success, the number of bytes written. On
+ * GHOSTTY_OUT_OF_SPACE, the required buffer size.
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_OUT_OF_SPACE if the buffer
+ * is too small
+ */
+GHOSTTY_API GhosttyResult ghostty_color_scheme_report_encode(
+ GhosttyColorScheme scheme,
+ char* buf,
+ size_t buf_len,
+ size_t* out_written);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif /* GHOSTTY_VT_COLOR_SCHEME_H */
diff --git a/vendor/libghostty-vt/include/ghostty/vt/kitty_graphics.h b/vendor/libghostty-vt/include/ghostty/vt/kitty_graphics.h
index d5b50067..dda8b836 100644
--- a/vendor/libghostty-vt/include/ghostty/vt/kitty_graphics.h
+++ b/vendor/libghostty-vt/include/ghostty/vt/kitty_graphics.h
@@ -84,6 +84,28 @@ extern "C" {
* - ghostty_kitty_graphics_placement_rect() — bounding rectangle as a
* @ref GhosttySelection.
*
+ * ## Change Detection
+ *
+ * Generation stamps allow renderers to cheaply detect whether Kitty
+ * graphics state changed between frames:
+ *
+ * - @ref GHOSTTY_KITTY_GRAPHICS_DATA_GENERATION is a storage-wide stamp
+ * updated on any transmit, placement, or delete. If unchanged, the
+ * placement set and all image data are identical and both placement
+ * snapshots and per-image staleness checks can be skipped. Placement
+ * geometry can still change independently (scrolling moves
+ * placements), so ghostty_kitty_graphics_placement_render_info()
+ * should still be recomputed on dirty frames.
+ * - @ref GHOSTTY_KITTY_IMAGE_DATA_GENERATION is a per-image stamp
+ * changed on every add/replace of that image ID. Texture caches
+ * should treat a cached texture as stale when this differs from the
+ * cached value; dimension/length heuristics cannot detect a
+ * same-sized retransmission.
+ *
+ * Stamps are unique and monotonically increasing process-wide, so
+ * caches keyed on a generation value never alias across screens
+ * (main/alternate), resets, or terminals.
+ *
* ## Lifetime and Thread Safety
*
* All handles borrowed from the terminal (GhosttyKittyGraphics,
@@ -119,6 +141,29 @@ typedef enum GHOSTTY_ENUM_TYPED {
* Output type: GhosttyKittyGraphicsPlacementIterator *
*/
GHOSTTY_KITTY_GRAPHICS_DATA_PLACEMENT_ITERATOR = 1,
+
+ /**
+ * Generation stamp of the last content mutation to this storage:
+ * any image transmit/replace, placement add, or delete. Zero means
+ * the storage has never been mutated (and is therefore empty).
+ *
+ * If the generation is unchanged since a previous query, the set of
+ * placements and all image data are identical, so placement iteration
+ * and image staleness checks can be skipped entirely. Note that
+ * placement *geometry* may still have changed (scrolling and resizing
+ * move placements without changing the storage contents), so rendering
+ * geometry such as ghostty_kitty_graphics_placement_render_info()
+ * must still be recomputed for frames marked dirty.
+ *
+ * Stamps are unique and monotonically increasing process-wide: a
+ * value observed from any storage never recurs for different content,
+ * even across screen switches (main vs. alternate screen have
+ * independent storages) or terminal resets. It is therefore safe to
+ * key caches on this value alone.
+ *
+ * Output type: uint64_t *
+ */
+ GHOSTTY_KITTY_GRAPHICS_DATA_GENERATION = 2,
GHOSTTY_KITTY_GRAPHICS_DATA_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
} GhosttyKittyGraphicsData;
@@ -255,6 +300,12 @@ typedef enum GHOSTTY_ENUM_TYPED {
/**
* Pixel format of a Kitty graphics image.
*
+ * Note that stored images are always fully decoded:
+ * GHOSTTY_KITTY_IMAGE_FORMAT_PNG is never returned by
+ * ghostty_kitty_graphics_image_get() because PNG payloads are decoded
+ * to GHOSTTY_KITTY_IMAGE_FORMAT_RGBA before storage. The PNG value
+ * exists only for protocol-level completeness.
+ *
* @ingroup kitty_graphics
*/
typedef enum GHOSTTY_ENUM_TYPED {
@@ -269,6 +320,12 @@ typedef enum GHOSTTY_ENUM_TYPED {
/**
* Compression of a Kitty graphics image.
*
+ * Note that stored images are always decompressed:
+ * GHOSTTY_KITTY_IMAGE_COMPRESSION_ZLIB_DEFLATE payloads are inflated
+ * before storage, so ghostty_kitty_graphics_image_get() always reports
+ * GHOSTTY_KITTY_IMAGE_COMPRESSION_NONE. Consumers never need to
+ * inflate image data themselves.
+ *
* @ingroup kitty_graphics
*/
typedef enum GHOSTTY_ENUM_TYPED {
@@ -315,14 +372,17 @@ typedef enum GHOSTTY_ENUM_TYPED {
GHOSTTY_KITTY_IMAGE_DATA_HEIGHT = 4,
/**
- * Pixel format of the image.
+ * Pixel format of the image. Never GHOSTTY_KITTY_IMAGE_FORMAT_PNG;
+ * PNG payloads are decoded to RGBA before storage.
*
* Output type: GhosttyKittyImageFormat *
*/
GHOSTTY_KITTY_IMAGE_DATA_FORMAT = 5,
/**
- * Compression of the image.
+ * Compression of the image. Always
+ * GHOSTTY_KITTY_IMAGE_COMPRESSION_NONE; compressed payloads are
+ * inflated before storage.
*
* Output type: GhosttyKittyImageCompression *
*/
@@ -332,25 +392,40 @@ typedef enum GHOSTTY_ENUM_TYPED {
* Borrowed pointer to the raw pixel data. Valid as long as the
* underlying terminal is not mutated.
*
+ * The data is always fully decoded, uncompressed pixels in the
+ * format reported by GHOSTTY_KITTY_IMAGE_DATA_FORMAT: zlib payloads
+ * are inflated and PNG payloads are decoded to RGBA at transmission
+ * time, before the image is stored. Consumers can upload this
+ * directly to the GPU without any decode step.
+ *
* Output type: const uint8_t **
*/
GHOSTTY_KITTY_IMAGE_DATA_DATA_PTR = 7,
/**
- * Length of the raw pixel data in bytes.
+ * Length of the raw pixel data in bytes. Always equal to
+ * width * height * bytes-per-pixel for the reported format.
*
* Output type: size_t *
*/
GHOSTTY_KITTY_IMAGE_DATA_DATA_LEN = 8,
/**
- * Timestamp of the image's most recent transmission, in nanoseconds.
- * The epoch is unspecified; only equality and ordering between values
- * read from the same terminal are meaningful.
+ * Generation stamp assigned when this image was added to (or
+ * replaced in) the storage. A changed generation for a given image
+ * ID means the pixel contents may have changed even when the
+ * dimensions, format, and data length are identical (e.g. a
+ * retransmission of the same image ID), so texture caches must key
+ * staleness on this value rather than on size heuristics.
+ *
+ * Stamps are unique and monotonically increasing process-wide and
+ * are drawn from the same sequence as
+ * GHOSTTY_KITTY_GRAPHICS_DATA_GENERATION. Never zero for a stored
+ * image, so zero can be used as an "empty" sentinel by callers.
*
* Output type: uint64_t *
*/
- GHOSTTY_KITTY_IMAGE_DATA_TRANSMIT_TIME_NS = 9,
+ GHOSTTY_KITTY_IMAGE_DATA_GENERATION = 9,
GHOSTTY_KITTY_IMAGE_DATA_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
} GhosttyKittyGraphicsImageData;
diff --git a/vendor/libghostty-vt/include/ghostty/vt/render.h b/vendor/libghostty-vt/include/ghostty/vt/render.h
index c5b1d0d4..2e3f2f71 100644
--- a/vendor/libghostty-vt/include/ghostty/vt/render.h
+++ b/vendor/libghostty-vt/include/ghostty/vt/render.h
@@ -39,6 +39,18 @@ extern "C" {
* 2. Update it from a terminal instance whenever you need.
* 3. Read from the render state to get the data needed to draw your frame.
*
+ * ## Two-Phase Updates
+ *
+ * For callers that synchronize terminal access (e.g. a renderer thread
+ * sharing a lock with an IO thread), the update can be split into two
+ * phases to minimize the time the terminal must be held exclusively:
+ * ghostty_render_state_begin_update requires terminal access, while
+ * ghostty_render_state_end_update completes any deferred work using only
+ * memory owned by the render state. A typical renderer would lock, begin
+ * the update, unlock, and then end the update while the IO thread is free
+ * to continue modifying the terminal. ghostty_render_state_update is a
+ * convenience that performs both phases in one call.
+ *
* ## Dirty Tracking
*
* Dirty tracking is a key feature of the render state that allows renderers
@@ -331,6 +343,12 @@ GHOSTTY_API void ghostty_render_state_free(GhosttyRenderState state);
* This consumes terminal/screen dirty state in the same way as the internal
* render state update path.
*
+ * This is a convenience function that performs a full update in one call,
+ * equivalent to ghostty_render_state_begin_update immediately followed by
+ * ghostty_render_state_end_update. Callers that hold a lock over the
+ * terminal state should prefer calling the two phases directly so that the
+ * lock is only held for the begin phase.
+ *
* @param state The render state handle (NULL returns GHOSTTY_INVALID_VALUE)
* @param terminal The terminal handle to read from (NULL returns GHOSTTY_INVALID_VALUE)
* @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if `state` or
@@ -343,6 +361,54 @@ GHOSTTY_API GhosttyResult ghostty_render_state_update(GhosttyRenderState state,
GhosttyTerminal terminal);
/**
+ * Begin an update of a render state instance from a terminal.
+ *
+ * Every begin must be completed with a ghostty_render_state_end_update call
+ * before the render state is read.
+ *
+ * This two-phase structure exists for callers that synchronize access to the
+ * terminal state (e.g. with a lock shared with an IO thread): only this
+ * function requires terminal access, so a caller can hold its lock for this
+ * call only and then call ghostty_render_state_end_update after releasing
+ * it. The end phase exclusively reads and writes memory owned by the render
+ * state, so it is safe to call while the terminal is being modified.
+ *
+ * Work that doesn't require terminal access may be deferred to the end phase
+ * to keep this call (and therefore lock hold time) as short as possible.
+ * Callers must treat the render state as incomplete until
+ * ghostty_render_state_end_update is called.
+ *
+ * This consumes terminal/screen dirty state in the same way as the internal
+ * render state update path.
+ *
+ * @param state The render state handle (NULL returns GHOSTTY_INVALID_VALUE)
+ * @param terminal The terminal handle to read from (NULL returns GHOSTTY_INVALID_VALUE)
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if `state` or
+ * `terminal` is NULL, GHOSTTY_OUT_OF_MEMORY if updating the state requires
+ * allocation and that allocation fails
+ *
+ * @ingroup render
+ */
+GHOSTTY_API GhosttyResult ghostty_render_state_begin_update(GhosttyRenderState state,
+ GhosttyTerminal terminal);
+
+/**
+ * Complete a prior ghostty_render_state_begin_update call by performing any
+ * deferred work.
+ *
+ * This only reads and writes memory owned by the render state, so it is safe
+ * to call while the terminal is being modified (no terminal synchronization
+ * is required). Calling this without a prior begin is a safe no-op.
+ *
+ * @param state The render state handle (NULL returns GHOSTTY_INVALID_VALUE)
+ * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if `state` is
+ * NULL
+ *
+ * @ingroup render
+ */
+GHOSTTY_API GhosttyResult ghostty_render_state_end_update(GhosttyRenderState state);
+
+/**
* Get a value from a render state.
*
* The `out` pointer must point to a value of the type corresponding to the
diff --git a/vendor/libghostty-vt/include/ghostty/vt/sgr.h b/vendor/libghostty-vt/include/ghostty/vt/sgr.h
index 8eec11dc..757c5aed 100644
--- a/vendor/libghostty-vt/include/ghostty/vt/sgr.h
+++ b/vendor/libghostty-vt/include/ghostty/vt/sgr.h
@@ -19,8 +19,11 @@
* The parser processes SGR parameters from CSI sequences (e.g., `ESC[1;31m`)
* and returns individual text attributes like bold, italic, colors, etc.
* It supports both semicolon (`;`) and colon (`:`) separators, possibly mixed,
- * and handles various color formats including 8-color, 16-color, 256-color,
- * X11 named colors, and RGB in multiple formats.
+ * and handles SGR color attributes including 8-color, 16-color, 256-color,
+ * direct RGB, underline color, and reset forms. Color values are returned
+ * using the shared @ref color types; applications that need to parse Ghostty
+ * config/theme color strings, generate palettes, inspect X11 color names, or
+ * calculate luminance and contrast should use the @ref color APIs directly.
*
* ## Basic Usage
*
diff --git a/vendor/libghostty-vt/include/ghostty/vt/terminal.h b/vendor/libghostty-vt/include/ghostty/vt/terminal.h
index ddfcb9c0..26ee0c0b 100644
--- a/vendor/libghostty-vt/include/ghostty/vt/terminal.h
+++ b/vendor/libghostty-vt/include/ghostty/vt/terminal.h
@@ -40,6 +40,17 @@ extern "C" {
* @snippet c-vt-stream/src/main.c vt-stream-init
* @snippet c-vt-stream/src/main.c vt-stream-write
*
+ * ## Scrollback Compression
+ *
+ * Scrollback compression is caller-driven. The terminal exposes an opaque
+ * activity token so an embedding application can restart an idle timer only
+ * when compression-relevant state changes. Once idle, call incremental
+ * compression until it no longer reports pending work. libghostty-vt does not
+ * create a timer or background thread.
+ *
+ * @snippet c-vt-compression/src/main.c compression-activity
+ * @snippet c-vt-compression/src/main.c compression-idle-step
+ *
* ## Effects
*
* By default, the terminal sequence processing with ghostty_terminal_vt_write()
@@ -76,11 +87,13 @@ extern "C" {
* | `GHOSTTY_TERMINAL_OPT_WRITE_PTY` | `GhosttyTerminalWritePtyFn` | Query responses written back to the pty |
* | `GHOSTTY_TERMINAL_OPT_BELL` | `GhosttyTerminalBellFn` | BEL character (0x07) |
* | `GHOSTTY_TERMINAL_OPT_TITLE_CHANGED` | `GhosttyTerminalTitleChangedFn` | Title change via OSC 0 / OSC 2 |
+ * | `GHOSTTY_TERMINAL_OPT_PWD_CHANGED` | `GhosttyTerminalPwdChangedFn` | Pwd change via OSC 7 / OSC 9 / OSC 1337 |
* | `GHOSTTY_TERMINAL_OPT_ENQUIRY` | `GhosttyTerminalEnquiryFn` | ENQ character (0x05) |
* | `GHOSTTY_TERMINAL_OPT_XTVERSION` | `GhosttyTerminalXtversionFn` | XTVERSION query (CSI > q) |
* | `GHOSTTY_TERMINAL_OPT_SIZE` | `GhosttyTerminalSizeFn` | XTWINOPS size query (CSI 14/16/18 t) |
* | `GHOSTTY_TERMINAL_OPT_COLOR_SCHEME` | `GhosttyTerminalColorSchemeFn` | Color scheme query (CSI ? 996 n) |
* | `GHOSTTY_TERMINAL_OPT_DEVICE_ATTRIBUTES`| `GhosttyTerminalDeviceAttributesFn`| Device attributes query (CSI c / > c / = c)|
+ * | `GHOSTTY_TERMINAL_OPT_CLIPBOARD_WRITE` | `GhosttyTerminalClipboardWriteFn` | Clipboard write via OSC 52 / OSC 1337 |
*
* ### Defining a write_pty callback
* @snippet c-vt-effects/src/main.c effects-write-pty
@@ -91,6 +104,9 @@ extern "C" {
* ### Defining a title_changed callback
* @snippet c-vt-effects/src/main.c effects-title-changed
*
+ * ### Defining a clipboard_write callback
+ * @snippet c-vt-effects/src/main.c effects-clipboard-write
+ *
* ### Registering effects and processing VT data
* @snippet c-vt-effects/src/main.c effects-register
*
@@ -177,6 +193,37 @@ typedef struct {
} GhosttyTerminalOptions;
/**
+ * Amount of compression work to perform before returning.
+ *
+ * @ingroup terminal
+ */
+typedef enum GHOSTTY_ENUM_TYPED {
+ /** Perform one bounded compression step suitable for idle scheduling. */
+ GHOSTTY_TERMINAL_COMPRESSION_MODE_INCREMENTAL = 0,
+
+ /** Synchronously inspect every currently eligible page. */
+ GHOSTTY_TERMINAL_COMPRESSION_MODE_FULL = 1,
+ GHOSTTY_TERMINAL_COMPRESSION_MODE_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
+} GhosttyTerminalCompressionMode;
+
+/**
+ * Scheduling result from terminal compression.
+ *
+ * @ingroup terminal
+ */
+typedef enum GHOSTTY_ENUM_TYPED {
+ /** Retained-mapping reclamation is unavailable on this target. */
+ GHOSTTY_TERMINAL_COMPRESSION_RESULT_UNSUPPORTED = 0,
+
+ /** More incremental compression work remains. */
+ GHOSTTY_TERMINAL_COMPRESSION_RESULT_PENDING = 1,
+
+ /** The pass has no continuation to schedule. */
+ GHOSTTY_TERMINAL_COMPRESSION_RESULT_COMPLETE = 2,
+ GHOSTTY_TERMINAL_COMPRESSION_RESULT_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
+} GhosttyTerminalCompressionResult;
+
+/**
* Scroll viewport behavior tag.
*
* @ingroup terminal
@@ -190,6 +237,21 @@ typedef enum GHOSTTY_ENUM_TYPED {
/** Scroll by a delta amount (up is negative). */
GHOSTTY_SCROLL_VIEWPORT_DELTA,
+
+ /**
+ * Scroll to an absolute row offset from the top of the scrollable
+ * area. Row 0 is the top of the scrollback and the requested row
+ * becomes the first visible row of the viewport. The value is
+ * clamped so the viewport never scrolls beyond the top of the
+ * active area. If the terminal has no scrollback (e.g. the
+ * alternate screen is active), the viewport always remains on the
+ * active area.
+ *
+ * This is the same row space as the offset field of
+ * GhosttyTerminalScrollbar, so a scrollbar position obtained from
+ * GHOSTTY_TERMINAL_DATA_SCROLLBAR round-trips cleanly.
+ */
+ GHOSTTY_SCROLL_VIEWPORT_ROW,
GHOSTTY_SCROLL_VIEWPORT_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
} GhosttyTerminalScrollViewportTag;
@@ -202,6 +264,9 @@ typedef union {
/** Scroll delta (only used with GHOSTTY_SCROLL_VIEWPORT_DELTA). Up is negative. */
intptr_t delta;
+ /** Absolute row offset (only used with GHOSTTY_SCROLL_VIEWPORT_ROW). */
+ size_t row;
+
/** Padding for ABI compatibility. Do not use. */
uint64_t _padding[2];
} GhosttyTerminalScrollViewportValue;
@@ -233,6 +298,26 @@ typedef enum GHOSTTY_ENUM_TYPED {
} GhosttyTerminalScreen;
/**
+ * Visual style of the terminal cursor.
+ *
+ * @ingroup terminal
+ */
+typedef enum GHOSTTY_ENUM_TYPED {
+ /** Bar cursor (DECSCUSR 5, 6). */
+ GHOSTTY_TERMINAL_CURSOR_STYLE_BAR = 0,
+
+ /** Block cursor (DECSCUSR 1, 2). */
+ GHOSTTY_TERMINAL_CURSOR_STYLE_BLOCK = 1,
+
+ /** Underline cursor (DECSCUSR 3, 4). */
+ GHOSTTY_TERMINAL_CURSOR_STYLE_UNDERLINE = 2,
+
+ /** Hollow block cursor. */
+ GHOSTTY_TERMINAL_CURSOR_STYLE_BLOCK_HOLLOW = 3,
+ GHOSTTY_TERMINAL_CURSOR_STYLE_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
+} GhosttyTerminalCursorStyle;
+
+/**
* Scrollbar state for the terminal viewport.
*
* Represents the scrollable area dimensions needed to render a scrollbar.
@@ -264,6 +349,125 @@ typedef void (*GhosttyTerminalBellFn)(GhosttyTerminal terminal,
void* userdata);
/**
+ * Clipboard destination for a clipboard write.
+ *
+ * Protocol-specific destination identifiers are normalized to these values
+ * before the clipboard write callback is invoked.
+ *
+ * @ingroup terminal
+ */
+typedef enum GHOSTTY_ENUM_TYPED {
+ /** The standard system clipboard. */
+ GHOSTTY_CLIPBOARD_LOCATION_STANDARD = 0,
+
+ /** The selection clipboard. */
+ GHOSTTY_CLIPBOARD_LOCATION_SELECTION = 1,
+
+ /** The primary selection clipboard. */
+ GHOSTTY_CLIPBOARD_LOCATION_PRIMARY = 2,
+ GHOSTTY_CLIPBOARD_LOCATION_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
+} GhosttyClipboardLocation;
+
+/**
+ * One MIME representation in a clipboard write.
+ *
+ * Both strings are borrowed and valid only for the duration of the callback.
+ * The data is binary-safe and has already been decoded from any protocol-level
+ * encoding. A zero-length data string is an explicit empty representation; it
+ * does not clear the clipboard.
+ *
+ * This struct has a frozen layout and will not gain fields in future versions.
+ *
+ * @ingroup terminal
+ */
+typedef struct {
+ /** MIME type of the representation. */
+ GhosttyString mime;
+
+ /** Decoded, binary-safe representation data. */
+ GhosttyString data;
+} GhosttyClipboardContent;
+
+/**
+ * A semantic, atomic clipboard write.
+ *
+ * This is a sized struct. The callback must only access fields present in the
+ * size reported by `size`. The request, contents array, MIME strings, and
+ * data strings are all borrowed and valid only for the callback duration.
+ *
+ * All entries in `contents` are representations of the same logical value
+ * and must be committed atomically. A `contents_len` of zero requests that
+ * the destination be cleared. This is distinct from a content entry whose data
+ * has zero length.
+ *
+ * @ingroup terminal
+ */
+typedef struct {
+ /** Size of this struct in bytes. */
+ size_t size;
+
+ /** Clipboard destination. */
+ GhosttyClipboardLocation location;
+
+ /** Borrowed array of MIME representations. */
+ const GhosttyClipboardContent* contents;
+
+ /** Number of entries in contents; zero means clear the destination. */
+ size_t contents_len;
+} GhosttyClipboardWrite;
+
+/**
+ * Result of a clipboard write callback.
+ *
+ * Protocols without write acknowledgements, including OSC 52 and iTerm2
+ * OSC 1337 Copy, ignore this result.
+ *
+ * @ingroup terminal
+ */
+typedef enum GHOSTTY_ENUM_TYPED {
+ /** The clipboard write completed successfully. */
+ GHOSTTY_CLIPBOARD_WRITE_RESULT_SUCCESS = 0,
+
+ /** The clipboard write was denied by policy or the user. */
+ GHOSTTY_CLIPBOARD_WRITE_RESULT_DENIED = 1,
+
+ /** The destination or one or more representations are unsupported. */
+ GHOSTTY_CLIPBOARD_WRITE_RESULT_UNSUPPORTED = 2,
+
+ /** The clipboard is temporarily unavailable. */
+ GHOSTTY_CLIPBOARD_WRITE_RESULT_BUSY = 3,
+
+ /** One or more representations contain invalid data. */
+ GHOSTTY_CLIPBOARD_WRITE_RESULT_INVALID_DATA = 4,
+
+ /** The clipboard write failed due to an I/O error. */
+ GHOSTTY_CLIPBOARD_WRITE_RESULT_IO_ERROR = 5,
+ GHOSTTY_CLIPBOARD_WRITE_RESULT_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
+} GhosttyClipboardWriteResult;
+
+/**
+ * Callback function type for clipboard_write.
+ *
+ * Called synchronously for a complete logical clipboard write. Protocol
+ * details such as OSC 52 selectors, base64 encoding, multipart chunks,
+ * aliases, and terminators are normalized before this callback is invoked.
+ * OSC 52 and iTerm2 OSC 1337 Copy writes therefore use the same callback
+ * shape. OSC 52 clipboard read requests ("?") are always ignored and never
+ * forwarded to this callback.
+ *
+ * @param terminal The terminal handle
+ * @param userdata The userdata pointer set via GHOSTTY_TERMINAL_OPT_USERDATA
+ * @param write Borrowed atomic clipboard write request
+ * @return The result of attempting the clipboard write
+ *
+ * @ingroup terminal
+ */
+typedef GhosttyClipboardWriteResult (*GhosttyTerminalClipboardWriteFn)(
+ GhosttyTerminal terminal,
+ void* userdata,
+ const GhosttyClipboardWrite* write);
+
+/**
* Callback function type for color scheme queries (CSI ? 996 n).
*
* Called when the terminal receives a color scheme device status report
@@ -353,6 +557,31 @@ typedef void (*GhosttyTerminalTitleChangedFn)(GhosttyTerminal terminal,
void* userdata);
/**
+ * Callback function type for pwd_changed.
+ *
+ * Called when the terminal pwd (current working directory) changes via
+ * escape sequences: OSC 7 (file:// URI), OSC 9 (ConEmu CurrentDir), or
+ * OSC 1337 CurrentDir (iTerm2). Use ghostty_terminal_get() with
+ * GHOSTTY_TERMINAL_DATA_PWD inside the callback to read the new value.
+ *
+ * The terminal stores whatever bytes the shell emitted, without parsing.
+ * That means for OSC 7 the value is the raw URI (typically file://...);
+ * for OSC 9/OSC 1337 it is typically a bare path. The embedder is
+ * responsible for decoding any URI scheme or host if it cares about them.
+ *
+ * The callback also fires when the shell clears the pwd (e.g. an empty
+ * OSC 7). In that case GHOSTTY_TERMINAL_DATA_PWD returns a zero-length
+ * string.
+ *
+ * @param terminal The terminal handle
+ * @param userdata The userdata pointer set via GHOSTTY_TERMINAL_OPT_USERDATA
+ *
+ * @ingroup terminal
+ */
+typedef void (*GhosttyTerminalPwdChangedFn)(GhosttyTerminal terminal,
+ void* userdata);
+
+/**
* Callback function type for write_pty.
*
* Called when the terminal needs to write data back to the pty, for
@@ -608,6 +837,56 @@ typedef enum GHOSTTY_ENUM_TYPED {
* Input type: GhosttySelection*
*/
GHOSTTY_TERMINAL_OPT_SELECTION = 21,
+
+ /**
+ * Set the default cursor style used by DECSCUSR reset (CSI 0 q).
+ *
+ * A NULL value pointer resets to the built-in default block cursor.
+ *
+ * Input type: GhosttyTerminalCursorStyle*
+ */
+ GHOSTTY_TERMINAL_OPT_DEFAULT_CURSOR_STYLE = 22,
+
+ /**
+ * Set whether the default cursor should blink when reset by DECSCUSR
+ * (CSI 0 q).
+ *
+ * A NULL value pointer resets to the built-in default of not blinking.
+ *
+ * Input type: bool*
+ */
+ GHOSTTY_TERMINAL_OPT_DEFAULT_CURSOR_BLINK = 23,
+
+ /**
+ * Enable or disable Glyph Protocol APC handling.
+ *
+ * When disabled, Glyph Protocol APC sequences are ignored and no
+ * support/query/register/clear responses are emitted. Disabling also clears
+ * the terminal session's glyph glossary. A NULL value pointer is a no-op.
+ *
+ * Input type: bool*
+ */
+ GHOSTTY_TERMINAL_OPT_GLYPH_PROTOCOL = 24,
+
+ /**
+ * Callback invoked when the terminal pwd changes via escape
+ * sequences (OSC 7, OSC 9, or OSC 1337 CurrentDir). Set to NULL
+ * to ignore pwd change events.
+ *
+ * Input type: GhosttyTerminalPwdChangedFn
+ */
+ GHOSTTY_TERMINAL_OPT_PWD_CHANGED = 25,
+
+ /**
+ * Callback invoked when the running program performs a clipboard write.
+ * OSC 52 and iTerm2 OSC 1337 Copy writes are normalized to an atomic set
+ * of decoded MIME representations. Set to NULL to ignore clipboard writes.
+ * Clipboard read requests are always ignored; see
+ * GhosttyTerminalClipboardWriteFn.
+ *
+ * Input type: GhosttyTerminalClipboardWriteFn
+ */
+ GHOSTTY_TERMINAL_OPT_CLIPBOARD_WRITE = 26,
GHOSTTY_TERMINAL_OPT_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
} GhosttyTerminalOption;
@@ -682,9 +961,16 @@ typedef enum GHOSTTY_ENUM_TYPED {
/**
* Scrollbar state for the terminal viewport.
*
- * This may be expensive to calculate depending on where the viewport
- * is (arbitrary pins are expensive). The caller should take care to only
- * call this as needed and not too frequently.
+ * This is amortized O(1): the total is maintained incrementally as
+ * the terminal is modified and the viewport offset is cached. The
+ * first read after the viewport moves to an arbitrary position that
+ * isn't an absolute row (e.g. scrolling to a selection) may cost
+ * O(pages) to compute the offset, after which it is cached again.
+ *
+ * There is intentionally no change notification for scroll state.
+ * Callers building scrollbars should poll this once per frame or
+ * per write batch and diff the result to detect changes; this is
+ * what Ghostty's own renderer does.
*
* Output type: GhosttyTerminalScrollbar *
*/
@@ -1035,7 +1321,10 @@ GHOSTTY_API void ghostty_terminal_vt_write(GhosttyTerminal terminal,
* Scrolls the terminal's viewport according to the given behavior.
* When using GHOSTTY_SCROLL_VIEWPORT_DELTA, set the delta field in
* the value union to specify the number of rows to scroll (negative
- * for up, positive for down). For other behaviors, the value is ignored.
+ * for up, positive for down). When using GHOSTTY_SCROLL_VIEWPORT_ROW,
+ * set the row field to the absolute row offset from the top of the
+ * scrollable area (the same row space as the offset field of
+ * GhosttyTerminalScrollbar). For other behaviors, the value is ignored.
*
* @param terminal The terminal handle (may be NULL, in which case this is a no-op)
* @param behavior The scroll behavior as a tagged union
@@ -1046,6 +1335,60 @@ GHOSTTY_API void ghostty_terminal_scroll_viewport(GhosttyTerminal terminal,
GhosttyTerminalScrollViewport behavior);
/**
+ * Return the current compression activity token.
+ *
+ * The token is opaque and only equality comparisons are meaningful. An
+ * embedding application should cache it and restart its compression idle
+ * delay whenever the value changes. The value may wrap and changes in either
+ * direction have the same meaning.
+ *
+ * This function only observes terminal state. It does not perform or schedule
+ * compression.
+ *
+ * @param terminal The terminal handle (NULL returns GHOSTTY_INVALID_VALUE)
+ * @param[out] out_activity Receives the current activity token
+ * @return GHOSTTY_SUCCESS on success, or GHOSTTY_INVALID_VALUE if an argument
+ * is NULL
+ *
+ * @ingroup terminal
+ */
+GHOSTTY_API GhosttyResult ghostty_terminal_compression_activity(
+ GhosttyTerminal terminal,
+ uint64_t* out_activity);
+
+/**
+ * Compress eligible terminal scrollback.
+ *
+ * Incremental mode performs bounded work suitable for an idle callback. A
+ * pending result means the application should invoke another step while the
+ * terminal remains idle. A complete result means no continuation is needed
+ * until ghostty_terminal_compression_activity() changes. Full mode performs
+ * one synchronous scan and can stall on large scrollback buffers.
+ *
+ * Compression is opportunistic. Complete means the pass has finished, not
+ * that every page was compressed: pages may be unprofitable or encounter an
+ * allocation or reclamation failure. Compression changes only the terminal's
+ * storage representation and never its logical contents or scrollback limit.
+ * Accessing compressed history restores it transparently.
+ *
+ * This function is not thread-safe with other operations on the same
+ * terminal. The caller must serialize it with writes, rendering, searches,
+ * and other terminal access.
+ *
+ * @param terminal The terminal handle (NULL returns GHOSTTY_INVALID_VALUE)
+ * @param mode The amount of compression work to perform
+ * @param[out] out_result Receives the compression scheduling result
+ * @return GHOSTTY_SUCCESS on success, or GHOSTTY_INVALID_VALUE if an argument
+ * or mode is invalid
+ *
+ * @ingroup terminal
+ */
+GHOSTTY_API GhosttyResult ghostty_terminal_compress(
+ GhosttyTerminal terminal,
+ GhosttyTerminalCompressionMode mode,
+ GhosttyTerminalCompressionResult* out_result);
+
+/**
* Get the current value of a terminal mode.
*
* Returns the value of the mode identified by the given mode.
diff --git a/vendor/libghostty-vt/include/ghostty/vt/unicode.h b/vendor/libghostty-vt/include/ghostty/vt/unicode.h
new file mode 100644
index 00000000..e4d62c81
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/unicode.h
@@ -0,0 +1,154 @@
+/**
+ * @file unicode.h
+ *
+ * Unicode utilities - codepoint properties matching the terminal's
+ * text layout semantics.
+ */
+
+#ifndef GHOSTTY_VT_UNICODE_H
+#define GHOSTTY_VT_UNICODE_H
+
+/** @defgroup unicode Unicode Utilities
+ *
+ * Unicode codepoint properties matching the terminal's text layout
+ * semantics.
+ *
+ * ## Basic Usage
+ *
+ * Use ghostty_unicode_codepoint_width() to determine how many terminal
+ * grid cells a codepoint occupies, using the exact same width table the
+ * terminal itself uses when laying out printed text. Use
+ * ghostty_unicode_grapheme_width() to segment and measure full grapheme
+ * clusters with the same rules the terminal uses when mode 2027 is
+ * enabled. These functions are useful for predicting column layout of
+ * text that has not yet been written to the terminal, such as IME
+ * preedit (composition) overlays.
+ *
+ * @{
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <ghostty/vt/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Returns the terminal display width of a Unicode codepoint in
+ * terminal grid cells: 0, 1, or 2.
+ *
+ * This is the same width table the terminal itself uses when laying
+ * out printed text, so callers can predict column layout (e.g. IME
+ * preedit overlays) that exactly matches what the terminal will do
+ * when the text is actually written to it.
+ *
+ * Semantics:
+ * - Returns 0 for zero-width codepoints: C0/C1 control characters,
+ * nonspacing and enclosing combining marks, default-ignorable
+ * codepoints (ZWJ, ZWNJ, variation selectors, etc.), and
+ * surrogate codepoints.
+ * - Returns 2 for wide codepoints: East Asian Wide/Fullwidth
+ * (including emoji with default emoji presentation) and regional
+ * indicators. Width is clamped to 2 (e.g. the three-em dash).
+ * - Returns 1 for everything else, including invalid codepoints
+ * beyond U+10FFFF (this function is total; it never fails).
+ *
+ * This operates on a single codepoint only and therefore cannot account
+ * for grapheme-cluster-level width rules (VS16 emoji presentation,
+ * combining sequences, etc.). For cluster-accurate widths, use
+ * ghostty_unicode_grapheme_width(). Summing per-codepoint widths is only
+ * correct when mode 2027 (grapheme clustering) is disabled.
+ *
+ * This function is pure, allocates nothing, and is thread-safe.
+ *
+ * @param cp The Unicode codepoint to measure
+ * @return Display width in cells: 0, 1, or 2
+ */
+GHOSTTY_API uint8_t ghostty_unicode_codepoint_width(uint32_t cp);
+
+/**
+ * Measures the terminal display width of the first grapheme cluster in a
+ * sequence of Unicode codepoints.
+ *
+ * This uses the exact same grapheme segmentation and cluster width rules
+ * the terminal itself uses when printing text with grapheme clustering
+ * enabled (mode 2027), so callers can predict column layout (e.g. IME
+ * preedit overlays) that exactly matches what the terminal will do when
+ * the text is actually written to it. Unlike
+ * ghostty_unicode_codepoint_width(), this accounts for cluster-level
+ * rules: emoji variation selectors, ZWJ sequences, combining marks, and
+ * skin tone modifiers.
+ *
+ * Reads codepoints from cps until the terminal would consider the
+ * grapheme cluster complete, stores the cluster's total width in cells
+ * (0, 1, or 2) into width (which may be NULL if only segmentation is
+ * desired), and returns the number of codepoints consumed. Returns 0 if
+ * and only if len is 0; otherwise consumes at least one codepoint. Measure
+ * a whole string by calling in a loop:
+ *
+ * @code
+ * size_t total = 0;
+ * for (size_t i = 0; i < len;) {
+ * uint8_t width;
+ * i += ghostty_unicode_grapheme_width(cps + i, len - i, &width);
+ * total += width;
+ * }
+ * @endcode
+ *
+ * This is not a streaming API. The provided sequence must contain a
+ * complete first grapheme cluster, or the logical end of the string. If
+ * input arrives in chunks, keep buffering while this function consumes all
+ * available codepoints (return value == len) and the stream may still
+ * continue; a later codepoint could still extend the cluster and change
+ * its width.
+ *
+ * Width semantics, matching the terminal with mode 2027 enabled:
+ * - The cluster starts at the width of its first codepoint, as returned by
+ * ghostty_unicode_codepoint_width().
+ * - VS16 (U+FE0F) forces the cluster wide (2) and VS15 (U+FE0E) forces it
+ * narrow (1), but only when the immediately preceding codepoint in the
+ * cluster is a valid emoji variation sequence base (per Unicode
+ * emoji-variation-sequences.txt). Invalid variation selectors are
+ * ignored entirely.
+ * - Any other continuation codepoint that contributes to grapheme width
+ * forces the cluster wide (2). Note this means cluster width is NOT the
+ * maximum of per-codepoint widths: some continuation marks have narrow
+ * codepoint width yet still widen the cluster.
+ *
+ * Mode dependence: this models mode 2027 (grapheme clustering) enabled,
+ * which is Ghostty's recommended configuration. When mode 2027 is
+ * disabled, clusters never combine and variation selectors never change
+ * width; predict layout in that case by summing
+ * ghostty_unicode_codepoint_width() over each codepoint instead.
+ *
+ * Edge cases:
+ * - Codepoints beyond U+10FFFF consume one codepoint, have width 1, and
+ * are always cluster boundaries. This function is total; it never fails.
+ * - Control characters (C0/C1, CR, LF) are never printed through the
+ * terminal's text path; passing them here returns an unspecified (but
+ * stable and bounded) result.
+ * - A cluster whose first codepoint is zero-width (e.g. a lone combining
+ * mark) is malformed at a cell start; the terminal may attach it to
+ * earlier screen content. This function reports the fold result for the
+ * sequence in isolation (typically 0).
+ *
+ * This function is pure, allocates nothing, and is thread-safe.
+ *
+ * @param cps Pointer to codepoints (may be NULL only when len is 0)
+ * @param len Number of codepoints available
+ * @param width Out: cluster display width in cells (0-2); may be NULL
+ * @return Number of codepoints in the first grapheme cluster
+ */
+GHOSTTY_API size_t ghostty_unicode_grapheme_width(const uint32_t *cps,
+ size_t len,
+ uint8_t *width);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif /* GHOSTTY_VT_UNICODE_H */