kconfig/mconf.c
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Sun Aug 02 20:06:44 2009 +0200 (2009-08-02)
changeset 1446 0a44fc4d6bd0
parent 94 f32c4f663805
child 2448 a103abae1560
permissions -rw-r--r--
[config] Allow user to specify custom CONFIG_SHELL

In case the shell the user wants to use as CONFIG_SHELL is located in a
weird place (eg. /opt/bash/bin/bash), or is weirdly named (eg. bash-4),
let the user enter the patch to the shell.
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@1
    28
"Some kernel features may be built directly into the kernel.\n"
yann@1
    29
"Some may be made into loadable runtime modules.  Some features\n"
yann@1
    30
"may be completely removed altogether.  There are also certain\n"
yann@1
    31
"kernel parameters which are not really features, but must be\n"
yann@1
    32
"entered in as decimal or hexadecimal numbers or possibly text.\n"
yann@1
    33
"\n"
yann@943
    34
"Menu items beginning with following braces represent features that\n"
yann@943
    35
"  [ ] can be built in or removed\n"
yann@943
    36
"  < > can be built in, modularized or removed\n"
yann@943
    37
"  { } can be built in or modularized (selected by other feature)\n"
yann@943
    38
"  - - are selected by other feature,\n"
yann@943
    39
"while *, M or whitespace inside braces means to build in, build as\n"
yann@943
    40
"a module or to exclude the feature respectively.\n"
yann@1
    41
"\n"
yann@1
    42
"To change any of these features, highlight it with the cursor\n"
yann@1
    43
"keys and press <Y> to build it in, <M> to make it a module or\n"
yann@1
    44
"<N> to removed it.  You may also press the <Space Bar> to cycle\n"
yann@1
    45
"through the available options (ie. Y->N->M->Y).\n"
yann@1
    46
"\n"
yann@1
    47
"Some additional keyboard hints:\n"
yann@1
    48
"\n"
yann@1
    49
"Menus\n"
yann@1
    50
"----------\n"
yann@1
    51
"o  Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
yann@1
    52
"   you wish to change or submenu wish to select and press <Enter>.\n"
yann@1
    53
"   Submenus are designated by \"--->\".\n"
yann@1
    54
"\n"
yann@1
    55
"   Shortcut: Press the option's highlighted letter (hotkey).\n"
yann@1
    56
"             Pressing a hotkey more than once will sequence\n"
yann@1
    57
"             through all visible items which use that hotkey.\n"
yann@1
    58
"\n"
yann@1
    59
"   You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
yann@1
    60
"   unseen options into view.\n"
yann@1
    61
"\n"
yann@1
    62
"o  To exit a menu use the cursor keys to highlight the <Exit> button\n"
yann@1
    63
"   and press <ENTER>.\n"
yann@1
    64
"\n"
yann@1
    65
"   Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\n"
yann@1
    66
"             using those letters.  You may press a single <ESC>, but\n"
yann@1
    67
"             there is a delayed response which you may find annoying.\n"
yann@1
    68
"\n"
yann@1
    69
"   Also, the <TAB> and cursor keys will cycle between <Select>,\n"
yann@1
    70
"   <Exit> and <Help>\n"
yann@1
    71
"\n"
yann@1
    72
"o  To get help with an item, use the cursor keys to highlight <Help>\n"
yann@1
    73
"   and Press <ENTER>.\n"
yann@1
    74
"\n"
yann@1
    75
"   Shortcut: Press <H> or <?>.\n"
yann@1
    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@1
   118
"between different kernel 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@1
   151
"If you prefer to have all of the kernel options listed in a single\n"
yann@1
   152
"menu, rather than the default multimenu hierarchy, run the menuconfig\n"
yann@1
   153
"with 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
nohelp_text[] = N_(
yann@1
   203
	"There is no help available for this kernel option.\n"),
yann@1
   204
load_config_text[] = N_(
yann@1
   205
	"Enter the name of the configuration file you wish to load.  "
yann@1
   206
	"Accept the name shown to restore the configuration you "
yann@1
   207
	"last retrieved.  Leave blank to abort."),
yann@1
   208
load_config_help[] = N_(
yann@1
   209
	"\n"
yann@1
   210
	"For various reasons, one may wish to keep several different kernel\n"
yann@1
   211
	"configurations available on a single machine.\n"
yann@1
   212
	"\n"
yann@1
   213
	"If you have saved a previous configuration in a file other than the\n"
yann@1
   214
	"kernel's default, entering the name of the file here will allow you\n"
yann@1
   215
	"to modify that configuration.\n"
yann@1
   216
	"\n"
yann@1
   217
	"If you are uncertain, then you have probably never used alternate\n"
yann@1
   218
	"configuration files.  You should therefor leave this blank to abort.\n"),
