patch 9.1.1224: cannot :put while keeping indent

Problem:  cannot :put while keeping indent (Peter Aronoff)
Solution: add the :iput ex command (64-bitman)

fixes: #16225
closes: #16886

Co-authored-by: zeertzjq <zeertzjq@outlook.com>
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: 64-bitman <60551350+64-bitman@users.noreply.github.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 4b69dfa..c0c3103 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -3253,6 +3253,58 @@
 }
 
 /*
+ * do ISN_PUT or ISN_IPUT instruction depending on fixindent parameter
+ */
+    static void
+isn_put_do(ectx_T *ectx, isn_T *iptr, typval_T *tv, int fixindent)
+{
+    int		regname = iptr->isn_arg.put.put_regname;
+    linenr_T	lnum = iptr->isn_arg.put.put_lnum;
+    char_u	*expr = NULL;
+    int		dir = FORWARD;
+
+    if (lnum < -2)
+    {
+	// line number was put on the stack by ISN_RANGE
+	tv = STACK_TV_BOT(-1);
+	curwin->w_cursor.lnum = tv->vval.v_number;
+	if (lnum == LNUM_VARIABLE_RANGE_ABOVE)
+	    dir = BACKWARD;
+	--ectx->ec_stack.ga_len;
+    }
+    else if (lnum == -2)
+	// :put! above cursor
+	dir = BACKWARD;
+    else if (lnum >= 0)
+    {
+	curwin->w_cursor.lnum = lnum;
+	if (lnum == 0)
+	    // check_cursor() below will move to line 1
+	    dir = BACKWARD;
+    }
+
+    if (regname == '=')
+    {
+	tv = STACK_TV_BOT(-1);
+	if (tv->v_type == VAR_STRING)
+	    expr = tv->vval.v_string;
+	else
+	{
+	    expr = typval2string(tv, TRUE); // allocates value
+	    clear_tv(tv);
+	}
+	--ectx->ec_stack.ga_len;
+    }
+    check_cursor();
+
+    if (fixindent)
+	do_put(regname, expr, dir, 1L, PUT_LINE|PUT_CURSLINE|PUT_FIXINDENT);
+    else
+	do_put(regname, expr, dir, 1L, PUT_LINE|PUT_CURSLINE);
+    vim_free(expr);
+}
+
+/*
  * Execute instructions in execution context "ectx".
  * Return OK or FAIL;
  */
@@ -5948,48 +6000,12 @@
 		break;
 
 	    case ISN_PUT:
-		{
-		    int		regname = iptr->isn_arg.put.put_regname;
-		    linenr_T	lnum = iptr->isn_arg.put.put_lnum;
-		    char_u	*expr = NULL;
-		    int		dir = FORWARD;
-
-		    if (lnum < -2)
-		    {
-			// line number was put on the stack by ISN_RANGE
-			tv = STACK_TV_BOT(-1);
-			curwin->w_cursor.lnum = tv->vval.v_number;
-			if (lnum == LNUM_VARIABLE_RANGE_ABOVE)
-			    dir = BACKWARD;
-			--ectx->ec_stack.ga_len;
-		    }
-		    else if (lnum == -2)
-			// :put! above cursor
-			dir = BACKWARD;
-		    else if (lnum >= 0)
-		    {
-			curwin->w_cursor.lnum = lnum;
-			if (lnum == 0)
-			    // check_cursor() below will move to line 1
-			    dir = BACKWARD;
-		    }
-
-		    if (regname == '=')
-		    {
-			tv = STACK_TV_BOT(-1);
-			if (tv->v_type == VAR_STRING)
-			    expr = tv->vval.v_string;
-			else
-			{
-			    expr = typval2string(tv, TRUE); // allocates value
-			    clear_tv(tv);
-			}
-			--ectx->ec_stack.ga_len;
-		    }
-		    check_cursor();
-		    do_put(regname, expr, dir, 1L, PUT_LINE|PUT_CURSLINE);
-		    vim_free(expr);
-		}
+		tv = NULL; // initialize it so we don't get a warning
+		isn_put_do(ectx, iptr, tv, FALSE);
+		break;
+	    case ISN_IPUT:
+		tv = NULL;
+		isn_put_do(ectx, iptr, tv, TRUE);
 		break;
 
 	    case ISN_CMDMOD:
@@ -7619,7 +7635,18 @@
 						 iptr->isn_arg.put.put_regname,
 					     (long)iptr->isn_arg.put.put_lnum);
 		break;
-
+	    case ISN_IPUT:
+		if (iptr->isn_arg.put.put_lnum == LNUM_VARIABLE_RANGE_ABOVE)
+		    smsg("%s%4d IPUT %c above range",
+				  pfx, current, iptr->isn_arg.put.put_regname);
+		else if (iptr->isn_arg.put.put_lnum == LNUM_VARIABLE_RANGE)
+		    smsg("%s%4d IPUT %c range",
+				  pfx, current, iptr->isn_arg.put.put_regname);
+		else
+		    smsg("%s%4d IPUT %c %ld", pfx, current,
+						 iptr->isn_arg.put.put_regname,
+					     (long)iptr->isn_arg.put.put_lnum);
+		break;
 	    case ISN_CMDMOD:
 		{
 		    char_u  *buf;
@@ -7846,5 +7873,4 @@
     return OK;
 }
 
-
 #endif // FEAT_EVAL