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