yann@1
   219
save_config_text[] = N_(
yann@1
   220
	"Enter a filename to which this configuration should be saved "
yann@1
   221
	"as an alternate.  Leave blank to abort."),
yann@1
   222
save_config_help[] = N_(
yann@1
   223
	"\n"
yann@1
   224
	"For various reasons, one may wish to keep different kernel\n"
yann@1
   225
	"configurations available on a single machine.\n"
yann@1
   226
	"\n"
yann@1
   227
	"Entering a file name here will allow you to later retrieve, modify\n"
yann@1
   228
	"and use the current configuration as an alternate to whatever\n"
yann@1
   229
	"configuration options you have selected at that time.\n"
yann@1
   230
	"\n"
yann@1
   231
	"If you are uncertain what all this means then you should probably\n"
yann@1
   232
	"leave this blank.\n"),
yann@1
   233
search_help[] = N_(
yann@1
   234
	"\n"
yann@1
   235
	"Search for CT_ symbols and display their relations.\n"
yann@1
   236
	"Regular expressions are allowed.\n"
yann@1
   237
	"Example: search for \"^FOO\"\n"
yann@1
   238
	"Result:\n"
yann@1
   239
	"-----------------------------------------------------------------\n"
yann@1
   240
	"Symbol: FOO [=m]\n"
yann@1
   241
	"Prompt: Foo bus is used to drive the bar HW\n"
yann@1
   242
	"Defined at drivers/pci/Kconfig:47\n"
yann@1
   243
	"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
yann@1
   244
	"Location:\n"
yann@1
   245
	"  -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
yann@1
   246
	"    -> PCI support (PCI [=y])\n"
yann@1
   247
	"      -> PCI access mode (<choice> [=y])\n"
yann@1
   248
	"Selects: LIBCRC32\n"
yann@1
   249
	"Selected by: BAR\n"
yann@1
   250
	"-----------------------------------------------------------------\n"
yann@1
   251
	"o The line 'Prompt:' shows the text used in the menu structure for\n"
yann@1
   252
	"  this CT_ symbol\n"
yann@1
   253
	"o The 'Defined at' line tell at what file / line number the symbol\n"
yann@1
   254
	"  is defined\n"
yann@1
   255
	"o The 'Depends on:' line tell what symbols needs to be defined for\n"
yann@1
   256
	"  this symbol to be visible in the menu (selectable)\n"
yann@1
   257
	"o The 'Location:' lines tell where in the menu structure this symbol\n"
yann@1
   258
	"  is located\n"
yann@1
   259
	"    A location followed by a [=y] indicate that this is a selectable\n"
yann@1
   260
	"    menu item - and current value is displayed inside brackets.\n"
yann@1
   261
	"o The 'Selects:' line tell what symbol will be automatically\n"
yann@1
   262
	"  selected if this symbol is selected (y or m)\n"
yann@1
   263
	"o The 'Selected by' line tell what symbol has selected this symbol\n"
yann@1
   264
	"\n"
yann@1
   265
	"Only relevant lines are shown.\n"
yann@1
   266
	"\n\n"
yann@1
   267
	"Search examples:\n"
yann@1
   268
	"Examples: USB	=> find all CT_ symbols containing USB\n"
yann@1
   269
	"          ^USB => find all CT_ symbols starting with USB\n"
yann@1
   270
	"          USB$ => find all CT_ symbols ending with USB\n"
yann@1
   271
	"\n");
yann@1
   272
yann@1
   273
static int indent;
yann@1
   274
static struct menu *current_menu;
yann@1
   275
static int child_count;
yann@1
   276
static int single_menu_mode;
yann@1
   277
yann@1
   278
static void conf(struct menu *menu);
yann@1
   279
static void conf_choice(struct menu *menu);
yann@1
   280
static void conf_string(struct menu *menu);
yann@1
   281
static void conf_load(void);
yann@1
   282
static void conf_save(void);
yann@1
   283
static void show_textbox(const char *title, const char *text, int r, int c);
yann@1
   284
static void show_helptext(const char *title, const char *text);
yann@1
   285
static void show_help(struct menu *menu);
yann@1
   286
yann@1
   287
