From dcebf9c7f954a55350b68d0ead1935612c4e2e05 Mon Sep 17 00:00:00 2001 From: Berke Güzel Date: Thu, 15 Oct 2026 13:04:01 +0300 Subject: Rename the library to wsap_vtcore ncurses installs and defines struct term. In a file that includes both headers, an ncurses TERMINAL * and this library's terminal are silently the same type. The name wsap_vtcore avoids the clash. The public header is now . Every global symbol uses the wsap_vtcore_ prefix, every macro uses WSAP_VTCORE_, and the shared library is libwsap_vtcore.so.0. The default terminal name is now "wsap_vtcore". The ISA override variable is WSAP_VTCORE_ISA. No other behavior changes. The amalgamation writes wsap_vtcore.c and wsap_vtcore.h. Co-Authored-By: Claude Haiku 5.5 --- include/wsap_vtcore/wsap_vtcore.h | 492 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 492 insertions(+) create mode 100644 include/wsap_vtcore/wsap_vtcore.h (limited to 'include/wsap_vtcore/wsap_vtcore.h') 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 +#include +#include + +#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 -- cgit v1.2.3