1/**
2 * @file sys.h
3 *
4 * System interface - runtime-swappable implementations for external dependencies.
5 */
6
7#ifndef GHOSTTY_VT_SYS_H
8#define GHOSTTY_VT_SYS_H
9
10#include <stdbool.h>
11#include <stddef.h>
12#include <stdint.h>
13#include <ghostty/vt/types.h>
14#include <ghostty/vt/allocator.h>
15
16/** @defgroup sys System Interface
17 *
18 * Runtime-swappable function pointers for operations that depend on
19 * external implementations (e.g. image decoding).
20 *
21 * These are process-global settings that must be configured at startup
22 * before any terminal functionality that depends on them is used.
23 * Setting these enables various optional features of the terminal. For
24 * example, setting a PNG decoder enables PNG image support in the Kitty
25 * Graphics Protocol.
26 *
27 * Use ghostty_sys_set() with a `GhosttySysOption` to install or clear
28 * an implementation. Passing NULL as the value clears the implementation
29 * and disables the corresponding feature.
30 *
31 * ## Example
32 *
33 * ### Defining a PNG decode callback
34 * @snippet c-vt-kitty-graphics/src/main.c kitty-graphics-decode-png
35 *
36 * ### Installing the callback and sending a PNG image
37 * @snippet c-vt-kitty-graphics/src/main.c kitty-graphics-main
38 *
39 * @{
40 */
41
42#ifdef __cplusplus
43extern "C" {
44#endif
45
46/**
47 * Result of decoding an image.
48 *
49 * The `data` buffer must be allocated through the allocator provided to
50 * the decode callback. The library takes ownership and will free it
51 * with the same allocator.
52 */
53typedef struct {
54 /** Image width in pixels. */
55 uint32_t width;
56
57 /** Image height in pixels. */
58 uint32_t height;
59
60 /** Pointer to the decoded RGBA pixel data. */
61 uint8_t* data;
62
63 /** Length of the pixel data in bytes. */
64 size_t data_len;
65} GhosttySysImage;
66
67/**
68 * Log severity levels for the log callback.
69 */
70typedef enum GHOSTTY_ENUM_TYPED {
71 GHOSTTY_SYS_LOG_LEVEL_ERROR = 0,
72 GHOSTTY_SYS_LOG_LEVEL_WARNING = 1,
73 GHOSTTY_SYS_LOG_LEVEL_INFO = 2,
74 GHOSTTY_SYS_LOG_LEVEL_DEBUG = 3,
75 GHOSTTY_SYS_LOG_LEVEL_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
76} GhosttySysLogLevel;
77
78/**
79 * Callback type for logging.
80 *
81 * When installed, internal library log messages are delivered through
82 * this callback instead of being discarded. The embedder is responsible
83 * for formatting and routing log output.
84 *
85 * @p scope is the log scope name as UTF-8 bytes (e.g. "osc", "kitty").
86 * When the log is unscoped (default scope), @p scope_len is 0.
87 *
88 * All pointer arguments are only valid for the duration of the callback.
89 * The callback must be safe to call from any thread.
90 *
91 * @param userdata The userdata pointer set via GHOSTTY_SYS_OPT_USERDATA
92 * @param level The severity level of the log message
93 * @param scope Pointer to the scope name bytes
94 * @param scope_len Length of the scope name in bytes
95 * @param message Pointer to the log message bytes
96 * @param message_len Length of the log message in bytes
97 */
98typedef void (*GhosttySysLogFn)(
99 void* userdata,
100 GhosttySysLogLevel level,
101 const uint8_t* scope,
102 size_t scope_len,
103 const uint8_t* message,
104 size_t message_len);
105
106/**
107 * Callback type for PNG decoding.
108 *
109 * Decodes raw PNG data into RGBA pixels. The output pixel data must be
110 * allocated through the provided allocator. The library takes ownership
111 * of the buffer and will free it with the same allocator.
112 *
113 * @param userdata The userdata pointer set via GHOSTTY_SYS_OPT_USERDATA
114 * @param allocator The allocator to use for the output pixel buffer
115 * @param data Pointer to the raw PNG data
116 * @param data_len Length of the raw PNG data in bytes
117 * @param[out] out On success, filled with the decoded image
118 * @return true on success, false on failure
119 */
120typedef bool (*GhosttySysDecodePngFn)(
121 void* userdata,
122 const GhosttyAllocator* allocator,
123 const uint8_t* data,
124 size_t data_len,
125 GhosttySysImage* out);
126
127/**
128 * System option identifiers for ghostty_sys_set().
129 */
130typedef enum GHOSTTY_ENUM_TYPED {
131 /**
132 * Set the userdata pointer passed to all sys callbacks.
133 *
134 * Input type: void* (or NULL)
135 */
136 GHOSTTY_SYS_OPT_USERDATA = 0,
137
138 /**
139 * Set the PNG decode function.
140 *
141 * When set, the terminal can accept PNG images via the Kitty
142 * Graphics Protocol. When cleared (NULL value), PNG decoding is
143 * unsupported and PNG image data will be rejected.
144 *
145 * Input type: GhosttySysDecodePngFn (function pointer, or NULL)
146 */
147 GHOSTTY_SYS_OPT_DECODE_PNG = 1,
148
149 /**
150 * Set the log callback.
151 *
152 * When set, internal library log messages are delivered to this
153 * callback. When cleared (NULL value), log messages are silently
154 * discarded.
155 *
156 * Use ghostty_sys_log_stderr as a convenience callback that
157 * writes formatted messages to stderr.
158 *
159 * Which log levels are emitted depends on the build mode of the
160 * library and is not configurable at runtime. Debug builds emit
161 * all levels (debug and above). Release builds emit info and
162 * above; debug-level messages are compiled out entirely and will
163 * never reach the callback.
164 *
165 * Input type: GhosttySysLogFn (function pointer, or NULL)
166 */
167 GHOSTTY_SYS_OPT_LOG = 2,
168 GHOSTTY_SYS_OPT_MAX_VALUE = GHOSTTY_ENUM_MAX_VALUE,
169} GhosttySysOption;
170
171/**
172 * Set a system-level option.
173 *
174 * Configures a process-global implementation function. These should be
175 * set once at startup before using any terminal functionality that
176 * depends on them.
177 *
178 * @param option The option to set
179 * @param value Pointer to the value (type depends on the option),
180 * or NULL to clear it
181 * @return GHOSTTY_SUCCESS on success, GHOSTTY_INVALID_VALUE if the
182 * option is not recognized
183 */
184GHOSTTY_API GhosttyResult ghostty_sys_set(GhosttySysOption option,
185 const void* value);
186
187/**
188 * Built-in log callback that writes to stderr.
189 *
190 * Formats each message as "[level](scope): message\n".
191 * Can be passed directly to ghostty_sys_set():
192 *
193 * @code
194 * ghostty_sys_set(GHOSTTY_SYS_OPT_LOG, &ghostty_sys_log_stderr);
195 * @endcode
196 */
197GHOSTTY_API void ghostty_sys_log_stderr(void* userdata,
198 GhosttySysLogLevel level,
199 const uint8_t* scope,
200 size_t scope_len,
201 const uint8_t* message,
202 size_t message_len);
203
204#ifdef __cplusplus
205}
206#endif
207
208/** @} */
209
210#endif /* GHOSTTY_VT_SYS_H */