Files
Terminal.Gui/Examples/UICatalog/Scenarios/CombiningMarks.cs
Tig 4c6145cee9 Fixes #4233 - CharMap rendering (#4255)
* Fixed almost all issues

* code comments

* fixed copilot suggestion

* Add Unicode filtering and improve context menu handling

Enabled nullable reference types for better null safety. Added a
Unicode category filter to `CharacterMap` via the new
`ShowUnicodeCategory` property and `OptionSelector`. Updated
rendering logic to dynamically manage visible rows based on the
filter, improving performance and usability.

Refactored menu items to include the Unicode category selector.
Enhanced `TextView` context menu handling to support mouse-based
positioning. Performed miscellaneous code cleanup and added
comments for improved readability and maintainability.

* Fix Unicode rendering and simplify CombiningMarks

Updated `RuneExtensions.GetColumns` to handle specific Unicode glyphs (I Ching symbols) rendered as double-width in Windows Terminal, despite being single-width per Unicode. Added a workaround to return `2` for these glyphs and fallback to `UnicodeCalculator.GetWidth` for others.

Simplified `CombiningMarks` by removing examples for Unicode characters `\u0600` and `\u0301`, streamlining the scenario.

Referenced PR #4255 for context on the workaround.

* Update RuneTests with new Unicode test cases and fixes

Added new test cases for Unicode characters U+d7b0 (ힰ) and
U+f61e () with expected parameters. Updated the test case
for U+4dc0 (䷀) to adjust the second parameter from 1 to 2
and added references to the Microsoft Terminal Unicode
width overrides file and GitHub issue #19389. Existing test
cases for other Unicode characters remain unchanged.

* Update Terminal.Gui/Views/CharMap/CharMap.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update comments in GetColumns method for clarity

Updated comments in the `GetColumns` method of the `RuneExtensions` class to replace "HACK" with "TODO" and reference issue #4259 instead of pull request #4255. This change clarifies that the code is a temporary measure and should be removed once the issue is resolved. No functional changes were made to the code logic.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-27 13:26:44 -06:00

92 lines
4.4 KiB
C#

namespace UICatalog.Scenarios;
[ScenarioMetadata ("Combining Marks", "Illustrates how Unicode Combining Marks work (or don't).")]
[ScenarioCategory ("Text and Formatting")]
public class CombiningMarks : Scenario
{
public override void Main ()
{
Application.Init ();
var top = new Toplevel ();
top.DrawComplete += (s, e) =>
{
// Forces reset _lineColsOffset because we're dealing with direct draw
Application.ClearScreenNextIteration = true;
var i = -1;
top.AddStr ("Terminal.Gui only supports combining marks that normalize. See Issue #2616.");
top.Move (0, ++i);
top.AddStr ("\u0301<- \"\\u0301\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("[\u0301]<- \"[\\u0301]\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("[ \u0301]<- \"[ \\u0301]\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("[\u0301 ]<- \"[\\u0301 ]\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("\u0301\u0301\u0328<- \"\\u0301\\u0301\\u0328\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("[\u0301\u0301\u0328]<- \"[\\u0301\\u0301\\u0328]\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("[a\u0301\u0301\u0328]<- \"[a\\u0301\\u0301\\u0328]\" using AddStr.");
top.Move (0, ++i);
top.AddRune ('[');
top.AddRune ('a');
top.AddRune ('\u0301');
top.AddRune ('\u0301');
top.AddRune ('\u0328');
top.AddRune (']');
top.AddStr ("<- \"[a\\u0301\\u0301\\u0328]\" using AddRune for each.");
top.Move (0, ++i);
top.AddStr ("[a\u0301\u0301\u0328]<- \"[a\\u0301\\u0301\\u0328]\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("[e\u0301\u0301\u0328]<- \"[e\\u0301\\u0301\\u0328]\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("[e\u0328\u0301]<- \"[e\\u0328\\u0301]\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("\u00ad<- \"\\u00ad\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("[\u00ad]<- \"[\\u00ad]\" using AddStr.");
top.Move (0, ++i);
top.AddRune ('[');
top.AddRune ('\u00ad');
top.AddRune (']');
top.AddStr ("<- \"[\\u00ad]\" using AddRune for each.");
i++;
top.Move (0, ++i);
top.AddStr ("From now on we are using TextFormatter");
TextFormatter tf = new () { Text = "[e\u0301\u0301\u0328]<- \"[e\\u0301\\u0301\\u0328]\" using TextFormatter." };
tf.Draw (new (0, ++i, tf.Text.Length, 1), top.GetAttributeForRole (VisualRole.Normal), top.GetAttributeForRole (VisualRole.Normal));
tf.Text = "[e\u0328\u0301]<- \"[e\\u0328\\u0301]\" using TextFormatter.";
tf.Draw (new (0, ++i, tf.Text.Length, 1), top.GetAttributeForRole (VisualRole.Normal), top.GetAttributeForRole (VisualRole.Normal));
i++;
top.Move (0, ++i);
top.AddStr ("From now on we are using Surrogate pairs with combining diacritics");
top.Move (0, ++i);
top.AddStr ("[\ud835\udc4b\u0302]<- \"[\\ud835\\udc4b\\u0302]\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("[\ud83d\udc68\ud83e\uddd2]<- \"[\\ud83d\\udc68\\ud83e\\uddd2]\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("\u200d<- \"\\u200d\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("[\u200d]<- \"[\\u200d]\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("[\ud83d\udc68\u200d\ud83e\uddd2]<- \"[\\ud83d\\udc68\\u200d\\ud83e\\uddd2]\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("[\U0001F469\U0001F9D2]<- \"[\\U0001F469\\U0001F9D2]\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("[\U0001F469\u200D\U0001F9D2]<- \"[\\U0001F469\\u200D\\U0001F9D2]\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("[\U0001F468\U0001F469\U0001F9D2]<- \"[\\U0001F468\\U0001F469\\U0001F9D2]\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("[\U0001F468\u200D\U0001F469\u200D\U0001F9D2]<- \"[\\U0001F468\\u200D\\U0001F469\\u200D\\U0001F9D2]\" using AddStr.");
};
Application.Run (top);
top.Dispose ();
Application.Shutdown ();
}
}