Merge tag 'nfs-for-6.4-1' of git://git.linux-nfs.org/projects/anna/linux-nfs
[linux-block.git] / scripts / kconfig / mconf.c
CommitLineData
0c874100 1// SPDX-License-Identifier: GPL-2.0
1da177e4
LT
2/*
3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
1da177e4
LT
4 *
5 * Introduced single menu mode (show all sub-menus in one large tree).
6 * 2002-11-06 Petr Baudis <pasky@ucw.cz>
3b9fa093
ACM
7 *
8 * i18n, 2005, Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1da177e4
LT
9 */
10
1da177e4
LT
11#include <ctype.h>
12#include <errno.h>
13#include <fcntl.h>
14#include <limits.h>
1da177e4
LT
15#include <stdarg.h>
16#include <stdlib.h>
17#include <string.h>
ba82f52e 18#include <strings.h>
564899f9 19#include <signal.h>
1da177e4
LT
20#include <unistd.h>
21
1da177e4 22#include "lkc.h"
2982de69 23#include "lxdialog/dialog.h"
1da177e4 24
40661621
MY
25#define JUMP_NB 9
26
694c49a7 27static const char mconf_readme[] =
1da177e4
LT
28"Overview\n"
29"--------\n"
8d9dfe82 30"This interface lets you select features and parameters for the build.\n"
652cf982
AL
31"Features can either be built-in, modularized, or ignored. Parameters\n"
32"must be entered in as decimal or hexadecimal numbers or text.\n"
1da177e4 33"\n"
b5d609db
ML
34"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"
1da177e4
LT
41"\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"
8d9dfe82
MW
44"<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"
1da177e4
LT
46"\n"
47"Some additional keyboard hints:\n"
48"\n"
49"Menus\n"
50"----------\n"
8d9dfe82
MW
51"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"
1278ebdb 53" Submenus are designated by \"--->\", empty ones by \"----\".\n"
1da177e4
LT
54"\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"
8d9dfe82 70" <Exit>, <Help>, <Save>, and <Load>.\n"
1da177e4
LT
71"\n"
72"o To get help with an item, use the cursor keys to highlight <Help>\n"
22c7eca6 73" and press <ENTER>.\n"
1da177e4
LT
74"\n"
75" Shortcut: Press <H> or <?>.\n"
76"\n"
f9447c49 77"o To toggle the display of hidden options, press <Z>.\n"
22c7eca6 78"\n"
1da177e4
LT
79"\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"
8d9dfe82 110" keys h,j,k,l function here as do <u>, <d>, <SPACE BAR> and <B> for\n"
9d4792c9 111" those who are familiar with less and lynx.\n"
1da177e4 112"\n"
9d4792c9 113"o Press <E>, <X>, <q>, <Enter> or <Esc><Esc> to exit.\n"
1da177e4
LT
114"\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"
652cf982 120"between different configurations.\n"
1da177e4 121"\n"
8d9dfe82
MW
122"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"
1da177e4 125"\n"
8d9dfe82
MW
126"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"
1da177e4
LT
130"\n"
131"Other information\n"
132"-----------------\n"
8d9dfe82
MW
133"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"
1da177e4
LT
137"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"
8d9dfe82
MW
151"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"
652cf982 153"MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
1da177e4
LT
154"\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"
45897213
SR
162"default mode.\n"
163"\n"
da8daff9
BC
164
165"Search\n"
166"-------\n"
167"Pressing the forward-slash (/) anywhere brings up a search dialog box.\n"
168"\n"
169
45897213
SR
170"Different color themes available\n"
171"--------------------------------\n"
172"It is possible to select different color themes using the variable\n"
173"MENUCONFIG_COLOR. To select a theme use:\n"
174"\n"
175"make MENUCONFIG_COLOR=<theme> menuconfig\n"
176"\n"
177"Available themes are\n"
178" mono => selects colors suitable for monochrome displays\n"
179" blackbg => selects a color scheme with black background\n"
350b5b76 180" classic => theme with blue background. The classic look\n"
8d9dfe82 181" bluetitle => an LCD friendly version of classic. (default)\n"
694c49a7
SR
182"\n",
183menu_instructions[] =
1da177e4 184 "Arrow keys navigate the menu. "
1278ebdb 185 "<Enter> selects submenus ---> (or empty submenus ----). "
1da177e4
LT
186 "Highlighted letters are hotkeys. "
187 "Pressing <Y> includes, <N> excludes, <M> modularizes features. "
188 "Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
694c49a7
SR
189 "Legend: [*] built-in [ ] excluded <M> module < > module capable",
190radiolist_instructions[] =
1da177e4
LT
191 "Use the arrow keys to navigate this window or "
192 "press the hotkey of the item you wish to select "
193 "followed by the <SPACE BAR>. "
694c49a7
SR
194 "Press <?> for additional information about this option.",
195inputbox_instructions_int[] =
1da177e4
LT
196 "Please enter a decimal value. "
197 "Fractions will not be accepted. "
694c49a7
SR
198 "Use the <TAB> key to move from the input field to the buttons below it.",
199inputbox_instructions_hex[] =
1da177e4 200 "Please enter a hexadecimal value. "
694c49a7
SR
201 "Use the <TAB> key to move from the input field to the buttons below it.",
202inputbox_instructions_string[] =
1da177e4 203 "Please enter a string value. "
694c49a7
SR
204 "Use the <TAB> key to move from the input field to the buttons below it.",
205setmod_text[] =
1da177e4 206 "This feature depends on another which has been configured as a module.\n"
694c49a7
SR
207 "As a result, this feature will be built as a module.",
208load_config_text[] =
1da177e4
LT
209 "Enter the name of the configuration file you wish to load. "
210 "Accept the name shown to restore the configuration you "
694c49a7
SR
211 "last retrieved. Leave blank to abort.",
212load_config_help[] =
1da177e4 213 "\n"
652cf982 214 "For various reasons, one may wish to keep several different\n"
1da177e4
LT
215 "configurations available on a single machine.\n"
216 "\n"
217 "If you have saved a previous configuration in a file other than the\n"
652cf982
AL
218 "default one, entering its name here will allow you to modify that\n"
219 "configuration.\n"
1da177e4
LT
220 "\n"
221 "If you are uncertain, then you have probably never used alternate\n"
694c49a7
SR
222 "configuration files. You should therefore leave this blank to abort.\n",
223save_config_text[] =
1da177e4 224 "Enter a filename to which this configuration should be saved "
694c49a7
SR
225 "as an alternate. Leave blank to abort.",
226save_config_help[] =
1da177e4 227 "\n"
652cf982
AL
228 "For various reasons, one may wish to keep different configurations\n"
229 "available on a single machine.\n"
1da177e4
LT
230 "\n"
231 "Entering a file name here will allow you to later retrieve, modify\n"
232 "and use the current configuration as an alternate to whatever\n"
233 "configuration options you have selected at that time.\n"
234 "\n"
235 "If you are uncertain what all this means then you should probably\n"
694c49a7
SR
236 "leave this blank.\n",
237search_help[] =
1da177e4 238 "\n"
59dfa24d 239 "Search for symbols and display their relations.\n"
503af334 240 "Regular expressions are allowed.\n"
1da177e4
LT
241 "Example: search for \"^FOO\"\n"
242 "Result:\n"
243 "-----------------------------------------------------------------\n"
244 "Symbol: FOO [=m]\n"
5e609add 245 "Type : tristate\n"
1da177e4 246 "Prompt: Foo bus is used to drive the bar HW\n"
5e609add
BP
247 " Location:\n"
248 " -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
249 " -> PCI support (PCI [=y])\n"
250 "(1) -> PCI access mode (<choice> [=y])\n"
8d9dfe82
MW
251 " Defined at drivers/pci/Kconfig:47\n"
252 " Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
5e609add 253 " Selects: LIBCRC32\n"
8d9dfe82 254 " Selected by: BAR [=n]\n"
1da177e4 255 "-----------------------------------------------------------------\n"
5e609add 256 "o The line 'Type:' shows the type of the configuration option for\n"
b92d804a 257 " this symbol (bool, tristate, string, ...)\n"
1da177e4 258 "o The line 'Prompt:' shows the text used in the menu structure for\n"
59dfa24d 259 " this symbol\n"
8d9dfe82 260 "o The 'Defined at' line tells at what file / line number the symbol\n"
1da177e4 261 " is defined\n"
8d9dfe82 262 "o The 'Depends on:' line tells what symbols need to be defined for\n"
1da177e4 263 " this symbol to be visible in the menu (selectable)\n"
8d9dfe82 264 "o The 'Location:' lines tells where in the menu structure this symbol\n"
1da177e4 265 " is located\n"
5e609add
BP
266 " A location followed by a [=y] indicates that this is a\n"
267 " selectable menu item - and the current value is displayed inside\n"
268 " brackets.\n"
269 " Press the key in the (#) prefix to jump directly to that\n"
270 " location. You will be returned to the current search results\n"
271 " after exiting this new menu.\n"
8d9dfe82 272 "o The 'Selects:' line tells what symbols will be automatically\n"
1da177e4 273 " selected if this symbol is selected (y or m)\n"
8d9dfe82 274 "o The 'Selected by' line tells what symbol has selected this symbol\n"
1da177e4
LT
275 "\n"
276 "Only relevant lines are shown.\n"
277 "\n\n"
278 "Search examples:\n"
59dfa24d
AL
279 "Examples: USB => find all symbols containing USB\n"
280 " ^USB => find all symbols starting with USB\n"
281 " USB$ => find all symbols ending with USB\n"
694c49a7 282 "\n";
1da177e4 283
1da177e4 284static int indent;
1da177e4
LT
285static struct menu *current_menu;
286static int child_count;
1da177e4 287static int single_menu_mode;
22c7eca6 288static int show_all_options;
6364fd0c 289static int save_and_exit;
0a1f00a1 290static int silent;
1da177e4 291
5e609add 292static void conf(struct menu *menu, struct menu *active_menu);
1da177e4
LT
293static void conf_choice(struct menu *menu);
294static void conf_string(struct menu *menu);
295static void conf_load(void);
296static void conf_save(void);
95ac9b3b
BP
297static int show_textbox_ext(const char *title, char *text, int r, int c,
298 int *keys, int *vscroll, int *hscroll,
299 update_text_fn update_text, void *data);
1da177e4
LT
300static void show_textbox(const char *title, const char *text, int r, int c);
301static void show_helptext(const char *title, const char *text);
302static void show_help(struct menu *menu);
1da177e4 303
95e30f95
SR
304static char filename[PATH_MAX+1];
305static void set_config_filename(const char *config_filename)
306{
307 static char menu_backtitle[PATH_MAX+128];
95e30f95 308
68876c38
MY
309 snprintf(menu_backtitle, sizeof(menu_backtitle), "%s - %s",
310 config_filename, rootmenu.prompt->text);
95e30f95
SR
311 set_dialog_backtitle(menu_backtitle);
312
68876c38 313 snprintf(filename, sizeof(filename), "%s", config_filename);
95e30f95
SR
314}
315
9a69abf8
BP
316struct subtitle_part {
317 struct list_head entries;
318 const char *text;
319};
320static LIST_HEAD(trail);
321
322static struct subtitle_list *subtitles;
323static void set_subtitle(void)
324{
325 struct subtitle_part *sp;
326 struct subtitle_list *pos, *tmp;
327
328 for (pos = subtitles; pos != NULL; pos = tmp) {
329 tmp = pos->next;
330 free(pos);
331 }
332
333 subtitles = NULL;
334 list_for_each_entry(sp, &trail, entries) {
335 if (sp->text) {
336 if (pos) {
e4e458b4 337 pos->next = xcalloc(1, sizeof(*pos));
9a69abf8
BP
338 pos = pos->next;
339 } else {
e4e458b4 340 subtitles = pos = xcalloc(1, sizeof(*pos));
9a69abf8
BP
341 }
342 pos->text = sp->text;
343 }
344 }
345
346 set_dialog_subtitles(subtitles);
347}
348
349static void reset_subtitle(void)
350{
351 struct subtitle_list *pos, *tmp;
352
353 for (pos = subtitles; pos != NULL; pos = tmp) {
354 tmp = pos->next;
355 free(pos);
356 }
357 subtitles = NULL;
358 set_dialog_subtitles(subtitles);
359}
95e30f95 360
95ac9b3b 361struct search_data {
bad9955d 362 struct list_head *head;
95ac9b3b
BP
363 struct menu **targets;
364 int *keys;
365};
366
367static void update_text(char *buf, size_t start, size_t end, void *_data)
368{
369 struct search_data *data = _data;
370 struct jump_key *pos;
371 int k = 0;
372
bad9955d 373 list_for_each_entry(pos, data->head, entries) {
95ac9b3b
BP
374 if (pos->offset >= start && pos->offset < end) {
375 char header[4];
376
377 if (k < JUMP_NB) {
378 int key = '0' + (pos->index % JUMP_NB) + 1;
379
380 sprintf(header, "(%c)", key);
381 data->keys[k] = key;
382 data->targets[k] = pos->target;
383 k++;
384 } else {
385 sprintf(header, " ");
386 }
387
388 memcpy(buf + pos->offset, header, sizeof(header) - 1);
389 }
390 }
391 data->keys[k] = 0;
392}
393
1da177e4
LT
394static void search_conf(void)
395{
396 struct symbol **sym_arr;
1da177e4 397 struct gstr res;
337a275d 398 struct gstr title;
0584f9f9 399 char *dialog_input;
5e609add
BP
400 int dres, vscroll = 0, hscroll = 0;
401 bool again;
9a69abf8
BP
402 struct gstr sttext;
403 struct subtitle_part stpart;
5e609add 404
337a275d 405 title = str_new();
694c49a7
SR
406 str_printf( &title, "Enter (sub)string or regexp to search for "
407 "(with or without \"%s\")", CONFIG_);
337a275d 408
1da177e4 409again:
e94c5bde 410 dialog_clear();
694c49a7 411 dres = dialog_inputbox("Search Configuration Parameter",
337a275d 412 str_get(&title),
2982de69
SR
413 10, 75, "");
414 switch (dres) {
1da177e4
LT
415 case 0:
416 break;
417 case 1:
694c49a7 418 show_helptext("Search Configuration", search_help);
1da177e4
LT
419 goto again;
420 default:
337a275d 421 str_free(&title);
1da177e4
LT
422 return;
423 }
424
ffb5957b 425 /* strip the prefix if necessary */
0584f9f9 426 dialog_input = dialog_input_result;
ffb5957b
AL
427 if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
428 dialog_input += strlen(CONFIG_);
0584f9f9 429
9a69abf8
BP
430 sttext = str_new();
431 str_printf(&sttext, "Search (%s)", dialog_input_result);
432 stpart.text = str_get(&sttext);
433 list_add_tail(&stpart.entries, &trail);
434
0584f9f9 435 sym_arr = sym_re_search(dialog_input);
5e609add 436 do {
bad9955d 437 LIST_HEAD(head);
95ac9b3b
BP
438 struct menu *targets[JUMP_NB];
439 int keys[JUMP_NB + 1], i;
440 struct search_data data = {
441 .head = &head,
442 .targets = targets,
443 .keys = keys,
444 };
edb749f4 445 struct jump_key *pos, *tmp;
95ac9b3b
BP
446
447 res = get_relations_str(sym_arr, &head);
9a69abf8 448 set_subtitle();
4d980fd1 449 dres = show_textbox_ext("Search Results", str_get(&res), 0, 0,
be5ea989 450 keys, &vscroll, &hscroll, &update_text,
95ac9b3b 451 &data);
5e609add 452 again = false;
95ac9b3b 453 for (i = 0; i < JUMP_NB && keys[i]; i++)
5e609add 454 if (dres == keys[i]) {
95ac9b3b 455 conf(targets[i]->parent, targets[i]);
5e609add
BP
456 again = true;
457 }
458 str_free(&res);
edb749f4
BP
459 list_for_each_entry_safe(pos, tmp, &head, entries)
460 free(pos);
5e609add 461 } while (again);
1da177e4 462 free(sym_arr);
337a275d 463 str_free(&title);
9a69abf8
BP
464 list_del(trail.prev);
465 str_free(&sttext);
1da177e4
LT
466}
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;
22c7eca6
LZ
476 bool visible;
477
478 /*
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)
1da177e4
LT
486 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++;
1da177e4 496 if (single_menu_mode) {
2982de69
SR
497 item_make("%s%*c%s",
498 menu->data ? "-->" : "++>",
499 indent + 1, ' ', prompt);
1da177e4 500 } else
1278ebdb
DG
501 item_make(" %*c%s %s",
502 indent + 1, ' ', prompt,
503 menu_is_empty(menu) ? "----" : "--->");
2982de69
SR
504 item_set_tag('m');
505 item_set_data(menu);
1da177e4
LT
506 if (single_menu_mode && menu->data)
507 goto conf_childs;
508 return;
48874077
SR
509 case P_COMMENT:
510 if (prompt) {
511 child_count++;
694c49a7 512 item_make(" %*c*** %s ***", indent + 1, ' ', prompt);
48874077
SR
513 item_set_tag(':');
514 item_set_data(menu);
515 }
516 break;
1da177e4
LT
517 default:
518 if (prompt) {
519 child_count++;
694c49a7 520 item_make("---%*c%s", indent + 1, ' ', prompt);
2982de69
SR
521 item_set_tag(':');
522 item_set_data(menu);
1da177e4
LT
523 }
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);
baa23ec8 542 if (sym_is_changeable(sym)) {
1da177e4
LT
543 switch (type) {
544 case S_BOOLEAN:
2982de69 545 item_make("[%c]", val == no ? ' ' : '*');
1da177e4
LT
546 break;
547 case S_TRISTATE:
548 switch (val) {
549 case yes: ch = '*'; break;
550 case mod: ch = 'M'; break;
551 default: ch = ' '; break;
552 }
2982de69 553 item_make("<%c>", ch);
1da177e4
LT
554 break;
555 }
2982de69
SR
556 item_set_tag('t');
557 item_set_data(menu);
1da177e4 558 } else {
2982de69
SR
559 item_make(" ");
560 item_set_tag(def_menu ? 't' : ':');
561 item_set_data(menu);
1da177e4
LT
562 }
563
694c49a7 564 item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
1da177e4
LT
565 if (val == yes) {
566 if (def_menu) {
694c49a7 567 item_add_str(" (%s)", menu_get_prompt(def_menu));
2982de69 568 item_add_str(" --->");
1da177e4
LT
569 if (def_menu->list) {
570 indent += 2;
571 build_conf(def_menu);
572 indent -= 2;
573 }
2982de69 574 }
1da177e4
LT
575 return;
576 }
1da177e4
LT
577 } else {
578 if (menu == current_menu) {
694c49a7 579 item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
2982de69
SR
580 item_set_tag(':');
581 item_set_data(menu);
1da177e4
LT
582 goto conf_childs;
583 }
584 child_count++;
585 val = sym_get_tristate_value(sym);
586 if (sym_is_choice_value(sym) && val == yes) {
2982de69
SR
587 item_make(" ");
588 item_set_tag(':');
589 item_set_data(menu);
1da177e4
LT
590 } else {
591 switch (type) {
592 case S_BOOLEAN:
baa23ec8 593 if (sym_is_changeable(sym))
2982de69 594 item_make("[%c]", val == no ? ' ' : '*');
1da177e4 595 else
b5d609db 596 item_make("-%c-", val == no ? ' ' : '*');
2982de69
SR
597 item_set_tag('t');
598 item_set_data(menu);
1da177e4
LT
599 break;
600 case S_TRISTATE:
1da177e4
LT
601 switch (val) {
602 case yes: ch = '*'; break;
603 case mod: ch = 'M'; break;
604 default: ch = ' '; break;
605 }
baa23ec8 606 if (sym_is_changeable(sym)) {
b5d609db
ML
607 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);
2982de69
SR
613 item_set_tag('t');
614 item_set_data(menu);
1da177e4
LT
615 break;
616 default:
2982de69
SR
617 tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
618 item_make("(%s)", sym_get_string_value(sym));
1da177e4
LT
619 tmp = indent - tmp + 4;
620 if (tmp < 0)
621 tmp = 0;
694c49a7 622 item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
baa23ec8 623 (sym_has_value(sym) || !sym_is_changeable(sym)) ?
694c49a7 624 "" : " (NEW)");
2982de69
SR
625 item_set_tag('s');
626 item_set_data(menu);
1da177e4
LT
627 goto conf_childs;
628 }
629 }
694c49a7 630 item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
baa23ec8 631 (sym_has_value(sym) || !sym_is_changeable(sym)) ?
694c49a7 632 "" : " (NEW)");
1da177e4 633 if (menu->prompt->type == P_MENU) {
1278ebdb 634 item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->");
1da177e4
LT
635 return;
636 }
1da177e4
LT
637 }
638
639conf_childs:
640 indent += doint;
641 for (child = menu->list; child; child = child->next)
642 build_conf(child);
643 indent -= doint;
644}
645
5e609add 646static void conf(struct menu *menu, struct menu *active_menu)
1da177e4
LT
647{
648 struct menu *submenu;
649 const char *prompt = menu_get_prompt(menu);
9a69abf8 650 struct subtitle_part stpart;
1da177e4 651 struct symbol *sym;
2982de69
SR
652 int res;
653 int s_scroll = 0;
1da177e4 654
9a69abf8
BP
655 if (menu != &rootmenu)
656 stpart.text = menu_get_prompt(menu);
657 else
658 stpart.text = NULL;
659 list_add_tail(&stpart.entries, &trail);
660
1da177e4 661 while (1) {
2982de69 662 item_reset();
1da177e4
LT
663 current_menu = menu;
664 build_conf(menu);
665 if (!child_count)
666 break;
9a69abf8 667 set_subtitle();
e94c5bde 668 dialog_clear();
694c49a7
SR
669 res = dialog_menu(prompt ? prompt : "Main Menu",
670 menu_instructions,
2982de69 671 active_menu, &s_scroll);
c8dc68ad 672 if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
1da177e4 673 break;
063f4661
DG
674 if (item_count() != 0) {
675 if (!item_activate_selected())
676 continue;
677 if (!item_tag())
678 continue;
679 }
2982de69
SR
680 submenu = item_data();
681 active_menu = item_data();
c8dc68ad
SR
682 if (submenu)
683 sym = submenu->sym;
684 else
685 sym = NULL;
1da177e4 686
2982de69 687 switch (res) {
1da177e4 688 case 0:
2982de69 689 switch (item_tag()) {
1da177e4
LT
690 case 'm':
691 if (single_menu_mode)
692 submenu->data = (void *) (long) !submenu->data;
693 else
5e609add 694 conf(submenu, NULL);
1da177e4
LT
695 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)
5e609add 700 conf(submenu, NULL);
1da177e4
LT
701 break;
702 case 's':
703 conf_string(submenu);
704 break;
1da177e4
LT
705 }
706 break;
707 case 2:
708 if (sym)
709 show_help(submenu);
9a69abf8
BP
710 else {
711 reset_subtitle();
694c49a7 712 show_helptext("README", mconf_readme);
9a69abf8 713 }
1da177e4
LT
714 break;
715 case 3:
9a69abf8 716 reset_subtitle();
6364fd0c
WY
717 conf_save();
718 break;
719 case 4:
9a69abf8 720 reset_subtitle();
6364fd0c
WY
721 conf_load();
722 break;
723 case 5:
2982de69 724 if (item_is_tag('t')) {
1da177e4
LT
725 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;
6364fd0c 731 case 6:
2982de69 732 if (item_is_tag('t'))
1da177e4
LT
733 sym_set_tristate_value(sym, no);
734 break;
6364fd0c 735 case 7:
2982de69 736 if (item_is_tag('t'))
1da177e4
LT
737 sym_set_tristate_value(sym, mod);
738 break;
6364fd0c 739 case 8:
2982de69 740 if (item_is_tag('t'))
1da177e4 741 sym_toggle_tristate_value(sym);
2982de69 742 else if (item_is_tag('m'))
5e609add 743 conf(submenu, NULL);
1da177e4 744 break;
6364fd0c 745 case 9:
1da177e4
LT
746 search_conf();
747 break;
6364fd0c 748 case 10:
22c7eca6
LZ
749 show_all_options = !show_all_options;
750 break;
1da177e4
LT
751 }
752 }
9a69abf8
BP
753
754 list_del(trail.prev);
1da177e4
LT
755}
756
95ac9b3b
BP
757static 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)
1da177e4 760{
e94c5bde 761 dialog_clear();
95ac9b3b
BP
762 return dialog_textbox(title, text, r, c, keys, vscroll, hscroll,
763 update_text, data);
537ddae7
BP
764}
765
766static void show_textbox(const char *title, const char *text, int r, int c)
767{
95ac9b3b
BP
768 show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL,
769 NULL, NULL);
1da177e4
LT
770}
771
772static void show_helptext(const char *title, const char *text)
773{
774 show_textbox(title, text, 0, 0);
775}
776
5accd7f3 777static void conf_message_callback(const char *s)
6364fd0c 778{
0a1f00a1
MM
779 if (save_and_exit) {
780 if (!silent)
5accd7f3 781 printf("%s", s);
0a1f00a1 782 } else {
5accd7f3 783 show_textbox(NULL, s, 6, 60);
0a1f00a1 784 }
6364fd0c
WY
785}
786
1da177e4
LT
787static void show_help(struct menu *menu)
788{
789 struct gstr help = str_new();
1d525e7c 790
da60fbbc 791 help.max_width = getmaxx(stdscr) - 10;
1d525e7c
CR
792 menu_get_ext_help(menu, &help);
793
694c49a7 794 show_helptext(menu_get_prompt(menu), str_get(&help));
1da177e4
LT
795 str_free(&help);
796}
797
1da177e4
LT
798static void conf_choice(struct menu *menu)
799{
694c49a7 800 const char *prompt = menu_get_prompt(menu);
1da177e4
LT
801 struct menu *child;
802 struct symbol *active;
1da177e4
LT
803
804 active = sym_get_choice_value(menu->sym);
805 while (1) {
2982de69
SR
806 int res;
807 int selected;
808 item_reset();
1da177e4
LT
809
810 current_menu = menu;
811 for (child = menu->list; child; child = child->next) {
812 if (!menu_is_visible(child))
813 continue;
af6c1598 814 if (child->sym)
694c49a7 815 item_make("%s", menu_get_prompt(child));
af6c1598 816 else {
694c49a7 817 item_make("*** %s ***", menu_get_prompt(child));
af6c1598
PK
818 item_set_tag(':');
819 }
2982de69
SR
820 item_set_data(child);
821 if (child->sym == active)
822 item_set_selected(1);
1da177e4 823 if (child->sym == sym_get_choice_value(menu->sym))
2982de69 824 item_set_tag('X');
1da177e4 825 }
e94c5bde 826 dialog_clear();
694c49a7
SR
827 res = dialog_checklist(prompt ? prompt : "Main Menu",
828 radiolist_instructions,
ff7b0c2c
SD
829 MENUBOX_HEIGTH_MIN,
830 MENUBOX_WIDTH_MIN,
831 CHECKLIST_HEIGTH_MIN);
2982de69
SR
832 selected = item_activate_selected();
833 switch (res) {
1da177e4 834 case 0:
2982de69
SR
835 if (selected) {
836 child = item_data();
af6c1598
PK
837 if (!child->sym)
838 break;
839
2982de69
SR
840 sym_set_tristate_value(child->sym, yes);
841 }
1da177e4
LT
842 return;
843 case 1:
2982de69
SR
844 if (selected) {
845 child = item_data();
1da177e4
LT
846 show_help(child);
847 active = child->sym;
848 } else
849 show_help(menu);
850 break;
f3cbcdc9 851 case KEY_ESC:
1da177e4 852 return;
c8dc68ad
SR
853 case -ERRDISPLAYTOOSMALL:
854 return;
1da177e4
LT
855 }
856 }
857}
858
859static void conf_string(struct menu *menu)
860{
861 const char *prompt = menu_get_prompt(menu);
1da177e4
LT
862
863 while (1) {
2982de69 864 int res;
c4143a83 865 const char *heading;
2982de69 866
1da177e4
LT
867 switch (sym_get_type(menu->sym)) {
868 case S_INT:
694c49a7 869 heading = inputbox_instructions_int;
1da177e4
LT
870 break;
871 case S_HEX:
694c49a7 872 heading = inputbox_instructions_hex;
1da177e4
LT
873 break;
874 case S_STRING:
694c49a7 875 heading = inputbox_instructions_string;
1da177e4
LT
876 break;
877 default:
694c49a7 878 heading = "Internal mconf error!";
1da177e4 879 }
e94c5bde 880 dialog_clear();
694c49a7 881 res = dialog_inputbox(prompt ? prompt : "Main Menu",
2982de69
SR
882 heading, 10, 75,
883 sym_get_string_value(menu->sym));
884 switch (res) {
1da177e4 885 case 0:
2982de69 886 if (sym_set_string_value(menu->sym, dialog_input_result))
1da177e4 887 return;
694c49a7 888 show_textbox(NULL, "You have made an invalid entry.", 5, 43);
1da177e4
LT
889 break;
890 case 1:
891 show_help(menu);
892 break;
f3cbcdc9 893 case KEY_ESC:
1da177e4
LT
894 return;
895 }
896 }
897}
898
899static void conf_load(void)
900{
1da177e4
LT
901
902 while (1) {
2982de69 903 int res;
e94c5bde 904 dialog_clear();
2982de69
SR
905 res = dialog_inputbox(NULL, load_config_text,
906 11, 55, filename);
907 switch(res) {
1da177e4 908 case 0:
2982de69 909 if (!dialog_input_result[0])
1da177e4 910 return;
95e30f95
SR
911 if (!conf_read(dialog_input_result)) {
912 set_config_filename(dialog_input_result);
5ee54659 913 conf_set_changed(true);
1da177e4 914 return;
95e30f95 915 }
694c49a7 916 show_textbox(NULL, "File does not exist!", 5, 38);
1da177e4
LT
917 break;
918 case 1:
694c49a7 919 show_helptext("Load Alternate Configuration", load_config_help);
1da177e4 920 break;
f3cbcdc9 921 case KEY_ESC:
1da177e4
LT
922 return;
923 }
924 }
925}
926
927static void conf_save(void)
928{
1da177e4 929 while (1) {
2982de69 930 int res;
e94c5bde 931 dialog_clear();
2982de69
SR
932 res = dialog_inputbox(NULL, save_config_text,
933 11, 55, filename);
934 switch(res) {
1da177e4 935 case 0:
2982de69 936 if (!dialog_input_result[0])
1da177e4 937 return;
95e30f95
SR
938 if (!conf_write(dialog_input_result)) {
939 set_config_filename(dialog_input_result);
1da177e4 940 return;
95e30f95 941 }
580c5b3e 942 show_textbox(NULL, "Can't create file!", 5, 60);
1da177e4
LT
943 break;
944 case 1:
694c49a7 945 show_helptext("Save Alternate Configuration", save_config_help);
1da177e4 946 break;
f3cbcdc9 947 case KEY_ESC:
1da177e4
LT
948 return;
949 }
950 }
951}
952
564899f9
DB
953static int handle_exit(void)
954{
955 int res;
956
6364fd0c 957 save_and_exit = 1;
9a69abf8 958 reset_subtitle();
564899f9
DB
959 dialog_clear();
960 if (conf_get_changed())
961 res = dialog_yesno(NULL,
694c49a7
SR
962 "Do you wish to save your new configuration?\n"
963 "(Press <ESC><ESC> to continue kernel configuration.)",
564899f9
DB
964 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)) {
694c49a7 973 fprintf(stderr, "\n\n"
564899f9
DB
974 "Error while writing of the configuration.\n"
975 "Your configuration changes were NOT saved."
694c49a7 976 "\n\n");
564899f9
DB
977 return 1;
978 }
00c864f8 979 conf_write_autoconf(0);
564899f9
DB
980 /* fall through */
981 case -1:
0a1f00a1 982 if (!silent)
694c49a7 983 printf("\n\n"
0a1f00a1
MM
984 "*** End of the configuration.\n"
985 "*** Execute 'make' to start the build or try 'make help'."
694c49a7 986 "\n\n");
564899f9
DB
987 res = 0;
988 break;
989 default:
0a1f00a1 990 if (!silent)
694c49a7 991 fprintf(stderr, "\n\n"
0a1f00a1 992 "Your configuration changes were NOT saved."
694c49a7 993 "\n\n");
30c4eaaf
LZ
994 if (res != KEY_ESC)
995 res = 0;
564899f9
DB
996 }
997
998 return res;
999}
1000
1001static void sig_handler(int signo)
1002{
1003 exit(handle_exit());
1004}
1005
1da177e4
LT
1006int main(int ac, char **av)
1007{
1da177e4 1008 char *mode;
2982de69 1009 int res;
1da177e4 1010
564899f9
DB
1011 signal(SIGINT, sig_handler);
1012
0a1f00a1
MM
1013 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 }
1da177e4
LT
1019 conf_parse(av[1]);
1020 conf_read(NULL);
1021
1da177e4
LT
1022 mode = getenv("MENUCONFIG_MODE");
1023 if (mode) {
1024 if (!strcasecmp(mode, "single_menu"))
1025 single_menu_mode = 1;
1026 }
1027
09af091f 1028 if (init_dialog(NULL)) {
694c49a7
SR
1029 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");
09af091f
LM
1031 return 1;
1032 }
1033
d802b50f 1034 set_config_filename(conf_get_configname());
6364fd0c 1035 conf_set_message_callback(conf_message_callback);
f3cbcdc9 1036 do {
5e609add 1037 conf(&rootmenu, NULL);
564899f9 1038 res = handle_exit();
f3cbcdc9 1039 } while (res == KEY_ESC);
1da177e4 1040
564899f9 1041 return res;
1da177e4 1042}