patch 9.1.0015: i_CTRL-R- no longer works in replace mode

Problem:  i_CTRL-R- no longer works in replace mode
Solution: delete characters in replace mode before putting, add a test,
          add a bit warning into the documentation, that i_CTRL-R-P/O
          is not supported in Replace mode for now

fixes: #13792
closes: #13816

Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt
index de8866f..6ebd83e 100644
--- a/runtime/doc/insert.txt
+++ b/runtime/doc/insert.txt
@@ -1,4 +1,4 @@
-*insert.txt*    For Vim version 9.1.  Last change: 2022 Sep 30
+*insert.txt*    For Vim version 9.1.  Last change: 2024 Jan 04
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -168,22 +168,22 @@
 		auto-indent.  Does the same as pasting with the mouse
 		|<MiddleMouse>|. When the register is linewise this will
 		insert the text above the current line, like with `P`.
-		Does not replace characters!
 		The '.' register (last inserted text) is still inserted as
 		typed.
 		After this command, the '.' register contains the command
 		typed and not the text. I.e., the literals "^R^O" and not the
 		text from the register.
+		Does not replace characters in |Replace-mode|!
 
 CTRL-R CTRL-P {register}			*i_CTRL-R_CTRL-P*
 		Insert the contents of a register literally and fix the
 		indent, like |[<MiddleMouse>|.
-		Does not replace characters!
 		The '.' register (last inserted text) is still inserted as
 		typed.
 		After this command, the '.' register contains the command
 		typed and not the text. I.e., the literals "^R^P" and not the
 		text from the register.
+		Does not replace characters in |Replace-mode|!
 
 						*i_CTRL-T*
 CTRL-T		Insert one shiftwidth of indent at the start of the current
diff --git a/src/register.c b/src/register.c
index 1d0e46b..f381e30 100644
--- a/src/register.c
+++ b/src/register.c
@@ -828,9 +828,22 @@
 	    {
 		if (regname == '-')
 		{
+		    int dir = BACKWARD;
+		    if ((State & REPLACE_FLAG) != 0)
+		    {
+			pos_T curpos;
+			u_save_cursor();
+			del_bytes((long)STRLEN(y_current->y_array[0]), TRUE, FALSE);
+			curpos = curwin->w_cursor;
+			if (oneright() == FAIL)
+			    // hit end of line, need to put forward (after the current position)
+			    dir = FORWARD;
+			curwin->w_cursor = curpos;
+		    }
+
 		    AppendCharToRedobuff(Ctrl_R);
 		    AppendCharToRedobuff(regname);
-		    do_put(regname, NULL, BACKWARD, 1L, PUT_CURSEND);
+		    do_put(regname, NULL, dir, 1L, PUT_CURSEND);
 		}
 		else
 		    stuffescaped(y_current->y_array[i], literally);
diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim
index 90bedf1..38ad810 100644
--- a/src/testdir/test_normal.vim
+++ b/src/testdir/test_normal.vim
@@ -4181,4 +4181,4 @@
   bw!
 endfunc
 
-" vim: shiftwidth=2 sts=2 expandtab
+" vim: shiftwidth=2 sts=2 expandtab nofoldenable
diff --git a/src/testdir/test_registers.vim b/src/testdir/test_registers.vim
index f85e727..50f3910 100644
--- a/src/testdir/test_registers.vim
+++ b/src/testdir/test_registers.vim
@@ -946,4 +946,24 @@
   bwipe!
 endfunc
 
+func Test_insert_small_delete_replace_mode()
+  new
+  call setline(1, ['foo', 'bar', 'foobar',  'bar'])
+  let @-='foo'
+  call cursor(2, 1)
+  exe ":norm! R\<C-R>-\<C-R>-"
+  call assert_equal('foofoo', getline(2))
+  call cursor(3, 1)
+  norm! D
+  call assert_equal(['foo', 'foofoo', '',  'bar'], getline(1, 4))
+  call cursor(4, 2)
+  exe ":norm! R\<C-R>-ZZZZ"
+  call assert_equal(['foo', 'foofoo', '',  'bfoobarZZZZ'], getline(1, 4))
+  call cursor(1, 1)
+  let @-=''
+  exe ":norm! R\<C-R>-ZZZ"
+  call assert_equal(['ZZZ', 'foofoo', '',  'bfoobarZZZZ'], getline(1, 4))
+  bwipe!
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index a6dae87..9a4106d 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    15,
+/**/
     14,
 /**/
     13,