X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=common%2Fmenu.c;h=5fb2ffbd065d4ed8a3dd22dddf81e8d121be5b83;hb=dd5b0fad8f295c6e786f1528d09f03fa546289cd;hp=6b2a2db3e0acae40f1332a349057de8ab96b161c;hpb=8594753ba0a7151e9352f1994b829f6c2d44a023;p=oweals%2Fu-boot.git
diff --git a/common/menu.c b/common/menu.c
index 6b2a2db3e0..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
@@ -46,8 +36,12 @@ struct menu {
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;
};
/*
@@ -113,13 +107,6 @@ static inline void *menu_item_destroy(struct menu *m,
return NULL;
}
-void __menu_display_statusline(struct menu *m)
-{
- return;
-}
-void menu_display_statusline(struct menu *m)
- __attribute__ ((weak, alias("__menu_display_statusline")));
-
/*
* Display a menu so the user can make a choice of an item. First display its
* title, if any, and then each item in the menu.
@@ -130,7 +117,8 @@ static inline void menu_display(struct menu *m)
puts(m->title);
putc('\n');
}
- menu_display_statusline(m);
+ if (m->display_statusline)
+ m->display_statusline(m);
menu_items_iter(m, menu_item_print, NULL);
}
@@ -174,7 +162,7 @@ static inline struct menu_item *menu_item_by_key(struct menu *m,
* 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;
@@ -204,18 +192,29 @@ static inline int menu_interactive_choice(struct menu *m, void **choice)
menu_display(m);
- readret = readline_into_buffer("Enter choice: ", cbuf,
- m->timeout / 10);
+ 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 {
+ char *key = m->item_choice(m->item_choice_data);
- if (readret >= 0) {
- choice_item = menu_item_by_key(m, cbuf);
+ if (key)
+ choice_item = menu_item_by_key(m, key);
+ }
- if (!choice_item) {
- printf("%s not found\n", cbuf);
- m->timeout = 0;
- }
- } else
- return menu_default_choice(m, choice);
+ if (!choice_item)
+ m->timeout = 0;
}
*choice = choice_item->data;
@@ -272,7 +271,7 @@ int menu_get_choice(struct menu *m, void **choice)
if (!m || !choice)
return -EINVAL;
- if (!m->prompt)
+ if (!m->prompt || m->item_cnt == 1)
return menu_default_choice(m, choice);
return menu_interactive_choice(m, choice);
@@ -324,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;
}
@@ -342,17 +342,29 @@ int menu_item_add(struct menu *m, char *item_key, void *item_data)
* 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.
* If NULL, each item's key will be printed instead. Since an item's key is
* 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 timeout, int prompt,
- void (*item_data_print)(void *))
+ void (*display_statusline)(struct menu *),
+ void (*item_data_print)(void *),
+ char *(*item_choice)(void *),
+ void *item_choice_data)
{
struct menu *m;
@@ -364,7 +376,11 @@ struct menu *menu_create(char *title, int timeout, 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);