diff --git a/Terminal.Gui/Core/TextFormatter.cs b/Terminal.Gui/Core/TextFormatter.cs
index 6a8512272..1cfaf62d7 100644
--- a/Terminal.Gui/Core/TextFormatter.cs
+++ b/Terminal.Gui/Core/TextFormatter.cs
@@ -196,7 +196,7 @@ namespace Terminal.Gui {
///
/// Formats the provided text to fit within the width provided using word wrapping.
///
- /// The text to word warp
+ /// The text to word wrap
/// The width to contrain the text to
/// Returns a list of word wrapped lines.
///
@@ -204,7 +204,7 @@ namespace Terminal.Gui {
/// This method does not do any justification.
///
///
- /// Newlines ('\n' and '\r\n') sequences are honored, adding the appropriate lines to the output.
+ /// This method strips Newline ('\n' and '\r\n') sequences before processing.
///
///
public static List WordWrap (ustring text, int width)
@@ -351,7 +351,7 @@ namespace Terminal.Gui {
int runeCount = runes.Count;
int lp = 0;
for (int i = 0; i < runeCount; i++) {
- Rune c = text [i];
+ Rune c = runes [i];
if (c == '\n') {
var wrappedLines = WordWrap (ustring.Make (runes.GetRange (lp, i - lp)), width);
foreach (var line in wrappedLines) {
diff --git a/UICatalog/Scenarios/TextFormatterDemo.cs b/UICatalog/Scenarios/TextFormatterDemo.cs
index f665f8b4a..dcadba536 100644
--- a/UICatalog/Scenarios/TextFormatterDemo.cs
+++ b/UICatalog/Scenarios/TextFormatterDemo.cs
@@ -1,4 +1,5 @@
-using System;
+using NStack;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -26,17 +27,19 @@ namespace UICatalog {
string text = "Hello world, how are you today? Pretty neat!\nSecond line\n\nFourth Line.";
string unicode = "Τὴ γλῶσσα μοῦ ἔδωσαν ἑλληνικὴ\nτὸ σπίτι φτωχικὸ στὶς ἀμμουδιὲς τοῦ Ὁμήρου.\nΜονάχη ἔγνοια ἡ γλῶσσα μου στὶς ἀμμουδιὲς τοῦ Ὁμήρου.";
- Label blockText = new Label () { ColorScheme = Colors.TopLevel, X = 0, Y = 3, Height = 7, Width = Dim.Fill (0) };
+ Label blockText = new Label () { ColorScheme = Colors.TopLevel, X = 0, Y = 0, Height = 10, Width = Dim.Fill (0) };
var block = new StringBuilder ();
- block.AppendLine (" _/ ");
- block.AppendLine (" _/_/_/ _/ _/ _/_/_/ _/_/_/");
- block.AppendLine (" _/ _/ _/ _/ _/ _/ _/_/ ");
- block.AppendLine (" _/ _/ _/ _/ _/ _/ _/_/ ");
- block.AppendLine (" _/_/_/ _/_/_/ _/ _/ _/_/_/ _/_/_/ ");
- block.AppendLine (" _/ ");
- block.AppendLine ("_ /_/ ");
- blockText.Text = block.ToString ();
+ block.AppendLine (" ▄████ █ ██ ██▓ ▄████▄ ██████ ");
+ block.AppendLine (" ██▒ ▀█▒ ██ ▓██▒▓██▒ ▒██▀ ▀█ ▒██ ▒ ");
+ block.AppendLine ("▒██░▄▄▄░▓██ ▒██░▒██▒ ▒▓█ ▄ ░ ▓██▄ ");
+ block.AppendLine ("░▓█ ██▓▓▓█ ░██░░██░ ▒▓▓▄ ▄██▒ ▒ ██▒");
+ block.AppendLine ("░▒▓███▀▒▒▒█████▓ ░██░ ██▓ ▒ ▓███▀ ░▒██████▒▒");
+ block.AppendLine (" ░▒ ▒ ░▒▓▒ ▒ ▒ ░▓ ▒▓▒ ░ ░▒ ▒ ░▒ ▒▓▒ ▒ ░");
+ block.AppendLine (" ░ ░ ░░▒░ ░ ░ ▒ ░ ░▒ ░ ▒ ░ ░▒ ░ ░");
+ block.AppendLine ("░ ░ ░ ░░░ ░ ░ ▒ ░ ░ ░ ░ ░ ░ ");
+ block.AppendLine (" ░ ░ ░ ░ ░ ░ ░ ");
+ block.AppendLine (" ░ ░ "); blockText.Text = ustring.Make (block.ToString ()); // .Replace(" ", "\u00A0"); // \u00A0 is 'non-breaking space
Win.Add (blockText);
var unicodeCheckBox = new CheckBox ("Unicode", Top.HotKeySpecifier == (Rune)' ') {
diff --git a/UnitTests/TextFormatterTests.cs b/UnitTests/TextFormatterTests.cs
index 1b20ff744..17200127b 100644
--- a/UnitTests/TextFormatterTests.cs
+++ b/UnitTests/TextFormatterTests.cs
@@ -1559,6 +1559,84 @@ namespace Terminal.Gui {
Assert.Equal ("ำ", wrappedLines [^1].ToString ());
}
+ [Fact]
+ public void WordWrap_Unicode_LineWithNonBreakingSpace ()
+ {
+ var text = ustring.Empty;
+ int width = 0;
+ List wrappedLines;
+
+ text = "This\u00A0is\u00A0a\u00A0sentence.";
+ width = text.RuneCount;
+ wrappedLines = TextFormatter.WordWrap (text, width);
+ Assert.True (wrappedLines.Count == 1);
+
+ width = text.RuneCount - 1;
+ wrappedLines = TextFormatter.WordWrap (text, width);
+ Assert.Equal (2, wrappedLines.Count);
+ Assert.Equal (ustring.Make (text.ToRunes () [0..(text.RuneCount - 1)]).ToString (), wrappedLines [0].ToString ());
+ Assert.Equal (".", wrappedLines [1].ToString ());
+
+ width = text.RuneCount - 2;
+ wrappedLines = TextFormatter.WordWrap (text, width);
+ Assert.Equal (2, wrappedLines.Count);
+ Assert.Equal (ustring.Make (text.ToRunes () [0..(text.RuneCount - 2)]).ToString (), wrappedLines [0].ToString ());
+
+ width = text.RuneCount - 5;
+ wrappedLines = TextFormatter.WordWrap (text, width);
+ Assert.Equal (2, wrappedLines.Count);
+
+ width = (int)Math.Ceiling ((double)(text.RuneCount / 2F));
+ wrappedLines = TextFormatter.WordWrap (text, width);
+ Assert.Equal (2, wrappedLines.Count);
+ Assert.Equal ("This\u00A0is\u00A0a\u00A0", wrappedLines [0].ToString ());
+ Assert.Equal ("sentence.", wrappedLines [1].ToString ());
+
+ width = (int)Math.Ceiling ((double)(text.RuneCount / 3F));
+ wrappedLines = TextFormatter.WordWrap (text, width);
+ Assert.Equal (3, wrappedLines.Count);
+ Assert.Equal ("This\u00A0is", wrappedLines [0].ToString ());
+ Assert.Equal ("\u00a0a\u00a0sent", wrappedLines [1].ToString ());
+ Assert.Equal ("ence.", wrappedLines [2].ToString ());
+
+ width = (int)Math.Ceiling ((double)(text.RuneCount / 4F));
+ wrappedLines = TextFormatter.WordWrap (text, width);
+ Assert.Equal (4, wrappedLines.Count);
+
+ width = (int)Math.Ceiling ((double)text.RuneCount / text.RuneCount);
+ wrappedLines = TextFormatter.WordWrap (text, width);
+ Assert.Equal (text.RuneCount, wrappedLines.Count);
+ Assert.Equal ("T", wrappedLines [0].ToString ());
+ Assert.Equal ("h", wrappedLines [1].ToString ());
+ Assert.Equal ("i", wrappedLines [2].ToString ());
+ Assert.Equal (".", wrappedLines [^1].ToString ());
+ }
+
+ [Fact]
+ public void WordWrap_Unicode_2LinesWithNonBreakingSpace ()
+ {
+ var text = ustring.Empty;
+ int width = 0;
+ List wrappedLines;
+
+ text = "This\u00A0is\n\u00A0a\u00A0sentence.";
+ width = text.RuneCount;
+ wrappedLines = TextFormatter.WordWrap (text, width);
+ Assert.True (wrappedLines.Count == 1);
+
+ width = text.RuneCount - 1;
+ wrappedLines = TextFormatter.WordWrap (text, width);
+#pragma warning disable xUnit2013 // Do not use equality check to check for collection size.
+ Assert.Equal (1, wrappedLines.Count);
+#pragma warning restore xUnit2013 // Do not use equality check to check for collection size.
+ Assert.Equal ("This\u00A0is\u00A0a\u00A0sentence.", wrappedLines [0].ToString ());
+
+ text = "\u00A0\u00A0\u00A0\u00A0\u00A0test\u00A0sentence.";
+ width = text.RuneCount;
+ wrappedLines = TextFormatter.WordWrap (text, width);
+ Assert.True (wrappedLines.Count == 1);
+ }
+
[Fact]
public void WordWrap_NoNewLines ()
{
@@ -1658,6 +1736,87 @@ namespace Terminal.Gui {
Assert.Equal ("(пÑивеÑ) has words.", wrappedLines [1].ToString ());
}
+ ///
+ /// WordWrap strips CRLF
+ ///
+ [Fact]
+ public void WordWrap_WithNewLines ()
+ {
+ var text = ustring.Empty;
+ int maxWidth = 0;
+ int expectedClippedWidth = 0;
+
+ List wrappedLines;
+
+ text = "A sentence has words.\nA paragraph has lines.";
+ maxWidth = text.RuneCount;
+ expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
+ wrappedLines = TextFormatter.WordWrap (text, maxWidth);
+#pragma warning disable xUnit2013 // Do not use equality check to check for collection size.
+ Assert.Equal (1, wrappedLines.Count);
+#pragma warning restore xUnit2013 // Do not use equality check to check for collection size.
+ Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
+ Assert.Equal ("A sentence has words.A paragraph has lines.", wrappedLines [0].ToString ());
+
+ maxWidth = text.RuneCount - 1;
+ expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
+ wrappedLines = TextFormatter.WordWrap (text, maxWidth);
+#pragma warning disable xUnit2013 // Do not use equality check to check for collection size.
+ Assert.Equal (1, wrappedLines.Count);
+#pragma warning restore xUnit2013 // Do not use equality check to check for collection size.
+ Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
+ Assert.Equal ("A sentence has words.A paragraph has lines.", wrappedLines [0].ToString ());
+
+ maxWidth = text.RuneCount - "words.".Length;
+ expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
+ wrappedLines = TextFormatter.WordWrap (text, maxWidth);
+ Assert.Equal (2, wrappedLines.Count);
+ Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
+ Assert.Equal ("A sentence has words.A paragraph has", wrappedLines [0].ToString ());
+ Assert.Equal ("lines.", wrappedLines [1].ToString ());
+
+ // Unicode
+ text = "A Unicode sentence (пÑивеÑ) has words.A Unicode Пункт has Линии.";
+ maxWidth = text.RuneCount;
+ expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
+ wrappedLines = TextFormatter.WordWrap (text, maxWidth);
+ Assert.True (wrappedLines.Count == 1);
+ Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
+ Assert.Equal ("A Unicode sentence (пÑивеÑ) has words.A Unicode Пункт has Линии.", wrappedLines [0].ToString ());
+
+ maxWidth = text.RuneCount - 1;
+ expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
+ wrappedLines = TextFormatter.WordWrap (text, maxWidth);
+ Assert.Equal (2, wrappedLines.Count);
+ Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
+ Assert.Equal ("A Unicode sentence (пÑивеÑ) has words.A Unicode Пункт has", wrappedLines [0].ToString ());
+ Assert.Equal ("Линии.", wrappedLines [1].ToString ());
+
+ maxWidth = text.RuneCount - "words.".Length;
+ expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
+ wrappedLines = TextFormatter.WordWrap (text, maxWidth);
+ Assert.Equal (2, wrappedLines.Count);
+ Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
+ Assert.Equal ("A Unicode sentence (пÑивеÑ) has words.A Unicode Пункт has", wrappedLines [0].ToString ());
+ Assert.Equal ("Линии.", wrappedLines [1].ToString ());
+
+ maxWidth = text.RuneCount - "s words.".Length;
+ expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
+ wrappedLines = TextFormatter.WordWrap (text, maxWidth);
+ Assert.Equal (2, wrappedLines.Count);
+ Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
+ Assert.Equal ("A Unicode sentence (пÑивеÑ) has words.A Unicode Пункт", wrappedLines [0].ToString ());
+ Assert.Equal ("has Линии.", wrappedLines [1].ToString ());
+
+ maxWidth = text.RuneCount - "веÑ) has words.".Length;
+ expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
+ wrappedLines = TextFormatter.WordWrap (text, maxWidth);
+ Assert.Equal (2, wrappedLines.Count);
+ Assert.True (expectedClippedWidth >= wrappedLines.Max (l => l.RuneCount));
+ Assert.Equal ("A Unicode sentence (пÑивеÑ) has words.A Unicode", wrappedLines [0].ToString ());
+ Assert.Equal ("Пункт has Линии.", wrappedLines [1].ToString ());
+ }
+
[Fact]
public void WordWrap_Narrow ()
{
@@ -2001,13 +2160,13 @@ namespace Terminal.Gui {
// Unicode
// Even # of chars
// 0123456789
- text = "пÑРвРÑ";
+ text = "\u2660пÑРвРÑ";
maxWidth = text.RuneCount - 1;
expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
Assert.True (list.Count == 2);
- Assert.Equal ("пÑРвÐ", list [0]);
+ Assert.Equal ("\u2660пÑРвÐ", list [0]);
Assert.Equal ("Ñ", list [1]);
// no clip
@@ -2015,24 +2174,24 @@ namespace Terminal.Gui {
expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
Assert.True (list.Count == 1);
- Assert.Equal ("пÑРвРÑ", list [0]);
+ Assert.Equal ("\u2660пÑРвРÑ", list [0]);
maxWidth = text.RuneCount + 1;
expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
Assert.True (list.Count == 1);
- Assert.Equal ("пÑРвРÑ", list [0]);
+ Assert.Equal ("\u2660пÑРвРÑ", list [0]);
// Unicode
// Odd # of chars
// 0123456789
- text = "Ð ÑРвРÑ";
+ text = "\u2660 ÑРвРÑ";
maxWidth = text.RuneCount - 1;
expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
Assert.True (list.Count == 2);
- Assert.Equal ("Ð ÑРвÐ", list [0]);
+ Assert.Equal ("\u2660 ÑРвÐ", list [0]);
Assert.Equal ("Ñ", list [1]);
// no clip
@@ -2040,14 +2199,48 @@ namespace Terminal.Gui {
expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
Assert.True (list.Count == 1);
- Assert.Equal ("Ð ÑРвРÑ", list [0]);
+ Assert.Equal ("\u2660 ÑРвРÑ", list [0]);
maxWidth = text.RuneCount + 1;
expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
Assert.True (list.Count == 1);
- Assert.Equal ("Ð ÑРвРÑ", list [0]);
+ Assert.Equal ("\u2660 ÑРвРÑ", list [0]);
+ }
+ [Fact]
+ public void Reformat_Unicode_Wrap_Spaces_NewLines ()
+ {
+ var text = ustring.Empty;
+ var list = new List ();
+ var maxWidth = 0;
+ var expectedClippedWidth = 0;
+ var wrap = true;
+
+ // Unicode
+ text = "\u2460\u2461\u2462\n\u2460\u2461\u2462\u2463\u2464";
+
+ maxWidth = text.RuneCount - 1;
+ expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
+ list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
+ Assert.Equal (2, list.Count);
+ Assert.Equal ("\u2460\u2461\u2462", list [0]);
+ Assert.Equal ("\u2460\u2461\u2462\u2463\u2464", list [1]);
+
+ // no clip
+ maxWidth = text.RuneCount + 0;
+ expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
+ list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
+ Assert.Equal (2, list.Count);
+ Assert.Equal ("\u2460\u2461\u2462", list [0]);
+ Assert.Equal ("\u2460\u2461\u2462\u2463\u2464", list [1]);
+
+ maxWidth = text.RuneCount + 1;
+ expectedClippedWidth = Math.Min (text.RuneCount, maxWidth);
+ list = TextFormatter.Format (text, maxWidth, TextAlignment.Left, wrap);
+ Assert.Equal (2, list.Count);
+ Assert.Equal ("\u2460\u2461\u2462", list [0]);
+ Assert.Equal ("\u2460\u2461\u2462\u2463\u2464", list [1]);
}
}
}
\ No newline at end of file