diff --git a/Terminal.Gui/Views/TextField.cs b/Terminal.Gui/Views/TextField.cs index e04397be8..4b7e78b56 100644 --- a/Terminal.Gui/Views/TextField.cs +++ b/Terminal.Gui/Views/TextField.cs @@ -143,6 +143,9 @@ namespace Terminal.Gui { var newText = OnTextChanging (value.Split ("\n") [0]); if (newText.Cancel) { + if (point > text.Count) { + point = text.Count; + } return; } text = TextModel.ToRunes (newText.NewText); @@ -347,7 +350,11 @@ namespace Terminal.Gui { return true; point--; - SetText (text.GetRange (0, oldCursorPos - 1).Concat (text.GetRange (oldCursorPos, text.Count - oldCursorPos))); + if (oldCursorPos < text.Count) { + SetText (text.GetRange (0, oldCursorPos - 1).Concat (text.GetRange (oldCursorPos, text.Count - oldCursorPos))); + } else { + SetText (text.GetRange (0, oldCursorPos - 1)); + } Adjust (); } else { DeleteSelectedText (); diff --git a/UnitTests/TextFieldTests.cs b/UnitTests/TextFieldTests.cs index bedcaf4fb..9b0453411 100644 --- a/UnitTests/TextFieldTests.cs +++ b/UnitTests/TextFieldTests.cs @@ -706,5 +706,72 @@ namespace Terminal.Gui.Views { _textField.ProcessKey (new KeyEvent ((Key)0x64, new KeyModifiers ())); // d Assert.Equal ("TAB to jumusedtween text fields.", _textField.Text); } + + [Fact] + public void ProcessKey_Backspace_From_End () + { + var tf = new TextField ("ABC"); + tf.EnsureFocus (); + Assert.Equal ("ABC", tf.Text); + + // now delete the C + tf.ProcessKey (new KeyEvent (Key.Backspace, new KeyModifiers ())); + Assert.Equal ("AB", tf.Text); + + // then delete the B + tf.ProcessKey (new KeyEvent (Key.Backspace, new KeyModifiers ())); + Assert.Equal ("A", tf.Text); + + // then delete the A + tf.ProcessKey (new KeyEvent (Key.Backspace, new KeyModifiers ())); + Assert.Equal ("", tf.Text); + } + + [Fact] + public void ProcessKey_Backspace_From_Middle () + { + var tf = new TextField ("ABC"); + tf.EnsureFocus (); + tf.CursorPosition = 2; + Assert.Equal ("ABC", tf.Text); + + // now delete the B + tf.ProcessKey (new KeyEvent (Key.Backspace, new KeyModifiers ())); + Assert.Equal ("AC", tf.Text); + + // then delete the A + tf.ProcessKey (new KeyEvent (Key.Backspace, new KeyModifiers ())); + Assert.Equal ("C", tf.Text); + + // then delete nothing + tf.ProcessKey (new KeyEvent (Key.Backspace, new KeyModifiers ())); + Assert.Equal ("C", tf.Text); + + // now delete the C + tf.CursorPosition = 1; + tf.ProcessKey (new KeyEvent (Key.Backspace, new KeyModifiers ())); + Assert.Equal ("", tf.Text); + } + + [Fact] + public void Cancel_TextChanging_ThenBackspace () + { + var tf = new TextField (); + tf.EnsureFocus (); + tf.ProcessKey (new KeyEvent (Key.A, new KeyModifiers ())); + Assert.Equal ("A", tf.Text); + + // cancel the next keystroke + tf.TextChanging += (e) => e.Cancel = e.NewText == "AB"; + tf.ProcessKey (new KeyEvent (Key.B, new KeyModifiers ())); + + // B was canceled so should just be A + Assert.Equal ("A", tf.Text); + + // now delete the A + tf.ProcessKey (new KeyEvent (Key.Backspace, new KeyModifiers ())); + + Assert.Equal ("", tf.Text); + } } }