static void get_prompt_str(struct gstr *r, struct property *prop)
yann@1
   288
{
yann@1
   289
	int i, j;
yann@1
   290
	struct menu *submenu[8], *menu;
yann@1
   291
yann@943
   292
	str_printf(r, _("Prompt: %s\n"), _(prop->text));
yann@943
   293
	str_printf(r, _("  Defined at %s:%d\n"), prop->menu->file->name,
yann@1
   294
		prop->menu->lineno);
yann@1
   295
	if (!expr_is_yes(prop->visible.expr)) {
yann@943
   296
		str_append(r, _("  Depends on: "));
yann@1
   297
		expr_gstr_print(prop->visible.expr, r);
yann@1
   298
		str_append(r, "\n");
yann@1
   299
	}
yann@1
   300
	menu = prop->menu->parent;
yann@1
   301
	for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
yann@1
   302
		submenu[i++] = menu;
yann@1
   303
	if (i > 0) {
yann@943
   304
		str_printf(r, _("  Location:\n"));
yann@1
   305
		for (j = 4; --i >= 0; j += 2) {
yann@1
   306
			menu = submenu[i];
yann@943
   307
			str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu)));
yann@1
   308
			if (menu->sym) {
yann@1
   309
				str_printf(r, " (%s [=%s])", menu->sym->name ?
yann@943
   310
					menu->sym->name : _("<choice>"),
yann@1
   311
					sym_get_string_value(menu->sym));
yann@1
   312
			}
yann@1
   313
			str_append(r, "\n");
yann@1
   314
		}
yann@1
   315
	}
yann@1
   316
}
yann@1
   317
yann@1
   318
static void get_symbol_str(struct gstr *r, struct symbol *sym)
yann@1
   319
{
yann@1
   320
	bool hit;
yann@1
   321
	struct property *prop;
yann@1
   322
yann@943
   323
	if (sym && sym->name)
yann@943
   324
		str_printf(r, "Symbol: %s [=%s]\n", sym->name,
yann@943
   325
		                                    sym_get_string_value(sym));
yann@1
   326
	for_all_prompts(sym, prop)
yann@1
   327
		get_prompt_str(r, prop);
yann@1
   328
	hit = false;
yann@1
   329
	for_all_properties(sym, prop, P_SELECT) {
yann@1
   330
		if (!hit) {
yann@1
   331
			str_append(r, "  Selects: ");
yann@1
   332
			hit = true;
yann@1
   333
		} else
yann@1
   334
			str_printf(r, " && ");
yann@1
   335
		expr_gstr_print(prop->expr, r);
yann@1
   336
	}
yann@1
   337
	if (hit)
yann@1
   338
		str_append(r, "\n");
yann@1
   339
	if (sym->rev_dep.expr) {
yann@943
   340
		str_append(r, _("  Selected by: "));
yann@1
   341
		expr_gstr_print(sym->rev_dep.expr, r);
yann@1
   342
		str_append(r, "\n");
yann@1
   343
	}
yann@1
   344
	str_append(r, "\n\n");
yann@1
   345
}
yann@1
   346
yann@1
   347
static struct gstr get_relations_str(struct symbol **sym_arr)
yann@1
   348
{
yann@1
   349
	struct symbol *sym;
yann@1
   350
	struct gstr res = str_new();
yann@1
   351
	int i;
yann@1
   352
yann@1
   353
	for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
yann@1
   354
		get_symbol_str(&res, sym);
yann@1
   355
	if (!i)
yann@943
   356
		str_append(&res, _("No matches found.\n"));
yann@1
   357
	return res;
yann@1
   358
}
yann@1
   359
yann@943
   360
static char filename[PATH_MAX+1];
yann@943
   361
static void set_config_filename(const char *config_filename)
yann@943
   362
{
yann@943
   363
	static char menu_backtitle[PATH_MAX+128];
yann@943
   364
	int size;
yann@943
   365
	struct symbol *sym;
yann@943
   366
yann@943
   367
	sym = sym_lookup("PROJECTVERSION", 0);
yann@943
   368
	sym_calc_value(sym);
yann@943
   369
	size = snprintf(menu_backtitle, sizeof(menu_backtitle),
yann@943
   370
	                _(PACKAGE " v%s Configuration - %s"),
yann@943
   371
		        sym_get_string_value(sym), config_filename);
yann@943
   372
	if (size >= sizeof(menu_backtitle))
yann@943
   373
		menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
yann@943
   374
	set_dialog_backtitle(menu_backtitle);
yann@943
   375
yann@943
   376
	size = snprintf(filename, sizeof(filename), "%s", config_filename);
yann@943
   377
	if (size >= sizeof(filename))
yann@943
   378
		filename[sizeof(filename)-1] = '\0';
yann@943
   379
}
yann@943
   380
yann@943
   381
yann@1
   382
