Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions src/utf8.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,31 @@ std::string utf8_substr (
return result;
}

////////////////////////////////////////////////////////////////////////////////
// Truncate a UTF-8 string to fit within a target display width.
// Unlike substr which counts characters, this counts display columns.
const std::string utf8_truncate_to_width (
const std::string& input,
unsigned int target_width)
{
unsigned int current_width = 0;
std::string::size_type i = 0;
std::string::size_type last_safe = 0;
unsigned int c;

while ((c = utf8_next_char (input, i)))
{
int w = mk_wcwidth (c);
if (w < 0) w = 0;
if (current_width + w > target_width)
break;
current_width += w;
last_safe = i;
}

return input.substr (0, last_safe);
}

////////////////////////////////////////////////////////////////////////////////
int mk_wcwidth(wchar_t ucs)
{
Expand All @@ -316,6 +341,23 @@ int mk_wcwidth(wchar_t ucs)
if (width == widechar_ambiguous)
return 1;

// Emoji pictographs (U+1F300+) — width 2 in modern terminals
if ((ucs >= 0x1F300 && ucs <= 0x1F9FF) || // Misc Symbols, Pictographs, Emoticons, Supplemental
(ucs >= 0x1FA00 && ucs <= 0x1FAFF)) // Symbols and Pictographs Extended-A
return 2;

// Common symbols — width 1 in modern terminals
if ((ucs >= 0x2190 && ucs <= 0x21FF) || // Arrows
(ucs >= 0x2300 && ucs <= 0x23FF) || // Misc Technical
(ucs >= 0x25A0 && ucs <= 0x25FF) || // Geometric Shapes
(ucs >= 0x2600 && ucs <= 0x26FF) || // Misc Symbols
(ucs >= 0x2700 && ucs <= 0x27BF)) // Dingbats
return 1;

// Variation selectors — zero width
if (ucs >= 0xFE00 && ucs <= 0xFE0F)
return 0;

// All other negative values
return 0;
}
Expand Down
2 changes: 2 additions & 0 deletions src/utf8.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ unsigned int utf8_width (const std::string& str);
unsigned int utf8_text_width (const std::string&);
std::string utf8_substr (const std::string&, unsigned int, unsigned int length = 0);

const std::string utf8_truncate_to_width (const std::string&, unsigned int target_width);

int mk_wcwidth (wchar_t);

#endif