On Thu, Aug 18, 2016 at 05:05:03PM +0300, Aleksey Kuleshov wrote: > Signed-off-by: Aleksey Kuleshov <rndfax@xxxxxxxxx> > --- > 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(-) Applied, thanks Sascha > > diff --git a/commands/menu.c b/commands/menu.c > index e1079fd..72db26e 100644 > --- a/commands/menu.c > +++ b/commands/menu.c > @@ -22,6 +22,7 @@ > #include <menu.h> > #include <getopt.h> > #include <errno.h> > +#include <libbb.h> > #include <linux/err.h> > > 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 0e9f27f..bc90502 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 9819569..64df458 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 eb14da0..400d1a6 100644 > --- a/common/menutree.c > +++ b/common/menutree.c > @@ -19,6 +19,7 @@ > #include <shell.h> > #include <libfile.h> > > +#include <linux/ctype.h> > #include <linux/stat.h> > > 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 8b0ffb1..3e704a8 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 > -- > 2.8.0.rc3 > > > _______________________________________________ > barebox mailing list > barebox@xxxxxxxxxxxxxxxxxxx > http://lists.infradead.org/mailman/listinfo/barebox > -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox