aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2016-01-07 14:34:47 -0600
committerRob Landley <rob@landley.net>2016-01-07 14:34:47 -0600
commitefb309d4cdb2f4c3926b0550d9dc1661c1e4a091 (patch)
treeaee8bfabdaf7ecf20d0ad54f97df9f3bb1ca840e
parentd3a435e53c94ec25b4ae5fa2614f49ef8884e08a (diff)
downloadtoybox-efb309d4cdb2f4c3926b0550d9dc1661c1e4a091.tar.gz
Make scan_key() specify timeout in miliseconds, split out terminal_probesize(),
add function key definitions and shift/ctrl/alt cursor keys.
-rw-r--r--lib/interestingtimes.c56
-rw-r--r--lib/lib.h5
-rw-r--r--toys/example/test_scankey.c19
-rw-r--r--toys/other/hexedit.c2
4 files changed, 51 insertions, 31 deletions
diff --git a/lib/interestingtimes.c b/lib/interestingtimes.c
index 612d9d6e..70fd4f9b 100644
--- a/lib/interestingtimes.c
+++ b/lib/interestingtimes.c
@@ -46,31 +46,28 @@ int terminal_size(unsigned *xx, unsigned *yy)
return x || y;
}
-// Wrapper that parses results from ANSI probe. If block|2 query size and
-// send ANSI probe if we can't. (Probe queries xterm size through
-// serial connection, when local TTY doesn't know and only remote end knows.)
-// Otherwise acts like scan_key()
-int scan_key_getsize(char *scratch, int block, unsigned *xx, unsigned *yy)
+// Query terminal size, sending ANSI probe if necesary. (Probe queries xterm
+// size through serial connection, when local TTY doesn't know but remote does.)
+// Returns 0 if ANSI probe sent, 1 if size determined from tty or environment
+
+int terminal_probesize(unsigned *xx, unsigned *yy)
{
- int key;
+ if (terminal_size(xx, yy) && (!xx || *xx) && (!yy || *yy)) return 1;
- if (block&2) {
- struct pollfd pfd;
+ // Send probe: bookmark cursor position, jump to bottom right,
+ // query position, return cursor to bookmarked position.
+ xprintf("\e[s\e[999C\e[999B\e[6n\e[u");
- if (terminal_size(xx, yy)) {
- if (!(block&1)) return -2;
- } else {
- // Send probe: bookmark cursor position, jump to bottom right,
- // query position, return cursor to bookmarked position.
- xprintf("\e[s\e[999C\e[999B\e[6n\e[u");
+ return 0;
+}
- // Wait up to a quarter second for a result
- memset(&pfd, 0, sizeof(struct pollfd));
- pfd.events = POLLIN;
- xpoll(&pfd, 0, 250);
- }
- }
- while (512&(key = scan_key(scratch, block&1))) {
+// Wrapper that parses results from ANSI probe to update screensize.
+// Otherwise acts like scan_key()
+int scan_key_getsize(char *scratch, int miliwait, unsigned *xx, unsigned *yy)
+{
+ int key;
+
+ while (512&(key = scan_key(scratch, miliwait))) {
if (key<0) break;
if (xx) *xx = (key>>10)&1023;
if (yy) *yy = (key>>20)&1023;
@@ -120,20 +117,27 @@ struct scan_key_list {
{"UP", "\033[A"}, {"DOWN", "\033[B"}, {"RIGHT", "\033[C"}, {"LEFT", "\033[D"},
{"PGUP", "\033[5~"}, {"PGDN", "\033[6~"}, {"HOME", "\033OH"},
{"END", "\033OF"}, {"INSERT", "\033[2~"},
+
+ {"F1", "\033OP"}, {"F2", "\033OQ"}, {"F3", "\033OR"}, {"F4", "\033OS"},
+ {"F5", "\033[15~"}, {"F6", "\033[17~"}, {"F7", "\033[18~"},
+ {"F8", "\033[19~"}, {"F9", "\033[20~"},
+
{"SUP", "\033[1;2A"}, {"AUP", "\033[1;3A"}, {"CUP", "\033[1;5A"},
{"SDOWN", "\033[1;2B"}, {"ADOWN", "\033[1;3B"}, {"CDOWN", "\033[1;5B"},
{"SRIGHT", "\033[1;2C"}, {"ARIGHT", "\033[1;3C"}, {"CRIGHT", "\033[1;5C"},
- {"SLEFT", "\033[1;2D"}, {"ALEFT", "\033[1;3D"}, {"CLEFT", "\033[1;5D"}
+ {"SLEFT", "\033[1;2D"}, {"ALEFT", "\033[1;3D"}, {"CLEFT", "\033[1;5D"},
+ {"SF1", "\033O1;2P"}, {"AF1", "\033O1;3P"}, {"CF1", "\033[1;5P"}
);
// Scan stdin for a keypress, parsing known escape sequences
+// Blocks for miliwait miliseconds, none 0, forever if -1
// Returns: 0-255=literal, -1=EOF, -2=NONE, 256-...=index into scan_key_list
// >512 is x<<9+y<<21
// scratch space is necessary because last char of !seq could start new seq
// Zero out first byte of scratch before first call to scan_key
// block=0 allows fetching multiple characters before updating display
-int scan_key(char *scratch, int block)
+int scan_key(char *scratch, int miliwait)
{
struct pollfd pfd;
int maybe, i, j;
@@ -151,7 +155,8 @@ int scan_key(char *scratch, int block)
// Check for return from terminal size probe
memset(pos, 0, 6*sizeof(int));
- sscanf(scratch+1, "\033%n[%n%3u%n,%n%3u%nR%n", pos, pos+1, &y,
+ scratch[(1+*scratch)&15] = 0;
+ sscanf(scratch+1, "\033%n[%n%3u%n;%n%3u%nR%n", pos, pos+1, &y,
pos+2, pos+3, &x, pos+4, pos+5);
if (pos[5]) {
// Recognized X/Y position, consume and return
@@ -180,7 +185,8 @@ int scan_key(char *scratch, int block)
// Need more data to decide
// 30 miliseconds is about the gap between characters at 300 baud
- if (maybe || !block) if (!xpoll(&pfd, 1, 30*maybe)) break;
+ if (maybe || miliwait != -1)
+ if (!xpoll(&pfd, 1, maybe ? 30 : miliwait)) break;
// Read 1 byte so we don't overshoot sequence match. (We can deviate
// and fail to match, but match consumes entire buffer.)
diff --git a/lib/lib.h b/lib/lib.h
index d56cdbe3..ade7c59b 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -221,9 +221,10 @@ int draw_rstr(char *start, int width, int (*escout)(FILE *out, wchar_t wc));
// interestingtimes.c
int xgettty(void);
int terminal_size(unsigned *xx, unsigned *yy);
-int scan_key_getsize(char *scratch, int block, unsigned *xx, unsigned *yy);
+int terminal_probesize(unsigned *xx, unsigned *yy);
+int scan_key_getsize(char *scratch, int miliwait, unsigned *xx, unsigned *yy);
int set_terminal(int fd, int raw, struct termios *old);
-int scan_key(char *scratch, int block);
+int scan_key(char *scratch, int miliwait);
void tty_esc(char *s);
void tty_jump(int x, int y);
void tty_reset(void);
diff --git a/toys/example/test_scankey.c b/toys/example/test_scankey.c
index 65c07204..57177416 100644
--- a/toys/example/test_scankey.c
+++ b/toys/example/test_scankey.c
@@ -1,6 +1,8 @@
/* test_scankey.c - collate incoming ansi escape sequences.
*
* Copyright 2015 Rob Landley <rob@landley.net>
+ *
+ * TODO sigwinch
USE_TEST_SCANKEY(NEWTOY(test_scankey, 0, 0))
@@ -37,10 +39,21 @@ void test_scankey_main(void)
tty_jump(x, y);
xputc(c);
t[1&++tick] = time(0);
- key = scan_key_getsize(scratch, !!t[0]+2*(t[0] != t[1]), &width, &height);
+ if (t[0] != t[1]) terminal_probesize(&width, &height);
+ // Don't block first time through, to force header print
+ key = scan_key_getsize(scratch, -1*!!t[0], &width, &height);
tty_jump(0, 0);
- printf("ESC to exit: key=%d x=%d y=%d width=%d height=%d ",
- key, x, y, width, height);
+ printf("ESC to exit: ");
+ // Print unknown escape sequence
+ if (*scratch) {
+ printf("key=[ESC");
+ // Fetch rest of sequence after deviation, time gap determines end
+ while (0<(key = scan_key_getsize(scratch, 0, &width, &height)))
+ printf("%c", key);
+ printf("] ");
+ } else printf("key=%d ", key);
+ printf("x=%d y=%d width=%d height=%d\033[K", x, y, width, height);
+ fflush(0);
if (key == -2) continue;
if (key <= ' ') break;
diff --git a/toys/other/hexedit.c b/toys/other/hexedit.c
index c45ef1ca..3c362dbd 100644
--- a/toys/other/hexedit.c
+++ b/toys/other/hexedit.c
@@ -176,7 +176,7 @@ void hexedit_main(void)
xflush();
// Wait for next key
- key = scan_key(keybuf, 1);
+ key = scan_key(keybuf, -1);
// Exit for q, ctrl-c, ctrl-d, escape, or EOF
if (key==-1 || key==3 || key==4 || key==27 || key=='q') break;
highlight(x, y, 2);