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