]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - scripts/kconfig/mconf.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
[mirror_ubuntu-jammy-kernel.git] / scripts / kconfig / mconf.c
CommitLineData
0c874100 1// SPDX-License-Identifier: GPL-2.0
1da177e4
LT
2/*
3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
1da177e4
LT
4 *
5 * Introduced single menu mode (show all sub-menus in one large tree).
6 * 2002-11-06 Petr Baudis <pasky@ucw.cz>
3b9fa093
ACM
7 *
8 * i18n, 2005, Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1da177e4
LT
9 */
10
1da177e4
LT
11#include <ctype.h>
12#include <errno.h>
13#include <fcntl.h>
14#include <limits.h>
1da177e4
LT
15#include <stdarg.h>
16#include <stdlib.h>
17#include <string.h>
ba82f52e 18#include <strings.h>
564899f9 19#include <signal.h>
1da177e4
LT
20#include <unistd.h>
21
1da177e4 22#include "lkc.h"
2982de69 23#include "lxdialog/dialog.h"
1da177e4 24
40661621
MY
25#define JUMP_NB 9
26
694c49a7 27static const char mconf_readme[] =
1da177e4
LT
28"Overview\n"
29"--------\n"
8d9dfe82 30"This interface lets you select features and parameters for the build.\n"
652cf982
AL
31"Features can either be built-in, modularized, or ignored. Parameters\n"
32"must be entered in as decimal or hexadecimal numbers or text.\n"
1da177e4 33"\n"
b5d609db
ML
34"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"
1da177e4
LT
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"
8d9dfe82
MW
44"<N> to remove it. You may also press the <Space Bar> to cycle\n"
45"through the available options (i.e. Y->N->M->Y).\n"
1da177e4
LT
46"\n"
47"Some additional keyboard hints:\n"
48"\n"
49"Menus\n"
50"----------\n"
8d9dfe82
MW
51"o Use the Up/Down arrow keys (cursor keys) to highlight the item you\n"
52" wish to change or the submenu you wish to select and press <Enter>.\n"
1278ebdb 53" Submenus are designated by \"--->\", empty ones by \"----\".\n"
1da177e4
LT
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"
8d9dfe82 70" <Exit>, <Help>, <Save>, and <Load>.\n"
1da177e4
LT
71"\n"
72"o To get help with an item, use the cursor keys to highlight <Help>\n"
22c7eca6 73" and press <ENTER>.\n"
1da177e4
LT
74"\n"
75" Shortcut: Press <H> or <?>.\n"
76"\n"
f9447c49 77"o To toggle the display of hidden options, press <Z>.\n"
22c7eca6 78"\n"
1da177e4
LT
79"\n"
80"Radiolists (Choice lists)\n"
81"-----------\n"
82"o Use the cursor keys to select the option you wish to set and press\n"
83" <S> or the <SPACE BAR>.\n"
84"\n"
85" Shortcut: Press the first letter of the option you wish to set then\n"
86" press <S> or <SPACE BAR>.\n"
87"\n"
88"o To see available help for the item, use the cursor keys to highlight\n"
89" <Help> and Press <ENTER>.\n"
90"\n"
91" Shortcut: Press <H> or <?>.\n"
92"\n"
93" Also, the <TAB> and cursor keys will cycle between <Select> and\n"
94" <Help>\n"
95"\n"
96"\n"
97"Data Entry\n"
98"-----------\n"
99"o Enter the requested information and press <ENTER>\n"
100" If you are entering hexadecimal values, it is not necessary to\n"
101" add the '0x' prefix to the entry.\n"
102"\n"
103"o For help, use the <TAB> or cursor keys to highlight the help option\n"
104" and press <ENTER>. You can try <TAB><H> as well.\n"
105"\n"
106"\n"
107"Text Box (Help Window)\n"
108"--------\n"
109"o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
8d9dfe82 110" keys h,j,k,l function here as do <u>, <d>, <SPACE BAR> and <B> for\n"
9d4792c9 111" those who are familiar with less and lynx.\n"
1da177e4 112"\n"
9d4792c9 113"o Press <E>, <X>, <q>, <Enter> or <Esc><Esc> to exit.\n"
1da177e4
LT
114"\n"
115"\n"
116"Alternate Configuration Files\n"
117"-----------------------------\n"
118"Menuconfig supports the use of alternate configuration files for\n"
119"those who, for various reasons, find it necessary to switch\n"
652cf982 120"between different configurations.\n"
1da177e4 121"\n"
8d9dfe82
MW
122"The <Save> button will let you save the current configuration to\n"
123"a file of your choosing. Use the <Load> button to load a previously\n"
124"saved alternate configuration.\n"
1da177e4 125"\n"
8d9dfe82
MW
126"Even if you don't use alternate configuration files, but you find\n"
127"during a Menuconfig session that you have completely messed up your\n"
128"settings, you may use the <Load> button to restore your previously\n"
129"saved settings from \".config\" without restarting Menuconfig.\n"
1da177e4
LT
130"\n"
131"Other information\n"
132"-----------------\n"
8d9dfe82
MW
133"If you use Menuconfig in an XTERM window, make sure you have your\n"
134"$TERM variable set to point to an xterm definition which supports\n"
135"color. Otherwise, Menuconfig will look rather bad. Menuconfig will\n"
136"not display correctly in an RXVT window because rxvt displays only one\n"
1da177e4
LT
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"
8d9dfe82
MW
151"If you prefer to have all of the options listed in a single menu,\n"
152"rather than the default multimenu hierarchy, run the menuconfig with\n"
652cf982 153"MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
1da177e4
LT
154"\n"
155"make MENUCONFIG_MODE=single_menu menuconfig\n"
156"\n"
157"<Enter> will then unroll the appropriate category, or enfold it if it\n"
158"is already unrolled.\n"
159"\n"
160"Note that this mode can eventually be a little more CPU expensive\n"
161"(especially with a larger number of unrolled categories) than the\n"
45897213
SR
162"default mode.\n"
163"\n"
164"Different color themes available\n"
165"--------------------------------\n"
166"It is possible to select different color themes using the variable\n"
167"MENUCONFIG_COLOR. To select a theme use:\n"
168"\n"
169"make MENUCONFIG_COLOR=<theme> menuconfig\n"
170"\n"
171"Available themes are\n"
172" mono => selects colors suitable for monochrome displays\n"
173" blackbg => selects a color scheme with black background\n"
350b5b76 174" classic => theme with blue background. The classic look\n"
8d9dfe82 175" bluetitle => an LCD friendly version of classic. (default)\n"
694c49a7
SR
176"\n",
177menu_instructions[] =
1da177e4 178 "Arrow keys navigate the menu. "
1278ebdb 179 "<Enter> selects submenus ---> (or empty submenus ----). "
1da177e4
LT
180 "Highlighted letters are hotkeys. "
181 "Pressing <Y> includes, <N> excludes, <M> modularizes features. "
182 "Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
694c49a7
SR
183 "Legend: [*] built-in [ ] excluded <M> module < > module capable",
184radiolist_instructions[] =
1da177e4
LT
185 "Use the arrow keys to navigate this window or "
186 "press the hotkey of the item you wish to select "
187 "followed by the <SPACE BAR>. "
694c49a7
SR
188 "Press <?> for additional information about this option.",
189inputbox_instructions_int[] =
1da177e4
LT
190 "Please enter a decimal value. "
191 "Fractions will not be accepted. "
694c49a7
SR
192 "Use the <TAB> key to move from the input field to the buttons below it.",
193inputbox_instructions_hex[] =
1da177e4 194 "Please enter a hexadecimal value. "
694c49a7
SR
195 "Use the <TAB> key to move from the input field to the buttons below it.",
196inputbox_instructions_string[] =
1da177e4 197 "Please enter a string value. "
694c49a7
SR
198 "Use the <TAB> key to move from the input field to the buttons below it.",
199setmod_text[] =
1da177e4 200 "This feature depends on another which has been configured as a module.\n"
694c49a7
SR
201 "As a result, this feature will be built as a module.",
202load_config_text[] =
1da177e4
LT
203 "Enter the name of the configuration file you wish to load. "
204 "Accept the name shown to restore the configuration you "
694c49a7
SR
205 "last retrieved. Leave blank to abort.",
206load_config_help[] =
1da177e4 207 "\n"
652cf982 208 "For various reasons, one may wish to keep several different\n"
1da177e4
LT
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"
652cf982
AL
212 "default one, entering its name here will allow you to modify that\n"
213 "configuration.\n"
1da177e4
LT
214 "\n"
215 "If you are uncertain, then you have probably never used alternate\n"
694c49a7
SR
216 "configuration files. You should therefore leave this blank to abort.\n",
217save_config_text[] =
1da177e4 218 "Enter a filename to which this configuration should be saved "
694c49a7
SR
219 "as an alternate. Leave blank to abort.",
220save_config_help[] =
1da177e4 221 "\n"
652cf982
AL
222 "For various reasons, one may wish to keep different configurations\n"
223 "available on a single machine.\n"
1da177e4
LT
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"
694c49a7
SR
230 "leave this blank.\n",
231search_help[] =
1da177e4 232 "\n"
59dfa24d 233 "Search for symbols and display their relations.\n"
503af334 234 "Regular expressions are allowed.\n"
1da177e4
LT
235 "Example: search for \"^FOO\"\n"
236 "Result:\n"
237 "-----------------------------------------------------------------\n"
238 "Symbol: FOO [=m]\n"
5e609add 239 "Type : tristate\n"
1da177e4 240 "Prompt: Foo bus is used to drive the bar HW\n"
5e609add
BP
241 " Location:\n"
242 " -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
243 " -> PCI support (PCI [=y])\n"
244 "(1) -> PCI access mode (<choice> [=y])\n"
8d9dfe82
MW
245 " Defined at drivers/pci/Kconfig:47\n"
246 " Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
5e609add 247 " Selects: LIBCRC32\n"
8d9dfe82 248 " Selected by: BAR [=n]\n"
1da177e4 249 "-----------------------------------------------------------------\n"
5e609add 250 "o The line 'Type:' shows the type of the configuration option for\n"
b92d804a 251 " this symbol (bool, tristate, string, ...)\n"
1da177e4 252 "o The line 'Prompt:' shows the text used in the menu structure for\n"
59dfa24d 253 " this symbol\n"
8d9dfe82 254 "o The 'Defined at' line tells at what file / line number the symbol\n"
1da177e4 255 " is defined\n"
8d9dfe82 256 "o The 'Depends on:' line tells what symbols need to be defined for\n"
1da177e4 257 " this symbol to be visible in the menu (selectable)\n"
8d9dfe82 258 "o The 'Location:' lines tells where in the menu structure this symbol\n"
1da177e4 259 " is located\n"
5e609add
BP
260 " A location followed by a [=y] indicates that this is a\n"
261 " selectable menu item - and the current value is displayed inside\n"
262 " brackets.\n"
263 " Press the key in the (#) prefix to jump directly to that\n"
264 " location. You will be returned to the current search results\n"
265 " after exiting this new menu.\n"
8d9dfe82 266 "o The 'Selects:' line tells what symbols will be automatically\n"
1da177e4 267 " selected if this symbol is selected (y or m)\n"
8d9dfe82 268 "o The 'Selected by' line tells what symbol has selected this symbol\n"
1da177e4
LT
269 "\n"
270 "Only relevant lines are shown.\n"
271 "\n\n"
272 "Search examples:\n"
59dfa24d
AL
273 "Examples: USB => find all symbols containing USB\n"
274 " ^USB => find all symbols starting with USB\n"
275 " USB$ => find all symbols ending with USB\n"
694c49a7 276 "\n";
1da177e4 277
1da177e4 278static int indent;
1da177e4
LT
279static struct menu *current_menu;
280static int child_count;
1da177e4 281static int single_menu_mode;
22c7eca6 282static int show_all_options;
6364fd0c 283static int save_and_exit;
0a1f00a1 284static int silent;
1da177e4 285
5e609add 286static void conf(struct menu *menu, struct menu *active_menu);
1da177e4
LT
287static void conf_choice(struct menu *menu);
288static void conf_string(struct menu *menu);
289static void conf_load(void);
290static void conf_save(void);
95ac9b3b
BP
291static int show_textbox_ext(const char *title, char *text, int r, int c,
292 int *keys, int *vscroll, int *hscroll,
293 update_text_fn update_text, void *data);
1da177e4
LT
294static void show_textbox(const char *title, const char *text, int r, int c);
295static void show_helptext(const char *title, const char *text);
296static void show_help(struct menu *menu);
1da177e4 297
95e30f95
SR
298static char filename[PATH_MAX+1];
299static void set_config_filename(const char *config_filename)
300{
301 static char menu_backtitle[PATH_MAX+128];
95e30f95 302
68876c38
MY
303 snprintf(menu_backtitle, sizeof(menu_backtitle), "%s - %s",
304 config_filename, rootmenu.prompt->text);
95e30f95
SR
305 set_dialog_backtitle(menu_backtitle);
306
68876c38 307 snprintf(filename, sizeof(filename), "%s", config_filename);
95e30f95
SR
308}
309
9a69abf8
BP
310struct subtitle_part {
311 struct list_head entries;
312 const char *text;
313};
314static LIST_HEAD(trail);
315
316static struct subtitle_list *subtitles;
317static void set_subtitle(void)
318{
319 struct subtitle_part *sp;
320 struct subtitle_list *pos, *tmp;
321
322 for (pos = subtitles; pos != NULL; pos = tmp) {
323 tmp = pos->next;
324 free(pos);
325 }
326
327 subtitles = NULL;
328 list_for_each_entry(sp, &trail, entries) {
329 if (sp->text) {
330 if (pos) {
e4e458b4 331 pos->next = xcalloc(1, sizeof(*pos));
9a69abf8
BP
332 pos = pos->next;
333 } else {
e4e458b4 334 subtitles = pos = xcalloc(1, sizeof(*pos));
9a69abf8
BP
335 }
336 pos->text = sp->text;
337 }
338 }
339
340 set_dialog_subtitles(subtitles);
341}
342
343static void reset_subtitle(void)
344{
345 struct subtitle_list *pos, *tmp;
346
347 for (pos = subtitles; pos != NULL; pos = tmp) {
348 tmp = pos->next;
349 free(pos);
350 }
351 subtitles = NULL;
352 set_dialog_subtitles(subtitles);
353}
95e30f95 354
95ac9b3b 355struct search_data {
bad9955d 356 struct list_head *head;
95ac9b3b
BP
357 struct menu **targets;
358 int *keys;
359};
360
361static void update_text(char *buf, size_t start, size_t end, void *_data)
362{
363 struct search_data *data = _data;
364 struct jump_key *pos;
365 int k = 0;
366
bad9955d 367 list_for_each_entry(pos, data->head, entries) {
95ac9b3b
BP
368 if (pos->offset >= start && pos->offset < end) {
369 char header[4];
370
371 if (k < JUMP_NB) {
372 int key = '0' + (pos->index % JUMP_NB) + 1;
373
374 sprintf(header, "(%c)", key);
375 data->keys[k] = key;
376 data->targets[k] = pos->target;
377 k++;
378 } else {
379 sprintf(header, " ");
380 }
381
382 memcpy(buf + pos->offset, header, sizeof(header) - 1);
383 }
384 }
385 data->keys[k] = 0;
386}
387
1da177e4
LT
388static void search_conf(void)
389{
390 struct symbol **sym_arr;
1da177e4 391 struct gstr res;
337a275d 392 struct gstr title;
0584f9f9 393 char *dialog_input;
5e609add
BP
394 int dres, vscroll = 0, hscroll = 0;
395 bool again;
9a69abf8
BP
396 struct gstr sttext;
397 struct subtitle_part stpart;
5e609add 398
337a275d 399 title = str_new();
694c49a7
SR
400 str_printf( &title, "Enter (sub)string or regexp to search for "
401 "(with or without \"%s\")", CONFIG_);
337a275d 402
1da177e4 403again:
e94c5bde 404 dialog_clear();
694c49a7 405 dres = dialog_inputbox("Search Configuration Parameter",
337a275d 406 str_get(&title),
2982de69
SR
407 10, 75, "");
408 switch (dres) {
1da177e4
LT
409 case 0:
410 break;
411 case 1:
694c49a7 412 show_helptext("Search Configuration", search_help);
1da177e4
LT
413 goto again;
414 default:
337a275d 415 str_free(&title);
1da177e4
LT
416 return;
417 }
418
ffb5957b 419 /* strip the prefix if necessary */
0584f9f9 420 dialog_input = dialog_input_result;
ffb5957b
AL
421 if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
422 dialog_input += strlen(CONFIG_);
0584f9f9 423
9a69abf8
BP
424 sttext = str_new();
425 str_printf(&sttext, "Search (%s)", dialog_input_result);
426 stpart.text = str_get(&sttext);
427 list_add_tail(&stpart.entries, &trail);
428
0584f9f9 429 sym_arr = sym_re_search(dialog_input);
5e609add 430 do {
bad9955d 431 LIST_HEAD(head);
95ac9b3b
BP
432 struct menu *targets[JUMP_NB];
433 int keys[JUMP_NB + 1], i;
434 struct search_data data = {
435 .head = &head,
436 .targets = targets,
437 .keys = keys,
438 };
edb749f4 439 struct jump_key *pos, *tmp;
95ac9b3b
BP
440
441 res = get_relations_str(sym_arr, &head);
9a69abf8 442 set_subtitle();
694c49a7 443 dres = show_textbox_ext("Search Results", (char *)
95ac9b3b
BP
444 str_get(&res), 0, 0, keys, &vscroll,
445 &hscroll, &update_text, (void *)
446 &data);
5e609add 447 again = false;
95ac9b3b 448 for (i = 0; i < JUMP_NB && keys[i]; i++)
5e609add 449 if (dres == keys[i]) {
95ac9b3b 450 conf(targets[i]->parent, targets[i]);
5e609add
BP
451 again = true;
452 }
453 str_free(&res);
edb749f4
BP
454 list_for_each_entry_safe(pos, tmp, &head, entries)
455 free(pos);
5e609add 456 } while (again);
1da177e4 457 free(sym_arr);
337a275d 458 str_free(&title);
9a69abf8
BP
459 list_del(trail.prev);
460 str_free(&sttext);
1da177e4
LT
461}
462
463static void build_conf(struct menu *menu)
464{
465 struct symbol *sym;
466 struct property *prop;
467 struct menu *child;
468 int type, tmp, doint = 2;
469 tristate val;
470 char ch;
22c7eca6
LZ
471 bool visible;
472
473 /*
474 * note: menu_is_visible() has side effect that it will
475 * recalc the value of the symbol.
476 */
477 visible = menu_is_visible(menu);
478 if (show_all_options && !menu_has_prompt(menu))
479 return;
480 else if (!show_all_options && !visible)
1da177e4
LT
481 return;
482
483 sym = menu->sym;
484 prop = menu->prompt;
485 if (!sym) {
486 if (prop && menu != current_menu) {
487 const char *prompt = menu_get_prompt(menu);
488 switch (prop->type) {
489 case P_MENU:
490 child_count++;
1da177e4 491 if (single_menu_mode) {
2982de69
SR
492 item_make("%s%*c%s",
493 menu->data ? "-->" : "++>",
494 indent + 1, ' ', prompt);
1da177e4 495 } else
1278ebdb
DG
496 item_make(" %*c%s %s",
497 indent + 1, ' ', prompt,
498 menu_is_empty(menu) ? "----" : "--->");
2982de69
SR
499 item_set_tag('m');
500 item_set_data(menu);
1da177e4
LT
501 if (single_menu_mode && menu->data)
502 goto conf_childs;
503 return;
48874077
SR
504 case P_COMMENT:
505 if (prompt) {
506 child_count++;
694c49a7 507 item_make(" %*c*** %s ***", indent + 1, ' ', prompt);
48874077
SR
508 item_set_tag(':');
509 item_set_data(menu);
510 }
511 break;
1da177e4
LT
512 default:
513 if (prompt) {
514 child_count++;
694c49a7 515 item_make("---%*c%s", indent + 1, ' ', prompt);
2982de69
SR
516 item_set_tag(':');
517 item_set_data(menu);
1da177e4
LT
518 }
519 }
520 } else
521 doint = 0;
522 goto conf_childs;
523 }
524
525 type = sym_get_type(sym);
526 if (sym_is_choice(sym)) {
527 struct symbol *def_sym = sym_get_choice_value(sym);
528 struct menu *def_menu = NULL;
529
530 child_count++;
531 for (child = menu->list; child; child = child->next) {
532 if (menu_is_visible(child) && child->sym == def_sym)
533 def_menu = child;
534 }
535
536 val = sym_get_tristate_value(sym);
baa23ec8 537 if (sym_is_changeable(sym)) {
1da177e4
LT
538 switch (type) {
539 case S_BOOLEAN:
2982de69 540 item_make("[%c]", val == no ? ' ' : '*');
1da177e4
LT
541 break;
542 case S_TRISTATE:
543 switch (val) {
544 case yes: ch = '*'; break;
545 case mod: ch = 'M'; break;
546 default: ch = ' '; break;
547 }
2982de69 548 item_make("<%c>", ch);
1da177e4
LT
549 break;
550 }
2982de69
SR
551 item_set_tag('t');
552 item_set_data(menu);
1da177e4 553 } else {
2982de69
SR
554 item_make(" ");
555 item_set_tag(def_menu ? 't' : ':');
556 item_set_data(menu);
1da177e4
LT
557 }
558
694c49a7 559 item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
1da177e4
LT
560 if (val == yes) {
561 if (def_menu) {
694c49a7 562 item_add_str(" (%s)", menu_get_prompt(def_menu));
2982de69 563 item_add_str(" --->");
1da177e4
LT
564 if (def_menu->list) {
565 indent += 2;
566 build_conf(def_menu);
567 indent -= 2;
568 }
2982de69 569 }
1da177e4
LT
570 return;
571 }
1da177e4
LT
572 } else {
573 if (menu == current_menu) {
694c49a7 574 item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
2982de69
SR
575 item_set_tag(':');
576 item_set_data(menu);
1da177e4
LT
577 goto conf_childs;
578 }
579 child_count++;
580 val = sym_get_tristate_value(sym);
581 if (sym_is_choice_value(sym) && val == yes) {
2982de69
SR
582 item_make(" ");
583 item_set_tag(':');
584 item_set_data(menu);
1da177e4
LT
585 } else {
586 switch (type) {
587 case S_BOOLEAN:
baa23ec8 588 if (sym_is_changeable(sym))
2982de69 589 item_make("[%c]", val == no ? ' ' : '*');
1da177e4 590 else
b5d609db 591 item_make("-%c-", val == no ? ' ' : '*');
2982de69
SR
592 item_set_tag('t');
593 item_set_data(menu);
1da177e4
LT
594 break;
595 case S_TRISTATE:
1da177e4
LT
596 switch (val) {
597 case yes: ch = '*'; break;
598 case mod: ch = 'M'; break;
599 default: ch = ' '; break;
600 }
baa23ec8 601 if (sym_is_changeable(sym)) {
b5d609db
ML
602 if (sym->rev_dep.tri == mod)
603 item_make("{%c}", ch);
604 else
605 item_make("<%c>", ch);
606 } else
607 item_make("-%c-", ch);
2982de69
SR
608 item_set_tag('t');
609 item_set_data(menu);
1da177e4
LT
610 break;
611 default:
2982de69
SR
612 tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
613 item_make("(%s)", sym_get_string_value(sym));
1da177e4
LT
614 tmp = indent - tmp + 4;
615 if (tmp < 0)
616 tmp = 0;
694c49a7 617 item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
baa23ec8 618 (sym_has_value(sym) || !sym_is_changeable(sym)) ?
694c49a7 619 "" : " (NEW)");
2982de69
SR
620 item_set_tag('s');
621 item_set_data(menu);
1da177e4
LT
622 goto conf_childs;
623 }
624 }
694c49a7 625 item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
baa23ec8 626 (sym_has_value(sym) || !sym_is_changeable(sym)) ?
694c49a7 627 "" : " (NEW)");
1da177e4 628 if (menu->prompt->type == P_MENU) {
1278ebdb 629 item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->");
1da177e4
LT
630 return;
631 }
1da177e4
LT
632 }
633
634conf_childs:
635 indent += doint;
636 for (child = menu->list; child; child = child->next)
637 build_conf(child);
638 indent -= doint;
639}
640
5e609add 641static void conf(struct menu *menu, struct menu *active_menu)
1da177e4
LT
642{
643 struct menu *submenu;
644 const char *prompt = menu_get_prompt(menu);
9a69abf8 645 struct subtitle_part stpart;
1da177e4 646 struct symbol *sym;
2982de69
SR
647 int res;
648 int s_scroll = 0;
1da177e4 649
9a69abf8
BP
650 if (menu != &rootmenu)
651 stpart.text = menu_get_prompt(menu);
652 else
653 stpart.text = NULL;
654 list_add_tail(&stpart.entries, &trail);
655
1da177e4 656 while (1) {
2982de69 657 item_reset();
1da177e4
LT
658 current_menu = menu;
659 build_conf(menu);
660 if (!child_count)
661 break;
9a69abf8 662 set_subtitle();
e94c5bde 663 dialog_clear();
694c49a7
SR
664 res = dialog_menu(prompt ? prompt : "Main Menu",
665 menu_instructions,
2982de69 666 active_menu, &s_scroll);
c8dc68ad 667 if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
1da177e4 668 break;
063f4661
DG
669 if (item_count() != 0) {
670 if (!item_activate_selected())
671 continue;
672 if (!item_tag())
673 continue;
674 }
2982de69
SR
675 submenu = item_data();
676 active_menu = item_data();
c8dc68ad
SR
677 if (submenu)
678 sym = submenu->sym;
679 else
680 sym = NULL;
1da177e4 681
2982de69 682 switch (res) {
1da177e4 683 case 0:
2982de69 684 switch (item_tag()) {
1da177e4
LT
685 case 'm':
686 if (single_menu_mode)
687 submenu->data = (void *) (long) !submenu->data;
688 else
5e609add 689 conf(submenu, NULL);
1da177e4
LT
690 break;
691 case 't':
692 if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
693 conf_choice(submenu);
694 else if (submenu->prompt->type == P_MENU)
5e609add 695 conf(submenu, NULL);
1da177e4
LT
696 break;
697 case 's':
698 conf_string(submenu);
699 break;
1da177e4
LT
700 }
701 break;
702 case 2:
703 if (sym)
704 show_help(submenu);
9a69abf8
BP
705 else {
706 reset_subtitle();
694c49a7 707 show_helptext("README", mconf_readme);
9a69abf8 708 }
1da177e4
LT
709 break;
710 case 3:
9a69abf8 711 reset_subtitle();
6364fd0c
WY
712 conf_save();
713 break;
714 case 4:
9a69abf8 715 reset_subtitle();
6364fd0c
WY
716 conf_load();
717 break;
718 case 5:
2982de69 719 if (item_is_tag('t')) {
1da177e4
LT
720 if (sym_set_tristate_value(sym, yes))
721 break;
722 if (sym_set_tristate_value(sym, mod))
723 show_textbox(NULL, setmod_text, 6, 74);
724 }
725 break;
6364fd0c 726 case 6:
2982de69 727 if (item_is_tag('t'))
1da177e4
LT
728 sym_set_tristate_value(sym, no);
729 break;
6364fd0c 730 case 7:
2982de69 731 if (item_is_tag('t'))
1da177e4
LT
732 sym_set_tristate_value(sym, mod);
733 break;
6364fd0c 734 case 8:
2982de69 735 if (item_is_tag('t'))
1da177e4 736 sym_toggle_tristate_value(sym);
2982de69 737 else if (item_is_tag('m'))
5e609add 738 conf(submenu, NULL);
1da177e4 739 break;
6364fd0c 740 case 9:
1da177e4
LT
741 search_conf();
742 break;
6364fd0c 743 case 10:
22c7eca6
LZ
744 show_all_options = !show_all_options;
745 break;
1da177e4
LT
746 }
747 }
9a69abf8
BP
748
749 list_del(trail.prev);
1da177e4
LT
750}
751
95ac9b3b
BP
752static int show_textbox_ext(const char *title, char *text, int r, int c, int
753 *keys, int *vscroll, int *hscroll, update_text_fn
754 update_text, void *data)
1da177e4 755{
e94c5bde 756 dialog_clear();
95ac9b3b
BP
757 return dialog_textbox(title, text, r, c, keys, vscroll, hscroll,
758 update_text, data);
537ddae7
BP
759}
760
761static void show_textbox(const char *title, const char *text, int r, int c)
762{
95ac9b3b
BP
763 show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL,
764 NULL, NULL);
1da177e4
LT
765}
766
767static void show_helptext(const char *title, const char *text)
768{
769 show_textbox(title, text, 0, 0);
770}
771
5accd7f3 772static void conf_message_callback(const char *s)
6364fd0c 773{
0a1f00a1
MM
774 if (save_and_exit) {
775 if (!silent)
5accd7f3 776 printf("%s", s);
0a1f00a1 777 } else {
5accd7f3 778 show_textbox(NULL, s, 6, 60);
0a1f00a1 779 }
6364fd0c
WY
780}
781
1da177e4
LT
782static void show_help(struct menu *menu)
783{
784 struct gstr help = str_new();
1d525e7c 785
da60fbbc 786 help.max_width = getmaxx(stdscr) - 10;
1d525e7c
CR
787 menu_get_ext_help(menu, &help);
788
694c49a7 789 show_helptext(menu_get_prompt(menu), str_get(&help));
1da177e4
LT
790 str_free(&help);
791}
792
1da177e4
LT
793static void conf_choice(struct menu *menu)
794{
694c49a7 795 const char *prompt = menu_get_prompt(menu);
1da177e4
LT
796 struct menu *child;
797 struct symbol *active;
1da177e4
LT
798
799 active = sym_get_choice_value(menu->sym);
800 while (1) {
2982de69
SR
801 int res;
802 int selected;
803 item_reset();
1da177e4
LT
804
805 current_menu = menu;
806 for (child = menu->list; child; child = child->next) {
807 if (!menu_is_visible(child))
808 continue;
af6c1598 809 if (child->sym)
694c49a7 810 item_make("%s", menu_get_prompt(child));
af6c1598 811 else {
694c49a7 812 item_make("*** %s ***", menu_get_prompt(child));
af6c1598
PK
813 item_set_tag(':');
814 }
2982de69
SR
815 item_set_data(child);
816 if (child->sym == active)
817 item_set_selected(1);
1da177e4 818 if (child->sym == sym_get_choice_value(menu->sym))
2982de69 819 item_set_tag('X');
1da177e4 820 }
e94c5bde 821 dialog_clear();
694c49a7
SR
822 res = dialog_checklist(prompt ? prompt : "Main Menu",
823 radiolist_instructions,
ff7b0c2c
SD
824 MENUBOX_HEIGTH_MIN,
825 MENUBOX_WIDTH_MIN,
826 CHECKLIST_HEIGTH_MIN);
2982de69
SR
827 selected = item_activate_selected();
828 switch (res) {
1da177e4 829 case 0:
2982de69
SR
830 if (selected) {
831 child = item_data();
af6c1598
PK
832 if (!child->sym)
833 break;
834
2982de69
SR
835 sym_set_tristate_value(child->sym, yes);
836 }
1da177e4
LT
837 return;
838 case 1:
2982de69
SR
839 if (selected) {
840 child = item_data();
1da177e4
LT
841 show_help(child);
842 active = child->sym;
843 } else
844 show_help(menu);
845 break;
f3cbcdc9 846 case KEY_ESC:
1da177e4 847 return;
c8dc68ad
SR
848 case -ERRDISPLAYTOOSMALL:
849 return;
1da177e4
LT
850 }
851 }
852}
853
854static void conf_string(struct menu *menu)
855{
856 const char *prompt = menu_get_prompt(menu);
1da177e4
LT
857
858 while (1) {
2982de69 859 int res;
c4143a83 860 const char *heading;
2982de69 861
1da177e4
LT
862 switch (sym_get_type(menu->sym)) {
863 case S_INT:
694c49a7 864 heading = inputbox_instructions_int;
1da177e4
LT
865 break;
866 case S_HEX:
694c49a7 867 heading = inputbox_instructions_hex;
1da177e4
LT
868 break;
869 case S_STRING:
694c49a7 870 heading = inputbox_instructions_string;
1da177e4
LT
871 break;
872 default:
694c49a7 873 heading = "Internal mconf error!";
1da177e4 874 }
e94c5bde 875 dialog_clear();
694c49a7 876 res = dialog_inputbox(prompt ? prompt : "Main Menu",
2982de69
SR
877 heading, 10, 75,
878 sym_get_string_value(menu->sym));
879 switch (res) {
1da177e4 880 case 0:
2982de69 881 if (sym_set_string_value(menu->sym, dialog_input_result))
1da177e4 882 return;
694c49a7 883 show_textbox(NULL, "You have made an invalid entry.", 5, 43);
1da177e4
LT
884 break;
885 case 1:
886 show_help(menu);
887 break;
f3cbcdc9 888 case KEY_ESC:
1da177e4
LT
889 return;
890 }
891 }
892}
893
894static void conf_load(void)
895{
1da177e4
LT
896
897 while (1) {
2982de69 898 int res;
e94c5bde 899 dialog_clear();
2982de69
SR
900 res = dialog_inputbox(NULL, load_config_text,
901 11, 55, filename);
902 switch(res) {
1da177e4 903 case 0:
2982de69 904 if (!dialog_input_result[0])
1da177e4 905 return;
95e30f95
SR
906 if (!conf_read(dialog_input_result)) {
907 set_config_filename(dialog_input_result);
5ee54659 908 conf_set_changed(true);
1da177e4 909 return;
95e30f95 910 }
694c49a7 911 show_textbox(NULL, "File does not exist!", 5, 38);
1da177e4
LT
912 break;
913 case 1:
694c49a7 914 show_helptext("Load Alternate Configuration", load_config_help);
1da177e4 915 break;
f3cbcdc9 916 case KEY_ESC:
1da177e4
LT
917 return;
918 }
919 }
920}
921
922static void conf_save(void)
923{
1da177e4 924 while (1) {
2982de69 925 int res;
e94c5bde 926 dialog_clear();
2982de69
SR
927 res = dialog_inputbox(NULL, save_config_text,
928 11, 55, filename);
929 switch(res) {
1da177e4 930 case 0:
2982de69 931 if (!dialog_input_result[0])
1da177e4 932 return;
95e30f95
SR
933 if (!conf_write(dialog_input_result)) {
934 set_config_filename(dialog_input_result);
1da177e4 935 return;
95e30f95 936 }
580c5b3e 937 show_textbox(NULL, "Can't create file!", 5, 60);
1da177e4
LT
938 break;
939 case 1:
694c49a7 940 show_helptext("Save Alternate Configuration", save_config_help);
1da177e4 941 break;
f3cbcdc9 942 case KEY_ESC:
1da177e4
LT
943 return;
944 }
945 }
946}
947
564899f9
DB
948static int handle_exit(void)
949{
950 int res;
951
6364fd0c 952 save_and_exit = 1;
9a69abf8 953 reset_subtitle();
564899f9
DB
954 dialog_clear();
955 if (conf_get_changed())
956 res = dialog_yesno(NULL,
694c49a7
SR
957 "Do you wish to save your new configuration?\n"
958 "(Press <ESC><ESC> to continue kernel configuration.)",
564899f9
DB
959 6, 60);
960 else
961 res = -1;
962
963 end_dialog(saved_x, saved_y);
964
965 switch (res) {
966 case 0:
967 if (conf_write(filename)) {
694c49a7 968 fprintf(stderr, "\n\n"
564899f9
DB
969 "Error while writing of the configuration.\n"
970 "Your configuration changes were NOT saved."
694c49a7 971 "\n\n");
564899f9
DB
972 return 1;
973 }
00c864f8 974 conf_write_autoconf(0);
564899f9
DB
975 /* fall through */
976 case -1:
0a1f00a1 977 if (!silent)
694c49a7 978 printf("\n\n"
0a1f00a1
MM
979 "*** End of the configuration.\n"
980 "*** Execute 'make' to start the build or try 'make help'."
694c49a7 981 "\n\n");
564899f9
DB
982 res = 0;
983 break;
984 default:
0a1f00a1 985 if (!silent)
694c49a7 986 fprintf(stderr, "\n\n"
0a1f00a1 987 "Your configuration changes were NOT saved."
694c49a7 988 "\n\n");
30c4eaaf
LZ
989 if (res != KEY_ESC)
990 res = 0;
564899f9
DB
991 }
992
993 return res;
994}
995
996static void sig_handler(int signo)
997{
998 exit(handle_exit());
999}
1000
1da177e4
LT
1001int main(int ac, char **av)
1002{
1da177e4 1003 char *mode;
2982de69 1004 int res;
1da177e4 1005
564899f9
DB
1006 signal(SIGINT, sig_handler);
1007
0a1f00a1
MM
1008 if (ac > 1 && strcmp(av[1], "-s") == 0) {
1009 silent = 1;
1010 /* Silence conf_read() until the real callback is set up */
1011 conf_set_message_callback(NULL);
1012 av++;
1013 }
1da177e4
LT
1014 conf_parse(av[1]);
1015 conf_read(NULL);
1016
1da177e4
LT
1017 mode = getenv("MENUCONFIG_MODE");
1018 if (mode) {
1019 if (!strcasecmp(mode, "single_menu"))
1020 single_menu_mode = 1;
1021 }
1022
09af091f 1023 if (init_dialog(NULL)) {
694c49a7
SR
1024 fprintf(stderr, "Your display is too small to run Menuconfig!\n");
1025 fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
09af091f
LM
1026 return 1;
1027 }
1028
d802b50f 1029 set_config_filename(conf_get_configname());
6364fd0c 1030 conf_set_message_callback(conf_message_callback);
f3cbcdc9 1031 do {
5e609add 1032 conf(&rootmenu, NULL);
564899f9 1033 res = handle_exit();
f3cbcdc9 1034 } while (res == KEY_ESC);
1da177e4 1035
564899f9 1036 return res;
1da177e4 1037}