static void search_conf(void)
yann@1
   383
{
yann@1
   384
	struct symbol **sym_arr;
yann@1
   385
	struct gstr res;
yann@943
   386
	char *dialog_input;
yann@1
   387
	int dres;
yann@1
   388
again:
yann@1
   389
	dialog_clear();
yann@1
   390
	dres = dialog_inputbox(_("Search Configuration Parameter"),
yann@943
   391
			      _("Enter CT_ (sub)string to search for "
yann@943
   392
				"(with or without \"CT\")"),
yann@1
   393
			      10, 75, "");
yann@1
   394
	switch (dres) {
yann@1
   395
	case 0:
yann@1
   396
		break;
yann@1
   397
	case 1:
yann@1
   398
		show_helptext(_("Search Configuration"), search_help);
yann@1
   399
		goto again;
yann@1
   400
	default:
yann@1
   401
		return;
yann@1
   402
	}
yann@1
   403
yann@943
   404
	/* strip CT_ if necessary */
yann@943
   405
	dialog_input = dialog_input_result;
yann@943
   406
	if (strncasecmp(dialog_input_result, "CT_", 3) == 0)
yann@943
   407
		dialog_input += 7;
yann@943
   408
yann@943
   409
	sym_arr = sym_re_search(dialog_input);
yann@1
   410
	res = get_relations_str(sym_arr);
yann@1
   411
	free(sym_arr);
yann@1
   412
	show_textbox(_("Search Results"), str_get(&res), 0, 0);
yann@1
   413
	str_free(&res);
yann@1
   414
}
yann@1
   415
yann@1
   416
static void build_conf(struct menu *menu)
yann@1
   417
{
yann@1
   418
	struct symbol *sym;
yann@1
   419
	struct property *prop;
yann@1
   420
	struct menu *child;
yann@1
   421
	int type, tmp, doint = 2;
yann@1
   422
	tristate val;
yann@1
   423
	char ch;
yann@1
   424
yann@1
   425
	if (!menu_is_visible(menu))
yann@1
   426
		return;
yann@1
   427
yann@1
   428
	sym = menu->sym;
yann@1
   429
	prop = menu->prompt;
yann@1
   430
	if (!sym) {
yann@1
   431
		if (prop && menu != current_menu) {
yann@1
   432
			const char *prompt = menu_get_prompt(menu);
yann@1
   433
			switch (prop->type) {
yann@1
   434
			case P_MENU:
yann@1
   435
				child_count++;
yann@943
   436
				prompt = _(prompt);
yann@1
   437
				if (single_menu_mode) {
yann@1
   438
					item_make("%s%*c%s",
yann@1
   439
						  menu->data ? "-->" : "++>",
yann@1
   440
						  indent + 1, ' ', prompt);
yann@1
   441
				} else
yann@1
   442
					item_make("   %*c%s  --->", indent + 1, ' ', prompt);
yann@1
   443
yann@1
   444
				item_set_tag('m');
yann@1
   445
				item_set_data(menu);
yann@1
   446
				if (single_menu_mode && menu->data)
yann@1
   447
					goto conf_childs;
yann@1
   448
				return;
yann@943
   449
			case P_COMMENT:
yann@943
   450
				if (prompt) {
yann@943
   451
					child_count++;
yann@943
   452
					item_make("   %*c*** %s ***", indent + 1, ' ', _(prompt));
yann@943
   453
					item_set_tag(':');
yann@943
   454
					item_set_data(menu);
yann@943
   455
				}
yann@943
   456
				break;
yann@1
   457
			default:
yann@1
   458
				if (prompt) {
yann@1
   459
					child_count++;
yann@943
   460
					item_make("---%*c%s", indent + 1, ' ', _(prompt));
yann@1
   461
					item_set_tag(':');
yann@1
   462
					item_set_data(menu);
yann@1
   463
				}
yann@1
   464
			}
yann@1
   465
		} else
yann@1
   466
			doint = 0;
yann@1
   467
		goto conf_childs;
yann@1
   468
	}
yann@1
   469
yann@1
   470
	type = sym_get_type(sym);
yann@1
   471
	if (sym_is_choice(sym)) {
yann@1
   472
		struct symbol *def_sym = sym_get_choice_value(sym);
yann@1
   473
		struct menu *def_menu = NULL;
yann@1
   474
yann@1
   475
		child_count++;
yann@1
   476
		for (child = menu->list; child; child = child->next) {
yann@1
   477
			if (menu_is_visible(child) && child->sym == def_sym)
yann@1
   478
				def_menu = child;
yann@1
   479
		}
yann@1
   480
yann@1
   481
		val = sym_get_tristate_value(sym);
yann@1
   482
		if (sym_is_changable(sym)) {
yann@1
   483
			switch (type) {
yann@1
   484
			case S_BOOLEAN:
yann@1
   485
				item_make("[%c]", val == no ? ' ' : '*');
yann@1
   486
				break;
yann@1
   487
			case S_TRISTATE:
yann@1
   488
				switch (val) {
yann@1
   489
				case yes: ch = '*'; break;
yann@1
   490
				case mod: ch = 'M'; break;
yann@1
   491
				default:  ch = ' '; break;
yann@1
   492
				}
yann@1
   493
				item_make("<%c>", ch);
yann@1
   494
				break;
yann@1
   495
			}
yann@1
   496
			item_set_tag('t');
yann@1
   497
			item_set_data(menu);
yann@1
   498
		} else {
yann@1
   499
			item_make("   ");
yann@1
   500
			item_set_tag(def_menu ? 't' : ':');
yann@1
   501
			item_set_data(menu);
yann@1
   502
		}
yann@1
   503
yann@943
   504
		item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
yann@1
   505
		if (val == yes) {
yann@1
   506
			if (def_menu) {
yann@943
   507
				item_add_str(" (%s)", _(menu_get_prompt(def_menu)));
yann@1
   508
				item_add_str("  --->");
yann@1
   509
				if (def_menu->list) {
yann@1
   510
					indent += 2;
yann@1
   511
					build_conf(def_menu);
yann@1
   512
					indent -= 2;
yann@1
   513
				}
yann@1
   514
			}
yann@1
   515
			return;
yann@1
   516
		}
yann@1
   517
	} else {
yann@1
   518
		if (menu == current_menu) {
yann@943
   519
			item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
yann@1
   520
			item_set_tag(':');
yann@1
   521
			item_set_data(menu);
yann@1
   522
			goto conf_childs;
yann@1
   523
		}
yann@1
   524
		child_count++;
yann@1
   525
		val = sym_get_tristate_value(sym);
yann@1
   526
		if (sym_is_choice_value(sym) && val == yes) {
yann@1
   527
			item_make("   ");
yann@1
   528
			item_set_tag(':');
yann@1
   529
			item_set_data(menu);
yann@1
   530
		} else {
yann@1
   531
			switch (type) {
yann@1
   532
			case S_BOOLEAN:
yann@1
   533
				if (sym_is_changable(sym))
yann@1
   534
					item_make("[%c]", val == no ? ' ' : '*');
yann@1
   535
				else
yann@943
   536
					item_make("-%c-", val == no ? ' ' : '*');
yann@1
   537
				item_set_tag('t');
yann@1
   538
				item_set_data(menu);
yann@1
   539
				break;
yann@1
   540
			case S_TRISTATE:
yann@1
   541
				switch (val) {
yann@1
   542
				case yes: ch = '*'; break;
yann@1
   543
				case mod: ch = 'M'; break;
yann@1
   544
				default:  ch = ' '; break;
yann@1
   545
				}
yann@943
   546
				if (sym_is_changable(sym)) {
yann@943
   547
					if (sym->rev_dep.tri == mod)
yann@943
   548
						item_make("{%c}", ch);
yann@943
   549
					else
yann@943
   550
						item_make("<%c>", ch);
yann@943
   551
				} else
yann@943
   552
					item_make("-%c-", ch);
yann@1
   553
				item_set_tag('t');
yann@1
   554
				item_set_data(menu);
yann@1
   555
				break;
yann@1
   556
			default:
yann@1
   557
				tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
yann@1
   558
				item_make("(%s)", sym_get_string_value(sym));
yann@1
   559
				tmp = indent - tmp + 4;
yann@1
   560
				if (tmp < 0)
yann@1
   561
					tmp = 0;
yann@943
   562
				item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)),
yann@1
   563
					     (sym_has_value(sym) || !sym_is_changable(sym)) ?
yann@943
   564
					     "" : _(" (NEW)"));
yann@1
   565
				item_set_tag('s');
yann@1
   566
				item_set_data(menu);
yann@1
   567
				goto conf_childs;
yann@1
   568
			}
