]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - common/menu.c
image: Use ENOENT instead of ENOMEDIUM for better compatibility
[karo-tx-uboot.git] / common / menu.c
index aa16c9a199d772f7bd9971e401efdb883bf06895..64b461abb491b8584d8cfc76087c0c808e8d7ebc 100644 (file)
@@ -47,6 +47,8 @@ struct menu {
        char *title;
        int prompt;
        void (*item_data_print)(void *);
+       char *(*item_choice)(void *);
+       void *item_choice_data;
        struct list_head items;
 };
 
@@ -170,37 +172,11 @@ static inline struct menu_item *menu_item_by_key(struct menu *m,
        return menu_items_iter(m, menu_item_key_match, item_key);
 }
 
-/*
- * Wait for the user to hit a key according to the timeout set for the menu.
- * Returns 1 if the user hit a key, or 0 if the timeout expired.
- */
-static inline int menu_interrupted(struct menu *m)
-{
-       if (!m->timeout)
-               return 0;
-
-       if (abortboot(m->timeout/10))
-               return 1;
-
-       return 0;
-}
-
-/*
- * 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, or the
- * user hits a key during the timeout period, 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 && !menu_interrupted(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;
@@ -230,20 +206,26 @@ static inline int menu_interactive_choice(struct menu *m, void **choice)
 
                menu_display(m);
 
-               readret = readline_into_buffer("Enter choice: ", cbuf,
-                               m->timeout);
-
-               if (readret >= 0) {
-                       choice_item = menu_item_by_key(m, cbuf);
+               if (!m->item_choice) {
+                       readret = readline_into_buffer("Enter choice: ", cbuf,
+                                       m->timeout / 10);
 
-                       if (!choice_item) {
-                               printf("%s not found\n", cbuf);
-                               m->timeout = 0;
+                       if (readret >= 0) {
+                               choice_item = menu_item_by_key(m, cbuf);
+                               if (!choice_item)
+                                       printf("%s not found\n", cbuf);
+                       } else {
+                               return menu_default_choice(m, choice);
                        }
                } else {
-                       puts("^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;
@@ -300,7 +282,7 @@ int menu_get_choice(struct menu *m, void **choice)
        if (!m || !choice)
                return -EINVAL;
 
-       if (menu_use_default(m))
+       if (!m->prompt)
                return menu_default_choice(m, choice);
 
        return menu_interactive_choice(m, choice);
@@ -376,11 +358,19 @@ 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 choosen 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 (*item_data_print)(void *),
+                               char *(*item_choice)(void *),
+                               void *item_choice_data)
 {
        struct menu *m;
 
@@ -393,6 +383,8 @@ struct menu *menu_create(char *title, int timeout, int prompt,
        m->prompt = prompt;
        m->timeout = timeout;
        m->item_data_print = item_data_print;
+       m->item_choice = item_choice;
+       m->item_choice_data = item_choice_data;
 
        if (title) {
                m->title = strdup(title);