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"Some kernel features may be built directly into the kernel.\n"
  29"Some may be made into loadable runtime modules.  Some features\n"
  30"may be completely removed altogether.  There are also certain\n"
  31"kernel parameters which are not really features, but must be\n"
  32"entered in as decimal or hexadecimal numbers or possibly text.\n"
  33"\n"
  34"Menu items beginning with following braces represent features that\n"
  35"  [ ] can be built in or removed\n"
  36"  < > can be built in, modularized or removed\n"
  37"  { } can be built in or modularized (selected by other feature)\n"
  38"  - - are selected by other feature,\n"
  39"while *, M or whitespace inside braces means to build in, build as\n"
  40"a module or to exclude the feature respectively.\n"
  41"\n"
  42"To change any of these features, highlight it with the cursor\n"
  43"keys and press <Y> to build it in, <M> to make it a module or\n"
  44"<N> to removed it.  You may also press the <Space Bar> to cycle\n"
  45"through the available options (ie. Y->N->M->Y).\n"
  46"\n"
  47"Some additional keyboard hints:\n"
  48"\n"
  49"Menus\n"
  50"----------\n"
  51"o  Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
  52"   you wish to change or submenu wish to select and press <Enter>.\n"
  53"   Submenus are designated by \"--->\".\n"
  54"\n"
  55"   Shortcut: Press the option's highlighted letter (hotkey).\n"
  56"             Pressing a hotkey more than once will sequence\n"
  57"             through all visible items which use that hotkey.\n"
  58"\n"
  59"   You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
  60"   unseen options into view.\n"
  61"\n"
  62"o  To exit a menu use the cursor keys to highlight the <Exit> button\n"
  63"   and press <ENTER>.\n"
  64"\n"
  65"   Shortcut: Press <ESC><ESC> or <E> or <X> if there is no hotkey\n"
  66"             using those letters.  You may press a single <ESC>, but\n"
  67"             there is a delayed response which you may find annoying.\n"
  68"\n"
  69"   Also, the <TAB> and cursor keys will cycle between <Select>,\n"
  70"   <Exit> and <Help>\n"
  71"\n"
  72"o  To get help with an item, use the cursor keys to highlight <Help>\n"
  73"   and Press <ENTER>.\n"
  74"\n"
  75"   Shortcut: Press <H> or <?>.\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 kernel 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 kernel options listed in a single\n"
 152"menu, rather than the default multimenu hierarchy, run the menuconfig\n"
 153"with 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 kernel\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        "kernel's default, entering the name of the file here will allow you\n"
 213        "to modify that configuration.\n"
 214        "\n"
 215        "If you are uncertain, then you have probably never used alternate\n"
 216        "configuration files.  You should therefor 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 kernel\n"
 223        "configurations 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 CONFIG_ 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 CONFIG_ 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 CONFIG_ symbols containing USB\n"
 267        "          ^USB => find all CONFIG_ symbols starting with USB\n"
 268        "          USB$ => find all CONFIG_ 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;
 275
 276static void conf(struct menu *menu);
 277static void conf_choice(struct menu *menu);
 278static void conf_string(struct menu *menu);
 279static void conf_load(void);
 280static void conf_save(void);
 281static void show_textbox(const char *title, const char *text, int r, int c);
 282static void show_helptext(const char *title, const char *text);
 283static void show_help(struct menu *menu);
 284
 285static struct gstr get_relations_str(struct symbol **sym_arr)
 286{
 287        struct symbol *sym;
 288        struct gstr res = str_new();
 289        int i;
 290
 291        for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
 292                get_symbol_str(&res, sym);
 293        if (!i)
 294                str_append(&res, _("No matches found.\n"));
 295        return res;
 296}
 297
 298static char filename[PATH_MAX+1];
 299static void set_config_filename(const char *config_filename)
 300{
 301        static char menu_backtitle[PATH_MAX+128];
 302        int size;
 303        struct symbol *sym;
 304
 305        sym = sym_lookup("KERNELVERSION", 0);
 306        sym_calc_value(sym);
 307        size = snprintf(menu_backtitle, sizeof(menu_backtitle),
 308                        _("%s - Linux Kernel v%s Configuration"),
 309                        config_filename, sym_get_string_value(sym));
 310        if (size >= sizeof(menu_backtitle))
 311                menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
 312        set_dialog_backtitle(menu_backtitle);
 313
 314        size = snprintf(filename, sizeof(filename), "%s", config_filename);
 315        if (size >= sizeof(filename))
 316                filename[sizeof(filename)-1] = '\0';
 317}
 318
 319
 320static void search_conf(void)
 321{
 322        struct symbol **sym_arr;
 323        struct gstr res;
 324        char *dialog_input;
 325        int dres;
 326again:
 327        dialog_clear();
 328        dres = dialog_inputbox(_("Search Configuration Parameter"),
 329                              _("Enter CONFIG_ (sub)string to search for "
 330                                "(with or without \"CONFIG\")"),
 331                              10, 75, "");
 332        switch (dres) {
 333        case 0:
 334                break;
 335        case 1:
 336                show_helptext(_("Search Configuration"), search_help);
 337                goto again;
 338        default:
 339                return;
 340        }
 341
 342        /* strip CONFIG_ if necessary */
 343        dialog_input = dialog_input_result;
 344        if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0)
 345                dialog_input += 7;
 346
 347        sym_arr = sym_re_search(dialog_input);
 348        res = get_relations_str(sym_arr);
 349        free(sym_arr);
 350        show_textbox(_("Search Results"), str_get(&res), 0, 0);
 351        str_free(&res);
 352}
 353
 354static void build_conf(struct menu *menu)
 355{
 356        struct symbol *sym;
 357        struct property *prop;
 358        struct menu *child;
 359        int type, tmp, doint = 2;
 360        tristate val;
 361        char ch;
 362
 363        if (!menu_is_visible(menu))
 364                return;
 365
 366        sym = menu->sym;
 367        prop = menu->prompt;
 368        if (!sym) {
 369                if (prop && menu != current_menu) {
 370                        const char *prompt = menu_get_prompt(menu);
 371                        switch (prop->type) {
 372                        case P_MENU:
 373                                child_count++;
 374                                prompt = _(prompt);
 375                                if (single_menu_mode) {
 376                                        item_make("%s%*c%s",
 377                                                  menu->data ? "-->" : "++>",
 378                                                  indent + 1, ' ', prompt);
 379                                } else
 380                                        item_make("   %*c%s  --->", indent + 1, ' ', prompt);
 381
 382                                item_set_tag('m');
 383                                item_set_data(menu);
 384                                if (single_menu_mode && menu->data)
 385                                        goto conf_childs;
 386                                return;
 387                        case P_COMMENT:
 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                                break;
 395                        default:
 396                                if (prompt) {
 397                                        child_count++;
 398                                        item_make("---%*c%s", indent + 1, ' ', _(prompt));
 399                                        item_set_tag(':');
 400                                        item_set_data(menu);
 401                                }
 402                        }
 403                } else
 404                        doint = 0;
 405                goto conf_childs;
 406        }
 407
 408        type = sym_get_type(sym);
 409        if (sym_is_choice(sym)) {
 410                struct symbol *def_sym = sym_get_choice_value(sym);
 411                struct menu *def_menu = NULL;
 412
 413                child_count++;
 414                for (child = menu->list; child; child = child->next) {
 415                        if (menu_is_visible(child) && child->sym == def_sym)
 416                                def_menu = child;
 417                }
 418
 419                val = sym_get_tristate_value(sym);
 420                if (sym_is_changable(sym)) {
 421                        switch (type) {
 422                        case S_BOOLEAN:
 423                                item_make("[%c]", val == no ? ' ' : '*');
 424                                break;
 425                        case S_TRISTATE:
 426                                switch (val) {
 427                                case yes: ch = '*'; break;
 428                                case mod: ch = 'M'; break;
 429                                default:  ch = ' '; break;
 430                                }
 431                                item_make("<%c>", ch);
 432                                break;
 433                        }
 434                        item_set_tag('t');
 435                        item_set_data(menu);
 436                } else {
 437                        item_make("   ");
 438                        item_set_tag(def_menu ? 't' : ':');
 439                        item_set_data(menu);
 440                }
 441
 442                item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
 443                if (val == yes) {
 444                        if (def_menu) {
 445                                item_add_str(" (%s)", _(menu_get_prompt(def_menu)));
 446                                item_add_str("  --->");
 447                                if (def_menu->list) {
 448                                        indent += 2;
 449                                        build_conf(def_menu);
 450                                        indent -= 2;
 451                                }
 452                        }
 453                        return;
 454                }
 455        } else {
 456                if (menu == current_menu) {
 457                        item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
 458                        item_set_tag(':');
 459                        item_set_data(menu);
 460                        goto conf_childs;
 461                }
 462                child_count++;
 463                val = sym_get_tristate_value(sym);
 464                if (sym_is_choice_value(sym) && val == yes) {
 465                        item_make("   ");
 466                        item_set_tag(':');
 467                        item_set_data(menu);
 468                } else {
 469                        switch (type) {
 470                        case S_BOOLEAN:
 471                                if (sym_is_changable(sym))
 472                                        item_make("[%c]", val == no ? ' ' : '*');
 473                                else
 474                                        item_make("-%c-", val == no ? ' ' : '*');
 475                                item_set_tag('t');
 476                                item_set_data(menu);
 477                                break;
 478                        case S_TRISTATE:
 479                                switch (val) {
 480                                case yes: ch = '*'; break;
 481                                case mod: ch = 'M'; break;
 482                                default:  ch = ' '; break;
 483                                }
 484                                if (sym_is_changable(sym)) {
 485                                        if (sym->rev_dep.tri == mod)
 486                                                item_make("{%c}", ch);
 487                                        else
 488                                                item_make("<%c>", ch);
 489                                } else
 490                                        item_make("-%c-", ch);
 491                                item_set_tag('t');
 492                                item_set_data(menu);
 493                                break;
 494                        default:
 495                                tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
 496                                item_make("(%s)", sym_get_string_value(sym));
 497                                tmp = indent - tmp + 4;
 498                                if (tmp < 0)
 499                                        tmp = 0;
 500                                item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)),
 501                                             (sym_has_value(sym) || !sym_is_changable(sym)) ?
 502                                             "" : _(" (NEW)"));
 503                                item_set_tag('s');
 504                                item_set_data(menu);
 505                                goto conf_childs;
 506                        }
 507                }
 508                item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)),
 509                          (sym_has_value(sym) || !sym_is_changable(sym)) ?
 510                          "" : _(" (NEW)"));
 511                if (menu->prompt->type == P_MENU) {
 512                        item_add_str("  --->");
 513                        return;
 514                }
 515        }
 516
 517conf_childs:
 518        indent += doint;
 519        for (child = menu->list; child; child = child->next)
 520                build_conf(child);
 521        indent -= doint;
 522}
 523
 524static void conf(struct menu *menu)
 525{
 526        struct menu *submenu;
 527        const char *prompt = menu_get_prompt(menu);
 528        struct symbol *sym;
 529        struct menu *active_menu = NULL;
 530        int res;
 531        int s_scroll = 0;
 532
 533        while (1) {
 534                item_reset();
 535                current_menu = menu;
 536                build_conf(menu);
 537                if (!child_count)
 538                        break;
 539                if (menu == &rootmenu) {
 540                        item_make("--- ");
 541                        item_set_tag(':');
 542                        item_make(_("    Load an Alternate Configuration File"));
 543                        item_set_tag('L');
 544                        item_make(_("    Save an Alternate Configuration File"));
 545                        item_set_tag('S');
 546                }
 547                dialog_clear();
 548                res = dialog_menu(prompt ? _(prompt) : _("Main Menu"),
 549                                  _(menu_instructions),
 550                                  active_menu, &s_scroll);
 551                if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
 552                        break;
 553                if (!item_activate_selected())
 554                        continue;
 555                if (!item_tag())
 556                        continue;
 557
 558                submenu = item_data();
 559                active_menu = item_data();
 560                if (submenu)
 561                        sym = submenu->sym;
 562                else
 563                        sym = NULL;
 564
 565                switch (res) {
 566                case 0:
 567                        switch (item_tag()) {
 568                        case 'm':
 569                                if (single_menu_mode)
 570                                        submenu->data = (void *) (long) !submenu->data;
 571                                else
 572                                        conf(submenu);
 573                                break;
 574                        case 't':
 575                                if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
 576                                        conf_choice(submenu);
 577                                else if (submenu->prompt->type == P_MENU)
 578                                        conf(submenu);
 579                                break;
 580                        case 's':
 581                                conf_string(submenu);
 582                                break;
 583                        case 'L':
 584                                conf_load();
 585                                break;
 586                        case 'S':
 587                                conf_save();
 588                                break;
 589                        }
 590                        break;
 591                case 2:
 592                        if (sym)
 593                                show_help(submenu);
 594                        else
 595                                show_helptext(_("README"), _(mconf_readme));
 596                        break;
 597                case 3:
 598                        if (item_is_tag('t')) {
 599                                if (sym_set_tristate_value(sym, yes))
 600                                        break;
 601                                if (sym_set_tristate_value(sym, mod))
 602                                        show_textbox(NULL, setmod_text, 6, 74);
 603                        }
 604                        break;
 605                case 4:
 606                        if (item_is_tag('t'))
 607                                sym_set_tristate_value(sym, no);
 608                        break;
 609                case 5:
 610                        if (item_is_tag('t'))
 611                                sym_set_tristate_value(sym, mod);
 612                        break;
 613                case 6:
 614                        if (item_is_tag('t'))
 615                                sym_toggle_tristate_value(sym);
 616                        else if (item_is_tag('m'))
 617                                conf(submenu);
 618                        break;
 619                case 7:
 620                        search_conf();
 621                        break;
 622                }
 623        }
 624}
 625
 626static void show_textbox(const char *title, const char *text, int r, int c)
 627{
 628        dialog_clear();
 629        dialog_textbox(title, text, r, c);
 630}
 631
 632static void show_helptext(const char *title, const char *text)
 633{
 634        show_textbox(title, text, 0, 0);
 635}
 636
 637static void show_help(struct menu *menu)
 638{
 639        struct gstr help = str_new();
 640
 641        menu_get_ext_help(menu, &help);
 642
 643        show_helptext(_(menu_get_prompt(menu)), str_get(&help));
 644        str_free(&help);
 645}
 646
 647static void conf_choice(struct menu *menu)
 648{
 649        const char *prompt = _(menu_get_prompt(menu));
 650        struct menu *child;
 651        struct symbol *active;
 652
 653        active = sym_get_choice_value(menu->sym);
 654        while (1) {
 655                int res;
 656                int selected;
 657                item_reset();
 658
 659                current_menu = menu;
 660                for (child = menu->list; child; child = child->next) {
 661                        if (!menu_is_visible(child))
 662                                continue;
 663                        if (child->sym)
 664                                item_make("%s", _(menu_get_prompt(child)));
 665                        else {
 666                                item_make("*** %s ***", _(menu_get_prompt(child)));
 667                                item_set_tag(':');
 668                        }
 669                        item_set_data(child);
 670                        if (child->sym == active)
 671                                item_set_selected(1);
 672                        if (child->sym == sym_get_choice_value(menu->sym))
 673                                item_set_tag('X');
 674                }
 675                dialog_clear();
 676                res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"),
 677                                        _(radiolist_instructions),
 678                                         15, 70, 6);
 679                selected = item_activate_selected();
 680                switch (res) {
 681                case 0:
 682                        if (selected) {
 683                                child = item_data();
 684                                if (!child->sym)
 685                                        break;
 686
 687                                sym_set_tristate_value(child->sym, yes);
 688                        }
 689                        return;
 690                case 1:
 691                        if (selected) {
 692                                child = item_data();
 693                                show_help(child);
 694                                active = child->sym;
 695                        } else
 696                                show_help(menu);
 697                        break;
 698                case KEY_ESC:
 699                        return;
 700                case -ERRDISPLAYTOOSMALL:
 701                        return;
 702                }
 703        }
 704}
 705
 706static void conf_string(struct menu *menu)
 707{
 708        const char *prompt = menu_get_prompt(menu);
 709
 710        while (1) {
 711                int res;
 712                const char *heading;
 713
 714                switch (sym_get_type(menu->sym)) {
 715                case S_INT:
 716                        heading = _(inputbox_instructions_int);
 717                        break;
 718                case S_HEX:
 719                        heading = _(inputbox_instructions_hex);
 720                        break;
 721                case S_STRING:
 722                        heading = _(inputbox_instructions_string);
 723                        break;
 724                default:
 725                        heading = _("Internal mconf error!");
 726                }
 727                dialog_clear();
 728                res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"),
 729                                      heading, 10, 75,
 730                                      sym_get_string_value(menu->sym));
 731                switch (res) {
 732                case 0:
 733                        if (sym_set_string_value(menu->sym, dialog_input_result))
 734                                return;
 735                        show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
 736                        break;
 737                case 1:
 738                        show_help(menu);
 739                        break;
 740                case KEY_ESC:
 741                        return;
 742                }
 743        }
 744}
 745
 746static void conf_load(void)
 747{
 748
 749        while (1) {
 750                int res;
 751                dialog_clear();
 752                res = dialog_inputbox(NULL, load_config_text,
 753                                      11, 55, filename);
 754                switch(res) {
 755                case 0:
 756                        if (!dialog_input_result[0])
 757                                return;
 758                        if (!conf_read(dialog_input_result)) {
 759                                set_config_filename(dialog_input_result);
 760                                sym_set_change_count(1);
 761                                return;
 762                        }
 763                        show_textbox(NULL, _("File does not exist!"), 5, 38);
 764                        break;
 765                case 1:
 766                        show_helptext(_("Load Alternate Configuration"), load_config_help);
 767                        break;
 768                case KEY_ESC:
 769                        return;
 770                }
 771        }
 772}
 773
 774static void conf_save(void)
 775{
 776        while (1) {
 777                int res;
 778                dialog_clear();
 779                res = dialog_inputbox(NULL, save_config_text,
 780                                      11, 55, filename);
 781                switch(res) {
 782                case 0:
 783                        if (!dialog_input_result[0])
 784                                return;
 785                        if (!conf_write(dialog_input_result)) {
 786                                set_config_filename(dialog_input_result);
 787                                return;
 788                        }
 789                        show_textbox(NULL, _("Can't create file!  Probably a nonexistent directory."), 5, 60);
 790                        break;
 791                case 1:
 792                        show_helptext(_("Save Alternate Configuration"), save_config_help);
 793                        break;
 794                case KEY_ESC:
 795                        return;
 796                }
 797        }
 798}
 799
 800int main(int ac, char **av)
 801{
 802        int saved_x, saved_y;
 803        char *mode;
 804        int res;
 805
 806        setlocale(LC_ALL, "");
 807        bindtextdomain(PACKAGE, LOCALEDIR);
 808        textdomain(PACKAGE);
 809
 810        conf_parse(av[1]);
 811        conf_read(NULL);
 812
 813        mode = getenv("MENUCONFIG_MODE");
 814        if (mode) {
 815                if (!strcasecmp(mode, "single_menu"))
 816                        single_menu_mode = 1;
 817        }
 818
 819        initscr();
 820
 821        getyx(stdscr, saved_y, saved_x);
 822        if (init_dialog(NULL)) {
 823                fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
 824                fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
 825                return 1;
 826        }
 827
 828        set_config_filename(conf_get_configname());
 829        do {
 830                conf(&rootmenu);
 831                dialog_clear();
 832                if (conf_get_changed())
 833                        res = dialog_yesno(NULL,
 834                                           _("Do you wish to save your "
 835                                             "new kernel configuration?\n"
 836                                             "<ESC><ESC> to continue."),
 837                                           6, 60);
 838                else
 839                        res = -1;
 840        } while (res == KEY_ESC);
 841        end_dialog(saved_x, saved_y);
 842
 843        switch (res) {
 844        case 0:
 845                if (conf_write(filename)) {
 846                        fprintf(stderr, _("\n\n"
 847                                "Error during writing of the kernel configuration.\n"
 848                                "Your kernel configuration changes were NOT saved."
 849                                "\n\n"));
 850                        return 1;
 851                }
 852        case -1:
 853                printf(_("\n\n"
 854                        "*** End of Linux kernel configuration.\n"
 855                        "*** Execute 'make' to build the kernel or try 'make help'."
 856                        "\n\n"));
 857                break;
 858        default:
 859                fprintf(stderr, _("\n\n"
 860                        "Your kernel configuration changes were NOT saved."
 861                        "\n\n"));
 862        }
 863
 864        return 0;
 865}
 866
 867