yann@1
   569
		}
yann@943
   570
		item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)),
yann@1
   571
			  (sym_has_value(sym) || !sym_is_changable(sym)) ?
yann@943
   572
			  "" : _(" (NEW)"));
yann@1
   573
		if (menu->prompt->type == P_MENU) {
yann@1
   574
			item_add_str("  --->");
yann@1
   575
			return;
yann@1
   576
		}
yann@1
   577
	}
yann@1
   578
yann@1
   579
conf_childs:
yann@1
   580
	indent += doint;
yann@1
   581
	for (child = menu->list; child; child = child->next)
yann@1
   582
		build_conf(child);
yann@1
   583
	indent -= doint;
yann@1
   584
}
yann@1
   585
yann@1
   586
static void conf(struct menu *menu)
yann@1
   587
{
yann@1
   588
	struct menu *submenu;
yann@1
   589
	const char *prompt = menu_get_prompt(menu);
yann@1
   590
	struct symbol *sym;
yann@1
   591
	struct menu *active_menu = NULL;
yann@1
   592
	int res;
yann@1
   593
	int s_scroll = 0;
yann@1
   594
yann@1
   595
	while (1) {
yann@1
   596
		item_reset();
yann@1
   597
		current_menu = menu;
yann@1
   598
		build_conf(menu);
yann@1
   599
		if (!child_count)
yann@1
   600
			break;
yann@1
   601
		if (menu == &rootmenu) {
yann@1
   602
			item_make("--- ");
yann@1
   603
			item_set_tag(':');
yann@1
   604
			item_make(_("    Load an Alternate Configuration File"));
yann@1
   605
			item_set_tag('L');
yann@1
   606
			item_make(_("    Save an Alternate Configuration File"));
yann@1
   607
			item_set_tag('S');
yann@1
   608
		}
yann@1
   609
		dialog_clear();
yann@943
   610
		res = dialog_menu(prompt ? _(prompt) : _("Main Menu"),
yann@1
   611
				  _(menu_instructions),
yann@1
   612
				  active_menu, &s_scroll);
yann@1
   613
		if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
yann@1
   614
			break;
yann@1
   615
		if (!item_activate_selected())
yann@1
   616
			continue;
yann@1
   617
		if (!item_tag())
yann@1
   618
			continue;
yann@1
   619
yann@1
   620
		submenu = item_data();
yann@1
   621
		active_menu = item_data();
yann@1
   622
		if (submenu)
yann@1
   623
			sym = submenu->sym;
yann@1
   624
		else
yann@1
   625
			sym = NULL;
yann@1
   626
yann@1
   627
		switch (res) {
yann@1
   628
		case 0:
yann@1
   629
			switch (item_tag()) {
yann@1
   630
			case 'm':
yann@1
   631
				if (single_menu_mode)
yann@1
   632
					submenu->data = (void *) (long) !submenu->data;
yann@1
   633
				else
yann@1
   634
					conf(submenu);
yann@1
   635
				break;
yann@1
   636
			case 't':
yann@1
   637
				if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
yann@1
   638
					conf_choice(submenu);
yann@1
   639
				else if (submenu->prompt->type == P_MENU)
yann@1
   640
					conf(submenu);
yann@1
   641
				break;
yann@1
   642
			case 's':
yann@1
   643
				conf_string(submenu);
yann@1
   644
				break;
yann@1
   645
			case 'L':
yann@1
   646
				conf_load();
yann@1
   647
				break;
yann@1
   648
			case 'S':
yann@1
   649
				conf_save();
yann@1
   650
				break;
yann@1
   651
			}
yann@1
   652
			break;
yann@1
   653
		case 2:
yann@1
   654
			if (sym)
yann@1
   655
				show_help(submenu);
yann@1
   656
			else
yann@943
   657
				show_helptext(_("README"), _(mconf_readme));
yann@1
   658
			break;
yann@1
   659
		case 3:
yann@1
   660
			if (item_is_tag('t')) {
yann@1
   661
				if (sym_set_tristate_value(sym, yes))
yann@1
   662
					break;
yann@1
   663
				if (sym_set_tristate_value(sym, mod))
yann@1
   664
					show_textbox(NULL, setmod_text, 6, 74);
yann@1
   665
			}
yann@1
   666
			break;
yann@1
   667
		case 4:
yann@1
   668
			if (item_is_tag('t'))
yann@1
   669
				sym_set_tristate_value(sym, no);
yann@1
   670
			break;
yann@1
   671
		case 5:
yann@1
   672
			if (item_is_tag('t'))
yann@1
   673
				sym_set_tristate_value(sym, mod);
yann@1
   674
			break;
yann@1
   675
		case 6:
yann@1
   676
			if (item_is_tag('t'))
yann@1
   677
				sym_toggle_tristate_value(sym);
yann@1
   678
			else if (item_is_tag('m'))
yann@1
   679
				conf(submenu);
yann@1
   680
			break;
yann@1
   681
		case 7:
yann@1
   682
			search_conf();
yann@1
   683
			break;
yann@1
   684
		}
yann@1
   685
	}
yann@1
   686
}
yann@1
   687
