summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhpa <hpa>2004-12-21 23:31:45 +0000
committerhpa <hpa>2004-12-21 23:31:45 +0000
commitcb23ea204292a261a85bc1f9b15a9db46c3d690e (patch)
tree76a023cbfb5129c4a7aa0752a8ff3c4633dc8697
parentc81c57367f2abbb1003de78990ead873c857193d (diff)
downloadsyslinux-cb23ea204292a261a85bc1f9b15a9db46c3d690e.tar.gz
Support timeout in the menusyslinux-2.20-pre12
-rw-r--r--com32/include/sys/times.h4
-rw-r--r--com32/libutil/get_key.c22
-rw-r--r--com32/libutil/include/getkey.h5
-rw-r--r--com32/modules/menu.c47
-rw-r--r--com32/samples/keytest.c2
5 files changed, 60 insertions, 20 deletions
diff --git a/com32/include/sys/times.h b/com32/include/sys/times.h
index 173efe2a..8d03af0a 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 b9042d6d..5cc147f8 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 99171e1c..37efc668 100644
--- a/com32/libutil/include/getkey.h
+++ b/com32/libutil/include/getkey.h
@@ -36,6 +36,9 @@
#define LIBUTIL_GETKEY_H
#include <stdio.h>
+#include <sys/times.h>
+
+#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 c9794c24..fe4d94a5 100644
--- a/com32/modules/menu.c
+++ b/com32/modules/menu.c
@@ -25,12 +25,19 @@
#include <consoles.h>
#include <getkey.h>
#include <minmax.h>
+#include <time.h>
+#include <sys/times.h>
+#include <unistd.h>
#ifdef __COM32__
#include <com32.h>
#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 d10bd665..0433201e 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");