aboutsummaryrefslogtreecommitdiff
path: root/libbb/read_key.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-05-17 16:44:54 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-05-17 16:44:54 +0200
commit020f40693a08b836abdea74f3823a0bce0378ec5 (patch)
tree4ae11c9b2156cccc1af8904c11c195b25b2886b0 /libbb/read_key.c
parent071ede1e5de784820f39c2546000c08d74b12f6d (diff)
downloadbusybox-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.c57
1 files changed, 49 insertions, 8 deletions
diff --git a/libbb/read_key.c b/libbb/read_key.c
index fd100b0ec..3771045d2 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;
}