summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko2008-10-14 10:09:56 +0000
committerDenis Vlasenko2008-10-14 10:09:56 +0000
commit5373fbcd1140a9fb4b2e259c04cdd79d4b80bc3b (patch)
tree11dd19b912f6ed606f7a50184c20ff38bac3474f
parent5e38cd910acacccb98387b0404bb2130280d0772 (diff)
downloadbusybox-5373fbcd1140a9fb4b2e259c04cdd79d4b80bc3b.zip
busybox-5373fbcd1140a9fb4b2e259c04cdd79d4b80bc3b.tar.gz
vi: add comments to Rob's algorithm of reading and matching ESC sequences
(nice work btw!)
-rw-r--r--editors/vi.c56
1 files changed, 33 insertions, 23 deletions
diff --git a/editors/vi.c b/editors/vi.c
index 3c3d759..e1cd7a4 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -2243,60 +2243,70 @@ static char readit(void) // read (maybe cursor) key from stdin
fflush(stdout);
- // If no data, block waiting for input.
n = chars_to_parse;
- while (!n) {
+ if (n == 0) {
+ // If no data, block waiting for input.
n = safe_read(0, readbuffer, 1);
if (n <= 0) {
+ error:
place_cursor(rows - 1, 0, FALSE); // go to bottom of screen
clear_to_eol(); // erase to end of line
cookmode(); // terminal to "cooked"
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
- c = *readbuffer;
+ c = readbuffer[0];
+ // Returning NUL from this routine would be bad.
+ if (c == '\0')
+ c = ' ';
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 (c == 27) {
const struct esc_cmds *eindex;
- for (eindex = esccmds; eindex < esccmds+ARRAY_SIZE(esccmds); eindex++) {
- int i=0, cnt = strnlen(eindex->seq, 4);
+ for (eindex = esccmds; eindex < esccmds + ARRAY_SIZE(esccmds); eindex++) {
+ // 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.
for (;;) {
-
- // 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.)
+ // We've matched this escape sequence up to [i-1]
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;
pfd.fd = 0;
pfd.events = POLLIN;
- if (0 < safe_poll(&pfd, 1, 300)
- && 0 < safe_read(0, readbuffer + n, 1))
- n++;
-
- // Since the array is sorted from shortest to longest, if
- // we needed more data we can't match anything later, so
- // break out of both loops.
- else goto loop_out;
+ // TODO: what is a good timeout here? why?
+ if (safe_poll(&pfd, 1, /*timeout:*/ 0)) {
+ if (safe_read(0, readbuffer + n, 1) <= 0)
+ goto error;
+ n++;
+ } else {
+ // No more data!
+ // 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 (++i == cnt) {
+ if (readbuffer[i] != eindex->seq[i])
+ break; // try next seq
+ if (++i == cnt) { // entire seq matched
c = eindex->val;
n = 0;
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: