diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index bc8da38724..7a271e8615 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -495,10 +495,10 @@ namespace Avalonia.Controls case 2: if (!StringUtils.IsStartOfWord(text, index)) { - SelectionStart = StringUtils.PreviousWord(text, index, false); + SelectionStart = StringUtils.PreviousWord(text, index); } - SelectionEnd = StringUtils.NextWord(text, index, false); + SelectionEnd = StringUtils.NextWord(text, index); break; case 3: SelectionStart = 0; @@ -638,11 +638,11 @@ namespace Avalonia.Controls { if (direction > 0) { - CaretIndex += StringUtils.NextWord(text, caretIndex, false) - caretIndex; + CaretIndex += StringUtils.NextWord(text, caretIndex) - caretIndex; } else { - CaretIndex += StringUtils.PreviousWord(text, caretIndex, false) - caretIndex; + CaretIndex += StringUtils.PreviousWord(text, caretIndex) - caretIndex; } } } @@ -718,6 +718,10 @@ namespace Avalonia.Controls if (pos < text.Length) { --pos; + if (pos > 0 && Text[pos - 1] == '\r' && Text[pos] == '\n') + { + --pos; + } } break; @@ -820,12 +824,6 @@ namespace Avalonia.Controls SelectionStart = CaretIndex; MoveHorizontal(1, modifiers); SelectionEnd = CaretIndex; - - string selection = GetSelection(); - if (selection != " " && selection.EndsWith(" ")) - { - SelectionEnd = CaretIndex - 1; - } } UndoRedoState UndoRedoHelper.IUndoRedoHost.UndoRedoState diff --git a/src/Avalonia.Controls/Utils/StringUtils.cs b/src/Avalonia.Controls/Utils/StringUtils.cs index 8571d663f5..2304866a85 100644 --- a/src/Avalonia.Controls/Utils/StringUtils.cs +++ b/src/Avalonia.Controls/Utils/StringUtils.cs @@ -57,7 +57,7 @@ namespace Avalonia.Controls.Utils } } - public static int PreviousWord(string text, int cursor, bool gtkMode) + public static int PreviousWord(string text, int cursor) { int begin; int i; @@ -81,60 +81,21 @@ namespace Avalonia.Controls.Utils return (cr > 0) ? cr : 0; } - if (gtkMode) - { - CharClass cc = GetCharClass(text[cursor - 1]); - begin = lf + 1; - i = cursor; - - // skip over the word, punctuation, or run of whitespace - while (i > begin && GetCharClass(text[i - 1]) == cc) - { - i--; - } + CharClass cc = GetCharClass(text[cursor - 1]); + begin = lf + 1; + i = cursor; - // if the cursor was at whitespace, skip back a word too - if (cc == CharClass.CharClassWhitespace && i > begin) - { - cc = GetCharClass(text[i - 1]); - while (i > begin && GetCharClass(text[i - 1]) == cc) - { - i--; - } - } - } - else + // skip over the word, punctuation, or run of whitespace + while (i > begin && GetCharClass(text[i - 1]) == cc) { - begin = lf + 1; - i = cursor; - - if (cursor < text.Length) - { - // skip to the beginning of this word - while (i > begin && !char.IsWhiteSpace(text[i - 1])) - { - i--; - } - - if (i < cursor && IsStartOfWord(text, i)) - { - return i; - } - } - - // skip to the start of the lwsp - while (i > begin && char.IsWhiteSpace(text[i - 1])) - { - i--; - } - - if (i > begin) - { - i--; - } + i--; + } - // skip to the beginning of the word - while (i > begin && !IsStartOfWord(text, i)) + // if the cursor was at whitespace, skip back a word too + if (cc == CharClass.CharClassWhitespace && i > begin) + { + cc = GetCharClass(text[i - 1]); + while (i > begin && GetCharClass(text[i - 1]) == cc) { i--; } @@ -143,7 +104,7 @@ namespace Avalonia.Controls.Utils return i; } - public static int NextWord(string text, int cursor, bool gtkMode) + public static int NextWord(string text, int cursor) { int i, lf, cr; @@ -169,50 +130,19 @@ namespace Avalonia.Controls.Utils return cursor; } - if (gtkMode) - { - CharClass cc = GetCharClass(text[cursor]); - i = cursor; - - // skip over the word, punctuation, or run of whitespace - while (i < cr && GetCharClass(text[i]) == cc) - { - i++; - } + CharClass cc = GetCharClass(text[cursor]); + i = cursor; - // skip any whitespace after the word/punct - while (i < cr && char.IsWhiteSpace(text[i])) - { - i++; - } - } - else + // skip over the word, punctuation, or run of whitespace + while (i < cr && GetCharClass(text[i]) == cc) { - i = cursor; - - // skip any whitespace before the word - while (i < cr && char.IsWhiteSpace(text[i])) - { - i++; - } - - // skip to the end of the current word - while (i < cr && !char.IsWhiteSpace(text[i])) - { - i++; - } - - // skip any whitespace after the word - while (i < cr && char.IsWhiteSpace(text[i])) - { - i++; - } + i++; + } - // find the start of the next word - while (i < cr && !IsStartOfWord(text, i)) - { - i++; - } + // skip any whitespace after the word/punct + while (i < cr && char.IsWhiteSpace(text[i])) + { + i++; } return i; diff --git a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs index 851657ab6c..cff49bc32e 100644 --- a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs @@ -175,24 +175,25 @@ namespace Avalonia.Controls.UnitTests RaiseKeyEvent(textBox, Key.Delete, InputModifiers.Control); Assert.Equal("First Second Third ", textBox.Text); - // (First Second| Third ) - textBox.CaretIndex = 12; + // (First Second |Third ) + textBox.CaretIndex = 13; RaiseKeyEvent(textBox, Key.Delete, InputModifiers.Control); Assert.Equal("First Second ", textBox.Text); // (First Sec|ond ) textBox.CaretIndex = 9; RaiseKeyEvent(textBox, Key.Delete, InputModifiers.Control); - Assert.Equal("First Sec ", textBox.Text); + Assert.Equal("First Sec", textBox.Text); // (Fi[rs]t Sec ) textBox.SelectionStart = 2; textBox.SelectionEnd = 4; RaiseKeyEvent(textBox, Key.Delete, InputModifiers.Control); - Assert.Equal("Fit Sec ", textBox.Text); + Assert.Equal("Fit Sec", textBox.Text); // (Fit Sec| ) + textBox.Text += " "; textBox.CaretIndex = 7; RaiseKeyEvent(textBox, Key.Delete, InputModifiers.Control); Assert.Equal("Fit Sec", textBox.Text);