Linux Audio

Check our new training course

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