aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/getchar.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/getchar.c')
-rw-r--r--src/nvim/getchar.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index b12b99b7ee..299385cb17 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -1253,7 +1253,14 @@ static int old_mod_mask; // mod_mask for ungotten character
static int old_mouse_grid; // mouse_grid related to old_char
static int old_mouse_row; // mouse_row related to old_char
static int old_mouse_col; // mouse_col related to old_char
+static int old_KeyStuffed; // whether old_char was stuffed
+static bool can_get_old_char(void)
+{
+ // If the old character was not stuffed and characters have been added to
+ // the stuff buffer, need to first get the stuffed characters instead.
+ return old_char != -1 && (old_KeyStuffed || stuff_empty());
+}
/*
* Save all three kinds of typeahead, so that the user must type at a prompt.
@@ -1454,7 +1461,7 @@ int vgetc(void)
* If a character was put back with vungetc, it was already processed.
* Return it directly.
*/
- if (old_char != -1) {
+ if (can_get_old_char()) {
c = old_char;
old_char = -1;
mod_mask = old_mod_mask;
@@ -1660,7 +1667,7 @@ int plain_vgetc(void)
*/
int vpeekc(void)
{
- if (old_char != -1) {
+ if (can_get_old_char()) {
return old_char;
}
return vgetorpeek(false);
@@ -2052,7 +2059,9 @@ static int handle_mapping(int *keylenp, bool *timedout, int *mapdepth)
return map_result_nomatch;
}
-// unget one character (can only be done once!)
+/// unget one character (can only be done once!)
+/// If the character was stuffed, vgetc() will get it next time it is called.
+/// Otherwise vgetc() will only get it when the stuff buffer is empty.
void vungetc(int c)
{
old_char = c;
@@ -2060,6 +2069,21 @@ void vungetc(int c)
old_mouse_grid = mouse_grid;
old_mouse_row = mouse_row;
old_mouse_col = mouse_col;
+ old_KeyStuffed = KeyStuffed;
+}
+
+/// When peeking and not getting a character, reg_executing cannot be cleared
+/// yet, so set a flag to clear it later.
+void check_end_reg_executing(bool advance)
+{
+ if (reg_executing != 0 && (typebuf.tb_maplen == 0 || pending_end_reg_executing)) {
+ if (advance) {
+ reg_executing = 0;
+ pending_end_reg_executing = false;
+ } else {
+ pending_end_reg_executing = true;
+ }
+ }
}
/// Gets a byte:
@@ -2116,9 +2140,7 @@ static int vgetorpeek(bool advance)
init_typebuf();
start_stuff();
- if (advance && typebuf.tb_maplen == 0) {
- reg_executing = 0;
- }
+ check_end_reg_executing(advance);
do {
// get a character: 1. from the stuffbuffer
if (typeahead_char != 0) {
@@ -2145,6 +2167,7 @@ static int vgetorpeek(bool advance)
// If a mapped key sequence is found we go back to the start to
// try re-mapping.
for (;;) {
+ check_end_reg_executing(advance);
// os_breakcheck() is slow, don't use it too often when
// inside a mapping. But call it each time for typed
// characters.
@@ -2330,8 +2353,6 @@ static int vgetorpeek(bool advance)
// cmdline window.
if (p_im && (State & INSERT)) {
c = Ctrl_L;
- } else if (exmode_active) {
- c = '\n';
} else if ((State & CMDLINE) || (cmdwin_type > 0 && tc == ESC)) {
c = Ctrl_C;
} else {
@@ -2573,7 +2594,7 @@ int inchar(char_u *buf, int maxlen, long wait_time)
// Don't use buf[] here, closescript() may have freed typebuf.tb_buf[]
// and buf may be pointing inside typebuf.tb_buf[].
if (got_int) {
-#define DUM_LEN MAXMAPLEN * 3 + 3
+#define DUM_LEN (MAXMAPLEN * 3 + 3)
char_u dum[DUM_LEN + 1];
for (;;) {