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