Merge branch 'kconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild-2.6
[pandora-kernel.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
292         size = snprintf(menu_backtitle, sizeof(menu_backtitle),
293                         "%s - %s", config_filename, rootmenu.prompt->text);
294         if (size >= sizeof(menu_backtitle))
295                 menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
296         set_dialog_backtitle(menu_backtitle);
297
298         size = snprintf(filename, sizeof(filename), "%s", config_filename);
299         if (size >= sizeof(filename))
300                 filename[sizeof(filename)-1] = '\0';
301 }
302
303
304 static void search_conf(void)
305 {
306         struct symbol **sym_arr;
307         struct gstr res;
308         char *dialog_input;
309         int dres;
310 again:
311         dialog_clear();
312         dres = dialog_inputbox(_("Search Configuration Parameter"),
313                               _("Enter " CONFIG_ " (sub)string to search for "
314                                 "(with or without \"" CONFIG_ "\")"),
315                               10, 75, "");
316         switch (dres) {
317         case 0:
318                 break;
319         case 1:
320                 show_helptext(_("Search Configuration"), search_help);
321                 goto again;
322         default:
323                 return;
324         }
325
326         /* strip the prefix if necessary */
327         dialog_input = dialog_input_result;
328         if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
329                 dialog_input += strlen(CONFIG_);
330
331         sym_arr = sym_re_search(dialog_input);
332         res = get_relations_str(sym_arr);
333         free(sym_arr);
334         show_textbox(_("Search Results"), str_get(&res), 0, 0);
335         str_free(&res);
336 }
337
338 static void build_conf(struct menu *menu)
339 {
340         struct symbol *sym;
341         struct property *prop;
342         struct menu *child;
343         int type, tmp, doint = 2;
344         tristate val;
345         char ch;
346         bool visible;
347
348         /*
349          * note: menu_is_visible() has side effect that it will
350          * recalc the value of the symbol.
351          */
352         visible = menu_is_visible(menu);
353         if (show_all_options && !menu_has_prompt(menu))
354                 return;
355         else if (!show_all_options && !visible)
356                 return;
357
358         sym = menu->sym;
359         prop = menu->prompt;
360         if (!sym) {
361                 if (prop && menu != current_menu) {
362                         const char *prompt = menu_get_prompt(menu);
363                         switch (prop->type) {
364                         case P_MENU:
365                                 child_count++;
366                                 prompt = _(prompt);
367                                 if (single_menu_mode) {
368                                         item_make("%s%*c%s",
369                                                   menu->data ? "-->" : "++>",
370                                                   indent + 1, ' ', prompt);
371                                 } else
372                                         item_make("   %*c%s  --->", indent + 1, ' ', prompt);
373
374                                 item_set_tag('m');
375                                 item_set_data(menu);
376                                 if (single_menu_mode && menu->data)
377                                         goto conf_childs;
378                                 return;
379                         case P_COMMENT:
380                                 if (prompt) {
381                                         child_count++;
382                                         item_make("   %*c*** %s ***", indent + 1, ' ', _(prompt));
383                                         item_set_tag(':');
384                                         item_set_data(menu);
385                                 }
386                                 break;
387                         default:
388                                 if (prompt) {
389                                         child_count++;
390                                         item_make("---%*c%s", indent + 1, ' ', _(prompt));
391                                         item_set_tag(':');
392                                         item_set_data(menu);
393                                 }
394                         }
395                 } else
396                         doint = 0;
397                 goto conf_childs;
398         }
399
400         type = sym_get_type(sym);
401         if (sym_is_choice(sym)) {
402                 struct symbol *def_sym = sym_get_choice_value(sym);
403                 struct menu *def_menu = NULL;
404
405                 child_count++;
406                 for (child = menu->list; child; child = child->next) {
407                         if (menu_is_visible(child) && child->sym == def_sym)
408                                 def_menu = child;
409                 }
410
411                 val = sym_get_tristate_value(sym);
412                 if (sym_is_changable(sym)) {
413                         switch (type) {
414                         case S_BOOLEAN:
415                                 item_make("[%c]", val == no ? ' ' : '*');
416                                 break;
417                         case S_TRISTATE:
418                                 switch (val) {
419                                 case yes: ch = '*'; break;
420                                 case mod: ch = 'M'; break;
421                                 default:  ch = ' '; break;
422                                 }
423                                 item_make("<%c>", ch);
424                                 break;
425                         }
426                         item_set_tag('t');
427                         item_set_data(menu);
428                 } else {
429                         item_make("   ");
430                         item_set_tag(def_menu ? 't' : ':');
431                         item_set_data(menu);
432                 }
433
434                 item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
435                 if (val == yes) {
436                         if (def_menu) {
437                                 item_add_str(" (%s)", _(menu_get_prompt(def_menu)));
438                                 item_add_str("  --->");
439                                 if (def_menu->list) {
440                                         indent += 2;
441                                         build_conf(def_menu);
442                                         indent -= 2;
443                                 }
444                         }
445                         return;
446                 }
447         } else {
448                 if (menu == current_menu) {
449                         item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu)));
450                         item_set_tag(':');
451                         item_set_data(menu);
452                         goto conf_childs;
453                 }
454                 child_count++;
455                 val = sym_get_tristate_value(sym);
456                 if (sym_is_choice_value(sym) && val == yes) {
457                         item_make("   ");
458                         item_set_tag(':');
459                         item_set_data(menu);
460                 } else {
461                         switch (type) {
462                         case S_BOOLEAN:
463                                 if (sym_is_changable(sym))
464                                         item_make("[%c]", val == no ? ' ' : '*');
465                                 else
466                                         item_make("-%c-", val == no ? ' ' : '*');
467                                 item_set_tag('t');
468                                 item_set_data(menu);
469                                 break;
470                         case S_TRISTATE:
471                                 switch (val) {
472                                 case yes: ch = '*'; break;
473                                 case mod: ch = 'M'; break;
474                                 default:  ch = ' '; break;
475                                 }
476                                 if (sym_is_changable(sym)) {
477                                         if (sym->rev_dep.tri == mod)
478                                                 item_make("{%c}", ch);
479                                         else
480                                                 item_make("<%c>", ch);
481                                 } else
482                                         item_make("-%c-", ch);
483                                 item_set_tag('t');
484                                 item_set_data(menu);
485                                 break;
486                         default:
487                                 tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
488                                 item_make("(%s)", sym_get_string_value(sym));
489                                 tmp = indent - tmp + 4;
490                                 if (tmp < 0)
491                                         tmp = 0;
492                                 item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)),
493                                              (sym_has_value(sym) || !sym_is_changable(sym)) ?
494                                              "" : _(" (NEW)"));
495                                 item_set_tag('s');
496                                 item_set_data(menu);
497                                 goto conf_childs;
498                         }
499                 }
500                 item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)),
501                           (sym_has_value(sym) || !sym_is_changable(sym)) ?
502                           "" : _(" (NEW)"));
503                 if (menu->prompt->type == P_MENU) {
504                         item_add_str("  --->");
505                         return;
506                 }
507         }
508
509 conf_childs:
510         indent += doint;
511         for (child = menu->list; child; child = child->next)
512                 build_conf(child);
513         indent -= doint;
514 }
515
516 static void conf(struct menu *menu)
517 {
518         struct menu *submenu;
519         const char *prompt = menu_get_prompt(menu);
520         struct symbol *sym;
521         struct menu *active_menu = NULL;
522         int res;
523         int s_scroll = 0;
524
525         while (1) {
526                 item_reset();
527                 current_menu = menu;
528                 build_conf(menu);
529                 if (!child_count)
530                         break;
531                 if (menu == &rootmenu) {
532                         item_make("--- ");
533                         item_set_tag(':');
534                         item_make(_("    Load an Alternate Configuration File"));
535                         item_set_tag('L');
536                         item_make(_("    Save an Alternate Configuration File"));
537                         item_set_tag('S');
538                 }
539                 dialog_clear();
540                 res = dialog_menu(prompt ? _(prompt) : _("Main Menu"),
541                                   _(menu_instructions),
542                                   active_menu, &s_scroll);
543                 if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
544                         break;
545                 if (!item_activate_selected())
546                         continue;
547                 if (!item_tag())
548                         continue;
549
550                 submenu = item_data();
551                 active_menu = item_data();
552                 if (submenu)
553                         sym = submenu->sym;
554                 else
555                         sym = NULL;
556
557                 switch (res) {
558                 case 0:
559                         switch (item_tag()) {
560                         case 'm':
561                                 if (single_menu_mode)
562                                         submenu->data = (void *) (long) !submenu->data;
563                                 else
564                                         conf(submenu);
565                                 break;
566                         case 't':
567                                 if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
568                                         conf_choice(submenu);
569                                 else if (submenu->prompt->type == P_MENU)
570                                         conf(submenu);
571                                 break;
572                         case 's':
573                                 conf_string(submenu);
574                                 break;
575                         case 'L':
576                                 conf_load();
577                                 break;
578                         case 'S':
579                                 conf_save();
580                                 break;
581                         }
582                         break;
583                 case 2:
584                         if (sym)
585                                 show_help(submenu);
586                         else
587                                 show_helptext(_("README"), _(mconf_readme));
588                         break;
589                 case 3:
590                         if (item_is_tag('t')) {
591                                 if (sym_set_tristate_value(sym, yes))
592                                         break;
593                                 if (sym_set_tristate_value(sym, mod))
594                                         show_textbox(NULL, setmod_text, 6, 74);
595                         }
596                         break;
597                 case 4:
598                         if (item_is_tag('t'))
599                                 sym_set_tristate_value(sym, no);
600                         break;
601                 case 5:
602                         if (item_is_tag('t'))
603                                 sym_set_tristate_value(sym, mod);
604                         break;
605                 case 6:
606                         if (item_is_tag('t'))
607                                 sym_toggle_tristate_value(sym);
608                         else if (item_is_tag('m'))
609                                 conf(submenu);
610                         break;
611                 case 7:
612                         search_conf();
613                         break;
614                 case 8:
615                         show_all_options = !show_all_options;
616                         break;
617                 }
618         }
619 }
620
621 static void show_textbox(const char *title, const char *text, int r, int c)
622 {
623         dialog_clear();
624         dialog_textbox(title, text, r, c);
625 }
626
627 static void show_helptext(const char *title, const char *text)
628 {
629         show_textbox(title, text, 0, 0);
630 }
631
632 static void show_help(struct menu *menu)
633 {
634         struct gstr help = str_new();
635
636         help.max_width = getmaxx(stdscr) - 10;
637         menu_get_ext_help(menu, &help);
638
639         show_helptext(_(menu_get_prompt(menu)), str_get(&help));
640         str_free(&help);
641 }
642
643 static void conf_choice(struct menu *menu)
644 {
645         const char *prompt = _(menu_get_prompt(menu));
646         struct menu *child;
647         struct symbol *active;
648
649         active = sym_get_choice_value(menu->sym);
650         while (1) {
651                 int res;
652                 int selected;
653                 item_reset();
654
655                 current_menu = menu;
656                 for (child = menu->list; child; child = child->next) {
657                         if (!menu_is_visible(child))
658                                 continue;
659                         if (child->sym)
660                                 item_make("%s", _(menu_get_prompt(child)));
661                         else {
662                                 item_make("*** %s ***", _(menu_get_prompt(child)));
663                                 item_set_tag(':');
664                         }
665                         item_set_data(child);
666                         if (child->sym == active)
667                                 item_set_selected(1);
668                         if (child->sym == sym_get_choice_value(menu->sym))
669                                 item_set_tag('X');
670                 }
671                 dialog_clear();
672                 res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"),
673                                         _(radiolist_instructions),
674                                          15, 70, 6);
675                 selected = item_activate_selected();
676                 switch (res) {
677                 case 0:
678                         if (selected) {
679                                 child = item_data();
680                                 if (!child->sym)
681                                         break;
682
683                                 sym_set_tristate_value(child->sym, yes);
684                         }
685                         return;
686                 case 1:
687                         if (selected) {
688                                 child = item_data();
689                                 show_help(child);
690                                 active = child->sym;
691                         } else
692                                 show_help(menu);
693                         break;
694                 case KEY_ESC:
695                         return;
696                 case -ERRDISPLAYTOOSMALL:
697                         return;
698                 }
699         }
700 }
701
702 static void conf_string(struct menu *menu)
703 {
704         const char *prompt = menu_get_prompt(menu);
705
706         while (1) {
707                 int res;
708                 const char *heading;
709
710                 switch (sym_get_type(menu->sym)) {
711                 case S_INT:
712                         heading = _(inputbox_instructions_int);
713                         break;
714                 case S_HEX:
715                         heading = _(inputbox_instructions_hex);
716                         break;
717                 case S_STRING:
718                         heading = _(inputbox_instructions_string);
719                         break;
720                 default:
721                         heading = _("Internal mconf error!");
722                 }
723                 dialog_clear();
724                 res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"),
725                                       heading, 10, 75,
726                                       sym_get_string_value(menu->sym));
727                 switch (res) {
728                 case 0:
729                         if (sym_set_string_value(menu->sym, dialog_input_result))
730                                 return;
731                         show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
732                         break;
733                 case 1:
734                         show_help(menu);
735                         break;
736                 case KEY_ESC:
737                         return;
738                 }
739         }
740 }
741
742 static void conf_load(void)
743 {
744
745         while (1) {
746                 int res;
747                 dialog_clear();
748                 res = dialog_inputbox(NULL, load_config_text,
749                                       11, 55, filename);
750                 switch(res) {
751                 case 0:
752                         if (!dialog_input_result[0])
753                                 return;
754                         if (!conf_read(dialog_input_result)) {
755                                 set_config_filename(dialog_input_result);
756                                 sym_set_change_count(1);
757                                 return;
758                         }
759                         show_textbox(NULL, _("File does not exist!"), 5, 38);
760                         break;
761                 case 1:
762                         show_helptext(_("Load Alternate Configuration"), load_config_help);
763                         break;
764                 case KEY_ESC:
765                         return;
766                 }
767         }
768 }
769
770 static void conf_save(void)
771 {
772         while (1) {
773                 int res;
774                 dialog_clear();
775                 res = dialog_inputbox(NULL, save_config_text,
776                                       11, 55, filename);
777                 switch(res) {
778                 case 0:
779                         if (!dialog_input_result[0])
780                                 return;
781                         if (!conf_write(dialog_input_result)) {
782                                 set_config_filename(dialog_input_result);
783                                 return;
784                         }
785                         show_textbox(NULL, _("Can't create file!  Probably a nonexistent directory."), 5, 60);
786                         break;
787                 case 1:
788                         show_helptext(_("Save Alternate Configuration"), save_config_help);
789                         break;
790                 case KEY_ESC:
791                         return;
792                 }
793         }
794 }
795
796 int main(int ac, char **av)
797 {
798         int saved_x, saved_y;
799         char *mode;
800         int res;
801
802         setlocale(LC_ALL, "");
803         bindtextdomain(PACKAGE, LOCALEDIR);
804         textdomain(PACKAGE);
805
806         conf_parse(av[1]);
807         conf_read(NULL);
808
809         mode = getenv("MENUCONFIG_MODE");
810         if (mode) {
811                 if (!strcasecmp(mode, "single_menu"))
812                         single_menu_mode = 1;
813         }
814
815         initscr();
816
817         getyx(stdscr, saved_y, saved_x);
818         if (init_dialog(NULL)) {
819                 fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
820                 fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
821                 return 1;
822         }
823
824         set_config_filename(conf_get_configname());
825         do {
826                 conf(&rootmenu);
827                 dialog_clear();
828                 if (conf_get_changed())
829                         res = dialog_yesno(NULL,
830                                            _("Do you wish to save your "
831                                              "new configuration?\n"
832                                              "<ESC><ESC> to continue."),
833                                            6, 60);
834                 else
835                         res = -1;
836         } while (res == KEY_ESC);
837         end_dialog(saved_x, saved_y);
838
839         switch (res) {
840         case 0:
841                 if (conf_write(filename)) {
842                         fprintf(stderr, _("\n\n"
843                                 "Error while writing of the configuration.\n"
844                                 "Your configuration changes were NOT saved."
845                                 "\n\n"));
846                         return 1;
847                 }
848         case -1:
849                 printf(_("\n\n"
850                         "*** End of the configuration.\n"
851                         "*** Execute 'make' to start the build or try 'make help'."
852                         "\n\n"));
853                 break;
854         default:
855                 fprintf(stderr, _("\n\n"
856                         "Your configuration changes were NOT saved."
857                         "\n\n"));
858         }
859
860         return 0;
861 }
862