diff options
Diffstat (limited to 'editors')
-rw-r--r-- | editors/vi.c | 119 |
1 files changed, 58 insertions, 61 deletions
diff --git a/editors/vi.c b/editors/vi.c index 02bdbb37b..6902b7688 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -210,11 +210,7 @@ struct globals { | |||
210 | #endif | 210 | #endif |
211 | // Should be just enough to hold a key sequence, | 211 | // Should be just enough to hold a key sequence, |
212 | // but CRASME mode uses it as generated command buffer too | 212 | // but CRASME mode uses it as generated command buffer too |
213 | #if ENABLE_FEATURE_VI_CRASHME | 213 | char readbuffer[8]; |
214 | char readbuffer[128]; | ||
215 | #else | ||
216 | char readbuffer[32]; | ||
217 | #endif | ||
218 | #define STATUS_BUFFER_LEN 200 | 214 | #define STATUS_BUFFER_LEN 200 |
219 | char status_buffer[STATUS_BUFFER_LEN]; // messages to the user | 215 | char status_buffer[STATUS_BUFFER_LEN]; // messages to the user |
220 | #if ENABLE_FEATURE_VI_DOT_CMD | 216 | #if ENABLE_FEATURE_VI_DOT_CMD |
@@ -2201,18 +2197,23 @@ static char readit(void) // read (maybe cursor) key from stdin | |||
2201 | { | 2197 | { |
2202 | char c; | 2198 | char c; |
2203 | int n; | 2199 | int n; |
2204 | struct esc_cmds { | 2200 | |
2201 | // Known escape sequences for cursor and function keys. | ||
2202 | static const struct esc_cmds { | ||
2205 | const char seq[4]; | 2203 | const char seq[4]; |
2206 | char val; | 2204 | char val; |
2207 | }; | 2205 | } esccmds[] = { |
2208 | |||
2209 | static const struct esc_cmds esccmds[] = { | ||
2210 | {"OA" , VI_K_UP }, // cursor key Up | 2206 | {"OA" , VI_K_UP }, // cursor key Up |
2211 | {"OB" , VI_K_DOWN }, // cursor key Down | 2207 | {"OB" , VI_K_DOWN }, // cursor key Down |
2212 | {"OC" , VI_K_RIGHT }, // Cursor Key Right | 2208 | {"OC" , VI_K_RIGHT }, // Cursor Key Right |
2213 | {"OD" , VI_K_LEFT }, // cursor key Left | 2209 | {"OD" , VI_K_LEFT }, // cursor key Left |
2214 | {"OH" , VI_K_HOME }, // Cursor Key Home | 2210 | {"OH" , VI_K_HOME }, // Cursor Key Home |
2215 | {"OF" , VI_K_END }, // Cursor Key End | 2211 | {"OF" , VI_K_END }, // Cursor Key End |
2212 | {"OP" , VI_K_FUN1 }, // Function Key F1 | ||
2213 | {"OQ" , VI_K_FUN2 }, // Function Key F2 | ||
2214 | {"OR" , VI_K_FUN3 }, // Function Key F3 | ||
2215 | {"OS" , VI_K_FUN4 }, // Function Key F4 | ||
2216 | |||
2216 | {"[A" , VI_K_UP }, // cursor key Up | 2217 | {"[A" , VI_K_UP }, // cursor key Up |
2217 | {"[B" , VI_K_DOWN }, // cursor key Down | 2218 | {"[B" , VI_K_DOWN }, // cursor key Down |
2218 | {"[C" , VI_K_RIGHT }, // Cursor Key Right | 2219 | {"[C" , VI_K_RIGHT }, // Cursor Key Right |
@@ -2225,10 +2226,6 @@ static char readit(void) // read (maybe cursor) key from stdin | |||
2225 | {"[4~" , VI_K_END }, // Cursor Key End | 2226 | {"[4~" , VI_K_END }, // Cursor Key End |
2226 | {"[5~" , VI_K_PAGEUP }, // Cursor Key Page Up | 2227 | {"[5~" , VI_K_PAGEUP }, // Cursor Key Page Up |
2227 | {"[6~" , VI_K_PAGEDOWN}, // Cursor Key Page Down | 2228 | {"[6~" , VI_K_PAGEDOWN}, // Cursor Key Page Down |
2228 | {"OP" , VI_K_FUN1 }, // Function Key F1 | ||
2229 | {"OQ" , VI_K_FUN2 }, // Function Key F2 | ||
2230 | {"OR" , VI_K_FUN3 }, // Function Key F3 | ||
2231 | {"OS" , VI_K_FUN4 }, // Function Key F4 | ||
2232 | // careful: these have no terminating NUL! | 2229 | // careful: these have no terminating NUL! |
2233 | {"[11~", VI_K_FUN1 }, // Function Key F1 | 2230 | {"[11~", VI_K_FUN1 }, // Function Key F1 |
2234 | {"[12~", VI_K_FUN2 }, // Function Key F2 | 2231 | {"[12~", VI_K_FUN2 }, // Function Key F2 |
@@ -2243,67 +2240,67 @@ static char readit(void) // read (maybe cursor) key from stdin | |||
2243 | {"[23~", VI_K_FUN11 }, // Function Key F11 | 2240 | {"[23~", VI_K_FUN11 }, // Function Key F11 |
2244 | {"[24~", VI_K_FUN12 }, // Function Key F12 | 2241 | {"[24~", VI_K_FUN12 }, // Function Key F12 |
2245 | }; | 2242 | }; |
2246 | enum { ESCCMDS_COUNT = ARRAY_SIZE(esccmds) }; | ||
2247 | 2243 | ||
2248 | fflush(stdout); | 2244 | fflush(stdout); |
2245 | |||
2246 | // If no data, block waiting for input. | ||
2249 | n = chars_to_parse; | 2247 | n = chars_to_parse; |
2250 | // get input from User - are there already input chars in Q? | 2248 | while (!n) { |
2251 | if (n <= 0) { | 2249 | n = safe_read(0, readbuffer, 1); |
2252 | // the Q is empty, wait for a typed char | ||
2253 | again: | ||
2254 | n = safe_read(STDIN_FILENO, readbuffer, sizeof(readbuffer)); | ||
2255 | if (n <= 0) { | 2250 | if (n <= 0) { |
2256 | place_cursor(rows - 1, 0, FALSE); // go to bottom of screen | 2251 | place_cursor(rows - 1, 0, FALSE); // go to bottom of screen |
2257 | clear_to_eol(); // erase to end of line | 2252 | clear_to_eol(); // erase to end of line |
2258 | cookmode(); // terminal to "cooked" | 2253 | cookmode(); // terminal to "cooked" |
2259 | bb_error_msg_and_die("can't read user input"); | 2254 | bb_error_msg_and_die("can't read user input"); |
2260 | } | 2255 | } |
2261 | /* elsewhere we can get very confused by NULs */ | 2256 | // Returning NUL from this routine would be bad. |
2262 | if (readbuffer[0] == '\0') | 2257 | if (*readbuffer) break; |
2263 | goto again; | 2258 | } |
2264 | if (readbuffer[0] == 27) { | 2259 | |
2265 | // This is an ESC char. Is this Esc sequence? | 2260 | // Grab character to return from buffer |
2266 | // Could be bare Esc key. See if there are any | 2261 | c = *readbuffer; |
2267 | // more chars to read after the ESC. This would | 2262 | n--; |
2268 | // be a Function or Cursor Key sequence. | 2263 | if (n) memmove(readbuffer, readbuffer+1, n); |
2269 | struct pollfd pfd[1]; | 2264 | |
2270 | pfd[0].fd = 0; | 2265 | // If it's an escape sequence, loop through known matches. |
2271 | pfd[0].events = POLLIN; | 2266 | if (c == 27) { |
2272 | // keep reading while there are input chars, and room in buffer | 2267 | const struct esc_cmds *eindex; |
2273 | // for a complete ESC sequence (assuming 8 chars is enough) | 2268 | |
2274 | while ((safe_poll(pfd, 1, 0) > 0) | 2269 | for (eindex = esccmds; eindex < esccmds+ARRAY_SIZE(esccmds); eindex++) { |
2275 | && ((size_t)n <= (sizeof(readbuffer) - 8)) | 2270 | int i=0, cnt = strnlen(eindex->seq, 4); |
2276 | ) { | 2271 | |
2277 | // read the rest of the ESC string | 2272 | // Loop through chars in this sequence. |
2278 | int r = safe_read(STDIN_FILENO, readbuffer + n, sizeof(readbuffer) - n); | 2273 | for (;;) { |
2279 | if (r > 0) | 2274 | |
2280 | n += r; | 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) { | ||
2280 | struct pollfd pfd; | ||
2281 | pfd.fd = 0; | ||
2282 | pfd.events = POLLIN; | ||
2283 | if (0 < safe_poll(&pfd, 1, 0) | ||
2284 | && 0 < safe_read(0, readbuffer + n, 1)) | ||
2285 | n++; | ||
2286 | |||
2287 | // Since the array is sorted from shortest to longest, if | ||
2288 | // we needed more data we can't match anything later, so | ||
2289 | // break out of both loops. | ||
2290 | else goto loop_out; | ||
2291 | } | ||
2292 | if (readbuffer[i] != eindex->seq[i]) break; | ||
2293 | if (++i == cnt) { | ||
2294 | c = eindex->val; | ||
2295 | n = 0; | ||
2296 | goto loop_out; | ||
2297 | } | ||
2281 | } | 2298 | } |
2282 | } | 2299 | } |
2283 | chars_to_parse = n; | ||
2284 | } | 2300 | } |
2285 | c = readbuffer[0]; | 2301 | loop_out: |
2286 | if (c == 27 && n > 1) { | ||
2287 | // Maybe cursor or function key? | ||
2288 | const struct esc_cmds *eindex; | ||
2289 | 2302 | ||
2290 | for (eindex = esccmds; eindex < &esccmds[ESCCMDS_COUNT]; eindex++) { | 2303 | chars_to_parse = n; |
2291 | int cnt = strnlen(eindex->seq, 4); | ||
2292 | if (n <= cnt) | ||
2293 | continue; | ||
2294 | if (strncmp(eindex->seq, readbuffer + 1, cnt) != 0) | ||
2295 | continue; | ||
2296 | c = eindex->val; // magic char value | ||
2297 | n = cnt + 1; // squeeze out the ESC sequence | ||
2298 | goto found; | ||
2299 | } | ||
2300 | // defined ESC sequence not found | ||
2301 | } | ||
2302 | n = 1; | ||
2303 | found: | ||
2304 | // remove key sequence from Q | ||
2305 | chars_to_parse -= n; | ||
2306 | memmove(readbuffer, readbuffer + n, sizeof(readbuffer) - n); | ||
2307 | return c; | 2304 | return c; |
2308 | } | 2305 | } |
2309 | 2306 | ||