From 539774207847fdff4e9202262b34642cfbcda7ba Mon Sep 17 00:00:00 2001 From: Aleksey Kuleshov Date: Wed, 17 Aug 2016 11:52:04 +0300 Subject: fix double free it already gets free in bootentries_free no need to do this in ->release method Signed-off-by: Aleksey Kuleshov Signed-off-by: Sascha Hauer --- common/boot.c | 1 - 1 file changed, 1 deletion(-) (limited to 'common/boot.c') diff --git a/common/boot.c b/common/boot.c index e66bacbb0e..8502464aa2 100644 --- a/common/boot.c +++ b/common/boot.c @@ -165,7 +165,6 @@ static void bootscript_entry_release(struct bootentry *entry) struct bootentry_script *bs = container_of(entry, struct bootentry_script, entry); free(bs->scriptpath); - free(bs->entry.me.display); free(bs); } -- cgit v1.2.3 From d0b8f4e0752fbe5e44fd9b2e6143ce80c0f5d4eb Mon Sep 17 00:00:00 2001 From: Aleksey Kuleshov Date: Wed, 17 Aug 2016 12:04:31 +0300 Subject: properly remove menu entry Signed-off-by: Aleksey Kuleshov Signed-off-by: Sascha Hauer --- common/boot.c | 1 + 1 file changed, 1 insertion(+) (limited to 'common/boot.c') diff --git a/common/boot.c b/common/boot.c index 8502464aa2..0e9f27f9bc 100644 --- a/common/boot.c +++ b/common/boot.c @@ -318,6 +318,7 @@ void bootsources_menu(struct bootentries *bootentries, int timeout) menu_show(bootentries->menu); + menu_remove_entry(bootentries->menu, back_entry); free(back_entry); } -- cgit v1.2.3 From bf2abf90501858a97bf1e05024d963800312a5c4 Mon Sep 17 00:00:00 2001 From: Aleksey Kuleshov Date: Thu, 18 Aug 2016 17:05:03 +0300 Subject: rework menu so that it can support multiline titles Signed-off-by: Aleksey Kuleshov Signed-off-by: Sascha Hauer --- commands/menu.c | 23 +++++++++++++--- common/boot.c | 8 ++++-- common/menu.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++------- common/menutree.c | 9 +++++-- include/menu.h | 6 ++++- 5 files changed, 108 insertions(+), 19 deletions(-) (limited to 'common/boot.c') diff --git a/commands/menu.c b/commands/menu.c index e1079fd51e..72db26e5d1 100644 --- a/commands/menu.c +++ b/commands/menu.c @@ -22,6 +22,7 @@ #include #include #include +#include #include typedef enum { @@ -146,9 +147,7 @@ static int do_menu_add(struct cmd_menu *cm) if (!m->name) goto free; - m->display = strdup(cm->description); - if (!m->display) - goto free; + menu_add_title(m, strdup(cm->description)); ret = menu_add(m); @@ -271,7 +270,23 @@ static int do_menu_list(struct cmd_menu *cm) } list_for_each_entry(m, &menus->list, list) { - printf("%s: %s\n", m->name, m->display? m->display : m->name); + printf("%s: ", m->name); + if (m->display_lines) { + static char outstr[256]; + int i; + + printf("\n"); + for (i = 0; i < m->display_lines; i++) + /* Conform to menu rendering logic */ + if (IS_ENABLED(CONFIG_SHELL_HUSH)) { + process_escape_sequence(m->display[i], outstr, 256); + printf("\t%s\n", outstr); + } else { + printf("\t%s\n", m->display[i]); + } + } else { + printf("%s\n", m->name); + } if (is_entry(cm)) print_entries(m); } diff --git a/common/boot.c b/common/boot.c index 0e9f27f9bc..bc90502284 100644 --- a/common/boot.c +++ b/common/boot.c @@ -43,7 +43,7 @@ struct bootentries *bootentries_alloc(void) if (IS_ENABLED(CONFIG_MENU)) { bootentries->menu = menu_alloc(); - bootentries->menu->display = basprintf("boot"); + menu_add_title(bootentries->menu, basprintf("boot")); } return bootentries; @@ -61,8 +61,12 @@ void bootentries_free(struct bootentries *bootentries) be->release(be); } - if (bootentries->menu) + if (bootentries->menu) { + int i; + for (i = 0; i < bootentries->menu->display_lines; i++) + free(bootentries->menu->display[i]); free(bootentries->menu->display); + } free(bootentries->menu); free(bootentries); } diff --git a/common/menu.c b/common/menu.c index 9819569f6f..64df458e68 100644 --- a/common/menu.c +++ b/common/menu.c @@ -43,10 +43,13 @@ EXPORT_SYMBOL(menu_get_menus); void menu_free(struct menu *m) { struct menu_entry *me, *tmp; + int i; if (!m) return; free(m->name); + for (i = 0; i < m->display_lines; i++) + free(m->display[i]); free(m->display); free(m->auto_display); @@ -164,7 +167,7 @@ static void __print_entry(const char *str) static void print_menu_entry(struct menu *m, struct menu_entry *me, int selected) { - gotoXY(3, me->num + 1); + gotoXY(3, me->num + m->display_lines); if (me->type == MENU_ENTRY_BOX) { if (me->box_state) @@ -232,14 +235,12 @@ EXPORT_SYMBOL(menu_set_auto_select); static void print_menu(struct menu *m) { struct menu_entry *me; + int i; clear(); - gotoXY(2, 1); - if(m->display) { - __print_entry(m->display); - } else { - puts("Menu : "); - puts(m->name); + for (i = 0; i < m->display_lines; i++) { + gotoXY(2, 1 + i); + __print_entry(m->display[i]); } list_for_each_entry(me, &m->entries, list) { @@ -269,7 +270,7 @@ int menu_show(struct menu *m) countdown = m->auto_select; if (m->auto_select >= 0) { - gotoXY(3, m->nb_entries + 2); + gotoXY(3, m->nb_entries + m->display_lines + 1); if (!m->auto_display) { printf("Auto Select in"); } else { @@ -293,10 +294,10 @@ int menu_show(struct menu *m) } } - gotoXY(3, m->nb_entries + 2); + gotoXY(3, m->nb_entries + m->display_lines + 1); printf("%*c", auto_display_len + 4, ' '); - gotoXY(3, m->selected->num + 1); + gotoXY(3, m->selected->num + m->display_lines); do { struct menu_entry *old_selected = m->selected; @@ -517,3 +518,63 @@ err_free: return ERR_PTR(ret); } EXPORT_SYMBOL(menu_add_command_entry); + +/* + * Add title to menu. + * Lines are separated by explicit char '\n' or by string "\n". + * + * @display: NULL or pointer to the string which will be freed in this function. + * If NULL or zero length string is provided, default title will be added. + */ +void menu_add_title(struct menu *m, char *display) +{ + char *tmp, *src, *dst; + int lines = 1; + int i; + + if (!display || !strlen(display)) { + free(display); + display = xasprintf("Menu : %s", m->name ? m->name : ""); + } + + src = dst = tmp = xstrdup(display); + /* Count lines and separate single string into multiple strings */ + while (*src) { + if (*src == '\\') { + if (*(src + 1) == '\\') { + *dst++ = *src++; + *dst++ = *src++; + continue; + } + if (*(src + 1) == 'n') { + *dst = 0; + src += 2; + dst++; + lines++; + continue; + } + } + if (*src == '\n') { + *dst = 0; + src++; + dst++; + lines++; + continue; + } + *dst++ = *src++; + } + *dst = 0; + + m->display = xzalloc(sizeof(*m->display) * lines); + m->display_lines = lines; + + for (src = tmp, i = 0; i < lines; i++) { + m->display[i] = xstrdup(src); + /* Go to the next line */ + src += strlen(src) + 1; + } + + free(tmp); + free(display); +} +EXPORT_SYMBOL(menu_add_title); diff --git a/common/menutree.c b/common/menutree.c index eb14da0d01..400d1a6939 100644 --- a/common/menutree.c +++ b/common/menutree.c @@ -19,6 +19,7 @@ #include #include +#include #include struct menutree { @@ -95,6 +96,7 @@ int menutree(const char *path, int toplevel) glob_t g; int i; char *globpath, *display; + size_t size; menu = menu_alloc(); @@ -106,14 +108,17 @@ int menutree(const char *path, int toplevel) goto out; } - display = read_file_line("%s/title", path); + globpath = basprintf("%s/title", path); + display = read_file(globpath, &size); + free(globpath); if (!display) { eprintf("no title found in %s/title\n", path); ret = -EINVAL; goto out; } - menu->display = shell_expand(display); + strim(display); + menu_add_title(menu, shell_expand(display)); free(display); for (i = 0; i < g.gl_pathc; i++) { diff --git a/include/menu.h b/include/menu.h index 8b0ffb1f83..3e704a8907 100644 --- a/include/menu.h +++ b/include/menu.h @@ -47,7 +47,10 @@ struct menu_entry { struct menu { char *name; - char *display; + /* Multiline title */ + char **display; + /* Number of lines */ + int display_lines; int auto_select; char *auto_display; @@ -88,6 +91,7 @@ int menu_set_selected_entry(struct menu *m, struct menu_entry* me); int menu_set_selected(struct menu *m, int num); int menu_set_auto_select(struct menu *m, int delay); struct menu* menu_get_menus(void); +void menu_add_title(struct menu *m, char *display); /* * menu entry functions -- cgit v1.2.3