yann@1
   688
static void show_textbox(const char *title, const char *text, int r, int c)
yann@1
   689
{
yann@1
   690
	dialog_clear();
yann@1
   691
	dialog_textbox(title, text, r, c);
yann@1
   692
}
yann@1
   693
yann@1
   694
static void show_helptext(const char *title, const char *text)
yann@1
   695
{
yann@1
   696
	show_textbox(title, text, 0, 0);
yann@1
   697
}
yann@1
   698
yann@1
   699
static void show_help(struct menu *menu)
yann@1
   700
{
yann@1
   701
	struct gstr help = str_new();
yann@1
   702
	struct symbol *sym = menu->sym;
yann@1
   703
yann@943
   704
	if (menu_has_help(menu))
yann@1
   705
	{
yann@1
   706
		if (sym->name) {
yann@1
   707
			str_printf(&help, "CT_%s:\n\n", sym->name);
yann@943
   708
			str_append(&help, _(menu_get_help(menu)));
yann@1
   709
			str_append(&help, "\n");
yann@1
   710
		}
yann@1
   711
	} else {
yann@1
   712
		str_append(&help, nohelp_text);
yann@1
   713
	}
yann@1
   714
	get_symbol_str(&help, sym);
yann@943
   715
	show_helptext(_(menu_get_prompt(menu)), str_get(&help));
yann@1
   716
	str_free(&help);
yann@1
   717
}
yann@1
   718
