bd44b5aa08
Test / build-libghostty-vt (x86_64-windows-gnu) (push) Has been cancelled
Test / build-libghostty-vt-macos (aarch64-ios) (push) Has been cancelled
Test / build-libghostty-vt-macos (aarch64-macos) (push) Has been cancelled
Test / build-libghostty-vt-macos (x86_64-macos) (push) Has been cancelled
Test / build-nix (namespace-profile-ghostty-md-arm64) (push) Has been cancelled
Test / build-dist (push) Has been cancelled
Test / GTK x11=true wayland=true (push) Has been cancelled
Test / Build -Dsimd=false (push) Has been cancelled
Test / Build -Dsimd=true (push) Has been cancelled
Test / Build -Dsentry=false (push) Has been cancelled
Test / Build -Dsentry=true (push) Has been cancelled
Test / zig-fmt (push) Has been cancelled
Test / GitHub Actions Pins (push) Has been cancelled
Test / prettier (push) Has been cancelled
Test / swiftlint (push) Has been cancelled
Test / alejandra (push) Has been cancelled
Test / typos (push) Has been cancelled
Nix / Required Checks: Nix (push) Has been cancelled
Nix / check-zig-cache-hash (push) Has been cancelled
Test / skip (push) Has been cancelled
Test / Required Checks: Test (push) Has been cancelled
Test / build-bench (push) Has been cancelled
Test / list-examples (push) Has been cancelled
Test / Example ${{ matrix.dir }} (Windows) (push) Has been cancelled
Test / build-cmake (push) Has been cancelled
Test / test-lib-vt-pkgconfig (push) Has been cancelled
Test / build-flatpak (push) Has been cancelled
Test / build-snap (push) Has been cancelled
Test / build-libghostty-vt (aarch64-linux) (push) Has been cancelled
Test / build-libghostty-vt (aarch64-macos) (push) Has been cancelled
Test / build-libghostty-vt (wasm32-freestanding) (push) Has been cancelled
Test / build-libghostty-vt (x86_64-linux) (push) Has been cancelled
Test / build-libghostty-vt (x86_64-linux-musl) (push) Has been cancelled
Test / build-libghostty-vt (x86_64-macos) (push) Has been cancelled
Test / build-libghostty-vt-android (aarch64-linux-android) (push) Has been cancelled
Test / build-libghostty-vt-android (arm-linux-androideabi) (push) Has been cancelled
Test / build-libghostty-vt-android (x86_64-linux-android) (push) Has been cancelled
Test / build-libghostty-vt-windows (push) Has been cancelled
Test / build-libghostty-windows-gnu (push) Has been cancelled
Test / build-linux (namespace-profile-ghostty-md) (push) Has been cancelled
Test / build-linux (namespace-profile-ghostty-md-arm64) (push) Has been cancelled
Test / build-linux-libghostty (push) Has been cancelled
Test / build-nix (namespace-profile-ghostty-md) (push) Has been cancelled
Test / build-dist-lib-vt (push) Has been cancelled
Test / trigger-snap (push) Has been cancelled
Test / trigger-flatpak (push) Has been cancelled
Test / build-macos (push) Has been cancelled
Test / build-macos-freetype (push) Has been cancelled
Test / test (push) Has been cancelled
Test / test-lib-vt (push) Has been cancelled
Test / GTK x11=false wayland=false (push) Has been cancelled
Test / GTK x11=true wayland=false (push) Has been cancelled
Test / GTK x11=false wayland=true (push) Has been cancelled
Test / test-macos (push) Has been cancelled
Test / test-windows (push) Has been cancelled
Test / Build -Di18n=false (push) Has been cancelled
Test / Build -Di18n=true (push) Has been cancelled
Test / Build test/fuzz-libghostty (push) Has been cancelled
Test / shellcheck (push) Has been cancelled
Test / translations (push) Has been cancelled
Test / blueprint-compiler (push) Has been cancelled
Test / Test pkg/wuffs (push) Has been cancelled
Test / Test build on Debian 13 (push) Has been cancelled
Test / valgrind (push) Has been cancelled
Test / Example ${{ matrix.dir }} (push) Has been cancelled
155 lines
6.2 KiB
C
155 lines
6.2 KiB
C
/**
|
|
* @file unicode.h
|
|
*
|
|
* Unicode utilities - codepoint properties matching the terminal's
|
|
* text layout semantics.
|
|
*/
|
|
|
|
#ifndef GHOSTTY_VT_UNICODE_H
|
|
#define GHOSTTY_VT_UNICODE_H
|
|
|
|
/** @defgroup unicode Unicode Utilities
|
|
*
|
|
* Unicode codepoint properties matching the terminal's text layout
|
|
* semantics.
|
|
*
|
|
* ## Basic Usage
|
|
*
|
|
* Use ghostty_unicode_codepoint_width() to determine how many terminal
|
|
* grid cells a codepoint occupies, using the exact same width table the
|
|
* terminal itself uses when laying out printed text. Use
|
|
* ghostty_unicode_grapheme_width() to segment and measure full grapheme
|
|
* clusters with the same rules the terminal uses when mode 2027 is
|
|
* enabled. These functions are useful for predicting column layout of
|
|
* text that has not yet been written to the terminal, such as IME
|
|
* preedit (composition) overlays.
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <ghostty/vt/types.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* Returns the terminal display width of a Unicode codepoint in
|
|
* terminal grid cells: 0, 1, or 2.
|
|
*
|
|
* This is the same width table the terminal itself uses when laying
|
|
* out printed text, so callers can predict column layout (e.g. IME
|
|
* preedit overlays) that exactly matches what the terminal will do
|
|
* when the text is actually written to it.
|
|
*
|
|
* Semantics:
|
|
* - Returns 0 for zero-width codepoints: C0/C1 control characters,
|
|
* nonspacing and enclosing combining marks, default-ignorable
|
|
* codepoints (ZWJ, ZWNJ, variation selectors, etc.), and
|
|
* surrogate codepoints.
|
|
* - Returns 2 for wide codepoints: East Asian Wide/Fullwidth
|
|
* (including emoji with default emoji presentation) and regional
|
|
* indicators. Width is clamped to 2 (e.g. the three-em dash).
|
|
* - Returns 1 for everything else, including invalid codepoints
|
|
* beyond U+10FFFF (this function is total; it never fails).
|
|
*
|
|
* This operates on a single codepoint only and therefore cannot account
|
|
* for grapheme-cluster-level width rules (VS16 emoji presentation,
|
|
* combining sequences, etc.). For cluster-accurate widths, use
|
|
* ghostty_unicode_grapheme_width(). Summing per-codepoint widths is only
|
|
* correct when mode 2027 (grapheme clustering) is disabled.
|
|
*
|
|
* This function is pure, allocates nothing, and is thread-safe.
|
|
*
|
|
* @param cp The Unicode codepoint to measure
|
|
* @return Display width in cells: 0, 1, or 2
|
|
*/
|
|
GHOSTTY_API uint8_t ghostty_unicode_codepoint_width(uint32_t cp);
|
|
|
|
/**
|
|
* Measures the terminal display width of the first grapheme cluster in a
|
|
* sequence of Unicode codepoints.
|
|
*
|
|
* This uses the exact same grapheme segmentation and cluster width rules
|
|
* the terminal itself uses when printing text with grapheme clustering
|
|
* enabled (mode 2027), so callers can predict column layout (e.g. IME
|
|
* preedit overlays) that exactly matches what the terminal will do when
|
|
* the text is actually written to it. Unlike
|
|
* ghostty_unicode_codepoint_width(), this accounts for cluster-level
|
|
* rules: emoji variation selectors, ZWJ sequences, combining marks, and
|
|
* skin tone modifiers.
|
|
*
|
|
* Reads codepoints from cps until the terminal would consider the
|
|
* grapheme cluster complete, stores the cluster's total width in cells
|
|
* (0, 1, or 2) into width (which may be NULL if only segmentation is
|
|
* desired), and returns the number of codepoints consumed. Returns 0 if
|
|
* and only if len is 0; otherwise consumes at least one codepoint. Measure
|
|
* a whole string by calling in a loop:
|
|
*
|
|
* @code
|
|
* size_t total = 0;
|
|
* for (size_t i = 0; i < len;) {
|
|
* uint8_t width;
|
|
* i += ghostty_unicode_grapheme_width(cps + i, len - i, &width);
|
|
* total += width;
|
|
* }
|
|
* @endcode
|
|
*
|
|
* This is not a streaming API. The provided sequence must contain a
|
|
* complete first grapheme cluster, or the logical end of the string. If
|
|
* input arrives in chunks, keep buffering while this function consumes all
|
|
* available codepoints (return value == len) and the stream may still
|
|
* continue; a later codepoint could still extend the cluster and change
|
|
* its width.
|
|
*
|
|
* Width semantics, matching the terminal with mode 2027 enabled:
|
|
* - The cluster starts at the width of its first codepoint, as returned by
|
|
* ghostty_unicode_codepoint_width().
|
|
* - VS16 (U+FE0F) forces the cluster wide (2) and VS15 (U+FE0E) forces it
|
|
* narrow (1), but only when the immediately preceding codepoint in the
|
|
* cluster is a valid emoji variation sequence base (per Unicode
|
|
* emoji-variation-sequences.txt). Invalid variation selectors are
|
|
* ignored entirely.
|
|
* - Any other continuation codepoint that contributes to grapheme width
|
|
* forces the cluster wide (2). Note this means cluster width is NOT the
|
|
* maximum of per-codepoint widths: some continuation marks have narrow
|
|
* codepoint width yet still widen the cluster.
|
|
*
|
|
* Mode dependence: this models mode 2027 (grapheme clustering) enabled,
|
|
* which is Ghostty's recommended configuration. When mode 2027 is
|
|
* disabled, clusters never combine and variation selectors never change
|
|
* width; predict layout in that case by summing
|
|
* ghostty_unicode_codepoint_width() over each codepoint instead.
|
|
*
|
|
* Edge cases:
|
|
* - Codepoints beyond U+10FFFF consume one codepoint, have width 1, and
|
|
* are always cluster boundaries. This function is total; it never fails.
|
|
* - Control characters (C0/C1, CR, LF) are never printed through the
|
|
* terminal's text path; passing them here returns an unspecified (but
|
|
* stable and bounded) result.
|
|
* - A cluster whose first codepoint is zero-width (e.g. a lone combining
|
|
* mark) is malformed at a cell start; the terminal may attach it to
|
|
* earlier screen content. This function reports the fold result for the
|
|
* sequence in isolation (typically 0).
|
|
*
|
|
* This function is pure, allocates nothing, and is thread-safe.
|
|
*
|
|
* @param cps Pointer to codepoints (may be NULL only when len is 0)
|
|
* @param len Number of codepoints available
|
|
* @param width Out: cluster display width in cells (0-2); may be NULL
|
|
* @return Number of codepoints in the first grapheme cluster
|
|
*/
|
|
GHOSTTY_API size_t ghostty_unicode_grapheme_width(const uint32_t *cps,
|
|
size_t len,
|
|
uint8_t *width);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
/** @} */
|
|
|
|
#endif /* GHOSTTY_VT_UNICODE_H */
|