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