diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-10-14 10:09:56 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-10-14 10:09:56 +0000 |
commit | 5373fbcd1140a9fb4b2e259c04cdd79d4b80bc3b (patch) | |
tree | 11dd19b912f6ed606f7a50184c20ff38bac3474f | |
parent | 5e38cd910acacccb98387b0404bb2130280d0772 (diff) | |
download | busybox-w32-5373fbcd1140a9fb4b2e259c04cdd79d4b80bc3b.tar.gz busybox-w32-5373fbcd1140a9fb4b2e259c04cdd79d4b80bc3b.tar.bz2 busybox-w32-5373fbcd1140a9fb4b2e259c04cdd79d4b80bc3b.zip |
vi: add comments to Rob's algorithm of reading and matching ESC sequences
(nice work btw!)
-rw-r--r-- | editors/vi.c | 56 |
1 files changed, 33 insertions, 23 deletions
diff --git a/editors/vi.c b/editors/vi.c index 3c3d759e5..e1cd7a482 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -2243,60 +2243,70 @@ static char readit(void) // read (maybe cursor) key from stdin | |||
2243 | 2243 | ||
2244 | fflush(stdout); | 2244 | fflush(stdout); |
2245 | 2245 | ||
2246 | // If no data, block waiting for input. | ||
2247 | n = chars_to_parse; | 2246 | n = chars_to_parse; |
2248 | while (!n) { | 2247 | if (n == 0) { |
2248 | // If no data, block waiting for input. | ||
2249 | n = safe_read(0, readbuffer, 1); | 2249 | n = safe_read(0, readbuffer, 1); |
2250 | if (n <= 0) { | 2250 | if (n <= 0) { |
2251 | error: | ||
2251 | place_cursor(rows - 1, 0, FALSE); // go to bottom of screen | 2252 | place_cursor(rows - 1, 0, FALSE); // go to bottom of screen |
2252 | clear_to_eol(); // erase to end of line | 2253 | clear_to_eol(); // erase to end of line |
2253 | cookmode(); // terminal to "cooked" | 2254 | cookmode(); // terminal to "cooked" |
2254 | bb_error_msg_and_die("can't read user input"); | 2255 | bb_error_msg_and_die("can't read user input"); |
2255 | } | 2256 | } |
2256 | // Returning NUL from this routine would be bad. | ||
2257 | if (*readbuffer) break; | ||
2258 | } | 2257 | } |
2259 | 2258 | ||
2260 | // Grab character to return from buffer | 2259 | // Grab character to return from buffer |
2261 | c = *readbuffer; | 2260 | c = readbuffer[0]; |
2261 | // Returning NUL from this routine would be bad. | ||
2262 | if (c == '\0') | ||
2263 | c = ' '; | ||
2262 | n--; | 2264 | n--; |
2263 | if (n) memmove(readbuffer, readbuffer+1, n); | 2265 | if (n) memmove(readbuffer, readbuffer + 1, n); |
2264 | 2266 | ||
2265 | // If it's an escape sequence, loop through known matches. | 2267 | // If it's an escape sequence, loop through known matches. |
2266 | if (c == 27) { | 2268 | if (c == 27) { |
2267 | const struct esc_cmds *eindex; | 2269 | const struct esc_cmds *eindex; |
2268 | 2270 | ||
2269 | for (eindex = esccmds; eindex < esccmds+ARRAY_SIZE(esccmds); eindex++) { | 2271 | for (eindex = esccmds; eindex < esccmds + ARRAY_SIZE(esccmds); eindex++) { |
2270 | int i=0, cnt = strnlen(eindex->seq, 4); | 2272 | // n - position in seq to read |
2273 | int i = 0; // position in seq to compare | ||
2274 | int cnt = strnlen(eindex->seq, 4); | ||
2271 | 2275 | ||
2272 | // Loop through chars in this sequence. | 2276 | // Loop through chars in this sequence. |
2273 | for (;;) { | 2277 | for (;;) { |
2274 | 2278 | // We've matched this escape sequence up to [i-1] | |
2275 | // If we've matched this escape sequence so far but need more | ||
2276 | // chars, read another as long as it wouldn't block. (Note that | ||
2277 | // escape sequences come in as a unit, so if we would block | ||
2278 | // it's not really an escape sequence.) | ||
2279 | if (n <= i) { | 2279 | if (n <= i) { |
2280 | // Need more chars, read another one if it wouldn't block. | ||
2281 | // (Note that escape sequences come in as a unit, | ||
2282 | // so if we would block it's not really an escape sequence.) | ||
2280 | struct pollfd pfd; | 2283 | struct pollfd pfd; |
2281 | pfd.fd = 0; | 2284 | pfd.fd = 0; |
2282 | pfd.events = POLLIN; | 2285 | pfd.events = POLLIN; |
2283 | if (0 < safe_poll(&pfd, 1, 300) | 2286 | // TODO: what is a good timeout here? why? |
2284 | && 0 < safe_read(0, readbuffer + n, 1)) | 2287 | if (safe_poll(&pfd, 1, /*timeout:*/ 0)) { |
2285 | n++; | 2288 | if (safe_read(0, readbuffer + n, 1) <= 0) |
2286 | 2289 | goto error; | |
2287 | // Since the array is sorted from shortest to longest, if | 2290 | n++; |
2288 | // we needed more data we can't match anything later, so | 2291 | } else { |
2289 | // break out of both loops. | 2292 | // No more data! |
2290 | else goto loop_out; | 2293 | // Array is sorted from shortest to longest, |
2294 | // we can't match anything later in array, | ||
2295 | // break out of both loops. | ||
2296 | goto loop_out; | ||
2297 | } | ||
2291 | } | 2298 | } |
2292 | if (readbuffer[i] != eindex->seq[i]) break; | 2299 | if (readbuffer[i] != eindex->seq[i]) |
2293 | if (++i == cnt) { | 2300 | break; // try next seq |
2301 | if (++i == cnt) { // entire seq matched | ||
2294 | c = eindex->val; | 2302 | c = eindex->val; |
2295 | n = 0; | 2303 | n = 0; |
2296 | goto loop_out; | 2304 | goto loop_out; |
2297 | } | 2305 | } |
2298 | } | 2306 | } |
2299 | } | 2307 | } |
2308 | // We did not find matching sequence, it was a bare ESC. | ||
2309 | // We possibly read and stored more input in readbuffer by now. | ||
2300 | } | 2310 | } |
2301 | loop_out: | 2311 | loop_out: |
2302 | 2312 | ||