kconfig/mconf.c
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Mon Aug 23 23:18:49 2010 +0200 (2010-08-23)
changeset 2099 1bb063c8a0ca
parent 94 f32c4f663805
child 2448 a103abae1560
permissions -rw-r--r--
complibs: noone is using companion libs on the target; nuke them

As there's no longer any user of the companion libraries on the
target, nuke the build for the target.

Well, at least, there's libelf that's still needed by ltrace, so
we keep it.

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@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