X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=common%2Fmenu.c;h=5fb2ffbd065d4ed8a3dd22dddf81e8d121be5b83;hb=dd5b0fad8f295c6e786f1528d09f03fa546289cd;hp=56439374f7464734440e040ba44214b917f1de87;hpb=b69bf52dfe34b9d7b2a20845c8a7e7e5978c2d2f;p=oweals%2Fu-boot.git diff --git a/common/menu.c b/common/menu.c index 56439374f7..5fb2ffbd06 100644 --- a/common/menu.c +++ b/common/menu.c @@ -1,21 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2010-2011 Calxeda, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . + * Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. */ #include +#include #include #include #include @@ -43,10 +33,15 @@ struct menu_item { */ struct menu { struct menu_item *default_item; + int timeout; char *title; int prompt; + void (*display_statusline)(struct menu *); void (*item_data_print)(void *); + char *(*item_choice)(void *); + void *item_choice_data; struct list_head items; + int item_cnt; }; /* @@ -86,10 +81,12 @@ static inline void *menu_item_print(struct menu *m, struct menu_item *item, void *extra) { - if (!m->item_data_print) - printf("%s\n", item->key); - else + if (!m->item_data_print) { + puts(item->key); + putc('\n'); + } else { m->item_data_print(item->data); + } return NULL; } @@ -116,8 +113,12 @@ static inline void *menu_item_destroy(struct menu *m, */ static inline void menu_display(struct menu *m) { - if (m->title) - printf("%s:\n", m->title); + if (m->title) { + puts(m->title); + putc('\n'); + } + if (m->display_statusline) + m->display_statusline(m); menu_items_iter(m, menu_item_print, NULL); } @@ -157,21 +158,11 @@ static inline struct menu_item *menu_item_by_key(struct menu *m, return menu_items_iter(m, menu_item_key_match, item_key); } -/* - * Checks whether or not the default menu item should be used without - * prompting for a user choice. If the menu is set to always prompt, return - * 0. Otherwise, return 1 to indicate we should use the default menu item. - */ -static inline int menu_use_default(struct menu *m) -{ - return !m->prompt; -} - /* * Set *choice to point to the default item's data, if any default item was * set, and returns 1. If no default item was set, returns -ENOENT. */ -static inline int menu_default_choice(struct menu *m, void **choice) +int menu_default_choice(struct menu *m, void **choice) { if (m->default_item) { *choice = m->default_item->data; @@ -201,17 +192,29 @@ static inline int menu_interactive_choice(struct menu *m, void **choice) menu_display(m); - readret = readline_into_buffer("Enter choice: ", cbuf); - - if (readret >= 0) { - choice_item = menu_item_by_key(m, cbuf); - - if (!choice_item) - printf("%s not found\n", cbuf); + if (!m->item_choice) { + readret = cli_readline_into_buffer("Enter choice: ", + cbuf, m->timeout); + + if (readret >= 0) { + choice_item = menu_item_by_key(m, cbuf); + if (!choice_item) + printf("%s not found\n", cbuf); + } else if (readret == -1) { + printf("\n"); + return -EINTR; + } else { + return menu_default_choice(m, choice); + } } else { - printf("^C\n"); - return -EINTR; + char *key = m->item_choice(m->item_choice_data); + + if (key) + choice_item = menu_item_by_key(m, key); } + + if (!choice_item) + m->timeout = 0; } *choice = choice_item->data; @@ -250,7 +253,8 @@ int menu_default_set(struct menu *m, char *item_key) /* * menu_get_choice() - Returns the user's selected menu entry, or the default - * if the menu is set to not prompt. This is safe to call more than once. + * if the menu is set to not prompt or the timeout expires. This is safe to + * call more than once. * * m - Points to a menu created by menu_create(). * @@ -259,15 +263,15 @@ int menu_default_set(struct menu *m, char *item_key) * written at the location it points to. * * Returns 1 if successful, -EINVAL if m or choice is NULL, -ENOENT if no - * default has been set and the menu is set to not prompt, or -EINTR if the - * user exits the menu via ^c. + * default has been set and the menu is set to not prompt or the timeout + * expires, or -EINTR if the user exits the menu via ^c. */ int menu_get_choice(struct menu *m, void **choice) { if (!m || !choice) return -EINVAL; - if (menu_use_default(m)) + if (!m->prompt || m->item_cnt == 1) return menu_default_choice(m, choice); return menu_interactive_choice(m, choice); @@ -319,6 +323,7 @@ int menu_item_add(struct menu *m, char *item_key, void *item_data) item->data = item_data; list_add_tail(&item->list, &m->items); + m->item_cnt++; return 1; } @@ -330,7 +335,15 @@ int menu_item_add(struct menu *m, char *item_key, void *item_data) * list of menu items. It will be copied to internal storage, and is safe to * discard after passing to menu_create(). * - * prompt - If 0, don't ask for user input. + * timeout - A delay in seconds to wait for user input. If 0, timeout is + * disabled, and the default choice will be returned unless prompt is 1. + * + * prompt - If 0, don't ask for user input unless there is an interrupted + * timeout. If 1, the user will be prompted for input regardless of the value + * of timeout. + * + * display_statusline - If not NULL, will be called to show a statusline when + * the menu is displayed. * * item_data_print - If not NULL, will be called for each item when the menu * is displayed, with the pointer to the item's data passed as the argument. @@ -338,11 +351,20 @@ int menu_item_add(struct menu *m, char *item_key, void *item_data) * what must be entered to select an item, the item_data_print function should * make it obvious what the key for each entry is. * + * item_choice - If not NULL, will be called when asking the user to choose an + * item. Returns a key string corresponding to the chosen item or NULL if + * no item has been selected. + * + * item_choice_data - Will be passed as the argument to the item_choice function + * * Returns a pointer to the menu if successful, or NULL if there is * insufficient memory available to create the menu. */ -struct menu *menu_create(char *title, int prompt, - void (*item_data_print)(void *)) +struct menu *menu_create(char *title, int timeout, int prompt, + void (*display_statusline)(struct menu *), + void (*item_data_print)(void *), + char *(*item_choice)(void *), + void *item_choice_data) { struct menu *m; @@ -353,7 +375,12 @@ struct menu *menu_create(char *title, int prompt, m->default_item = NULL; m->prompt = prompt; + m->timeout = timeout; + m->display_statusline = display_statusline; m->item_data_print = item_data_print; + m->item_choice = item_choice; + m->item_choice_data = item_choice_data; + m->item_cnt = 0; if (title) { m->title = strdup(title);