Skip to content

Commit

Permalink
TermControl: force all ambiguous glyphs to be narrow
Browse files Browse the repository at this point in the history
From Egmont Koblinger:
> In terminal emulation, apps have to be able to print something and
keep track of the cursor, whereas they by design have no idea of the
font being used. In many terminals the font can also be changed runtime
and it's absolutely not feasible to then rearrange the cells. In some
other cases there is no font at all (e.g. the libvterm headless terminal
emulation library, or a detached screen/tmux), or there are multiple
fonts at once (a screen/tmux attached from multiple graphical
emulators).

> The only way to do that is via some external agreement on the number
of cells, which is typically the Unicode EastAsianWidth, often accessed
via wcwidth(). It's not perfect (changes through Unicode versions, has
ambiguous characters, etc.) but is still the best we have.

> glibc's wcwidth() reports 1 for ambiguous width characters, so the de
facto standard is that in terminals they are narrow.

> If the glyph is wider then the terminal has to figure out what to do.
It could crop it (newer versions of Konsole, as far as I know), overflow
to the right (VTE), shrink it (Kitty I believe does this), etc.

See Also:
https://bugzilla.gnome.org/show_bug.cgi?id=767529
https://gitlab.freedesktop.org/terminal-wg/specifications/issues/9
https://www.unicode.org/reports/tr11/tr11-34.html

Salient point from proposed update to Unicode Standard Annex #11:
> Note: The East_Asian_Width property is not intended for use by modern
terminal emulators without appropriate tailoring on a case-by-case
basis.

Fixes #2066
Fixes #2375
  • Loading branch information
DHowett committed Sep 27, 2019
1 parent 86c9e58 commit c2a0d19
Showing 1 changed file with 20 additions and 5 deletions.
25 changes: 20 additions & 5 deletions src/cascadia/TerminalControl/TermControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,25 @@ using namespace winrt::Microsoft::Terminal::Settings;

namespace winrt::Microsoft::Terminal::TerminalControl::implementation
{
// Helper static function to ensure that all ambiguous-width glyphs are reported as narrow.
// See microsoft/terminal#2066 for more info.
static bool _IsGlyphWideForceNarrowFallback(const std::wstring_view /* glyph */)
{
return false; // glyph is not wide.
}

static bool _EnsureStaticInitialization()
{
// use C++11 magic statics to make sure we only do this once.
static bool initialized = []() {
// *** THIS IS A SINGLETON ***
SetGlyphWidthFallback(_IsGlyphWideForceNarrowFallback);

return true;
}();
return initialized;
}

TermControl::TermControl() :
TermControl(Settings::TerminalSettings{}, TerminalConnection::ITerminalConnection{ nullptr })
{
Expand All @@ -47,6 +66,7 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
_lastMouseClick{},
_lastMouseClickPos{}
{
_EnsureStaticInitialization();
_Create();
}

Expand Down Expand Up @@ -413,11 +433,6 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation
auto dxEngine = std::make_unique<::Microsoft::Console::Render::DxEngine>();
_renderer->AddRenderEngine(dxEngine.get());

// Set up the renderer to be used to calculate the width of a glyph,
// should we be unable to figure out its width another way.
auto pfn = std::bind(&::Microsoft::Console::Render::Renderer::IsGlyphWideByFont, _renderer.get(), std::placeholders::_1);
SetGlyphWidthFallback(pfn);

// Initialize our font with the renderer
// We don't have to care about DPI. We'll get a change message immediately if it's not 96
// and react accordingly.
Expand Down

0 comments on commit c2a0d19

Please sign in to comment.