summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-02-22 11:03:34 -0800
committerH. Peter Anvin <hpa@zytor.com>2008-02-22 11:03:34 -0800
commit44e9cab0e6bc5a7a75d8470e7a4ba41d739f4a37 (patch)
tree596fa498ea69ab61b30e6fa35199783728b1da7a
parent728ef8ec0fc80014676bb55ded7136353ce6eff4 (diff)
downloadsyslinux-44e9cab0e6bc5a7a75d8470e7a4ba41d739f4a37.tar.gz
Fix the handling of hotkeys in MENU LABEL on submenussyslinux-3.62-pre14
Two bugs: - We didn't strip ^ symbols inheriting from MENU LABEL to MENU TITLE - We did consider_for_hotkey() with the wrong menu (the submenu itself, as opposed to the parent menu.) As part of these changes, make a function available to create an uninitialized, mutable refstring (that can be constructed and then used as a refstring, that is.)
-rw-r--r--com32/menu/readconfig.c39
-rw-r--r--com32/menu/refstr.c45
-rw-r--r--com32/menu/refstr.h1
3 files changed, 59 insertions, 26 deletions
diff --git a/com32/menu/readconfig.c b/com32/menu/readconfig.c
index a17beb2f..65e230d5 100644
--- a/com32/menu/readconfig.c
+++ b/com32/menu/readconfig.c
@@ -93,6 +93,36 @@ skipspace(char *p)
return p;
}
+/* Strip ^ from a string, returning a new reference to the same refstring
+ if none present */
+static const char *strip_caret(const char *str)
+{
+ const char *p, *r;
+ char *q;
+ int carets = 0;
+
+ p = str;
+ for (;;) {
+ p = strchr(p, '^');
+ if (!p)
+ break;
+ carets++;
+ p++;
+ }
+
+ if (!carets)
+ return refstr_get(str);
+
+ r = q = refstr_alloc(strlen(str)-carets);
+ for (p = str; *p; p++)
+ if (*p != '^')
+ *q++ = *p;
+
+ *q = '\0'; /* refstr_alloc() already did this... */
+
+ return r;
+}
+
/* Check to see if we are at a certain keyword (case insensitive) */
/* Returns a pointer to the first character past the keyword */
static char *
@@ -223,12 +253,11 @@ static struct menu_entry *new_entry(struct menu *m)
static void consider_for_hotkey(struct menu *m, struct menu_entry *me)
{
- unsigned char *p =
- (unsigned char *)strchr(me->displayname, '^');
+ const char *p = strchr(me->displayname, '^');
if (me->action != MA_DISABLED) {
if ( p && p[1] ) {
- int hotkey = p[1] & ~0x20;
+ unsigned char hotkey = p[1] & ~0x20;
if ( !m->menu_hotkeys[hotkey] ) {
me->hotkey = hotkey;
m->menu_hotkeys[hotkey] = me;
@@ -571,11 +600,11 @@ static void parse_config_file(FILE *f)
} else if ( m->parent_entry ) {
refstr_put(m->parent_entry->displayname);
m->parent_entry->displayname = refstrdup(skipspace(p+5));
- consider_for_hotkey(m, m->parent_entry);
+ consider_for_hotkey(m->parent, m->parent_entry);
if (!m->title[0]) {
/* MENU LABEL -> MENU TITLE on submenu */
refstr_put(m->title);
- m->title = refstr_get(m->parent_entry->displayname);
+ m->title = strip_caret(m->parent_entry->displayname);
}
}
} else if ( looking_at(p, "title") ) {
diff --git a/com32/menu/refstr.c b/com32/menu/refstr.c
index 868a8ac8..f727abc4 100644
--- a/com32/menu/refstr.c
+++ b/com32/menu/refstr.c
@@ -21,6 +21,19 @@
#include <stdio.h>
#include "refstr.h"
+/* Allocate space for a refstring of len bytes, plus final null */
+/* The final null is inserted in the string; the rest is uninitialized. */
+char *refstr_alloc(size_t len)
+{
+ char *r = malloc(sizeof(unsigned int)+len+1);
+ if (!r)
+ return NULL;
+ *(unsigned int *)r = 1;
+ r += sizeof(unsigned int);
+ r[len] = '\0';
+ return r;
+}
+
const char *refstrndup(const char *str, size_t len)
{
char *r;
@@ -29,11 +42,9 @@ const char *refstrndup(const char *str, size_t len)
return NULL;
len = strnlen(str, len);
- r = malloc(sizeof(unsigned int)+len+1);
- *(unsigned int *)r = 1;
- r += sizeof(unsigned int);
- memcpy(r, str, len);
- r[len] = '\0';
+ r = refstr_alloc(len);
+ if (r)
+ memcpy(r, str, len);
return r;
}
@@ -46,35 +57,27 @@ const char *refstrdup(const char *str)
return NULL;
len = strlen(str);
- r = malloc(sizeof(unsigned int)+len+1);
- *(unsigned int *)r = 1;
- r += sizeof(unsigned int);
- memcpy(r, str, len);
- r[len] = '\0';
+ r = refstr_alloc(len);
+ if (r)
+ memcpy(r, str, len);
return r;
}
int vrsprintf(const char **bufp, const char *fmt, va_list ap)
{
va_list ap1;
- int bytes;
+ int len;
char *p;
va_copy(ap1, ap);
- bytes = vsnprintf(NULL, 0, fmt, ap1)+1;
+ len = vsnprintf(NULL, 0, fmt, ap1);
va_end(ap1);
- p = malloc(bytes+sizeof(unsigned int));
- if ( !p ) {
- *bufp = NULL;
+ *bufp = p = refstr_alloc(len);
+ if ( !p )
return -1;
- }
-
- *(unsigned int *)p = 1;
- p += sizeof(unsigned int);
- *bufp = p;
- return vsnprintf(p, bytes, fmt, ap);
+ return vsnprintf(p, len+1, fmt, ap);
}
int rsprintf(const char **bufp, const char *fmt, ...)
diff --git a/com32/menu/refstr.h b/com32/menu/refstr.h
index 8bec0182..f51777d0 100644
--- a/com32/menu/refstr.h
+++ b/com32/menu/refstr.h
@@ -31,6 +31,7 @@ const char *refstr_get(const char *r)
}
void refstr_put(const char *);
+char *refstr_alloc(size_t);
const char *refstrdup(const char *);
const char *refstrndup(const char *, size_t);
int rsprintf(const char **, const char *, ...);