]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - scripts/kconfig/mconf.c
kconfig: add hints/tips/tricks to Documentation/kbuild/kconfig-language.txt
[mirror_ubuntu-zesty-kernel.git] / scripts / kconfig / mconf.c
CommitLineData
1da177e4
LT
1/*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
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
11#include <sys/ioctl.h>
12#include <sys/wait.h>
13#include <ctype.h>
14#include <errno.h>
15#include <fcntl.h>
16#include <limits.h>
17#include <signal.h>
18#include <stdarg.h>
19#include <stdlib.h>
20#include <string.h>
21#include <termios.h>
22#include <unistd.h>
442ff702 23#include <locale.h>
1da177e4
LT
24
25#define LKC_DIRECT_LINK
26#include "lkc.h"
2982de69 27#include "lxdialog/dialog.h"
1da177e4 28
3b9fa093 29static const char mconf_readme[] = N_(
1da177e4
LT
30"Overview\n"
31"--------\n"
32"Some kernel features may be built directly into the kernel.\n"
33"Some may be made into loadable runtime modules. Some features\n"
34"may be completely removed altogether. There are also certain\n"
35"kernel parameters which are not really features, but must be\n"
36"entered in as decimal or hexadecimal numbers or possibly text.\n"
37"\n"
b5d609db
ML
38"Menu items beginning with following braces represent features that\n"
39" [ ] can be built in or removed\n"
40" < > can be built in, modularized or removed\n"
41" { } can be built in or modularized (selected by other feature)\n"
42" - - are selected by other feature,\n"
43"while *, M or whitespace inside braces means to build in, build as\n"
44"a module or to exclude the feature respectively.\n"
1da177e4
LT
45"\n"
46"To change any of these features, highlight it with the cursor\n"
47"keys and press <Y> to build it in, <M> to make it a module or\n"
48"<N> to removed it. You may also press the <Space Bar> to cycle\n"
49"through the available options (ie. Y->N->M->Y).\n"
50"\n"
51"Some additional keyboard hints:\n"
52"\n"
53"Menus\n"
54"----------\n"
55"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
56" you wish to change or submenu wish to select and press <Enter>.\n"
57" Submenus are designated by \"--->\".\n"
58"\n"
59" Shortcut: Press the option's highlighted letter (hotkey).\n"
60" Pressing a hotkey more than once will sequence\n"
61" through all visible items which use that hotkey.\n"
62"\n"
63" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
64" unseen options into view.\n"
65"\n"
66"o To exit a menu use the cursor keys to highlight the <Exit> button\n"
67" and press <ENTER>.\n"
68"\n"
69" Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\n"
70" using those letters. You may press a single <ESC>, but\n"
71" there is a delayed response which you may find annoying.\n"
72"\n"
73" Also, the <TAB> and cursor keys will cycle between <Select>,\n"
74" <Exit> and <Help>\n"
75"\n"
76"o To get help with an item, use the cursor keys to highlight <Help>\n"
77" and Press <ENTER>.\n"
78"\n"
79" Shortcut: Press <H> or <?>.\n"
80"\n"
81"\n"
82"Radiolists (Choice lists)\n"
83"-----------\n"
84"o Use the cursor keys to select the option you wish to set and press\n"
85" <S> or the <SPACE BAR>.\n"
86"\n"
87" Shortcut: Press the first letter of the option you wish to set then\n"
88" press <S> or <SPACE BAR>.\n"
89"\n"
90"o To see available help for the item, use the cursor keys to highlight\n"
91" <Help> and Press <ENTER>.\n"
92"\n"
93" Shortcut: Press <H> or <?>.\n"
94"\n"
95" Also, the <TAB> and cursor keys will cycle between <Select> and\n"
96" <Help>\n"
97"\n"
98"\n"
99"Data Entry\n"
100"-----------\n"
101"o Enter the requested information and press <ENTER>\n"
102" If you are entering hexadecimal values, it is not necessary to\n"
103" add the '0x' prefix to the entry.\n"
104"\n"
105"o For help, use the <TAB> or cursor keys to highlight the help option\n"
106" and press <ENTER>. You can try <TAB><H> as well.\n"
107"\n"
108"\n"
109"Text Box (Help Window)\n"
110"--------\n"
111"o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
112" keys h,j,k,l function here as do <SPACE BAR> and <B> for those\n"
113" who are familiar with less and lynx.\n"
114"\n"
115"o Press <E>, <X>, <Enter> or <Esc><Esc> to exit.\n"
116"\n"
117"\n"
118"Alternate Configuration Files\n"
119"-----------------------------\n"
120"Menuconfig supports the use of alternate configuration files for\n"
121"those who, for various reasons, find it necessary to switch\n"
122"between different kernel configurations.\n"
123"\n"
124"At the end of the main menu you will find two options. One is\n"
125"for saving the current configuration to a file of your choosing.\n"
126"The other option is for loading a previously saved alternate\n"
127"configuration.\n"
128"\n"
129"Even if you don't use alternate configuration files, but you\n"
130"find during a Menuconfig session that you have completely messed\n"
131"up your settings, you may use the \"Load Alternate...\" option to\n"
132"restore your previously saved settings from \".config\" without\n"
133"restarting Menuconfig.\n"
134"\n"
135"Other information\n"
136"-----------------\n"
137"If you use Menuconfig in an XTERM window make sure you have your\n"
138"$TERM variable set to point to a xterm definition which supports color.\n"
139"Otherwise, Menuconfig will look rather bad. Menuconfig will not\n"
140"display correctly in a RXVT window because rxvt displays only one\n"
141"intensity of color, bright.\n"
142"\n"
143"Menuconfig will display larger menus on screens or xterms which are\n"
144"set to display more than the standard 25 row by 80 column geometry.\n"
145"In order for this to work, the \"stty size\" command must be able to\n"
146"display the screen's current row and column geometry. I STRONGLY\n"
147"RECOMMEND that you make sure you do NOT have the shell variables\n"
148"LINES and COLUMNS exported into your environment. Some distributions\n"
149"export those variables via /etc/profile. Some ncurses programs can\n"
150"become confused when those variables (LINES & COLUMNS) don't reflect\n"
151"the true screen size.\n"
152"\n"
153"Optional personality available\n"
154"------------------------------\n"
155"If you prefer to have all of the kernel options listed in a single\n"
156"menu, rather than the default multimenu hierarchy, run the menuconfig\n"
157"with MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
158"\n"
159"make MENUCONFIG_MODE=single_menu menuconfig\n"
160"\n"
161"<Enter> will then unroll the appropriate category, or enfold it if it\n"
162"is already unrolled.\n"
163"\n"
164"Note that this mode can eventually be a little more CPU expensive\n"
165"(especially with a larger number of unrolled categories) than the\n"
45897213
SR
166"default mode.\n"
167"\n"
168"Different color themes available\n"
169"--------------------------------\n"
170"It is possible to select different color themes using the variable\n"
171"MENUCONFIG_COLOR. To select a theme use:\n"
172"\n"
173"make MENUCONFIG_COLOR=<theme> menuconfig\n"
174"\n"
175"Available themes are\n"
176" mono => selects colors suitable for monochrome displays\n"
177" blackbg => selects a color scheme with black background\n"
350b5b76
SR
178" classic => theme with blue background. The classic look\n"
179" bluetitle => a LCD friendly version of classic. (default)\n"
45897213 180"\n"),
3b9fa093 181menu_instructions[] = N_(
1da177e4
LT
182 "Arrow keys navigate the menu. "
183 "<Enter> selects submenus --->. "
184 "Highlighted letters are hotkeys. "
185 "Pressing <Y> includes, <N> excludes, <M> modularizes features. "
186 "Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
3b9fa093
ACM
187 "Legend: [*] built-in [ ] excluded <M> module < > module capable"),
188radiolist_instructions[] = N_(
1da177e4
LT
189 "Use the arrow keys to navigate this window or "
190 "press the hotkey of the item you wish to select "
191 "followed by the <SPACE BAR>. "
3b9fa093
ACM
192 "Press <?> for additional information about this option."),
193inputbox_instructions_int[] = N_(
1da177e4
LT
194 "Please enter a decimal value. "
195 "Fractions will not be accepted. "
3b9fa093
ACM
196 "Use the <TAB> key to move from the input field to the buttons below it."),
197inputbox_instructions_hex[] = N_(
1da177e4 198 "Please enter a hexadecimal value. "
3b9fa093
ACM
199 "Use the <TAB> key to move from the input field to the buttons below it."),
200inputbox_instructions_string[] = N_(
1da177e4 201 "Please enter a string value. "
3b9fa093
ACM
202 "Use the <TAB> key to move from the input field to the buttons below it."),
203setmod_text[] = N_(
1da177e4 204 "This feature depends on another which has been configured as a module.\n"
3b9fa093
ACM
205 "As a result, this feature will be built as a module."),
206nohelp_text[] = N_(
207 "There is no help available for this kernel option.\n"),
208load_config_text[] = N_(
1da177e4
LT
209 "Enter the name of the configuration file you wish to load. "
210 "Accept the name shown to restore the configuration you "
3b9fa093
ACM
211 "last retrieved. Leave blank to abort."),
212load_config_help[] = N_(
1da177e4
LT
213 "\n"
214 "For various reasons, one may wish to keep several different kernel\n"
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"
218 "kernel's default, entering the name of the file here will allow you\n"
219 "to modify that configuration.\n"
220 "\n"
221 "If you are uncertain, then you have probably never used alternate\n"
3b9fa093
ACM
222 "configuration files. You should therefor leave this blank to abort.\n"),
223save_config_text[] = N_(
1da177e4 224 "Enter a filename to which this configuration should be saved "
3b9fa093
ACM
225 "as an alternate. Leave blank to abort."),
226save_config_help[] = N_(
1da177e4
LT
227 "\n"
228 "For various reasons, one may wish to keep different kernel\n"
229 "configurations available on a single machine.\n"
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"
3b9fa093
ACM
236 "leave this blank.\n"),
237search_help[] = N_(
1da177e4
LT
238 "\n"
239 "Search for CONFIG_ 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"
245 "Prompt: Foo bus is used to drive the bar HW\n"
246 "Defined at drivers/pci/Kconfig:47\n"
247 "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
248 "Location:\n"
249 " -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
250 " -> PCI support (PCI [=y])\n"
251 " -> PCI access mode (<choice> [=y])\n"
252 "Selects: LIBCRC32\n"
253 "Selected by: BAR\n"
254 "-----------------------------------------------------------------\n"
255 "o The line 'Prompt:' shows the text used in the menu structure for\n"
256 " this CONFIG_ symbol\n"
257 "o The 'Defined at' line tell at what file / line number the symbol\n"
258 " is defined\n"
259 "o The 'Depends on:' line tell what symbols needs to be defined for\n"
260 " this symbol to be visible in the menu (selectable)\n"
261 "o The 'Location:' lines tell where in the menu structure this symbol\n"
262 " is located\n"
263 " A location followed by a [=y] indicate that this is a selectable\n"
264 " menu item - and current value is displayed inside brackets.\n"
265 "o The 'Selects:' line tell what symbol will be automatically\n"
266 " selected if this symbol is selected (y or m)\n"
267 "o The 'Selected by' line tell what symbol has selected this symbol\n"
268 "\n"
269 "Only relevant lines are shown.\n"
270 "\n\n"
271 "Search examples:\n"
272 "Examples: USB => find all CONFIG_ symbols containing USB\n"
273 " ^USB => find all CONFIG_ symbols starting with USB\n"
274 " USB$ => find all CONFIG_ symbols ending with USB\n"
3b9fa093 275 "\n");
1da177e4 276
1da177e4
LT
277static int indent;
278static struct termios ios_org;
279static int rows = 0, cols = 0;
280static struct menu *current_menu;
281static int child_count;
1da177e4
LT
282static int single_menu_mode;
283
284static void conf(struct menu *menu);
285static void conf_choice(struct menu *menu);
286static void conf_string(struct menu *menu);
287static void conf_load(void);
288static void conf_save(void);
289static void show_textbox(const char *title, const char *text, int r, int c);
290static void show_helptext(const char *title, const char *text);
291static void show_help(struct menu *menu);
1da177e4
LT
292
293static void init_wsize(void)
294{
295 struct winsize ws;
296 char *env;
297
298 if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &ws)) {
299 rows = ws.ws_row;
300 cols = ws.ws_col;
301 }
302
303 if (!rows) {
304 env = getenv("LINES");
305 if (env)
306 rows = atoi(env);
307 if (!rows)
308 rows = 24;
309 }
310 if (!cols) {
311 env = getenv("COLUMNS");
312 if (env)
313 cols = atoi(env);
314 if (!cols)
315 cols = 80;
316 }
317
318 if (rows < 19 || cols < 80) {
3b9fa093
ACM
319 fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
320 fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
1da177e4
LT
321 exit(1);
322 }
323
324 rows -= 4;
325 cols -= 5;
326}
327
1da177e4
LT
328static void get_prompt_str(struct gstr *r, struct property *prop)
329{
330 int i, j;
331 struct menu *submenu[8], *menu;
332
333 str_printf(r, "Prompt: %s\n", prop->text);
334 str_printf(r, " Defined at %s:%d\n", prop->menu->file->name,
335 prop->menu->lineno);
336 if (!expr_is_yes(prop->visible.expr)) {
337 str_append(r, " Depends on: ");
338 expr_gstr_print(prop->visible.expr, r);
339 str_append(r, "\n");
340 }
341 menu = prop->menu->parent;
342 for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
343 submenu[i++] = menu;
344 if (i > 0) {
345 str_printf(r, " Location:\n");
346 for (j = 4; --i >= 0; j += 2) {
347 menu = submenu[i];
348 str_printf(r, "%*c-> %s", j, ' ', menu_get_prompt(menu));
349 if (menu->sym) {
350 str_printf(r, " (%s [=%s])", menu->sym->name ?
351 menu->sym->name : "<choice>",
352 sym_get_string_value(menu->sym));
353 }
354 str_append(r, "\n");
355 }
356 }
357}
358
359static void get_symbol_str(struct gstr *r, struct symbol *sym)
360{
361 bool hit;
362 struct property *prop;
363
a67cb131
SR
364 if (sym && sym->name)
365 str_printf(r, "Symbol: %s [=%s]\n", sym->name,
366 sym_get_string_value(sym));
1da177e4
LT
367 for_all_prompts(sym, prop)
368 get_prompt_str(r, prop);
369 hit = false;
370 for_all_properties(sym, prop, P_SELECT) {
371 if (!hit) {
372 str_append(r, " Selects: ");
373 hit = true;
374 } else
375 str_printf(r, " && ");
376 expr_gstr_print(prop->expr, r);
377 }
378 if (hit)
379 str_append(r, "\n");
380 if (sym->rev_dep.expr) {
381 str_append(r, " Selected by: ");
382 expr_gstr_print(sym->rev_dep.expr, r);
383 str_append(r, "\n");
384 }
385 str_append(r, "\n\n");
386}
387
388static struct gstr get_relations_str(struct symbol **sym_arr)
389{
390 struct symbol *sym;
391 struct gstr res = str_new();
392 int i;
393
394 for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
395 get_symbol_str(&res, sym);
396 if (!i)
397 str_append(&res, "No matches found.\n");
398 return res;
399}
400
95e30f95
SR
401static char filename[PATH_MAX+1];
402static void set_config_filename(const char *config_filename)
403{
404 static char menu_backtitle[PATH_MAX+128];
405 int size;
406 struct symbol *sym;
407
408 sym = sym_lookup("KERNELVERSION", 0);
409 sym_calc_value(sym);
410 size = snprintf(menu_backtitle, sizeof(menu_backtitle),
411 _("%s - Linux Kernel v%s Configuration"),
412 config_filename, sym_get_string_value(sym));
413 if (size >= sizeof(menu_backtitle))
414 menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
415 set_dialog_backtitle(menu_backtitle);
416
417 size = snprintf(filename, sizeof(filename), "%s", config_filename);
418 if (size >= sizeof(filename))
419 filename[sizeof(filename)-1] = '\0';
420}
421
422
1da177e4
LT
423static void search_conf(void)
424{
425 struct symbol **sym_arr;
1da177e4 426 struct gstr res;
0584f9f9 427 char *dialog_input;
2982de69 428 int dres;
1da177e4 429again:
e94c5bde 430 dialog_clear();
2982de69 431 dres = dialog_inputbox(_("Search Configuration Parameter"),
0584f9f9
BW
432 _("Enter CONFIG_ (sub)string to search for "
433 "(with or without \"CONFIG\")"),
2982de69
SR
434 10, 75, "");
435 switch (dres) {
1da177e4
LT
436 case 0:
437 break;
438 case 1:
3b9fa093 439 show_helptext(_("Search Configuration"), search_help);
1da177e4
LT
440 goto again;
441 default:
442 return;
443 }
444
0584f9f9
BW
445 /* strip CONFIG_ if necessary */
446 dialog_input = dialog_input_result;
447 if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0)
448 dialog_input += 7;
449
450 sym_arr = sym_re_search(dialog_input);
1da177e4
LT
451 res = get_relations_str(sym_arr);
452 free(sym_arr);
3b9fa093 453 show_textbox(_("Search Results"), str_get(&res), 0, 0);
1da177e4
LT
454 str_free(&res);
455}
456
457static void build_conf(struct menu *menu)
458{
459 struct symbol *sym;
460 struct property *prop;
461 struct menu *child;
462 int type, tmp, doint = 2;
463 tristate val;
464 char ch;
465
466 if (!menu_is_visible(menu))
467 return;
468
469 sym = menu->sym;
470 prop = menu->prompt;
471 if (!sym) {
472 if (prop && menu != current_menu) {
473 const char *prompt = menu_get_prompt(menu);
474 switch (prop->type) {
475 case P_MENU:
476 child_count++;
1da177e4 477 if (single_menu_mode) {
2982de69
SR
478 item_make("%s%*c%s",
479 menu->data ? "-->" : "++>",
480 indent + 1, ' ', prompt);
1da177e4 481 } else
2982de69 482 item_make(" %*c%s --->", indent + 1, ' ', prompt);
1da177e4 483
2982de69
SR
484 item_set_tag('m');
485 item_set_data(menu);
1da177e4
LT
486 if (single_menu_mode && menu->data)
487 goto conf_childs;
488 return;
48874077
SR
489 case P_COMMENT:
490 if (prompt) {
491 child_count++;
492 item_make(" %*c*** %s ***", indent + 1, ' ', prompt);
493 item_set_tag(':');
494 item_set_data(menu);
495 }
496 break;
1da177e4
LT
497 default:
498 if (prompt) {
499 child_count++;
2982de69
SR
500 item_make("---%*c%s", indent + 1, ' ', prompt);
501 item_set_tag(':');
502 item_set_data(menu);
1da177e4
LT
503 }
504 }
505 } else
506 doint = 0;
507 goto conf_childs;
508 }
509
510 type = sym_get_type(sym);
511 if (sym_is_choice(sym)) {
512 struct symbol *def_sym = sym_get_choice_value(sym);
513 struct menu *def_menu = NULL;
514
515 child_count++;
516 for (child = menu->list; child; child = child->next) {
517 if (menu_is_visible(child) && child->sym == def_sym)
518 def_menu = child;
519 }
520
521 val = sym_get_tristate_value(sym);
522 if (sym_is_changable(sym)) {
1da177e4
LT
523 switch (type) {
524 case S_BOOLEAN:
2982de69 525 item_make("[%c]", val == no ? ' ' : '*');
1da177e4
LT
526 break;
527 case S_TRISTATE:
528 switch (val) {
529 case yes: ch = '*'; break;
530 case mod: ch = 'M'; break;
531 default: ch = ' '; break;
532 }
2982de69 533 item_make("<%c>", ch);
1da177e4
LT
534 break;
535 }
2982de69
SR
536 item_set_tag('t');
537 item_set_data(menu);
1da177e4 538 } else {
2982de69
SR
539 item_make(" ");
540 item_set_tag(def_menu ? 't' : ':');
541 item_set_data(menu);
1da177e4
LT
542 }
543
2982de69 544 item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
1da177e4
LT
545 if (val == yes) {
546 if (def_menu) {
2982de69
SR
547 item_add_str(" (%s)", menu_get_prompt(def_menu));
548 item_add_str(" --->");
1da177e4
LT
549 if (def_menu->list) {
550 indent += 2;
551 build_conf(def_menu);
552 indent -= 2;
553 }
2982de69 554 }
1da177e4
LT
555 return;
556 }
1da177e4
LT
557 } else {
558 if (menu == current_menu) {
2982de69
SR
559 item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
560 item_set_tag(':');
561 item_set_data(menu);
1da177e4
LT
562 goto conf_childs;
563 }
564 child_count++;
565 val = sym_get_tristate_value(sym);
566 if (sym_is_choice_value(sym) && val == yes) {
2982de69
SR
567 item_make(" ");
568 item_set_tag(':');
569 item_set_data(menu);
1da177e4
LT
570 } else {
571 switch (type) {
572 case S_BOOLEAN:
1da177e4 573 if (sym_is_changable(sym))
2982de69 574 item_make("[%c]", val == no ? ' ' : '*');
1da177e4 575 else
b5d609db 576 item_make("-%c-", val == no ? ' ' : '*');
2982de69
SR
577 item_set_tag('t');
578 item_set_data(menu);
1da177e4
LT
579 break;
580 case S_TRISTATE:
1da177e4
LT
581 switch (val) {
582 case yes: ch = '*'; break;
583 case mod: ch = 'M'; break;
584 default: ch = ' '; break;
585 }
b5d609db
ML
586 if (sym_is_changable(sym)) {
587 if (sym->rev_dep.tri == mod)
588 item_make("{%c}", ch);
589 else
590 item_make("<%c>", ch);
591 } else
592 item_make("-%c-", ch);
2982de69
SR
593 item_set_tag('t');
594 item_set_data(menu);
1da177e4
LT
595 break;
596 default:
2982de69
SR
597 tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
598 item_make("(%s)", sym_get_string_value(sym));
1da177e4
LT
599 tmp = indent - tmp + 4;
600 if (tmp < 0)
601 tmp = 0;
2982de69
SR
602 item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
603 (sym_has_value(sym) || !sym_is_changable(sym)) ?
604 "" : " (NEW)");
605 item_set_tag('s');
606 item_set_data(menu);
1da177e4
LT
607 goto conf_childs;
608 }
609 }
2982de69
SR
610 item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
611 (sym_has_value(sym) || !sym_is_changable(sym)) ?
612 "" : " (NEW)");
1da177e4 613 if (menu->prompt->type == P_MENU) {
2982de69 614 item_add_str(" --->");
1da177e4
LT
615 return;
616 }
1da177e4
LT
617 }
618
619conf_childs:
620 indent += doint;
621 for (child = menu->list; child; child = child->next)
622 build_conf(child);
623 indent -= doint;
624}
625
626static void conf(struct menu *menu)
627{
628 struct menu *submenu;
629 const char *prompt = menu_get_prompt(menu);
630 struct symbol *sym;
2982de69
SR
631 struct menu *active_menu = NULL;
632 int res;
633 int s_scroll = 0;
1da177e4 634
1da177e4 635 while (1) {
2982de69 636 item_reset();
1da177e4
LT
637 current_menu = menu;
638 build_conf(menu);
639 if (!child_count)
640 break;
641 if (menu == &rootmenu) {
2982de69
SR
642 item_make("--- ");
643 item_set_tag(':');
644 item_make(_(" Load an Alternate Configuration File"));
645 item_set_tag('L');
646 item_make(_(" Save an Alternate Configuration File"));
647 item_set_tag('S');
1da177e4 648 }
e94c5bde 649 dialog_clear();
2982de69
SR
650 res = dialog_menu(prompt ? prompt : _("Main Menu"),
651 _(menu_instructions),
2982de69 652 active_menu, &s_scroll);
c8dc68ad 653 if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
1da177e4 654 break;
2982de69
SR
655 if (!item_activate_selected())
656 continue;
657 if (!item_tag())
1da177e4
LT
658 continue;
659
2982de69
SR
660 submenu = item_data();
661 active_menu = item_data();
c8dc68ad
SR
662 if (submenu)
663 sym = submenu->sym;
664 else
665 sym = NULL;
1da177e4 666
2982de69 667 switch (res) {
1da177e4 668 case 0:
2982de69 669 switch (item_tag()) {
1da177e4
LT
670 case 'm':
671 if (single_menu_mode)
672 submenu->data = (void *) (long) !submenu->data;
673 else
674 conf(submenu);
675 break;
676 case 't':
677 if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
678 conf_choice(submenu);
679 else if (submenu->prompt->type == P_MENU)
680 conf(submenu);
681 break;
682 case 's':
683 conf_string(submenu);
684 break;
685 case 'L':
686 conf_load();
687 break;
688 case 'S':
689 conf_save();
690 break;
691 }
692 break;
693 case 2:
694 if (sym)
695 show_help(submenu);
696 else
3b9fa093 697 show_helptext("README", _(mconf_readme));
1da177e4
LT
698 break;
699 case 3:
2982de69 700 if (item_is_tag('t')) {
1da177e4
LT
701 if (sym_set_tristate_value(sym, yes))
702 break;
703 if (sym_set_tristate_value(sym, mod))
704 show_textbox(NULL, setmod_text, 6, 74);
705 }
706 break;
707 case 4:
2982de69 708 if (item_is_tag('t'))
1da177e4
LT
709 sym_set_tristate_value(sym, no);
710 break;
711 case 5:
2982de69 712 if (item_is_tag('t'))
1da177e4
LT
713 sym_set_tristate_value(sym, mod);
714 break;
715 case 6:
2982de69 716 if (item_is_tag('t'))
1da177e4 717 sym_toggle_tristate_value(sym);
2982de69 718 else if (item_is_tag('m'))
1da177e4
LT
719 conf(submenu);
720 break;
721 case 7:
722 search_conf();
723 break;
724 }
725 }
726}
727
728static void show_textbox(const char *title, const char *text, int r, int c)
729{
e94c5bde 730 dialog_clear();
c8dc68ad 731 dialog_textbox(title, text, r, c);
1da177e4
LT
732}
733
734static void show_helptext(const char *title, const char *text)
735{
736 show_textbox(title, text, 0, 0);
737}
738
739static void show_help(struct menu *menu)
740{
741 struct gstr help = str_new();
742 struct symbol *sym = menu->sym;
743
03d29122 744 if (menu_has_help(menu))
1da177e4
LT
745 {
746 if (sym->name) {
747 str_printf(&help, "CONFIG_%s:\n\n", sym->name);
03d29122 748 str_append(&help, _(menu_get_help(menu)));
1da177e4
LT
749 str_append(&help, "\n");
750 }
751 } else {
752 str_append(&help, nohelp_text);
753 }
754 get_symbol_str(&help, sym);
755 show_helptext(menu_get_prompt(menu), str_get(&help));
756 str_free(&help);
757}
758
1da177e4
LT
759static void conf_choice(struct menu *menu)
760{
761 const char *prompt = menu_get_prompt(menu);
762 struct menu *child;
763 struct symbol *active;
1da177e4
LT
764
765 active = sym_get_choice_value(menu->sym);
766 while (1) {
2982de69
SR
767 int res;
768 int selected;
769 item_reset();
1da177e4
LT
770
771 current_menu = menu;
772 for (child = menu->list; child; child = child->next) {
773 if (!menu_is_visible(child))
774 continue;
2982de69
SR
775 item_make("%s", menu_get_prompt(child));
776 item_set_data(child);
777 if (child->sym == active)
778 item_set_selected(1);
1da177e4 779 if (child->sym == sym_get_choice_value(menu->sym))
2982de69 780 item_set_tag('X');
1da177e4 781 }
e94c5bde 782 dialog_clear();
2982de69
SR
783 res = dialog_checklist(prompt ? prompt : _("Main Menu"),
784 _(radiolist_instructions),
785 15, 70, 6);
786 selected = item_activate_selected();
787 switch (res) {
1da177e4 788 case 0:
2982de69
SR
789 if (selected) {
790 child = item_data();
791 sym_set_tristate_value(child->sym, yes);
792 }
1da177e4
LT
793 return;
794 case 1:
2982de69
SR
795 if (selected) {
796 child = item_data();
1da177e4
LT
797 show_help(child);
798 active = child->sym;
799 } else
800 show_help(menu);
801 break;
f3cbcdc9 802 case KEY_ESC:
1da177e4 803 return;
c8dc68ad
SR
804 case -ERRDISPLAYTOOSMALL:
805 return;
1da177e4
LT
806 }
807 }
808}
809
810static void conf_string(struct menu *menu)
811{
812 const char *prompt = menu_get_prompt(menu);
1da177e4
LT
813
814 while (1) {
2982de69
SR
815 int res;
816 char *heading;
817
1da177e4
LT
818 switch (sym_get_type(menu->sym)) {
819 case S_INT:
2982de69 820 heading = _(inputbox_instructions_int);
1da177e4
LT
821 break;
822 case S_HEX:
2982de69 823 heading = _(inputbox_instructions_hex);
1da177e4
LT
824 break;
825 case S_STRING:
2982de69 826 heading = _(inputbox_instructions_string);
1da177e4
LT
827 break;
828 default:
2982de69 829 heading = "Internal mconf error!";
1da177e4 830 }
e94c5bde 831 dialog_clear();
2982de69
SR
832 res = dialog_inputbox(prompt ? prompt : _("Main Menu"),
833 heading, 10, 75,
834 sym_get_string_value(menu->sym));
835 switch (res) {
1da177e4 836 case 0:
2982de69 837 if (sym_set_string_value(menu->sym, dialog_input_result))
1da177e4 838 return;
3b9fa093 839 show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
1da177e4
LT
840 break;
841 case 1:
842 show_help(menu);
843 break;
f3cbcdc9 844 case KEY_ESC:
1da177e4
LT
845 return;
846 }
847 }
848}
849
850static void conf_load(void)
851{
1da177e4
LT
852
853 while (1) {
2982de69 854 int res;
e94c5bde 855 dialog_clear();
2982de69
SR
856 res = dialog_inputbox(NULL, load_config_text,
857 11, 55, filename);
858 switch(res) {
1da177e4 859 case 0:
2982de69 860 if (!dialog_input_result[0])
1da177e4 861 return;
95e30f95
SR
862 if (!conf_read(dialog_input_result)) {
863 set_config_filename(dialog_input_result);
1da177e4 864 return;
95e30f95 865 }
3b9fa093 866 show_textbox(NULL, _("File does not exist!"), 5, 38);
1da177e4
LT
867 break;
868 case 1:
3b9fa093 869 show_helptext(_("Load Alternate Configuration"), load_config_help);
1da177e4 870 break;
f3cbcdc9 871 case KEY_ESC:
1da177e4
LT
872 return;
873 }
874 }
875}
876
877static void conf_save(void)
878{
1da177e4 879 while (1) {
2982de69 880 int res;
e94c5bde 881 dialog_clear();
2982de69
SR
882 res = dialog_inputbox(NULL, save_config_text,
883 11, 55, filename);
884 switch(res) {
1da177e4 885 case 0:
2982de69 886 if (!dialog_input_result[0])
1da177e4 887 return;
95e30f95
SR
888 if (!conf_write(dialog_input_result)) {
889 set_config_filename(dialog_input_result);
1da177e4 890 return;
95e30f95 891 }
3b9fa093 892 show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60);
1da177e4
LT
893 break;
894 case 1:
3b9fa093 895 show_helptext(_("Save Alternate Configuration"), save_config_help);
1da177e4 896 break;
f3cbcdc9 897 case KEY_ESC:
1da177e4
LT
898 return;
899 }
900 }
901}
902
903static void conf_cleanup(void)
904{
905 tcsetattr(1, TCSAFLUSH, &ios_org);
1da177e4
LT
906}
907
908int main(int ac, char **av)
909{
1da177e4 910 char *mode;
2982de69 911 int res;
1da177e4 912
3b9fa093
ACM
913 setlocale(LC_ALL, "");
914 bindtextdomain(PACKAGE, LOCALEDIR);
915 textdomain(PACKAGE);
916
1da177e4
LT
917 conf_parse(av[1]);
918 conf_read(NULL);
919
1da177e4
LT
920 mode = getenv("MENUCONFIG_MODE");
921 if (mode) {
922 if (!strcasecmp(mode, "single_menu"))
923 single_menu_mode = 1;
924 }
925
926 tcgetattr(1, &ios_org);
927 atexit(conf_cleanup);
928 init_wsize();
2982de69 929 reset_dialog();
95e30f95 930 init_dialog(NULL);
d802b50f 931 set_config_filename(conf_get_configname());
f3cbcdc9
SR
932 do {
933 conf(&rootmenu);
e94c5bde 934 dialog_clear();
b3214293
KW
935 if (conf_get_changed())
936 res = dialog_yesno(NULL,
937 _("Do you wish to save your "
938 "new kernel configuration?\n"
939 "<ESC><ESC> to continue."),
940 6, 60);
941 else
942 res = -1;
f3cbcdc9 943 } while (res == KEY_ESC);
2982de69 944 end_dialog();
b3214293
KW
945
946 switch (res) {
947 case 0:
95e30f95 948 if (conf_write(filename)) {
3b9fa093 949 fprintf(stderr, _("\n\n"
1da177e4
LT
950 "Error during writing of the kernel configuration.\n"
951 "Your kernel configuration changes were NOT saved."
3b9fa093 952 "\n\n"));
1da177e4
LT
953 return 1;
954 }
b3214293 955 case -1:
3b9fa093 956 printf(_("\n\n"
1da177e4
LT
957 "*** End of Linux kernel configuration.\n"
958 "*** Execute 'make' to build the kernel or try 'make help'."
3b9fa093 959 "\n\n"));
b3214293
KW
960 break;
961 default:
3b9fa093 962 fprintf(stderr, _("\n\n"
1da177e4 963 "Your kernel configuration changes were NOT saved."
3b9fa093 964 "\n\n"));
1da177e4
LT
965 }
966
967 return 0;
968}