diff options
author | Denys Vlasenko | 2009-05-17 16:44:54 +0200 |
---|---|---|
committer | Denys Vlasenko | 2009-05-17 16:44:54 +0200 |
commit | 020f40693a08b836abdea74f3823a0bce0378ec5 (patch) | |
tree | 4ae11c9b2156cccc1af8904c11c195b25b2886b0 /libbb/read_key.c | |
parent | 071ede1e5de784820f39c2546000c08d74b12f6d (diff) | |
download | busybox-020f40693a08b836abdea74f3823a0bce0378ec5.zip busybox-020f40693a08b836abdea74f3823a0bce0378ec5.tar.gz |
line editing: add an option to emit ESC [ 6 n and use results
This makes line editing able to recognize case when
cursor was not at the beginning of the line. It may also
be adapted later to find out display size (serial line users
would love it).
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'libbb/read_key.c')
-rw-r--r-- | libbb/read_key.c | 57 |
1 files changed, 49 insertions, 8 deletions
diff --git a/libbb/read_key.c b/libbb/read_key.c index fd100b0..3771045 100644 --- a/libbb/read_key.c +++ b/libbb/read_key.c @@ -9,7 +9,7 @@ */ #include "libbb.h" -int FAST_FUNC read_key(int fd, smalluint *nbuffered, char *buffer) +int64_t FAST_FUNC read_key(int fd, char *buffer) { struct pollfd pfd; const char *seq; @@ -67,9 +67,7 @@ int FAST_FUNC read_key(int fd, smalluint *nbuffered, char *buffer) }; errno = 0; - n = 0; - if (nbuffered) - n = *nbuffered; + n = (unsigned char) *buffer++; if (n == 0) { /* If no data, block waiting for input. If we read more * than the minimal ESC sequence size, the "n=0" below @@ -148,11 +146,54 @@ int FAST_FUNC read_key(int fd, smalluint *nbuffered, char *buffer) } } /* We did not find matching sequence, it was a bare ESC. - * We possibly read and stored more input in buffer[] - * by now. */ + * We possibly read and stored more input in buffer[] by now. */ + + /* Try to decipher "ESC [ NNN ; NNN R" sequence */ + if (ENABLE_FEATURE_EDITING_ASK_TERMINAL + && n != 0 + && buffer[0] == '[' + ) { + char *end; + unsigned long row, col; + + while (n < KEYCODE_BUFFER_SIZE-1) { /* 1 for cnt */ + if (safe_poll(&pfd, 1, 50) == 0) { + /* No more data! */ + break; + } + errno = 0; + if (safe_read(fd, buffer + n, 1) <= 0) { + /* If EAGAIN, then fd is O_NONBLOCK and poll lied: + * in fact, there is no data. */ + if (errno != EAGAIN) + c = -1; /* otherwise it's EOF/error */ + goto ret; + } + if (buffer[n++] == 'R') + goto got_R; + } + goto ret; + got_R: + if (!isdigit(buffer[1])) + goto ret; + row = strtoul(buffer + 1, &end, 10); + if (*end != ';' || !isdigit(end[1])) + goto ret; + col = strtoul(end + 1, &end, 10); + if (*end != 'R') + goto ret; + if (row < 1 || col < 1 || (row | col) > 0x7fff) + goto ret; + + buffer[-1] = 0; + + /* Pack into "1 <row15bits> <col16bits>" 32-bit sequence */ + c = (((-1 << 15) | row) << 16) | col; + /* Return it in high-order word */ + return ((int64_t) c << 32) | (uint32_t)KEYCODE_CURSOR_POS; + } ret: - if (nbuffered) - *nbuffered = n; + buffer[-1] = n; return c; } |