blob: 1935818040e25a18609962e58850344ca2815ecd [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
Sam Ravnborga67cb132007-09-19 21:23:09 +0200360 if (sym && sym->name)
361 str_printf(r, "Symbol: %s [=%s]\n", sym->name,
362 sym_get_string_value(sym));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363 for_all_prompts(sym, prop)
364 get_prompt_str(r, prop);
365 hit = false;
366 for_all_properties(sym, prop, P_SELECT) {
367 if (!hit) {
368 str_append(r, " Selects: ");
369 hit = true;
370 } else
371 str_printf(r, " && ");
372 expr_gstr_print(prop->expr, r);
373 }
374 if (hit)
375 str_append(r, "\n");
376 if (sym->rev_dep.expr) {
377 str_append(r, " Selected by: ");
378 expr_gstr_print(sym->rev_dep.expr, r);
379 str_append(r, "\n");
380 }
381 str_append(r, "\n\n");
382}
383
384static struct gstr get_relations_str(struct symbol **sym_arr)
385{
386 struct symbol *sym;
387 struct gstr res = str_new();
388 int i;
389
390 for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
391 get_symbol_str(&res, sym);
392 if (!i)
393 str_append(&res, "No matches found.\n");
394 return res;
395}
396
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100397static char filename[PATH_MAX+1];
398static void set_config_filename(const char *config_filename)
399{
400 static char menu_backtitle[PATH_MAX+128];
401 int size;
402 struct symbol *sym;
403
404 sym = sym_lookup("KERNELVERSION", 0);
405 sym_calc_value(sym);
406 size = snprintf(menu_backtitle, sizeof(menu_backtitle),
407 _("%s - Linux Kernel v%s Configuration"),
408 config_filename, sym_get_string_value(sym));
409 if (size >= sizeof(menu_backtitle))
410 menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
411 set_dialog_backtitle(menu_backtitle);
412
413 size = snprintf(filename, sizeof(filename), "%s", config_filename);
414 if (size >= sizeof(filename))
415 filename[sizeof(filename)-1] = '\0';
416}
417
418
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419static void search_conf(void)
420{
421 struct symbol **sym_arr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 struct gstr res;
Bernhard Walle0584f9f2007-07-09 11:43:56 -0700423 char *dialog_input;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200424 int dres;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425again:
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200426 dialog_clear();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200427 dres = dialog_inputbox(_("Search Configuration Parameter"),
Bernhard Walle0584f9f2007-07-09 11:43:56 -0700428 _("Enter CONFIG_ (sub)string to search for "
429 "(with or without \"CONFIG\")"),
Sam Ravnborg2982de62006-07-27 22:10:27 +0200430 10, 75, "");
431 switch (dres) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 case 0:
433 break;
434 case 1:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700435 show_helptext(_("Search Configuration"), search_help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 goto again;
437 default:
438 return;
439 }
440
Bernhard Walle0584f9f2007-07-09 11:43:56 -0700441 /* strip CONFIG_ if necessary */
442 dialog_input = dialog_input_result;
443 if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0)
444 dialog_input += 7;
445
446 sym_arr = sym_re_search(dialog_input);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 res = get_relations_str(sym_arr);
448 free(sym_arr);
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700449 show_textbox(_("Search Results"), str_get(&res), 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 str_free(&res);
451}
452
453static void build_conf(struct menu *menu)
454{
455 struct symbol *sym;
456 struct property *prop;
457 struct menu *child;
458 int type, tmp, doint = 2;
459 tristate val;
460 char ch;
461
462 if (!menu_is_visible(menu))
463 return;
464
465 sym = menu->sym;
466 prop = menu->prompt;
467 if (!sym) {
468 if (prop && menu != current_menu) {
469 const char *prompt = menu_get_prompt(menu);
470 switch (prop->type) {
471 case P_MENU:
472 child_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 if (single_menu_mode) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200474 item_make("%s%*c%s",
475 menu->data ? "-->" : "++>",
476 indent + 1, ' ', prompt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 } else
Sam Ravnborg2982de62006-07-27 22:10:27 +0200478 item_make(" %*c%s --->", indent + 1, ' ', prompt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479
Sam Ravnborg2982de62006-07-27 22:10:27 +0200480 item_set_tag('m');
481 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482 if (single_menu_mode && menu->data)
483 goto conf_childs;
484 return;
Sam Ravnborg48874072007-09-18 21:12:26 +0200485 case P_COMMENT:
486 if (prompt) {
487 child_count++;
488 item_make(" %*c*** %s ***", indent + 1, ' ', prompt);
489 item_set_tag(':');
490 item_set_data(menu);
491 }
492 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 default:
494 if (prompt) {
495 child_count++;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200496 item_make("---%*c%s", indent + 1, ' ', prompt);
497 item_set_tag(':');
498 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 }
500 }
501 } else
502 doint = 0;
503 goto conf_childs;
504 }
505
506 type = sym_get_type(sym);
507 if (sym_is_choice(sym)) {
508 struct symbol *def_sym = sym_get_choice_value(sym);
509 struct menu *def_menu = NULL;
510
511 child_count++;
512 for (child = menu->list; child; child = child->next) {
513 if (menu_is_visible(child) && child->sym == def_sym)
514 def_menu = child;
515 }
516
517 val = sym_get_tristate_value(sym);
518 if (sym_is_changable(sym)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 switch (type) {
520 case S_BOOLEAN:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200521 item_make("[%c]", val == no ? ' ' : '*');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 break;
523 case S_TRISTATE:
524 switch (val) {
525 case yes: ch = '*'; break;
526 case mod: ch = 'M'; break;
527 default: ch = ' '; break;
528 }
Sam Ravnborg2982de62006-07-27 22:10:27 +0200529 item_make("<%c>", ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 break;
531 }
Sam Ravnborg2982de62006-07-27 22:10:27 +0200532 item_set_tag('t');
533 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 } else {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200535 item_make(" ");
536 item_set_tag(def_menu ? 't' : ':');
537 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 }
539
Sam Ravnborg2982de62006-07-27 22:10:27 +0200540 item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 if (val == yes) {
542 if (def_menu) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200543 item_add_str(" (%s)", menu_get_prompt(def_menu));
544 item_add_str(" --->");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 if (def_menu->list) {
546 indent += 2;
547 build_conf(def_menu);
548 indent -= 2;
549 }
Sam Ravnborg2982de62006-07-27 22:10:27 +0200550 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 return;
552 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 } else {
554 if (menu == current_menu) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200555 item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
556 item_set_tag(':');
557 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 goto conf_childs;
559 }
560 child_count++;
561 val = sym_get_tristate_value(sym);
562 if (sym_is_choice_value(sym) && val == yes) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200563 item_make(" ");
564 item_set_tag(':');
565 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 } else {
567 switch (type) {
568 case S_BOOLEAN:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569 if (sym_is_changable(sym))
Sam Ravnborg2982de62006-07-27 22:10:27 +0200570 item_make("[%c]", val == no ? ' ' : '*');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 else
Sam Ravnborg2982de62006-07-27 22:10:27 +0200572 item_make("---");
573 item_set_tag('t');
574 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 break;
576 case S_TRISTATE:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 switch (val) {
578 case yes: ch = '*'; break;
579 case mod: ch = 'M'; break;
580 default: ch = ' '; break;
581 }
582 if (sym_is_changable(sym))
Sam Ravnborg2982de62006-07-27 22:10:27 +0200583 item_make("<%c>", ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 else
Sam Ravnborg2982de62006-07-27 22:10:27 +0200585 item_make("---");
586 item_set_tag('t');
587 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 break;
589 default:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200590 tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
591 item_make("(%s)", sym_get_string_value(sym));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 tmp = indent - tmp + 4;
593 if (tmp < 0)
594 tmp = 0;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200595 item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
596 (sym_has_value(sym) || !sym_is_changable(sym)) ?
597 "" : " (NEW)");
598 item_set_tag('s');
599 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 goto conf_childs;
601 }
602 }
Sam Ravnborg2982de62006-07-27 22:10:27 +0200603 item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
604 (sym_has_value(sym) || !sym_is_changable(sym)) ?
605 "" : " (NEW)");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 if (menu->prompt->type == P_MENU) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200607 item_add_str(" --->");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 return;
609 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 }
611
612conf_childs:
613 indent += doint;
614 for (child = menu->list; child; child = child->next)
615 build_conf(child);
616 indent -= doint;
617}
618
619static void conf(struct menu *menu)
620{
621 struct menu *submenu;
622 const char *prompt = menu_get_prompt(menu);
623 struct symbol *sym;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200624 struct menu *active_menu = NULL;
625 int res;
626 int s_scroll = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200629 item_reset();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 current_menu = menu;
631 build_conf(menu);
632 if (!child_count)
633 break;
634 if (menu == &rootmenu) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200635 item_make("--- ");
636 item_set_tag(':');
637 item_make(_(" Load an Alternate Configuration File"));
638 item_set_tag('L');
639 item_make(_(" Save an Alternate Configuration File"));
640 item_set_tag('S');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 }
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200642 dialog_clear();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200643 res = dialog_menu(prompt ? prompt : _("Main Menu"),
644 _(menu_instructions),
Sam Ravnborg2982de62006-07-27 22:10:27 +0200645 active_menu, &s_scroll);
Sam Ravnborgc8dc68a2006-07-29 22:48:57 +0200646 if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 break;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200648 if (!item_activate_selected())
649 continue;
650 if (!item_tag())
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 continue;
652
Sam Ravnborg2982de62006-07-27 22:10:27 +0200653 submenu = item_data();
654 active_menu = item_data();
Sam Ravnborgc8dc68a2006-07-29 22:48:57 +0200655 if (submenu)
656 sym = submenu->sym;
657 else
658 sym = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659
Sam Ravnborg2982de62006-07-27 22:10:27 +0200660 switch (res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200662 switch (item_tag()) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663 case 'm':
664 if (single_menu_mode)
665 submenu->data = (void *) (long) !submenu->data;
666 else
667 conf(submenu);
668 break;
669 case 't':
670 if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
671 conf_choice(submenu);
672 else if (submenu->prompt->type == P_MENU)
673 conf(submenu);
674 break;
675 case 's':
676 conf_string(submenu);
677 break;
678 case 'L':
679 conf_load();
680 break;
681 case 'S':
682 conf_save();
683 break;
684 }
685 break;
686 case 2:
687 if (sym)
688 show_help(submenu);
689 else
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700690 show_helptext("README", _(mconf_readme));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 break;
692 case 3:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200693 if (item_is_tag('t')) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 if (sym_set_tristate_value(sym, yes))
695 break;
696 if (sym_set_tristate_value(sym, mod))
697 show_textbox(NULL, setmod_text, 6, 74);
698 }
699 break;
700 case 4:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200701 if (item_is_tag('t'))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 sym_set_tristate_value(sym, no);
703 break;
704 case 5:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200705 if (item_is_tag('t'))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 sym_set_tristate_value(sym, mod);
707 break;
708 case 6:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200709 if (item_is_tag('t'))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 sym_toggle_tristate_value(sym);
Sam Ravnborg2982de62006-07-27 22:10:27 +0200711 else if (item_is_tag('m'))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 conf(submenu);
713 break;
714 case 7:
715 search_conf();
716 break;
717 }
718 }
719}
720
721static void show_textbox(const char *title, const char *text, int r, int c)
722{
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200723 dialog_clear();
Sam Ravnborgc8dc68a2006-07-29 22:48:57 +0200724 dialog_textbox(title, text, r, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725}
726
727static void show_helptext(const char *title, const char *text)
728{
729 show_textbox(title, text, 0, 0);
730}
731
732static void show_help(struct menu *menu)
733{
734 struct gstr help = str_new();
735 struct symbol *sym = menu->sym;
736
Sam Ravnborg03d29122007-07-21 00:00:36 +0200737 if (menu_has_help(menu))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 {
739 if (sym->name) {
740 str_printf(&help, "CONFIG_%s:\n\n", sym->name);
Sam Ravnborg03d29122007-07-21 00:00:36 +0200741 str_append(&help, _(menu_get_help(menu)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 str_append(&help, "\n");
743 }
744 } else {
745 str_append(&help, nohelp_text);
746 }
747 get_symbol_str(&help, sym);
748 show_helptext(menu_get_prompt(menu), str_get(&help));
749 str_free(&help);
750}
751
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752static void conf_choice(struct menu *menu)
753{
754 const char *prompt = menu_get_prompt(menu);
755 struct menu *child;
756 struct symbol *active;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757
758 active = sym_get_choice_value(menu->sym);
759 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200760 int res;
761 int selected;
762 item_reset();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763
764 current_menu = menu;
765 for (child = menu->list; child; child = child->next) {
766 if (!menu_is_visible(child))
767 continue;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200768 item_make("%s", menu_get_prompt(child));
769 item_set_data(child);
770 if (child->sym == active)
771 item_set_selected(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 if (child->sym == sym_get_choice_value(menu->sym))
Sam Ravnborg2982de62006-07-27 22:10:27 +0200773 item_set_tag('X');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 }
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200775 dialog_clear();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200776 res = dialog_checklist(prompt ? prompt : _("Main Menu"),
777 _(radiolist_instructions),
778 15, 70, 6);
779 selected = item_activate_selected();
780 switch (res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200782 if (selected) {
783 child = item_data();
784 sym_set_tristate_value(child->sym, yes);
785 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 return;
787 case 1:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200788 if (selected) {
789 child = item_data();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 show_help(child);
791 active = child->sym;
792 } else
793 show_help(menu);
794 break;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200795 case KEY_ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 return;
Sam Ravnborgc8dc68a2006-07-29 22:48:57 +0200797 case -ERRDISPLAYTOOSMALL:
798 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 }
800 }
801}
802
803static void conf_string(struct menu *menu)
804{
805 const char *prompt = menu_get_prompt(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806
807 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200808 int res;
809 char *heading;
810
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 switch (sym_get_type(menu->sym)) {
812 case S_INT:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200813 heading = _(inputbox_instructions_int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 break;
815 case S_HEX:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200816 heading = _(inputbox_instructions_hex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 break;
818 case S_STRING:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200819 heading = _(inputbox_instructions_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 break;
821 default:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200822 heading = "Internal mconf error!";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 }
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200824 dialog_clear();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200825 res = dialog_inputbox(prompt ? prompt : _("Main Menu"),
826 heading, 10, 75,
827 sym_get_string_value(menu->sym));
828 switch (res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200830 if (sym_set_string_value(menu->sym, dialog_input_result))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831 return;
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700832 show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 break;
834 case 1:
835 show_help(menu);
836 break;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200837 case KEY_ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 return;
839 }
840 }
841}
842
843static void conf_load(void)
844{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845
846 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200847 int res;
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200848 dialog_clear();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200849 res = dialog_inputbox(NULL, load_config_text,
850 11, 55, filename);
851 switch(res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200853 if (!dialog_input_result[0])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 return;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100855 if (!conf_read(dialog_input_result)) {
856 set_config_filename(dialog_input_result);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 return;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100858 }
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700859 show_textbox(NULL, _("File does not exist!"), 5, 38);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 break;
861 case 1:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700862 show_helptext(_("Load Alternate Configuration"), load_config_help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 break;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200864 case KEY_ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 return;
866 }
867 }
868}
869
870static void conf_save(void)
871{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200873 int res;
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200874 dialog_clear();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200875 res = dialog_inputbox(NULL, save_config_text,
876 11, 55, filename);
877 switch(res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200879 if (!dialog_input_result[0])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 return;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100881 if (!conf_write(dialog_input_result)) {
882 set_config_filename(dialog_input_result);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 return;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100884 }
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700885 show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 break;
887 case 1:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700888 show_helptext(_("Save Alternate Configuration"), save_config_help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 break;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200890 case KEY_ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 return;
892 }
893 }
894}
895
896static void conf_cleanup(void)
897{
898 tcsetattr(1, TCSAFLUSH, &ios_org);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899}
900
901int main(int ac, char **av)
902{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 char *mode;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200904 int res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700906 setlocale(LC_ALL, "");
907 bindtextdomain(PACKAGE, LOCALEDIR);
908 textdomain(PACKAGE);
909
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 conf_parse(av[1]);
911 conf_read(NULL);
912
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 mode = getenv("MENUCONFIG_MODE");
914 if (mode) {
915 if (!strcasecmp(mode, "single_menu"))
916 single_menu_mode = 1;
917 }
918
919 tcgetattr(1, &ios_org);
920 atexit(conf_cleanup);
921 init_wsize();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200922 reset_dialog();
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100923 init_dialog(NULL);
Sam Ravnborgd802b502007-04-01 22:29:38 +0200924 set_config_filename(conf_get_configname());
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200925 do {
926 conf(&rootmenu);
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200927 dialog_clear();
Karsten Wieseb3214292006-12-13 00:34:06 -0800928 if (conf_get_changed())
929 res = dialog_yesno(NULL,
930 _("Do you wish to save your "
931 "new kernel configuration?\n"
932 "<ESC><ESC> to continue."),
933 6, 60);
934 else
935 res = -1;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200936 } while (res == KEY_ESC);
Sam Ravnborg2982de62006-07-27 22:10:27 +0200937 end_dialog();
Karsten Wieseb3214292006-12-13 00:34:06 -0800938
939 switch (res) {
940 case 0:
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100941 if (conf_write(filename)) {
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700942 fprintf(stderr, _("\n\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 "Error during writing of the kernel configuration.\n"
944 "Your kernel configuration changes were NOT saved."
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700945 "\n\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 return 1;
947 }
Karsten Wieseb3214292006-12-13 00:34:06 -0800948 case -1:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700949 printf(_("\n\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 "*** End of Linux kernel configuration.\n"
951 "*** Execute 'make' to build the kernel or try 'make help'."
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700952 "\n\n"));
Karsten Wieseb3214292006-12-13 00:34:06 -0800953 break;
954 default:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700955 fprintf(stderr, _("\n\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 "Your kernel configuration changes were NOT saved."
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700957 "\n\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 }
959
960 return 0;
961}