1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/kconfig/mconf.c Sun Mar 04 22:56:04 2007 +0000
1.3 @@ -0,0 +1,919 @@
1.4 +/*
1.5 + * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
1.6 + * Released under the terms of the GNU GPL v2.0.
1.7 + *
1.8 + * Introduced single menu mode (show all sub-menus in one large tree).
1.9 + * 2002-11-06 Petr Baudis <pasky@ucw.cz>
1.10 + *
1.11 + * i18n, 2005, Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1.12 + */
1.13 +
1.14 +#include <sys/ioctl.h>
1.15 +#include <sys/wait.h>
1.16 +#include <ctype.h>
1.17 +#include <errno.h>
1.18 +#include <fcntl.h>
1.19 +#include <limits.h>
1.20 +#include <signal.h>
1.21 +#include <stdarg.h>
1.22 +#include <stdlib.h>
1.23 +#include <string.h>
1.24 +#include <termios.h>
1.25 +#include <unistd.h>
1.26 +#include <locale.h>
1.27 +
1.28 +#define LKC_DIRECT_LINK
1.29 +#include "lkc.h"
1.30 +#include "lxdialog/dialog.h"
1.31 +
1.32 +static char menu_backtitle[128];
1.33 +static const char mconf_readme[] = N_(
1.34 +"Overview\n"
1.35 +"--------\n"
1.36 +"Some kernel features may be built directly into the kernel.\n"
1.37 +"Some may be made into loadable runtime modules. Some features\n"
1.38 +"may be completely removed altogether. There are also certain\n"
1.39 +"kernel parameters which are not really features, but must be\n"
1.40 +"entered in as decimal or hexadecimal numbers or possibly text.\n"
1.41 +"\n"
1.42 +"Menu items beginning with [*], <M> or [ ] represent features\n"
1.43 +"configured to be built in, modularized or removed respectively.\n"
1.44 +"Pointed brackets <> represent module capable features.\n"
1.45 +"\n"
1.46 +"To change any of these features, highlight it with the cursor\n"
1.47 +"keys and press <Y> to build it in, <M> to make it a module or\n"
1.48 +"<N> to removed it. You may also press the <Space Bar> to cycle\n"
1.49 +"through the available options (ie. Y->N->M->Y).\n"
1.50 +"\n"
1.51 +"Some additional keyboard hints:\n"
1.52 +"\n"
1.53 +"Menus\n"
1.54 +"----------\n"
1.55 +"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
1.56 +" you wish to change or submenu wish to select and press <Enter>.\n"
1.57 +" Submenus are designated by \"--->\".\n"
1.58 +"\n"
1.59 +" Shortcut: Press the option's highlighted letter (hotkey).\n"
1.60 +" Pressing a hotkey more than once will sequence\n"
1.61 +" through all visible items which use that hotkey.\n"
1.62 +"\n"
1.63 +" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
1.64 +" unseen options into view.\n"
1.65 +"\n"
1.66 +"o To exit a menu use the cursor keys to highlight the <Exit> button\n"
1.67 +" and press <ENTER>.\n"
1.68 +"\n"
1.69 +" Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\n"
1.70 +" using those letters. You may press a single <ESC>, but\n"
1.71 +" there is a delayed response which you may find annoying.\n"
1.72 +"\n"
1.73 +" Also, the <TAB> and cursor keys will cycle between <Select>,\n"
1.74 +" <Exit> and <Help>\n"
1.75 +"\n"
1.76 +"o To get help with an item, use the cursor keys to highlight <Help>\n"
1.77 +" and Press <ENTER>.\n"
1.78 +"\n"
1.79 +" Shortcut: Press <H> or <?>.\n"
1.80 +"\n"
1.81 +"\n"
1.82 +"Radiolists (Choice lists)\n"
1.83 +"-----------\n"
1.84 +"o Use the cursor keys to select the option you wish to set and press\n"
1.85 +" <S> or the <SPACE BAR>.\n"
1.86 +"\n"
1.87 +" Shortcut: Press the first letter of the option you wish to set then\n"
1.88 +" press <S> or <SPACE BAR>.\n"
1.89 +"\n"
1.90 +"o To see available help for the item, use the cursor keys to highlight\n"
1.91 +" <Help> and Press <ENTER>.\n"
1.92 +"\n"
1.93 +" Shortcut: Press <H> or <?>.\n"
1.94 +"\n"
1.95 +" Also, the <TAB> and cursor keys will cycle between <Select> and\n"
1.96 +" <Help>\n"
1.97 +"\n"
1.98 +"\n"
1.99 +"Data Entry\n"
1.100 +"-----------\n"
1.101 +"o Enter the requested information and press <ENTER>\n"
1.102 +" If you are entering hexadecimal values, it is not necessary to\n"
1.103 +" add the '0x' prefix to the entry.\n"
1.104 +"\n"
1.105 +"o For help, use the <TAB> or cursor keys to highlight the help option\n"
1.106 +" and press <ENTER>. You can try <TAB><H> as well.\n"
1.107 +"\n"
1.108 +"\n"
1.109 +"Text Box (Help Window)\n"
1.110 +"--------\n"
1.111 +"o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
1.112 +" keys h,j,k,l function here as do <SPACE BAR> and <B> for those\n"
1.113 +" who are familiar with less and lynx.\n"
1.114 +"\n"
1.115 +"o Press <E>, <X>, <Enter> or <Esc><Esc> to exit.\n"
1.116 +"\n"
1.117 +"\n"
1.118 +"Alternate Configuration Files\n"
1.119 +"-----------------------------\n"
1.120 +"Menuconfig supports the use of alternate configuration files for\n"
1.121 +"those who, for various reasons, find it necessary to switch\n"
1.122 +"between different kernel configurations.\n"
1.123 +"\n"
1.124 +"At the end of the main menu you will find two options. One is\n"
1.125 +"for saving the current configuration to a file of your choosing.\n"
1.126 +"The other option is for loading a previously saved alternate\n"
1.127 +"configuration.\n"
1.128 +"\n"
1.129 +"Even if you don't use alternate configuration files, but you\n"
1.130 +"find during a Menuconfig session that you have completely messed\n"
1.131 +"up your settings, you may use the \"Load Alternate...\" option to\n"
1.132 +"restore your previously saved settings from \".config\" without\n"
1.133 +"restarting Menuconfig.\n"
1.134 +"\n"
1.135 +"Other information\n"
1.136 +"-----------------\n"
1.137 +"If you use Menuconfig in an XTERM window make sure you have your\n"
1.138 +"$TERM variable set to point to a xterm definition which supports color.\n"
1.139 +"Otherwise, Menuconfig will look rather bad. Menuconfig will not\n"
1.140 +"display correctly in a RXVT window because rxvt displays only one\n"
1.141 +"intensity of color, bright.\n"
1.142 +"\n"
1.143 +"Menuconfig will display larger menus on screens or xterms which are\n"
1.144 +"set to display more than the standard 25 row by 80 column geometry.\n"
1.145 +"In order for this to work, the \"stty size\" command must be able to\n"
1.146 +"display the screen's current row and column geometry. I STRONGLY\n"
1.147 +"RECOMMEND that you make sure you do NOT have the shell variables\n"
1.148 +"LINES and COLUMNS exported into your environment. Some distributions\n"
1.149 +"export those variables via /etc/profile. Some ncurses programs can\n"
1.150 +"become confused when those variables (LINES & COLUMNS) don't reflect\n"
1.151 +"the true screen size.\n"
1.152 +"\n"
1.153 +"Optional personality available\n"
1.154 +"------------------------------\n"
1.155 +"If you prefer to have all of the kernel options listed in a single\n"
1.156 +"menu, rather than the default multimenu hierarchy, run the menuconfig\n"
1.157 +"with MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
1.158 +"\n"
1.159 +"make MENUCONFIG_MODE=single_menu menuconfig\n"
1.160 +"\n"
1.161 +"<Enter> will then unroll the appropriate category, or enfold it if it\n"
1.162 +"is already unrolled.\n"
1.163 +"\n"
1.164 +"Note that this mode can eventually be a little more CPU expensive\n"
1.165 +"(especially with a larger number of unrolled categories) than the\n"
1.166 +"default mode.\n"
1.167 +"\n"
1.168 +"Different color themes available\n"
1.169 +"--------------------------------\n"
1.170 +"It is possible to select different color themes using the variable\n"
1.171 +"MENUCONFIG_COLOR. To select a theme use:\n"
1.172 +"\n"
1.173 +"make MENUCONFIG_COLOR=<theme> menuconfig\n"
1.174 +"\n"
1.175 +"Available themes are\n"
1.176 +" mono => selects colors suitable for monochrome displays\n"
1.177 +" blackbg => selects a color scheme with black background\n"
1.178 +" classic => theme with blue background. The classic look\n"
1.179 +" bluetitle => a LCD friendly version of classic. (default)\n"
1.180 +"\n"),
1.181 +menu_instructions[] = N_(
1.182 + "Arrow keys navigate the menu. "
1.183 + "<Enter> selects submenus --->. "
1.184 + "Highlighted letters are hotkeys. "
1.185 + "Pressing <Y> includes, <N> excludes, <M> modularizes features. "
1.186 + "Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
1.187 + "Legend: [*] built-in [ ] excluded <M> module < > module capable"),
1.188 +radiolist_instructions[] = N_(
1.189 + "Use the arrow keys to navigate this window or "
1.190 + "press the hotkey of the item you wish to select "
1.191 + "followed by the <SPACE BAR>. "
1.192 + "Press <?> for additional information about this option."),
1.193 +inputbox_instructions_int[] = N_(
1.194 + "Please enter a decimal value. "
1.195 + "Fractions will not be accepted. "
1.196 + "Use the <TAB> key to move from the input field to the buttons below it."),
1.197 +inputbox_instructions_hex[] = N_(
1.198 + "Please enter a hexadecimal value. "
1.199 + "Use the <TAB> key to move from the input field to the buttons below it."),
1.200 +inputbox_instructions_string[] = N_(
1.201 + "Please enter a string value. "
1.202 + "Use the <TAB> key to move from the input field to the buttons below it."),
1.203 +setmod_text[] = N_(
1.204 + "This feature depends on another which has been configured as a module.\n"
1.205 + "As a result, this feature will be built as a module."),
1.206 +nohelp_text[] = N_(
1.207 + "There is no help available for this kernel option.\n"),
1.208 +load_config_text[] = N_(
1.209 + "Enter the name of the configuration file you wish to load. "
1.210 + "Accept the name shown to restore the configuration you "
1.211 + "last retrieved. Leave blank to abort."),
1.212 +load_config_help[] = N_(
1.213 + "\n"
1.214 + "For various reasons, one may wish to keep several different kernel\n"
1.215 + "configurations available on a single machine.\n"
1.216 + "\n"
1.217 + "If you have saved a previous configuration in a file other than the\n"
1.218 + "kernel's default, entering the name of the file here will allow you\n"
1.219 + "to modify that configuration.\n"
1.220 + "\n"
1.221 + "If you are uncertain, then you have probably never used alternate\n"
1.222 + "configuration files. You should therefor leave this blank to abort.\n"),
1.223 +save_config_text[] = N_(
1.224 + "Enter a filename to which this configuration should be saved "
1.225 + "as an alternate. Leave blank to abort."),
1.226 +save_config_help[] = N_(
1.227 + "\n"
1.228 + "For various reasons, one may wish to keep different kernel\n"
1.229 + "configurations available on a single machine.\n"
1.230 + "\n"
1.231 + "Entering a file name here will allow you to later retrieve, modify\n"
1.232 + "and use the current configuration as an alternate to whatever\n"
1.233 + "configuration options you have selected at that time.\n"
1.234 + "\n"
1.235 + "If you are uncertain what all this means then you should probably\n"
1.236 + "leave this blank.\n"),
1.237 +search_help[] = N_(
1.238 + "\n"
1.239 + "Search for CT_ symbols and display their relations.\n"
1.240 + "Regular expressions are allowed.\n"
1.241 + "Example: search for \"^FOO\"\n"
1.242 + "Result:\n"
1.243 + "-----------------------------------------------------------------\n"
1.244 + "Symbol: FOO [=m]\n"
1.245 + "Prompt: Foo bus is used to drive the bar HW\n"
1.246 + "Defined at drivers/pci/Kconfig:47\n"
1.247 + "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
1.248 + "Location:\n"
1.249 + " -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
1.250 + " -> PCI support (PCI [=y])\n"
1.251 + " -> PCI access mode (<choice> [=y])\n"
1.252 + "Selects: LIBCRC32\n"
1.253 + "Selected by: BAR\n"
1.254 + "-----------------------------------------------------------------\n"
1.255 + "o The line 'Prompt:' shows the text used in the menu structure for\n"
1.256 + " this CT_ symbol\n"
1.257 + "o The 'Defined at' line tell at what file / line number the symbol\n"
1.258 + " is defined\n"
1.259 + "o The 'Depends on:' line tell what symbols needs to be defined for\n"
1.260 + " this symbol to be visible in the menu (selectable)\n"
1.261 + "o The 'Location:' lines tell where in the menu structure this symbol\n"
1.262 + " is located\n"
1.263 + " A location followed by a [=y] indicate that this is a selectable\n"
1.264 + " menu item - and current value is displayed inside brackets.\n"
1.265 + "o The 'Selects:' line tell what symbol will be automatically\n"
1.266 + " selected if this symbol is selected (y or m)\n"
1.267 + "o The 'Selected by' line tell what symbol has selected this symbol\n"
1.268 + "\n"
1.269 + "Only relevant lines are shown.\n"
1.270 + "\n\n"
1.271 + "Search examples:\n"
1.272 + "Examples: USB => find all CT_ symbols containing USB\n"
1.273 + " ^USB => find all CT_ symbols starting with USB\n"
1.274 + " USB$ => find all CT_ symbols ending with USB\n"
1.275 + "\n");
1.276 +
1.277 +static char filename[PATH_MAX+1] = ".config";
1.278 +static int indent;
1.279 +static struct termios ios_org;
1.280 +static int rows = 0, cols = 0;
1.281 +static struct menu *current_menu;
1.282 +static int child_count;
1.283 +static int single_menu_mode;
1.284 +
1.285 +static void conf(struct menu *menu);
1.286 +static void conf_choice(struct menu *menu);
1.287 +static void conf_string(struct menu *menu);
1.288 +static void conf_load(void);
1.289 +static void conf_save(void);
1.290 +static void show_textbox(const char *title, const char *text, int r, int c);
1.291 +static void show_helptext(const char *title, const char *text);
1.292 +static void show_help(struct menu *menu);
1.293 +
1.294 +static void init_wsize(void)
1.295 +{
1.296 + struct winsize ws;
1.297 + char *env;
1.298 +
1.299 + if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &ws)) {
1.300 + rows = ws.ws_row;
1.301 + cols = ws.ws_col;
1.302 + }
1.303 +
1.304 + if (!rows) {
1.305 + env = getenv("LINES");
1.306 + if (env)
1.307 + rows = atoi(env);
1.308 + if (!rows)
1.309 + rows = 24;
1.310 + }
1.311 + if (!cols) {
1.312 + env = getenv("COLUMNS");
1.313 + if (env)
1.314 + cols = atoi(env);
1.315 + if (!cols)
1.316 + cols = 80;
1.317 + }
1.318 +
1.319 + if (rows < 19 || cols < 80) {
1.320 + fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
1.321 + fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
1.322 + exit(1);
1.323 + }
1.324 +
1.325 + rows -= 4;
1.326 + cols -= 5;
1.327 +}
1.328 +
1.329 +static void get_prompt_str(struct gstr *r, struct property *prop)
1.330 +{
1.331 + int i, j;
1.332 + struct menu *submenu[8], *menu;
1.333 +
1.334 + str_printf(r, "Prompt: %s\n", prop->text);
1.335 + str_printf(r, " Defined at %s:%d\n", prop->menu->file->name,
1.336 + prop->menu->lineno);
1.337 + if (!expr_is_yes(prop->visible.expr)) {
1.338 + str_append(r, " Depends on: ");
1.339 + expr_gstr_print(prop->visible.expr, r);
1.340 + str_append(r, "\n");
1.341 + }
1.342 + menu = prop->menu->parent;
1.343 + for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
1.344 + submenu[i++] = menu;
1.345 + if (i > 0) {
1.346 + str_printf(r, " Location:\n");
1.347 + for (j = 4; --i >= 0; j += 2) {
1.348 + menu = submenu[i];
1.349 + str_printf(r, "%*c-> %s", j, ' ', menu_get_prompt(menu));
1.350 + if (menu->sym) {
1.351 + str_printf(r, " (%s [=%s])", menu->sym->name ?
1.352 + menu->sym->name : "<choice>",
1.353 + sym_get_string_value(menu->sym));
1.354 + }
1.355 + str_append(r, "\n");
1.356 + }
1.357 + }
1.358 +}
1.359 +
1.360 +static void get_symbol_str(struct gstr *r, struct symbol *sym)
1.361 +{
1.362 + bool hit;
1.363 + struct property *prop;
1.364 +
1.365 + str_printf(r, "Symbol: %s [=%s]\n", sym->name,
1.366 + sym_get_string_value(sym));
1.367 + for_all_prompts(sym, prop)
1.368 + get_prompt_str(r, prop);
1.369 + hit = false;
1.370 + for_all_properties(sym, prop, P_SELECT) {
1.371 + if (!hit) {
1.372 + str_append(r, " Selects: ");
1.373 + hit = true;
1.374 + } else
1.375 + str_printf(r, " && ");
1.376 + expr_gstr_print(prop->expr, r);
1.377 + }
1.378 + if (hit)
1.379 + str_append(r, "\n");
1.380 + if (sym->rev_dep.expr) {
1.381 + str_append(r, " Selected by: ");
1.382 + expr_gstr_print(sym->rev_dep.expr, r);
1.383 + str_append(r, "\n");
1.384 + }
1.385 + str_append(r, "\n\n");
1.386 +}
1.387 +
1.388 +static struct gstr get_relations_str(struct symbol **sym_arr)
1.389 +{
1.390 + struct symbol *sym;
1.391 + struct gstr res = str_new();
1.392 + int i;
1.393 +
1.394 + for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
1.395 + get_symbol_str(&res, sym);
1.396 + if (!i)
1.397 + str_append(&res, "No matches found.\n");
1.398 + return res;
1.399 +}
1.400 +
1.401 +static void search_conf(void)
1.402 +{
1.403 + struct symbol **sym_arr;
1.404 + struct gstr res;
1.405 + int dres;
1.406 +again:
1.407 + dialog_clear();
1.408 + dres = dialog_inputbox(_("Search Configuration Parameter"),
1.409 + _("Enter CT_ (sub)string to search for (omit CT_)"),
1.410 + 10, 75, "");
1.411 + switch (dres) {
1.412 + case 0:
1.413 + break;
1.414 + case 1:
1.415 + show_helptext(_("Search Configuration"), search_help);
1.416 + goto again;
1.417 + default:
1.418 + return;
1.419 + }
1.420 +
1.421 + sym_arr = sym_re_search(dialog_input_result);
1.422 + res = get_relations_str(sym_arr);
1.423 + free(sym_arr);
1.424 + show_textbox(_("Search Results"), str_get(&res), 0, 0);
1.425 + str_free(&res);
1.426 +}
1.427 +
1.428 +static void build_conf(struct menu *menu)
1.429 +{
1.430 + struct symbol *sym;
1.431 + struct property *prop;
1.432 + struct menu *child;
1.433 + int type, tmp, doint = 2;
1.434 + tristate val;
1.435 + char ch;
1.436 +
1.437 + if (!menu_is_visible(menu))
1.438 + return;
1.439 +
1.440 + sym = menu->sym;
1.441 + prop = menu->prompt;
1.442 + if (!sym) {
1.443 + if (prop && menu != current_menu) {
1.444 + const char *prompt = menu_get_prompt(menu);
1.445 + switch (prop->type) {
1.446 + case P_MENU:
1.447 + child_count++;
1.448 + if (single_menu_mode) {
1.449 + item_make("%s%*c%s",
1.450 + menu->data ? "-->" : "++>",
1.451 + indent + 1, ' ', prompt);
1.452 + } else
1.453 + item_make(" %*c%s --->", indent + 1, ' ', prompt);
1.454 +
1.455 + item_set_tag('m');
1.456 + item_set_data(menu);
1.457 + if (single_menu_mode && menu->data)
1.458 + goto conf_childs;
1.459 + return;
1.460 + default:
1.461 + if (prompt) {
1.462 + child_count++;
1.463 + item_make("---%*c%s", indent + 1, ' ', prompt);
1.464 + item_set_tag(':');
1.465 + item_set_data(menu);
1.466 + }
1.467 + }
1.468 + } else
1.469 + doint = 0;
1.470 + goto conf_childs;
1.471 + }
1.472 +
1.473 + type = sym_get_type(sym);
1.474 + if (sym_is_choice(sym)) {
1.475 + struct symbol *def_sym = sym_get_choice_value(sym);
1.476 + struct menu *def_menu = NULL;
1.477 +
1.478 + child_count++;
1.479 + for (child = menu->list; child; child = child->next) {
1.480 + if (menu_is_visible(child) && child->sym == def_sym)
1.481 + def_menu = child;
1.482 + }
1.483 +
1.484 + val = sym_get_tristate_value(sym);
1.485 + if (sym_is_changable(sym)) {
1.486 + switch (type) {
1.487 + case S_BOOLEAN:
1.488 + item_make("[%c]", val == no ? ' ' : '*');
1.489 + break;
1.490 + case S_TRISTATE:
1.491 + switch (val) {
1.492 + case yes: ch = '*'; break;
1.493 + case mod: ch = 'M'; break;
1.494 + default: ch = ' '; break;
1.495 + }
1.496 + item_make("<%c>", ch);
1.497 + break;
1.498 + }
1.499 + item_set_tag('t');
1.500 + item_set_data(menu);
1.501 + } else {
1.502 + item_make(" ");
1.503 + item_set_tag(def_menu ? 't' : ':');
1.504 + item_set_data(menu);
1.505 + }
1.506 +
1.507 + item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
1.508 + if (val == yes) {
1.509 + if (def_menu) {
1.510 + item_add_str(" (%s)", menu_get_prompt(def_menu));
1.511 + item_add_str(" --->");
1.512 + if (def_menu->list) {
1.513 + indent += 2;
1.514 + build_conf(def_menu);
1.515 + indent -= 2;
1.516 + }
1.517 + }
1.518 + return;
1.519 + }
1.520 + } else {
1.521 + if (menu == current_menu) {
1.522 + item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
1.523 + item_set_tag(':');
1.524 + item_set_data(menu);
1.525 + goto conf_childs;
1.526 + }
1.527 + child_count++;
1.528 + val = sym_get_tristate_value(sym);
1.529 + if (sym_is_choice_value(sym) && val == yes) {
1.530 + item_make(" ");
1.531 + item_set_tag(':');
1.532 + item_set_data(menu);
1.533 + } else {
1.534 + switch (type) {
1.535 + case S_BOOLEAN:
1.536 + if (sym_is_changable(sym))
1.537 + item_make("[%c]", val == no ? ' ' : '*');
1.538 + else
1.539 + item_make("---");
1.540 + item_set_tag('t');
1.541 + item_set_data(menu);
1.542 + break;
1.543 + case S_TRISTATE:
1.544 + switch (val) {
1.545 + case yes: ch = '*'; break;
1.546 + case mod: ch = 'M'; break;
1.547 + default: ch = ' '; break;
1.548 + }
1.549 + if (sym_is_changable(sym))
1.550 + item_make("<%c>", ch);
1.551 + else
1.552 + item_make("---");
1.553 + item_set_tag('t');
1.554 + item_set_data(menu);
1.555 + break;
1.556 + default:
1.557 + tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
1.558 + item_make("(%s)", sym_get_string_value(sym));
1.559 + tmp = indent - tmp + 4;
1.560 + if (tmp < 0)
1.561 + tmp = 0;
1.562 + item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
1.563 + (sym_has_value(sym) || !sym_is_changable(sym)) ?
1.564 + "" : " (NEW)");
1.565 + item_set_tag('s');
1.566 + item_set_data(menu);
1.567 + goto conf_childs;
1.568 + }
1.569 + }
1.570 + item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
1.571 + (sym_has_value(sym) || !sym_is_changable(sym)) ?
1.572 + "" : " (NEW)");
1.573 + if (menu->prompt->type == P_MENU) {
1.574 + item_add_str(" --->");
1.575 + return;
1.576 + }
1.577 + }
1.578 +
1.579 +conf_childs:
1.580 + indent += doint;
1.581 + for (child = menu->list; child; child = child->next)
1.582 + build_conf(child);
1.583 + indent -= doint;
1.584 +}
1.585 +
1.586 +static void conf(struct menu *menu)
1.587 +{
1.588 + struct menu *submenu;
1.589 + const char *prompt = menu_get_prompt(menu);
1.590 + struct symbol *sym;
1.591 + struct menu *active_menu = NULL;
1.592 + int res;
1.593 + int s_scroll = 0;
1.594 +
1.595 + while (1) {
1.596 + item_reset();
1.597 + current_menu = menu;
1.598 + build_conf(menu);
1.599 + if (!child_count)
1.600 + break;
1.601 + if (menu == &rootmenu) {
1.602 + item_make("--- ");
1.603 + item_set_tag(':');
1.604 + item_make(_(" Load an Alternate Configuration File"));
1.605 + item_set_tag('L');
1.606 + item_make(_(" Save an Alternate Configuration File"));
1.607 + item_set_tag('S');
1.608 + }
1.609 + dialog_clear();
1.610 + res = dialog_menu(prompt ? prompt : _("Main Menu"),
1.611 + _(menu_instructions),
1.612 + active_menu, &s_scroll);
1.613 + if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
1.614 + break;
1.615 + if (!item_activate_selected())
1.616 + continue;
1.617 + if (!item_tag())
1.618 + continue;
1.619 +
1.620 + submenu = item_data();
1.621 + active_menu = item_data();
1.622 + if (submenu)
1.623 + sym = submenu->sym;
1.624 + else
1.625 + sym = NULL;
1.626 +
1.627 + switch (res) {
1.628 + case 0:
1.629 + switch (item_tag()) {
1.630 + case 'm':
1.631 + if (single_menu_mode)
1.632 + submenu->data = (void *) (long) !submenu->data;
1.633 + else
1.634 + conf(submenu);
1.635 + break;
1.636 + case 't':
1.637 + if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
1.638 + conf_choice(submenu);
1.639 + else if (submenu->prompt->type == P_MENU)
1.640 + conf(submenu);
1.641 + break;
1.642 + case 's':
1.643 + conf_string(submenu);
1.644 + break;
1.645 + case 'L':
1.646 + conf_load();
1.647 + break;
1.648 + case 'S':
1.649 + conf_save();
1.650 + break;
1.651 + }
1.652 + break;
1.653 + case 2:
1.654 + if (sym)
1.655 + show_help(submenu);
1.656 + else
1.657 + show_helptext("README", _(mconf_readme));
1.658 + break;
1.659 + case 3:
1.660 + if (item_is_tag('t')) {
1.661 + if (sym_set_tristate_value(sym, yes))
1.662 + break;
1.663 + if (sym_set_tristate_value(sym, mod))
1.664 + show_textbox(NULL, setmod_text, 6, 74);
1.665 + }
1.666 + break;
1.667 + case 4:
1.668 + if (item_is_tag('t'))
1.669 + sym_set_tristate_value(sym, no);
1.670 + break;
1.671 + case 5:
1.672 + if (item_is_tag('t'))
1.673 + sym_set_tristate_value(sym, mod);
1.674 + break;
1.675 + case 6:
1.676 + if (item_is_tag('t'))
1.677 + sym_toggle_tristate_value(sym);
1.678 + else if (item_is_tag('m'))
1.679 + conf(submenu);
1.680 + break;
1.681 + case 7:
1.682 + search_conf();
1.683 + break;
1.684 + }
1.685 + }
1.686 +}
1.687 +
1.688 +static void show_textbox(const char *title, const char *text, int r, int c)
1.689 +{
1.690 + dialog_clear();
1.691 + dialog_textbox(title, text, r, c);
1.692 +}
1.693 +
1.694 +static void show_helptext(const char *title, const char *text)
1.695 +{
1.696 + show_textbox(title, text, 0, 0);
1.697 +}
1.698 +
1.699 +static void show_help(struct menu *menu)
1.700 +{
1.701 + struct gstr help = str_new();
1.702 + struct symbol *sym = menu->sym;
1.703 +
1.704 + if (sym->help)
1.705 + {
1.706 + if (sym->name) {
1.707 + str_printf(&help, "CT_%s:\n\n", sym->name);
1.708 + str_append(&help, _(sym->help));
1.709 + str_append(&help, "\n");
1.710 + }
1.711 + } else {
1.712 + str_append(&help, nohelp_text);
1.713 + }
1.714 + get_symbol_str(&help, sym);
1.715 + show_helptext(menu_get_prompt(menu), str_get(&help));
1.716 + str_free(&help);
1.717 +}
1.718 +
1.719 +static void conf_choice(struct menu *menu)
1.720 +{
1.721 + const char *prompt = menu_get_prompt(menu);
1.722 + struct menu *child;
1.723 + struct symbol *active;
1.724 +
1.725 + active = sym_get_choice_value(menu->sym);
1.726 + while (1) {
1.727 + int res;
1.728 + int selected;
1.729 + item_reset();
1.730 +
1.731 + current_menu = menu;
1.732 + for (child = menu->list; child; child = child->next) {
1.733 + if (!menu_is_visible(child))
1.734 + continue;
1.735 + item_make("%s", menu_get_prompt(child));
1.736 + item_set_data(child);
1.737 + if (child->sym == active)
1.738 + item_set_selected(1);
1.739 + if (child->sym == sym_get_choice_value(menu->sym))
1.740 + item_set_tag('X');
1.741 + }
1.742 + dialog_clear();
1.743 + res = dialog_checklist(prompt ? prompt : _("Main Menu"),
1.744 + _(radiolist_instructions),
1.745 + 15, 70, 6);
1.746 + selected = item_activate_selected();
1.747 + switch (res) {
1.748 + case 0:
1.749 + if (selected) {
1.750 + child = item_data();
1.751 + sym_set_tristate_value(child->sym, yes);
1.752 + }
1.753 + return;
1.754 + case 1:
1.755 + if (selected) {
1.756 + child = item_data();
1.757 + show_help(child);
1.758 + active = child->sym;
1.759 + } else
1.760 + show_help(menu);
1.761 + break;
1.762 + case KEY_ESC:
1.763 + return;
1.764 + case -ERRDISPLAYTOOSMALL:
1.765 + return;
1.766 + }
1.767 + }
1.768 +}
1.769 +
1.770 +static void conf_string(struct menu *menu)
1.771 +{
1.772 + const char *prompt = menu_get_prompt(menu);
1.773 +
1.774 + while (1) {
1.775 + int res;
1.776 + char *heading;
1.777 +
1.778 + switch (sym_get_type(menu->sym)) {
1.779 + case S_INT:
1.780 + heading = _(inputbox_instructions_int);
1.781 + break;
1.782 + case S_HEX:
1.783 + heading = _(inputbox_instructions_hex);
1.784 + break;
1.785 + case S_STRING:
1.786 + heading = _(inputbox_instructions_string);
1.787 + break;
1.788 + default:
1.789 + heading = "Internal mconf error!";
1.790 + }
1.791 + dialog_clear();
1.792 + res = dialog_inputbox(prompt ? prompt : _("Main Menu"),
1.793 + heading, 10, 75,
1.794 + sym_get_string_value(menu->sym));
1.795 + switch (res) {
1.796 + case 0:
1.797 + if (sym_set_string_value(menu->sym, dialog_input_result))
1.798 + return;
1.799 + show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
1.800 + break;
1.801 + case 1:
1.802 + show_help(menu);
1.803 + break;
1.804 + case KEY_ESC:
1.805 + return;
1.806 + }
1.807 + }
1.808 +}
1.809 +
1.810 +static void conf_load(void)
1.811 +{
1.812 +
1.813 + while (1) {
1.814 + int res;
1.815 + dialog_clear();
1.816 + res = dialog_inputbox(NULL, load_config_text,
1.817 + 11, 55, filename);
1.818 + switch(res) {
1.819 + case 0:
1.820 + if (!dialog_input_result[0])
1.821 + return;
1.822 + if (!conf_read(dialog_input_result))
1.823 + return;
1.824 + show_textbox(NULL, _("File does not exist!"), 5, 38);
1.825 + break;
1.826 + case 1:
1.827 + show_helptext(_("Load Alternate Configuration"), load_config_help);
1.828 + break;
1.829 + case KEY_ESC:
1.830 + return;
1.831 + }
1.832 + }
1.833 +}
1.834 +
1.835 +static void conf_save(void)
1.836 +{
1.837 + while (1) {
1.838 + int res;
1.839 + dialog_clear();
1.840 + res = dialog_inputbox(NULL, save_config_text,
1.841 + 11, 55, filename);
1.842 + switch(res) {
1.843 + case 0:
1.844 + if (!dialog_input_result[0])
1.845 + return;
1.846 + if (!conf_write(dialog_input_result))
1.847 + return;
1.848 + show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60);
1.849 + break;
1.850 + case 1:
1.851 + show_helptext(_("Save Alternate Configuration"), save_config_help);
1.852 + break;
1.853 + case KEY_ESC:
1.854 + return;
1.855 + }
1.856 + }
1.857 +}
1.858 +
1.859 +static void conf_cleanup(void)
1.860 +{
1.861 + tcsetattr(1, TCSAFLUSH, &ios_org);
1.862 +}
1.863 +
1.864 +int main(int ac, char **av)
1.865 +{
1.866 + struct symbol *sym;
1.867 + char *mode;
1.868 + int res;
1.869 +
1.870 + setlocale(LC_ALL, "");
1.871 + bindtextdomain(PACKAGE, LOCALEDIR);
1.872 + textdomain(PACKAGE);
1.873 +
1.874 + conf_parse(av[1] ? av[1] : "");
1.875 + conf_read(NULL);
1.876 +
1.877 + sym = sym_lookup("PROJECTVERSION", 0);
1.878 + sym_calc_value(sym);
1.879 + sprintf(menu_backtitle, _(PROJECT_NAME" v%s Configuration"),
1.880 + sym_get_string_value(sym));
1.881 +
1.882 + mode = getenv("MENUCONFIG_MODE");
1.883 + if (mode) {
1.884 + if (!strcasecmp(mode, "single_menu"))
1.885 + single_menu_mode = 1;
1.886 + }
1.887 +
1.888 + tcgetattr(1, &ios_org);
1.889 + atexit(conf_cleanup);
1.890 + init_wsize();
1.891 + reset_dialog();
1.892 + init_dialog(menu_backtitle);
1.893 + do {
1.894 + conf(&rootmenu);
1.895 + dialog_clear();
1.896 + res = dialog_yesno(NULL,
1.897 + _("Do you wish to save your "
1.898 + "new "PROJECT_NAME" configuration?\n"
1.899 + "<ESC><ESC> to continue."),
1.900 + 6, 60);
1.901 + } while (res == KEY_ESC);
1.902 + end_dialog();
1.903 + if (res == 0) {
1.904 + if (conf_write(NULL)) {
1.905 + fprintf(stderr, _("\n\n"
1.906 + "Error writing "PROJECT_NAME" configuration.\n"
1.907 + "Your configuration changes were NOT saved."
1.908 + "\n\n"));
1.909 + return 1;
1.910 + }
1.911 + printf(_("\n\n"
1.912 + "*** End of "PROJECT_NAME" configuration.\n"
1.913 + "*** Execute 'make' to build, or try 'make help'."
1.914 + "\n\n"));
1.915 + } else {
1.916 + fprintf(stderr, _("\n\n"
1.917 + "Your configuration changes were NOT saved."
1.918 + "\n\n"));
1.919 + }
1.920 +
1.921 + return 0;
1.922 +}