Merge branch 'master' of git://github.com/chunkeey/carl9170fw
[carl9170fw.git] / config / menu.c
index d66008639a43f46e60235dee932558a6c4d00223..f3bffa309333061ed5d852e7c00132107017add5 100644 (file)
@@ -10,8 +10,7 @@
 
 #include "lkc.h"
 
-static const char nohelp_text[] = N_(
-       "There is no help available for this option.\n");
+static const char nohelp_text[] = "There is no help available for this option.";
 
 struct menu rootmenu;
 static struct menu **last_entry_ptr;
@@ -49,7 +48,7 @@ void menu_add_entry(struct symbol *sym)
 {
        struct menu *menu;
 
-       menu = malloc(sizeof(*menu));
+       menu = xmalloc(sizeof(*menu));
        memset(menu, 0, sizeof(*menu));
        menu->sym = sym;
        menu->parent = current_menu;
@@ -508,10 +507,12 @@ const char *menu_get_help(struct menu *menu)
                return "";
 }
 
-static void get_prompt_str(struct gstr *r, struct property *prop)
+static void get_prompt_str(struct gstr *r, struct property *prop,
+                          struct list_head *head)
 {
        int i, j;
-       struct menu *submenu[8], *menu;
+       struct menu *submenu[8], *menu, *location = NULL;
+       struct jump_key *jump;
 
        str_printf(r, _("Prompt: %s\n"), _(prop->text));
        str_printf(r, _("  Defined at %s:%d\n"), prop->menu->file->name,
@@ -522,13 +523,44 @@ static void get_prompt_str(struct gstr *r, struct property *prop)
                str_append(r, "\n");
        }
        menu = prop->menu->parent;
-       for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
+       for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
+               bool accessible = menu_is_visible(menu);
+
                submenu[i++] = menu;
+               if (location == NULL && accessible)
+                       location = menu;
+       }
+       if (head && location) {
+               jump = xmalloc(sizeof(struct jump_key));
+
+               if (menu_is_visible(prop->menu)) {
+                       /*
+                        * There is not enough room to put the hint at the
+                        * beginning of the "Prompt" line. Put the hint on the
+                        * last "Location" line even when it would belong on
+                        * the former.
+                        */
+                       jump->target = prop->menu;
+               } else
+                       jump->target = location;
+
+               if (list_empty(head))
+                       jump->index = 0;
+               else
+                       jump->index = list_entry(head->prev, struct jump_key,
+                                                entries)->index + 1;
+
+               list_add_tail(&jump->entries, head);
+       }
+
        if (i > 0) {
                str_printf(r, _("  Location:\n"));
                for (j = 4; --i >= 0; j += 2) {
                        menu = submenu[i];
-                       str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu)));
+                       if (head && location && menu == location)
+                               jump->offset = r->len - 1;
+                       str_printf(r, "%*c-> %s", j, ' ',
+                                  _(menu_get_prompt(menu)));
                        if (menu->sym) {
                                str_printf(r, " (%s [=%s])", menu->sym->name ?
                                        menu->sym->name : _("<choice>"),
@@ -539,7 +571,11 @@ static void get_prompt_str(struct gstr *r, struct property *prop)
        }
 }
 
-void get_symbol_str(struct gstr *r, struct symbol *sym)
+/*
+ * head is optional and may be NULL
+ */
+void get_symbol_str(struct gstr *r, struct symbol *sym,
+                   struct list_head *head)
 {
        bool hit;
        struct property *prop;
@@ -558,7 +594,7 @@ void get_symbol_str(struct gstr *r, struct symbol *sym)
                }
        }
        for_all_prompts(sym, prop)
-               get_prompt_str(r, prop);
+               get_prompt_str(r, prop, head);
        hit = false;
        for_all_properties(sym, prop, P_SELECT) {
                if (!hit) {
@@ -578,14 +614,14 @@ void get_symbol_str(struct gstr *r, struct symbol *sym)
        str_append(r, "\n\n");
 }
 
-struct gstr get_relations_str(struct symbol **sym_arr)
+struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
 {
        struct symbol *sym;
        struct gstr res = str_new();
        int i;
 
        for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
-               get_symbol_str(&res, sym);
+               get_symbol_str(&res, sym, head);
        if (!i)
                str_append(&res, _("No matches found.\n"));
        return res;
@@ -595,16 +631,14 @@ struct gstr get_relations_str(struct symbol **sym_arr)
 void menu_get_ext_help(struct menu *menu, struct gstr *help)
 {
        struct symbol *sym = menu->sym;
+       const char *help_text = nohelp_text;
 
        if (menu_has_help(menu)) {
-               if (sym->name) {
+               if (sym->name)
                        str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
-                       str_append(help, _(menu_get_help(menu)));
-                       str_append(help, "\n");
-               }
-       } else {
-               str_append(help, nohelp_text);
+               help_text = menu_get_help(menu);
        }
+       str_printf(help, "%s\n", _(help_text));
        if (sym)
-               get_symbol_str(help, sym);
+               get_symbol_str(help, sym, NULL);
 }