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

Register callbacks for what a program asks of the terminal: pty replies, the bell, title changes, OSC 52 clipboard reads and writes, and unknown sequences. You need these as soon as a real program runs in the terminal.

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <ghostty/vt.h>
void on_write_pty(GhosttyTerminal terminal,
void* userdata,
const uint8_t* data,
size_t len) {
(void)terminal;
(void)userdata;
printf(" write_pty (%zu bytes): ", len);
fwrite(data, 1, len, stdout);
printf("\n");
}
void on_bell(GhosttyTerminal terminal, void* userdata) {
(void)terminal;
int* count = (int*)userdata;
(*count)++;
printf(" bell! (count=%d)\n", *count);
}
void on_title_changed(GhosttyTerminal terminal, void* userdata) {
(void)userdata;
// The new title is already set, so you can read it here with
// GHOSTTY_TERMINAL_DATA_TITLE. This example reads the cursor position
// to show that the terminal can be queried from a callback.
uint16_t col = 0;
printf(" title changed (cursor at col %u)\n", col);
}
void on_clipboard_write(
GhosttyTerminal terminal,
void* userdata,
const GhosttyClipboardWrite* write) {
(void)terminal;
(void)userdata;
// The write is synchronous: a real embedder would ask the user for
// permission here (unless write->granted) and the VT stream waits until
// this callback returns. The replied result is sent to the program
// (OSC 5522) through the write_pty callback.
printf(" clipboard write (location=%d, contents=%zu)\n",
(int)write->location, write->contents_len);
if (write->contents_len == 0) {
printf(" clear\n");
}
for (size_t i = 0; i < write->contents_len; i++) {
const GhosttyClipboardContent* content = &write->contents[i];
printf(" ");
if (content->mime.len > 0) {
fwrite(content->mime.ptr, 1, content->mime.len, stdout);
}
printf(" (%zu bytes): ", content->data.len);
if (content->data.len > 0) {
fwrite(content->data.ptr, 1, content->data.len, stdout);
}
printf("\n");
}
.size = sizeof(reply),
.remember = false,
};
write->reply(write, &reply);
}
void on_clipboard_read(
GhosttyTerminal terminal,
void* userdata,
const GhosttyClipboardRead* read) {
(void)terminal;
(void)userdata;
// The read is synchronous: a real embedder would ask the user for
// permission here (unless read->granted) and the VT stream waits until
// this callback returns. The reply is sent to the program through the
// write_pty callback.
printf(" clipboard read (location=%d, mimes=%zu)\n",
(int)read->location, read->mimes_len);
for (size_t i = 0; i < read->mimes_len; i++) {
printf(" ");
fwrite(read->mimes[i].ptr, 1, read->mimes[i].len, stdout);
printf("\n");
}
// Reply with every requested representation we have. This example only
// has text.
const char* text = "Hello from the clipboard";
.mime = {.ptr = (const uint8_t*)"text/plain", .len = 10},
.data = {.ptr = (const uint8_t*)text, .len = strlen(text)},
};
.size = sizeof(reply),
.contents = &content,
.contents_len = 1,
.available = NULL,
.available_len = 0,
.remember = false,
};
read->reply(read, &reply);
}
void on_unknown_sequence(
GhosttyTerminal terminal,
void* userdata,
const GhosttyTerminalUnknownSequence* sequence) {
(void)terminal;
(void)userdata;
switch (sequence->tag) {
const GhosttyTerminalUnknownStringSequence* apc = &sequence->value.apc;
printf(" unknown APC (truncated=%s, content=%zu bytes): ",
apc->truncated ? "yes" : "no",
apc->content.len);
if (apc->content.len > 0) {
fwrite(apc->content.ptr, 1, apc->content.len, stdout);
}
printf("\n");
break;
}
// The content starts with the OSC number, for example
// "7400;status=busy". A real application would check for the
// numbers it implements and ignore the rest. If it replies, it should
// end the reply with the same terminator the program used.
const GhosttyTerminalUnknownOscSequence* osc = &sequence->value.osc;
printf(" unknown OSC (truncated=%s, terminator=%s, content=%zu bytes): ",
osc->truncated ? "yes" : "no",
osc->terminator == GHOSTTY_OSC_TERMINATOR_BEL ? "BEL" : "ST",
osc->content.len);
if (osc->content.len > 0) {
fwrite(osc->content.ptr, 1, osc->content.len, stdout);
}
printf("\n");
break;
}
default:
break;
}
}
int main() {
// Create a terminal
GhosttyTerminal terminal = NULL;
if (ghostty_terminal_new(NULL, &terminal, 80, 24) != GHOSTTY_SUCCESS) {
fprintf(stderr, "Failed to create terminal\n");
return 1;
}
// Set up userdata — a simple bell counter
int bell_count = 0;
// Register effect callbacks
(const void *)on_write_pty);
(const void *)on_bell);
(const void *)on_title_changed);
(const void *)on_clipboard_write);
(const void *)on_clipboard_read);
(const void *)on_unknown_sequence);
// Unknown sequence capture is independently bounded and disabled by
// default. This limit will apply to every supported unknown sequence type.
size_t unknown_max_bytes = 256;
&unknown_max_bytes);
// Feed VT data that triggers effects:
// 1. Bell (BEL = 0x07)
printf("Sending BEL:\n");
const uint8_t bel = 0x07;
ghostty_terminal_vt_write(terminal, &bel, 1);
// 2. Title change (OSC 2 ; <title> ST)
printf("Sending title change:\n");
const char* title_seq = "\x1B]2;Hello Effects\x1B\\";
ghostty_terminal_vt_write(terminal, (const uint8_t*)title_seq,
strlen(title_seq));
// 3. Device status report (DECRQM for wraparound mode ?7)
// triggers write_pty with the response
printf("Sending DECRQM query:\n");
const char* decrqm = "\x1B[?7$p";
ghostty_terminal_vt_write(terminal, (const uint8_t*)decrqm,
strlen(decrqm));
// 4. Clipboard write (OSC 52 ; c ; <base64 data> ST)
printf("Sending clipboard write:\n");
const char* clipboard_seq =
"\x1B]52;c;SGVsbG8gY2xpcGJvYXJk\x1B\\";
ghostty_terminal_vt_write(terminal, (const uint8_t*)clipboard_seq,
strlen(clipboard_seq));
// 5. Clipboard read (OSC 52 ; c ; ? ST)
printf("Sending clipboard read:\n");
const char* clipboard_read_seq = "\x1B]52;c;?\x1B\\";
ghostty_terminal_vt_write(terminal, (const uint8_t*)clipboard_read_seq,
strlen(clipboard_read_seq));
// 6. Unsupported APC sequence
printf("Sending unknown APC:\n");
const char* unknown_apc = "\x1B_private-command;payload\x1B\\";
ghostty_terminal_vt_write(terminal, (const uint8_t*)unknown_apc,
strlen(unknown_apc));
printf("Sending unknown OSC:\n");
const char* unknown_osc = "\x1B]7400;status=busy\x07";
ghostty_terminal_vt_write(terminal, (const uint8_t*)unknown_osc,
strlen(unknown_osc));
// 7. Another bell to show the counter increments
printf("Sending another BEL:\n");
ghostty_terminal_vt_write(terminal, &bel, 1);
printf("Total bells: %d\n", bell_count);
return 0;
}
@ GHOSTTY_SUCCESS
Definition types.h:145
@ GHOSTTY_CLIPBOARD_READ_RESULT_SUCCESS
Definition terminal.h:947
@ GHOSTTY_CLIPBOARD_WRITE_RESULT_SUCCESS
Definition terminal.h:780
@ GHOSTTY_TERMINAL_UNKNOWN_SEQUENCE_OSC
Definition terminal.h:598
@ GHOSTTY_TERMINAL_UNKNOWN_SEQUENCE_APC
Definition terminal.h:595
@ GHOSTTY_OSC_TERMINATOR_BEL
Definition osc.h:125
GHOSTTY_API GhosttyResult ghostty_terminal_set(GhosttyTerminal terminal, GhosttyTerminalOption option, const void *value)
GHOSTTY_API GhosttyResult ghostty_terminal_get(GhosttyTerminal terminal, GhosttyTerminalData data, void *out)
struct GhosttyTerminalImpl * GhosttyTerminal
Definition types.h:196
GHOSTTY_API void ghostty_terminal_free(GhosttyTerminal terminal)
GHOSTTY_API void ghostty_terminal_vt_write(GhosttyTerminal terminal, const uint8_t *data, size_t len)
GHOSTTY_API GhosttyResult ghostty_terminal_new(const GhosttyAllocator *allocator, GhosttyTerminal *terminal, uint16_t cols, uint16_t rows)
@ GHOSTTY_TERMINAL_DATA_CURSOR_X
Definition terminal.h:2681
@ GHOSTTY_TERMINAL_OPT_TITLE_CHANGED
Definition terminal.h:2083
@ GHOSTTY_TERMINAL_OPT_UNKNOWN_MAX_BYTES
Definition terminal.h:2473
@ GHOSTTY_TERMINAL_OPT_USERDATA
Definition terminal.h:2040
@ GHOSTTY_TERMINAL_OPT_CLIPBOARD_WRITE
Definition terminal.h:2304
@ GHOSTTY_TERMINAL_OPT_WRITE_PTY
Definition terminal.h:2050
@ GHOSTTY_TERMINAL_OPT_BELL
Definition terminal.h:2058
@ GHOSTTY_TERMINAL_OPT_UNKNOWN_SEQUENCE
Definition terminal.h:2452
@ GHOSTTY_TERMINAL_OPT_CLIPBOARD_READ
Definition terminal.h:2500
GhosttyString mime
Definition terminal.h:767
GhosttyString data
Definition terminal.h:770
GhosttyClipboardReadReplyFn reply
Definition terminal.h:1097
GhosttyClipboardLocation location
Definition terminal.h:1050
const GhosttyString * mimes
Definition terminal.h:1057
GhosttyClipboardWriteReplyFn reply
Definition terminal.h:906
const GhosttyClipboardContent * contents
Definition terminal.h:878
GhosttyClipboardLocation location
Definition terminal.h:875
size_t len
Definition types.h:444
const uint8_t * ptr
Definition types.h:441
GhosttyOscTerminator terminator
Definition terminal.h:657
GhosttyTerminalUnknownOscSequence osc
Definition terminal.h:670
GhosttyTerminalUnknownStringSequence apc
Definition terminal.h:667