kconfig: m/nconf: merge two item_add_str() calls
[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
4dae9cf5 22#include "list.h"
1da177e4 23#include "lkc.h"
2982de69 24#include "lxdialog/dialog.h"
6c07fd84 25#include "mnconf-common.h"
1da177e4 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 251 " Defined at drivers/pci/Kconfig:47\n"
0df8e970 252 " Depends on: X86_LOCAL_APIC && X86_IO_APIC\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 293
95e30f95
SR
294static char filename[PATH_MAX+1];
295static void set_config_filename(const char *config_filename)
296{
297 static char menu_backtitle[PATH_MAX+128];
95e30f95 298
68876c38
MY
299 snprintf(menu_backtitle, sizeof(menu_backtitle), "%s - %s",
300 config_filename, rootmenu.prompt->text);
95e30f95
SR
301 set_dialog_backtitle(menu_backtitle);
302
68876c38 303 snprintf(filename, sizeof(filename), "%s", config_filename);
95e30f95
SR
304}
305
9a69abf8
BP
306struct subtitle_part {
307 struct list_head entries;
308 const char *text;
309};
310static LIST_HEAD(trail);
311
312static struct subtitle_list *subtitles;
313static void set_subtitle(void)
314{
315 struct subtitle_part *sp;
316 struct subtitle_list *pos, *tmp;
317
318 for (pos = subtitles; pos != NULL; pos = tmp) {
319 tmp = pos->next;
320 free(pos);
321 }
322
323 subtitles = NULL;
324 list_for_each_entry(sp, &trail, entries) {
325 if (sp->text) {
326 if (pos) {
e4e458b4 327 pos->next = xcalloc(1, sizeof(*pos));
9a69abf8
BP
328 pos = pos->next;
329 } else {
e4e458b4 330 subtitles = pos = xcalloc(1, sizeof(*pos));
9a69abf8
BP
331 }
332 pos->text = sp->text;
333 }
334 }
335
336 set_dialog_subtitles(subtitles);
337}
338
339static void reset_subtitle(void)
340{
341 struct subtitle_list *pos, *tmp;
342
343 for (pos = subtitles; pos != NULL; pos = tmp) {
344 tmp = pos->next;
345 free(pos);
346 }
347 subtitles = NULL;
348 set_dialog_subtitles(subtitles);
349}
95e30f95 350
e14f1242
MY
351static int show_textbox_ext(const char *title, const char *text, int r, int c,
352 int *vscroll, int *hscroll,
353 int (*extra_key_cb)(int, size_t, size_t, void *),
354 void *data)
fb318e54
MY
355{
356 dialog_clear();
e14f1242
MY
357 return dialog_textbox(title, text, r, c, vscroll, hscroll,
358 extra_key_cb, data);
fb318e54
MY
359}
360
361static void show_textbox(const char *title, const char *text, int r, int c)
362{
e14f1242 363 show_textbox_ext(title, text, r, c, NULL, NULL, NULL, NULL);
fb318e54
MY
364}
365
366static void show_helptext(const char *title, const char *text)
367{
368 show_textbox(title, text, 0, 0);
369}
370
371static void show_help(struct menu *menu)
372{
373 struct gstr help = str_new();
374
375 help.max_width = getmaxx(stdscr) - 10;
376 menu_get_ext_help(menu, &help);
377
378 show_helptext(menu_get_prompt(menu), str_get(&help));
379 str_free(&help);
380}
381
1da177e4
LT
382static void search_conf(void)
383{
384 struct symbol **sym_arr;
1da177e4 385 struct gstr res;
337a275d 386 struct gstr title;
0584f9f9 387 char *dialog_input;
5e609add
BP
388 int dres, vscroll = 0, hscroll = 0;
389 bool again;
9a69abf8
BP
390 struct gstr sttext;
391 struct subtitle_part stpart;
5e609add 392
337a275d 393 title = str_new();
694c49a7
SR
394 str_printf( &title, "Enter (sub)string or regexp to search for "
395 "(with or without \"%s\")", CONFIG_);
337a275d 396
1da177e4 397again:
e94c5bde 398 dialog_clear();
694c49a7 399 dres = dialog_inputbox("Search Configuration Parameter",
337a275d 400 str_get(&title),
2982de69
SR
401 10, 75, "");
402 switch (dres) {
1da177e4
LT
403 case 0:
404 break;
405 case 1:
694c49a7 406 show_helptext("Search Configuration", search_help);
1da177e4
LT
407 goto again;
408 default:
337a275d 409 str_free(&title);
1da177e4
LT
410 return;
411 }
412
ffb5957b 413 /* strip the prefix if necessary */
0584f9f9 414 dialog_input = dialog_input_result;
ffb5957b
AL
415 if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
416 dialog_input += strlen(CONFIG_);
0584f9f9 417
9a69abf8
BP
418 sttext = str_new();
419 str_printf(&sttext, "Search (%s)", dialog_input_result);
420 stpart.text = str_get(&sttext);
421 list_add_tail(&stpart.entries, &trail);
422
0584f9f9 423 sym_arr = sym_re_search(dialog_input);
5e609add 424 do {
bad9955d 425 LIST_HEAD(head);
95ac9b3b
BP
426 struct search_data data = {
427 .head = &head,
95ac9b3b 428 };
edb749f4 429 struct jump_key *pos, *tmp;
95ac9b3b 430
e14f1242 431 jump_key_char = 0;
95ac9b3b 432 res = get_relations_str(sym_arr, &head);
9a69abf8 433 set_subtitle();
4d980fd1 434 dres = show_textbox_ext("Search Results", str_get(&res), 0, 0,
e14f1242
MY
435 &vscroll, &hscroll,
436 handle_search_keys, &data);
5e609add 437 again = false;
e14f1242
MY
438 if (dres >= '1' && dres <= '9') {
439 assert(data.target != NULL);
440 conf(data.target->parent, data.target);
441 again = true;
442 }
5e609add 443 str_free(&res);
edb749f4
BP
444 list_for_each_entry_safe(pos, tmp, &head, entries)
445 free(pos);
5e609add 446 } while (again);
1da177e4 447 free(sym_arr);
337a275d 448 str_free(&title);
9a69abf8
BP
449 list_del(trail.prev);
450 str_free(&sttext);
1da177e4
LT
451}
452
453static void build_conf(struct menu *menu)
454{
455 struct symbol *sym;
456 struct property *prop;
457 struct menu *child;
458 int type, tmp, doint = 2;
459 tristate val;
460 char ch;
22c7eca6
LZ
461 bool visible;
462
463 /*
464 * note: menu_is_visible() has side effect that it will
465 * recalc the value of the symbol.
466 */
467 visible = menu_is_visible(menu);
468 if (show_all_options && !menu_has_prompt(menu))
469 return;
470 else if (!show_all_options && !visible)
1da177e4
LT
471 return;
472
473 sym = menu->sym;
474 prop = menu->prompt;
475 if (!sym) {
476 if (prop && menu != current_menu) {
477 const char *prompt = menu_get_prompt(menu);
478 switch (prop->type) {
479 case P_MENU:
480 child_count++;
1da177e4 481 if (single_menu_mode) {
2982de69
SR
482 item_make("%s%*c%s",
483 menu->data ? "-->" : "++>",
484 indent + 1, ' ', prompt);
1da177e4 485 } else
1278ebdb
DG
486 item_make(" %*c%s %s",
487 indent + 1, ' ', prompt,
488 menu_is_empty(menu) ? "----" : "--->");
2982de69
SR
489 item_set_tag('m');
490 item_set_data(menu);
1da177e4
LT
491 if (single_menu_mode && menu->data)
492 goto conf_childs;
493 return;
48874077
SR
494 case P_COMMENT:
495 if (prompt) {
496 child_count++;
694c49a7 497 item_make(" %*c*** %s ***", indent + 1, ' ', prompt);
48874077
SR
498 item_set_tag(':');
499 item_set_data(menu);
500 }
501 break;
1da177e4
LT
502 default:
503 if (prompt) {
504 child_count++;
694c49a7 505 item_make("---%*c%s", indent + 1, ' ', prompt);
2982de69
SR
506 item_set_tag(':');
507 item_set_data(menu);
1da177e4
LT
508 }
509 }
510 } else
511 doint = 0;
512 goto conf_childs;
513 }
514
515 type = sym_get_type(sym);
516 if (sym_is_choice(sym)) {
517 struct symbol *def_sym = sym_get_choice_value(sym);
518 struct menu *def_menu = NULL;
519
520 child_count++;
521 for (child = menu->list; child; child = child->next) {
522 if (menu_is_visible(child) && child->sym == def_sym)
523 def_menu = child;
524 }
525
526 val = sym_get_tristate_value(sym);
baa23ec8 527 if (sym_is_changeable(sym)) {
cc3e4e5e
MY
528 switch (val) {
529 case yes: ch = '*'; break;
530 case mod: ch = 'M'; break;
531 default: ch = ' '; break;
1da177e4 532 }
cc3e4e5e 533 item_make("<%c>", ch);
2982de69
SR
534 item_set_tag('t');
535 item_set_data(menu);
1da177e4 536 } else {
2982de69
SR
537 item_make(" ");
538 item_set_tag(def_menu ? 't' : ':');
539 item_set_data(menu);
1da177e4
LT
540 }
541
694c49a7 542 item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
1da177e4 543 if (val == yes) {
648d82a9
MY
544 if (def_menu)
545 item_add_str(" (%s) --->", menu_get_prompt(def_menu));
1da177e4
LT
546 return;
547 }
1da177e4
LT
548 } else {
549 if (menu == current_menu) {
694c49a7 550 item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
2982de69
SR
551 item_set_tag(':');
552 item_set_data(menu);
1da177e4
LT
553 goto conf_childs;
554 }
555 child_count++;
556 val = sym_get_tristate_value(sym);
e89b4615
MY
557 switch (type) {
558 case S_BOOLEAN:
559 if (sym_is_changeable(sym))
560 item_make("[%c]", val == no ? ' ' : '*');
561 else
562 item_make("-%c-", val == no ? ' ' : '*');
563 item_set_tag('t');
2982de69 564 item_set_data(menu);
e89b4615
MY
565 break;
566 case S_TRISTATE:
567 switch (val) {
568 case yes: ch = '*'; break;
569 case mod: ch = 'M'; break;
570 default: ch = ' '; break;
1da177e4 571 }
e89b4615
MY
572 if (sym_is_changeable(sym)) {
573 if (sym->rev_dep.tri == mod)
574 item_make("{%c}", ch);
575 else
576 item_make("<%c>", ch);
577 } else
578 item_make("-%c-", ch);
579 item_set_tag('t');
580 item_set_data(menu);
581 break;
582 default:
583 tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
584 item_make("(%s)", sym_get_string_value(sym));
585 tmp = indent - tmp + 4;
586 if (tmp < 0)
587 tmp = 0;
588 item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
589 (sym_has_value(sym) || !sym_is_changeable(sym)) ?
590 "" : " (NEW)");
591 item_set_tag('s');
592 item_set_data(menu);
593 goto conf_childs;
1da177e4 594 }
694c49a7 595 item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
baa23ec8 596 (sym_has_value(sym) || !sym_is_changeable(sym)) ?
694c49a7 597 "" : " (NEW)");
1da177e4 598 if (menu->prompt->type == P_MENU) {
1278ebdb 599 item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->");
1da177e4
LT
600 return;
601 }
1da177e4
LT
602 }
603
604conf_childs:
605 indent += doint;
606 for (child = menu->list; child; child = child->next)
607 build_conf(child);
608 indent -= doint;
609}
610
1da177e4
LT
611static void conf_choice(struct menu *menu)
612{
694c49a7 613 const char *prompt = menu_get_prompt(menu);
1da177e4
LT
614 struct menu *child;
615 struct symbol *active;
1da177e4
LT
616
617 active = sym_get_choice_value(menu->sym);
618 while (1) {
2982de69
SR
619 int res;
620 int selected;
621 item_reset();
1da177e4
LT
622
623 current_menu = menu;
624 for (child = menu->list; child; child = child->next) {
625 if (!menu_is_visible(child))
626 continue;
af6c1598 627 if (child->sym)
694c49a7 628 item_make("%s", menu_get_prompt(child));
af6c1598 629 else {
694c49a7 630 item_make("*** %s ***", menu_get_prompt(child));
af6c1598
PK
631 item_set_tag(':');
632 }
2982de69
SR
633 item_set_data(child);
634 if (child->sym == active)
635 item_set_selected(1);
1da177e4 636 if (child->sym == sym_get_choice_value(menu->sym))
2982de69 637 item_set_tag('X');
1da177e4 638 }
e94c5bde 639 dialog_clear();
694c49a7
SR
640 res = dialog_checklist(prompt ? prompt : "Main Menu",
641 radiolist_instructions,
89e5462b 642 MENUBOX_HEIGHT_MIN,
ff7b0c2c 643 MENUBOX_WIDTH_MIN,
89e5462b 644 CHECKLIST_HEIGHT_MIN);
2982de69
SR
645 selected = item_activate_selected();
646 switch (res) {
1da177e4 647 case 0:
2982de69
SR
648 if (selected) {
649 child = item_data();
af6c1598
PK
650 if (!child->sym)
651 break;
652
2982de69
SR
653 sym_set_tristate_value(child->sym, yes);
654 }
1da177e4
LT
655 return;
656 case 1:
2982de69
SR
657 if (selected) {
658 child = item_data();
1da177e4
LT
659 show_help(child);
660 active = child->sym;
661 } else
662 show_help(menu);
663 break;
f3cbcdc9 664 case KEY_ESC:
1da177e4 665 return;
c8dc68ad
SR
666 case -ERRDISPLAYTOOSMALL:
667 return;
1da177e4
LT
668 }
669 }
670}
671
672static void conf_string(struct menu *menu)
673{
674 const char *prompt = menu_get_prompt(menu);
1da177e4
LT
675
676 while (1) {
2982de69 677 int res;
c4143a83 678 const char *heading;
2982de69 679
1da177e4
LT
680 switch (sym_get_type(menu->sym)) {
681 case S_INT:
694c49a7 682 heading = inputbox_instructions_int;
1da177e4
LT
683 break;
684 case S_HEX:
694c49a7 685 heading = inputbox_instructions_hex;
1da177e4
LT
686 break;
687 case S_STRING:
694c49a7 688 heading = inputbox_instructions_string;
1da177e4
LT
689 break;
690 default:
694c49a7 691 heading = "Internal mconf error!";
1da177e4 692 }
e94c5bde 693 dialog_clear();
694c49a7 694 res = dialog_inputbox(prompt ? prompt : "Main Menu",
2982de69
SR
695 heading, 10, 75,
696 sym_get_string_value(menu->sym));
697 switch (res) {
1da177e4 698 case 0:
2982de69 699 if (sym_set_string_value(menu->sym, dialog_input_result))
1da177e4 700 return;
694c49a7 701 show_textbox(NULL, "You have made an invalid entry.", 5, 43);
1da177e4
LT
702 break;
703 case 1:
704 show_help(menu);
705 break;
f3cbcdc9 706 case KEY_ESC:
1da177e4
LT
707 return;
708 }
709 }
710}
711
712static void conf_load(void)
713{
1da177e4
LT
714
715 while (1) {
2982de69 716 int res;
e94c5bde 717 dialog_clear();
2982de69
SR
718 res = dialog_inputbox(NULL, load_config_text,
719 11, 55, filename);
720 switch(res) {
1da177e4 721 case 0:
2982de69 722 if (!dialog_input_result[0])
1da177e4 723 return;
95e30f95
SR
724 if (!conf_read(dialog_input_result)) {
725 set_config_filename(dialog_input_result);
5ee54659 726 conf_set_changed(true);
1da177e4 727 return;
95e30f95 728 }
694c49a7 729 show_textbox(NULL, "File does not exist!", 5, 38);
1da177e4
LT
730 break;
731 case 1:
694c49a7 732 show_helptext("Load Alternate Configuration", load_config_help);
1da177e4 733 break;
f3cbcdc9 734 case KEY_ESC:
1da177e4
LT
735 return;
736 }
737 }
738}
739
740static void conf_save(void)
741{
1da177e4 742 while (1) {
2982de69 743 int res;
e94c5bde 744 dialog_clear();
2982de69
SR
745 res = dialog_inputbox(NULL, save_config_text,
746 11, 55, filename);
747 switch(res) {
1da177e4 748 case 0:
2982de69 749 if (!dialog_input_result[0])
1da177e4 750 return;
95e30f95
SR
751 if (!conf_write(dialog_input_result)) {
752 set_config_filename(dialog_input_result);
1da177e4 753 return;
95e30f95 754 }
580c5b3e 755 show_textbox(NULL, "Can't create file!", 5, 60);
1da177e4
LT
756 break;
757 case 1:
694c49a7 758 show_helptext("Save Alternate Configuration", save_config_help);
1da177e4 759 break;
f3cbcdc9 760 case KEY_ESC:
1da177e4
LT
761 return;
762 }
763 }
764}
765
fb318e54
MY
766static void conf(struct menu *menu, struct menu *active_menu)
767{
768 struct menu *submenu;
769 const char *prompt = menu_get_prompt(menu);
770 struct subtitle_part stpart;
771 struct symbol *sym;
772 int res;
773 int s_scroll = 0;
774
775 if (menu != &rootmenu)
776 stpart.text = menu_get_prompt(menu);
777 else
778 stpart.text = NULL;
779 list_add_tail(&stpart.entries, &trail);
780
781 while (1) {
782 item_reset();
783 current_menu = menu;
784 build_conf(menu);
785 if (!child_count)
786 break;
787 set_subtitle();
788 dialog_clear();
789 res = dialog_menu(prompt ? prompt : "Main Menu",
790 menu_instructions,
791 active_menu, &s_scroll);
792 if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
793 break;
794 if (item_count() != 0) {
795 if (!item_activate_selected())
796 continue;
797 if (!item_tag())
798 continue;
799 }
800 submenu = item_data();
801 active_menu = item_data();
802 if (submenu)
803 sym = submenu->sym;
804 else
805 sym = NULL;
806
807 switch (res) {
808 case 0:
809 switch (item_tag()) {
810 case 'm':
811 if (single_menu_mode)
812 submenu->data = (void *) (long) !submenu->data;
813 else
814 conf(submenu, NULL);
815 break;
816 case 't':
817 if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
818 conf_choice(submenu);
819 else if (submenu->prompt->type == P_MENU)
820 conf(submenu, NULL);
821 break;
822 case 's':
823 conf_string(submenu);
824 break;
825 }
826 break;
827 case 2:
828 if (sym)
829 show_help(submenu);
830 else {
831 reset_subtitle();
832 show_helptext("README", mconf_readme);
833 }
834 break;
835 case 3:
836 reset_subtitle();
837 conf_save();
838 break;
839 case 4:
840 reset_subtitle();
841 conf_load();
842 break;
843 case 5:
844 if (item_is_tag('t')) {
845 if (sym_set_tristate_value(sym, yes))
846 break;
847 if (sym_set_tristate_value(sym, mod))
848 show_textbox(NULL, setmod_text, 6, 74);
849 }
850 break;
851 case 6:
852 if (item_is_tag('t'))
853 sym_set_tristate_value(sym, no);
854 break;
855 case 7:
856 if (item_is_tag('t'))
857 sym_set_tristate_value(sym, mod);
858 break;
859 case 8:
860 if (item_is_tag('t'))
861 sym_toggle_tristate_value(sym);
862 else if (item_is_tag('m'))
863 conf(submenu, NULL);
864 break;
865 case 9:
866 search_conf();
867 break;
868 case 10:
869 show_all_options = !show_all_options;
870 break;
871 }
872 }
873
874 list_del(trail.prev);
875}
876
877static void conf_message_callback(const char *s)
878{
879 if (save_and_exit) {
880 if (!silent)
881 printf("%s", s);
882 } else {
883 show_textbox(NULL, s, 6, 60);
884 }
885}
886
564899f9
DB
887static int handle_exit(void)
888{
889 int res;
890
6364fd0c 891 save_and_exit = 1;
9a69abf8 892 reset_subtitle();
564899f9
DB
893 dialog_clear();
894 if (conf_get_changed())
895 res = dialog_yesno(NULL,
694c49a7
SR
896 "Do you wish to save your new configuration?\n"
897 "(Press <ESC><ESC> to continue kernel configuration.)",
564899f9
DB
898 6, 60);
899 else
900 res = -1;
901
902 end_dialog(saved_x, saved_y);
903
904 switch (res) {
905 case 0:
906 if (conf_write(filename)) {
694c49a7 907 fprintf(stderr, "\n\n"
564899f9
DB
908 "Error while writing of the configuration.\n"
909 "Your configuration changes were NOT saved."
694c49a7 910 "\n\n");
564899f9
DB
911 return 1;
912 }
00c864f8 913 conf_write_autoconf(0);
564899f9
DB
914 /* fall through */
915 case -1:
0a1f00a1 916 if (!silent)
694c49a7 917 printf("\n\n"
0a1f00a1
MM
918 "*** End of the configuration.\n"
919 "*** Execute 'make' to start the build or try 'make help'."
694c49a7 920 "\n\n");
564899f9
DB
921 res = 0;
922 break;
923 default:
0a1f00a1 924 if (!silent)
694c49a7 925 fprintf(stderr, "\n\n"
0a1f00a1 926 "Your configuration changes were NOT saved."
694c49a7 927 "\n\n");
30c4eaaf
LZ
928 if (res != KEY_ESC)
929 res = 0;
564899f9
DB
930 }
931
932 return res;
933}
934
935static void sig_handler(int signo)
936{
937 exit(handle_exit());
938}
939
1da177e4
LT
940int main(int ac, char **av)
941{
1da177e4 942 char *mode;
2982de69 943 int res;
1da177e4 944
564899f9
DB
945 signal(SIGINT, sig_handler);
946
0a1f00a1
MM
947 if (ac > 1 && strcmp(av[1], "-s") == 0) {
948 silent = 1;
949 /* Silence conf_read() until the real callback is set up */
950 conf_set_message_callback(NULL);
951 av++;
952 }
1da177e4
LT
953 conf_parse(av[1]);
954 conf_read(NULL);
955
1da177e4
LT
956 mode = getenv("MENUCONFIG_MODE");
957 if (mode) {
958 if (!strcasecmp(mode, "single_menu"))
959 single_menu_mode = 1;
960 }
961
09af091f 962 if (init_dialog(NULL)) {
694c49a7
SR
963 fprintf(stderr, "Your display is too small to run Menuconfig!\n");
964 fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
09af091f
LM
965 return 1;
966 }
967
d802b50f 968 set_config_filename(conf_get_configname());
6364fd0c 969 conf_set_message_callback(conf_message_callback);
f3cbcdc9 970 do {
5e609add 971 conf(&rootmenu, NULL);
564899f9 972 res = handle_exit();
f3cbcdc9 973 } while (res == KEY_ESC);
1da177e4 974
564899f9 975 return res;
1da177e4 976}