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