aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/include/ghostty/vt/unicode.h
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-07-16 23:28:05 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-07-16 23:29:28 +0300
commit4a3302d19a2baa3a33e910e0088c24e780905b90 (patch)
treedcaf76fae1c82102d933c9225b17ca7ac5d3a847 /vendor/libghostty-vt/include/ghostty/vt/unicode.h
parent550e9f8cc085f428429f5cf2da0bb2dba897e8b8 (diff)
chore: update vendored libghostty-vt
refs #276
Diffstat (limited to 'vendor/libghostty-vt/include/ghostty/vt/unicode.h')
-rw-r--r--vendor/libghostty-vt/include/ghostty/vt/unicode.h154
1 files changed, 154 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/include/ghostty/vt/unicode.h b/vendor/libghostty-vt/include/ghostty/vt/unicode.h
new file mode 100644
index 00000000..e4d62c81
--- /dev/null
+++ b/vendor/libghostty-vt/include/ghostty/vt/unicode.h
@@ -0,0 +1,154 @@
+/**
+ * @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 */