File Index
Files and directories
Sign in
FILE

mconf.c

File preview with syntax highlighting.

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