[syslinux:master] menu: Add "menu hiddenkey" to make terminating menu hidden a command

syslinux-bot for H. Peter Anvin hpa at linux.intel.com
Mon Apr 18 13:54:18 PDT 2011


Commit-ID:  a8e74b2834664543166744cf0832e1d6db36347f
Gitweb:     http://syslinux.zytor.com/commit/a8e74b2834664543166744cf0832e1d6db36347f
Author:     H. Peter Anvin <hpa at linux.intel.com>
AuthorDate: Mon, 11 Apr 2011 14:59:45 -0700
Committer:  H. Peter Anvin <hpa at linux.intel.com>
CommitDate: Mon, 11 Apr 2011 15:06:38 -0700

menu: Add "menu hiddenkey" to make terminating menu hidden a command

Use "menu hiddenkey" together with "menu hidden" for a one-keystroke
action.

Signed-off-by: H. Peter Anvin <hpa at linux.intel.com>


---
 com32/libutil/Makefile         |    3 +-
 com32/libutil/include/getkey.h |    4 +
 com32/libutil/keyname.c        |  133 ++++++++++++++++++++++++++++++++++++++++
 com32/menu/menu.h              |    2 +
 com32/menu/menumain.c          |    2 +-
 com32/menu/readconfig.c        |   31 +++++++++-
 doc/menu.txt                   |   16 +++++
 7 files changed, 188 insertions(+), 3 deletions(-)

diff --git a/com32/libutil/Makefile b/com32/libutil/Makefile
index 02789ca..7a6b527 100644
--- a/com32/libutil/Makefile
+++ b/com32/libutil/Makefile
@@ -32,7 +32,8 @@
 topdir = ../..
 include ../MCONFIG
 
-LIBOBJS	   = ansiline.o ansiraw.o get_key.o sha1hash.o unbase64.o \
+LIBOBJS	   = ansiline.o ansiraw.o get_key.o keyname.o \
+	     sha1hash.o unbase64.o \
 	     md5.o crypt-md5.o sha256crypt.o sha512crypt.o base64.o
 LNXLIBOBJS = $(patsubst %.o,%.lo,$(LIBOBJS))
 
diff --git a/com32/libutil/include/getkey.h b/com32/libutil/include/getkey.h
index 52312a2..a46de81 100644
--- a/com32/libutil/include/getkey.h
+++ b/com32/libutil/include/getkey.h
@@ -75,6 +75,10 @@
 #define KEY_INSERT	0x0128
 #define KEY_DELETE	0x0129
 
+#define KEY_MAX		0x012a
+
 int get_key(FILE *, clock_t);
+int key_name_to_code(const char *);
+const char *key_code_to_name(int);
 
 #endif /* LIBUTIL_GETKEY_H */
diff --git a/com32/libutil/keyname.c b/com32/libutil/keyname.c
new file mode 100644
index 0000000..6aebbd5
--- /dev/null
+++ b/com32/libutil/keyname.c
@@ -0,0 +1,133 @@
+/* ----------------------------------------------------------------------- *
+ *
+ *   Copyright 2011 Intel Corporation; author: H. Peter Anvin
+ *
+ *   Permission is hereby granted, free of charge, to any person
+ *   obtaining a copy of this software and associated documentation
+ *   files (the "Software"), to deal in the Software without
+ *   restriction, including without limitation the rights to use,
+ *   copy, modify, merge, publish, distribute, sublicense, and/or
+ *   sell copies of the Software, and to permit persons to whom
+ *   the Software is furnished to do so, subject to the following
+ *   conditions:
+ *
+ *   The above copyright notice and this permission notice shall
+ *   be included in all copies or substantial portions of the Software.
+ *
+ *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *   OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * keyname.c
+ *
+ * Conversion between strings and get_key() key numbers.
+ */
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/times.h>
+#include <getkey.h>
+#include <libutil.h>
+
+struct keyname {
+    const char *string;
+    int key;
+};
+
+static const struct keyname key_names[] = {
+    { "Backspace", KEY_BACKSPACE },
+    { "Tab", KEY_TAB },
+    { "Enter", KEY_ENTER },
+    { "Esc", KEY_ESC },
+    { "Escape", KEY_ESC },
+    { "Space", ' ' },
+    { "^?", KEY_DEL },
+    { "F1", KEY_F1 },
+    { "F2", KEY_F2},
+    { "F3", KEY_F3 },
+    { "F4", KEY_F4 },
+    { "F5", KEY_F5 },
+    { "F6", KEY_F6 },
+    { "F7", KEY_F7 },
+    { "F8", KEY_F8 },
+    { "F9", KEY_F9 },
+    { "F10", KEY_F10 },
+    { "F11", KEY_F11 },
+    { "F12", KEY_F12 },
+    { "Up", KEY_UP },
+    { "Down", KEY_DOWN },
+    { "Left", KEY_LEFT },
+    { "Right", KEY_RIGHT },
+    { "PgUp", KEY_PGUP },
+    { "PgDn", KEY_PGDN },
+    { "Home", KEY_HOME },
+    { "End", KEY_END },
+    { "Insert", KEY_INSERT },
+    { "Delete", KEY_DELETE },
+    { NULL, KEY_NONE }
+};
+
+int key_name_to_code(const char *code)
+{
+    const struct keyname *name;
+
+    if (code[0] && !code[1]) {
+	/* Single character */
+	return (unsigned char)code[0];
+    } else if (code[0] == '^' && code[1] && !code[2]) {
+	/* Control character */
+	if (code[1] == '?')
+	    return 0x7f;
+	else
+	    return (unsigned char)code[1] & 0x9f;
+    }
+
+
+    for (name = key_names; name->string; name++) {
+	if (!strcasecmp(name->string, code))
+	    break;
+    }
+    return name->key;	/* KEY_NONE at end of array */
+}
+
+const char *key_code_to_name(int key)
+{
+    static char buf[4];
+    const struct keyname *name;
+
+    if (key < 0)
+	return NULL;
+
+    if (key < 0x100 && key != ' ') {
+	if (key == 0x7f) {
+	    return "^?";
+	} else if (key & 0x60) {
+	    buf[0] = key;
+	    buf[1] = '\0';
+	} else {
+	    buf[0] = '^';
+	    buf[1] = key | 0x40;
+	    buf[2] = '\0';
+	}
+	return buf;
+    }
+
+    for (name = key_names; name->string; name++) {
+	if (key == name->key)
+	    return name->string;
+    }
+
+    return NULL;
+}
diff --git a/com32/menu/menu.h b/com32/menu/menu.h
index 36c5669..1db4d7c 100644
--- a/com32/menu/menu.h
+++ b/com32/menu/menu.h
@@ -26,6 +26,7 @@
 #include <unistd.h>
 #include <colortbl.h>
 #include <stdbool.h>
