summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhpa <hpa>2004-12-21 00:27:17 +0000
committerhpa <hpa>2004-12-21 00:27:17 +0000
commit02b5962d945dcc7a81ba6da1dfb7590f4030244c (patch)
treeeaeb3963d071b93fa3b51b4f3402e58261ebb4b7
parentfc9d1511c2a841c529fe2e6855aaa4e34fef98f5 (diff)
downloadsyslinux-02b5962d945dcc7a81ba6da1dfb7590f4030244c.tar.gz
Add code to edit the command line in the simple menu
-rw-r--r--com32/include/stdio.h3
-rw-r--r--com32/lib/Makefile1
-rw-r--r--com32/libutil/include/getkey.h6
-rw-r--r--com32/modules/menu.c194
4 files changed, 157 insertions, 47 deletions
diff --git a/com32/include/stdio.h b/com32/include/stdio.h
index 0ebe922d..ada42fbe 100644
--- a/com32/include/stdio.h
+++ b/com32/include/stdio.h
@@ -96,6 +96,9 @@ __extern int vsprintf(char *, const char *, va_list);
__extern int snprintf(char *, size_t n, const char *, ...);
__extern int vsnprintf(char *, size_t n, const char *, va_list);
+__extern int asprintf(char **, const char *, ...);
+__extern int vasprintf(char **, const char *, va_list);
+
/* No buffering, so no flushing needed */
extern __inline__ int
fflush(FILE *__f)
diff --git a/com32/lib/Makefile b/com32/lib/Makefile
index 972c63c5..8ba4220e 100644
--- a/com32/lib/Makefile
+++ b/com32/lib/Makefile
@@ -13,6 +13,7 @@ LIBOBJS = abort.o atexit.o atoi.o atol.o atoll.o calloc.o creat.o \
strntoimax.o strntoumax.o strrchr.o strsep.o strspn.o strstr.o \
strtoimax.o strtok.o strtol.o strtoll.o strtoul.o strtoull.o \
strtoumax.o vfprintf.o vprintf.o vsnprintf.o vsprintf.o \
+ asprintf.o vasprintf.o \
vsscanf.o libgcc/__ashldi3.o libgcc/__udivdi3.o \
libgcc/__negdi2.o libgcc/__ashrdi3.o libgcc/__lshrdi3.o \
libgcc/__muldi3.o libgcc/__udivmoddi4.o libgcc/__umoddi3.o \
diff --git a/com32/libutil/include/getkey.h b/com32/libutil/include/getkey.h
index ac5fd2bf..99171e1c 100644
--- a/com32/libutil/include/getkey.h
+++ b/com32/libutil/include/getkey.h
@@ -37,6 +37,12 @@
#include <stdio.h>
+#define KEY_CTRL(x) ((x) & 0x001f)
+#define KEY_BACKSPACE 0x0008
+#define KEY_TAB 0x0009
+#define KEY_ENTER 0x000d
+#define KEY_ESC 0x001b
+
#define KEY_F1 0x0100
#define KEY_F2 0x0101
#define KEY_F3 0x0102
diff --git a/com32/modules/menu.c b/com32/modules/menu.c
index 357952c9..6757a9f9 100644
--- a/com32/modules/menu.c
+++ b/com32/modules/menu.c
@@ -18,6 +18,7 @@
* a command line and/or edit it.
*/
+#define _GNU_SOURCE /* Needed for asprintf() on Linux */
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
@@ -29,35 +30,16 @@
#endif
struct menu_entry {
- const char *displayname;
- const char *cmdline;
+ char *displayname;
+ char *cmdline;
};
-struct menu_entry menu_entries[] =
- {
- { "Test", "vmlinux root=/dev/zero" },
- { "this", "chain.c32 hd0 2" },
- { "entry 3", "runentry val=3" },
- { "entry 4", "runentry val=3" },
- { "entry 5", "runentry val=3" },
- { "entry 6", "runentry val=3" },
- { "entry 7", "runentry val=3" },
- { "entry 8", "runentry val=3" },
- { "entry 9", "runentry val=3" },
- { "entry 10", "runentry val=10" },
- { "entry 11", "runentry val=11" },
- { "entry 12", "runentry val=12" },
- { "entry 13", "runentry val=13" },
- { "entry 14", "runentry val=14" },
- { "entry 15", "runentry val=15" },
- { "entry 16", "runentry val=16" },
- { "entry 17", "runentry val=17" },
- { "entry 18", "runentry val=18" },
- { "entry 19", "runentry val=19" },
- { "entry 20", "runentry val=20" },
- };
-
-int nentries = sizeof menu_entries / sizeof(struct menu_entry);
+#define MAX_CMDLINE_LEN 256
+
+#define MAX_ENTRIES 4096 /* Oughta be enough for anybody */
+struct menu_entry menu_entries[MAX_ENTRIES];
+
+int nentries = 0;
int defentry = 0;
int allowedit = 1; /* Allow edits of the command line */
@@ -68,6 +50,7 @@ struct menu_attrib {
const char *title; /* Title bar */
const char *unsel; /* Unselected menu item */
const char *sel; /* Selected */
+ const char *more; /* [More] tag */
const char *tabmsg; /* Press [Tab] message */
const char *cmdmark; /* Command line marker */
const char *cmdline; /* Command line */
@@ -79,6 +62,7 @@ const struct menu_attrib default_attrib = {
.title = "\033[1;36;44m",
.unsel = "\033[0;37;44m",
.sel = "\033[0;30;47m",
+ .more = "\033[0;37;44m",
.tabmsg = "\033[0;31;40m",
.cmdmark = "\033[1;36;40m",
.cmdline = "\033[0;37;40m",
@@ -134,6 +118,11 @@ void draw_menu(int sel, int top)
putchar('\304');
putchar('\266');
+ if ( top != 0 )
+ printf("%s\033[3;%dH[-]%s",
+ menu_attrib->more, WIDTH-MARGIN-5,
+ menu_attrib->border);
+
for ( y = 4 ; y < 4+MENU_ROWS ; y++ ) {
int i = (y-4)+top;
const char *txt = (i >= nentries) ? "" : menu_entries[i].displayname;
@@ -150,15 +139,89 @@ void draw_menu(int sel, int top)
putchar('\315');
putchar('\274');
+ if ( top < nentries-MENU_ROWS )
+ printf("%s\033[%d;%dH[+]", menu_attrib->more, y, WIDTH-MARGIN-5);
+
if ( allowedit )
printf("%s\033[%d;1H%s", menu_attrib->tabmsg, TABMSG_ROW,
pad_line("Press [Tab] to edit options", 1, WIDTH));
- printf("\033[%d;1H%s> %s%s\033[%d;1H",
- CMDLINE_ROW, menu_attrib->cmdmark,
- menu_attrib->cmdline,
- pad_line(menu_entries[sel].cmdline, 0, 255),
- END_ROW);
+ /* sel == -1 is a valid way of saying "draw nothing" */
+ if ( sel >= 0 ) {
+ printf("\033[%d;1H%s> %s%s\033[%d;1H",
+ CMDLINE_ROW, menu_attrib->cmdmark,
+ menu_attrib->cmdline,
+ pad_line(menu_entries[sel].cmdline, 0, 255),
+ END_ROW);
+ }
+}
+
+char *edit_cmdline(char *input)
+{
+ static char cmdline[MAX_CMDLINE_LEN];
+ int key, len;
+ int redraw = 1;
+
+ strncpy(cmdline, input, MAX_CMDLINE_LEN);
+ cmdline[MAX_CMDLINE_LEN-1] = '\0';
+
+ len = strlen(cmdline);
+
+ for (;;) {
+ if ( redraw ) {
+ printf("\033[%d;1H%s> %s%s",
+ CMDLINE_ROW, menu_attrib->cmdmark,
+ menu_attrib->cmdline, pad_line(cmdline, 0, MAX_CMDLINE_LEN-1));
+ printf("%s\033[%d;3H%s",
+ menu_attrib->cmdline, CMDLINE_ROW, cmdline);
+ redraw = 0;
+ }
+
+ key = get_key(stdin);
+
+ /* FIX: should handle arrow keys and edit-in-middle */
+
+ switch( key ) {
+ case KEY_ENTER:
+ case KEY_CTRL('J'):
+ return cmdline;
+ case KEY_ESC:
+ case KEY_CTRL('C'):
+ return NULL;
+ case KEY_BACKSPACE:
+ case KEY_DEL:
+ case '\x7F':
+ if ( len ) {
+ cmdline[--len] = '\0';
+ redraw = 1;
+ }
+ break;
+ case KEY_CTRL('U'):
+ if ( len ) {
+ len = 0;
+ cmdline[len] = 0;
+ redraw = 1;
+ }
+ break;
+ case KEY_CTRL('W'):
+ if ( len ) {
+ int wasbs = (cmdline[len-1] <= ' ');
+ while ( len && (cmdline[len-1] <= ' ' || !wasbs) ) {
+ len--;
+ wasbs = wasbs || (cmdline[len-1] <= ' ');
+ }
+ redraw = 1;
+ }
+ break;
+ default:
+ if ( key >= ' ' && key <= 0xFF && len < MAX_CMDLINE_LEN-1 ) {
+ cmdline[len] = key;
+ cmdline[++len] = '\0';
+ putchar(key);
+ }
+ break;
+ }
+ }
}
const char *run_menu(void)
@@ -167,38 +230,70 @@ const char *run_menu(void)
int done = 0;
int entry = defentry;
int top = 0;
+ char *cmdline;
/* Start with a clear screen */
printf("%s\033[2J", menu_attrib->screen);
while ( !done ) {
- if ( top < entry-MENU_ROWS+1 )
- top = max(entry-MENU_ROWS+1, 0);
+ if ( entry < 0 )
+ entry = 0;
+ else if ( entry >= nentries )
+ entry = nentries-1;
+
+ if ( top < 0 || top < entry-MENU_ROWS+1 )
+ top = max(0,entry-MENU_ROWS+1);
else if ( top > entry )
- top = min(entry, nentries-MENU_ROWS+1);
+ top = entry;
draw_menu(entry, top);
- gkey:
key = get_key(stdin);
switch ( key ) {
- case '\r':
+ case KEY_ENTER:
+ case KEY_CTRL('J'):
done = 1;
break;
+ case 'P':
+ case 'p':
case KEY_UP:
- if ( entry > 0 )
- entry--;
+ entry--;
break;
+ case 'N':
+ case 'n':
case KEY_DOWN:
- if ( entry < nentries-1 )
- entry++;
+ entry++;
+ break;
+ case KEY_CTRL('P'):
+ case KEY_PGUP:
+ entry -= MENU_ROWS;
+ top -= MENU_ROWS;
+ break;
+ case KEY_CTRL('N'):
+ case KEY_PGDN:
+ case ' ':
+ entry += MENU_ROWS;
+ top += MENU_ROWS;
break;
- case '\003': /* Ctrl-C */
- case '\033': /* Esc */
+ case '-':
+ entry--;
+ top--;
+ break;
+ case '+':
+ entry++;
+ top++;
+ break;
+ case KEY_TAB:
+ draw_menu(-1, top); /* Disable bar */
+ cmdline = edit_cmdline(menu_entries[entry].cmdline);
+ if ( cmdline )
+ return cmdline;
+ break;
+ case KEY_CTRL('C'): /* Ctrl-C */
+ case KEY_ESC: /* Esc */
exit(1); /* FIX THIS... do something sane here */
default:
- printf("[%04x]", key);
- goto gkey;
+ break;
}
}
@@ -228,13 +323,18 @@ void __attribute__((noreturn)) execute(const char *cmdline)
int main(void)
{
const char *cmdline;
+ int i;
console_ansi_raw();
fputs("\033%@\033(U", stdout); /* Enable CP 437 graphics on a real console */
+ for ( i = 1 ; i < 30 ; i++ ) {
+ asprintf(&menu_entries[nentries].displayname, "entry %2d", i);
+ asprintf(&menu_entries[nentries].cmdline, "runentry n=%d", i);
+ nentries++;
+ }
+
cmdline = run_menu();
execute(cmdline);
}
-
-