From e2bfd46bfc6372501d9379f5251bd97cce04ff3c Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 19 Feb 2008 16:16:03 -0800 Subject: [PATCH] simple menu: The use of realloc() requires indirect pointers Since we store pointers to struct menu_entry, we can't put it in storage that is subject to realloc(). Accordingly, make menu_entries an indirect array instead. --- com32/menu/menu.h | 3 ++- com32/menu/menumain.c | 51 ++++++++++++++++++++++++++++--------------------- com32/menu/readconfig.c | 12 ++++++------ 3 files changed, 37 insertions(+), 29 deletions(-) diff --git a/com32/menu/menu.h b/com32/menu/menu.h index 62b2f46a..99d378e5 100644 --- a/com32/menu/menu.h +++ b/com32/menu/menu.h @@ -45,6 +45,7 @@ enum menu_action { }; struct menu_entry { + int entry; /* Entry number inside menu */ const char *displayname; const char *label; const char *passwd; @@ -134,7 +135,7 @@ struct menu { struct menu *parent; struct menu_entry *parent_entry; /* Entry for self in parent */ - struct menu_entry *menu_entries; + struct menu_entry **menu_entries; struct menu_entry *menu_hotkeys[256]; const char *messages[MSG_COUNT]; diff --git a/com32/menu/menumain.c b/com32/menu/menumain.c index 84fe2b0e..fb6a99f9 100644 --- a/com32/menu/menumain.c +++ b/com32/menu/menumain.c @@ -131,7 +131,7 @@ static void draw_row(int y, int sel, int top, int sbtop, int sbbot) { int i = (y-4-VSHIFT)+top; - int dis = (i < cm->nentries) && is_disabled(&cm->menu_entries[i]); + int dis = (i < cm->nentries) && is_disabled(cm->menu_entries[i]); printf("\033[%d;%dH\1#1\016x\017%s ", y, MARGIN+1+HSHIFT, @@ -140,7 +140,7 @@ draw_row(int y, int sel, int top, int sbtop, int sbbot) if ( i >= cm->nentries ) { fputs(pad_line("", 0, WIDTH-2*MARGIN-4), stdout); } else { - display_entry(&cm->menu_entries[i], + display_entry(cm->menu_entries[i], (i == sel) ? "\1#5" : dis ? "\2#17" : "\1#3", (i == sel) ? "\1#6" : dis ? "\2#17" : "\1#4", WIDTH-2*MARGIN-4); @@ -676,7 +676,7 @@ do_hidden_menu(void) } } - return cm->menu_entries[cm->defentry].cmdline; /* Default entry */ + return cm->menu_entries[cm->defentry]->cmdline; /* Default entry */ } static const char * @@ -689,6 +689,7 @@ run_menu(void) int clear = 1, to_clear; const char *cmdline = NULL; volatile clock_t key_timeout, timeout_left, this_timeout; + const struct menu_entry *me; /* Note: for both key_timeout and timeout == 0 means no limit */ timeout_left = key_timeout = cm->timeout; @@ -696,7 +697,7 @@ run_menu(void) /* If we're in shiftkey mode, exit immediately unless a shift key is pressed */ if ( shiftkey && !shift_is_held() ) { - return cm->menu_entries[cm->defentry].cmdline; + return cm->menu_entries[cm->defentry]->cmdline; } else { shiftkey = 0; } @@ -726,23 +727,25 @@ run_menu(void) top = min(entry, max(0, cm->nentries-MENU_ROWS)); draw_menu(cm->ontimeout ? -1 : entry, top, 1); - cmdline = cm->ontimeout ? cm->ontimeout : cm->menu_entries[entry].cmdline; + cmdline = cm->ontimeout ? cm->ontimeout : cm->menu_entries[entry]->cmdline; done = 1; } while ( !done ) { if ( entry <= 0 ) { entry = 0; - while (entry < cm->nentries && is_disabled(&cm->menu_entries[entry])) + while (entry < cm->nentries && is_disabled(cm->menu_entries[entry])) entry++; } if ( entry >= cm->nentries ) { entry = cm->nentries-1; - while (entry > 0 && is_disabled(&cm->menu_entries[entry])) + while (entry > 0 && is_disabled(cm->menu_entries[entry])) entry--; } + me = cm->menu_entries[entry]; + if ( top < 0 || top < entry-MENU_ROWS+1 ) top = max(0, entry-MENU_ROWS+1); else if ( top > entry || top > max(0, cm->nentries-MENU_ROWS) ) @@ -762,11 +765,11 @@ run_menu(void) if ( top != prev_top ) { draw_menu(entry, top, 1); - display_help(cm->menu_entries[entry].helptext); + display_help(me->helptext); } else if ( entry != prev_entry ) { draw_row(prev_entry-top+4+VSHIFT, entry, top, 0, 0); draw_row(entry-top+4+VSHIFT, entry, top, 0, 0); - display_help(cm->menu_entries[entry].helptext); + display_help(me->helptext); } prev_entry = entry; prev_top = top; @@ -815,23 +818,23 @@ run_menu(void) case KEY_ENTER: case KEY_CTRL('J'): key_timeout = 0; /* Cancels timeout */ - if ( cm->menu_entries[entry].passwd ) { + if ( me->passwd ) { clear = 1; - done = ask_passwd(cm->menu_entries[entry].passwd); + done = ask_passwd(me->passwd); } else { done = 1; } cmdline = NULL; if (done) { - switch (cm->menu_entries[entry].action) { + switch (me->action) { case MA_CMD: - cmdline = cm->menu_entries[entry].cmdline; + cmdline = me->cmdline; break; case MA_SUBMENU: case MA_GOTO: done = 0; clear = 2; - cm = cm->menu_entries[entry].submenu; + cm = me->submenu; entry = top = 0; break; case MA_QUIT: @@ -849,13 +852,13 @@ run_menu(void) case KEY_UP: case KEY_CTRL('P'): - while (entry > 0 && entry-- && is_disabled(&cm->menu_entries[entry])) { + while (entry > 0 && entry-- && is_disabled(cm->menu_entries[entry])) { if ( entry < top ) top -= MENU_ROWS; } if ( entry == 0 ) { - while (is_disabled(&cm->menu_entries[entry])) + while (is_disabled(cm->menu_entries[entry])) entry++; } break; @@ -863,13 +866,13 @@ run_menu(void) case KEY_DOWN: case KEY_CTRL('N'): while (entry < cm->nentries-1 && entry++ && - is_disabled(&cm->menu_entries[entry])) { + is_disabled(cm->menu_entries[entry])) { if ( entry >= top+MENU_ROWS ) top += MENU_ROWS; } if ( entry >= cm->nentries-1 ) { - while (is_disabled(&cm->menu_entries[entry])) + while (is_disabled(cm->menu_entries[entry])) entry--; } break; @@ -929,7 +932,7 @@ run_menu(void) break; case KEY_TAB: - if ( cm->allowedit ) { + if ( cm->allowedit && me->action == MA_CMD ) { int ok = 1; key_timeout = 0; /* Cancels timeout */ @@ -946,7 +949,7 @@ run_menu(void) } if ( ok ) { - cmdline = edit_cmdline(cm->menu_entries[entry].cmdline, top); + cmdline = edit_cmdline(me->cmdline, top); done = !!cmdline; clear = 1; /* In case we hit [Esc] and done is null */ } else { @@ -956,7 +959,11 @@ run_menu(void) break; case KEY_CTRL('C'): /* Ctrl-C */ case KEY_ESC: /* Esc */ - if ( cm->allowedit ) { + if ( cm->parent ) { + cm = cm->parent; + clear = 2; + entry = top = 0; + } else if ( cm->allowedit ) { done = 1; clear = 1; key_timeout = 0; @@ -972,7 +979,7 @@ run_menu(void) key &= ~0x20; /* Upper case */ if ( cm->menu_hotkeys[key] ) { key_timeout = 0; - entry = cm->menu_hotkeys[key] - cm->menu_entries; + entry = cm->menu_hotkeys[key]->entry; /* Should we commit at this point? */ } } diff --git a/com32/menu/readconfig.c b/com32/menu/readconfig.c index 4c2ecbd4..c3f2da4b 100644 --- a/com32/menu/readconfig.c +++ b/com32/menu/readconfig.c @@ -211,12 +211,12 @@ static struct menu_entry *new_entry(struct menu *m) m->nentries_space <<= 1; m->menu_entries = realloc(m->menu_entries, m->nentries_space* - sizeof(struct menu_entry)); + sizeof(struct menu_entry *)); } - me = &m->menu_entries[m->nentries++]; - memset(me, 0, sizeof *me); - + me = calloc(1, sizeof(struct menu_entry)); + me->entry = m->nentries; + m->menu_entries[m->nentries++] = me; *all_entries_end = me; all_entries_end = &me->next; @@ -367,8 +367,8 @@ static const char *unlabel(const char *str) /* p now points to the first byte beyond the kernel name */ pos = p-str; - for ( me = all_entries ; me ; me = me->next ) { - if ( !strncmp(str, me->label, pos) && !me->label[pos] ) { + for (me = all_entries; me; me = me->next) { + if (!strncmp(str, me->label, pos) && !me->label[pos]) { /* Found matching label */ rsprintf(&q, "%s%s", me->cmdline, p); refstr_put(str); -- 2.11.4.GIT