refactor: shared Unicode display-width utility with grapheme cluster support
Consolidate two inconsistent codepoint_width implementations from Screen.cpp and EventEditor.cpp into nocal/tui/unicode.hpp. The unified table covers all CJK, Hangul, emoji, symbol, and combining mark ranges. display_width and fit_text handle grapheme clusters (ZWJ sequences, skin-tone/hair modifiers, regional indicator pairs, variation selectors) so calendar text with emoji or East Asian characters renders correctly.
This commit is contained in:
35
include/nocal/tui/unicode.hpp
Normal file
35
include/nocal/tui/unicode.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace nocal::tui {
|
||||
|
||||
struct DecodedCodepoint {
|
||||
std::uint32_t value;
|
||||
std::size_t length;
|
||||
};
|
||||
|
||||
// Decode one UTF-8 codepoint at position `at` in `text`.
|
||||
// Returns {0xfffd, 1} on error. Caller must ensure at < text.size().
|
||||
[[nodiscard]] DecodedCodepoint decode_codepoint(std::string_view text, std::size_t at) noexcept;
|
||||
|
||||
// Terminal display width of a single codepoint: 0 (zero-width/combining), 1, or 2.
|
||||
// Uses Unicode East Asian Width property with complete range tables.
|
||||
[[nodiscard]] int codepoint_width(std::uint32_t value) noexcept;
|
||||
|
||||
// Display width of a string. Handles grapheme clusters:
|
||||
// - Emoji ZWJ sequences → width 2
|
||||
// - Emoji + skin tone / hair modifiers → width 2
|
||||
// - Regional indicator pairs (flags) → width 2
|
||||
// - Combining marks → absorbed by base
|
||||
[[nodiscard]] int display_width(std::string_view text);
|
||||
|
||||
// Truncate to `width` display cells. If `ellipsis` is true and the text is
|
||||
// truncated, appends U+2026. Right-pads with spaces to reach `width`.
|
||||
// Never breaks a grapheme cluster.
|
||||
[[nodiscard]] std::string fit_text(std::string_view text, int width, bool ellipsis = true);
|
||||
|
||||
} // namespace nocal::tui
|
||||
Reference in New Issue
Block a user