Skip to content

Commit

Permalink
Improve width predictions for color emoji codepoints.
Browse files Browse the repository at this point in the history
Win 8.1 uses width 1 for non-surrogate pair color emoji codepoints, and
width 2 for surrogate pair color emoji codepoints.

Win 10 behaves like Win 8.1 in conhost, but like Win 11 in Windows
Terminal.

Win 11 uses width 2 for color emoji codepoints both in conhost and in
Windows Terminal.
  • Loading branch information
chrisant996 committed Oct 28, 2024
1 parent da42ec7 commit dc31308
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 30 deletions.
11 changes: 5 additions & 6 deletions clink/terminal/src/wcwidth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,11 @@ static int32 mk_wcwidth_ucs2(char32_t ucs)
if (ucs < 0xa0)
return -1;

/* special processing for color emoji */
if (g_color_emoji &&
bisearch(ucs, emojis, _countof(emojis) - 1))
return 2;

/* binary search in table of non-spacing characters */
if (bisearch(ucs, combining, _countof(combining) - 1))
return s_combining_mark_width;
Expand Down Expand Up @@ -686,17 +691,11 @@ void reset_wcwidths()
if (use_cjk)
{
wcwidth = s_only_ucs2 ? mk_wcwidth_cjk_ucs2 : mk_wcwidth_cjk;
#if 0
wcswidth = mk_wcswidth_cjk;
#endif
init_cached_font();
}
else
{
wcwidth = s_only_ucs2 ? mk_wcwidth_ucs2 : mk_wcwidth;
#if 0
wcswidth = mk_wcswidth;
#endif
reset_cached_font();
}
}
Expand Down
53 changes: 29 additions & 24 deletions clink/terminal/src/win_screen_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,8 @@ static setting_enum g_terminal_color_emoji(
"to display the input line properly when it contains emoji characters.\n"
"When set to 'off' Clink assumes emoji are rendered using 1 character cell.\n"
"When set to 'on' Clink assumes emoji are rendered using 2 character cells.\n"
"When set to 'auto' (the default) Clink assumes emoji are rendered using 2\n"
"character cells when using Windows Terminal or WezTerm, or otherwise using 1\n"
"character cell.",
"When set to 'auto' (the default) Clink tries to predict how emoji will be\n"
"rendered based on the OS version and terminal program.",
"off,on,auto",
2);

Expand Down Expand Up @@ -223,6 +222,9 @@ void win_screen_buffer::begin()
static bool s_detect_native_ansi_handler = true;
const bool detect_native_ansi_handler = s_detect_native_ansi_handler;

static bool s_win10_15063 = false;
static bool s_win11 = false;

// One-time detection.
if (detect_native_ansi_handler)
{
Expand All @@ -234,8 +236,10 @@ void win_screen_buffer::begin()
OSVERSIONINFO ver = { sizeof(ver) };
if (GetVersionEx(&ver))
{
if ((ver.dwMajorVersion > 10) ||
(ver.dwMajorVersion == 10 && ver.dwBuildNumber >= 15063))
s_win10_15063 = ((ver.dwMajorVersion > 10) || (ver.dwMajorVersion == 10 && ver.dwBuildNumber >= 15063));
s_win11 = ((ver.dwMajorVersion > 10) || (ver.dwMajorVersion == 10 && ver.dwBuildNumber >= 22000));

if (s_win10_15063)
{
DWORD type;
DWORD data;
Expand All @@ -253,25 +257,6 @@ void win_screen_buffer::begin()
s_in_windows_terminal = check_for_windows_terminal();
}

// Check for color emoji width handling.
switch (g_terminal_color_emoji.get())
{
default:
case 0:
g_color_emoji = false;
break;
case 1:
g_color_emoji = true;
break;
case 2:
// Even with HKCU\Console\ForceV2 == 0, the Unicode codepoints for
// color emoji are rendered as two character cells. I don't know for
// sure when Windows started doing that, but for now I'll make it the
// default assumption.
g_color_emoji = true;
break;
}

// Always recheck the native terminal mode. For example, it's possible
// for ANSICON to be loaded or unloaded after Clink is initialized.
{
Expand Down Expand Up @@ -355,6 +340,26 @@ void win_screen_buffer::begin()
while (false);
}

// Check for color emoji width handling.
switch (g_terminal_color_emoji.get())
{
default:
case 0:
g_color_emoji = false;
break;
case 1:
g_color_emoji = true;
break;
case 2:
if (s_win11)
g_color_emoji = true;
else if (s_win10_15063)
g_color_emoji = s_in_windows_terminal;
else
g_color_emoji = false;
break;
}

GetConsoleMode(m_handle, &m_prev_mode);

CONSOLE_SCREEN_BUFFER_INFO csbi;
Expand Down

0 comments on commit dc31308

Please sign in to comment.