Linux Audio

Check our new training course

Embedded Linux training

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