diff --git a/widget/entry.go b/widget/entry.go index 0f28e899a8..9b12fc63c9 100644 --- a/widget/entry.go +++ b/widget/entry.go @@ -876,14 +876,15 @@ func (e *Entry) registerShortcut() { func (e *Entry) rowColFromTextPos(pos int) (row int, col int) { provider := e.textProvider() canWrap := e.Wrapping == fyne.TextWrapBreak || e.Wrapping == fyne.TextWrapWord - for i := 0; i < provider.rows(); i++ { + totalRows := provider.rows() + for i := 0; i < totalRows; i++ { b := provider.rowBoundary(i) if b[0] <= pos { if b[1] < pos { row++ } col = pos - b[0] - if canWrap && b[0] == pos && col == 0 && pos != 0 { + if canWrap && b[0] == pos && col == 0 && pos != 0 && row < (totalRows-1) { row++ } } else { diff --git a/widget/entry_test.go b/widget/entry_test.go index 96cfc0b52e..d487a5ad00 100644 --- a/widget/entry_test.go +++ b/widget/entry_test.go @@ -331,6 +331,34 @@ func TestEntry_MultilineSelect(t *testing.T) { assert.Equal(t, "ng\nTe", e.SelectedText()) } +func TestEntry_MultilineWrapping_DeleteWithBackspace(t *testing.T) { + entry := widget.NewMultiLineEntry() + entry.Wrapping = fyne.TextWrapWord + entry.Resize(fyne.NewSize(64, 64)) + test.Type(entry, "line1") + test.Type(entry, "\nline2") + test.Type(entry, "\nline3") + + assert.Equal(t, 5, entry.CursorColumn) + assert.Equal(t, 2, entry.CursorRow) + + for i := 0; i < 4; i++ { + entry.TypedKey(&fyne.KeyEvent{Name: fyne.KeyBackspace}) + assert.Equal(t, 4-i, entry.CursorColumn) + assert.Equal(t, 2, entry.CursorRow) + } + + entry.TypedKey(&fyne.KeyEvent{Name: fyne.KeyBackspace}) + assert.Equal(t, 0, entry.CursorColumn) + assert.Equal(t, 2, entry.CursorRow) + + assert.NotPanics(t, func() { + entry.TypedKey(&fyne.KeyEvent{Name: fyne.KeyBackspace}) + }) + assert.Equal(t, 5, entry.CursorColumn) + assert.Equal(t, 1, entry.CursorRow) +} + func TestEntry_Notify(t *testing.T) { entry := widget.NewEntry() changed := false