kconfig: rephrase help texts/comments not to include the package name
[linux-2.6.git] / scripts / kconfig / mconf.c
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
25 static 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"),
177 menu_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"),
184 radiolist_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."),
189 inputbox_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."),
193 inputbox_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."),
196 inputbox_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."),
199 setmod_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."),
202 load_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."),
206 load_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"),
217 save_config_text[] = N_(
218         "Enter a filename to which this configuration should be saved "
219         "as an alternate.  Leave blank to abort."),
220 save_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"),
231 search_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
271 static int indent;
272 static struct menu *current_menu;
273 static int child_count;
274 static int single_menu_mode;
275 static int show_all_options;
276
277 static void conf(struct menu *menu);
278 static void conf_choice(struct menu *menu);
279 static void conf_string(struct menu *menu);
280 static void conf_load(void);
281 static void conf_save(void);
282 static void show_textbox(const char *title, const char *text, int r, int c);
283 static void show_helptext(const char *title, const char *text);
284 static void show_help(struct menu *menu);
285
286 static char filename[PATH_MAX+1];
287 static void set_config_filename(const char *config_filename)
288 {
289         static char menu_backtitle[PATH_MAX+128];
290         int size;
291         struct symbol *sym;
292
293         sym = sym_lookup("KERNELVERSION", 0);
294         sym_calc_value(sym);
295         size = snprintf(menu_backtitle, sizeof(menu_backtitle),
296                         _("%s - Linux Kernel v%s Configuration"),
297                         config_filename, sym_get_string_value(sym));
298         if (size >= sizeof(menu_backtitle))
299                 menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
300         set_dialog_backtitle(menu_backtitle);
301
302         size = snprintf(filename, sizeof(filename), "%s", config_filename);
303         if (size >= sizeof(filename))
304                 filename[sizeof(filename)-1] = '\0';
305 }
306
307
308 static void search_conf(void)
309 {
310         struct symbol **sym_arr;
311         struct gstr res;
312         char *dialog_input;
313         int dres;
314 again:
315         dialog_clear();
316         dres = dialog_inputbox(_("Search Configuration Parameter"),
317                               _("Enter " CONFIG_ " (sub)string to search for "
318                                 "(with or without \"" CONFIG_ "\")"),
319                               10, 75, "");
320         switch (dres) {
321         case 0:
322                 break;
323         case 1:
324                 show_helptext(_("Search Configuration"), search_help);
325                 goto again;
326         default:
327                 return;
328         }
329
330         /* strip the prefix if necessary */
331         dialog_input = dialog_input_result;
332         if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
333                 dialog_input += strlen(CONFIG_);
334
335         sym_arr = sym_re_search(dialog_input);
336         res = get_relations_str(sym_arr);
337         free(sym_arr);
338         show_textbox(_("Search Results"), str_get(&res), 0, 0);
339         str_free(&res);
340 }
341
342 static void build_conf(struct menu *menu)
343 {
344         struct symbol *sym;
345         struct property *prop;
346         struct menu *child;
347         int type, tmp, doint = 2;
348         tristate val;
349         char ch;
350         bool visible;
351
352         /*
353          * note: menu_is_visible() has side effect that it will
354          * recalc the value of the symbol.
355          */
356         visible = menu_is_visible(menu);
357         if (show_all_options && !menu_has_prompt(menu))
358                 return;
359         else if (!show_all_options && !visible)
360                 return;
361
362         sym = menu->sym;
363         prop = menu->prompt;
364         if (!sym) {
365                 if (prop && menu != current_menu) {
366                         const char *prompt = menu_get_prompt(menu);
367                         switch (prop->type) {
368                         case P_MENU:
369                                 child_count++;
370                                 prompt = _(prompt);
371                                 if (single_menu_mode) {
372                                         item_make("%s%*c%s",
373                                                   menu->data ? "-->" : "++>",
374                                                   indent + 1, ' ', prompt);
375                                 } else
376                                         item_make("   %*c%s  --->", indent + 1, ' ', prompt);
377
378                                 item_set_tag('m');
379                                 item_set_data(menu);
380                                 if (single_menu_mode && menu->data)
381                                         goto conf_childs;
382                                 return;
383                         case P_COMMENT:
384                                 if (prompt) {
385                                         child_count++;
386                                         item_make("   %*c*** %s ***", indent + 1, ' ', _(prompt));
387                                         item_set_tag(':');
388                                         item_set_data(menu);
389                                 }
390                                 break;
391                         default:
392                                 if (prompt) {
393                                         child_count++;
394                                         item_make("---%*c%s", indent + 1, ' ', _(prompt));
395                                         item_set_tag(':');
396                                         item_set_data(menu);
397                                 }
398                         }
399                 } else
400                         doint = 0;
401                 goto conf_childs;
402         }
403
404         type = sym_get_type(sym);
405         if (sym_is_choice(sym)) {
406                 struct symbol *def_sym = sym_get_choice_value(sym);
407                 struct menu *def_menu = NULL;
408
409                 child_count++;
410                 for (child = menu->list; child; child = child->next) {
411                         if (menu_is_visible(child) && child->sym == def_sym)
412                                 def_menu = child;
413                 }
414
415                 val = sym_get_tristate_value(sym);
416                 if (sym_is_changable(sym)) {
417                         switch (type) {
418                         case S_BOOLEAN:
419                                 item_make("[%c]", val == no ? ' ' : '*');
420                                 break;
421                         case S_TRISTATE:
422                                 switch (val) {
423                                 case yes: ch = '*'; break;
424                                 case mod: ch = 'M'; break;
425                                 default:  ch = ' '; break;
426                                 }
427                                 item_make("<%c>", ch);
428                                 break;
429                         }
430                         item_set_tag('t');
431                         item_set_data(menu);
432                 } else {
433                         item_make("   ");
434                         item_set_tag(def_menu ? 't' : ':');
435                         item_set_data(menu);
436                 }
437
438                 item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
439                 if (val == yes) {
440                         if (def_menu) {
441                                 item_add_str(" (%s)", _(menu_get_prompt(def_menu)));
442                                 item_add_str("  --->");
443                                 if (def_menu->list) {
444                                         indent += 2;
445                                         build_conf(def_menu);
446                                         indent -= 2;
447                                 }
448                         }
449                         return;
450                 }
451         } else {
452                 if (menu == current_menu) {
453                         item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
454                         item_set_tag(':');
455                         item_set_data(menu);
456                         goto conf_childs;
457                 }
458                 child_count++;
459                 val = sym_get_tristate_value(sym);
460                 if (sym_is_choice_value(sym) && val == yes) {
461                         item_make("   ");
462                         item_set_tag(':');
463                         item_set_data(menu);
464                 } else {
465                         switch (type) {
466                         case S_BOOLEAN:
467                                 if (sym_is_changable(sym))
468                                         item_make("[%c]", val == no ? ' ' : '*');
469                                 else
470                                         item_make("-%c-", val == no ? ' ' : '*');
471                                 item_set_tag('t');
472                                 item_set_data(menu);
473                                 break;
474                         case S_TRISTATE:
475                                 switch (val) {
476                                 case yes: ch = '*'; break;
477                                 case mod: ch = 'M'; break;
478                                 default:  ch = ' '; break;
479                                 }
480                                 if (sym_is_changable(sym)) {
481                                         if (sym->rev_dep.tri == mod)
482                                                 item_make("{%c}", ch);
483                                         else
484                                                 item_make("<%c>", ch);
485                                 } else
486                                         item_make("-%c-", ch);
487                                 item_set_tag('t');
488                                 item_set_data(menu);
489                                 break;
490                         default:
491                                 tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
492                                 item_make("(%s)", sym_get_string_value(sym));
493                                 tmp = indent - tmp + 4;
494                                 if (tmp < 0)
495                                         tmp = 0;
496                                 item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)),
497                                              (sym_has_value(sym) || !sym_is_changable(sym)) ?
498                                              "" : _(" (NEW)"));
499                                 item_set_tag('s');
500                                 item_set_data(menu);
501                                 goto conf_childs;
502                         }
503                 }
504                 item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)),
505                           (sym_has_value(sym) || !sym_is_changable(sym)) ?
506                           "" : _(" (NEW)"));
507                 if (menu->prompt->type == P_MENU) {
508                         item_add_str("  --->");
509                         return;
510                 }
511         }
512
513 conf_childs:
514         indent += doint;
515         for (child = menu->list; child; child = child->next)
516                 build_conf(child);
517         indent -= doint;
518 }
519
520 static void conf(struct menu *menu)
521 {
522         struct menu *submenu;
523         const char *prompt = menu_get_prompt(menu);
524         struct symbol *sym;
525         struct menu *active_menu = NULL;
526         int res;
527         int s_scroll = 0;
528
529         while (1) {
530                 item_reset();
531                 current_menu = menu;
532                 build_conf(menu);
533                 if (!child_count)
534                         break;
535                 if (menu == &rootmenu) {
536                         item_make("--- ");
537                         item_set_tag(':');
538                         item_make(_("    Load an Alternate Configuration File"));
539                         item_set_tag('L');
540                         item_make(_("    Save an Alternate Configuration File"));
541                         item_set_tag('S');
542                 }
543                 dialog_clear();
544                 res = dialog_menu(prompt ? _(prompt) : _("Main Menu"),
545                                   _(menu_instructions),
546                                   active_menu, &s_scroll);
547                 if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
548                         break;
549                 if (!item_activate_selected())
550                         continue;
551                 if (!item_tag())
552                         continue;
553
554                 submenu = item_data();
555                 active_menu = item_data();
556                 if (submenu)
557                         sym = submenu->sym;
558                 else
559                         sym = NULL;
560
561                 switch (res) {
562                 case 0:
563                         switch (item_tag()) {
564                         case 'm':
565                                 if (single_menu_mode)
566                                         submenu->data = (void *) (long) !submenu->data;
567                                 else
568                                         conf(submenu);
569                                 break;
570                         case 't':
571                                 if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
572                                         conf_choice(submenu);
573                                 else if (submenu->prompt->type == P_MENU)
574                                         conf(submenu);
575                                 break;
576                         case 's':
577                                 conf_string(submenu);
578                                 break;
579                         case 'L':
580                                 conf_load();
581                                 break;
582                         case 'S':
583                                 conf_save();
584                                 break;
585                         }
586                         break;
587                 case 2:
588                         if (sym)
589                                 show_help(submenu);
590                         else
591                                 show_helptext(_("README"), _(mconf_readme));
592                         break;
593                 case 3:
594                         if (item_is_tag('t')) {
595                                 if (sym_set_tristate_value(sym, yes))
596                                         break;
597                                 if (sym_set_tristate_value(sym, mod))
598                                         show_textbox(NULL, setmod_text, 6, 74);
599                         }
600                         break;
601                 case 4:
602                         if (item_is_tag('t'))
603                                 sym_set_tristate_value(sym, no);
604                         break;
605                 case 5:
606                         if (item_is_tag('t'))
607                                 sym_set_tristate_value(sym, mod);
608                         break;
609                 case 6:
610                         if (item_is_tag('t'))
611                                 sym_toggle_tristate_value(sym);
612                         else if (item_is_tag('m'))
613                                 conf(submenu);
614                         break;
615                 case 7:
616                         search_conf();
617                         break;
618                 case 8:
619                         show_all_options = !show_all_options;
620                         break;
621                 }
622         }
623 }
624
625 static void show_textbox(const char *title, const char *text, int r, int c)
626 {
627         dialog_clear();
628         dialog_textbox(title, text, r, c);
629 }
630
631 static void show_helptext(const char *title, const char *text)
632 {
633         show_textbox(title, text, 0, 0);
634 }
635
636 static void show_help(struct menu *menu)
637 {
638         struct gstr help = str_new();
639
640         help.max_width = getmaxx(stdscr) - 10;
641         menu_get_ext_help(menu, &help);
642
643         show_helptext(_(menu_get_prompt(menu)), str_get(&help));
644         str_free(&help);
645 }
646
647 static 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
706 static 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
746 static 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
774 static 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
800 int 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 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 while writing of the configuration.\n"
848                                 "Your configuration changes were NOT saved."
849                                 "\n\n"));
850                         return 1;
851                 }
852         case -1:
853                 printf(_("\n\n"
854                         "*** End of the configuration.\n"
855                         "*** Execute 'make' to start the build or try 'make help'."
856                         "\n\n"));
857                 break;
858         default:
859                 fprintf(stderr, _("\n\n"
860                         "Your configuration changes were NOT saved."
861                         "\n\n"));
862         }
863
864         return 0;
865 }
866