summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2012-02-05 22:05:48 +0100
committerBram Moolenaar <Bram@vim.org>2012-02-05 22:05:48 +0100
commita8c8a688ac66958f9d1d8763925cefe739e46ccc (patch)
tree693bc1e2a539465e425979c2784a4729c07ec8b7
parent73b2470896034e9d5a13837eec49b2f1065b8c12 (diff)
updated for version 7.3.431v7.3.431
Problem: Fetching a key at a prompt may be confused by escape sequences. Especially when getting a prompt at a VimEnter autocommand. (Alex Efros) Solution: Properly handle escape sequences deleted by check_termcode().
-rw-r--r--src/getchar.c3
-rw-r--r--src/misc1.c37
-rw-r--r--src/proto/term.pro2
-rw-r--r--src/term.c26
-rw-r--r--src/version.c2
5 files changed, 50 insertions, 20 deletions
diff --git a/src/getchar.c b/src/getchar.c
index af18c6f249..dc7d768476 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -2282,7 +2282,8 @@ vgetorpeek(advance)
typebuf.tb_off] == RM_YES))
&& !timedout)
{
- keylen = check_termcode(max_mlen + 1, NULL, 0);
+ keylen = check_termcode(max_mlen + 1,
+ NULL, 0, NULL);
/* If no termcode matched but 'pastetoggle'
* matched partially it's like an incomplete key
diff --git a/src/misc1.c b/src/misc1.c
index 1cd7cceee8..1945d0ac9b 100644
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -3105,8 +3105,9 @@ ask_yesno(str, direct)
int
get_keystroke()
{
-#define CBUFLEN 151
- char_u buf[CBUFLEN];
+ char_u *buf = NULL;
+ int buflen = 150;
+ int maxlen;
int len = 0;
int n;
int save_mapped_ctrl_c = mapped_ctrl_c;
@@ -3118,12 +3119,29 @@ get_keystroke()
cursor_on();
out_flush();
+ /* Leave some room for check_termcode() to insert a key code into (max
+ * 5 chars plus NUL). And fix_input_buffer() can triple the number of
+ * bytes. */
+ maxlen = (buflen - 6 - len) / 3;
+ if (buf == NULL)
+ buf = alloc(buflen);
+ else if (maxlen < 10)
+ {
+ /* Need some more space. This migth happen when receiving a long
+ * escape sequence. */
+ buflen += 100;
+ buf = vim_realloc(buf, buflen);
+ maxlen = (buflen - 6 - len) / 3;
+ }
+ if (buf == NULL)
+ {
+ do_outofmem_msg((long_u)buflen);
+ return ESC; /* panic! */
+ }
+
/* First time: blocking wait. Second time: wait up to 100ms for a
- * terminal code to complete. Leave some room for check_termcode() to
- * insert a key code into (max 5 chars plus NUL). And
- * fix_input_buffer() can triple the number of bytes. */
- n = ui_inchar(buf + len, (CBUFLEN - 6 - len) / 3,
- len == 0 ? -1L : 100L, 0);
+ * terminal code to complete. */
+ n = ui_inchar(buf + len, maxlen, len == 0 ? -1L : 100L, 0);
if (n > 0)
{
/* Replace zero and CSI by a special key code. */
@@ -3135,7 +3153,7 @@ get_keystroke()
++waited; /* keep track of the waiting time */
/* Incomplete termcode and not timed out yet: get more characters */
- if ((n = check_termcode(1, buf, len)) < 0
+ if ((n = check_termcode(1, buf, buflen, &len)) < 0
&& (!p_ttimeout || waited * 100L < (p_ttm < 0 ? p_tm : p_ttm)))
continue;
@@ -3203,7 +3221,7 @@ get_keystroke()
{
if (MB_BYTE2LEN(n) > len)
continue; /* more bytes to get */
- buf[len >= CBUFLEN ? CBUFLEN - 1 : len] = NUL;
+ buf[len >= buflen ? buflen - 1 : len] = NUL;
n = (*mb_ptr2char)(buf);
}
#endif
@@ -3213,6 +3231,7 @@ get_keystroke()
#endif
break;
}
+ vim_free(buf);
mapped_ctrl_c = save_mapped_ctrl_c;
return n;
diff --git a/src/proto/term.pro b/src/proto/term.pro
index 66c4c2ed50..9958763bfc 100644
--- a/src/proto/term.pro
+++ b/src/proto/term.pro
@@ -50,7 +50,7 @@ char_u *find_termcode __ARGS((char_u *name));
char_u *get_termcode __ARGS((int i));
void del_termcode __ARGS((char_u *name));
void set_mouse_topline __ARGS((win_T *wp));
-int check_termcode __ARGS((int max_offset, char_u *buf, int buflen));
+int check_termcode __ARGS((int max_offset, char_u *buf, int bufsize, int *buflen));
char_u *replace_termcodes __ARGS((char_u *from, char_u **bufp, int from_part, int do_lt, int special));
int find_term_bykeys __ARGS((char_u *src));
void show_termcodes __ARGS((void));
diff --git a/src/term.c b/src/term.c
index 47df299615..74c5a336fe 100644
--- a/src/term.c
+++ b/src/term.c
@@ -3785,14 +3785,16 @@ set_mouse_topline(wp)
* With a match, the match is removed, the replacement code is inserted in
* typebuf.tb_buf[] and the number of characters in typebuf.tb_buf[] is
* returned.
- * When "buf" is not NULL, it is used instead of typebuf.tb_buf[]. "buflen" is
- * then the length of the string in buf[].
+ * When "buf" is not NULL, buf[bufsize] is used instead of typebuf.tb_buf[].
+ * "buflen" is then the length of the string in buf[] and is updated for
+ * inserts and deletes.
*/
int
-check_termcode(max_offset, buf, buflen)
+check_termcode(max_offset, buf, bufsize, buflen)
int max_offset;
char_u *buf;
- int buflen;
+ int bufsize;
+ int *buflen;
{
char_u *tp;
char_u *p;
@@ -3864,10 +3866,10 @@ check_termcode(max_offset, buf, buflen)
}
else
{
- if (offset >= buflen)
+ if (offset >= *buflen)
break;
tp = buf + offset;
- len = buflen - offset;
+ len = *buflen - offset;
}
/*
@@ -5002,12 +5004,18 @@ check_termcode(max_offset, buf, buflen)
if (extra < 0)
/* remove matched characters */
mch_memmove(buf + offset, buf + offset - extra,
- (size_t)(buflen + offset + extra));
+ (size_t)(*buflen + offset + extra));
else if (extra > 0)
- /* insert the extra space we need */
+ {
+ /* Insert the extra space we need. If there is insufficient
+ * space return -1. */
+ if (*buflen + extra + new_slen >= bufsize)
+ return -1;
mch_memmove(buf + offset + extra, buf + offset,
- (size_t)(buflen - offset));
+ (size_t)(*buflen - offset));
+ }
mch_memmove(buf + offset, string, (size_t)new_slen);
+ *buflen = *buflen + extra + new_slen;
}
return retval == 0 ? (len + extra + offset) : retval;
}
diff --git a/src/version.c b/src/version.c
index 88bb6e0aee..89720f950a 100644
--- a/src/version.c
+++ b/src/version.c
@@ -715,6 +715,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 431,
+/**/
430,
/**/
429,