vi: add comments to Rob's algorithm of reading and matching ESC sequences

(nice work btw!)
This commit is contained in:
Denis Vlasenko 2008-10-14 10:09:56 +00:00
parent 5e38cd910a
commit 5373fbcd11

View File

@ -2243,60 +2243,70 @@ static char readit(void) // read (maybe cursor) key from stdin
fflush(stdout); fflush(stdout);
// If no data, block waiting for input.
n = chars_to_parse; n = chars_to_parse;
while (!n) { if (n == 0) {
// If no data, block waiting for input.
n = safe_read(0, readbuffer, 1); n = safe_read(0, readbuffer, 1);
if (n <= 0) { if (n <= 0) {
error:
place_cursor(rows - 1, 0, FALSE); // go to bottom of screen place_cursor(rows - 1, 0, FALSE); // go to bottom of screen
clear_to_eol(); // erase to end of line clear_to_eol(); // erase to end of line
cookmode(); // terminal to "cooked" cookmode(); // terminal to "cooked"
bb_error_msg_and_die("can't read user input"); bb_error_msg_and_die("can't read user input");
} }
// Returning NUL from this routine would be bad.
if (*readbuffer) break;
} }
// Grab character to return from buffer // Grab character to return from buffer
c = *readbuffer; c = readbuffer[0];
// Returning NUL from this routine would be bad.
if (c == '\0')
c = ' ';
n--; n--;
if (n) memmove(readbuffer, readbuffer+1, n); if (n) memmove(readbuffer, readbuffer + 1, n);
// If it's an escape sequence, loop through known matches. // If it's an escape sequence, loop through known matches.
if (c == 27) { if (c == 27) {
const struct esc_cmds *eindex; const struct esc_cmds *eindex;
for (eindex = esccmds; eindex < esccmds+ARRAY_SIZE(esccmds); eindex++) { for (eindex = esccmds; eindex < esccmds + ARRAY_SIZE(esccmds); eindex++) {
int i=0, cnt = strnlen(eindex->seq, 4); // n - position in seq to read
int i = 0; // position in seq to compare
int cnt = strnlen(eindex->seq, 4);
// Loop through chars in this sequence. // Loop through chars in this sequence.
for (;;) { for (;;) {
// We've matched this escape sequence up to [i-1]
// If we've matched this escape sequence so far but need more
// chars, read another as long as it wouldn't block. (Note that
// escape sequences come in as a unit, so if we would block
// it's not really an escape sequence.)
if (n <= i) { if (n <= i) {
// Need more chars, read another one if it wouldn't block.
// (Note that escape sequences come in as a unit,
// so if we would block it's not really an escape sequence.)
struct pollfd pfd; struct pollfd pfd;
pfd.fd = 0; pfd.fd = 0;
pfd.events = POLLIN; pfd.events = POLLIN;
if (0 < safe_poll(&pfd, 1, 300) // TODO: what is a good timeout here? why?
&& 0 < safe_read(0, readbuffer + n, 1)) if (safe_poll(&pfd, 1, /*timeout:*/ 0)) {
n++; if (safe_read(0, readbuffer + n, 1) <= 0)
goto error;
// Since the array is sorted from shortest to longest, if n++;
// we needed more data we can't match anything later, so } else {
// break out of both loops. // No more data!
else goto loop_out; // Array is sorted from shortest to longest,
// we can't match anything later in array,
// break out of both loops.
goto loop_out;
}
} }
if (readbuffer[i] != eindex->seq[i]) break; if (readbuffer[i] != eindex->seq[i])
if (++i == cnt) { break; // try next seq
if (++i == cnt) { // entire seq matched
c = eindex->val; c = eindex->val;
n = 0; n = 0;
goto loop_out; goto loop_out;
} }
} }
} }
// We did not find matching sequence, it was a bare ESC.
// We possibly read and stored more input in readbuffer by now.
} }
loop_out: loop_out: