summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-15 13:04:32 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-15 13:04:32 +0300
commitbdaedce69b17b654bd0060579dd9b9ff120009b5 (patch)
tree0e9cd8597652263a96c48ba678fb0b66e1fc131b /include
parentba75c8b0a1bba03ad92c53375432f122ddb4cb98 (diff)
parentdcebf9c7f954a55350b68d0ead1935612c4e2e05 (diff)
Merge branch 'wt/rename' into api-hardening
# Conflicts: # README.md
Diffstat (limited to 'include')
-rw-r--r--include/term/term.h492
-rw-r--r--include/term/term_input.h202
-rw-r--r--include/term/unicode/grapheme.h26
-rw-r--r--include/term/unicode/unicode.h6
-rw-r--r--include/term/unicode/width.h56
-rw-r--r--include/wsap_vtcore/unicode/grapheme.h26
-rw-r--r--include/wsap_vtcore/unicode/unicode.h6
-rw-r--r--include/wsap_vtcore/unicode/unicode_data.inc (renamed from include/term/unicode/unicode_data.inc)14
-rw-r--r--include/wsap_vtcore/unicode/utf8.h (renamed from include/term/unicode/utf8.h)70
-rw-r--r--include/wsap_vtcore/unicode/width.h56
-rw-r--r--include/wsap_vtcore/wsap_vtcore.h492
-rw-r--r--include/wsap_vtcore/wsap_vtcore_input.h202
-rw-r--r--include/wsap_vtcore/wsap_vtcore_types.h (renamed from include/term/term_types.h)14
13 files changed, 831 insertions, 831 deletions
diff --git a/include/term/term.h b/include/term/term.h
deleted file mode 100644
index 8b98a25..0000000
--- a/include/term/term.h
+++ /dev/null
@@ -1,492 +0,0 @@
-#ifndef TERM_H
-#define TERM_H
-
-/*
- * Terminal emulator core.
- *
- * A struct term parses the bytes that a program writes and keeps the screen,
- * the history, and the modes. The application feeds bytes with term_feed()
- * and reads state with the getters below. A renderer never reads the
- * terminal directly: it copies the viewport into a struct term_snapshot and
- * paints from that copy.
- *
- * All functions take the terminal as the first argument. Functions that take
- * a const struct term do not change what it shows. Selection, history, link,
- * directory, and pointer-shape queries return owned strings; release them
- * with term_text_free().
- *
- * Threads. Any thread can call any function. Each call that reads or changes
- * a terminal enters its writer section, so calls on one terminal run one at a
- * time. A thread that waits for the section sleeps. On POSIX the section is a
- * mutex with priority inheritance where the platform has it. A snapshot
- * belongs to one thread at a time. term_free() is the last call on a terminal.
- */
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include "term_input.h"
-#include "term_types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct term;
-struct term_snapshot;
-
-/* A row holds at most this many cells. */
-#define TERM_MAX_COLS 65535
-/* The history limit when term_options.scrollback is 0. */
-#define TERM_SCROLLBACK_DEFAULT 10000
-/* The largest term_options.scrollback. */
-#define TERM_SCROLLBACK_MAX 1000000
-
-/*
- * The version of this header. A host compares TERM_VERSION_CODE with
- * term_version() to check that the library matches the header.
- */
-#define TERM_VERSION(major, minor, patch) (((major) << 16) | ((minor) << 8) | (patch))
-#define TERM_VERSION_MAJOR 0
-#define TERM_VERSION_MINOR 1
-#define TERM_VERSION_PATCH 0
-#define TERM_VERSION_CODE TERM_VERSION(TERM_VERSION_MAJOR, TERM_VERSION_MINOR, TERM_VERSION_PATCH)
-
-/*
- * Colors. A term_color is either a direct color (alpha 0xFF, then RGB) or a
- * palette slot: an index 0-255, the default foreground, or the default
- * background. A slot resolves when a snapshot is painted, so a theme change
- * recolors text that is already on screen.
- */
-typedef uint32_t term_color;
-
-#define TERM_COLOR_SLOT 0x01000000u
-/* The palette index of a slot; see struct term_view.palette. */
-#define TERM_COLOR_SLOT_INDEX 0x1FFu
-#define TERM_COLOR_FG (TERM_COLOR_SLOT | 0x100u)
-#define TERM_COLOR_BG (TERM_COLOR_SLOT | 0x101u)
-
-static inline term_color term_color_index(int n)
-{
- return TERM_COLOR_SLOT | ((uint32_t)n & 0xFFu);
-}
-
-static inline term_color term_color_rgb(uint8_t r, uint8_t g, uint8_t b)
-{
- return 0xFF000000u | (uint32_t)r << 16 | (uint32_t)g << 8 | b;
-}
-
-static inline bool term_color_is_slot(term_color c)
-{
- return (c >> 24) == (TERM_COLOR_SLOT >> 24);
-}
-
-/* Parse an X11 or OSC color specification ("#rgb", "rgb:r/g/b", ...). */
-TERM_API bool term_color_parse(const char *spec, uint32_t *argb);
-
-/* The colors a terminal starts with. All values are ARGB. An all-zero theme
- * selects the built-in theme. */
-struct term_theme {
- uint32_t fg, bg, cursor;
- uint32_t ansi[16];
-};
-
-/* Fill theme with the built-in theme. */
-TERM_API void term_theme_default(struct term_theme *theme);
-/* Fill theme with the high-contrast theme. */
-TERM_API void term_theme_high_contrast(struct term_theme *theme);
-/* Sets one palette key: foreground, background, or color0 to color15.
- * An empty value resets the key to the built-in theme. False, with no
- * change, for an unknown key or a bad color. */
-TERM_API bool term_theme_set_key(struct term_theme *p, const char *key, const char *val);
-
-enum term_cursor_style {
- TERM_CURSOR_BLOCK,
- TERM_CURSOR_UNDERLINE,
- TERM_CURSOR_BAR,
-};
-
-/* Mouse reporting modes and encodings. The values are the DEC mode numbers. */
-enum term_mouse {
- TERM_MOUSE_OFF = 0,
- TERM_MOUSE_X10 = 9,
- TERM_MOUSE_NORMAL = 1000,
- TERM_MOUSE_BUTTON = 1002,
- TERM_MOUSE_ANY = 1003,
-};
-
-enum term_mouse_encoding {
- TERM_MOUSE_ENC_X10 = 0,
- TERM_MOUSE_ENC_UTF8 = 1005,
- TERM_MOUSE_ENC_SGR = 1006,
- TERM_MOUSE_ENC_URXVT = 1015,
- TERM_MOUSE_ENC_SGR_PIXELS = 1016,
-};
-
-/*
- * Callbacks. They run inside term_feed() and term_focus(), on the thread
- * that calls those functions. A callback must not call back into the
- * terminal. String arguments are valid only during the call.
- */
-struct term_callbacks {
- void *ud;
- /* Bytes the terminal sends back to the program (replies to queries). */
- void (*reply)(void *ud, const char *bytes, size_t len);
- void (*title)(void *ud, const char *title);
- /*
- * OSC 52 clipboard callback.
- * selection names the target clipboard buffer(s), commonly:
- * "c" - clipboard (system clipboard)
- * "p" - primary selection (X11 primary)
- * "q" - secondary selection
- * "s" - select selection
- * "0".."7" - cut buffers 0 to 7
- * A parameter may contain multiple targets (e.g. "cp").
- * data contains decoded bytes of length len.
- */
- void (*clipboard)(void *ud, const char *selection, const char *data, size_t len);
- void (*notify)(void *ud, const char *title, const char *body);
- void (*bell)(void *ud);
- /* Parser trace lines for debugging. NULL turns tracing off. The line has no newline. */
- void (*trace)(void *ud, const char *line);
-};
-
-/*
- * Options for term_new(). An all-zero value is valid. A size component of 0
- * selects 80 columns or 24 rows. A negative component, or columns above
- * TERM_MAX_COLS, makes term_new() fail. A scrollback below 0 or above
- * TERM_SCROLLBACK_MAX fails too.
- * cursor_style must be a value of enum term_cursor_style.
- */
-struct term_options {
- struct term_vector2i size; /* columns and rows */
- int scrollback; /* history lines; 0 selects TERM_SCROLLBACK_DEFAULT */
- struct term_theme theme;
- enum term_cursor_style cursor_style;
- bool cursor_steady; /* false: the cursor blinks */
- /*
- * The terminal's name. Programs read it with XTVERSION and XTGETTCAP.
- * It is also the title of a notification that has none. NULL or ""
- * selects "term". Otherwise 1 to 63 printable ASCII bytes, or term_new()
- * returns NULL. term_new() copies the name.
- */
- const char *name;
- struct term_callbacks callbacks;
- /* Must be zero. term_new() returns NULL if any word is nonzero, so a
- * later version can give a word a meaning. */
- uint32_t reserved[8];
-};
-
-/* The Unicode version of the width tables, such as "18.0.0". A host can
- * pass it to programs as UNICODE_VERSION. */
-TERM_API const char *term_unicode_version(void);
-/* The TERM_VERSION_CODE the library was built with. */
-TERM_API unsigned term_version(void);
-
-/* The length of the prefix of buf made of bytes in [0x20, hi). With hi
- * 0x7f, it finds a run of printable ASCII in UTF-8 text, so a host can
- * skip shaping for it. Any thread can call it. */
-TERM_API size_t term_scan_printable_span(const char *buf, size_t len, unsigned char hi);
-
-/* The instruction set level of the running code: "base", "avx2", "avx512",
- * or "neon". On x86-64, the first term_new() picks the highest level the CPU
- * supports. Set TERM_HEADLESS_ISA to a lower level to force it, for tests
- * and comparisons. */
-TERM_API const char *term_isa(void);
-
-/* NULL when memory runs out or an option is invalid. */
-TERM_API struct term *term_new(const struct term_options *opt);
-TERM_API void term_free(struct term *t);
-
-/* Hold the writer section across several calls, so that no other thread
- * changes the terminal between them. The section is a mutex, and a waiting
- * thread sleeps. Keep it short. The thread that holds it can call every
- * function, and it can enter the section again. Each term_lock() needs one
- * term_unlock(). */
-TERM_API void term_lock(struct term *t);
-TERM_API void term_unlock(struct term *t);
-
-/* Change the size in cells. Returns false, and the terminal is unchanged,
- * when a component is below 1, when cols is above TERM_MAX_COLS, or when
- * memory runs out. The screen reflows to the new width. */
-TERM_API bool term_resize(struct term *t, struct term_vector2i size);
-
-/* Replace the theme. A different theme also drops the colors that the
- * program set with OSC; the same theme changes nothing. */
-TERM_API void term_set_theme(struct term *t, const struct term_theme *theme);
-
-/* The cursor style that DECSCUSR 0 and a reset restore. */
-TERM_API void term_set_cursor_default(struct term *t, enum term_cursor_style style, bool steady);
-
-/*
- * Bytes from the program.
- *
- * TERM_FEED_ONLCR: a line feed also returns the cursor to column 0, as a tty
- * with OPOST and ONLCR does. Set it when the bytes did not pass through the
- * tty output processing (for example the fast pipe).
- */
-enum term_feed_flags {
- TERM_FEED_ONLCR = 1u << 0,
-};
-
-/*
- * Feed bytes from the program. Returns false, and changes nothing, when t is
- * NULL, when bytes is NULL and len is not 0, or when flags has a bit that is
- * not in enum term_feed_flags. A len of 0 is a no-op that returns true.
- */
-TERM_API bool term_feed(struct term *t, const char *bytes, size_t len, unsigned flags);
-
-/* Report a focus change. The terminal replies only in focus-event mode. */
-TERM_API void term_focus(struct term *t, bool focused);
-
-/* Modes that affect how the application encodes input. */
-struct term_modes {
- unsigned keyboard; /* kitty keyboard protocol flags */
- enum term_mouse mouse;
- enum term_mouse_encoding mouse_encoding;
- struct term_vector2i grid; /* columns and rows */
- bool app_cursor; /* DECCKM */
- bool app_keypad; /* DECKPAM */
- bool backarrow_bs; /* DECBKM */
- bool bracketed_paste;
- bool focus_events;
- bool alternate; /* the alternate screen is active */
- bool reverse_video; /* DECSCNM */
- bool synchronized; /* mode 2026 */
-};
-
-struct term_cursor {
- struct term_vector2i pos;
- enum term_cursor_style style;
- bool visible;
- bool blink;
-};
-
-TERM_API struct term_vector2i term_size(const struct term *t);
-TERM_API struct term_modes term_modes(const struct term *t);
-
-/*
- * Encode an input event as the bytes the program expects. Get modes from
- * term_modes(). Record ev in keyboard with term_keyboard_update() first. Send
- * the bytes to the program yourself.
- */
-TERM_API struct term_input_result term_input_encode_key(
- const struct term_keyboard_state *keyboard,
- const struct term_key_event *ev,
- const struct term_modes *modes,
- char *buf, size_t capacity
-);
-
-TERM_API struct term_input_result term_input_encode_mouse(
- const struct term_mouse_event *ev,
- const struct term_modes *modes,
- char *buf, size_t capacity
-);
-
-/* Bytes term_input_encode_paste() adds to the text at most. */
-#define TERM_PASTE_EXTRA 12
-
-/*
- * Encode pasted text. Drop control characters and bidi controls, so the
- * program sees only what the user saw. Send a line break as CR. Add the
- * bracketed-paste markers when the program asked for them. A buffer of
- * len + TERM_PASTE_EXTRA bytes is always large enough. Text that is empty
- * after the filter gives TERM_INPUT_CONSUMED.
- */
-TERM_API struct term_input_result term_input_encode_paste(
- const struct term_modes *modes,
- const char *text, size_t len,
- char *buf, size_t capacity
-);
-/* The cursor in screen coordinates (not the viewport). */
-TERM_API struct term_cursor term_cursor(const struct term *t);
-/* Owned, NUL-terminated text from OSC 7 and OSC 22. NULL when unavailable
- * or allocation fails. The strings stay valid after the terminal changes
- * or is freed. Release them with term_text_free(). */
-TERM_API char *term_cwd(const struct term *t);
-TERM_API char *term_pointer_shape(const struct term *t);
-/* Release any owned text returned by the library. NULL is safe. */
-TERM_API void term_text_free(char *text);
-
-/*
- * Viewport. The viewport shows as many rows as the screen. Offset 0 shows
- * the live screen; a larger offset shows that many rows of history above it.
- * The alternate screen has no history, so its offset is always 0.
- */
-struct term_scrollback {
- int offset; /* rows between the viewport and the live screen */
- int total; /* history rows at the current width */
-};
-
-TERM_API struct term_scrollback term_scrollback(const struct term *t);
-/* Scroll the viewport. A positive count moves back into history. */
-TERM_API void term_scroll(struct term *t, int lines);
-TERM_API void term_scroll_to(struct term *t, int offset);
-
-/*
- * Selection, in viewport coordinates. A selection starts at one cell and
- * extends to another; the unit widens both ends to words or whole lines.
- * The terminal clears the selection when the text under it changes.
- */
-enum term_select_unit {
- TERM_SELECT_CELL,
- TERM_SELECT_WORD,
- TERM_SELECT_LINE,
-};
-
-/* Start a selection at cell. For TERM_SELECT_CELL, right_half means the
- * pointer is on the right half of the cell, so the selection starts after it.
- * Returns false when memory runs out; the selection is then unchanged. */
-TERM_API bool term_select_start(struct term *t, struct term_vector2i cell, bool right_half,
- enum term_select_unit unit);
-/* Extend the selection from its start to cell. Returns false when memory runs
- * out; the selection is then unchanged. */
-TERM_API bool term_select_extend(struct term *t, struct term_vector2i cell, bool right_half);
-TERM_API void term_select_clear(struct term *t);
-TERM_API bool term_has_selection(const struct term *t);
-/* Owned, NUL-terminated UTF-8 of the selection. NULL when nothing is
- * selected or allocation fails; a selection of blanks may produce an empty
- * string. Capture is atomic with respect to other calls on t. Release the
- * result with term_text_free(). */
-TERM_API char *term_selection_text(const struct term *t);
-/* Owned OSC 8 link or detected URL at a viewport cell. NULL when there is
- * no link or allocation fails. Release the result with term_text_free(). */
-TERM_API char *term_link_at(const struct term *t, struct term_vector2i cell);
-
-/* Cell attributes share the write core's bit layout. Underline styles are
- * mutually exclusive flags, not a shifted enum; use term_attr_underline(). */
-enum term_attr {
- TERM_ATTR_BOLD = 1u << 0,
- TERM_ATTR_ITALIC = 1u << 1,
- TERM_ATTR_UNDERLINE = 1u << 2,
- TERM_ATTR_STRIKE = 1u << 3,
- TERM_ATTR_OVERLINE = 1u << 4,
- TERM_ATTR_EMOJI = 1u << 5, /* the text requested emoji presentation */
- TERM_ATTR_TEXT = 1u << 6, /* the text requested text presentation */
- TERM_ATTR_FAINT = 1u << 10,
- TERM_ATTR_DOUBLE_UNDERLINE = 1u << 11,
- TERM_ATTR_CURLY_UNDERLINE = 1u << 12,
- TERM_ATTR_DOTTED_UNDERLINE = 1u << 13,
- TERM_ATTR_DASHED_UNDERLINE = 1u << 14,
- TERM_ATTR_LINK = 1u << 15,
-};
-
-#define TERM_ATTR_UNDERLINE_MASK \
- (TERM_ATTR_UNDERLINE | TERM_ATTR_DOUBLE_UNDERLINE | TERM_ATTR_CURLY_UNDERLINE | \
- TERM_ATTR_DOTTED_UNDERLINE | TERM_ATTR_DASHED_UNDERLINE)
-
-enum term_underline {
- TERM_UNDERLINE_NONE,
- TERM_UNDERLINE_SINGLE,
- TERM_UNDERLINE_DOUBLE,
- TERM_UNDERLINE_CURLY,
- TERM_UNDERLINE_DOTTED,
- TERM_UNDERLINE_DASHED,
-};
-
-static inline enum term_underline term_attr_underline(uint16_t attrs)
-{
- if (attrs & TERM_ATTR_DOUBLE_UNDERLINE) return TERM_UNDERLINE_DOUBLE;
- if (attrs & TERM_ATTR_CURLY_UNDERLINE) return TERM_UNDERLINE_CURLY;
- if (attrs & TERM_ATTR_DOTTED_UNDERLINE) return TERM_UNDERLINE_DOTTED;
- if (attrs & TERM_ATTR_DASHED_UNDERLINE) return TERM_UNDERLINE_DASHED;
- return attrs & TERM_ATTR_UNDERLINE ? TERM_UNDERLINE_SINGLE : TERM_UNDERLINE_NONE;
-}
-
-/* text refers to a grapheme cluster in the snapshot; see term_snapshot_cluster(). */
-#define TERM_TEXT_CLUSTER 0x80000000u
-
-/* One cell as a snapshot shows it. */
-struct term_cell {
- uint32_t text; /* a code point, TERM_TEXT_CLUSTER | n, or 0 for an empty cell */
- term_color fg, bg;
- uint16_t attrs; /* enum term_attr flags; at most one underline flag */
- uint8_t width; /* 1; 2 for a wide glyph; 0 for the right half of a wide glyph */
- uint8_t reserved;
-};
-
-#ifdef __cplusplus
-static_assert(sizeof(struct term_cell) == 16, "four cells fill one 64-byte line");
-#else
-_Static_assert(sizeof(struct term_cell) == 16, "four cells fill one 64-byte line");
-#endif
-
-/*
- * Snapshot: a copy of the viewport for a renderer. It holds no pointer into
- * the terminal, so it stays valid while the terminal changes. One terminal
- * may have several snapshots, for example a window and a tab preview.
- */
-TERM_API struct term_snapshot *term_snapshot_new(void);
-TERM_API void term_snapshot_free(struct term_snapshot *s);
-
-/* Copy the viewport of t into s. Keep rows with unchanged content keys.
- * Update the history view index and refine counts for visible wide lines.
- * Return false when memory runs out. The snapshot then keeps its previous content. */
-TERM_API bool term_snapshot_update(struct term_snapshot *s, struct term *t);
-
-/* Palette entries of struct term_view.palette after the 256 indexed colors. */
-enum {
- TERM_PALETTE_FG = 256,
- TERM_PALETTE_BG = 257,
- TERM_PALETTE_CURSOR = 258,
- TERM_PALETTE_SIZE = 259,
-};
-
-struct term_view {
- struct term_vector2i size;
- struct term_cursor cursor; /* viewport coordinates; not visible when scrolled away */
- int scroll_offset;
- /* Rows the content moved up since the previous update, when that movement
- * explains the change; otherwise 0. */
- int scrolled;
- bool reverse_video;
- /* Changes when any part of the view changes. */
- uint64_t version;
- /* Changes when a palette entry changes. */
- uint64_t palette_version;
- const uint32_t *palette; /* TERM_PALETTE_SIZE ARGB entries */
-};
-
-/* The view of s, NULL for a NULL s. The view and view->palette keep their
- * address until term_snapshot_free(); their contents change on each update. */
-TERM_API const struct term_view *term_snapshot_view(const struct term_snapshot *s);
-/* The cells of viewport row y: view->size.x entries. NULL when y is outside
- * the viewport or s is NULL. An update can move the cells, so the pointer is
- * valid only until the next term_snapshot_update() or term_snapshot_free() of s. */
-TERM_API const struct term_cell *term_snapshot_row(const struct term_snapshot *s, int y);
-/* An identity for the content of row y. Two rows with the same key hold the
- * same cells, also when the content moved to another row. 0 when y is outside
- * the viewport or s is NULL. */
-TERM_API uint64_t term_snapshot_row_key(const struct term_snapshot *s, int y);
-
-/* Number of rows in history above the screen. 0 if alternate screen or no history. */
-TERM_API int term_history_rows(const struct term *t);
-/* Owned, NUL-terminated UTF-8 of up to max_rows history rows before the
- * current viewport. Join soft-wrapped rows and end closed lines with a
- * newline. Does not change the selection. No history or max_rows <= 0 gives
- * an empty string; NULL means allocation failed or t is NULL. Release the
- * result with term_text_free(). */
-TERM_API char *term_history_text(struct term *t, int max_rows);
-/* The selected columns of viewport row y, end exclusive. An empty span when y
- * is outside the viewport or s is NULL. */
-TERM_API struct term_span term_snapshot_row_selection(const struct term_snapshot *s, int y);
-
-/* The code points of a cluster cell. Returns the number of code points and
- * writes at most cap of them. Writes nothing when cps is NULL or cap is 0.
- * Returns 0 when s is NULL. */
-TERM_API int term_snapshot_cluster(const struct term_snapshot *s, uint32_t text, uint32_t *cps, int cap);
-
-/* The ARGB value of a color in a view. */
-static inline uint32_t term_view_color(const struct term_view *v, term_color c)
-{
- if (!term_color_is_slot(c))
- return c;
- return v->palette[c & TERM_COLOR_SLOT_INDEX];
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/term/term_input.h b/include/term/term_input.h
deleted file mode 100644
index 19d9355..0000000
--- a/include/term/term_input.h
+++ /dev/null
@@ -1,202 +0,0 @@
-#ifndef TERM_INPUT_H
-#define TERM_INPUT_H
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-#include "term_types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum term_key {
- TERM_KEY_NONE = 0,
-
- TERM_KEY_RETURN,
- TERM_KEY_BACKSPACE,
- TERM_KEY_TAB,
- TERM_KEY_ESCAPE,
-
- TERM_KEY_UP,
- TERM_KEY_DOWN,
- TERM_KEY_RIGHT,
- TERM_KEY_LEFT,
- TERM_KEY_HOME,
- TERM_KEY_END,
- TERM_KEY_PAGE_UP,
- TERM_KEY_PAGE_DOWN,
- TERM_KEY_INSERT,
- TERM_KEY_DELETE,
-
- TERM_KEY_F1, TERM_KEY_F2, TERM_KEY_F3, TERM_KEY_F4, TERM_KEY_F5,
- TERM_KEY_F6, TERM_KEY_F7, TERM_KEY_F8, TERM_KEY_F9, TERM_KEY_F10,
- TERM_KEY_F11, TERM_KEY_F12, TERM_KEY_F13, TERM_KEY_F14, TERM_KEY_F15,
- TERM_KEY_F16, TERM_KEY_F17, TERM_KEY_F18, TERM_KEY_F19, TERM_KEY_F20,
- TERM_KEY_F21, TERM_KEY_F22, TERM_KEY_F23, TERM_KEY_F24, TERM_KEY_F25,
- TERM_KEY_F26, TERM_KEY_F27, TERM_KEY_F28, TERM_KEY_F29, TERM_KEY_F30,
- TERM_KEY_F31, TERM_KEY_F32, TERM_KEY_F33, TERM_KEY_F34, TERM_KEY_F35,
-
- TERM_KEY_KP_0, TERM_KEY_KP_1, TERM_KEY_KP_2, TERM_KEY_KP_3, TERM_KEY_KP_4,
- TERM_KEY_KP_5, TERM_KEY_KP_6, TERM_KEY_KP_7, TERM_KEY_KP_8, TERM_KEY_KP_9,
- TERM_KEY_KP_DECIMAL,
- TERM_KEY_KP_ENTER,
- TERM_KEY_KP_ADD,
- TERM_KEY_KP_SUBTRACT,
- TERM_KEY_KP_MULTIPLY,
- TERM_KEY_KP_DIVIDE,
- TERM_KEY_KP_EQUAL,
- TERM_KEY_KP_SEPARATOR,
- TERM_KEY_KP_LEFT,
- TERM_KEY_KP_RIGHT,
- TERM_KEY_KP_UP,
- TERM_KEY_KP_DOWN,
- TERM_KEY_KP_PAGE_UP,
- TERM_KEY_KP_PAGE_DOWN,
- TERM_KEY_KP_HOME,
- TERM_KEY_KP_END,
- TERM_KEY_KP_INSERT,
- TERM_KEY_KP_DELETE,
- TERM_KEY_KP_BEGIN,
-
- TERM_KEY_CAPS_LOCK,
- TERM_KEY_SCROLL_LOCK,
- TERM_KEY_NUM_LOCK,
- TERM_KEY_PRINT_SCREEN,
- TERM_KEY_PAUSE,
- TERM_KEY_MENU,
-
- TERM_KEY_MEDIA_PLAY,
- TERM_KEY_MEDIA_PAUSE,
- TERM_KEY_MEDIA_STOP,
- TERM_KEY_MEDIA_FORWARD,
- TERM_KEY_MEDIA_REWIND,
- TERM_KEY_MEDIA_NEXT,
- TERM_KEY_MEDIA_PREV,
- TERM_KEY_MEDIA_RECORD,
- TERM_KEY_VOLUME_DOWN,
- TERM_KEY_VOLUME_UP,
- TERM_KEY_MUTE,
-
- TERM_KEY_LSHIFT,
- TERM_KEY_LCTRL,
- TERM_KEY_LALT,
- TERM_KEY_LSUPER,
- TERM_KEY_LHYPER,
- TERM_KEY_LMETA,
- TERM_KEY_RSHIFT,
- TERM_KEY_RCTRL,
- TERM_KEY_RALT,
- TERM_KEY_RSUPER,
- TERM_KEY_RHYPER,
- TERM_KEY_RMETA,
- TERM_KEY_ISO_LEVEL3_SHIFT,
- TERM_KEY_ISO_LEVEL5_SHIFT,
-
- TERM_KEY_COUNT
-};
-
-enum term_mod {
- TERM_MOD_SHIFT = 1,
- TERM_MOD_ALT = 2,
- TERM_MOD_CTRL = 4,
- TERM_MOD_SUPER = 8,
- TERM_MOD_HYPER = 16,
- TERM_MOD_META = 32,
- TERM_MOD_CAPS = 64,
- TERM_MOD_NUM = 128,
-};
-
-enum term_key_action {
- TERM_KEY_PRESS = 1,
- TERM_KEY_REPEAT = 2,
- TERM_KEY_RELEASE = 3,
-};
-
-enum term_mouse_button {
- TERM_MOUSE_BUTTON_PRIMARY = 0,
- TERM_MOUSE_BUTTON_MIDDLE,
- TERM_MOUSE_BUTTON_SECONDARY,
- TERM_MOUSE_BUTTON_NONE,
- /* Extra buttons 8 through 11 in xterm mouse reporting (encoded as 128..131). */
- TERM_MOUSE_BUTTON_EXTRA_1,
- TERM_MOUSE_BUTTON_EXTRA_2,
- TERM_MOUSE_BUTTON_EXTRA_3,
- TERM_MOUSE_BUTTON_EXTRA_4,
- TERM_MOUSE_WHEEL_UP = 16,
- TERM_MOUSE_WHEEL_DOWN,
- TERM_MOUSE_WHEEL_LEFT,
- TERM_MOUSE_WHEEL_RIGHT,
-};
-
-enum term_mouse_event_kind {
- TERM_MOUSE_PRESS = 0,
- TERM_MOUSE_RELEASE,
- TERM_MOUSE_MOTION,
- TERM_MOUSE_SCROLL,
- TERM_MOUSE_LEAVE,
-};
-
-struct term_key_event {
- enum term_key_action action;
- uint16_t key; /* enum term_key; TERM_KEY_NONE for a text key */
- uint16_t keypad; /* the TERM_KEY_KP_* key when the key is on the keypad */
- unsigned mods; /* enum term_mod */
- uint32_t codepoint; /* the code point of the key without modifiers */
- uint32_t shifted; /* the code point of the key with Shift */
- uint32_t base; /* the code point of the key in the US layout */
- uint32_t text; /* the code point the key types, or 0 */
- bool text_deferred; /* an input method sends the text later */
-};
-
-struct term_mouse_event {
- struct term_vector2i pos; /* Grid cell coordinates (col, row) */
- struct term_vector2i pixel; /* Absolute pixel position in terminal grid */
- /*
- * Button identifier:
- * - Press and release: the button that changed state (TERM_MOUSE_BUTTON_*).
- * - Motion: the held button for drag events, or TERM_MOUSE_BUTTON_NONE for hover.
- * - Scroll: the wheel direction (TERM_MOUSE_WHEEL_*).
- */
- int button;
- unsigned mods;
- int scroll_lines;
- float scroll_delta;
- enum term_mouse_event_kind kind;
-};
-
-/* The keys that are down. An all-zero value has no keys down. */
-struct term_keyboard_state {
- uint64_t down[(TERM_KEY_COUNT + 63) / 64];
-};
-
-/* Record a press, repeat, or release in s. */
-TERM_API void term_keyboard_update(struct term_keyboard_state *s, const struct term_key_event *ev);
-TERM_API bool term_keyboard_key_down(const struct term_keyboard_state *s, enum term_key key);
-
-/* Kitty keyboard protocol flags, as in term_modes.keyboard. */
-enum term_keyboard_flag {
- TERM_KEYBOARD_DISAMBIGUATE = 1,
- TERM_KEYBOARD_EVENT_TYPES = 2,
- TERM_KEYBOARD_ALTERNATE_KEYS = 4,
- TERM_KEYBOARD_ALL_KEYS = 8,
- TERM_KEYBOARD_ASSOCIATED_TEXT = 16,
-};
-
-enum term_input_status {
- TERM_INPUT_UNHANDLED = 0, /* the terminal does not use the event */
- TERM_INPUT_CONSUMED, /* the terminal uses the event but sends nothing */
- TERM_INPUT_BYTES, /* send the len bytes in buf to the program */
- TERM_INPUT_BUFFER_FULL, /* buf is too small; len is 0 */
-};
-
-struct term_input_result {
- size_t len;
- enum term_input_status status;
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* TERM_INPUT_H */
diff --git a/include/term/unicode/grapheme.h b/include/term/unicode/grapheme.h
deleted file mode 100644
index 0946bb6..0000000
--- a/include/term/unicode/grapheme.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef TERM_UNICODE_GRAPHEME_H
-#define TERM_UNICODE_GRAPHEME_H
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#define TERM_GRAPHEME_MAX_LEN 20
-#define TERM_GRAPHEME_HANDLE_BASE 0x7F000000u
-
-static inline bool term_grapheme_is_handle(uint32_t c)
-{
- return c >= TERM_GRAPHEME_HANDLE_BASE;
-}
-
-static inline bool term_grapheme_regional_indicator(uint32_t cp)
-{
- return cp >= 0x1F1E6 && cp <= 0x1F1FF;
-}
-
-static inline bool term_grapheme_emoji_modifier(uint32_t cp)
-{
- return cp >= 0x1F3FB && cp <= 0x1F3FF;
-}
-
-#endif
diff --git a/include/term/unicode/unicode.h b/include/term/unicode/unicode.h
deleted file mode 100644
index 932cbf6..0000000
--- a/include/term/unicode/unicode.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef TERM_UNICODE_UNICODE_H
-#define TERM_UNICODE_UNICODE_H
-
-#include "width.h"
-
-#endif
diff --git a/include/term/unicode/width.h b/include/term/unicode/width.h
deleted file mode 100644
index a85ec77..0000000
--- a/include/term/unicode/width.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#ifndef TERM_UNICODE_WIDTH_H
-#define TERM_UNICODE_WIDTH_H
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-struct term_unicode_range { uint32_t lo, hi; };
-
-#include "unicode_data.inc"
-
-static inline bool term_in_ranges(const struct term_unicode_range *ranges, size_t count, uint32_t cp)
-{
- if (count == 0 || cp < ranges[0].lo || cp > ranges[count - 1].hi)
- return false;
- const struct term_unicode_range *base = ranges;
- size_t n = count;
- while (n > 1) {
- size_t half = n / 2;
- base = (base[half].lo <= cp) ? base + half : base;
- n -= half;
- }
- return cp <= base->hi;
-}
-
-#define TERM_IN_TABLE(table, cp) term_in_ranges(table, sizeof(table) / sizeof(table[0]), cp)
-
-static inline int term_unicode_width(uint32_t cp)
-{
- if (cp > 0x10FFFF || TERM_IN_TABLE(term_nonprintable, cp))
- return -1;
- if (TERM_IN_TABLE(term_zero_width, cp))
- return 0;
- return TERM_IN_TABLE(term_unicode_wide, cp) ? 2 : 1;
-}
-
-static inline bool term_unicode_extended_pictographic(uint32_t cp)
-{
- return TERM_IN_TABLE(term_extended_pictographic, cp);
-}
-
-static inline bool term_unicode_emoji_presentation(uint32_t cp)
-{
- return TERM_IN_TABLE(term_emoji_presentation, cp);
-}
-
-static inline bool term_unicode_spacing_mark(uint32_t cp)
-{
- if (cp < 0x903 || ((cp - 0xABEDu) < (0x11000u - 0xABEDu)) || cp > 0x1D281)
- return false;
- return TERM_IN_TABLE(term_spacing_mark, cp);
-}
-
-#undef TERM_IN_TABLE
-
-#endif
diff --git a/include/wsap_vtcore/unicode/grapheme.h b/include/wsap_vtcore/unicode/grapheme.h
new file mode 100644
index 0000000..6146239
--- /dev/null
+++ b/include/wsap_vtcore/unicode/grapheme.h
@@ -0,0 +1,26 @@
+#ifndef WSAP_VTCORE_UNICODE_GRAPHEME_H
+#define WSAP_VTCORE_UNICODE_GRAPHEME_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#define WSAP_VTCORE_GRAPHEME_MAX_LEN 20
+#define WSAP_VTCORE_GRAPHEME_HANDLE_BASE 0x7F000000u
+
+static inline bool wsap_vtcore_grapheme_is_handle(uint32_t c)
+{
+ return c >= WSAP_VTCORE_GRAPHEME_HANDLE_BASE;
+}
+
+static inline bool wsap_vtcore_grapheme_regional_indicator(uint32_t cp)
+{
+ return cp >= 0x1F1E6 && cp <= 0x1F1FF;
+}
+
+static inline bool wsap_vtcore_grapheme_emoji_modifier(uint32_t cp)
+{
+ return cp >= 0x1F3FB && cp <= 0x1F3FF;
+}
+
+#endif
diff --git a/include/wsap_vtcore/unicode/unicode.h b/include/wsap_vtcore/unicode/unicode.h
new file mode 100644
index 0000000..02181b4
--- /dev/null
+++ b/include/wsap_vtcore/unicode/unicode.h
@@ -0,0 +1,6 @@
+#ifndef WSAP_VTCORE_UNICODE_UNICODE_H
+#define WSAP_VTCORE_UNICODE_UNICODE_H
+
+#include "width.h"
+
+#endif
diff --git a/include/term/unicode/unicode_data.inc b/include/wsap_vtcore/unicode/unicode_data.inc
index 4ab1461..35831e5 100644
--- a/include/term/unicode/unicode_data.inc
+++ b/include/wsap_vtcore/unicode/unicode_data.inc
@@ -1,8 +1,8 @@
/* Generated from Unicode 18.0.0 data by tools/generate_unicode.py. */
-#define TERM_UNICODE_DATA_VERSION "18.0.0"
+#define WSAP_VTCORE_UNICODE_DATA_VERSION "18.0.0"
-static const struct term_unicode_range term_zero_width[] = {
+static const struct wsap_vtcore_unicode_range wsap_vtcore_zero_width[] = {
{0xAD,0xAD},{0x300,0x36F},{0x483,0x489},{0x591,0x5BD},
{0x5BF,0x5BF},{0x5C1,0x5C2},{0x5C4,0x5C5},{0x5C7,0x5C9},
{0x600,0x605},{0x610,0x61A},{0x61C,0x61C},{0x64B,0x65F},
@@ -101,11 +101,11 @@ static const struct term_unicode_range term_zero_width[] = {
{0xE0020,0xE007F},{0xE0100,0xE01EF},
};
-static const struct term_unicode_range term_nonprintable[] = {
+static const struct wsap_vtcore_unicode_range wsap_vtcore_nonprintable[] = {
{0x0,0x1F},{0x7F,0x9F},{0xD800,0xDFFF},
};
-static const struct term_unicode_range term_unicode_wide[] = {
+static const struct wsap_vtcore_unicode_range wsap_vtcore_unicode_wide[] = {
{0x1100,0x115F},{0x231A,0x231B},{0x2329,0x232A},{0x23E9,0x23EC},
{0x23F0,0x23F0},{0x23F3,0x23F3},{0x25FD,0x25FE},{0x2614,0x2615},
{0x2630,0x2637},{0x2648,0x2653},{0x267F,0x267F},{0x268A,0x268F},
@@ -140,7 +140,7 @@ static const struct term_unicode_range term_unicode_wide[] = {
{0x20000,0x2FFFD},{0x30000,0x3FFFD},
};
-static const struct term_unicode_range term_spacing_mark[] = {
+static const struct wsap_vtcore_unicode_range wsap_vtcore_spacing_mark[] = {
{0x903,0x903},{0x93B,0x93B},{0x93E,0x940},{0x949,0x94C},
{0x94E,0x94F},{0x982,0x983},{0x9BE,0x9C0},{0x9C7,0x9C8},
{0x9CB,0x9CC},{0x9D7,0x9D7},{0xA03,0xA03},{0xA3E,0xA40},
@@ -192,7 +192,7 @@ static const struct term_unicode_range term_spacing_mark[] = {
{0x1D16D,0x1D172},{0x1D250,0x1D252},{0x1D25F,0x1D25F},{0x1D280,0x1D281},
};
-static const struct term_unicode_range term_extended_pictographic[] = {
+static const struct wsap_vtcore_unicode_range wsap_vtcore_extended_pictographic[] = {
{0xA9,0xA9},{0xAE,0xAE},{0x203C,0x203C},{0x2049,0x2049},
{0x2122,0x2122},{0x2139,0x2139},{0x2194,0x2199},{0x21A9,0x21AA},
{0x231A,0x231B},{0x2328,0x2328},{0x23CF,0x23CF},{0x23E9,0x23F3},
@@ -234,7 +234,7 @@ static const struct term_unicode_range term_extended_pictographic[] = {
{0x1F947,0x1F9FF},{0x1FA58,0x1FA5F},{0x1FA6E,0x1FAFF},{0x1FC00,0x1FFFD},
};
-static const struct term_unicode_range term_emoji_presentation[] = {
+static const struct wsap_vtcore_unicode_range wsap_vtcore_emoji_presentation[] = {
{0x231A,0x231B},{0x23E9,0x23EC},{0x23F0,0x23F0},{0x23F3,0x23F3},
{0x25FD,0x25FE},{0x2614,0x2615},{0x2648,0x2653},{0x267F,0x267F},
{0x2693,0x2693},{0x26A1,0x26A1},{0x26AA,0x26AB},{0x26BD,0x26BE},
diff --git a/include/term/unicode/utf8.h b/include/wsap_vtcore/unicode/utf8.h
index ad44465..7660e41 100644
--- a/include/term/unicode/utf8.h
+++ b/include/wsap_vtcore/unicode/utf8.h
@@ -1,19 +1,19 @@
-#ifndef TERM_UNICODE_UTF8_H
-#define TERM_UNICODE_UTF8_H
+#ifndef WSAP_VTCORE_UNICODE_UTF8_H
+#define WSAP_VTCORE_UNICODE_UTF8_H
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
-#define TERM_UTF8_ACCEPT 0
-#define TERM_UTF8_REJECT 1
+#define WSAP_VTCORE_UTF8_ACCEPT 0
+#define WSAP_VTCORE_UTF8_REJECT 1
-#define TERM_UTF8_3BYTE_MIN 0x800u
-#define TERM_UTF8_SURROGATE_LO 0xd800u
-#define TERM_UTF8_SURROGATE_HI 0xdfffu
+#define WSAP_VTCORE_UTF8_3BYTE_MIN 0x800u
+#define WSAP_VTCORE_UTF8_SURROGATE_LO 0xd800u
+#define WSAP_VTCORE_UTF8_SURROGATE_HI 0xdfffu
-static const uint8_t term_utf8d[] = {
+static const uint8_t wsap_vtcore_utf8d[] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -30,19 +30,19 @@ static const uint8_t term_utf8d[] = {
1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
};
-static inline uint32_t term_utf8_decode(uint32_t *state, uint32_t *codep, uint32_t byte) {
+static inline uint32_t wsap_vtcore_utf8_decode(uint32_t *state, uint32_t *codep, uint32_t byte) {
byte &= 0xff;
- uint32_t type = term_utf8d[byte];
+ uint32_t type = wsap_vtcore_utf8d[byte];
- *codep = (*state != TERM_UTF8_ACCEPT) ?
+ *codep = (*state != WSAP_VTCORE_UTF8_ACCEPT) ?
(byte & 0x3fu) | (*codep << 6) :
(0xff >> type) & (byte);
- *state = term_utf8d[256 + *state*16 + type];
+ *state = wsap_vtcore_utf8d[256 + *state*16 + type];
return *state;
}
-static const uint8_t term_utf8_acc_state[256] = {
+static const uint8_t wsap_vtcore_utf8_acc_state[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -60,7 +60,7 @@ static const uint8_t term_utf8_acc_state[256] = {
4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3,
6, 7, 7, 7, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
-static const uint8_t term_utf8_acc_codep[256] = {
+static const uint8_t wsap_vtcore_utf8_acc_codep[256] = {
0, 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,
@@ -86,7 +86,7 @@ static const uint8_t term_utf8_acc_codep[256] = {
* ends an unfinished sequence the same way. An unfinished sequence at the
* end of buf gives *cp = 0 and keeps the state.
*/
-static inline int term_utf8_decode_ground(uint32_t *state, uint32_t *codep,
+static inline int wsap_vtcore_utf8_decode_ground(uint32_t *state, uint32_t *codep,
const char *buf, size_t len, uint32_t *cp) {
uint32_t st = *state;
uint32_t cpv = *codep;
@@ -97,25 +97,25 @@ static inline int term_utf8_decode_ground(uint32_t *state, uint32_t *codep,
do {
unsigned char c = (unsigned char)buf[n];
if (c < 0x20) {
- if (st != TERM_UTF8_ACCEPT) *cp = 0xFFFD;
- st = TERM_UTF8_ACCEPT;
+ if (st != WSAP_VTCORE_UTF8_ACCEPT) *cp = 0xFFFD;
+ st = WSAP_VTCORE_UTF8_ACCEPT;
break;
}
uint32_t before = st;
n++;
- if (st == TERM_UTF8_ACCEPT) {
- cpv = term_utf8_acc_codep[c];
- st = term_utf8_acc_state[c];
+ if (st == WSAP_VTCORE_UTF8_ACCEPT) {
+ cpv = wsap_vtcore_utf8_acc_codep[c];
+ st = wsap_vtcore_utf8_acc_state[c];
} else {
- uint32_t type = term_utf8d[c];
+ uint32_t type = wsap_vtcore_utf8d[c];
cpv = (c & 0x3fu) | (cpv << 6);
- st = term_utf8d[256 + st*16 + type];
+ st = wsap_vtcore_utf8d[256 + st*16 + type];
}
- if (st == TERM_UTF8_ACCEPT) { *cp = cpv; break; }
- if (st == TERM_UTF8_REJECT) {
- st = TERM_UTF8_ACCEPT;
+ if (st == WSAP_VTCORE_UTF8_ACCEPT) { *cp = cpv; break; }
+ if (st == WSAP_VTCORE_UTF8_REJECT) {
+ st = WSAP_VTCORE_UTF8_ACCEPT;
*cp = 0xFFFD;
- if (before != TERM_UTF8_ACCEPT) n--;
+ if (before != WSAP_VTCORE_UTF8_ACCEPT) n--;
break;
}
} while ((size_t)n < len);
@@ -125,7 +125,7 @@ static inline int term_utf8_decode_ground(uint32_t *state, uint32_t *codep,
}
static inline int
-term_utf8_decode_one(const char *buf, size_t len, uint32_t *codep)
+wsap_vtcore_utf8_decode_one(const char *buf, size_t len, uint32_t *codep)
{
const unsigned char *s = (const unsigned char *)buf;
unsigned c0, c1, c2, c3;
@@ -159,8 +159,8 @@ term_utf8_decode_one(const char *buf, size_t len, uint32_t *codep)
if ((c1 & 0xc0) != 0x80 || (c2 & 0xc0) != 0x80)
return 0;
cp = ((c0 & 0x0f) << 12) | ((c1 & 0x3f) << 6) | (c2 & 0x3f);
- if (cp < TERM_UTF8_3BYTE_MIN ||
- (cp >= TERM_UTF8_SURROGATE_LO && cp <= TERM_UTF8_SURROGATE_HI))
+ if (cp < WSAP_VTCORE_UTF8_3BYTE_MIN ||
+ (cp >= WSAP_VTCORE_UTF8_SURROGATE_LO && cp <= WSAP_VTCORE_UTF8_SURROGATE_HI))
return 0;
*codep = cp;
return 3;
@@ -183,14 +183,14 @@ term_utf8_decode_one(const char *buf, size_t len, uint32_t *codep)
}
static inline void
-term_utf8_sanitize(char *dst, size_t cap, const char *src)
+wsap_vtcore_utf8_sanitize(char *dst, size_t cap, const char *src)
{
if (!cap)
return;
size_t i = 0, len = strlen(src), off = 0;
while (off < len && i + 1 < cap) {
uint32_t cp;
- int n = term_utf8_decode_one(src + off, len - off, &cp);
+ int n = wsap_vtcore_utf8_decode_one(src + off, len - off, &cp);
if (n <= 0 || i + (size_t)n >= cap) {
off++;
continue;
@@ -204,17 +204,17 @@ term_utf8_sanitize(char *dst, size_t cap, const char *src)
/* A sanitized copy of src. Sanitizing only drops bytes, so the copy is
* never longer than src. */
-static inline char *term_utf8_sanitize_dup(const char *src)
+static inline char *wsap_vtcore_utf8_sanitize_dup(const char *src)
{
size_t cap = strlen(src) + 1;
char *dst = (char *)malloc(cap);
if (dst)
- term_utf8_sanitize(dst, cap, src);
+ wsap_vtcore_utf8_sanitize(dst, cap, src);
return dst;
}
-#define TERM_UTF8_MAX_BYTES 4
-static inline int term_utf8_encode(uint32_t cp, char *out)
+#define WSAP_VTCORE_UTF8_MAX_BYTES 4
+static inline int wsap_vtcore_utf8_encode(uint32_t cp, char *out)
{
if (cp > 0x10ffff || (cp >= 0xd800 && cp <= 0xdfff))
cp = 0xfffd;
diff --git a/include/wsap_vtcore/unicode/width.h b/include/wsap_vtcore/unicode/width.h
new file mode 100644
index 0000000..21d8252
--- /dev/null
+++ b/include/wsap_vtcore/unicode/width.h
@@ -0,0 +1,56 @@
+#ifndef WSAP_VTCORE_UNICODE_WIDTH_H
+#define WSAP_VTCORE_UNICODE_WIDTH_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+struct wsap_vtcore_unicode_range { uint32_t lo, hi; };
+
+#include "unicode_data.inc"
+
+static inline bool wsap_vtcore_in_ranges(const struct wsap_vtcore_unicode_range *ranges, size_t count, uint32_t cp)
+{
+ if (count == 0 || cp < ranges[0].lo || cp > ranges[count - 1].hi)
+ return false;
+ const struct wsap_vtcore_unicode_range *base = ranges;
+ size_t n = count;
+ while (n > 1) {
+ size_t half = n / 2;
+ base = (base[half].lo <= cp) ? base + half : base;
+ n -= half;
+ }
+ return cp <= base->hi;
+}
+
+#define WSAP_VTCORE_IN_TABLE(table, cp) wsap_vtcore_in_ranges(table, sizeof(table) / sizeof(table[0]), cp)
+
+static inline int wsap_vtcore_unicode_width(uint32_t cp)
+{
+ if (cp > 0x10FFFF || WSAP_VTCORE_IN_TABLE(wsap_vtcore_nonprintable, cp))
+ return -1;
+ if (WSAP_VTCORE_IN_TABLE(wsap_vtcore_zero_width, cp))
+ return 0;
+ return WSAP_VTCORE_IN_TABLE(wsap_vtcore_unicode_wide, cp) ? 2 : 1;
+}
+
+static inline bool wsap_vtcore_unicode_extended_pictographic(uint32_t cp)
+{
+ return WSAP_VTCORE_IN_TABLE(wsap_vtcore_extended_pictographic, cp);
+}
+
+static inline bool wsap_vtcore_unicode_emoji_presentation(uint32_t cp)
+{
+ return WSAP_VTCORE_IN_TABLE(wsap_vtcore_emoji_presentation, cp);
+}
+
+static inline bool wsap_vtcore_unicode_spacing_mark(uint32_t cp)
+{
+ if (cp < 0x903 || ((cp - 0xABEDu) < (0x11000u - 0xABEDu)) || cp > 0x1D281)
+ return false;
+ return WSAP_VTCORE_IN_TABLE(wsap_vtcore_spacing_mark, cp);
+}
+
+#undef WSAP_VTCORE_IN_TABLE
+
+#endif
diff --git a/include/wsap_vtcore/wsap_vtcore.h b/include/wsap_vtcore/wsap_vtcore.h
new file mode 100644
index 0000000..d72a55b
--- /dev/null
+++ b/include/wsap_vtcore/wsap_vtcore.h
@@ -0,0 +1,492 @@
+#ifndef WSAP_VTCORE_H
+#define WSAP_VTCORE_H
+
+/*
+ * Terminal emulator core.
+ *
+ * A struct wsap_vtcore parses the bytes that a program writes and keeps
+ * the screen, the history, and the modes. The application feeds bytes with
+ * wsap_vtcore_feed() and reads state with the getters below. A renderer
+ * never reads the terminal directly: it copies the viewport into a
+ * struct wsap_vtcore_snapshot and paints from that copy.
+ *
+ * All functions take the terminal as the first argument. Functions that take
+ * a const struct wsap_vtcore do not change what it shows. Selection, history, link,
+ * directory, and pointer-shape queries return owned strings; release them
+ * with wsap_vtcore_text_free().
+ *
+ * Threads. Any thread can call any function. Each call that reads or changes
+ * a terminal enters its writer section, so calls on one terminal run one at a
+ * time. A thread that waits for the section sleeps. On POSIX the section is a
+ * mutex with priority inheritance where the platform has it. A snapshot
+ * belongs to one thread at a time. wsap_vtcore_free() is the last call on a terminal.
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "wsap_vtcore_input.h"
+#include "wsap_vtcore_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct wsap_vtcore;
+struct wsap_vtcore_snapshot;
+
+/* A row holds at most this many cells. */
+#define WSAP_VTCORE_MAX_COLS 65535
+/* The history limit when wsap_vtcore_options.scrollback is 0. */
+#define WSAP_VTCORE_SCROLLBACK_DEFAULT 10000
+/* The largest wsap_vtcore_options.scrollback. */
+#define WSAP_VTCORE_SCROLLBACK_MAX 1000000
+
+/*
+ * The version of this header. A host compares WSAP_VTCORE_VERSION_CODE with
+ * wsap_vtcore_version() to check that the library matches the header.
+ */
+#define WSAP_VTCORE_VERSION(major, minor, patch) (((major) << 16) | ((minor) << 8) | (patch))
+#define WSAP_VTCORE_VERSION_MAJOR 0
+#define WSAP_VTCORE_VERSION_MINOR 1
+#define WSAP_VTCORE_VERSION_PATCH 0
+#define WSAP_VTCORE_VERSION_CODE WSAP_VTCORE_VERSION(WSAP_VTCORE_VERSION_MAJOR, WSAP_VTCORE_VERSION_MINOR, WSAP_VTCORE_VERSION_PATCH)
+
+/*
+ * Colors. A wsap_vtcore_color is either a direct color (alpha 0xFF, then RGB) or a
+ * palette slot: an index 0-255, the default foreground, or the default
+ * background. A slot resolves when a snapshot is painted, so a theme change
+ * recolors text that is already on screen.
+ */
+typedef uint32_t wsap_vtcore_color;
+
+#define WSAP_VTCORE_COLOR_SLOT 0x01000000u
+/* The palette index of a slot; see struct wsap_vtcore_view.palette. */
+#define WSAP_VTCORE_COLOR_SLOT_INDEX 0x1FFu
+#define WSAP_VTCORE_COLOR_FG (WSAP_VTCORE_COLOR_SLOT | 0x100u)
+#define WSAP_VTCORE_COLOR_BG (WSAP_VTCORE_COLOR_SLOT | 0x101u)
+
+static inline wsap_vtcore_color wsap_vtcore_color_index(int n)
+{
+ return WSAP_VTCORE_COLOR_SLOT | ((uint32_t)n & 0xFFu);
+}
+
+static inline wsap_vtcore_color wsap_vtcore_color_rgb(uint8_t r, uint8_t g, uint8_t b)
+{
+ return 0xFF000000u | (uint32_t)r << 16 | (uint32_t)g << 8 | b;
+}
+
+static inline bool wsap_vtcore_color_is_slot(wsap_vtcore_color c)
+{
+ return (c >> 24) == (WSAP_VTCORE_COLOR_SLOT >> 24);
+}
+
+/* Parse an X11 or OSC color specification ("#rgb", "rgb:r/g/b", ...). */
+WSAP_VTCORE_API bool wsap_vtcore_color_parse(const char *spec, uint32_t *argb);
+
+/* The colors a terminal starts with. All values are ARGB. An all-zero theme
+ * selects the built-in theme. */
+struct wsap_vtcore_theme {
+ uint32_t fg, bg, cursor;
+ uint32_t ansi[16];
+};
+
+/* Fill theme with the built-in theme. */
+WSAP_VTCORE_API void wsap_vtcore_theme_default(struct wsap_vtcore_theme *theme);
+/* Fill theme with the high-contrast theme. */
+WSAP_VTCORE_API void wsap_vtcore_theme_high_contrast(struct wsap_vtcore_theme *theme);
+/* Sets one palette key: foreground, background, or color0 to color15.
+ * An empty value resets the key to the built-in theme. False, with no
+ * change, for an unknown key or a bad color. */
+WSAP_VTCORE_API bool wsap_vtcore_theme_set_key(struct wsap_vtcore_theme *p, const char *key, const char *val);
+
+enum wsap_vtcore_cursor_style {
+ WSAP_VTCORE_CURSOR_BLOCK,
+ WSAP_VTCORE_CURSOR_UNDERLINE,
+ WSAP_VTCORE_CURSOR_BAR,
+};
+
+/* Mouse reporting modes and encodings. The values are the DEC mode numbers. */
+enum wsap_vtcore_mouse {
+ WSAP_VTCORE_MOUSE_OFF = 0,
+ WSAP_VTCORE_MOUSE_X10 = 9,
+ WSAP_VTCORE_MOUSE_NORMAL = 1000,
+ WSAP_VTCORE_MOUSE_BUTTON = 1002,
+ WSAP_VTCORE_MOUSE_ANY = 1003,
+};
+
+enum wsap_vtcore_mouse_encoding {
+ WSAP_VTCORE_MOUSE_ENC_X10 = 0,
+ WSAP_VTCORE_MOUSE_ENC_UTF8 = 1005,
+ WSAP_VTCORE_MOUSE_ENC_SGR = 1006,
+ WSAP_VTCORE_MOUSE_ENC_URXVT = 1015,
+ WSAP_VTCORE_MOUSE_ENC_SGR_PIXELS = 1016,
+};
+
+/*
+ * Callbacks. They run inside wsap_vtcore_feed() and wsap_vtcore_focus(), on the thread
+ * that calls those functions. A callback must not call back into the
+ * terminal. String arguments are valid only during the call.
+ */
+struct wsap_vtcore_callbacks {
+ void *ud;
+ /* Bytes the terminal sends back to the program (replies to queries). */
+ void (*reply)(void *ud, const char *bytes, size_t len);
+ void (*title)(void *ud, const char *title);
+ /*
+ * OSC 52 clipboard callback.
+ * selection names the target clipboard buffer(s), commonly:
+ * "c" - clipboard (system clipboard)
+ * "p" - primary selection (X11 primary)
+ * "q" - secondary selection
+ * "s" - select selection
+ * "0".."7" - cut buffers 0 to 7
+ * A parameter may contain multiple targets (e.g. "cp").
+ * data contains decoded bytes of length len.
+ */
+ void (*clipboard)(void *ud, const char *selection, const char *data, size_t len);
+ void (*notify)(void *ud, const char *title, const char *body);
+ void (*bell)(void *ud);
+ /* Parser trace lines for debugging. NULL turns tracing off. The line has no newline. */
+ void (*trace)(void *ud, const char *line);
+};
+
+/*
+ * Options for wsap_vtcore_new(). An all-zero value is valid. A size component of 0
+ * selects 80 columns or 24 rows. A negative component, or columns above
+ * WSAP_VTCORE_MAX_COLS, makes wsap_vtcore_new() fail. A scrollback below 0 or above
+ * WSAP_VTCORE_SCROLLBACK_MAX fails too.
+ * cursor_style must be a value of enum wsap_vtcore_cursor_style.
+ */
+struct wsap_vtcore_options {
+ struct wsap_vtcore_vector2i size; /* columns and rows */
+ int scrollback; /* history lines; 0 selects WSAP_VTCORE_SCROLLBACK_DEFAULT */
+ struct wsap_vtcore_theme theme;
+ enum wsap_vtcore_cursor_style cursor_style;
+ bool cursor_steady; /* false: the cursor blinks */
+ /*
+ * The terminal's name. Programs read it with XTVERSION and XTGETTCAP.
+ * It is also the title of a notification that has none. NULL or ""
+ * selects "wsap_vtcore". Otherwise 1 to 63 printable ASCII bytes, or
+ * wsap_vtcore_new() returns NULL. wsap_vtcore_new() copies the name.
+ */
+ const char *name;
+ struct wsap_vtcore_callbacks callbacks;
+ /* Must be zero. wsap_vtcore_new() returns NULL if any word is nonzero, so a
+ * later version can give a word a meaning. */
+ uint32_t reserved[8];
+};
+
+/* The Unicode version of the width tables, such as "18.0.0". A host can
+ * pass it to programs as UNICODE_VERSION. */
+WSAP_VTCORE_API const char *wsap_vtcore_unicode_version(void);
+/* The WSAP_VTCORE_VERSION_CODE the library was built with. */
+WSAP_VTCORE_API unsigned wsap_vtcore_version(void);
+
+/* The length of the prefix of buf made of bytes in [0x20, hi). With hi
+ * 0x7f, it finds a run of printable ASCII in UTF-8 text, so a host can
+ * skip shaping for it. Any thread can call it. */
+WSAP_VTCORE_API size_t wsap_vtcore_scan_printable_span(const char *buf, size_t len, unsigned char hi);
+
+/* The instruction set level of the running code: "base", "avx2", "avx512",
+ * or "neon". On x86-64, the first wsap_vtcore_new() picks the highest level the CPU
+ * supports. Set WSAP_VTCORE_ISA to a lower level to force it, for tests
+ * and comparisons. */
+WSAP_VTCORE_API const char *wsap_vtcore_isa(void);
+
+/* NULL when memory runs out or an option is invalid. */
+WSAP_VTCORE_API struct wsap_vtcore *wsap_vtcore_new(const struct wsap_vtcore_options *opt);
+WSAP_VTCORE_API void wsap_vtcore_free(struct wsap_vtcore *t);
+
+/* Hold the writer section across several calls, so that no other thread
+ * changes the terminal between them. The section is a mutex, and a waiting
+ * thread sleeps. Keep it short. The thread that holds it can call every
+ * function, and it can enter the section again. Each wsap_vtcore_lock() needs one
+ * wsap_vtcore_unlock(). */
+WSAP_VTCORE_API void wsap_vtcore_lock(struct wsap_vtcore *t);
+WSAP_VTCORE_API void wsap_vtcore_unlock(struct wsap_vtcore *t);
+
+/* Change the size in cells. Returns false, and the terminal is unchanged,
+ * when a component is below 1, when cols is above WSAP_VTCORE_MAX_COLS, or when
+ * memory runs out. The screen reflows to the new width. */
+WSAP_VTCORE_API bool wsap_vtcore_resize(struct wsap_vtcore *t, struct wsap_vtcore_vector2i size);
+
+/* Replace the theme. A different theme also drops the colors that the
+ * program set with OSC; the same theme changes nothing. */
+WSAP_VTCORE_API void wsap_vtcore_set_theme(struct wsap_vtcore *t, const struct wsap_vtcore_theme *theme);
+
+/* The cursor style that DECSCUSR 0 and a reset restore. */
+WSAP_VTCORE_API void wsap_vtcore_set_cursor_default(struct wsap_vtcore *t, enum wsap_vtcore_cursor_style style, bool steady);
+
+/*
+ * Bytes from the program.
+ *
+ * WSAP_VTCORE_FEED_ONLCR: a line feed also returns the cursor to column 0, as a tty
+ * with OPOST and ONLCR does. Set it when the bytes did not pass through the
+ * tty output processing (for example the fast pipe).
+ */
+enum wsap_vtcore_feed_flags {
+ WSAP_VTCORE_FEED_ONLCR = 1u << 0,
+};
+
+/*
+ * Feed bytes from the program. Returns false, and changes nothing, when t is
+ * NULL, when bytes is NULL and len is not 0, or when flags has a bit that is
+ * not in enum wsap_vtcore_feed_flags. A len of 0 is a no-op that returns true.
+ */
+WSAP_VTCORE_API bool wsap_vtcore_feed(struct wsap_vtcore *t, const char *bytes, size_t len, unsigned flags);
+
+/* Report a focus change. The terminal replies only in focus-event mode. */
+WSAP_VTCORE_API void wsap_vtcore_focus(struct wsap_vtcore *t, bool focused);
+
+/* Modes that affect how the application encodes input. */
+struct wsap_vtcore_modes {
+ unsigned keyboard; /* kitty keyboard protocol flags */
+ enum wsap_vtcore_mouse mouse;
+ enum wsap_vtcore_mouse_encoding mouse_encoding;
+ struct wsap_vtcore_vector2i grid; /* columns and rows */
+ bool app_cursor; /* DECCKM */
+ bool app_keypad; /* DECKPAM */
+ bool backarrow_bs; /* DECBKM */
+ bool bracketed_paste;
+ bool focus_events;
+ bool alternate; /* the alternate screen is active */
+ bool reverse_video; /* DECSCNM */
+ bool synchronized; /* mode 2026 */
+};
+
+struct wsap_vtcore_cursor {
+ struct wsap_vtcore_vector2i pos;
+ enum wsap_vtcore_cursor_style style;
+ bool visible;
+ bool blink;
+};
+
+WSAP_VTCORE_API struct wsap_vtcore_vector2i wsap_vtcore_size(const struct wsap_vtcore *t);
+WSAP_VTCORE_API struct wsap_vtcore_modes wsap_vtcore_modes(const struct wsap_vtcore *t);
+
+/*
+ * Encode an input event as the bytes the program expects. Get modes from
+ * wsap_vtcore_modes(). Record ev in keyboard with wsap_vtcore_keyboard_update() first. Send
+ * the bytes to the program yourself.
+ */
+WSAP_VTCORE_API struct wsap_vtcore_input_result wsap_vtcore_input_encode_key(
+ const struct wsap_vtcore_keyboard_state *keyboard,
+ const struct wsap_vtcore_key_event *ev,
+ const struct wsap_vtcore_modes *modes,
+ char *buf, size_t capacity
+);
+
+WSAP_VTCORE_API struct wsap_vtcore_input_result wsap_vtcore_input_encode_mouse(
+ const struct wsap_vtcore_mouse_event *ev,
+ const struct wsap_vtcore_modes *modes,
+ char *buf, size_t capacity
+);
+
+/* Bytes wsap_vtcore_input_encode_paste() adds to the text at most. */
+#define WSAP_VTCORE_PASTE_EXTRA 12
+
+/*
+ * Encode pasted text. Drop control characters and bidi controls, so the
+ * program sees only what the user saw. Send a line break as CR. Add the
+ * bracketed-paste markers when the program asked for them. A buffer of
+ * len + WSAP_VTCORE_PASTE_EXTRA bytes is always large enough. Text that is empty
+ * after the filter gives WSAP_VTCORE_INPUT_CONSUMED.
+ */
+WSAP_VTCORE_API struct wsap_vtcore_input_result wsap_vtcore_input_encode_paste(
+ const struct wsap_vtcore_modes *modes,
+ const char *text, size_t len,
+ char *buf, size_t capacity
+);
+/* The cursor in screen coordinates (not the viewport). */
+WSAP_VTCORE_API struct wsap_vtcore_cursor wsap_vtcore_cursor(const struct wsap_vtcore *t);
+/* Owned, NUL-terminated text from OSC 7 and OSC 22. NULL when unavailable
+ * or allocation fails. The strings stay valid after the terminal changes
+ * or is freed. Release them with wsap_vtcore_text_free(). */
+WSAP_VTCORE_API char *wsap_vtcore_cwd(const struct wsap_vtcore *t);
+WSAP_VTCORE_API char *wsap_vtcore_pointer_shape(const struct wsap_vtcore *t);
+/* Release any owned text returned by the library. NULL is safe. */
+WSAP_VTCORE_API void wsap_vtcore_text_free(char *text);
+
+/*
+ * Viewport. The viewport shows as many rows as the screen. Offset 0 shows
+ * the live screen; a larger offset shows that many rows of history above it.
+ * The alternate screen has no history, so its offset is always 0.
+ */
+struct wsap_vtcore_scrollback {
+ int offset; /* rows between the viewport and the live screen */
+ int total; /* history rows at the current width */
+};
+
+WSAP_VTCORE_API struct wsap_vtcore_scrollback wsap_vtcore_scrollback(const struct wsap_vtcore *t);
+/* Scroll the viewport. A positive count moves back into history. */
+WSAP_VTCORE_API void wsap_vtcore_scroll(struct wsap_vtcore *t, int lines);
+WSAP_VTCORE_API void wsap_vtcore_scroll_to(struct wsap_vtcore *t, int offset);
+
+/*
+ * Selection, in viewport coordinates. A selection starts at one cell and
+ * extends to another; the unit widens both ends to words or whole lines.
+ * The terminal clears the selection when the text under it changes.
+ */
+enum wsap_vtcore_select_unit {
+ WSAP_VTCORE_SELECT_CELL,
+ WSAP_VTCORE_SELECT_WORD,
+ WSAP_VTCORE_SELECT_LINE,
+};
+
+/* Start a selection at cell. For WSAP_VTCORE_SELECT_CELL, right_half means the
+ * pointer is on the right half of the cell, so the selection starts after it.
+ * Returns false when memory runs out; the selection is then unchanged. */
+WSAP_VTCORE_API bool wsap_vtcore_select_start(struct wsap_vtcore *t, struct wsap_vtcore_vector2i cell, bool right_half,
+ enum wsap_vtcore_select_unit unit);
+/* Extend the selection from its start to cell. Returns false when memory runs
+ * out; the selection is then unchanged. */
+WSAP_VTCORE_API bool wsap_vtcore_select_extend(struct wsap_vtcore *t, struct wsap_vtcore_vector2i cell, bool right_half);
+WSAP_VTCORE_API void wsap_vtcore_select_clear(struct wsap_vtcore *t);
+WSAP_VTCORE_API bool wsap_vtcore_has_selection(const struct wsap_vtcore *t);
+/* Owned, NUL-terminated UTF-8 of the selection. NULL when nothing is
+ * selected or allocation fails; a selection of blanks may produce an empty
+ * string. Capture is atomic with respect to other calls on t. Release the
+ * result with wsap_vtcore_text_free(). */
+WSAP_VTCORE_API char *wsap_vtcore_selection_text(const struct wsap_vtcore *t);
+/* Owned OSC 8 link or detected URL at a viewport cell. NULL when there is
+ * no link or allocation fails. Release the result with wsap_vtcore_text_free(). */
+WSAP_VTCORE_API char *wsap_vtcore_link_at(const struct wsap_vtcore *t, struct wsap_vtcore_vector2i cell);
+
+/* Cell attributes share the write core's bit layout. Underline styles are
+ * mutually exclusive flags, not a shifted enum; use wsap_vtcore_attr_underline(). */
+enum wsap_vtcore_attr {
+ WSAP_VTCORE_ATTR_BOLD = 1u << 0,
+ WSAP_VTCORE_ATTR_ITALIC = 1u << 1,
+ WSAP_VTCORE_ATTR_UNDERLINE = 1u << 2,
+ WSAP_VTCORE_ATTR_STRIKE = 1u << 3,
+ WSAP_VTCORE_ATTR_OVERLINE = 1u << 4,
+ WSAP_VTCORE_ATTR_EMOJI = 1u << 5, /* the text requested emoji presentation */
+ WSAP_VTCORE_ATTR_TEXT = 1u << 6, /* the text requested text presentation */
+ WSAP_VTCORE_ATTR_FAINT = 1u << 10,
+ WSAP_VTCORE_ATTR_DOUBLE_UNDERLINE = 1u << 11,
+ WSAP_VTCORE_ATTR_CURLY_UNDERLINE = 1u << 12,
+ WSAP_VTCORE_ATTR_DOTTED_UNDERLINE = 1u << 13,
+ WSAP_VTCORE_ATTR_DASHED_UNDERLINE = 1u << 14,
+ WSAP_VTCORE_ATTR_LINK = 1u << 15,
+};
+
+#define WSAP_VTCORE_ATTR_UNDERLINE_MASK \
+ (WSAP_VTCORE_ATTR_UNDERLINE | WSAP_VTCORE_ATTR_DOUBLE_UNDERLINE | WSAP_VTCORE_ATTR_CURLY_UNDERLINE | \
+ WSAP_VTCORE_ATTR_DOTTED_UNDERLINE | WSAP_VTCORE_ATTR_DASHED_UNDERLINE)
+
+enum wsap_vtcore_underline {
+ WSAP_VTCORE_UNDERLINE_NONE,
+ WSAP_VTCORE_UNDERLINE_SINGLE,
+ WSAP_VTCORE_UNDERLINE_DOUBLE,
+ WSAP_VTCORE_UNDERLINE_CURLY,
+ WSAP_VTCORE_UNDERLINE_DOTTED,
+ WSAP_VTCORE_UNDERLINE_DASHED,
+};
+
+static inline enum wsap_vtcore_underline wsap_vtcore_attr_underline(uint16_t attrs)
+{
+ if (attrs & WSAP_VTCORE_ATTR_DOUBLE_UNDERLINE) return WSAP_VTCORE_UNDERLINE_DOUBLE;
+ if (attrs & WSAP_VTCORE_ATTR_CURLY_UNDERLINE) return WSAP_VTCORE_UNDERLINE_CURLY;
+ if (attrs & WSAP_VTCORE_ATTR_DOTTED_UNDERLINE) return WSAP_VTCORE_UNDERLINE_DOTTED;
+ if (attrs & WSAP_VTCORE_ATTR_DASHED_UNDERLINE) return WSAP_VTCORE_UNDERLINE_DASHED;
+ return attrs & WSAP_VTCORE_ATTR_UNDERLINE ? WSAP_VTCORE_UNDERLINE_SINGLE : WSAP_VTCORE_UNDERLINE_NONE;
+}
+
+/* text refers to a grapheme cluster in the snapshot; see wsap_vtcore_snapshot_cluster(). */
+#define WSAP_VTCORE_TEXT_CLUSTER 0x80000000u
+
+/* One cell as a snapshot shows it. */
+struct wsap_vtcore_cell {
+ uint32_t text; /* a code point, WSAP_VTCORE_TEXT_CLUSTER | n, or 0 for an empty cell */
+ wsap_vtcore_color fg, bg;
+ uint16_t attrs; /* enum wsap_vtcore_attr flags; at most one underline flag */
+ uint8_t width; /* 1; 2 for a wide glyph; 0 for the right half of a wide glyph */
+ uint8_t reserved;
+};
+
+#ifdef __cplusplus
+static_assert(sizeof(struct wsap_vtcore_cell) == 16, "four cells fill one 64-byte line");
+#else
+_Static_assert(sizeof(struct wsap_vtcore_cell) == 16, "four cells fill one 64-byte line");
+#endif
+
+/*
+ * Snapshot: a copy of the viewport for a renderer. It holds no pointer into
+ * the terminal, so it stays valid while the terminal changes. One terminal
+ * may have several snapshots, for example a window and a tab preview.
+ */
+WSAP_VTCORE_API struct wsap_vtcore_snapshot *wsap_vtcore_snapshot_new(void);
+WSAP_VTCORE_API void wsap_vtcore_snapshot_free(struct wsap_vtcore_snapshot *s);
+
+/* Copy the viewport of t into s. Keep rows with unchanged content keys.
+ * Update the history view index and refine counts for visible wide lines.
+ * Return false when memory runs out. The snapshot then keeps its previous content. */
+WSAP_VTCORE_API bool wsap_vtcore_snapshot_update(struct wsap_vtcore_snapshot *s, struct wsap_vtcore *t);
+
+/* Palette entries of struct wsap_vtcore_view.palette after the 256 indexed colors. */
+enum {
+ WSAP_VTCORE_PALETTE_FG = 256,
+ WSAP_VTCORE_PALETTE_BG = 257,
+ WSAP_VTCORE_PALETTE_CURSOR = 258,
+ WSAP_VTCORE_PALETTE_SIZE = 259,
+};
+
+struct wsap_vtcore_view {
+ struct wsap_vtcore_vector2i size;
+ struct wsap_vtcore_cursor cursor; /* viewport coordinates; not visible when scrolled away */
+ int scroll_offset;
+ /* Rows the content moved up since the previous update, when that movement
+ * explains the change; otherwise 0. */
+ int scrolled;
+ bool reverse_video;
+ /* Changes when any part of the view changes. */
+ uint64_t version;
+ /* Changes when a palette entry changes. */
+ uint64_t palette_version;
+ const uint32_t *palette; /* WSAP_VTCORE_PALETTE_SIZE ARGB entries */
+};
+
+/* The view of s, NULL for a NULL s. The view and view->palette keep their
+ * address until wsap_vtcore_snapshot_free(); their contents change on each update. */
+WSAP_VTCORE_API const struct wsap_vtcore_view *wsap_vtcore_snapshot_view(const struct wsap_vtcore_snapshot *s);
+/* The cells of viewport row y: view->size.x entries. NULL when y is outside
+ * the viewport or s is NULL. An update can move the cells, so the pointer is
+ * valid only until the next wsap_vtcore_snapshot_update() or wsap_vtcore_snapshot_free() of s. */
+WSAP_VTCORE_API const struct wsap_vtcore_cell *wsap_vtcore_snapshot_row(const struct wsap_vtcore_snapshot *s, int y);
+/* An identity for the content of row y. Two rows with the same key hold the
+ * same cells, also when the content moved to another row. 0 when y is outside
+ * the viewport or s is NULL. */
+WSAP_VTCORE_API uint64_t wsap_vtcore_snapshot_row_key(const struct wsap_vtcore_snapshot *s, int y);
+
+/* Number of rows in history above the screen. 0 if alternate screen or no history. */
+WSAP_VTCORE_API int wsap_vtcore_history_rows(const struct wsap_vtcore *t);
+/* Owned, NUL-terminated UTF-8 of up to max_rows history rows before the
+ * current viewport. Join soft-wrapped rows and end closed lines with a
+ * newline. Does not change the selection. No history or max_rows <= 0 gives
+ * an empty string; NULL means allocation failed or t is NULL. Release the
+ * result with wsap_vtcore_text_free(). */
+WSAP_VTCORE_API char *wsap_vtcore_history_text(struct wsap_vtcore *t, int max_rows);
+/* The selected columns of viewport row y, end exclusive. An empty span when y
+ * is outside the viewport or s is NULL. */
+WSAP_VTCORE_API struct wsap_vtcore_span wsap_vtcore_snapshot_row_selection(const struct wsap_vtcore_snapshot *s, int y);
+
+/* The code points of a cluster cell. Returns the number of code points and
+ * writes at most cap of them. Writes nothing when cps is NULL or cap is 0.
+ * Returns 0 when s is NULL. */
+WSAP_VTCORE_API int wsap_vtcore_snapshot_cluster(const struct wsap_vtcore_snapshot *s, uint32_t text, uint32_t *cps, int cap);
+
+/* The ARGB value of a color in a view. */
+static inline uint32_t wsap_vtcore_view_color(const struct wsap_vtcore_view *v, wsap_vtcore_color c)
+{
+ if (!wsap_vtcore_color_is_slot(c))
+ return c;
+ return v->palette[c & WSAP_VTCORE_COLOR_SLOT_INDEX];
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/wsap_vtcore/wsap_vtcore_input.h b/include/wsap_vtcore/wsap_vtcore_input.h
new file mode 100644
index 0000000..337a292
--- /dev/null
+++ b/include/wsap_vtcore/wsap_vtcore_input.h
@@ -0,0 +1,202 @@
+#ifndef WSAP_VTCORE_INPUT_H
+#define WSAP_VTCORE_INPUT_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include "wsap_vtcore_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum wsap_vtcore_key {
+ WSAP_VTCORE_KEY_NONE = 0,
+
+ WSAP_VTCORE_KEY_RETURN,
+ WSAP_VTCORE_KEY_BACKSPACE,
+ WSAP_VTCORE_KEY_TAB,
+ WSAP_VTCORE_KEY_ESCAPE,
+
+ WSAP_VTCORE_KEY_UP,
+ WSAP_VTCORE_KEY_DOWN,
+ WSAP_VTCORE_KEY_RIGHT,
+ WSAP_VTCORE_KEY_LEFT,
+ WSAP_VTCORE_KEY_HOME,
+ WSAP_VTCORE_KEY_END,
+ WSAP_VTCORE_KEY_PAGE_UP,
+ WSAP_VTCORE_KEY_PAGE_DOWN,
+ WSAP_VTCORE_KEY_INSERT,
+ WSAP_VTCORE_KEY_DELETE,
+
+ WSAP_VTCORE_KEY_F1, WSAP_VTCORE_KEY_F2, WSAP_VTCORE_KEY_F3, WSAP_VTCORE_KEY_F4, WSAP_VTCORE_KEY_F5,
+ WSAP_VTCORE_KEY_F6, WSAP_VTCORE_KEY_F7, WSAP_VTCORE_KEY_F8, WSAP_VTCORE_KEY_F9, WSAP_VTCORE_KEY_F10,
+ WSAP_VTCORE_KEY_F11, WSAP_VTCORE_KEY_F12, WSAP_VTCORE_KEY_F13, WSAP_VTCORE_KEY_F14, WSAP_VTCORE_KEY_F15,
+ WSAP_VTCORE_KEY_F16, WSAP_VTCORE_KEY_F17, WSAP_VTCORE_KEY_F18, WSAP_VTCORE_KEY_F19, WSAP_VTCORE_KEY_F20,
+ WSAP_VTCORE_KEY_F21, WSAP_VTCORE_KEY_F22, WSAP_VTCORE_KEY_F23, WSAP_VTCORE_KEY_F24, WSAP_VTCORE_KEY_F25,
+ WSAP_VTCORE_KEY_F26, WSAP_VTCORE_KEY_F27, WSAP_VTCORE_KEY_F28, WSAP_VTCORE_KEY_F29, WSAP_VTCORE_KEY_F30,
+ WSAP_VTCORE_KEY_F31, WSAP_VTCORE_KEY_F32, WSAP_VTCORE_KEY_F33, WSAP_VTCORE_KEY_F34, WSAP_VTCORE_KEY_F35,
+
+ WSAP_VTCORE_KEY_KP_0, WSAP_VTCORE_KEY_KP_1, WSAP_VTCORE_KEY_KP_2, WSAP_VTCORE_KEY_KP_3, WSAP_VTCORE_KEY_KP_4,
+ WSAP_VTCORE_KEY_KP_5, WSAP_VTCORE_KEY_KP_6, WSAP_VTCORE_KEY_KP_7, WSAP_VTCORE_KEY_KP_8, WSAP_VTCORE_KEY_KP_9,
+ WSAP_VTCORE_KEY_KP_DECIMAL,
+ WSAP_VTCORE_KEY_KP_ENTER,
+ WSAP_VTCORE_KEY_KP_ADD,
+ WSAP_VTCORE_KEY_KP_SUBTRACT,
+ WSAP_VTCORE_KEY_KP_MULTIPLY,
+ WSAP_VTCORE_KEY_KP_DIVIDE,
+ WSAP_VTCORE_KEY_KP_EQUAL,
+ WSAP_VTCORE_KEY_KP_SEPARATOR,
+ WSAP_VTCORE_KEY_KP_LEFT,
+ WSAP_VTCORE_KEY_KP_RIGHT,
+ WSAP_VTCORE_KEY_KP_UP,
+ WSAP_VTCORE_KEY_KP_DOWN,
+ WSAP_VTCORE_KEY_KP_PAGE_UP,
+ WSAP_VTCORE_KEY_KP_PAGE_DOWN,
+ WSAP_VTCORE_KEY_KP_HOME,
+ WSAP_VTCORE_KEY_KP_END,
+ WSAP_VTCORE_KEY_KP_INSERT,
+ WSAP_VTCORE_KEY_KP_DELETE,
+ WSAP_VTCORE_KEY_KP_BEGIN,
+
+ WSAP_VTCORE_KEY_CAPS_LOCK,
+ WSAP_VTCORE_KEY_SCROLL_LOCK,
+ WSAP_VTCORE_KEY_NUM_LOCK,
+ WSAP_VTCORE_KEY_PRINT_SCREEN,
+ WSAP_VTCORE_KEY_PAUSE,
+ WSAP_VTCORE_KEY_MENU,
+
+ WSAP_VTCORE_KEY_MEDIA_PLAY,
+ WSAP_VTCORE_KEY_MEDIA_PAUSE,
+ WSAP_VTCORE_KEY_MEDIA_STOP,
+ WSAP_VTCORE_KEY_MEDIA_FORWARD,
+ WSAP_VTCORE_KEY_MEDIA_REWIND,
+ WSAP_VTCORE_KEY_MEDIA_NEXT,
+ WSAP_VTCORE_KEY_MEDIA_PREV,
+ WSAP_VTCORE_KEY_MEDIA_RECORD,
+ WSAP_VTCORE_KEY_VOLUME_DOWN,
+ WSAP_VTCORE_KEY_VOLUME_UP,
+ WSAP_VTCORE_KEY_MUTE,
+
+ WSAP_VTCORE_KEY_LSHIFT,
+ WSAP_VTCORE_KEY_LCTRL,
+ WSAP_VTCORE_KEY_LALT,
+ WSAP_VTCORE_KEY_LSUPER,
+ WSAP_VTCORE_KEY_LHYPER,
+ WSAP_VTCORE_KEY_LMETA,
+ WSAP_VTCORE_KEY_RSHIFT,
+ WSAP_VTCORE_KEY_RCTRL,
+ WSAP_VTCORE_KEY_RALT,
+ WSAP_VTCORE_KEY_RSUPER,
+ WSAP_VTCORE_KEY_RHYPER,
+ WSAP_VTCORE_KEY_RMETA,
+ WSAP_VTCORE_KEY_ISO_LEVEL3_SHIFT,
+ WSAP_VTCORE_KEY_ISO_LEVEL5_SHIFT,
+
+ WSAP_VTCORE_KEY_COUNT
+};
+
+enum wsap_vtcore_mod {
+ WSAP_VTCORE_MOD_SHIFT = 1,
+ WSAP_VTCORE_MOD_ALT = 2,
+ WSAP_VTCORE_MOD_CTRL = 4,
+ WSAP_VTCORE_MOD_SUPER = 8,
+ WSAP_VTCORE_MOD_HYPER = 16,
+ WSAP_VTCORE_MOD_META = 32,
+ WSAP_VTCORE_MOD_CAPS = 64,
+ WSAP_VTCORE_MOD_NUM = 128,
+};
+
+enum wsap_vtcore_key_action {
+ WSAP_VTCORE_KEY_PRESS = 1,
+ WSAP_VTCORE_KEY_REPEAT = 2,
+ WSAP_VTCORE_KEY_RELEASE = 3,
+};
+
+enum wsap_vtcore_mouse_button {
+ WSAP_VTCORE_MOUSE_BUTTON_PRIMARY = 0,
+ WSAP_VTCORE_MOUSE_BUTTON_MIDDLE,
+ WSAP_VTCORE_MOUSE_BUTTON_SECONDARY,
+ WSAP_VTCORE_MOUSE_BUTTON_NONE,
+ /* Extra buttons 8 through 11 in xterm mouse reporting (encoded as 128..131). */
+ WSAP_VTCORE_MOUSE_BUTTON_EXTRA_1,
+ WSAP_VTCORE_MOUSE_BUTTON_EXTRA_2,
+ WSAP_VTCORE_MOUSE_BUTTON_EXTRA_3,
+ WSAP_VTCORE_MOUSE_BUTTON_EXTRA_4,
+ WSAP_VTCORE_MOUSE_WHEEL_UP = 16,
+ WSAP_VTCORE_MOUSE_WHEEL_DOWN,
+ WSAP_VTCORE_MOUSE_WHEEL_LEFT,
+ WSAP_VTCORE_MOUSE_WHEEL_RIGHT,
+};
+
+enum wsap_vtcore_mouse_event_kind {
+ WSAP_VTCORE_MOUSE_PRESS = 0,
+ WSAP_VTCORE_MOUSE_RELEASE,
+ WSAP_VTCORE_MOUSE_MOTION,
+ WSAP_VTCORE_MOUSE_SCROLL,
+ WSAP_VTCORE_MOUSE_LEAVE,
+};
+
+struct wsap_vtcore_key_event {
+ enum wsap_vtcore_key_action action;
+ uint16_t key; /* enum wsap_vtcore_key; WSAP_VTCORE_KEY_NONE for a text key */
+ uint16_t keypad; /* the WSAP_VTCORE_KEY_KP_* key when the key is on the keypad */
+ unsigned mods; /* enum wsap_vtcore_mod */
+ uint32_t codepoint; /* the code point of the key without modifiers */
+ uint32_t shifted; /* the code point of the key with Shift */
+ uint32_t base; /* the code point of the key in the US layout */
+ uint32_t text; /* the code point the key types, or 0 */
+ bool text_deferred; /* an input method sends the text later */
+};
+
+struct wsap_vtcore_mouse_event {
+ struct wsap_vtcore_vector2i pos; /* Grid cell coordinates (col, row) */
+ struct wsap_vtcore_vector2i pixel; /* Absolute pixel position in terminal grid */
+ /*
+ * Button identifier:
+ * - Press and release: the button that changed state (WSAP_VTCORE_MOUSE_BUTTON_*).
+ * - Motion: the held button for drag events, or WSAP_VTCORE_MOUSE_BUTTON_NONE for hover.
+ * - Scroll: the wheel direction (WSAP_VTCORE_MOUSE_WHEEL_*).
+ */
+ int button;
+ unsigned mods;
+ int scroll_lines;
+ float scroll_delta;
+ enum wsap_vtcore_mouse_event_kind kind;
+};
+
+/* The keys that are down. An all-zero value has no keys down. */
+struct wsap_vtcore_keyboard_state {
+ uint64_t down[(WSAP_VTCORE_KEY_COUNT + 63) / 64];
+};
+
+/* Record a press, repeat, or release in s. */
+WSAP_VTCORE_API void wsap_vtcore_keyboard_update(struct wsap_vtcore_keyboard_state *s, const struct wsap_vtcore_key_event *ev);
+WSAP_VTCORE_API bool wsap_vtcore_keyboard_key_down(const struct wsap_vtcore_keyboard_state *s, enum wsap_vtcore_key key);
+
+/* Kitty keyboard protocol flags, as in wsap_vtcore_modes.keyboard. */
+enum wsap_vtcore_keyboard_flag {
+ WSAP_VTCORE_KEYBOARD_DISAMBIGUATE = 1,
+ WSAP_VTCORE_KEYBOARD_EVENT_TYPES = 2,
+ WSAP_VTCORE_KEYBOARD_ALTERNATE_KEYS = 4,
+ WSAP_VTCORE_KEYBOARD_ALL_KEYS = 8,
+ WSAP_VTCORE_KEYBOARD_ASSOCIATED_TEXT = 16,
+};
+
+enum wsap_vtcore_input_status {
+ WSAP_VTCORE_INPUT_UNHANDLED = 0, /* the terminal does not use the event */
+ WSAP_VTCORE_INPUT_CONSUMED, /* the terminal uses the event but sends nothing */
+ WSAP_VTCORE_INPUT_BYTES, /* send the len bytes in buf to the program */
+ WSAP_VTCORE_INPUT_BUFFER_FULL, /* buf is too small; len is 0 */
+};
+
+struct wsap_vtcore_input_result {
+ size_t len;
+ enum wsap_vtcore_input_status status;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WSAP_VTCORE_INPUT_H */
diff --git a/include/term/term_types.h b/include/wsap_vtcore/wsap_vtcore_types.h
index 78be371..0944da3 100644
--- a/include/term/term_types.h
+++ b/include/wsap_vtcore/wsap_vtcore_types.h
@@ -1,14 +1,14 @@
-#ifndef TERM_TYPES_H
-#define TERM_TYPES_H
+#ifndef WSAP_VTCORE_TYPES_H
+#define WSAP_VTCORE_TYPES_H
/* Marks the public functions. The library builds with hidden symbols, so
* only these are visible outside a shared build. A host can define it
* first, for example as __declspec(dllimport). */
-#ifndef TERM_API
+#ifndef WSAP_VTCORE_API
#if defined(__GNUC__) || defined(__clang__)
-#define TERM_API __attribute__((visibility("default")))
+#define WSAP_VTCORE_API __attribute__((visibility("default")))
#else
-#define TERM_API
+#define WSAP_VTCORE_API
#endif
#endif
@@ -16,11 +16,11 @@
extern "C" {
#endif
-struct term_vector2i {
+struct wsap_vtcore_vector2i {
int x, y;
};
-struct term_span {
+struct wsap_vtcore_span {
int begin;
int end;
};