diff options
Diffstat (limited to 'Src/Zle')
-rw-r--r-- | Src/Zle/zle_keymap.c | 2 | ||||
-rw-r--r-- | Src/Zle/zle_main.c | 47 | ||||
-rw-r--r-- | Src/Zle/zle_misc.c | 2 | ||||
-rw-r--r-- | Src/Zle/zle_vi.c | 2 |
4 files changed, 41 insertions, 12 deletions
diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c index 6f4e062fc..376805549 100644 --- a/Src/Zle/zle_keymap.c +++ b/Src/Zle/zle_keymap.c @@ -1341,7 +1341,7 @@ getkeymapcmd(Keymap km, Thingy *funcp, char **strp) static int getkeybuf(int w) { - int c = getbyte(w); + int c = getbyte(w, NULL); if(c < 0) return EOF; diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index 2522f67fd..4f598b889 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -628,13 +628,16 @@ raw_getbyte(int keytmout, char *cptr) /**/ mod_export int -getbyte(int keytmout) +getbyte(int keytmout, int *timeout) { char cc; unsigned int ret; int die = 0, r, icnt = 0; int old_errno = errno, obreaks = breaks; + if (timeout) + *timeout = 0; + #ifdef ZLE_UNICODE_SUPPORT /* * Reading a single byte always invalidates the status @@ -660,8 +663,12 @@ getbyte(int keytmout) dont_queue_signals(); r = raw_getbyte(keytmout, &cc); restore_queue_signals(q); - if (r == -2) /* timeout */ + if (r == -2) { + /* timeout */ + if (timeout) + *timeout = 1; return lastchar = EOF; + } if (r == 1) break; if (r == 0) { @@ -733,7 +740,7 @@ getbyte(int keytmout) mod_export ZLE_INT_T getfullchar(int keytmout) { - int inchar = getbyte(keytmout); + int inchar = getbyte(keytmout, NULL); #ifdef ZLE_UNICODE_SUPPORT return getrestchar(inchar); @@ -759,7 +766,7 @@ getrestchar(int inchar) /* char cnull = '\0'; */ char c = inchar; wchar_t outchar; - int ret; + int ret, timeout; static mbstate_t ps; /* @@ -769,8 +776,11 @@ getrestchar(int inchar) */ lastchar_wide_valid = 1; - if (inchar == EOF) + if (inchar == EOF) { + /* End of input, so reset the shift state. */ + memset(&ps, 0, sizeof(ps)); return lastchar_wide = WEOF; + } /* * Return may be zero if we have a NULL; handle this like @@ -781,15 +791,34 @@ getrestchar(int inchar) /* * Invalid input. Hmm, what's the right thing to do here? */ + memset(&ps, 0, sizeof(ps)); return lastchar_wide = WEOF; } - /* No timeout here as we really need the character. */ - inchar = getbyte(0); + /* + * Always apply KEYTIMEOUT to the remains of the input + * character. The parts of a multibyte character should + * arrive together. If we don't do this the input can + * get stuck if an invalid byte sequence arrives. + */ + inchar = getbyte(1, &timeout); /* getbyte deliberately resets lastchar_wide_valid */ lastchar_wide_valid = 1; - if (inchar == EOF) - return lastchar_wide = WEOF; + if (inchar == EOF) { + memset(&ps, 0, sizeof(ps)); + if (timeout) + { + /* + * This case means that we got a valid initial byte + * (since we tested for EOF above), but the followup + * timed out. This probably indicates a duff character. + * Return a '?'. + */ + lastchar_wide = L'?'; + } + else + return lastchar_wide = WEOF; + } c = inchar; } return lastchar_wide = (ZLE_INT_T)outchar; diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index 6b79f431c..05a780b0c 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -595,7 +595,7 @@ universalargument(char **args) * * Hence for now this remains byte-by-byte. */ - while ((gotk = getbyte(0)) != EOF) { + while ((gotk = getbyte(0, NULL)) != EOF) { if (gotk == '-' && !digcnt) { minus = -1; digcnt++; diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c index a83f0197e..cb072cdb6 100644 --- a/Src/Zle/zle_vi.c +++ b/Src/Zle/zle_vi.c @@ -108,7 +108,7 @@ vigetkey(void) char m[3], *str; Thingy cmd; - if(getbyte(0) == EOF) + if (getbyte(0, NULL) == EOF) return ZLEEOF; m[0] = lastchar; |