+#include <getkey.h>
 #include "refstr.h"
 
 /* #define DEBUG 1 */
@@ -186,6 +187,7 @@ extern int shiftkey;
 extern int hiddenmenu;
 extern int clearmenu;
 extern long long totaltimeout;
+extern const char *hide_key[KEY_MAX];
 
 void parse_configs(char **argv);
 int draw_background(const char *filename);
diff --git a/com32/menu/menumain.c b/com32/menu/menumain.c
index 06725f3..df1eb18 100644
--- a/com32/menu/menumain.c
+++ b/com32/menu/menumain.c
@@ -727,7 +727,7 @@ static const char *do_hidden_menu(void)
 	    key = mygetkey(this_timeout);
 
 	    if (key != KEY_NONE)
-		return NULL;	/* Key pressed */
+		return hide_key[key]; /* NULL if no MENU HIDEKEY in effect */
 
 	    timeout_left -= this_timeout;
 	}
diff --git a/com32/menu/readconfig.c b/com32/menu/readconfig.c
index f3b0f96..1d02120 100644
--- a/com32/menu/readconfig.c
+++ b/com32/menu/readconfig.c
@@ -1,7 +1,7 @@
 /* ----------------------------------------------------------------------- *
  *
  *   Copyright 2004-2009 H. Peter Anvin - All Rights Reserved
- *   Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
+ *   Copyright 2009-2011 Intel Corporation; author: H. Peter Anvin
  *
  *   This program is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -37,6 +37,7 @@ int shiftkey = 0;		/* Only display menu if shift key pressed */
 int hiddenmenu = 0;
 int clearmenu = 0;
 long long totaltimeout = 0;
+const char *hide_key[KEY_MAX];
 
 /* Keep track of global default */
 static int has_ui = 0;		/* DEFAULT only counts if UI is found */
@@ -141,6 +142,22 @@ static char *looking_at(char *line, const char *kwd)
     return my_isspace(*p) ? p : NULL;	/* Must be EOL or whitespace */
 }
 
+/* Get a single word into a new refstr; advances the input pointer */
+static char *get_word(char *str, const char **word)
+{
+    char *p = str;
+    char *q;
+
+    while (*p && !my_isspace(*p))
+	p++;
+
+    *word = q = refstr_alloc(p - str + 1);
+    memcpy(q, str, p - str);
+    /* refstr_alloc() already inserted a terminating NUL */
+
+    return p;
+}
+
 static struct menu *new_menu(struct menu *parent,
 			     struct menu_entry *parent_entry, const char *label)
 {
@@ -703,6 +720,18 @@ static void parse_config_file(FILE * f)
 		m->menu_background = refdup_word(&p);
 	    } else if ((ep = looking_at(p, "hidden"))) {
 		hiddenmenu = 1;
+	    } else if (looking_at(p, "hiddenkey")) {
+		const char *key_name;
+		int key;
+		p = skipspace(p + 7);
+		p = get_word(p, &key_name);
+		p = skipspace(p);
+		key = key_name_to_code(key_name);
+		refstr_put(key_name);
+		if (key >= 0) {
+		    refstr_put(hide_key[key]);
+		    hide_key[key] = refstrdup(skipspace(p));
+		}
 	    } else if ((ep = looking_at(p, "clear"))) {
 		clearmenu = 1;
 	    } else if ((ep = is_message_name(p, &msgnr))) {
diff --git a/doc/menu.txt b/doc/menu.txt
index e2dd1e1..892de48 100644
--- a/doc/menu.txt
+++ b/doc/menu.txt
@@ -48,6 +48,22 @@ MENU HIDDEN
 	All that is displayed is a timeout message.
 
 
+MENU HIDDENKEY key command...
+
+	If they key used to interrupt MENU HIDDEN is <key>, then
+	execute the specified command instead of displaying the menu.
+
+	Currently, the following key names are recognized:
+
+	Backspace, Tab, Enter, Esc, Space, F1..F12, Up, Down, Left,
+	Right, PgUp, PgDn, Home, End, Insert, Delete
+
+	... in addition to all single characters plus the syntax ^X
+	for Ctrl-X.  Note that single characters are treated as case
+	sensitive, so a different command can be bound to "A" than
+	"a".
+	
+
 MENU CLEAR
 
 	Clear the screen when exiting the menu, instead of leaving the



More information about the Syslinux-commits mailing list