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