blob: ac1e9dacde976e036306d9789512817c5cffb7ce [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
Vadim Bendebury (вб)da60fbb2009-12-20 00:29:49 -0800641 help.max_width = getmaxx(stdscr) - 10;
Cheng Renquan1d525e72009-07-12 16:11:45 +0800642 menu_get_ext_help(menu, &help);
643
EGRY Gabor413f0062008-01-11 23:50:37 +0100644 show_helptext(_(menu_get_prompt(menu)), str_get(&help));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 str_free(&help);
646}
647
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648static void conf_choice(struct menu *menu)
649{
EGRY Gabor413f0062008-01-11 23:50:37 +0100650 const char *prompt = _(menu_get_prompt(menu));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 struct menu *child;
652 struct symbol *active;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653
654 active = sym_get_choice_value(menu->sym);
655 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200656 int res;
657 int selected;
658 item_reset();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659
660 current_menu = menu;
661 for (child = menu->list; child; child = child->next) {
662 if (!menu_is_visible(child))
663 continue;
Peter Korsgaardaf6c1592009-02-15 22:15:16 +0100664 if (child->sym)
665 item_make("%s", _(menu_get_prompt(child)));
666 else {
667 item_make("*** %s ***", _(menu_get_prompt(child)));
668 item_set_tag(':');
669 }
Sam Ravnborg2982de62006-07-27 22:10:27 +0200670 item_set_data(child);
671 if (child->sym == active)
672 item_set_selected(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 if (child->sym == sym_get_choice_value(menu->sym))
Sam Ravnborg2982de62006-07-27 22:10:27 +0200674 item_set_tag('X');
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 }
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200676 dialog_clear();
EGRY Gabor413f0062008-01-11 23:50:37 +0100677 res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"),
Sam Ravnborg2982de62006-07-27 22:10:27 +0200678 _(radiolist_instructions),
679 15, 70, 6);
680 selected = item_activate_selected();
681 switch (res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200683 if (selected) {
684 child = item_data();
Peter Korsgaardaf6c1592009-02-15 22:15:16 +0100685 if (!child->sym)
686 break;
687
Sam Ravnborg2982de62006-07-27 22:10:27 +0200688 sym_set_tristate_value(child->sym, yes);
689 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 return;
691 case 1:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200692 if (selected) {
693 child = item_data();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 show_help(child);
695 active = child->sym;
696 } else
697 show_help(menu);
698 break;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200699 case KEY_ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 return;
Sam Ravnborgc8dc68a2006-07-29 22:48:57 +0200701 case -ERRDISPLAYTOOSMALL:
702 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 }
704 }
705}
706
707static void conf_string(struct menu *menu)
708{
709 const char *prompt = menu_get_prompt(menu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710
711 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200712 int res;
Sam Ravnborgc4143a82008-05-04 21:03:20 +0200713 const char *heading;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200714
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715 switch (sym_get_type(menu->sym)) {
716 case S_INT:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200717 heading = _(inputbox_instructions_int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 break;
719 case S_HEX:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200720 heading = _(inputbox_instructions_hex);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 break;
722 case S_STRING:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200723 heading = _(inputbox_instructions_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 break;
725 default:
EGRY Gabor413f0062008-01-11 23:50:37 +0100726 heading = _("Internal mconf error!");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 }
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200728 dialog_clear();
EGRY Gabor413f0062008-01-11 23:50:37 +0100729 res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"),
Sam Ravnborg2982de62006-07-27 22:10:27 +0200730 heading, 10, 75,
731 sym_get_string_value(menu->sym));
732 switch (res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200734 if (sym_set_string_value(menu->sym, dialog_input_result))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 return;
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700736 show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 break;
738 case 1:
739 show_help(menu);
740 break;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200741 case KEY_ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 return;
743 }
744 }
745}
746
747static void conf_load(void)
748{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749
750 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200751 int res;
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200752 dialog_clear();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200753 res = dialog_inputbox(NULL, load_config_text,
754 11, 55, filename);
755 switch(res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200757 if (!dialog_input_result[0])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 return;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100759 if (!conf_read(dialog_input_result)) {
760 set_config_filename(dialog_input_result);
Sam Ravnborg36ef8052008-02-02 20:44:09 +0100761 sym_set_change_count(1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 return;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100763 }
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700764 show_textbox(NULL, _("File does not exist!"), 5, 38);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 break;
766 case 1:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700767 show_helptext(_("Load Alternate Configuration"), load_config_help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 break;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200769 case KEY_ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 return;
771 }
772 }
773}
774
775static void conf_save(void)
776{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 while (1) {
Sam Ravnborg2982de62006-07-27 22:10:27 +0200778 int res;
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200779 dialog_clear();
Sam Ravnborg2982de62006-07-27 22:10:27 +0200780 res = dialog_inputbox(NULL, save_config_text,
781 11, 55, filename);
782 switch(res) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 case 0:
Sam Ravnborg2982de62006-07-27 22:10:27 +0200784 if (!dialog_input_result[0])
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785 return;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100786 if (!conf_write(dialog_input_result)) {
787 set_config_filename(dialog_input_result);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 return;
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100789 }
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700790 show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 break;
792 case 1:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700793 show_helptext(_("Save Alternate Configuration"), save_config_help);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 break;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200795 case KEY_ESC:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 return;
797 }
798 }
799}
800
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801int main(int ac, char **av)
802{
Ladislav Michl09af0912007-12-17 19:07:41 +0100803 int saved_x, saved_y;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 char *mode;
Sam Ravnborg2982de62006-07-27 22:10:27 +0200805 int res;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700807 setlocale(LC_ALL, "");
808 bindtextdomain(PACKAGE, LOCALEDIR);
809 textdomain(PACKAGE);
810
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 conf_parse(av[1]);
812 conf_read(NULL);
813
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 mode = getenv("MENUCONFIG_MODE");
815 if (mode) {
816 if (!strcasecmp(mode, "single_menu"))
817 single_menu_mode = 1;
818 }
819
Arnaud Lacombed0e1e092009-07-06 00:07:28 -0400820 initscr();
821
Ladislav Michl09af0912007-12-17 19:07:41 +0100822 getyx(stdscr, saved_y, saved_x);
823 if (init_dialog(NULL)) {
824 fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
825 fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
826 return 1;
827 }
828
Sam Ravnborgd802b502007-04-01 22:29:38 +0200829 set_config_filename(conf_get_configname());
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200830 do {
831 conf(&rootmenu);
Sam Ravnborge94c5bd2006-09-25 17:35:43 +0200832 dialog_clear();
Karsten Wieseb3214292006-12-13 00:34:06 -0800833 if (conf_get_changed())
834 res = dialog_yesno(NULL,
835 _("Do you wish to save your "
836 "new kernel configuration?\n"
837 "<ESC><ESC> to continue."),
838 6, 60);
839 else
840 res = -1;
Sam Ravnborgf3cbcdc2006-07-28 23:57:48 +0200841 } while (res == KEY_ESC);
Ladislav Michl09af0912007-12-17 19:07:41 +0100842 end_dialog(saved_x, saved_y);
Karsten Wieseb3214292006-12-13 00:34:06 -0800843
844 switch (res) {
845 case 0:
Sam Ravnborg95e30f92007-03-18 10:48:46 +0100846 if (conf_write(filename)) {
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700847 fprintf(stderr, _("\n\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 "Error during writing of the kernel configuration.\n"
849 "Your kernel configuration changes were NOT saved."
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700850 "\n\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 return 1;
852 }
Karsten Wieseb3214292006-12-13 00:34:06 -0800853 case -1:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700854 printf(_("\n\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 "*** End of Linux kernel configuration.\n"
856 "*** Execute 'make' to build the kernel or try 'make help'."
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700857 "\n\n"));
Karsten Wieseb3214292006-12-13 00:34:06 -0800858 break;
859 default:
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700860 fprintf(stderr, _("\n\n"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 "Your kernel configuration changes were NOT saved."
Arnaldo Carvalho de Melo3b9fa092005-05-05 15:09:46 -0700862 "\n\n"));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 }
864
865 return 0;
866}
Sam Ravnborgc4143a82008-05-04 21:03:20 +0200867