yann@1
   719
static void conf_choice(struct menu *menu)
yann@1
   720
{
yann@943
   721
	const char *prompt = _(menu_get_prompt(menu));
yann@1
   722
	struct menu *child;
yann@1
   723
	struct symbol *active;
yann@1
   724
yann@1
   725
	active = sym_get_choice_value(menu->sym);
yann@1
   726
	while (1) {
yann@1
   727
		int res;
yann@1
   728
		int selected;
yann@1
   729
		item_reset();
yann@1
   730
yann@1
   731
		current_menu = menu;
yann@1
   732
		for (child = menu->list; child; child = child->next) {
yann@1
   733
			if (!menu_is_visible(child))
yann@1
   734
				continue;
yann@943
   735
			item_make("%s", _(menu_get_prompt(child)));
yann@1
   736
			item_set_data(child);
yann@1
   737
			if (child->sym == active)
yann@1
   738
				item_set_selected(1);
yann@1
   739
			if (child->sym == sym_get_choice_value(menu->sym))
yann@1
   740
				item_set_tag('X');
yann@1
   741
		}
yann@1
   742
		dialog_clear();
yann@943
   743
		res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"),
yann@1
   744
					_(radiolist_instructions),
yann@1
   745
					 15, 70, 6);
yann@1
   746
		selected = item_activate_selected();
yann@1
   747
		switch (res) {
yann@1
   748
		case 0:
yann@1
   749
			if (selected) {
yann@1
   750
				child = item_data();
yann@1
   751
				sym_set_tristate_value(child->sym, yes);
yann@1
   752
			}
yann@1
   753
			return;
yann@1
   754
		case 1:
yann@1
   755
			if (selected) {
yann@1
   756
				child = item_data();
yann@1
   757
				show_help(child);
yann@1
   758
				active = child->sym;
yann@1
   759
			} else
yann@1
   760
				show_help(menu);
yann@1
   761
			break;
yann@1
   762
		case KEY_ESC:
yann@1
   763
			return;
yann@1
   764
		case -ERRDISPLAYTOOSMALL:
yann@1
   765
			return;
yann@1
   766
		}
yann@1
   767
	}
yann@1
   768
}
yann@1
   769
yann@1
   770
static void conf_string(struct menu *menu)
yann@1
   771
{
yann@1
   772
	const char *prompt = menu_get_prompt(menu);
yann@1
   773
yann@1
   774
	while (1) {
yann@1
   775
		int res;
yann@943
   776
		const char *heading;
yann@1
   777
yann@1
   778
		switch (sym_get_type(menu->sym)) {
yann@1
   779
		case S_INT:
yann@1
   780
			heading = _(inputbox_instructions_int);
yann@1
   781
			break;
yann@1
   782
		case S_HEX:
yann@1
   783
			heading = _(inputbox_instructions_hex);
yann@1
   784
			break;
yann@1
   785
		case S_STRING:
yann@1
   786
			heading = _(inputbox_instructions_string);
yann@1
   787
			break;
yann@1
   788
		default:
yann@943
   789
			heading = _("Internal mconf error!");
yann@1
   790
		}
yann@1
   791
		dialog_clear();
yann@943
   792
		res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"),
yann@1
   793
				      heading, 10, 75,
yann@1
   794
				      sym_get_string_value(menu->sym));
yann@1
   795
		switch (res) {
yann@1
   796
		case 0:
yann@1
   797
			if (sym_set_string_value(menu->sym, dialog_input_result))
yann@1
   798
				return;
yann@1
   799
			show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
yann@1
   800
			break;
yann@1
   801
		case 1:
yann@1
   802
			show_help(menu);
yann@1
   803
			break;
yann@1
   804
		case KEY_ESC:
yann@1
   805
			return;
yann@1
   806
		}
yann@1
   807
	}
yann@1
   808
}
yann@1
   809
yann@1
   810
