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.)
+/* 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 *
/* Check to see if we are at a certain keyword (case insensitive) */
/* Returns a pointer to the first character past the keyword */
static char *
static void consider_for_hotkey(struct menu *m, struct menu_entry *me)
{
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] ) {
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;
if ( !m->menu_hotkeys[hotkey] ) {
me->hotkey = hotkey;
m->menu_hotkeys[hotkey] = me;
} else if ( m->parent_entry ) {
refstr_put(m->parent_entry->displayname);
m->parent_entry->displayname = refstrdup(skipspace(p+5));
} 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);
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") ) {
}
}
} else if ( looking_at(p, "title") ) {
#include <stdio.h>
#include "refstr.h"
#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;
const char *refstrndup(const char *str, size_t len)
{
char *r;
return NULL;
len = strnlen(str, 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 NULL;
len = strlen(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;
return r;
}
int vrsprintf(const char **bufp, const char *fmt, va_list ap)
{
va_list ap1;
char *p;
va_copy(ap1, ap);
char *p;
va_copy(ap1, ap);
- bytes = vsnprintf(NULL, 0, fmt, ap1)+1;
+ len = vsnprintf(NULL, 0, fmt, ap1);
- p = malloc(bytes+sizeof(unsigned int));
- if ( !p ) {
- *bufp = NULL;
+ *bufp = p = refstr_alloc(len);
+ if ( !p )
- }
-
- *(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, ...)
}
int rsprintf(const char **bufp, const char *fmt, ...)
}
void refstr_put(const char *);
}
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 *, ...);
const char *refstrdup(const char *);
const char *refstrndup(const char *, size_t);
int rsprintf(const char **, const char *, ...);