pass HOST_ variables, not BUILD_
[buildroot.git] / package / config / mconf.c
blob7587891b62ba13d565c16022eaac9325c57b0fce
1 /*
2 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3 * Released under the terms of the GNU GPL v2.0.
5 * Introduced single menu mode (show all sub-menus in one large tree).
6 * 2002-11-06 Petr Baudis <pasky@ucw.cz>
8 * i18n, 2005, Arnaldo Carvalho de Melo <acme@conectiva.com.br>
9 */
11 #include <sys/ioctl.h>
12 #include <sys/wait.h>
13 #include <ctype.h>
14 #include <errno.h>
15 #include <fcntl.h>
16 #include <limits.h>
17 #include <signal.h>
18 #include <stdarg.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <termios.h>
22 #include <unistd.h>
23 #include <locale.h>
25 #define LKC_DIRECT_LINK
26 #include "lkc.h"
27 #include "lxdialog/dialog.h"
29 static const char mconf_readme[] = N_(
30 "Overview\n"
31 "--------\n"
32 "Some features may be built directly into Buildroot. Some features\n"
33 "may be completely removed altogether. There are also certain\n"
34 "parameters which are not really features, but must be\n"
35 "entered in as decimal or hexadecimal numbers or possibly text.\n"
36 "\n"
37 "Menu items beginning with following braces represent features that\n"
38 " [ ] can be built in or removed\n"
39 " < > can be built in, modularized or removed\n"
40 " { } can be built in or modularized (selected by other feature)\n"
41 " - - are selected by other feature,\n"
42 "while *, M or whitespace inside braces means to build in, build as\n"
43 "a module or to exclude the feature respectively.\n"
44 "\n"
45 "To change any of these features, highlight it with the cursor\n"
46 "keys and press <Y> to build it in, <M> to make it a module or\n"
47 "<N> to removed it. You may also press the <Space Bar> to cycle\n"
48 "through the available options (ie. Y->N->M->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 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 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> selectes a feature, while <N> will exclude a feature. "
185 "Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
186 "Legend: [*] feature is selected [ ] feature is excluded"),
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 nohelp_text[] = N_(
206 "There is no help available for this option.\n"),
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 Buildroot\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 "Buildroot'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 therefor 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 Buildroot\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");
276 static int indent;
277 static struct termios ios_org;
278 static int rows = 0, cols = 0;
279 static struct menu *current_menu;
280 static int child_count;
281 static int single_menu_mode;
283 static void conf(struct menu *menu);
284 static void conf_choice(struct menu *menu);
285 static void conf_string(struct menu *menu);
286 static void conf_load(void);
287 static void conf_save(void);
288 static void show_textbox(const char *title, const char *text, int r, int c);
289 static void show_helptext(const char *title, const char *text);
290 static void show_help(struct menu *menu);
292 static void init_wsize(void)
294 struct winsize ws;
295 char *env;
297 if (!ioctl(STDIN_FILENO, TIOCGWINSZ, &ws)) {
298 rows = ws.ws_row;
299 cols = ws.ws_col;
302 if (!rows) {
303 env = getenv("LINES");
304 if (env)
305 rows = atoi(env);
306 if (!rows)
307 rows = 24;
309 if (!cols) {
310 env = getenv("COLUMNS");
311 if (env)
312 cols = atoi(env);
313 if (!cols)
314 cols = 80;
317 if (rows < 19 || cols < 80) {
318 fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
319 fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
320 exit(1);
323 rows -= 4;
324 cols -= 5;
327 static void get_prompt_str(struct gstr *r, struct property *prop)
329 int i, j;
330 struct menu *submenu[8], *menu;
332 str_printf(r, "Prompt: %s\n", prop->text);
333 str_printf(r, " Defined at %s:%d\n", prop->menu->file->name,
334 prop->menu->lineno);
335 if (!expr_is_yes(prop->visible.expr)) {
336 str_append(r, " Depends on: ");
337 expr_gstr_print(prop->visible.expr, r);
338 str_append(r, "\n");
340 menu = prop->menu->parent;
341 for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
342 submenu[i++] = menu;
343 if (i > 0) {
344 str_printf(r, " Location:\n");
345 for (j = 4; --i >= 0; j += 2) {
346 menu = submenu[i];
347 str_printf(r, "%*c-> %s", j, ' ', menu_get_prompt(menu));
348 if (menu->sym) {
349 str_printf(r, " (%s [=%s])", menu->sym->name ?
350 menu->sym->name : "<choice>",
351 sym_get_string_value(menu->sym));
353 str_append(r, "\n");
358 static void get_symbol_str(struct gstr *r, struct symbol *sym)
360 bool hit;
361 struct property *prop;
363 if (sym && sym->name)
364 str_printf(r, "Symbol: %s [=%s]\n", sym->name,
365 sym_get_string_value(sym));
366 for_all_prompts(sym, prop)
367 get_prompt_str(r, prop);
368 hit = false;
369 for_all_properties(sym, prop, P_SELECT) {
370 if (!hit) {
371 str_append(r, " Selects: ");
372 hit = true;
373 } else
374 str_printf(r, " && ");
375 expr_gstr_print(prop->expr, r);
377 if (hit)
378 str_append(r, "\n");
379 if (sym->rev_dep.expr) {
380 str_append(r, " Selected by: ");
381 expr_gstr_print(sym->rev_dep.expr, r);
382 str_append(r, "\n");
384 str_append(r, "\n\n");
387 static struct gstr get_relations_str(struct symbol **sym_arr)
389 struct symbol *sym;
390 struct gstr res = str_new();
391 int i;
393 for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
394 get_symbol_str(&res, sym);
395 if (!i)
396 str_append(&res, "No matches found.\n");
397 return res;
400 static char filename[PATH_MAX+1];
401 static void set_config_filename(const char *config_filename)
403 static char menu_backtitle[PATH_MAX+128];
404 int size;
405 struct symbol *sym;
407 sym = sym_lookup("BR2_VERSION", 0);
408 sym_calc_value(sym);
409 size = snprintf(menu_backtitle, sizeof(menu_backtitle),
410 _("%s - buildroot v%s Configuration"),
411 config_filename, sym_get_string_value(sym));
412 if (size >= sizeof(menu_backtitle))
413 menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
414 set_dialog_backtitle(menu_backtitle);
416 size = snprintf(filename, sizeof(filename), "%s", config_filename);
417 if (size >= sizeof(filename))
418 filename[sizeof(filename)-1] = '\0';
422 static void search_conf(void)
424 struct symbol **sym_arr;
425 struct gstr res;
426 char *dialog_input;
427 int dres;
428 again:
429 dialog_clear();
430 dres = dialog_inputbox(_("Search Configuration Parameter"),
431 _("Enter CONFIG_ (sub)string to search for "
432 "(with or without \"CONFIG\")"),
433 10, 75, "");
434 switch (dres) {
435 case 0:
436 break;
437 case 1:
438 show_helptext(_("Search Configuration"), search_help);
439 goto again;
440 default:
441 return;
444 /* strip CONFIG_ if necessary */
445 dialog_input = dialog_input_result;
446 if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0)
447 dialog_input += 7;
449 sym_arr = sym_re_search(dialog_input);
450 res = get_relations_str(sym_arr);
451 free(sym_arr);
452 show_textbox(_("Search Results"), str_get(&res), 0, 0);
453 str_free(&res);
456 static void build_conf(struct menu *menu)
458 struct symbol *sym;
459 struct property *prop;
460 struct menu *child;
461 int type, tmp, doint = 2;
462 tristate val;
463 char ch;
465 if (!menu_is_visible(menu))
466 return;
468 sym = menu->sym;
469 prop = menu->prompt;
470 if (!sym) {
471 if (prop && menu != current_menu) {
472 const char *prompt = menu_get_prompt(menu);
473 switch (prop->type) {
474 case P_MENU:
475 child_count++;
476 if (single_menu_mode) {
477 item_make("%s%*c%s",
478 menu->data ? "-->" : "++>",
479 indent + 1, ' ', prompt);
480 } else
481 item_make(" %*c%s --->", indent + 1, ' ', prompt);
483 item_set_tag('m');
484 item_set_data(menu);
485 if (single_menu_mode && menu->data)
486 goto conf_childs;
487 return;
488 case P_COMMENT:
489 if (prompt) {
490 child_count++;
491 item_make(" %*c*** %s ***", indent + 1, ' ', prompt);
492 item_set_tag(':');
493 item_set_data(menu);
495 break;
496 default:
497 if (prompt) {
498 child_count++;
499 item_make("---%*c%s", indent + 1, ' ', prompt);
500 item_set_tag(':');
501 item_set_data(menu);
504 } else
505 doint = 0;
506 goto conf_childs;
509 type = sym_get_type(sym);
510 if (sym_is_choice(sym)) {
511 struct symbol *def_sym = sym_get_choice_value(sym);
512 struct menu *def_menu = NULL;
514 child_count++;
515 for (child = menu->list; child; child = child->next) {
516 if (menu_is_visible(child) && child->sym == def_sym)
517 def_menu = child;
520 val = sym_get_tristate_value(sym);
521 if (sym_is_changable(sym)) {
522 switch (type) {
523 case S_BOOLEAN:
524 item_make("[%c]", val == no ? ' ' : '*');
525 break;
526 case S_TRISTATE:
527 switch (val) {
528 case yes: ch = '*'; break;
529 case mod: ch = 'M'; break;
530 default: ch = ' '; break;
532 item_make("<%c>", ch);
533 break;
535 item_set_tag('t');
536 item_set_data(menu);
537 } else {
538 item_make(" ");
539 item_set_tag(def_menu ? 't' : ':');
540 item_set_data(menu);
543 item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
544 if (val == yes) {
545 if (def_menu) {
546 item_add_str(" (%s)", menu_get_prompt(def_menu));
547 item_add_str(" --->");
548 if (def_menu->list) {
549 indent += 2;
550 build_conf(def_menu);
551 indent -= 2;
554 return;
556 } else {
557 if (menu == current_menu) {
558 item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
559 item_set_tag(':');
560 item_set_data(menu);
561 goto conf_childs;
563 child_count++;
564 val = sym_get_tristate_value(sym);
565 if (sym_is_choice_value(sym) && val == yes) {
566 item_make(" ");
567 item_set_tag(':');
568 item_set_data(menu);
569 } else {
570 switch (type) {
571 case S_BOOLEAN:
572 if (sym_is_changable(sym))
573 item_make("[%c]", val == no ? ' ' : '*');
574 else
575 item_make("-%c-", val == no ? ' ' : '*');
576 item_set_tag('t');
577 item_set_data(menu);
578 break;
579 case S_TRISTATE:
580 switch (val) {
581 case yes: ch = '*'; break;
582 case mod: ch = 'M'; break;
583 default: ch = ' '; break;
585 if (sym_is_changable(sym)) {
586 if (sym->rev_dep.tri == mod)
587 item_make("{%c}", ch);
588 else
589 item_make("<%c>", ch);
590 } else
591 item_make("-%c-", ch);
592 item_set_tag('t');
593 item_set_data(menu);
594 break;
595 default:
596 tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
597 item_make("(%s)", sym_get_string_value(sym));
598 tmp = indent - tmp + 4;
599 if (tmp < 0)
600 tmp = 0;
601 item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
602 (sym_has_value(sym) || !sym_is_changable(sym)) ?
603 "" : " (NEW)");
604 item_set_tag('s');
605 item_set_data(menu);
606 goto conf_childs;
609 item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
610 (sym_has_value(sym) || !sym_is_changable(sym)) ?
611 "" : " (NEW)");
612 if (menu->prompt->type == P_MENU) {
613 item_add_str(" --->");
614 return;
618 conf_childs:
619 indent += doint;
620 for (child = menu->list; child; child = child->next)
621 build_conf(child);
622 indent -= doint;
625 static void conf(struct menu *menu)
627 struct menu *submenu;
628 const char *prompt = menu_get_prompt(menu);
629 struct symbol *sym;
630 struct menu *active_menu = NULL;
631 int res;
632 int s_scroll = 0;
634 while (1) {
635 item_reset();
636 current_menu = menu;
637 build_conf(menu);
638 if (!child_count)
639 break;
640 if (menu == &rootmenu) {
641 item_make("--- ");
642 item_set_tag(':');
643 item_make(_(" Load an Alternate Configuration File"));
644 item_set_tag('L');
645 item_make(_(" Save an Alternate Configuration File"));
646 item_set_tag('S');
648 dialog_clear();
649 res = dialog_menu(prompt ? prompt : _("Main Menu"),
650 _(menu_instructions),
651 active_menu, &s_scroll);
652 if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
653 break;
654 if (!item_activate_selected())
655 continue;
656 if (!item_tag())
657 continue;
659 submenu = item_data();
660 active_menu = item_data();
661 if (submenu)
662 sym = submenu->sym;
663 else
664 sym = NULL;
666 switch (res) {
667 case 0:
668 switch (item_tag()) {
669 case 'm':
670 if (single_menu_mode)
671 submenu->data = (void *) (long) !submenu->data;
672 else
673 conf(submenu);
674 break;
675 case 't':
676 if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
677 conf_choice(submenu);
678 else if (submenu->prompt->type == P_MENU)
679 conf(submenu);
680 break;
681 case 's':
682 conf_string(submenu);
683 break;
684 case 'L':
685 conf_load();
686 break;
687 case 'S':
688 conf_save();
689 break;
691 break;
692 case 2:
693 if (sym)
694 show_help(submenu);
695 else
696 show_helptext("README", _(mconf_readme));
697 break;
698 case 3:
699 if (item_is_tag('t')) {
700 if (sym_set_tristate_value(sym, yes))
701 break;
702 if (sym_set_tristate_value(sym, mod))
703 show_textbox(NULL, setmod_text, 6, 74);
705 break;
706 case 4:
707 if (item_is_tag('t'))
708 sym_set_tristate_value(sym, no);
709 break;
710 case 5:
711 if (item_is_tag('t'))
712 sym_set_tristate_value(sym, mod);
713 break;
714 case 6:
715 if (item_is_tag('t'))
716 sym_toggle_tristate_value(sym);
717 else if (item_is_tag('m'))
718 conf(submenu);
719 break;
720 case 7:
721 search_conf();
722 break;
727 static void show_textbox(const char *title, const char *text, int r, int c)
729 dialog_clear();
730 dialog_textbox(title, text, r, c);
733 static void show_helptext(const char *title, const char *text)
735 show_textbox(title, text, 0, 0);
738 static void show_help(struct menu *menu)
740 struct gstr help = str_new();
741 struct symbol *sym = menu->sym;
743 if (menu_has_help(menu))
745 if (sym->name) {
746 str_printf(&help, "%s:\n\n", sym->name);
747 str_append(&help, _(menu_get_help(menu)));
748 str_append(&help, "\n");
750 } else {
751 str_append(&help, nohelp_text);
753 get_symbol_str(&help, sym);
754 show_helptext(menu_get_prompt(menu), str_get(&help));
755 str_free(&help);
758 static void conf_choice(struct menu *menu)
760 const char *prompt = menu_get_prompt(menu);
761 struct menu *child;
762 struct symbol *active;
764 active = sym_get_choice_value(menu->sym);
765 while (1) {
766 int res;
767 int selected;
768 item_reset();
770 current_menu = menu;
771 for (child = menu->list; child; child = child->next) {
772 if (!menu_is_visible(child))
773 continue;
774 item_make("%s", menu_get_prompt(child));
775 item_set_data(child);
776 if (child->sym == active)
777 item_set_selected(1);
778 if (child->sym == sym_get_choice_value(menu->sym))
779 item_set_tag('X');
781 dialog_clear();
782 res = dialog_checklist(prompt ? prompt : _("Main Menu"),
783 _(radiolist_instructions),
784 15, 70, 6);
785 selected = item_activate_selected();
786 switch (res) {
787 case 0:
788 if (selected) {
789 child = item_data();
790 sym_set_tristate_value(child->sym, yes);
792 return;
793 case 1:
794 if (selected) {
795 child = item_data();
796 show_help(child);
797 active = child->sym;
798 } else
799 show_help(menu);
800 break;
801 case KEY_ESC:
802 return;
803 case -ERRDISPLAYTOOSMALL:
804 return;
809 static void conf_string(struct menu *menu)
811 const char *prompt = menu_get_prompt(menu);
813 while (1) {
814 int res;
815 char *heading;
817 switch (sym_get_type(menu->sym)) {
818 case S_INT:
819 heading = _(inputbox_instructions_int);
820 break;
821 case S_HEX:
822 heading = _(inputbox_instructions_hex);
823 break;
824 case S_STRING:
825 heading = _(inputbox_instructions_string);
826 break;
827 default:
828 heading = "Internal mconf error!";
830 dialog_clear();
831 res = dialog_inputbox(prompt ? prompt : _("Main Menu"),
832 heading, 10, 75,
833 sym_get_string_value(menu->sym));
834 switch (res) {
835 case 0:
836 if (sym_set_string_value(menu->sym, dialog_input_result))
837 return;
838 show_textbox(NULL, _("You have made an invalid entry."), 5, 43);
839 break;
840 case 1:
841 show_help(menu);
842 break;
843 case KEY_ESC:
844 return;
849 static void conf_load(void)
852 while (1) {
853 int res;
854 dialog_clear();
855 res = dialog_inputbox(NULL, load_config_text,
856 11, 55, filename);
857 switch(res) {
858 case 0:
859 if (!dialog_input_result[0])
860 return;
861 if (!conf_read(dialog_input_result)) {
862 set_config_filename(dialog_input_result);
863 return;
865 show_textbox(NULL, _("File does not exist!"), 5, 38);
866 break;
867 case 1:
868 show_helptext(_("Load Alternate Configuration"), load_config_help);
869 break;
870 case KEY_ESC:
871 return;
876 static void conf_save(void)
878 while (1) {
879 int res;
880 dialog_clear();
881 res = dialog_inputbox(NULL, save_config_text,
882 11, 55, filename);
883 switch(res) {
884 case 0:
885 if (!dialog_input_result[0])
886 return;
887 if (!conf_write(dialog_input_result)) {
888 set_config_filename(dialog_input_result);
889 return;
891 show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60);
892 break;
893 case 1:
894 show_helptext(_("Save Alternate Configuration"), save_config_help);
895 break;
896 case KEY_ESC:
897 return;
902 static void conf_cleanup(void)
904 tcsetattr(1, TCSAFLUSH, &ios_org);
907 int main(int ac, char **av)
909 char *mode;
910 int res;
912 setlocale(LC_ALL, "");
913 bindtextdomain(PACKAGE, LOCALEDIR);
914 textdomain(PACKAGE);
916 conf_parse(av[1]);
917 conf_read(NULL);
919 mode = getenv("MENUCONFIG_MODE");
920 if (mode) {
921 if (!strcasecmp(mode, "single_menu"))
922 single_menu_mode = 1;
925 tcgetattr(1, &ios_org);
926 atexit(conf_cleanup);
927 init_wsize();
928 reset_dialog();
929 init_dialog(NULL);
930 set_config_filename(conf_get_configname());
931 do {
932 conf(&rootmenu);
933 dialog_clear();
934 if (conf_get_changed())
935 res = dialog_yesno(NULL,
936 _("Do you wish to save your "
937 "new Buildroot configuration?\n"
938 "<ESC><ESC> to continue."),
939 6, 60);
940 else
941 res = -1;
942 } while (res == KEY_ESC);
943 end_dialog();
945 switch (res) {
946 case 0:
947 if (conf_write(filename)) {
948 fprintf(stderr, _("\n\n"
949 "Error during writing of the Buildroot configuration.\n"
950 "Your Buildroot configuration changes were NOT saved."
951 "\n\n"));
952 return 1;
954 case -1:
955 printf(_("\n\n"
956 "*** End of Buildroot configuration.\n"
957 "*** Execute 'make' to build Buildroot or try 'make help'."
958 "\n\n"));
959 break;
960 default:
961 fprintf(stderr, _("\n\n"
962 "Your Buildroot configuration changes were NOT saved."
963 "\n\n"));
966 return conf_write_autoconf();