patch 9.1.1070: Cannot control cursor positioning of getchar()

Problem:  Cannot control cursor positioning of getchar().
Solution: Add "cursor" flag to {opts}, with possible values "hide",
          "keep" and "msg".

related: #10603
closes: #16569

Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/getchar.c b/src/getchar.c
index 06f4ad4..83a9861 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -2386,9 +2386,11 @@
     static void
 getchar_common(typval_T *argvars, typval_T *rettv, int allow_number)
 {
-    varnumber_T		n;
+    varnumber_T		n = 0;
+    int			called_emsg_start = called_emsg;
     int			error = FALSE;
     int			simplify = TRUE;
+    char_u		cursor_flag = 'm';
 
     if ((in_vim9script()
 		&& check_for_opt_bool_or_number_arg(argvars, 0) == FAIL)
@@ -2399,18 +2401,31 @@
     if (argvars[0].v_type != VAR_UNKNOWN && argvars[1].v_type == VAR_DICT)
     {
 	dict_T		*d = argvars[1].vval.v_dict;
+	char_u		*cursor_str;
 
 	if (allow_number)
 	    allow_number = dict_get_bool(d, "number", TRUE);
 	else if (dict_has_key(d, "number"))
-	{
 	    semsg(_(e_invalid_argument_str), "number");
-	    error = TRUE;
-	}
 
 	simplify = dict_get_bool(d, "simplify", TRUE);
+
+	cursor_str = dict_get_string(d, "cursor", FALSE);
+	if (cursor_str != NULL)
+	{
+	    if (STRCMP(cursor_str, "hide") != 0
+		    && STRCMP(cursor_str, "keep") != 0
+		    && STRCMP(cursor_str, "msg") != 0)
+		semsg(_(e_invalid_value_for_argument_str_str), "cursor",
+								   cursor_str);
+	    else
+		cursor_flag = cursor_str[0];
+	}
     }
 
+    if (called_emsg != called_emsg_start)
+	return;
+
 #ifdef MESSAGE_QUEUE
     // vpeekc() used to check for messages, but that caused problems, invoking
     // a callback where it was not expected.  Some plugins use getchar(1) in a
@@ -2418,14 +2433,16 @@
     parse_queued_messages();
 #endif
 
-    // Position the cursor.  Needed after a message that ends in a space.
-    windgoto(msg_row, msg_col);
+    if (cursor_flag == 'h')
+	cursor_sleep();
+    else if (cursor_flag == 'm')
+	windgoto(msg_row, msg_col);
 
     ++no_mapping;
     ++allow_keys;
     if (!simplify)
 	++no_reduce_keys;
-    while (!error)
+    for (;;)
     {
 	if (argvars[0].v_type == VAR_UNKNOWN
 		|| (argvars[0].v_type == VAR_NUMBER
@@ -2453,6 +2470,9 @@
     if (!simplify)
 	--no_reduce_keys;
 
+    if (cursor_flag == 'h')
+	cursor_unsleep();
+
     set_vim_var_nr(VV_MOUSE_WIN, 0);
     set_vim_var_nr(VV_MOUSE_WINID, 0);
     set_vim_var_nr(VV_MOUSE_LNUM, 0);