diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h index d4ecce8bc3a6..52f4246bd34d 100644 --- a/scripts/kconfig/expr.h +++ b/scripts/kconfig/expr.h @@ -173,6 +173,8 @@ struct menu { #define MENU_CHANGED 0x0001 #define MENU_ROOT 0x0002 +#define JUMP_NB 9 + extern struct file *file_list; extern struct file *current_file; struct file *lookup_file(const char *name); diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h index 47fe9c340f9a..946c2cb367f9 100644 --- a/scripts/kconfig/lkc_proto.h +++ b/scripts/kconfig/lkc_proto.h @@ -21,8 +21,10 @@ P(menu_get_root_menu,struct menu *,(struct menu *menu)); P(menu_get_parent_menu,struct menu *,(struct menu *menu)); P(menu_has_help,bool,(struct menu *menu)); P(menu_get_help,const char *,(struct menu *menu)); -P(get_symbol_str, void, (struct gstr *r, struct symbol *sym)); -P(get_relations_str, struct gstr, (struct symbol **sym_arr)); +P(get_symbol_str, int, (struct gstr *r, struct symbol *sym, struct menu + **jumps, int jump_nb)); +P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct menu + **jumps)); P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help)); /* symbol.c */ diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index b3a37c2b16ae..6f409745b373 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -236,16 +236,19 @@ search_help[] = N_( "Result:\n" "-----------------------------------------------------------------\n" "Symbol: FOO [=m]\n" + "Type : tristate\n" "Prompt: Foo bus is used to drive the bar HW\n" - "Defined at drivers/pci/Kconfig:47\n" - "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" - "Location:\n" - " -> Bus options (PCI, PCMCIA, EISA, ISA)\n" - " -> PCI support (PCI [=y])\n" - " -> PCI access mode ( [=y])\n" - "Selects: LIBCRC32\n" - "Selected by: BAR\n" + " Defined at drivers/pci/Kconfig:47\n" + " Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" + " Location:\n" + " -> Bus options (PCI, PCMCIA, EISA, ISA)\n" + " -> PCI support (PCI [=y])\n" + "(1) -> PCI access mode ( [=y])\n" + " Selects: LIBCRC32\n" + " Selected by: BAR\n" "-----------------------------------------------------------------\n" + "o The line 'Type:' shows the type of the configuration option for\n" + " this symbol (boolean, tristate, string, ...)\n" "o The line 'Prompt:' shows the text used in the menu structure for\n" " this symbol\n" "o The 'Defined at' line tell at what file / line number the symbol\n" @@ -254,8 +257,12 @@ search_help[] = N_( " this symbol to be visible in the menu (selectable)\n" "o The 'Location:' lines tell where in the menu structure this symbol\n" " is located\n" - " A location followed by a [=y] indicate that this is a selectable\n" - " menu item - and current value is displayed inside brackets.\n" + " A location followed by a [=y] indicates that this is a\n" + " selectable menu item - and the current value is displayed inside\n" + " brackets.\n" + " Press the key in the (#) prefix to jump directly to that\n" + " location. You will be returned to the current search results\n" + " after exiting this new menu.\n" "o The 'Selects:' line tell what symbol will be automatically\n" " selected if this symbol is selected (y or m)\n" "o The 'Selected by' line tell what symbol has selected this symbol\n" @@ -274,7 +281,7 @@ static int child_count; static int single_menu_mode; static int show_all_options; -static void conf(struct menu *menu); +static void conf(struct menu *menu, struct menu *active_menu); static void conf_choice(struct menu *menu); static void conf_string(struct menu *menu); static void conf_load(void); @@ -308,7 +315,9 @@ static void search_conf(void) struct symbol **sym_arr; struct gstr res; char *dialog_input; - int dres; + int dres, vscroll = 0, hscroll = 0; + bool again; + again: dialog_clear(); dres = dialog_inputbox(_("Search Configuration Parameter"), @@ -331,10 +340,24 @@ again: dialog_input += strlen(CONFIG_); sym_arr = sym_re_search(dialog_input); - res = get_relations_str(sym_arr); + do { + struct menu *jumps[JUMP_NB] = {0}; + int keys[JUMP_NB + 1] = {0}, i; + + res = get_relations_str(sym_arr, jumps); + for (i = 0; i < JUMP_NB && jumps[i]; i++) + keys[i] = '1' + i; + dres = show_textbox_ext(_("Search Results"), str_get(&res), 0, + 0, keys, &vscroll, &hscroll); + again = false; + for (i = 0; i < JUMP_NB && jumps[i]; i++) + if (dres == keys[i]) { + conf(jumps[i]->parent, jumps[i]); + again = true; + } + str_free(&res); + } while (again); free(sym_arr); - show_textbox(_("Search Results"), str_get(&res), 0, 0); - str_free(&res); } static void build_conf(struct menu *menu) @@ -515,12 +538,11 @@ conf_childs: indent -= doint; } -static void conf(struct menu *menu) +static void conf(struct menu *menu, struct menu *active_menu) { struct menu *submenu; const char *prompt = menu_get_prompt(menu); struct symbol *sym; - struct menu *active_menu = NULL; int res; int s_scroll = 0; @@ -563,13 +585,13 @@ static void conf(struct menu *menu) if (single_menu_mode) submenu->data = (void *) (long) !submenu->data; else - conf(submenu); + conf(submenu, NULL); break; case 't': if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes) conf_choice(submenu); else if (submenu->prompt->type == P_MENU) - conf(submenu); + conf(submenu, NULL); break; case 's': conf_string(submenu); @@ -608,7 +630,7 @@ static void conf(struct menu *menu) if (item_is_tag('t')) sym_toggle_tristate_value(sym); else if (item_is_tag('m')) - conf(submenu); + conf(submenu, NULL); break; case 7: search_conf(); @@ -877,7 +899,7 @@ int main(int ac, char **av) set_config_filename(conf_get_configname()); do { - conf(&rootmenu); + conf(&rootmenu, NULL); res = handle_exit(); } while (res == KEY_ESC); diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index 8c2a97e60faf..a5241859326a 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c @@ -507,10 +507,12 @@ const char *menu_get_help(struct menu *menu) return ""; } -static void get_prompt_str(struct gstr *r, struct property *prop) +static int get_prompt_str(struct gstr *r, struct property *prop, struct menu + **jumps, int jump_nb) { int i, j; - struct menu *submenu[8], *menu; + char header[4]; + struct menu *submenu[8], *menu, *location = NULL; str_printf(r, _("Prompt: %s\n"), _(prop->text)); str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name, @@ -521,13 +523,34 @@ 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 (jumps && jump_nb < JUMP_NB && location) { + 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. + */ + jumps[jump_nb] = prop->menu; + } else + jumps[jump_nb] = location; + snprintf(header, 4, "(%d)", jump_nb + 1); + } else + location = NULL; + if (i > 0) { str_printf(r, _(" Location:\n")); - for (j = 4; --i >= 0; j += 2) { + for (j = 1; --i >= 0; j += 2) { menu = submenu[i]; - str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu))); + str_printf(r, "%s%*c-> %s", menu == location ? header + : " ", j, ' ', _(menu_get_prompt(menu))); if (menu->sym) { str_printf(r, " (%s [=%s])", menu->sym->name ? menu->sym->name : _(""), @@ -536,12 +559,20 @@ static void get_prompt_str(struct gstr *r, struct property *prop) str_append(r, "\n"); } } + + return location ? 1 : 0; } -void get_symbol_str(struct gstr *r, struct symbol *sym) +/* + * jumps is optional and may be NULL + * returns the number of jumps inserted + */ +int get_symbol_str(struct gstr *r, struct symbol *sym, struct menu **jumps, + int jump_nb) { bool hit; struct property *prop; + int i = 0; if (sym && sym->name) { str_printf(r, "Symbol: %s [=%s]\n", sym->name, @@ -557,7 +588,7 @@ void get_symbol_str(struct gstr *r, struct symbol *sym) } } for_all_prompts(sym, prop) - get_prompt_str(r, prop); + i += get_prompt_str(r, prop, jumps, jump_nb + i); hit = false; for_all_properties(sym, prop, P_SELECT) { if (!hit) { @@ -575,16 +606,18 @@ void get_symbol_str(struct gstr *r, struct symbol *sym) str_append(r, "\n"); } str_append(r, "\n\n"); + + return i; } -struct gstr get_relations_str(struct symbol **sym_arr) +struct gstr get_relations_str(struct symbol **sym_arr, struct menu **jumps) { struct symbol *sym; struct gstr res = str_new(); - int i; + int i, jump_nb = 0; for (i = 0; sym_arr && (sym = sym_arr[i]); i++) - get_symbol_str(&res, sym); + jump_nb += get_symbol_str(&res, sym, jumps, jump_nb); if (!i) str_append(&res, _("No matches found.\n")); return res; @@ -603,5 +636,5 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help) } str_printf(help, "%s\n", _(help_text)); if (sym) - get_symbol_str(help, sym); + get_symbol_str(help, sym, NULL, 0); } diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c index 1704a8562a5d..87d4b15da951 100644 --- a/scripts/kconfig/nconf.c +++ b/scripts/kconfig/nconf.c @@ -721,7 +721,7 @@ again: dialog_input += strlen(CONFIG_); sym_arr = sym_re_search(dialog_input); - res = get_relations_str(sym_arr); + res = get_relations_str(sym_arr, NULL); free(sym_arr); show_scroll_win(main_window, _("Search Results"), str_get(&res));