diff --git a/Terminal.Gui/Views/TextField.cs b/Terminal.Gui/Views/TextField.cs index 07389fb4f..f8c4e23da 100644 --- a/Terminal.Gui/Views/TextField.cs +++ b/Terminal.Gui/Views/TextField.cs @@ -1064,8 +1064,8 @@ namespace Terminal.Gui { EnsureHasFocus (); int x = PositionCursor (ev); int sbw = x; - if (x == text.Count || (x > 0 && (char)Text [x - 1] != ' ' - || (x > 0 && (char)Text [x] == ' '))) { + if (x == text.Count || (x > 0 && (char)text [x - 1] != ' ') + || (x > 0 && (char)text [x] == ' ')) { sbw = WordBackward (x); } diff --git a/UnitTests/Views/TextFieldTests.cs b/UnitTests/Views/TextFieldTests.cs index 860cfb68c..1c0ddb34e 100644 --- a/UnitTests/Views/TextFieldTests.cs +++ b/UnitTests/Views/TextFieldTests.cs @@ -1,9 +1,18 @@ -using System; +using NStack; +using System; +using System.Globalization; using System.Reflection; using Xunit; +using Xunit.Abstractions; namespace Terminal.Gui.ViewTests { public class TextFieldTests { + readonly ITestOutputHelper output; + + public TextFieldTests (ITestOutputHelper output) + { + this.output = output; + } // This class enables test functions annotated with the [InitShutdown] attribute // to have a function called before the test function is called and after. @@ -1177,6 +1186,21 @@ namespace Terminal.Gui.ViewTests { Assert.Equal ("-", newText); Assert.Equal ("-1", oldText); Assert.Equal ("-", tf.Text.ToString ()); + + // Delete word with accented char + tf.Text = "Les Misérables movie."; + Assert.True (tf.MouseEvent (new MouseEvent { + X = 7, + Y = 1, + Flags = MouseFlags.Button1DoubleClicked, + View = tf + })); + Assert.Equal ("Misérables ", tf.SelectedText); + Assert.Equal (11, tf.SelectedLength); + Assert.True (tf.ProcessKey (new KeyEvent (Key.Delete, new KeyModifiers ()))); + Assert.Equal ("Les movie.", newText); + Assert.Equal ("Les Misérables movie.", oldText); + Assert.Equal ("Les movie.", tf.Text.ToString ()); } [Fact] @@ -1323,5 +1347,98 @@ namespace Terminal.Gui.ViewTests { Assert.Equal (0, tf.SelectedLength); Assert.Null (tf.SelectedText); } + + + [Fact] + public void WordBackward_WordForward_SelectedText_With_Accent () + { + string text = "Les Misérables movie."; + var tf = new TextField (text) { Width = 30 }; + + Assert.Equal (21, text.Length); + Assert.Equal (21, tf.Text.RuneCount); + Assert.Equal (21, tf.Text.ConsoleWidth); + + var runes = tf.Text.ToRuneList (); + Assert.Equal (21, runes.Count); + Assert.Equal (22, tf.Text.Length); + + for (int i = 0; i < runes.Count; i++) { + var cs = text [i]; + var cus = (char)runes [i]; + Assert.Equal (cs, cus); + } + + var idx = 15; + Assert.Equal ('m', text [idx]); + Assert.Equal ('m', (char)runes [idx]); + Assert.Equal ("m", ustring.Make (runes [idx])); + + Assert.True (tf.MouseEvent (new MouseEvent { + X = idx, + Y = 1, + Flags = MouseFlags.Button1DoubleClicked, + View = tf + })); + Assert.Equal ("movie.", tf.SelectedText); + + Assert.True (tf.MouseEvent (new MouseEvent { + X = idx + 1, + Y = 1, + Flags = MouseFlags.Button1DoubleClicked, + View = tf + })); + Assert.Equal ("movie.", tf.SelectedText); + } + + [Fact, AutoInitShutdown] + public void Words_With_Accents_Incorrect_Order_Will_Result_With_Wrong_Accent_Place () + { + var tf = new TextField ("Les Misérables") { Width = 30 }; + var top = Application.Top; + top.Add (tf); + Application.Begin (top); + + TestHelpers.AssertDriverContentsWithFrameAre (@" +Les Misérables", output); + + tf.Text = "Les Mise" + char.ConvertFromUtf32 (int.Parse ("0301", NumberStyles.HexNumber)) + "rables"; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre (@" +Les Misérables", output); + + // incorrect order will result with a wrong accent place + tf.Text = "Les Mis" + char.ConvertFromUtf32 (int.Parse ("0301", NumberStyles.HexNumber)) + "erables"; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre (@" +Les Miśerables", output); + } + + [Fact, AutoInitShutdown] + public void Accented_Letter_With_Three_Combining_Unicode_Chars () + { + var tf = new TextField ("ắ") { Width = 3 }; + var top = Application.Top; + top.Add (tf); + Application.Begin (top); + + TestHelpers.AssertDriverContentsWithFrameAre (@" +ắ", output); + + tf.Text = "\u1eaf"; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre (@" +ắ", output); + + tf.Text = "\u0103\u0301"; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre (@" +ắ", output); + + tf.Text = "\u0061\u0306\u0301"; + Application.Refresh (); + TestHelpers.AssertDriverContentsWithFrameAre (@" +ắ", output); + } } } \ No newline at end of file