From cb23ea204292a261a85bc1f9b15a9db46c3d690e Mon Sep 17 00:00:00 2001 From: hpa Date: Tue, 21 Dec 2004 23:31:45 +0000 Subject: [PATCH] Support timeout in the menu --- com32/include/sys/times.h | 4 ++-- com32/libutil/get_key.c | 22 ++++++++++++-------- com32/libutil/include/getkey.h | 5 ++++- com32/modules/menu.c | 47 +++++++++++++++++++++++++++++++++++------- com32/samples/keytest.c | 2 +- 5 files changed, 60 insertions(+), 20 deletions(-) diff --git a/com32/include/sys/times.h b/com32/include/sys/times.h index 173efe2..8d03af0 100644 --- a/com32/include/sys/times.h +++ b/com32/include/sys/times.h @@ -11,8 +11,8 @@ struct tms { /* Empty */ }; -#define HZ 18 /* Piddly resolution... */ -#define CLK_TCK HZ +#define HZ 18 /* Piddly resolution... */ +#define CLK_TCK HZ typedef uint16_t clock_t; diff --git a/com32/libutil/get_key.c b/com32/libutil/get_key.c index b9042d6..5cc147f 100644 --- a/com32/libutil/get_key.c +++ b/com32/libutil/get_key.c @@ -111,7 +111,7 @@ static const struct keycode keycodes[] = { }; #define NCODES ((int)(sizeof keycodes/sizeof(struct keycode))) -int get_key(FILE *f) +int get_key(FILE *f, clock_t timeout) { unsigned char buffer[MAXLEN]; int nc, i, rv; @@ -120,19 +120,23 @@ int get_key(FILE *f) unsigned char ch; clock_t start; + /* We typically start in the middle of a clock tick */ + if ( timeout ) + timeout++; + nc = 0; start = times(NULL); do { rv = read(fileno(f), &ch, 1); if ( rv == 0 || (rv == -1 && errno == EAGAIN) ) { - if ( nc && (clock_t)(times(NULL)-start) >= 2+CLK_TCK/20 ) - return buffer[0]; /* timeout */ - else { - if ( !nc ) - start = times(NULL); - another = 1; - continue; - } + clock_t lateness = times(NULL)-start; + if ( nc && lateness > 1+CLK_TCK/20 ) + return buffer[0]; /* timeout in sequence */ + else if ( !nc && timeout && lateness > timeout ) + return KEY_NONE; /* timeout before sequence */ + + another = 1; + continue; } start = times(NULL); diff --git a/com32/libutil/include/getkey.h b/com32/libutil/include/getkey.h index 99171e1..37efc66 100644 --- a/com32/libutil/include/getkey.h +++ b/com32/libutil/include/getkey.h @@ -36,6 +36,9 @@ #define LIBUTIL_GETKEY_H #include +#include + +#define KEY_NONE (-1) #define KEY_CTRL(x) ((x) & 0x001f) #define KEY_BACKSPACE 0x0008 @@ -67,6 +70,6 @@ #define KEY_INS 0x0128 #define KEY_DEL 0x0129 -int get_key(FILE *); +int get_key(FILE *, clock_t); #endif /* LIBUTIL_GETKEY_H */ diff --git a/com32/modules/menu.c b/com32/modules/menu.c index c9794c2..fe4d94a 100644 --- a/com32/modules/menu.c +++ b/com32/modules/menu.c @@ -25,12 +25,19 @@ #include #include #include +#include +#include +#include #ifdef __COM32__ #include #endif #include "menu.h" +#ifndef CLK_TCK +# define CLK_TCK sysconf(_SC_CLK_TCK) +#endif + struct menu_attrib { const char *border; /* Border area */ const char *title; /* Title bar */ @@ -135,11 +142,11 @@ void draw_menu(int sel, int top) printf("%s\033[%d;1H", menu_attrib->screen, END_ROW); } -char *edit_cmdline(char *input) +char *edit_cmdline(char *input, int top) { static char cmdline[MAX_CMDLINE_LEN]; int key, len; - int redraw = 1; + int redraw = 2; strncpy(cmdline, input, MAX_CMDLINE_LEN); cmdline[MAX_CMDLINE_LEN-1] = '\0'; @@ -147,7 +154,14 @@ char *edit_cmdline(char *input) len = strlen(cmdline); for (;;) { - if ( redraw ) { + if ( redraw > 1 ) { + /* Clear and redraw whole screen */ + printf("%s\033[2J", menu_attrib->screen); + draw_menu(-1, top); + } + + if ( redraw > 0 ) { + /* Redraw the command line */ printf("\033[%d;1H%s> %s%s", CMDLINE_ROW, menu_attrib->cmdmark, menu_attrib->cmdline, pad_line(cmdline, 0, MAX_CMDLINE_LEN-1)); @@ -156,11 +170,14 @@ char *edit_cmdline(char *input) redraw = 0; } - key = get_key(stdin); + key = get_key(stdin, 0); /* FIX: should handle arrow keys and edit-in-middle */ switch( key ) { + case KEY_CTRL('L'): + redraw = 2; + break; case KEY_ENTER: case KEY_CTRL('J'): return cmdline; @@ -212,6 +229,11 @@ const char *run_menu(void) int top = 0; int clear = 1; char *cmdline; + clock_t key_timeout; + + /* Convert timeout from deciseconds to clock ticks */ + /* Note: for both key_timeout and timeout == 0 means no limit */ + key_timeout = (clock_t)(CLK_TCK*timeout+9)/10; while ( !done ) { if ( entry < 0 ) @@ -231,8 +253,20 @@ const char *run_menu(void) draw_menu(entry, top); - key = get_key(stdin); + key = get_key(stdin, key_timeout); switch ( key ) { + case KEY_NONE: /* Timeout */ + /* This is somewhat hacky, but this at least lets the user + know what's going on, and still deals with "phantom inputs" + e.g. on serial ports. */ + if ( entry != defentry ) + entry = defentry; + else + done = 1; + break; + case KEY_CTRL('L'): + clear = 1; + break; case KEY_ENTER: case KEY_CTRL('J'): done = 1; @@ -268,8 +302,7 @@ const char *run_menu(void) break; case KEY_TAB: if ( allowedit ) { - draw_menu(-1, top); /* Disable bar */ - cmdline = edit_cmdline(menu_entries[entry].cmdline); + cmdline = edit_cmdline(menu_entries[entry].cmdline, top); if ( cmdline ) return cmdline; else diff --git a/com32/samples/keytest.c b/com32/samples/keytest.c index d10bd66..0433201 100644 --- a/com32/samples/keytest.c +++ b/com32/samples/keytest.c @@ -33,7 +33,7 @@ static void cooked_keys(void) printf("[cooked]"); for(;;) { - key = get_key(stdin); + key = get_key(stdin, 0); if ( key == 0x03 ) { printf("[done]\n"); -- 2.7.4