kconfig/mconf.c
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Sun May 08 14:14:40 2011 +0200 (2011-05-08)
changeset 2448 a103abae1560
parent 943 1cca90ce0481
child 2452 ff170381d13a
permissions -rw-r--r--
kconfig: update from linux-next

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