Skip to content

Commit

Permalink
Fixes gui-cs#3873. TextFormatter isn't properly handling combining ma…
Browse files Browse the repository at this point in the history
…rks on alignments. (gui-cs#3874)

Co-authored-by: Tig <tig@users.noreply.github.com>
  • Loading branch information
BDisp and tig authored Dec 5, 2024
1 parent 287e050 commit dbfe521
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 6 deletions.
12 changes: 6 additions & 6 deletions Terminal.Gui/Text/TextFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1411,7 +1411,7 @@ public static string ClipAndJustify (

if (textFormatter is { Alignment: Alignment.Center })
{
return GetRangeThatFits (runes, Math.Max ((runes.Count - width) / 2, 0), text, width, tabWidth, textDirection);
return GetRangeThatFits (runes, Math.Max ((runes.Count - width - zeroLength) / 2, 0), text, width, tabWidth, textDirection);
}

return GetRangeThatFits (runes, 0, text, width, tabWidth, textDirection);
Expand All @@ -1426,7 +1426,7 @@ public static string ClipAndJustify (

if (textFormatter is { VerticalAlignment: Alignment.Center })
{
return GetRangeThatFits (runes, Math.Max ((runes.Count - width) / 2, 0), text, width, tabWidth, textDirection);
return GetRangeThatFits (runes, Math.Max ((runes.Count - width - zeroLength) / 2, 0), text, width, tabWidth, textDirection);
}

return GetRangeThatFits (runes, 0, text, width, tabWidth, textDirection);
Expand All @@ -1451,7 +1451,7 @@ public static string ClipAndJustify (
}
else if (textFormatter is { Alignment: Alignment.Center })
{
return GetRangeThatFits (runes, Math.Max ((runes.Count - width) / 2, 0), text, width, tabWidth, textDirection);
return GetRangeThatFits (runes, Math.Max ((runes.Count - width - zeroLength) / 2, 0), text, width, tabWidth, textDirection);
}
else if (GetRuneWidth (text, tabWidth, textDirection) > width)
{
Expand All @@ -1470,7 +1470,7 @@ public static string ClipAndJustify (
}
else if (textFormatter is { VerticalAlignment: Alignment.Center })
{
return GetRangeThatFits (runes, Math.Max ((runes.Count - width) / 2, 0), text, width, tabWidth, textDirection);
return GetRangeThatFits (runes, Math.Max ((runes.Count - width - zeroLength) / 2, 0), text, width, tabWidth, textDirection);
}
else if (runes.Count - zeroLength > width)
{
Expand Down Expand Up @@ -1526,7 +1526,7 @@ public static string Justify (
}
else
{
textCount = words.Sum (arg => arg.GetRuneCount ());
textCount = words.Sum (arg => arg.GetRuneCount ()) - text.EnumerateRunes ().Sum (r => r.GetColumns () == 0 ? 1 : 0);
}

int spaces = words.Length > 1 ? (width - textCount) / (words.Length - 1) : 0;
Expand Down Expand Up @@ -1936,7 +1936,7 @@ private static int GetRuneWidth (List<Rune> runes, int tabWidth, TextDirection t

private static int GetRuneWidth (Rune rune, int tabWidth, TextDirection textDirection = TextDirection.LeftRight_TopBottom)
{
int runeWidth = IsHorizontalDirection (textDirection) ? rune.GetColumns () : 1;
int runeWidth = IsHorizontalDirection (textDirection) ? rune.GetColumns () : rune.GetColumns () == 0 ? 0 : 1;

if (rune.Value == '\t')
{
Expand Down
84 changes: 84 additions & 0 deletions UnitTests/Text/TextFormatterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4629,6 +4629,90 @@ string expectedWrappedText
Assert.Equal (expectedWrappedText, wrappedText);
}

[Theory]
[InlineData (
"Les Mise\u0301rables",
14,
-1,
false,
new [] { "Les Misérables" },
"Les Misérables"
)]
[InlineData (
"Les Mise\u0328\u0301rables",
14,
-2,
false,
new [] { "Les Misę́rables" },
"Les Misę́rables"
)]
public void Format_Combining_Marks_Alignments (
string text,
int maxWidth,
int widthOffset,
bool wrap,
IEnumerable<string> resultLines,
string expectedText
)
{
Assert.Equal (maxWidth, text.GetRuneCount () + widthOffset);

// Horizontal text direction
foreach (Alignment alignment in Enum.GetValues (typeof (Alignment)))
{
TextFormatter tf = new () { Text = text, ConstrainToSize = new (maxWidth, 1), WordWrap = wrap, Alignment = alignment };

List<string> list = TextFormatter.Format (
text,
maxWidth,
alignment,
wrap,
tf.PreserveTrailingSpaces,
tf.TabWidth,
tf.Direction,
tf.MultiLine,
tf);
Assert.Equal (list.Count, resultLines.Count ());
Assert.Equal (resultLines, list);
var formattedText = string.Empty;

foreach (string txt in list)
{
formattedText += txt;
}

Assert.Equal (expectedText, formattedText);
}

// Vertical text direction
foreach (Alignment alignment in Enum.GetValues (typeof (Alignment)))
{
TextFormatter tf = new ()
{ Text = text, ConstrainToSize = new (1, maxWidth), WordWrap = wrap, VerticalAlignment = alignment, Direction = TextDirection.TopBottom_LeftRight };

List<string> list = TextFormatter.Format (
text,
maxWidth,
alignment,
wrap,
tf.PreserveTrailingSpaces,
tf.TabWidth,
tf.Direction,
tf.MultiLine,
tf);
Assert.Equal (list.Count, resultLines.Count ());
Assert.Equal (resultLines, list);
var formattedText = string.Empty;

foreach (string txt in list)
{
formattedText += txt;
}

Assert.Equal (expectedText, formattedText);
}
}

public static IEnumerable<object []> FormatEnvironmentNewLine =>
new List<object []>
{
Expand Down

0 comments on commit dbfe521

Please sign in to comment.