kconfig/mconf.c
author "Benoît Thébaudeau" <benoit.thebaudeau@advansee.com>
Mon Apr 16 15:25:36 2012 +0200 (2012-04-16)
changeset 2941 13e40098fffc
parent 2448 a103abae1560
permissions -rw-r--r--
cc/gcc: update Linaro GCC revisions to 2012.04

Update Linaro GCC with the latest available revisions.

The 4.7 revision is also released, but the infrastructure is not yet ready for
it in CT-NG.

Signed-off-by: "Benoît Thébaudeau" <benoit.thebaudeau@advansee.com>
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@39
   849
		break;
yann@39
   850
	default:
yann@2448
   851
		fprintf(stderr, _("\n\n"
yann@2448
   852
			"Your configuration changes were NOT saved."
yann@2448
   853
			"\n\n"));
yann@1
   854
	}
yann@1
   855
yann@1
   856
	return 0;
yann@1
   857
}
yann@943
   858