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