blob: d2c2a429887b30152b57d26eaea78086a41bd3c3 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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>
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -07007 *
8 * i18n, 2005, Arnaldo Carvalho de Melo <acme@conectiva.com.br>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 */
10
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>
Jean-Christophe Dubois442ff702005-06-25 14:55:43 -070023#include <locale.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
25#define LKC_DIRECT_LINK
26#include "lkc.h"
Sam Ravnborg2982de62006-07-27 22:10:27 +020027#include "lxdialog/dialog.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070028
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -070029static const char mconf_readme[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -070030"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"
Sam Ravnborg45897212006-07-24 22:04:04 +0200162"default mode.\n"
163"\n"
164"Different color themes available\n"
165"--------------------------------\n"
166"It is possible to select different color themes using the variable\n"
167"MENUCONFIG_COLOR. To select a theme use:\n"
168"\n"
169"make MENUCONFIG_COLOR=<theme> menuconfig\n"
170"\n"
171"Available themes are\n"
172" mono => selects colors suitable for monochrome displays\n"
173" blackbg => selects a color scheme with black background\n"
Sam Ravnborg350b5b72006-07-24 22:19:51 +0200174" classic => theme with blue background. The classic look\n"
175" bluetitle => a LCD friendly version of classic. (default)\n"
Sam Ravnborg45897212006-07-24 22:04:04 +0200176"\n"),
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700177menu_instructions[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178 "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. "
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700183 "Legend: [*] built-in [ ] excluded <M> module < > module capable"),
184radiolist_instructions[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 "Use the arrow keys to navigate this window or "
186 "press the hotkey of the item you wish to select "
187 "followed by the <SPACE BAR>. "
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700188 "Press <?> for additional information about this option."),
189inputbox_instructions_int[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 "Please enter a decimal value. "
191 "Fractions will not be accepted. "
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700192 "Use the <TAB> key to move from the input field to the buttons below it."),
193inputbox_instructions_hex[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 "Please enter a hexadecimal value. "
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700195 "Use the <TAB> key to move from the input field to the buttons below it."),
196inputbox_instructions_string[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 "Please enter a string value. "
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700198 "Use the <TAB> key to move from the input field to the buttons below it."),
199setmod_text[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200 "This feature depends on another which has been configured as a module.\n"
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700201 "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_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 "Enter the name of the configuration file you wish to load. "
206 "Accept the name shown to restore the configuration you "
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700207 "last retrieved. Leave blank to abort."),
208load_config_help[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 "\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"
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700218 "configuration files. You should therefor leave this blank to abort.\n"),
219save_config_text[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 "Enter a filename to which this configuration should be saved "
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700221 "as an alternate. Leave blank to abort."),
222save_config_help[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223 "\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"
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700232 "leave this blank.\n"),
233search_help[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 "\n"
235 "Search for CONFIG_ symbols and display their relations.\n"
Randy Dunlap503af332005-10-30 15:02:15 -0800236 "Regular expressions are allowed.\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 "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"
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700271 "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273static int indent;
274static struct termios ios_org;
275static int rows = 0, cols = 0;
276static struct menu *current_menu;
277static int child_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278static 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288
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) {
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700315 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"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317 exit(1);
318 }
319
320 rows -= 4;
321 cols -= 5;
322}
323
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324static 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
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100396static 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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418static void search_conf(void)
419{
420 struct symbol **sym_arr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 struct gstr res;
Bernhard Walle0584f9f2007-07-09 11:43:56 -0700422 char *dialog_input;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200423 int dres;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424again:
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200425 dialog_clear();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200426 dres = dialog_inputbox(_("Search Configuration Parameter"),
Bernhard Walle0584f9f2007-07-09 11:43:56 -0700427 _("Enter CONFIG_ (sub)string to search for "
428 "(with or without \"CONFIG\")"),
Sam Ravnborg2982de62006-07-27 22:10:27 +0200429 10, 75, "");
430 switch (dres) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 case 0:
432 break;
433 case 1:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700434 show_helptext(_("Search Configuration"), search_help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 goto again;
436 default:
437 return;
438 }
439
Bernhard Walle0584f9f2007-07-09 11:43:56 -0700440 /* 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 res = get_relations_str(sym_arr);
447 free(sym_arr);
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700448 show_textbox(_("Search Results"), str_get(&res), 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 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++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 if (single_menu_mode) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200473 item_make("%s%*c%s",
474 menu->data ? "-->" : "++>",
475 indent + 1, ' ', prompt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 } else
Sam Ravnborg2982de62006-07-27 22:10:27 +0200477 item_make(" %*c%s --->", indent + 1, ' ', prompt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
Sam Ravnborg2982de62006-07-27 22:10:27 +0200479 item_set_tag('m');
480 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 if (single_menu_mode && menu->data)
482 goto conf_childs;
483 return;
484 default:
485 if (prompt) {
486 child_count++;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200487 item_make("---%*c%s", indent + 1, ' ', prompt);
488 item_set_tag(':');
489 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 }
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)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 switch (type) {
511 case S_BOOLEAN:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200512 item_make("[%c]", val == no ? ' ' : '*');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 break;
514 case S_TRISTATE:
515 switch (val) {
516 case yes: ch = '*'; break;
517 case mod: ch = 'M'; break;
518 default: ch = ' '; break;
519 }
Sam Ravnborg2982de62006-07-27 22:10:27 +0200520 item_make("<%c>", ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 break;
522 }
Sam Ravnborg2982de62006-07-27 22:10:27 +0200523 item_set_tag('t');
524 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 } else {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200526 item_make(" ");
527 item_set_tag(def_menu ? 't' : ':');
528 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 }
530
Sam Ravnborg2982de62006-07-27 22:10:27 +0200531 item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 if (val == yes) {
533 if (def_menu) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200534 item_add_str(" (%s)", menu_get_prompt(def_menu));
535 item_add_str(" --->");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 if (def_menu->list) {
537 indent += 2;
538 build_conf(def_menu);
539 indent -= 2;
540 }
Sam Ravnborg2982de62006-07-27 22:10:27 +0200541 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 return;
543 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 } else {
545 if (menu == current_menu) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200546 item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
547 item_set_tag(':');
548 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 goto conf_childs;
550 }
551 child_count++;
552 val = sym_get_tristate_value(sym);
553 if (sym_is_choice_value(sym) && val == yes) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200554 item_make(" ");
555 item_set_tag(':');
556 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 } else {
558 switch (type) {
559 case S_BOOLEAN:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 if (sym_is_changable(sym))
Sam Ravnborg2982de62006-07-27 22:10:27 +0200561 item_make("[%c]", val == no ? ' ' : '*');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 else
Sam Ravnborg2982de62006-07-27 22:10:27 +0200563 item_make("---");
564 item_set_tag('t');
565 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 break;
567 case S_TRISTATE:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 switch (val) {
569 case yes: ch = '*'; break;
570 case mod: ch = 'M'; break;
571 default: ch = ' '; break;
572 }
573 if (sym_is_changable(sym))
Sam Ravnborg2982de62006-07-27 22:10:27 +0200574 item_make("<%c>", ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 else
Sam Ravnborg2982de62006-07-27 22:10:27 +0200576 item_make("---");
577 item_set_tag('t');
578 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 break;
580 default:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200581 tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
582 item_make("(%s)", sym_get_string_value(sym));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 tmp = indent - tmp + 4;
584 if (tmp < 0)
585 tmp = 0;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200586 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 goto conf_childs;
592 }
593 }
Sam Ravnborg2982de62006-07-27 22:10:27 +0200594 item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
595 (sym_has_value(sym) || !sym_is_changable(sym)) ?
596 "" : " (NEW)");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 if (menu->prompt->type == P_MENU) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200598 item_add_str(" --->");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 return;
600 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 }
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;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200615 struct menu *active_menu = NULL;
616 int res;
617 int s_scroll = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200620 item_reset();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 current_menu = menu;
622 build_conf(menu);
623 if (!child_count)
624 break;
625 if (menu == &rootmenu) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200626 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');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 }
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200633 dialog_clear();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200634 res = dialog_menu(prompt ? prompt : _("Main Menu"),
635 _(menu_instructions),
Sam Ravnborg2982de62006-07-27 22:10:27 +0200636 active_menu, &s_scroll);
Sam Ravnborgc8dc68a2006-07-29 22:48:57 +0200637 if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 break;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200639 if (!item_activate_selected())
640 continue;
641 if (!item_tag())
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 continue;
643
Sam Ravnborg2982de62006-07-27 22:10:27 +0200644 submenu = item_data();
645 active_menu = item_data();
Sam Ravnborgc8dc68a2006-07-29 22:48:57 +0200646 if (submenu)
647 sym = submenu->sym;
648 else
649 sym = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650
Sam Ravnborg2982de62006-07-27 22:10:27 +0200651 switch (res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200653 switch (item_tag()) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 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
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700681 show_helptext("README", _(mconf_readme));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 break;
683 case 3:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200684 if (item_is_tag('t')) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 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:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200692 if (item_is_tag('t'))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 sym_set_tristate_value(sym, no);
694 break;
695 case 5:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200696 if (item_is_tag('t'))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 sym_set_tristate_value(sym, mod);
698 break;
699 case 6:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200700 if (item_is_tag('t'))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 sym_toggle_tristate_value(sym);
Sam Ravnborg2982de62006-07-27 22:10:27 +0200702 else if (item_is_tag('m'))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 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{
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200714 dialog_clear();
Sam Ravnborgc8dc68a2006-07-29 22:48:57 +0200715 dialog_textbox(title, text, r, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716}
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
728 if (sym->help)
729 {
730 if (sym->name) {
731 str_printf(&help, "CONFIG_%s:\n\n", sym->name);
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700732 str_append(&help, _(sym->help));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743static void conf_choice(struct menu *menu)
744{
745 const char *prompt = menu_get_prompt(menu);
746 struct menu *child;
747 struct symbol *active;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748
749 active = sym_get_choice_value(menu->sym);
750 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200751 int res;
752 int selected;
753 item_reset();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
755 current_menu = menu;
756 for (child = menu->list; child; child = child->next) {
757 if (!menu_is_visible(child))
758 continue;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200759 item_make("%s", menu_get_prompt(child));
760 item_set_data(child);
761 if (child->sym == active)
762 item_set_selected(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 if (child->sym == sym_get_choice_value(menu->sym))
Sam Ravnborg2982de62006-07-27 22:10:27 +0200764 item_set_tag('X');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 }
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200766 dialog_clear();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200767 res = dialog_checklist(prompt ? prompt : _("Main Menu"),
768 _(radiolist_instructions),
769 15, 70, 6);
770 selected = item_activate_selected();
771 switch (res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200773 if (selected) {
774 child = item_data();
775 sym_set_tristate_value(child->sym, yes);
776 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 return;
778 case 1:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200779 if (selected) {
780 child = item_data();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 show_help(child);
782 active = child->sym;
783 } else
784 show_help(menu);
785 break;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200786 case KEY_ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 return;
Sam Ravnborgc8dc68a2006-07-29 22:48:57 +0200788 case -ERRDISPLAYTOOSMALL:
789 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 }
791 }
792}
793
794static void conf_string(struct menu *menu)
795{
796 const char *prompt = menu_get_prompt(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797
798 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200799 int res;
800 char *heading;
801
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 switch (sym_get_type(menu->sym)) {
803 case S_INT:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200804 heading = _(inputbox_instructions_int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 break;
806 case S_HEX:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200807 heading = _(inputbox_instructions_hex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 break;
809 case S_STRING:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200810 heading = _(inputbox_instructions_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 break;
812 default:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200813 heading = "Internal mconf error!";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 }
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200815 dialog_clear();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200816 res = dialog_inputbox(prompt ? prompt : _("Main Menu"),
817 heading, 10, 75,
818 sym_get_string_value(menu->sym));
819 switch (res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200821 if (sym_set_string_value(menu->sym, dialog_input_result))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 return;
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700823 show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 break;
825 case 1:
826 show_help(menu);
827 break;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200828 case KEY_ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 return;
830 }
831 }
832}
833
834static void conf_load(void)
835{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836
837 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200838 int res;
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200839 dialog_clear();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200840 res = dialog_inputbox(NULL, load_config_text,
841 11, 55, filename);
842 switch(res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200844 if (!dialog_input_result[0])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 return;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100846 if (!conf_read(dialog_input_result)) {
847 set_config_filename(dialog_input_result);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 return;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100849 }
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700850 show_textbox(NULL, _("File does not exist!"), 5, 38);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 break;
852 case 1:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700853 show_helptext(_("Load Alternate Configuration"), load_config_help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 break;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200855 case KEY_ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 return;
857 }
858 }
859}
860
861static void conf_save(void)
862{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200864 int res;
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200865 dialog_clear();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200866 res = dialog_inputbox(NULL, save_config_text,
867 11, 55, filename);
868 switch(res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200870 if (!dialog_input_result[0])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 return;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100872 if (!conf_write(dialog_input_result)) {
873 set_config_filename(dialog_input_result);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 return;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100875 }
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700876 show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 break;
878 case 1:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700879 show_helptext(_("Save Alternate Configuration"), save_config_help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 break;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200881 case KEY_ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 return;
883 }
884 }
885}
886
887static void conf_cleanup(void)
888{
889 tcsetattr(1, TCSAFLUSH, &ios_org);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890}
891
892int main(int ac, char **av)
893{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 char *mode;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200895 int res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700897 setlocale(LC_ALL, "");
898 bindtextdomain(PACKAGE, LOCALEDIR);
899 textdomain(PACKAGE);
900
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 conf_parse(av[1]);
902 conf_read(NULL);
903
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 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();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200913 reset_dialog();
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100914 init_dialog(NULL);
Sam Ravnborgd802b502007-04-01 22:29:38 +0200915 set_config_filename(conf_get_configname());
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200916 do {
917 conf(&rootmenu);
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200918 dialog_clear();
Karsten Wieseb3214292006-12-13 00:34:06 -0800919 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;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200927 } while (res == KEY_ESC);
Sam Ravnborg2982de62006-07-27 22:10:27 +0200928 end_dialog();
Karsten Wieseb3214292006-12-13 00:34:06 -0800929
930 switch (res) {
931 case 0:
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100932 if (conf_write(filename)) {
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700933 fprintf(stderr, _("\n\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 "Error during writing of the kernel configuration.\n"
935 "Your kernel configuration changes were NOT saved."
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700936 "\n\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 return 1;
938 }
Karsten Wieseb3214292006-12-13 00:34:06 -0800939 case -1:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700940 printf(_("\n\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 "*** End of Linux kernel configuration.\n"
942 "*** Execute 'make' to build the kernel or try 'make help'."
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700943 "\n\n"));
Karsten Wieseb3214292006-12-13 00:34:06 -0800944 break;
945 default:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700946 fprintf(stderr, _("\n\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 "Your kernel configuration changes were NOT saved."
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700948 "\n\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 }
950
951 return 0;
952}