static void conf_load(void)
yann@1
   811
{
yann@1
   812
yann@1
   813
	while (1) {
yann@1
   814
		int res;
yann@1
   815
		dialog_clear();
yann@1
   816
		res = dialog_inputbox(NULL, load_config_text,
yann@1
   817
				      11, 55, filename);
yann@1
   818
		switch(res) {
yann@1
   819
		case 0:
yann@1
   820
			if (!dialog_input_result[0])
yann@1
   821
				return;
yann@943
   822
			if (!conf_read(dialog_input_result)) {
yann@943
   823
				set_config_filename(dialog_input_result);
yann@943
   824
				sym_set_change_count(1);
yann@1
   825
				return;
yann@943
   826
			}
yann@1
   827
			show_textbox(NULL, _("File does not exist!"), 5, 38);
yann@1
   828
			break;
yann@1
   829
		case 1:
yann@1
   830
			show_helptext(_("Load Alternate Configuration"), load_config_help);
yann@1
   831
			break;
yann@1
   832
		case KEY_ESC:
yann@1
   833
			return;
yann@1
   834
		}
yann@1
   835
	}
yann@1
   836
}
yann@1
   837
yann@1
   838
static void conf_save(void)
yann@1
   839
{
yann@1
   840
	while (1) {
yann@1
   841
		int res;
yann@1
   842
		dialog_clear();
yann@1
   843
		res = dialog_inputbox(NULL, save_config_text,
yann@1
   844
				      11, 55, filename);
yann@1
   845
		switch(res) {
yann@1
   846
		case 0:
yann@1
   847
			if (!dialog_input_result[0])
yann@1
   848
				return;
yann@943
   849
			if (!conf_write(dialog_input_result)) {
yann@943
   850
				set_config_filename(dialog_input_result);
yann@1
   851
				return;
yann@943
   852
			}
yann@1
   853
			show_textbox(NULL, _("Can't create file!  Probably a nonexistent directory."), 5, 60);
yann@1
   854
			break;
yann@1
   855
		case 1:
yann@1
   856
			show_helptext(_("Save Alternate Configuration"), save_config_help);
yann@1
   857
			break;
yann@1
   858
		case KEY_ESC:
yann@1
   859
			return;
yann@1
   860
		}
yann@1
   861
	}
yann@1
   862
}
yann@1
   863
yann@1
   864
int main(int ac, char **av)
yann@1
   865
{
yann@943
   866
	int saved_x, saved_y;
yann@1
   867
	char *mode;
yann@1
   868
	int res;
yann@1
   869
yann@1
   870
	setlocale(LC_ALL, "");
yann@1
   871
	bindtextdomain(PACKAGE, LOCALEDIR);
yann@1
   872
	textdomain(PACKAGE);
yann@1
   873
yann@39
   874
	conf_parse(av[1]);
yann@1
   875
	conf_read(NULL);
yann@1
   876
yann@1
   877
	mode = getenv("MENUCONFIG_MODE");
yann@1
   878
	if (mode) {
yann@1
   879
		if (!strcasecmp(mode, "single_menu"))
yann@1
   880
			single_menu_mode = 1;
yann@1
   881
	}
yann@1
   882
yann@943
   883
	getyx(stdscr, saved_y, saved_x);
yann@943
   884
	if (init_dialog(NULL)) {
yann@943
   885
		fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
yann@943
   886
		fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
yann@943
   887
		return 1;
yann@943
   888
	}
yann@943
   889
yann@943
   890
	set_config_filename(conf_get_configname());
yann@1
   891
	do {
yann@1
   892
		conf(&rootmenu);
yann@1
   893
		dialog_clear();
yann@39
   894
		if (conf_get_changed())
yann@39
   895
			res = dialog_yesno(NULL,
yann@39
   896
					   _("Do you wish to save your "
yann@943
   897
					     "new " PACKAGE " configuration?\n"
yann@39
   898
					     "<ESC><ESC> to continue."),
yann@39
   899
					   6, 60);
yann@39
   900
		else
yann@39
   901
			res = -1;
yann@1
   902
	} while (res == KEY_ESC);
yann@943
   903
	end_dialog(saved_x, saved_y);
yann@39
   904
yann@39
   905
	switch (res) {
yann@39
   906
	case 0:
yann@943
   907
		if (conf_write(filename)) {
yann@943
   908
			fprintf(stderr, _("\n\n"
yann@943
   909
				"Error during writing of " PACKAGE " configuration.\n"
yann@943
   910
				"Your " PACKAGE " configuration changes were NOT saved."
yann@943
   911
				"\n\n"));
yann@1
   912
			return 1;
yann@1
   913
		}
yann@39
   914
	case -1:
yann@39
   915
		break;
yann@39
   916
	default:
yann@943
   917
		fprintf(stderr, _("Your configuration changes were NOT saved.\n"));
yann@1
   918
	}
yann@1
   919
yann@1
   920
	return 0;
yann@1
   921
}
yann@943
   922