patch 9.1.1221: Wrong cursor pos when leaving Insert mode just after 'autoindent'

Problem:  Wrong cursor position and '^' mark when leaving Insert mode
          just after 'autoindent' and cursor on last char of line.
Solution: Don't move cursor to NUL when it wasn't moved to the left
          (zeertzjq).

fixes: #15581
related: neovim/neovim#30165 neovim/neovim#32943
closes: #16922

Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/edit.c b/src/edit.c
index 42ee125..143a4ce 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -2512,6 +2512,7 @@
 		&& end_insert_pos->lnum <= curbuf->b_ml.ml_line_count)
 	{
 	    pos_T	tpos = curwin->w_cursor;
+	    colnr_T	prev_col = end_insert_pos->col;
 
 	    curwin->w_cursor = *end_insert_pos;
 	    check_cursor_col();  // make sure it is not past the line
@@ -2527,7 +2528,7 @@
 	    }
 	    if (curwin->w_cursor.lnum != tpos.lnum)
 		curwin->w_cursor = tpos;
-	    else
+	    else if (curwin->w_cursor.col < prev_col)
 	    {
 		// reset tpos, could have been invalidated in the loop above
 		tpos = curwin->w_cursor;
diff --git a/src/testdir/test_edit.vim b/src/testdir/test_edit.vim
index 30a917c..dbeb78d 100644
--- a/src/testdir/test_edit.vim
+++ b/src/testdir/test_edit.vim
@@ -460,6 +460,64 @@
   call delete('Xarifile')
 endfunc
 
+func Test_edit_esc_after_CR_autoindent()
+  new
+  setlocal autoindent
+  autocmd InsertLeavePre * let g:prev_cursor = getpos('.')
+
+  call setline(1, 'foobar')
+  exe "normal! $hi\<CR>\<Esc>"
+  call assert_equal(['foob', 'ar'], getline(1, '$'))
+  call assert_equal([0, 2, 1, 0], getpos('.'))
+  call assert_equal([0, 2, 1, 0], getpos("'^"))
+  call assert_equal([0, 2, 1, 0], g:prev_cursor)
+  %d
+
+  call setline(1, 'foobar')
+  exe "normal! $i\<CR>\<Esc>"
+  call assert_equal(['fooba', 'r'], getline(1, '$'))
+  call assert_equal([0, 2, 1, 0], getpos('.'))
+  call assert_equal([0, 2, 1, 0], getpos("'^"))
+  call assert_equal([0, 2, 1, 0], g:prev_cursor)
+  %d
+
+  call setline(1, 'foobar')
+  exe "normal! A\<CR>\<Esc>"
+  call assert_equal(['foobar', ''], getline(1, '$'))
+  call assert_equal([0, 2, 1, 0], getpos('.'))
+  call assert_equal([0, 2, 1, 0], getpos("'^"))
+  call assert_equal([0, 2, 1, 0], g:prev_cursor)
+  %d
+
+  call setline(1, '  foobar')
+  exe "normal! $hi\<CR>\<Esc>"
+  call assert_equal(['  foob', '  ar'], getline(1, '$'))
+  call assert_equal([0, 2, 2, 0], getpos('.'))
+  call assert_equal([0, 2, 3, 0], getpos("'^"))
+  call assert_equal([0, 2, 3, 0], g:prev_cursor)
+  %d
+
+  call setline(1, '  foobar')
+  exe "normal! $i\<CR>\<Esc>"
+  call assert_equal(['  fooba', '  r'], getline(1, '$'))
+  call assert_equal([0, 2, 2, 0], getpos('.'))
+  call assert_equal([0, 2, 3, 0], getpos("'^"))
+  call assert_equal([0, 2, 3, 0], g:prev_cursor)
+  %d
+
+  call setline(1, '  foobar')
+  exe "normal! A\<CR>\<Esc>"
+  call assert_equal(['  foobar', ''], getline(1, '$'))
+  call assert_equal([0, 2, 1, 0], getpos('.'))
+  call assert_equal([0, 2, 1, 0], getpos("'^"))
+  call assert_equal([0, 2, 1, 0], g:prev_cursor)
+  %d
+
+  autocmd! InsertLeavePre
+  unlet g:prev_cursor
+  bwipe!
+endfunc
+
 func Test_edit_CR()
   " Test for <CR> in insert mode
   " basically only in quickfix mode it's tested, the rest
diff --git a/src/version.c b/src/version.c
index 606cc1e..12a7f45 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1221,
+/**/
     1220,
 /**/
     1219,