mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-28 16:58:01 +01:00
Adjust CharMap scenario with graphemes
This commit is contained in:
@@ -148,10 +148,8 @@ public class CharMap : View, IDesignable
|
||||
break;
|
||||
}
|
||||
|
||||
var rune = new Rune (cp);
|
||||
Span<char> utf16 = new char [2];
|
||||
rune.EncodeToUtf16 (utf16);
|
||||
UnicodeCategory cat = CharUnicodeInfo.GetUnicodeCategory (utf16 [0]);
|
||||
string grapheme = new Rune (cp).ToString ();
|
||||
UnicodeCategory cat = CharUnicodeInfo.GetUnicodeCategory (cp);
|
||||
if (cat == ShowUnicodeCategory.Value)
|
||||
{
|
||||
anyVisible = true;
|
||||
@@ -685,7 +683,7 @@ public class CharMap : View, IDesignable
|
||||
// Don't render out-of-range scalars
|
||||
if (scalar > MAX_CODE_POINT)
|
||||
{
|
||||
AddRune (' ');
|
||||
AddStr (" ");
|
||||
if (visibleRow == selectedRowIndex && col == selectedCol)
|
||||
{
|
||||
SetAttributeForRole (VisualRole.Normal);
|
||||
@@ -693,22 +691,20 @@ public class CharMap : View, IDesignable
|
||||
continue;
|
||||
}
|
||||
|
||||
var rune = (Rune)'?';
|
||||
string grapheme = "?";
|
||||
|
||||
if (Rune.IsValid (scalar))
|
||||
{
|
||||
rune = new (scalar);
|
||||
grapheme = new Rune (scalar).ToString ();
|
||||
}
|
||||
|
||||
int width = rune.GetColumns ();
|
||||
int width = grapheme.GetColumns ();
|
||||
|
||||
// Compute visibility based on ShowUnicodeCategory
|
||||
bool isVisible = Rune.IsValid (scalar);
|
||||
if (isVisible && ShowUnicodeCategory.HasValue)
|
||||
{
|
||||
Span<char> filterUtf16 = new char [2];
|
||||
rune.EncodeToUtf16 (filterUtf16);
|
||||
UnicodeCategory cat = CharUnicodeInfo.GetUnicodeCategory (filterUtf16 [0]);
|
||||
UnicodeCategory cat = CharUnicodeInfo.GetUnicodeCategory (scalar);
|
||||
isVisible = cat == ShowUnicodeCategory.Value;
|
||||
}
|
||||
|
||||
@@ -717,11 +713,11 @@ public class CharMap : View, IDesignable
|
||||
// Glyph row
|
||||
if (isVisible)
|
||||
{
|
||||
RenderRune (rune, width);
|
||||
RenderGrapheme (grapheme, width, scalar);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddRune (' ');
|
||||
AddStr (" ");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -736,7 +732,7 @@ public class CharMap : View, IDesignable
|
||||
}
|
||||
else
|
||||
{
|
||||
AddRune (' ');
|
||||
AddStr (" ");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -750,21 +746,18 @@ public class CharMap : View, IDesignable
|
||||
|
||||
return true;
|
||||
|
||||
void RenderRune (Rune rune, int width)
|
||||
void RenderGrapheme (string grapheme, int width, int scalar)
|
||||
{
|
||||
// Get the UnicodeCategory
|
||||
Span<char> utf16 = new char [2];
|
||||
int charCount = rune.EncodeToUtf16 (utf16);
|
||||
|
||||
// Get the bidi class for the first code unit
|
||||
// For most bidi characters, the first code unit is sufficient
|
||||
UnicodeCategory category = CharUnicodeInfo.GetUnicodeCategory (utf16 [0]);
|
||||
UnicodeCategory category = CharUnicodeInfo.GetUnicodeCategory (scalar);
|
||||
|
||||
switch (category)
|
||||
{
|
||||
case UnicodeCategory.OtherNotAssigned:
|
||||
SetAttributeForRole (VisualRole.Highlight);
|
||||
AddRune (Rune.ReplacementChar);
|
||||
AddStr (Rune.ReplacementChar.ToString ());
|
||||
SetAttributeForRole (VisualRole.Normal);
|
||||
|
||||
break;
|
||||
@@ -773,7 +766,7 @@ public class CharMap : View, IDesignable
|
||||
// These report width of 0 and don't render on their own.
|
||||
case UnicodeCategory.Format:
|
||||
SetAttributeForRole (VisualRole.Highlight);
|
||||
AddRune ('F');
|
||||
AddStr ("F");
|
||||
SetAttributeForRole (VisualRole.Normal);
|
||||
|
||||
break;
|
||||
@@ -786,38 +779,8 @@ public class CharMap : View, IDesignable
|
||||
case UnicodeCategory.EnclosingMark:
|
||||
if (width > 0)
|
||||
{
|
||||
AddRune (rune);
|
||||
AddStr (grapheme);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rune.IsCombiningMark ())
|
||||
{
|
||||
// This is a hack to work around the fact that combining marks
|
||||
// a) can't be rendered on their own
|
||||
// b) that don't normalize are not properly supported in
|
||||
// any known terminal (esp Windows/AtlasEngine).
|
||||
// See Issue #2616
|
||||
var sb = new StringBuilder ();
|
||||
sb.Append ('a');
|
||||
sb.Append (rune);
|
||||
|
||||
// Try normalizing after combining with 'a'. If it normalizes, at least
|
||||
// it'll show on the 'a'. If not, just show the replacement char.
|
||||
string normal = sb.ToString ().Normalize (NormalizationForm.FormC);
|
||||
|
||||
if (normal.Length == 1)
|
||||
{
|
||||
AddRune ((Rune)normal [0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetAttributeForRole (VisualRole.Highlight);
|
||||
AddRune ('M');
|
||||
SetAttributeForRole (VisualRole.Normal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
// These report width of 0, but render as 1
|
||||
@@ -825,20 +788,28 @@ public class CharMap : View, IDesignable
|
||||
case UnicodeCategory.LineSeparator:
|
||||
case UnicodeCategory.ParagraphSeparator:
|
||||
case UnicodeCategory.Surrogate:
|
||||
AddRune (rune);
|
||||
AddStr (grapheme);
|
||||
|
||||
break;
|
||||
case UnicodeCategory.OtherLetter:
|
||||
AddStr (grapheme);
|
||||
|
||||
if (width == 0)
|
||||
{
|
||||
AddStr (" ");
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
|
||||
// Draw the rune
|
||||
if (width > 0)
|
||||
{
|
||||
AddRune (rune);
|
||||
AddStr (grapheme);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException ($"The Rune \"{rune}\" (U+{rune.Value:x6}) has zero width and no special-case UnicodeCategory logic applies.");
|
||||
throw new InvalidOperationException ($"The Rune \"{grapheme}\" (U+{Rune.GetRuneAt (grapheme, 0).Value:x6}) has zero width and no special-case UnicodeCategory logic applies.");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user