From 06767193fb8eec918ed10543906e1f6550f699a7 Mon Sep 17 00:00:00 2001 From: BDisp Date: Fri, 5 Dec 2025 00:11:59 +0000 Subject: [PATCH] Fixes #4440. TextView with ReadOnly as true, MoveRight doesn't select text up to the end of the line (#4441) * Fixes #4440. TextView with ReadOnly as true, MoveRight doesn't select text up to the end of the line * Each character must return at least one column, with the exception of Tab. * Add unit test for the LeftColumn --- Terminal.Gui/Views/TextInput/TextModel.cs | 7 +++- Terminal.Gui/Views/TextInput/TextView.cs | 2 +- .../Views/TextViewTests.cs | 39 +++++++++++++++++++ 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/Terminal.Gui/Views/TextInput/TextModel.cs b/Terminal.Gui/Views/TextInput/TextModel.cs index 296c39579..e350c0c1d 100644 --- a/Terminal.Gui/Views/TextInput/TextModel.cs +++ b/Terminal.Gui/Views/TextInput/TextModel.cs @@ -616,7 +616,8 @@ internal class TextModel for (; i < tCount; i++) { string text = t [i]; - size += text.GetColumns (false); + int colWidth = text.GetColumns (false); + size += colWidth; len += text.Length; if (text == "\t") @@ -624,6 +625,10 @@ internal class TextModel size += tabWidth + 1; len += tabWidth - 1; } + else if (colWidth == -1) + { + size += 2; // -1+2=1 + } if (checkNextRune && i == tCount - 1 && t.Count > tCount && IsWideText (t [i + 1], tabWidth, out int s, out int l)) { diff --git a/Terminal.Gui/Views/TextInput/TextView.cs b/Terminal.Gui/Views/TextInput/TextView.cs index b16c85da3..1ad6494b0 100644 --- a/Terminal.Gui/Views/TextInput/TextView.cs +++ b/Terminal.Gui/Views/TextInput/TextView.cs @@ -3654,7 +3654,7 @@ public class TextView : View, IDesignable { List currentLine = GetCurrentLine (); - if ((ReadOnly ? CurrentColumn + 1 : CurrentColumn) < currentLine.Count) + if (CurrentColumn < currentLine.Count) { CurrentColumn++; } diff --git a/Tests/UnitTestsParallelizable/Views/TextViewTests.cs b/Tests/UnitTestsParallelizable/Views/TextViewTests.cs index 4618865cd..ec7ba27f3 100644 --- a/Tests/UnitTestsParallelizable/Views/TextViewTests.cs +++ b/Tests/UnitTestsParallelizable/Views/TextViewTests.cs @@ -2405,5 +2405,44 @@ public class TextViewTests Assert.Equal (expectedText, tv.SelectedText); } + [Fact] + public void ReadOnly_True_Move_Right_Moves_Until_The_End_Of_Text_More_One_Column () + { + TextView tv = CreateTextView (); + tv.Text = "Hi"; + tv.ReadOnly = true; + + Assert.Equal (0, tv.CurrentColumn); + + Assert.True (tv.NewKeyDownEvent (Key.CursorRight.WithShift)); + Assert.Equal (1, tv.CurrentColumn); + Assert.Equal ("H", tv.SelectedText); + + Assert.True (tv.NewKeyDownEvent (Key.CursorRight.WithShift)); + Assert.Equal (2, tv.CurrentColumn); + Assert.Equal ("Hi", tv.SelectedText); + } + + [Fact] + public void LeftColumn_Treat_Negative_Width_As_One_Column () + { + TextView tv = new () { Width = 2, Height = 1, Text = "\u001B[" }; + + Assert.Equal (0, tv.LeftColumn); + Assert.Equal (new (0, 0), tv.CursorPosition); + + Assert.True (tv.NewKeyDownEvent (Key.CursorRight)); + Assert.Equal (0, tv.LeftColumn); + Assert.Equal (new (1, 0), tv.CursorPosition); + + Assert.True (tv.NewKeyDownEvent (Key.CursorRight)); + Assert.Equal (1, tv.LeftColumn); + Assert.Equal (new (2, 0), tv.CursorPosition); + + Assert.False (tv.NewKeyDownEvent (Key.CursorRight)); + Assert.Equal (1, tv.LeftColumn); + Assert.Equal (new (2, 0), tv.CursorPosition); + } + private TextView CreateTextView () { return new () { Width = 30, Height = 10 }; } }