Fixes #4387. Runes should not be used on a cell, but rather should use a single grapheme rendering 1 or 2 columns (#4388)

* Fixes #4382. StringExtensions.GetColumns method should only return the total text width and not the sum of all runes width

* Trying to fix unit test error

* Update StringExtensions.cs

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

* Resolving merge conflicts

* Prevents Runes throwing if Grapheme is null

* Add unit test to prove that null and empty string doesn't not throws anything.

* Fix unit test failure

* Fix IsValidLocation for wide graphemes

* Add more combining

* Prevent set invalid graphemes

* Fix unit tests

* Grapheme doesn't support invalid code points like lone surrogates

* Fixes more unit tests

* Fix unit test

* Seems all test are fixed now

* Adjust CharMap scenario with graphemes

* Upgrade Wcwidth to version 4.0.0

* Reformat

* Trying fix CheckDefaultState assertion

* Revert "Trying fix CheckDefaultState assertion"

This reverts commit c9b46b796a.

* Forgot to include driver.End in the test

* Reapply "Trying fix CheckDefaultState assertion"

This reverts commit 1060ac9b63.

* Remove ToString

* Fix merge errors

* Change to conditional expression

* Assertion to prove that no exception throws during cell initialization.

* Remove unnecessary assignment

* Remove assignment to end

* Replace string concatenation with 'StringBuilder'.

* Replace more string concatenation with 'StringBuilder'

* Remove redundant call to 'ToString' because Rune cast to a String object.

* Replace foreach loop with Sum linq

---------

Co-authored-by: Tig <tig@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
BDisp
2025-11-20 18:45:13 +00:00
committed by GitHub
parent 726b15dd28
commit cd75a20c60
53 changed files with 2654 additions and 2145 deletions

View File

@@ -16,7 +16,8 @@ public class CombiningMarks : Scenario
Application.Current!.SetNeedsDraw ();
var i = -1;
top.AddStr ("Terminal.Gui only supports combining marks that normalize. See Issue #2616.");
top.Move (0, ++i);
top.AddStr ("Terminal.Gui supports all combining sequences that can be rendered as an unique grapheme.");
top.Move (0, ++i);
top.AddStr ("\u0301<- \"\\u0301\" using AddStr.");
top.Move (0, ++i);
@@ -38,7 +39,7 @@ public class CombiningMarks : Scenario
top.AddRune ('\u0301');
top.AddRune ('\u0328');
top.AddRune (']');
top.AddStr ("<- \"[a\\u0301\\u0301\\u0328]\" using AddRune for each.");
top.AddStr ("<- \"[a\\u0301\\u0301\\u0328]\" using AddRune for each. Avoid use AddRune for combining sequences because may result with empty blocks at end.");
top.Move (0, ++i);
top.AddStr ("[a\u0301\u0301\u0328]<- \"[a\\u0301\\u0301\\u0328]\" using AddStr.");
top.Move (0, ++i);
@@ -82,6 +83,16 @@ public class CombiningMarks : Scenario
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.");
top.Move (0, ++i);
top.AddStr ("[\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466]<- \"[\\U0001F468\\u200D\\U0001F469\\u200D\\U0001F467\\u200D\\U0001F466]\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("[\u0e32\u0e33]<- \"[\\u0e32\\u0e33]\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("[\U0001F469\u200D\u2764\uFE0F\u200D\U0001F48B\u200D\U0001F468]<- \"[\\U0001F469\\u200D\\u2764\\uFE0F\\u200D\\U0001F48B\\u200D\\U0001F468]\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("[\u0061\uFE20\u0065\uFE21]<- \"[\\u0061\\uFE20\\u0065\\uFE21]\" using AddStr.");
top.Move (0, ++i);
top.AddStr ("[\u1100\uD7B0]<- \"[\\u1100\\uD7B0]\" using AddStr.");
};
Application.Run (top);

View File

@@ -284,7 +284,7 @@ public class DrawingArea : View
SetCurrentAttribute (c.Value.Value.Attribute ?? GetAttributeForRole (VisualRole.Normal));
// TODO: #2616 - Support combining sequences that don't normalize
AddRune (c.Key.X, c.Key.Y, c.Value.Value.Rune);
AddStr (c.Key.X, c.Key.Y, c.Value.Value.Grapheme);
}
}
}

View File

@@ -86,17 +86,17 @@ public class Sliders : Scenario
{
if (single.Orientation == Orientation.Horizontal)
{
single.Style.SpaceChar = new () { Rune = Glyphs.HLine };
single.Style.OptionChar = new () { Rune = Glyphs.HLine };
single.Style.SpaceChar = new () { Grapheme = Glyphs.HLine.ToString () };
single.Style.OptionChar = new () { Grapheme = Glyphs.HLine.ToString () };
}
else
{
single.Style.SpaceChar = new () { Rune = Glyphs.VLine };
single.Style.OptionChar = new () { Rune = Glyphs.VLine };
single.Style.SpaceChar = new () { Grapheme = Glyphs.VLine.ToString () };
single.Style.OptionChar = new () { Grapheme = Glyphs.VLine.ToString () };
}
};
single.Style.SetChar = new () { Rune = Glyphs.ContinuousMeterSegment };
single.Style.DragChar = new () { Rune = Glyphs.ContinuousMeterSegment };
single.Style.SetChar = new () { Grapheme = Glyphs.ContinuousMeterSegment.ToString () };
single.Style.DragChar = new () { Grapheme = Glyphs.ContinuousMeterSegment.ToString () };
v.Add (single);
@@ -257,7 +257,7 @@ public class Sliders : Scenario
{
s.Orientation = Orientation.Horizontal;
s.Style.SpaceChar = new () { Rune = Glyphs.HLine };
s.Style.SpaceChar = new () { Grapheme = Glyphs.HLine.ToString () };
if (prev == null)
{
@@ -275,7 +275,7 @@ public class Sliders : Scenario
{
s.Orientation = Orientation.Vertical;
s.Style.SpaceChar = new () { Rune = Glyphs.VLine };
s.Style.SpaceChar = new () { Grapheme = Glyphs.VLine.ToString () };
if (prev == null)
{

View File

@@ -152,12 +152,12 @@ public class SyntaxHighlighting : Scenario
),
null,
new (
"_Load Rune Cells",
"_Load Text Cells",
"",
() => ApplyLoadCells ()
),
new (
"_Save Rune Cells",
"_Save Text Cells",
"",
() => SaveCells ()
),
@@ -240,12 +240,9 @@ public class SyntaxHighlighting : Scenario
{
string csName = color.Key;
foreach (Rune rune in csName.EnumerateRunes ())
{
cells.Add (new () { Rune = rune, Attribute = color.Value.Normal });
}
cells.AddRange (Cell.ToCellList (csName, color.Value.Normal));
cells.Add (new () { Rune = (Rune)'\n', Attribute = color.Value.Focus });
cells.Add (new () { Grapheme = "\n", Attribute = color.Value.Focus });
}
if (File.Exists (_path))