blob: 8413cf38ed277ea0061efb708c9db881ab4b6a12 [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
Linus Torvalds1da177e2005-04-16 15:20:36 -070011#include <ctype.h>
12#include <errno.h>
13#include <fcntl.h>
14#include <limits.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <stdarg.h>
16#include <stdlib.h>
17#include <string.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include <unistd.h>
Jean-Christophe Dubois442ff702005-06-25 14:55:43 -070019#include <locale.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070020
21#define LKC_DIRECT_LINK
22#include "lkc.h"
Sam Ravnborg2982de62006-07-27 22:10:27 +020023#include "lxdialog/dialog.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -070025static const char mconf_readme[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -070026"Overview\n"
27"--------\n"
28"Some kernel features may be built directly into the kernel.\n"
29"Some may be made into loadable runtime modules. Some features\n"
30"may be completely removed altogether. There are also certain\n"
31"kernel parameters which are not really features, but must be\n"
32"entered in as decimal or hexadecimal numbers or possibly text.\n"
33"\n"
Matej Laitlb5d609d2007-10-02 13:46:50 -070034"Menu items beginning with following braces represent features that\n"
35" [ ] can be built in or removed\n"
36" < > can be built in, modularized or removed\n"
37" { } can be built in or modularized (selected by other feature)\n"
38" - - are selected by other feature,\n"
39"while *, M or whitespace inside braces means to build in, build as\n"
40"a module or to exclude the feature respectively.\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -070041"\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."),
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700202load_config_text[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 "Enter the name of the configuration file you wish to load. "
204 "Accept the name shown to restore the configuration you "
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700205 "last retrieved. Leave blank to abort."),
206load_config_help[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207 "\n"
208 "For various reasons, one may wish to keep several different kernel\n"
209 "configurations available on a single machine.\n"
210 "\n"
211 "If you have saved a previous configuration in a file other than the\n"
212 "kernel's default, entering the name of the file here will allow you\n"
213 "to modify that configuration.\n"
214 "\n"
215 "If you are uncertain, then you have probably never used alternate\n"
André Goddard Rosaaf901ca2009-11-14 13:09:05 -0200216 "configuration files. You should therefore leave this blank to abort.\n"),
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700217save_config_text[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 "Enter a filename to which this configuration should be saved "
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700219 "as an alternate. Leave blank to abort."),
220save_config_help[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 "\n"
222 "For various reasons, one may wish to keep different kernel\n"
223 "configurations available on a single machine.\n"
224 "\n"
225 "Entering a file name here will allow you to later retrieve, modify\n"
226 "and use the current configuration as an alternate to whatever\n"
227 "configuration options you have selected at that time.\n"
228 "\n"
229 "If you are uncertain what all this means then you should probably\n"
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700230 "leave this blank.\n"),
231search_help[] = N_(
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 "\n"
233 "Search for CONFIG_ symbols and display their relations.\n"
Randy Dunlap503af332005-10-30 15:02:15 -0800234 "Regular expressions are allowed.\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 "Example: search for \"^FOO\"\n"
236 "Result:\n"
237 "-----------------------------------------------------------------\n"
238 "Symbol: FOO [=m]\n"
239 "Prompt: Foo bus is used to drive the bar HW\n"
240 "Defined at drivers/pci/Kconfig:47\n"
241 "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
242 "Location:\n"
243 " -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
244 " -> PCI support (PCI [=y])\n"
245 " -> PCI access mode (<choice> [=y])\n"
246 "Selects: LIBCRC32\n"
247 "Selected by: BAR\n"
248 "-----------------------------------------------------------------\n"
249 "o The line 'Prompt:' shows the text used in the menu structure for\n"
250 " this CONFIG_ symbol\n"
251 "o The 'Defined at' line tell at what file / line number the symbol\n"
252 " is defined\n"
253 "o The 'Depends on:' line tell what symbols needs to be defined for\n"
254 " this symbol to be visible in the menu (selectable)\n"
255 "o The 'Location:' lines tell where in the menu structure this symbol\n"
256 " is located\n"
257 " A location followed by a [=y] indicate that this is a selectable\n"
258 " menu item - and current value is displayed inside brackets.\n"
259 "o The 'Selects:' line tell what symbol will be automatically\n"
260 " selected if this symbol is selected (y or m)\n"
261 "o The 'Selected by' line tell what symbol has selected this symbol\n"
262 "\n"
263 "Only relevant lines are shown.\n"
264 "\n\n"
265 "Search examples:\n"
266 "Examples: USB => find all CONFIG_ symbols containing USB\n"
267 " ^USB => find all CONFIG_ symbols starting with USB\n"
268 " USB$ => find all CONFIG_ symbols ending with USB\n"
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700269 "\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271static int indent;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272static struct menu *current_menu;
273static int child_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274static int single_menu_mode;
275
276static void conf(struct menu *menu);
277static void conf_choice(struct menu *menu);
278static void conf_string(struct menu *menu);
279static void conf_load(void);
280static void conf_save(void);
281static void show_textbox(const char *title, const char *text, int r, int c);
282static void show_helptext(const char *title, const char *text);
283static void show_help(struct menu *menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285static struct gstr get_relations_str(struct symbol **sym_arr)
286{
287 struct symbol *sym;
288 struct gstr res = str_new();
289 int i;
290
291 for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
292 get_symbol_str(&res, sym);
293 if (!i)
EGRY Gabor413f0062008-01-11 23:50:37 +0100294 str_append(&res, _("No matches found.\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 return res;
296}
297
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100298static char filename[PATH_MAX+1];
299static void set_config_filename(const char *config_filename)
300{
301 static char menu_backtitle[PATH_MAX+128];
302 int size;
303 struct symbol *sym;
304
305 sym = sym_lookup("KERNELVERSION", 0);
306 sym_calc_value(sym);
307 size = snprintf(menu_backtitle, sizeof(menu_backtitle),
308 _("%s - Linux Kernel v%s Configuration"),
309 config_filename, sym_get_string_value(sym));
310 if (size >= sizeof(menu_backtitle))
311 menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
312 set_dialog_backtitle(menu_backtitle);
313
314 size = snprintf(filename, sizeof(filename), "%s", config_filename);
315 if (size >= sizeof(filename))
316 filename[sizeof(filename)-1] = '\0';
317}
318
319
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320static void search_conf(void)
321{
322 struct symbol **sym_arr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 struct gstr res;
Bernhard Walle0584f9f2007-07-09 11:43:56 -0700324 char *dialog_input;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200325 int dres;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326again:
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200327 dialog_clear();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200328 dres = dialog_inputbox(_("Search Configuration Parameter"),
Bernhard Walle0584f9f2007-07-09 11:43:56 -0700329 _("Enter CONFIG_ (sub)string to search for "
330 "(with or without \"CONFIG\")"),
Sam Ravnborg2982de62006-07-27 22:10:27 +0200331 10, 75, "");
332 switch (dres) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 case 0:
334 break;
335 case 1:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700336 show_helptext(_("Search Configuration"), search_help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 goto again;
338 default:
339 return;
340 }
341
Bernhard Walle0584f9f2007-07-09 11:43:56 -0700342 /* strip CONFIG_ if necessary */
343 dialog_input = dialog_input_result;
344 if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0)
345 dialog_input += 7;
346
347 sym_arr = sym_re_search(dialog_input);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 res = get_relations_str(sym_arr);
349 free(sym_arr);
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700350 show_textbox(_("Search Results"), str_get(&res), 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 str_free(&res);
352}
353
354static void build_conf(struct menu *menu)
355{
356 struct symbol *sym;
357 struct property *prop;
358 struct menu *child;
359 int type, tmp, doint = 2;
360 tristate val;
361 char ch;
362
363 if (!menu_is_visible(menu))
364 return;
365
366 sym = menu->sym;
367 prop = menu->prompt;
368 if (!sym) {
369 if (prop && menu != current_menu) {
370 const char *prompt = menu_get_prompt(menu);
371 switch (prop->type) {
372 case P_MENU:
373 child_count++;
EGRY Gabor413f0062008-01-11 23:50:37 +0100374 prompt = _(prompt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 if (single_menu_mode) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200376 item_make("%s%*c%s",
377 menu->data ? "-->" : "++>",
378 indent + 1, ' ', prompt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 } else
Sam Ravnborg2982de62006-07-27 22:10:27 +0200380 item_make(" %*c%s --->", indent + 1, ' ', prompt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381
Sam Ravnborg2982de62006-07-27 22:10:27 +0200382 item_set_tag('m');
383 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384 if (single_menu_mode && menu->data)
385 goto conf_childs;
386 return;
Sam Ravnborg48874072007-09-18 21:12:26 +0200387 case P_COMMENT:
388 if (prompt) {
389 child_count++;
EGRY Gabor413f0062008-01-11 23:50:37 +0100390 item_make(" %*c*** %s ***", indent + 1, ' ', _(prompt));
Sam Ravnborg48874072007-09-18 21:12:26 +0200391 item_set_tag(':');
392 item_set_data(menu);
393 }
394 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395 default:
396 if (prompt) {
397 child_count++;
EGRY Gabor413f0062008-01-11 23:50:37 +0100398 item_make("---%*c%s", indent + 1, ' ', _(prompt));
Sam Ravnborg2982de62006-07-27 22:10:27 +0200399 item_set_tag(':');
400 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 }
402 }
403 } else
404 doint = 0;
405 goto conf_childs;
406 }
407
408 type = sym_get_type(sym);
409 if (sym_is_choice(sym)) {
410 struct symbol *def_sym = sym_get_choice_value(sym);
411 struct menu *def_menu = NULL;
412
413 child_count++;
414 for (child = menu->list; child; child = child->next) {
415 if (menu_is_visible(child) && child->sym == def_sym)
416 def_menu = child;
417 }
418
419 val = sym_get_tristate_value(sym);
420 if (sym_is_changable(sym)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 switch (type) {
422 case S_BOOLEAN:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200423 item_make("[%c]", val == no ? ' ' : '*');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 break;
425 case S_TRISTATE:
426 switch (val) {
427 case yes: ch = '*'; break;
428 case mod: ch = 'M'; break;
429 default: ch = ' '; break;
430 }
Sam Ravnborg2982de62006-07-27 22:10:27 +0200431 item_make("<%c>", ch);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 break;
433 }
Sam Ravnborg2982de62006-07-27 22:10:27 +0200434 item_set_tag('t');
435 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 } else {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200437 item_make(" ");
438 item_set_tag(def_menu ? 't' : ':');
439 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 }
441
EGRY Gabor413f0062008-01-11 23:50:37 +0100442 item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 if (val == yes) {
444 if (def_menu) {
EGRY Gabor413f0062008-01-11 23:50:37 +0100445 item_add_str(" (%s)", _(menu_get_prompt(def_menu)));
Sam Ravnborg2982de62006-07-27 22:10:27 +0200446 item_add_str(" --->");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 if (def_menu->list) {
448 indent += 2;
449 build_conf(def_menu);
450 indent -= 2;
451 }
Sam Ravnborg2982de62006-07-27 22:10:27 +0200452 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 return;
454 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 } else {
456 if (menu == current_menu) {
EGRY Gabor413f0062008-01-11 23:50:37 +0100457 item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
Sam Ravnborg2982de62006-07-27 22:10:27 +0200458 item_set_tag(':');
459 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 goto conf_childs;
461 }
462 child_count++;
463 val = sym_get_tristate_value(sym);
464 if (sym_is_choice_value(sym) && val == yes) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200465 item_make(" ");
466 item_set_tag(':');
467 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 } else {
469 switch (type) {
470 case S_BOOLEAN:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471 if (sym_is_changable(sym))
Sam Ravnborg2982de62006-07-27 22:10:27 +0200472 item_make("[%c]", val == no ? ' ' : '*');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 else
Matej Laitlb5d609d2007-10-02 13:46:50 -0700474 item_make("-%c-", val == no ? ' ' : '*');
Sam Ravnborg2982de62006-07-27 22:10:27 +0200475 item_set_tag('t');
476 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 break;
478 case S_TRISTATE:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 switch (val) {
480 case yes: ch = '*'; break;
481 case mod: ch = 'M'; break;
482 default: ch = ' '; break;
483 }
Matej Laitlb5d609d2007-10-02 13:46:50 -0700484 if (sym_is_changable(sym)) {
485 if (sym->rev_dep.tri == mod)
486 item_make("{%c}", ch);
487 else
488 item_make("<%c>", ch);
489 } else
490 item_make("-%c-", ch);
Sam Ravnborg2982de62006-07-27 22:10:27 +0200491 item_set_tag('t');
492 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 break;
494 default:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200495 tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
496 item_make("(%s)", sym_get_string_value(sym));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 tmp = indent - tmp + 4;
498 if (tmp < 0)
499 tmp = 0;
EGRY Gabor413f0062008-01-11 23:50:37 +0100500 item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)),
Sam Ravnborg2982de62006-07-27 22:10:27 +0200501 (sym_has_value(sym) || !sym_is_changable(sym)) ?
EGRY Gabor413f0062008-01-11 23:50:37 +0100502 "" : _(" (NEW)"));
Sam Ravnborg2982de62006-07-27 22:10:27 +0200503 item_set_tag('s');
504 item_set_data(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 goto conf_childs;
506 }
507 }
EGRY Gabor413f0062008-01-11 23:50:37 +0100508 item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)),
Sam Ravnborg2982de62006-07-27 22:10:27 +0200509 (sym_has_value(sym) || !sym_is_changable(sym)) ?
EGRY Gabor413f0062008-01-11 23:50:37 +0100510 "" : _(" (NEW)"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 if (menu->prompt->type == P_MENU) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200512 item_add_str(" --->");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 return;
514 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 }
516
517conf_childs:
518 indent += doint;
519 for (child = menu->list; child; child = child->next)
520 build_conf(child);
521 indent -= doint;
522}
523
524static void conf(struct menu *menu)
525{
526 struct menu *submenu;
527 const char *prompt = menu_get_prompt(menu);
528 struct symbol *sym;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200529 struct menu *active_menu = NULL;
530 int res;
531 int s_scroll = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200534 item_reset();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 current_menu = menu;
536 build_conf(menu);
537 if (!child_count)
538 break;
539 if (menu == &rootmenu) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200540 item_make("--- ");
541 item_set_tag(':');
542 item_make(_(" Load an Alternate Configuration File"));
543 item_set_tag('L');
544 item_make(_(" Save an Alternate Configuration File"));
545 item_set_tag('S');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 }
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200547 dialog_clear();
EGRY Gabor413f0062008-01-11 23:50:37 +0100548 res = dialog_menu(prompt ? _(prompt) : _("Main Menu"),
Sam Ravnborg2982de62006-07-27 22:10:27 +0200549 _(menu_instructions),
Sam Ravnborg2982de62006-07-27 22:10:27 +0200550 active_menu, &s_scroll);
Sam Ravnborgc8dc68a2006-07-29 22:48:57 +0200551 if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 break;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200553 if (!item_activate_selected())
554 continue;
555 if (!item_tag())
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 continue;
557
Sam Ravnborg2982de62006-07-27 22:10:27 +0200558 submenu = item_data();
559 active_menu = item_data();
Sam Ravnborgc8dc68a2006-07-29 22:48:57 +0200560 if (submenu)
561 sym = submenu->sym;
562 else
563 sym = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564
Sam Ravnborg2982de62006-07-27 22:10:27 +0200565 switch (res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200567 switch (item_tag()) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 case 'm':
569 if (single_menu_mode)
570 submenu->data = (void *) (long) !submenu->data;
571 else
572 conf(submenu);
573 break;
574 case 't':
575 if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
576 conf_choice(submenu);
577 else if (submenu->prompt->type == P_MENU)
578 conf(submenu);
579 break;
580 case 's':
581 conf_string(submenu);
582 break;
583 case 'L':
584 conf_load();
585 break;
586 case 'S':
587 conf_save();
588 break;
589 }
590 break;
591 case 2:
592 if (sym)
593 show_help(submenu);
594 else
EGRY Gabor413f0062008-01-11 23:50:37 +0100595 show_helptext(_("README"), _(mconf_readme));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 break;
597 case 3:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200598 if (item_is_tag('t')) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 if (sym_set_tristate_value(sym, yes))
600 break;
601 if (sym_set_tristate_value(sym, mod))
602 show_textbox(NULL, setmod_text, 6, 74);
603 }
604 break;
605 case 4:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200606 if (item_is_tag('t'))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 sym_set_tristate_value(sym, no);
608 break;
609 case 5:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200610 if (item_is_tag('t'))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 sym_set_tristate_value(sym, mod);
612 break;
613 case 6:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200614 if (item_is_tag('t'))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 sym_toggle_tristate_value(sym);
Sam Ravnborg2982de62006-07-27 22:10:27 +0200616 else if (item_is_tag('m'))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 conf(submenu);
618 break;
619 case 7:
620 search_conf();
621 break;
622 }
623 }
624}
625
626static void show_textbox(const char *title, const char *text, int r, int c)
627{
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200628 dialog_clear();
Sam Ravnborgc8dc68a2006-07-29 22:48:57 +0200629 dialog_textbox(title, text, r, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630}
631
632static void show_helptext(const char *title, const char *text)
633{
634 show_textbox(title, text, 0, 0);
635}
636
637static void show_help(struct menu *menu)
638{
639 struct gstr help = str_new();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
Cheng Renquan1d525e72009-07-12 16:11:45 +0800641 menu_get_ext_help(menu, &help);
642
EGRY Gabor413f0062008-01-11 23:50:37 +0100643 show_helptext(_(menu_get_prompt(menu)), str_get(&help));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 str_free(&help);
645}
646
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647static void conf_choice(struct menu *menu)
648{
EGRY Gabor413f0062008-01-11 23:50:37 +0100649 const char *prompt = _(menu_get_prompt(menu));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 struct menu *child;
651 struct symbol *active;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652
653 active = sym_get_choice_value(menu->sym);
654 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200655 int res;
656 int selected;
657 item_reset();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658
659 current_menu = menu;
660 for (child = menu->list; child; child = child->next) {
661 if (!menu_is_visible(child))
662 continue;
Peter Korsgaardaf6c1592009-02-15 22:15:16 +0100663 if (child->sym)
664 item_make("%s", _(menu_get_prompt(child)));
665 else {
666 item_make("*** %s ***", _(menu_get_prompt(child)));
667 item_set_tag(':');
668 }
Sam Ravnborg2982de62006-07-27 22:10:27 +0200669 item_set_data(child);
670 if (child->sym == active)
671 item_set_selected(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 if (child->sym == sym_get_choice_value(menu->sym))
Sam Ravnborg2982de62006-07-27 22:10:27 +0200673 item_set_tag('X');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674 }
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200675 dialog_clear();
EGRY Gabor413f0062008-01-11 23:50:37 +0100676 res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"),
Sam Ravnborg2982de62006-07-27 22:10:27 +0200677 _(radiolist_instructions),
678 15, 70, 6);
679 selected = item_activate_selected();
680 switch (res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200682 if (selected) {
683 child = item_data();
Peter Korsgaardaf6c1592009-02-15 22:15:16 +0100684 if (!child->sym)
685 break;
686
Sam Ravnborg2982de62006-07-27 22:10:27 +0200687 sym_set_tristate_value(child->sym, yes);
688 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 return;
690 case 1:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200691 if (selected) {
692 child = item_data();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 show_help(child);
694 active = child->sym;
695 } else
696 show_help(menu);
697 break;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200698 case KEY_ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 return;
Sam Ravnborgc8dc68a2006-07-29 22:48:57 +0200700 case -ERRDISPLAYTOOSMALL:
701 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 }
703 }
704}
705
706static void conf_string(struct menu *menu)
707{
708 const char *prompt = menu_get_prompt(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
710 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200711 int res;
Sam Ravnborgc4143a82008-05-04 21:03:20 +0200712 const char *heading;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200713
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 switch (sym_get_type(menu->sym)) {
715 case S_INT:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200716 heading = _(inputbox_instructions_int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 break;
718 case S_HEX:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200719 heading = _(inputbox_instructions_hex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 break;
721 case S_STRING:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200722 heading = _(inputbox_instructions_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 break;
724 default:
EGRY Gabor413f0062008-01-11 23:50:37 +0100725 heading = _("Internal mconf error!");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 }
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200727 dialog_clear();
EGRY Gabor413f0062008-01-11 23:50:37 +0100728 res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"),
Sam Ravnborg2982de62006-07-27 22:10:27 +0200729 heading, 10, 75,
730 sym_get_string_value(menu->sym));
731 switch (res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200733 if (sym_set_string_value(menu->sym, dialog_input_result))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 return;
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700735 show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 break;
737 case 1:
738 show_help(menu);
739 break;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200740 case KEY_ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 return;
742 }
743 }
744}
745
746static void conf_load(void)
747{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748
749 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200750 int res;
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200751 dialog_clear();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200752 res = dialog_inputbox(NULL, load_config_text,
753 11, 55, filename);
754 switch(res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200756 if (!dialog_input_result[0])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 return;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100758 if (!conf_read(dialog_input_result)) {
759 set_config_filename(dialog_input_result);
Sam Ravnborg36ef8052008-02-02 20:44:09 +0100760 sym_set_change_count(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 return;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100762 }
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700763 show_textbox(NULL, _("File does not exist!"), 5, 38);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 break;
765 case 1:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700766 show_helptext(_("Load Alternate Configuration"), load_config_help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 break;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200768 case KEY_ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 return;
770 }
771 }
772}
773
774static void conf_save(void)
775{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200777 int res;
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200778 dialog_clear();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200779 res = dialog_inputbox(NULL, save_config_text,
780 11, 55, filename);
781 switch(res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200783 if (!dialog_input_result[0])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 return;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100785 if (!conf_write(dialog_input_result)) {
786 set_config_filename(dialog_input_result);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 return;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100788 }
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700789 show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 break;
791 case 1:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700792 show_helptext(_("Save Alternate Configuration"), save_config_help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 break;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200794 case KEY_ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 return;
796 }
797 }
798}
799
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800int main(int ac, char **av)
801{
Ladislav Michl09af0912007-12-17 19:07:41 +0100802 int saved_x, saved_y;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 char *mode;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200804 int res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700806 setlocale(LC_ALL, "");
807 bindtextdomain(PACKAGE, LOCALEDIR);
808 textdomain(PACKAGE);
809
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 conf_parse(av[1]);
811 conf_read(NULL);
812
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 mode = getenv("MENUCONFIG_MODE");
814 if (mode) {
815 if (!strcasecmp(mode, "single_menu"))
816 single_menu_mode = 1;
817 }
818
Arnaud Lacombed0e1e092009-07-06 00:07:28 -0400819 initscr();
820
Ladislav Michl09af0912007-12-17 19:07:41 +0100821 getyx(stdscr, saved_y, saved_x);
822 if (init_dialog(NULL)) {
823 fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
824 fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
825 return 1;
826 }
827
Sam Ravnborgd802b502007-04-01 22:29:38 +0200828 set_config_filename(conf_get_configname());
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200829 do {
830 conf(&rootmenu);
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200831 dialog_clear();
Karsten Wieseb3214292006-12-13 00:34:06 -0800832 if (conf_get_changed())
833 res = dialog_yesno(NULL,
834 _("Do you wish to save your "
835 "new kernel configuration?\n"
836 "<ESC><ESC> to continue."),
837 6, 60);
838 else
839 res = -1;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200840 } while (res == KEY_ESC);
Ladislav Michl09af0912007-12-17 19:07:41 +0100841 end_dialog(saved_x, saved_y);
Karsten Wieseb3214292006-12-13 00:34:06 -0800842
843 switch (res) {
844 case 0:
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100845 if (conf_write(filename)) {
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700846 fprintf(stderr, _("\n\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 "Error during writing of the kernel configuration.\n"
848 "Your kernel configuration changes were NOT saved."
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700849 "\n\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 return 1;
851 }
Karsten Wieseb3214292006-12-13 00:34:06 -0800852 case -1:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700853 printf(_("\n\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 "*** End of Linux kernel configuration.\n"
855 "*** Execute 'make' to build the kernel or try 'make help'."
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700856 "\n\n"));
Karsten Wieseb3214292006-12-13 00:34:06 -0800857 break;
858 default:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700859 fprintf(stderr, _("\n\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 "Your kernel configuration changes were NOT saved."
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700861 "\n\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 }
863
864 return 0;
865}
Sam Ravnborgc4143a82008-05-04 21:03:20 +0200866