blob: 01b6c27224e279dce9a934fc0a7355244d47567b [file] [log] [blame]
Masahiro Yamada0c874102018-12-18 21:13:35 +09001// SPDX-License-Identifier: GPL-2.0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
5 * Introduced single menu mode (show all sub-menus in one large tree).
6 * 2002-11-06 Petr Baudis <pasky@ucw.cz>
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -07007 *
8 * i18n, 2005, Arnaldo Carvalho de Melo <acme@conectiva.com.br>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 */
10
Linus Torvalds1da177e2005-04-16 15:20:36 -070011#include <ctype.h>
12#include <errno.h>
13#include <fcntl.h>
14#include <limits.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <stdarg.h>
16#include <stdlib.h>
17#include <string.h>
Bartosz Golaszewskiba82f522020-01-09 17:16:36 +010018#include <strings.h>
Davidlohr Bueso564899f2011-08-21 22:04:09 -030019#include <signal.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include <unistd.h>
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include "lkc.h"
Sam Ravnborg2982de62006-07-27 22:10:27 +020023#include "lxdialog/dialog.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
Masahiro Yamada40661622021-03-14 04:48:31 +090025#define JUMP_NB 9
26
Sam Ravnborg694c49a2018-05-22 21:36:12 +020027static const char mconf_readme[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -070028"Overview\n"
29"--------\n"
Martin Walch8d9dfe82013-10-03 17:28:14 +020030"This interface lets you select features and parameters for the build.\n"
Arnaud Lacombe652cf982010-08-14 23:51:40 -040031"Features can either be built-in, modularized, or ignored. Parameters\n"
32"must be entered in as decimal or hexadecimal numbers or text.\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -070033"\n"
Matej Laitlb5d609d2007-10-02 13:46:50 -070034"Menu items beginning with following braces represent features that\n"
35" [ ] can be built in or removed\n"
36" < > can be built in, modularized or removed\n"
37" { } can be built in or modularized (selected by other feature)\n"
38" - - are selected by other feature,\n"
39"while *, M or whitespace inside braces means to build in, build as\n"
40"a module or to exclude the feature respectively.\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -070041"\n"
42"To change any of these features, highlight it with the cursor\n"
43"keys and press <Y> to build it in, <M> to make it a module or\n"
Martin Walch8d9dfe82013-10-03 17:28:14 +020044"<N> to remove it. You may also press the <Space Bar> to cycle\n"
45"through the available options (i.e. Y->N->M->Y).\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -070046"\n"
47"Some additional keyboard hints:\n"
48"\n"
49"Menus\n"
50"----------\n"
Martin Walch8d9dfe82013-10-03 17:28:14 +020051"o Use the Up/Down arrow keys (cursor keys) to highlight the item you\n"
52" wish to change or the submenu you wish to select and press <Enter>.\n"
Dirk Gouders1278ebd2013-05-19 21:49:34 +020053" Submenus are designated by \"--->\", empty ones by \"----\".\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -070054"\n"
55" Shortcut: Press the option's highlighted letter (hotkey).\n"
56" Pressing a hotkey more than once will sequence\n"
57" through all visible items which use that hotkey.\n"
58"\n"
59" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
60" unseen options into view.\n"
61"\n"
62"o To exit a menu use the cursor keys to highlight the <Exit> button\n"
63" and press <ENTER>.\n"
64"\n"
65" Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\n"
66" using those letters. You may press a single <ESC>, but\n"
67" there is a delayed response which you may find annoying.\n"
68"\n"
69" Also, the <TAB> and cursor keys will cycle between <Select>,\n"
Martin Walch8d9dfe82013-10-03 17:28:14 +020070" <Exit>, <Help>, <Save>, and <Load>.\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -070071"\n"
72"o To get help with an item, use the cursor keys to highlight <Help>\n"
Li Zefan22c7eca2010-04-14 11:46:02 +080073" and press <ENTER>.\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -070074"\n"
75" Shortcut: Press <H> or <?>.\n"
76"\n"
Li Zefanf9447c42010-05-07 13:57:22 +080077"o To toggle the display of hidden options, press <Z>.\n"
Li Zefan22c7eca2010-04-14 11:46:02 +080078"\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -070079"\n"
80"Radiolists (Choice lists)\n"
81"-----------\n"
82"o Use the cursor keys to select the option you wish to set and press\n"
83" <S> or the <SPACE BAR>.\n"
84"\n"
85" Shortcut: Press the first letter of the option you wish to set then\n"
86" press <S> or <SPACE BAR>.\n"
87"\n"
88"o To see available help for the item, use the cursor keys to highlight\n"
89" <Help> and Press <ENTER>.\n"
90"\n"
91" Shortcut: Press <H> or <?>.\n"
92"\n"
93" Also, the <TAB> and cursor keys will cycle between <Select> and\n"
94" <Help>\n"
95"\n"
96"\n"
97"Data Entry\n"
98"-----------\n"
99"o Enter the requested information and press <ENTER>\n"
100" If you are entering hexadecimal values, it is not necessary to\n"
101" add the '0x' prefix to the entry.\n"
102"\n"
103"o For help, use the <TAB> or cursor keys to highlight the help option\n"
104" and press <ENTER>. You can try <TAB><H> as well.\n"
105"\n"
106"\n"
107"Text Box (Help Window)\n"
108"--------\n"
109"o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
Martin Walch8d9dfe82013-10-03 17:28:14 +0200110" keys h,j,k,l function here as do <u>, <d>, <SPACE BAR> and <B> for\n"
Benjamin Poirier9d4792c2012-07-24 16:12:02 -0400111" those who are familiar with less and lynx.\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112"\n"
Benjamin Poirier9d4792c2012-07-24 16:12:02 -0400113"o Press <E>, <X>, <q>, <Enter> or <Esc><Esc> to exit.\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114"\n"
115"\n"
116"Alternate Configuration Files\n"
117"-----------------------------\n"
118"Menuconfig supports the use of alternate configuration files for\n"
119"those who, for various reasons, find it necessary to switch\n"
Arnaud Lacombe652cf982010-08-14 23:51:40 -0400120"between different configurations.\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121"\n"
Martin Walch8d9dfe82013-10-03 17:28:14 +0200122"The <Save> button will let you save the current configuration to\n"
123"a file of your choosing. Use the <Load> button to load a previously\n"
124"saved alternate configuration.\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125"\n"
Martin Walch8d9dfe82013-10-03 17:28:14 +0200126"Even if you don't use alternate configuration files, but you find\n"
127"during a Menuconfig session that you have completely messed up your\n"
128"settings, you may use the <Load> button to restore your previously\n"
129"saved settings from \".config\" without restarting Menuconfig.\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130"\n"
131"Other information\n"
132"-----------------\n"
Martin Walch8d9dfe82013-10-03 17:28:14 +0200133"If you use Menuconfig in an XTERM window, make sure you have your\n"
134"$TERM variable set to point to an xterm definition which supports\n"
135"color. Otherwise, Menuconfig will look rather bad. Menuconfig will\n"
136"not display correctly in an RXVT window because rxvt displays only one\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137"intensity of color, bright.\n"
138"\n"
139"Menuconfig will display larger menus on screens or xterms which are\n"
140"set to display more than the standard 25 row by 80 column geometry.\n"
141"In order for this to work, the \"stty size\" command must be able to\n"
142"display the screen's current row and column geometry. I STRONGLY\n"
143"RECOMMEND that you make sure you do NOT have the shell variables\n"
144"LINES and COLUMNS exported into your environment. Some distributions\n"
145"export those variables via /etc/profile. Some ncurses programs can\n"
146"become confused when those variables (LINES & COLUMNS) don't reflect\n"
147"the true screen size.\n"
148"\n"
149"Optional personality available\n"
150"------------------------------\n"
Martin Walch8d9dfe82013-10-03 17:28:14 +0200151"If you prefer to have all of the options listed in a single menu,\n"
152"rather than the default multimenu hierarchy, run the menuconfig with\n"
Arnaud Lacombe652cf982010-08-14 23:51:40 -0400153"MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154"\n"
155"make MENUCONFIG_MODE=single_menu menuconfig\n"
156"\n"
157"<Enter> will then unroll the appropriate category, or enfold it if it\n"
158"is already unrolled.\n"
159"\n"
160"Note that this mode can eventually be a little more CPU expensive\n"
161"(especially with a larger number of unrolled categories) than the\n"
Sam Ravnborg45897212006-07-24 22:04:04 +0200162"default mode.\n"
163"\n"
164"Different color themes available\n"
165"--------------------------------\n"
166"It is possible to select different color themes using the variable\n"
167"MENUCONFIG_COLOR. To select a theme use:\n"
168"\n"
169"make MENUCONFIG_COLOR=<theme> menuconfig\n"
170"\n"
171"Available themes are\n"
172" mono => selects colors suitable for monochrome displays\n"
173" blackbg => selects a color scheme with black background\n"
Sam Ravnborg350b5b72006-07-24 22:19:51 +0200174" classic => theme with blue background. The classic look\n"
Martin Walch8d9dfe82013-10-03 17:28:14 +0200175" bluetitle => an LCD friendly version of classic. (default)\n"
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200176"\n",
177menu_instructions[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 "Arrow keys navigate the menu. "
Dirk Gouders1278ebd2013-05-19 21:49:34 +0200179 "<Enter> selects submenus ---> (or empty submenus ----). "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 "Highlighted letters are hotkeys. "
181 "Pressing <Y> includes, <N> excludes, <M> modularizes features. "
182 "Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200183 "Legend: [*] built-in [ ] excluded <M> module < > module capable",
184radiolist_instructions[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 "Use the arrow keys to navigate this window or "
186 "press the hotkey of the item you wish to select "
187 "followed by the <SPACE BAR>. "
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200188 "Press <?> for additional information about this option.",
189inputbox_instructions_int[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 "Please enter a decimal value. "
191 "Fractions will not be accepted. "
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200192 "Use the <TAB> key to move from the input field to the buttons below it.",
193inputbox_instructions_hex[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 "Please enter a hexadecimal value. "
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200195 "Use the <TAB> key to move from the input field to the buttons below it.",
196inputbox_instructions_string[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 "Please enter a string value. "
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200198 "Use the <TAB> key to move from the input field to the buttons below it.",
199setmod_text[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 "This feature depends on another which has been configured as a module.\n"
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200201 "As a result, this feature will be built as a module.",
202load_config_text[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 "Enter the name of the configuration file you wish to load. "
204 "Accept the name shown to restore the configuration you "
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200205 "last retrieved. Leave blank to abort.",
206load_config_help[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 "\n"
Arnaud Lacombe652cf982010-08-14 23:51:40 -0400208 "For various reasons, one may wish to keep several different\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 "configurations available on a single machine.\n"
210 "\n"
211 "If you have saved a previous configuration in a file other than the\n"
Arnaud Lacombe652cf982010-08-14 23:51:40 -0400212 "default one, entering its name here will allow you to modify that\n"
213 "configuration.\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 "\n"
215 "If you are uncertain, then you have probably never used alternate\n"
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200216 "configuration files. You should therefore leave this blank to abort.\n",
217save_config_text[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 "Enter a filename to which this configuration should be saved "
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200219 "as an alternate. Leave blank to abort.",
220save_config_help[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 "\n"
Arnaud Lacombe652cf982010-08-14 23:51:40 -0400222 "For various reasons, one may wish to keep different configurations\n"
223 "available on a single machine.\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 "\n"
225 "Entering a file name here will allow you to later retrieve, modify\n"
226 "and use the current configuration as an alternate to whatever\n"
227 "configuration options you have selected at that time.\n"
228 "\n"
229 "If you are uncertain what all this means then you should probably\n"
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200230 "leave this blank.\n",
231search_help[] =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 "\n"
Arnaud Lacombe59dfa242010-08-21 00:43:46 -0400233 "Search for symbols and display their relations.\n"
Randy Dunlap503af332005-10-30 15:02:15 -0800234 "Regular expressions are allowed.\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 "Example: search for \"^FOO\"\n"
236 "Result:\n"
237 "-----------------------------------------------------------------\n"
238 "Symbol: FOO [=m]\n"
Benjamin Poirier5e609ad2012-08-23 14:55:06 -0400239 "Type : tristate\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 "Prompt: Foo bus is used to drive the bar HW\n"
Benjamin Poirier5e609ad2012-08-23 14:55:06 -0400241 " Location:\n"
242 " -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
243 " -> PCI support (PCI [=y])\n"
244 "(1) -> PCI access mode (<choice> [=y])\n"
Martin Walch8d9dfe82013-10-03 17:28:14 +0200245 " Defined at drivers/pci/Kconfig:47\n"
246 " Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
Benjamin Poirier5e609ad2012-08-23 14:55:06 -0400247 " Selects: LIBCRC32\n"
Martin Walch8d9dfe82013-10-03 17:28:14 +0200248 " Selected by: BAR [=n]\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 "-----------------------------------------------------------------\n"
Benjamin Poirier5e609ad2012-08-23 14:55:06 -0400250 "o The line 'Type:' shows the type of the configuration option for\n"
Masahiro Yamadab92d8042017-12-16 00:38:02 +0900251 " this symbol (bool, tristate, string, ...)\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 "o The line 'Prompt:' shows the text used in the menu structure for\n"
Arnaud Lacombe59dfa242010-08-21 00:43:46 -0400253 " this symbol\n"
Martin Walch8d9dfe82013-10-03 17:28:14 +0200254 "o The 'Defined at' line tells at what file / line number the symbol\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 " is defined\n"
Martin Walch8d9dfe82013-10-03 17:28:14 +0200256 "o The 'Depends on:' line tells what symbols need to be defined for\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 " this symbol to be visible in the menu (selectable)\n"
Martin Walch8d9dfe82013-10-03 17:28:14 +0200258 "o The 'Location:' lines tells where in the menu structure this symbol\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 " is located\n"
Benjamin Poirier5e609ad2012-08-23 14:55:06 -0400260 " A location followed by a [=y] indicates that this is a\n"
261 " selectable menu item - and the current value is displayed inside\n"
262 " brackets.\n"
263 " Press the key in the (#) prefix to jump directly to that\n"
264 " location. You will be returned to the current search results\n"
265 " after exiting this new menu.\n"
Martin Walch8d9dfe82013-10-03 17:28:14 +0200266 "o The 'Selects:' line tells what symbols will be automatically\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267 " selected if this symbol is selected (y or m)\n"
Martin Walch8d9dfe82013-10-03 17:28:14 +0200268 "o The 'Selected by' line tells what symbol has selected this symbol\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 "\n"
270 "Only relevant lines are shown.\n"
271 "\n\n"
272 "Search examples:\n"
Arnaud Lacombe59dfa242010-08-21 00:43:46 -0400273 "Examples: USB => find all symbols containing USB\n"
274 " ^USB => find all symbols starting with USB\n"
275 " USB$ => find all symbols ending with USB\n"
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200276 "\n";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278static int indent;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279static struct menu *current_menu;
280static int child_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281static int single_menu_mode;
Li Zefan22c7eca2010-04-14 11:46:02 +0800282static int show_all_options;
Wang YanQing6364fd02012-12-19 09:50:58 +0800283static int save_and_exit;
Michal Marek0a1f00a2015-04-08 13:30:42 +0200284static int silent;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
Benjamin Poirier5e609ad2012-08-23 14:55:06 -0400286static void conf(struct menu *menu, struct menu *active_menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287static void conf_choice(struct menu *menu);
288static void conf_string(struct menu *menu);
289static void conf_load(void);
290static void conf_save(void);
Benjamin Poirier95ac9b32012-08-23 14:55:08 -0400291static int show_textbox_ext(const char *title, char *text, int r, int c,
292 int *keys, int *vscroll, int *hscroll,
293 update_text_fn update_text, void *data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294static void show_textbox(const char *title, const char *text, int r, int c);
295static void show_helptext(const char *title, const char *text);
296static void show_help(struct menu *menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100298static char filename[PATH_MAX+1];
299static void set_config_filename(const char *config_filename)
300{
301 static char menu_backtitle[PATH_MAX+128];
302 int size;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100303
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100304 size = snprintf(menu_backtitle, sizeof(menu_backtitle),
Masahiro Yamadabb66fc62014-06-10 19:08:13 +0900305 "%s - %s", config_filename, rootmenu.prompt->text);
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100306 if (size >= sizeof(menu_backtitle))
307 menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
308 set_dialog_backtitle(menu_backtitle);
309
310 size = snprintf(filename, sizeof(filename), "%s", config_filename);
311 if (size >= sizeof(filename))
312 filename[sizeof(filename)-1] = '\0';
313}
314
Benjamin Poirier9a69abf2013-04-16 10:07:23 -0400315struct subtitle_part {
316 struct list_head entries;
317 const char *text;
318};
319static LIST_HEAD(trail);
320
321static struct subtitle_list *subtitles;
322static void set_subtitle(void)
323{
324 struct subtitle_part *sp;
325 struct subtitle_list *pos, *tmp;
326
327 for (pos = subtitles; pos != NULL; pos = tmp) {
328 tmp = pos->next;
329 free(pos);
330 }
331
332 subtitles = NULL;
333 list_for_each_entry(sp, &trail, entries) {
334 if (sp->text) {
335 if (pos) {
Arjun Sreedharane4e458b2014-12-06 17:10:43 +0530336 pos->next = xcalloc(1, sizeof(*pos));
Benjamin Poirier9a69abf2013-04-16 10:07:23 -0400337 pos = pos->next;
338 } else {
Arjun Sreedharane4e458b2014-12-06 17:10:43 +0530339 subtitles = pos = xcalloc(1, sizeof(*pos));
Benjamin Poirier9a69abf2013-04-16 10:07:23 -0400340 }
341 pos->text = sp->text;
342 }
343 }
344
345 set_dialog_subtitles(subtitles);
346}
347
348static void reset_subtitle(void)
349{
350 struct subtitle_list *pos, *tmp;
351
352 for (pos = subtitles; pos != NULL; pos = tmp) {
353 tmp = pos->next;
354 free(pos);
355 }
356 subtitles = NULL;
357 set_dialog_subtitles(subtitles);
358}
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100359
Benjamin Poirier95ac9b32012-08-23 14:55:08 -0400360struct search_data {
Benjamin Poirierbad99552012-10-21 05:27:53 -0400361 struct list_head *head;
Benjamin Poirier95ac9b32012-08-23 14:55:08 -0400362 struct menu **targets;
363 int *keys;
364};
365
366static void update_text(char *buf, size_t start, size_t end, void *_data)
367{
368 struct search_data *data = _data;
369 struct jump_key *pos;
370 int k = 0;
371
Benjamin Poirierbad99552012-10-21 05:27:53 -0400372 list_for_each_entry(pos, data->head, entries) {
Benjamin Poirier95ac9b32012-08-23 14:55:08 -0400373 if (pos->offset >= start && pos->offset < end) {
374 char header[4];
375
376 if (k < JUMP_NB) {
377 int key = '0' + (pos->index % JUMP_NB) + 1;
378
379 sprintf(header, "(%c)", key);
380 data->keys[k] = key;
381 data->targets[k] = pos->target;
382 k++;
383 } else {
384 sprintf(header, " ");
385 }
386
387 memcpy(buf + pos->offset, header, sizeof(header) - 1);
388 }
389 }
390 data->keys[k] = 0;
391}
392
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393static void search_conf(void)
394{
395 struct symbol **sym_arr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 struct gstr res;
Yann E. MORIN337a2752012-10-20 01:06:23 +0200397 struct gstr title;
Bernhard Walle0584f9f2007-07-09 11:43:56 -0700398 char *dialog_input;
Benjamin Poirier5e609ad2012-08-23 14:55:06 -0400399 int dres, vscroll = 0, hscroll = 0;
400 bool again;
Benjamin Poirier9a69abf2013-04-16 10:07:23 -0400401 struct gstr sttext;
402 struct subtitle_part stpart;
Benjamin Poirier5e609ad2012-08-23 14:55:06 -0400403
Yann E. MORIN337a2752012-10-20 01:06:23 +0200404 title = str_new();
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200405 str_printf( &title, "Enter (sub)string or regexp to search for "
406 "(with or without \"%s\")", CONFIG_);
Yann E. MORIN337a2752012-10-20 01:06:23 +0200407
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408again:
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200409 dialog_clear();
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200410 dres = dialog_inputbox("Search Configuration Parameter",
Yann E. MORIN337a2752012-10-20 01:06:23 +0200411 str_get(&title),
Sam Ravnborg2982de62006-07-27 22:10:27 +0200412 10, 75, "");
413 switch (dres) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 case 0:
415 break;
416 case 1:
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200417 show_helptext("Search Configuration", search_help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 goto again;
419 default:
Yann E. MORIN337a2752012-10-20 01:06:23 +0200420 str_free(&title);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 return;
422 }
423
Arnaud Lacombeffb59572010-08-14 23:57:43 -0400424 /* strip the prefix if necessary */
Bernhard Walle0584f9f2007-07-09 11:43:56 -0700425 dialog_input = dialog_input_result;
Arnaud Lacombeffb59572010-08-14 23:57:43 -0400426 if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
427 dialog_input += strlen(CONFIG_);
Bernhard Walle0584f9f2007-07-09 11:43:56 -0700428
Benjamin Poirier9a69abf2013-04-16 10:07:23 -0400429 sttext = str_new();
430 str_printf(&sttext, "Search (%s)", dialog_input_result);
431 stpart.text = str_get(&sttext);
432 list_add_tail(&stpart.entries, &trail);
433
Bernhard Walle0584f9f2007-07-09 11:43:56 -0700434 sym_arr = sym_re_search(dialog_input);
Benjamin Poirier5e609ad2012-08-23 14:55:06 -0400435 do {
Benjamin Poirierbad99552012-10-21 05:27:53 -0400436 LIST_HEAD(head);
Benjamin Poirier95ac9b32012-08-23 14:55:08 -0400437 struct menu *targets[JUMP_NB];
438 int keys[JUMP_NB + 1], i;
439 struct search_data data = {
440 .head = &head,
441 .targets = targets,
442 .keys = keys,
443 };
Benjamin Poirieredb749f2013-04-15 10:13:50 -0400444 struct jump_key *pos, *tmp;
Benjamin Poirier5e609ad2012-08-23 14:55:06 -0400445
Benjamin Poirier95ac9b32012-08-23 14:55:08 -0400446 res = get_relations_str(sym_arr, &head);
Benjamin Poirier9a69abf2013-04-16 10:07:23 -0400447 set_subtitle();
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200448 dres = show_textbox_ext("Search Results", (char *)
Benjamin Poirier95ac9b32012-08-23 14:55:08 -0400449 str_get(&res), 0, 0, keys, &vscroll,
450 &hscroll, &update_text, (void *)
451 &data);
Benjamin Poirier5e609ad2012-08-23 14:55:06 -0400452 again = false;
Benjamin Poirier95ac9b32012-08-23 14:55:08 -0400453 for (i = 0; i < JUMP_NB && keys[i]; i++)
Benjamin Poirier5e609ad2012-08-23 14:55:06 -0400454 if (dres == keys[i]) {
Benjamin Poirier95ac9b32012-08-23 14:55:08 -0400455 conf(targets[i]->parent, targets[i]);
Benjamin Poirier5e609ad2012-08-23 14:55:06 -0400456 again = true;
457 }
458 str_free(&res);
Benjamin Poirieredb749f2013-04-15 10:13:50 -0400459 list_for_each_entry_safe(pos, tmp, &head, entries)
460 free(pos);
Benjamin Poirier5e609ad2012-08-23 14:55:06 -0400461 } while (again);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 free(sym_arr);
Yann E. MORIN337a2752012-10-20 01:06:23 +0200463 str_free(&title);
Benjamin Poirier9a69abf2013-04-16 10:07:23 -0400464 list_del(trail.prev);
465 str_free(&sttext);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466}
467
468static void build_conf(struct menu *menu)
469{
470 struct symbol *sym;
471 struct property *prop;
472 struct menu *child;
473 int type, tmp, doint = 2;
474 tristate val;
475 char ch;
Li Zefan22c7eca2010-04-14 11:46:02 +0800476 bool visible;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477
Li Zefan22c7eca2010-04-14 11:46:02 +0800478 /*
479 * note: menu_is_visible() has side effect that it will
480 * recalc the value of the symbol.
481 */
482 visible = menu_is_visible(menu);
483 if (show_all_options && !menu_has_prompt(menu))
484 return;
485 else if (!show_all_options && !visible)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486 return;
487
488 sym = menu->sym;
489 prop = menu->prompt;
490 if (!sym) {
491 if (prop && menu != current_menu) {
492 const char *prompt = menu_get_prompt(menu);
493 switch (prop->type) {
494 case P_MENU:
495 child_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 if (single_menu_mode) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200497 item_make("%s%*c%s",
498 menu->data ? "-->" : "++>",
499 indent + 1, ' ', prompt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 } else
Dirk Gouders1278ebd2013-05-19 21:49:34 +0200501 item_make(" %*c%s %s",
502 indent + 1, ' ', prompt,
503 menu_is_empty(menu) ? "----" : "--->");
Sam Ravnborg2982de62006-07-27 22:10:27 +0200504 item_set_tag('m');
505 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 if (single_menu_mode && menu->data)
507 goto conf_childs;
508 return;
Sam Ravnborg48874072007-09-18 21:12:26 +0200509 case P_COMMENT:
510 if (prompt) {
511 child_count++;
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200512 item_make(" %*c*** %s ***", indent + 1, ' ', prompt);
Sam Ravnborg48874072007-09-18 21:12:26 +0200513 item_set_tag(':');
514 item_set_data(menu);
515 }
516 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 default:
518 if (prompt) {
519 child_count++;
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200520 item_make("---%*c%s", indent + 1, ' ', prompt);
Sam Ravnborg2982de62006-07-27 22:10:27 +0200521 item_set_tag(':');
522 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 }
524 }
525 } else
526 doint = 0;
527 goto conf_childs;
528 }
529
530 type = sym_get_type(sym);
531 if (sym_is_choice(sym)) {
532 struct symbol *def_sym = sym_get_choice_value(sym);
533 struct menu *def_menu = NULL;
534
535 child_count++;
536 for (child = menu->list; child; child = child->next) {
537 if (menu_is_visible(child) && child->sym == def_sym)
538 def_menu = child;
539 }
540
541 val = sym_get_tristate_value(sym);
Marco Ammonbaa23ec2019-07-04 12:50:41 +0200542 if (sym_is_changeable(sym)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 switch (type) {
544 case S_BOOLEAN:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200545 item_make("[%c]", val == no ? ' ' : '*');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 break;
547 case S_TRISTATE:
548 switch (val) {
549 case yes: ch = '*'; break;
550 case mod: ch = 'M'; break;
551 default: ch = ' '; break;
552 }
Sam Ravnborg2982de62006-07-27 22:10:27 +0200553 item_make("<%c>", ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554 break;
555 }
Sam Ravnborg2982de62006-07-27 22:10:27 +0200556 item_set_tag('t');
557 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 } else {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200559 item_make(" ");
560 item_set_tag(def_menu ? 't' : ':');
561 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 }
563
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200564 item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 if (val == yes) {
566 if (def_menu) {
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200567 item_add_str(" (%s)", menu_get_prompt(def_menu));
Sam Ravnborg2982de62006-07-27 22:10:27 +0200568 item_add_str(" --->");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 if (def_menu->list) {
570 indent += 2;
571 build_conf(def_menu);
572 indent -= 2;
573 }
Sam Ravnborg2982de62006-07-27 22:10:27 +0200574 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 return;
576 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 } else {
578 if (menu == current_menu) {
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200579 item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
Sam Ravnborg2982de62006-07-27 22:10:27 +0200580 item_set_tag(':');
581 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 goto conf_childs;
583 }
584 child_count++;
585 val = sym_get_tristate_value(sym);
586 if (sym_is_choice_value(sym) && val == yes) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200587 item_make(" ");
588 item_set_tag(':');
589 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 } else {
591 switch (type) {
592 case S_BOOLEAN:
Marco Ammonbaa23ec2019-07-04 12:50:41 +0200593 if (sym_is_changeable(sym))
Sam Ravnborg2982de62006-07-27 22:10:27 +0200594 item_make("[%c]", val == no ? ' ' : '*');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 else
Matej Laitlb5d609d2007-10-02 13:46:50 -0700596 item_make("-%c-", val == no ? ' ' : '*');
Sam Ravnborg2982de62006-07-27 22:10:27 +0200597 item_set_tag('t');
598 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 break;
600 case S_TRISTATE:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 switch (val) {
602 case yes: ch = '*'; break;
603 case mod: ch = 'M'; break;
604 default: ch = ' '; break;
605 }
Marco Ammonbaa23ec2019-07-04 12:50:41 +0200606 if (sym_is_changeable(sym)) {
Matej Laitlb5d609d2007-10-02 13:46:50 -0700607 if (sym->rev_dep.tri == mod)
608 item_make("{%c}", ch);
609 else
610 item_make("<%c>", ch);
611 } else
612 item_make("-%c-", ch);
Sam Ravnborg2982de62006-07-27 22:10:27 +0200613 item_set_tag('t');
614 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 break;
616 default:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200617 tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
618 item_make("(%s)", sym_get_string_value(sym));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 tmp = indent - tmp + 4;
620 if (tmp < 0)
621 tmp = 0;
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200622 item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
Marco Ammonbaa23ec2019-07-04 12:50:41 +0200623 (sym_has_value(sym) || !sym_is_changeable(sym)) ?
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200624 "" : " (NEW)");
Sam Ravnborg2982de62006-07-27 22:10:27 +0200625 item_set_tag('s');
626 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 goto conf_childs;
628 }
629 }
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200630 item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
Marco Ammonbaa23ec2019-07-04 12:50:41 +0200631 (sym_has_value(sym) || !sym_is_changeable(sym)) ?
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200632 "" : " (NEW)");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 if (menu->prompt->type == P_MENU) {
Dirk Gouders1278ebd2013-05-19 21:49:34 +0200634 item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 return;
636 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 }
638
639conf_childs:
640 indent += doint;
641 for (child = menu->list; child; child = child->next)
642 build_conf(child);
643 indent -= doint;
644}
645
Benjamin Poirier5e609ad2012-08-23 14:55:06 -0400646static void conf(struct menu *menu, struct menu *active_menu)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647{
648 struct menu *submenu;
649 const char *prompt = menu_get_prompt(menu);
Benjamin Poirier9a69abf2013-04-16 10:07:23 -0400650 struct subtitle_part stpart;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 struct symbol *sym;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200652 int res;
653 int s_scroll = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654
Benjamin Poirier9a69abf2013-04-16 10:07:23 -0400655 if (menu != &rootmenu)
656 stpart.text = menu_get_prompt(menu);
657 else
658 stpart.text = NULL;
659 list_add_tail(&stpart.entries, &trail);
660
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200662 item_reset();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 current_menu = menu;
664 build_conf(menu);
665 if (!child_count)
666 break;
Benjamin Poirier9a69abf2013-04-16 10:07:23 -0400667 set_subtitle();
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200668 dialog_clear();
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200669 res = dialog_menu(prompt ? prompt : "Main Menu",
670 menu_instructions,
Sam Ravnborg2982de62006-07-27 22:10:27 +0200671 active_menu, &s_scroll);
Sam Ravnborgc8dc68a2006-07-29 22:48:57 +0200672 if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 break;
Dirk Gouders063f4662013-05-19 21:48:44 +0200674 if (item_count() != 0) {
675 if (!item_activate_selected())
676 continue;
677 if (!item_tag())
678 continue;
679 }
Sam Ravnborg2982de62006-07-27 22:10:27 +0200680 submenu = item_data();
681 active_menu = item_data();
Sam Ravnborgc8dc68a2006-07-29 22:48:57 +0200682 if (submenu)
683 sym = submenu->sym;
684 else
685 sym = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686
Sam Ravnborg2982de62006-07-27 22:10:27 +0200687 switch (res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200689 switch (item_tag()) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 case 'm':
691 if (single_menu_mode)
692 submenu->data = (void *) (long) !submenu->data;
693 else
Benjamin Poirier5e609ad2012-08-23 14:55:06 -0400694 conf(submenu, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 break;
696 case 't':
697 if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
698 conf_choice(submenu);
699 else if (submenu->prompt->type == P_MENU)
Benjamin Poirier5e609ad2012-08-23 14:55:06 -0400700 conf(submenu, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 break;
702 case 's':
703 conf_string(submenu);
704 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 }
706 break;
707 case 2:
708 if (sym)
709 show_help(submenu);
Benjamin Poirier9a69abf2013-04-16 10:07:23 -0400710 else {
711 reset_subtitle();
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200712 show_helptext("README", mconf_readme);
Benjamin Poirier9a69abf2013-04-16 10:07:23 -0400713 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 break;
715 case 3:
Benjamin Poirier9a69abf2013-04-16 10:07:23 -0400716 reset_subtitle();
Wang YanQing6364fd02012-12-19 09:50:58 +0800717 conf_save();
718 break;
719 case 4:
Benjamin Poirier9a69abf2013-04-16 10:07:23 -0400720 reset_subtitle();
Wang YanQing6364fd02012-12-19 09:50:58 +0800721 conf_load();
722 break;
723 case 5:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200724 if (item_is_tag('t')) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 if (sym_set_tristate_value(sym, yes))
726 break;
727 if (sym_set_tristate_value(sym, mod))
728 show_textbox(NULL, setmod_text, 6, 74);
729 }
730 break;
Wang YanQing6364fd02012-12-19 09:50:58 +0800731 case 6:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200732 if (item_is_tag('t'))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 sym_set_tristate_value(sym, no);
734 break;
Wang YanQing6364fd02012-12-19 09:50:58 +0800735 case 7:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200736 if (item_is_tag('t'))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 sym_set_tristate_value(sym, mod);
738 break;
Wang YanQing6364fd02012-12-19 09:50:58 +0800739 case 8:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200740 if (item_is_tag('t'))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 sym_toggle_tristate_value(sym);
Sam Ravnborg2982de62006-07-27 22:10:27 +0200742 else if (item_is_tag('m'))
Benjamin Poirier5e609ad2012-08-23 14:55:06 -0400743 conf(submenu, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 break;
Wang YanQing6364fd02012-12-19 09:50:58 +0800745 case 9:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 search_conf();
747 break;
Wang YanQing6364fd02012-12-19 09:50:58 +0800748 case 10:
Li Zefan22c7eca2010-04-14 11:46:02 +0800749 show_all_options = !show_all_options;
750 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 }
752 }
Benjamin Poirier9a69abf2013-04-16 10:07:23 -0400753
754 list_del(trail.prev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755}
756
Benjamin Poirier95ac9b32012-08-23 14:55:08 -0400757static int show_textbox_ext(const char *title, char *text, int r, int c, int
758 *keys, int *vscroll, int *hscroll, update_text_fn
759 update_text, void *data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760{
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200761 dialog_clear();
Benjamin Poirier95ac9b32012-08-23 14:55:08 -0400762 return dialog_textbox(title, text, r, c, keys, vscroll, hscroll,
763 update_text, data);
Benjamin Poirier537ddae2012-08-23 14:55:04 -0400764}
765
766static void show_textbox(const char *title, const char *text, int r, int c)
767{
Benjamin Poirier95ac9b32012-08-23 14:55:08 -0400768 show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL,
769 NULL, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770}
771
772static void show_helptext(const char *title, const char *text)
773{
774 show_textbox(title, text, 0, 0);
775}
776
Masahiro Yamada5accd7f2018-07-05 11:46:12 +0900777static void conf_message_callback(const char *s)
Wang YanQing6364fd02012-12-19 09:50:58 +0800778{
Michal Marek0a1f00a2015-04-08 13:30:42 +0200779 if (save_and_exit) {
780 if (!silent)
Masahiro Yamada5accd7f2018-07-05 11:46:12 +0900781 printf("%s", s);
Michal Marek0a1f00a2015-04-08 13:30:42 +0200782 } else {
Masahiro Yamada5accd7f2018-07-05 11:46:12 +0900783 show_textbox(NULL, s, 6, 60);
Michal Marek0a1f00a2015-04-08 13:30:42 +0200784 }
Wang YanQing6364fd02012-12-19 09:50:58 +0800785}
786
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787static void show_help(struct menu *menu)
788{
789 struct gstr help = str_new();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
Vadim Bendebury (вб)da60fbb2009-12-20 00:29:49 -0800791 help.max_width = getmaxx(stdscr) - 10;
Cheng Renquan1d525e72009-07-12 16:11:45 +0800792 menu_get_ext_help(menu, &help);
793
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200794 show_helptext(menu_get_prompt(menu), str_get(&help));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 str_free(&help);
796}
797
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798static void conf_choice(struct menu *menu)
799{
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200800 const char *prompt = menu_get_prompt(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 struct menu *child;
802 struct symbol *active;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803
804 active = sym_get_choice_value(menu->sym);
805 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200806 int res;
807 int selected;
808 item_reset();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809
810 current_menu = menu;
811 for (child = menu->list; child; child = child->next) {
812 if (!menu_is_visible(child))
813 continue;
Peter Korsgaardaf6c1592009-02-15 22:15:16 +0100814 if (child->sym)
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200815 item_make("%s", menu_get_prompt(child));
Peter Korsgaardaf6c1592009-02-15 22:15:16 +0100816 else {
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200817 item_make("*** %s ***", menu_get_prompt(child));
Peter Korsgaardaf6c1592009-02-15 22:15:16 +0100818 item_set_tag(':');
819 }
Sam Ravnborg2982de62006-07-27 22:10:27 +0200820 item_set_data(child);
821 if (child->sym == active)
822 item_set_selected(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 if (child->sym == sym_get_choice_value(menu->sym))
Sam Ravnborg2982de62006-07-27 22:10:27 +0200824 item_set_tag('X');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 }
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200826 dialog_clear();
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200827 res = dialog_checklist(prompt ? prompt : "Main Menu",
828 radiolist_instructions,
Sedat Dilekff7b0c22013-06-16 18:43:04 +0200829 MENUBOX_HEIGTH_MIN,
830 MENUBOX_WIDTH_MIN,
831 CHECKLIST_HEIGTH_MIN);
Sam Ravnborg2982de62006-07-27 22:10:27 +0200832 selected = item_activate_selected();
833 switch (res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200835 if (selected) {
836 child = item_data();
Peter Korsgaardaf6c1592009-02-15 22:15:16 +0100837 if (!child->sym)
838 break;
839
Sam Ravnborg2982de62006-07-27 22:10:27 +0200840 sym_set_tristate_value(child->sym, yes);
841 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 return;
843 case 1:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200844 if (selected) {
845 child = item_data();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 show_help(child);
847 active = child->sym;
848 } else
849 show_help(menu);
850 break;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200851 case KEY_ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 return;
Sam Ravnborgc8dc68a2006-07-29 22:48:57 +0200853 case -ERRDISPLAYTOOSMALL:
854 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 }
856 }
857}
858
859static void conf_string(struct menu *menu)
860{
861 const char *prompt = menu_get_prompt(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862
863 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200864 int res;
Sam Ravnborgc4143a82008-05-04 21:03:20 +0200865 const char *heading;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200866
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 switch (sym_get_type(menu->sym)) {
868 case S_INT:
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200869 heading = inputbox_instructions_int;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 break;
871 case S_HEX:
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200872 heading = inputbox_instructions_hex;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 break;
874 case S_STRING:
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200875 heading = inputbox_instructions_string;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 break;
877 default:
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200878 heading = "Internal mconf error!";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 }
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200880 dialog_clear();
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200881 res = dialog_inputbox(prompt ? prompt : "Main Menu",
Sam Ravnborg2982de62006-07-27 22:10:27 +0200882 heading, 10, 75,
883 sym_get_string_value(menu->sym));
884 switch (res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200886 if (sym_set_string_value(menu->sym, dialog_input_result))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 return;
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200888 show_textbox(NULL, "You have made an invalid entry.", 5, 43);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 break;
890 case 1:
891 show_help(menu);
892 break;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200893 case KEY_ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 return;
895 }
896 }
897}
898
899static void conf_load(void)
900{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901
902 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200903 int res;
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200904 dialog_clear();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200905 res = dialog_inputbox(NULL, load_config_text,
906 11, 55, filename);
907 switch(res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200909 if (!dialog_input_result[0])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 return;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100911 if (!conf_read(dialog_input_result)) {
912 set_config_filename(dialog_input_result);
Sam Ravnborg36ef8052008-02-02 20:44:09 +0100913 sym_set_change_count(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 return;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100915 }
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200916 show_textbox(NULL, "File does not exist!", 5, 38);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 break;
918 case 1:
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200919 show_helptext("Load Alternate Configuration", load_config_help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 break;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200921 case KEY_ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 return;
923 }
924 }
925}
926
927static void conf_save(void)
928{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200930 int res;
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200931 dialog_clear();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200932 res = dialog_inputbox(NULL, save_config_text,
933 11, 55, filename);
934 switch(res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200936 if (!dialog_input_result[0])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 return;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100938 if (!conf_write(dialog_input_result)) {
939 set_config_filename(dialog_input_result);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 return;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100941 }
Masahiro Yamada580c5b32019-05-11 01:56:01 +0900942 show_textbox(NULL, "Can't create file!", 5, 60);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 break;
944 case 1:
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200945 show_helptext("Save Alternate Configuration", save_config_help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 break;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200947 case KEY_ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 return;
949 }
950 }
951}
952
Davidlohr Bueso564899f2011-08-21 22:04:09 -0300953static int handle_exit(void)
954{
955 int res;
956
Wang YanQing6364fd02012-12-19 09:50:58 +0800957 save_and_exit = 1;
Benjamin Poirier9a69abf2013-04-16 10:07:23 -0400958 reset_subtitle();
Davidlohr Bueso564899f2011-08-21 22:04:09 -0300959 dialog_clear();
960 if (conf_get_changed())
961 res = dialog_yesno(NULL,
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200962 "Do you wish to save your new configuration?\n"
963 "(Press <ESC><ESC> to continue kernel configuration.)",
Davidlohr Bueso564899f2011-08-21 22:04:09 -0300964 6, 60);
965 else
966 res = -1;
967
968 end_dialog(saved_x, saved_y);
969
970 switch (res) {
971 case 0:
972 if (conf_write(filename)) {
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200973 fprintf(stderr, "\n\n"
Davidlohr Bueso564899f2011-08-21 22:04:09 -0300974 "Error while writing of the configuration.\n"
975 "Your configuration changes were NOT saved."
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200976 "\n\n");
Davidlohr Bueso564899f2011-08-21 22:04:09 -0300977 return 1;
978 }
Masahiro Yamada00c864f2018-07-20 16:46:31 +0900979 conf_write_autoconf(0);
Davidlohr Bueso564899f2011-08-21 22:04:09 -0300980 /* fall through */
981 case -1:
Michal Marek0a1f00a2015-04-08 13:30:42 +0200982 if (!silent)
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200983 printf("\n\n"
Michal Marek0a1f00a2015-04-08 13:30:42 +0200984 "*** End of the configuration.\n"
985 "*** Execute 'make' to start the build or try 'make help'."
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200986 "\n\n");
Davidlohr Bueso564899f2011-08-21 22:04:09 -0300987 res = 0;
988 break;
989 default:
Michal Marek0a1f00a2015-04-08 13:30:42 +0200990 if (!silent)
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200991 fprintf(stderr, "\n\n"
Michal Marek0a1f00a2015-04-08 13:30:42 +0200992 "Your configuration changes were NOT saved."
Sam Ravnborg694c49a2018-05-22 21:36:12 +0200993 "\n\n");
Li Zefan30c4eaa2012-01-16 15:57:39 +0800994 if (res != KEY_ESC)
995 res = 0;
Davidlohr Bueso564899f2011-08-21 22:04:09 -0300996 }
997
998 return res;
999}
1000
1001static void sig_handler(int signo)
1002{
1003 exit(handle_exit());
1004}
1005
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006int main(int ac, char **av)
1007{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 char *mode;
Sam Ravnborg2982de62006-07-27 22:10:27 +02001009 int res;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010
Davidlohr Bueso564899f2011-08-21 22:04:09 -03001011 signal(SIGINT, sig_handler);
1012
Michal Marek0a1f00a2015-04-08 13:30:42 +02001013 if (ac > 1 && strcmp(av[1], "-s") == 0) {
1014 silent = 1;
1015 /* Silence conf_read() until the real callback is set up */
1016 conf_set_message_callback(NULL);
1017 av++;
1018 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 conf_parse(av[1]);
1020 conf_read(NULL);
1021
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 mode = getenv("MENUCONFIG_MODE");
1023 if (mode) {
1024 if (!strcasecmp(mode, "single_menu"))
1025 single_menu_mode = 1;
1026 }
1027
Ladislav Michl09af0912007-12-17 19:07:41 +01001028 if (init_dialog(NULL)) {
Sam Ravnborg694c49a2018-05-22 21:36:12 +02001029 fprintf(stderr, "Your display is too small to run Menuconfig!\n");
1030 fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
Ladislav Michl09af0912007-12-17 19:07:41 +01001031 return 1;
1032 }
1033
Sam Ravnborgd802b502007-04-01 22:29:38 +02001034 set_config_filename(conf_get_configname());
Wang YanQing6364fd02012-12-19 09:50:58 +08001035 conf_set_message_callback(conf_message_callback);
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +02001036 do {
Benjamin Poirier5e609ad2012-08-23 14:55:06 -04001037 conf(&rootmenu, NULL);
Davidlohr Bueso564899f2011-08-21 22:04:09 -03001038 res = handle_exit();
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +02001039 } while (res == KEY_ESC);
Karsten Wieseb3214292006-12-13 00:34:06 -08001040
Davidlohr Bueso564899f2011-08-21 22:04:09 -03001041 return res;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042}