xref: /OK3568_Linux_fs/kernel/scripts/kconfig/mconf.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
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 <strings.h>
19*4882a593Smuzhiyun #include <signal.h>
20*4882a593Smuzhiyun #include <unistd.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #include "lkc.h"
23*4882a593Smuzhiyun #include "lxdialog/dialog.h"
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun static const char mconf_readme[] =
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[] =
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[] =
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[] =
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[] =
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[] =
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[] =
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[] =
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[] =
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[] =
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[] =
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[] =
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 (bool, 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 				sprintf(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 				if (single_menu_mode) {
495*4882a593Smuzhiyun 					item_make("%s%*c%s",
496*4882a593Smuzhiyun 						  menu->data ? "-->" : "++>",
497*4882a593Smuzhiyun 						  indent + 1, ' ', prompt);
498*4882a593Smuzhiyun 				} else
499*4882a593Smuzhiyun 					item_make("   %*c%s  %s",
500*4882a593Smuzhiyun 						  indent + 1, ' ', prompt,
501*4882a593Smuzhiyun 						  menu_is_empty(menu) ? "----" : "--->");
502*4882a593Smuzhiyun 				item_set_tag('m');
503*4882a593Smuzhiyun 				item_set_data(menu);
504*4882a593Smuzhiyun 				if (single_menu_mode && menu->data)
505*4882a593Smuzhiyun 					goto conf_childs;
506*4882a593Smuzhiyun 				return;
507*4882a593Smuzhiyun 			case P_COMMENT:
508*4882a593Smuzhiyun 				if (prompt) {
509*4882a593Smuzhiyun 					child_count++;
510*4882a593Smuzhiyun 					item_make("   %*c*** %s ***", indent + 1, ' ', prompt);
511*4882a593Smuzhiyun 					item_set_tag(':');
512*4882a593Smuzhiyun 					item_set_data(menu);
513*4882a593Smuzhiyun 				}
514*4882a593Smuzhiyun 				break;
515*4882a593Smuzhiyun 			default:
516*4882a593Smuzhiyun 				if (prompt) {
517*4882a593Smuzhiyun 					child_count++;
518*4882a593Smuzhiyun 					item_make("---%*c%s", indent + 1, ' ', prompt);
519*4882a593Smuzhiyun 					item_set_tag(':');
520*4882a593Smuzhiyun 					item_set_data(menu);
521*4882a593Smuzhiyun 				}
522*4882a593Smuzhiyun 			}
523*4882a593Smuzhiyun 		} else
524*4882a593Smuzhiyun 			doint = 0;
525*4882a593Smuzhiyun 		goto conf_childs;
526*4882a593Smuzhiyun 	}
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 	type = sym_get_type(sym);
529*4882a593Smuzhiyun 	if (sym_is_choice(sym)) {
530*4882a593Smuzhiyun 		struct symbol *def_sym = sym_get_choice_value(sym);
531*4882a593Smuzhiyun 		struct menu *def_menu = NULL;
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun 		child_count++;
534*4882a593Smuzhiyun 		for (child = menu->list; child; child = child->next) {
535*4882a593Smuzhiyun 			if (menu_is_visible(child) && child->sym == def_sym)
536*4882a593Smuzhiyun 				def_menu = child;
537*4882a593Smuzhiyun 		}
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 		val = sym_get_tristate_value(sym);
540*4882a593Smuzhiyun 		if (sym_is_changeable(sym)) {
541*4882a593Smuzhiyun 			switch (type) {
542*4882a593Smuzhiyun 			case S_BOOLEAN:
543*4882a593Smuzhiyun 				item_make("[%c]", val == no ? ' ' : '*');
544*4882a593Smuzhiyun 				break;
545*4882a593Smuzhiyun 			case S_TRISTATE:
546*4882a593Smuzhiyun 				switch (val) {
547*4882a593Smuzhiyun 				case yes: ch = '*'; break;
548*4882a593Smuzhiyun 				case mod: ch = 'M'; break;
549*4882a593Smuzhiyun 				default:  ch = ' '; break;
550*4882a593Smuzhiyun 				}
551*4882a593Smuzhiyun 				item_make("<%c>", ch);
552*4882a593Smuzhiyun 				break;
553*4882a593Smuzhiyun 			}
554*4882a593Smuzhiyun 			item_set_tag('t');
555*4882a593Smuzhiyun 			item_set_data(menu);
556*4882a593Smuzhiyun 		} else {
557*4882a593Smuzhiyun 			item_make("   ");
558*4882a593Smuzhiyun 			item_set_tag(def_menu ? 't' : ':');
559*4882a593Smuzhiyun 			item_set_data(menu);
560*4882a593Smuzhiyun 		}
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun 		item_add_str("%*c%s", indent + 1, ' ', menu_get_prompt(menu));
563*4882a593Smuzhiyun 		if (val == yes) {
564*4882a593Smuzhiyun 			if (def_menu) {
565*4882a593Smuzhiyun 				item_add_str(" (%s)", menu_get_prompt(def_menu));
566*4882a593Smuzhiyun 				item_add_str("  --->");
567*4882a593Smuzhiyun 				if (def_menu->list) {
568*4882a593Smuzhiyun 					indent += 2;
569*4882a593Smuzhiyun 					build_conf(def_menu);
570*4882a593Smuzhiyun 					indent -= 2;
571*4882a593Smuzhiyun 				}
572*4882a593Smuzhiyun 			}
573*4882a593Smuzhiyun 			return;
574*4882a593Smuzhiyun 		}
575*4882a593Smuzhiyun 	} else {
576*4882a593Smuzhiyun 		if (menu == current_menu) {
577*4882a593Smuzhiyun 			item_make("---%*c%s", indent + 1, ' ', menu_get_prompt(menu));
578*4882a593Smuzhiyun 			item_set_tag(':');
579*4882a593Smuzhiyun 			item_set_data(menu);
580*4882a593Smuzhiyun 			goto conf_childs;
581*4882a593Smuzhiyun 		}
582*4882a593Smuzhiyun 		child_count++;
583*4882a593Smuzhiyun 		val = sym_get_tristate_value(sym);
584*4882a593Smuzhiyun 		if (sym_is_choice_value(sym) && val == yes) {
585*4882a593Smuzhiyun 			item_make("   ");
586*4882a593Smuzhiyun 			item_set_tag(':');
587*4882a593Smuzhiyun 			item_set_data(menu);
588*4882a593Smuzhiyun 		} else {
589*4882a593Smuzhiyun 			switch (type) {
590*4882a593Smuzhiyun 			case S_BOOLEAN:
591*4882a593Smuzhiyun 				if (sym_is_changeable(sym))
592*4882a593Smuzhiyun 					item_make("[%c]", val == no ? ' ' : '*');
593*4882a593Smuzhiyun 				else
594*4882a593Smuzhiyun 					item_make("-%c-", val == no ? ' ' : '*');
595*4882a593Smuzhiyun 				item_set_tag('t');
596*4882a593Smuzhiyun 				item_set_data(menu);
597*4882a593Smuzhiyun 				break;
598*4882a593Smuzhiyun 			case S_TRISTATE:
599*4882a593Smuzhiyun 				switch (val) {
600*4882a593Smuzhiyun 				case yes: ch = '*'; break;
601*4882a593Smuzhiyun 				case mod: ch = 'M'; break;
602*4882a593Smuzhiyun 				default:  ch = ' '; break;
603*4882a593Smuzhiyun 				}
604*4882a593Smuzhiyun 				if (sym_is_changeable(sym)) {
605*4882a593Smuzhiyun 					if (sym->rev_dep.tri == mod)
606*4882a593Smuzhiyun 						item_make("{%c}", ch);
607*4882a593Smuzhiyun 					else
608*4882a593Smuzhiyun 						item_make("<%c>", ch);
609*4882a593Smuzhiyun 				} else
610*4882a593Smuzhiyun 					item_make("-%c-", ch);
611*4882a593Smuzhiyun 				item_set_tag('t');
612*4882a593Smuzhiyun 				item_set_data(menu);
613*4882a593Smuzhiyun 				break;
614*4882a593Smuzhiyun 			default:
615*4882a593Smuzhiyun 				tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */
616*4882a593Smuzhiyun 				item_make("(%s)", sym_get_string_value(sym));
617*4882a593Smuzhiyun 				tmp = indent - tmp + 4;
618*4882a593Smuzhiyun 				if (tmp < 0)
619*4882a593Smuzhiyun 					tmp = 0;
620*4882a593Smuzhiyun 				item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
621*4882a593Smuzhiyun 					     (sym_has_value(sym) || !sym_is_changeable(sym)) ?
622*4882a593Smuzhiyun 					     "" : " (NEW)");
623*4882a593Smuzhiyun 				item_set_tag('s');
624*4882a593Smuzhiyun 				item_set_data(menu);
625*4882a593Smuzhiyun 				goto conf_childs;
626*4882a593Smuzhiyun 			}
627*4882a593Smuzhiyun 		}
628*4882a593Smuzhiyun 		item_add_str("%*c%s%s", indent + 1, ' ', menu_get_prompt(menu),
629*4882a593Smuzhiyun 			  (sym_has_value(sym) || !sym_is_changeable(sym)) ?
630*4882a593Smuzhiyun 			  "" : " (NEW)");
631*4882a593Smuzhiyun 		if (menu->prompt->type == P_MENU) {
632*4882a593Smuzhiyun 			item_add_str("  %s", menu_is_empty(menu) ? "----" : "--->");
633*4882a593Smuzhiyun 			return;
634*4882a593Smuzhiyun 		}
635*4882a593Smuzhiyun 	}
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun conf_childs:
638*4882a593Smuzhiyun 	indent += doint;
639*4882a593Smuzhiyun 	for (child = menu->list; child; child = child->next)
640*4882a593Smuzhiyun 		build_conf(child);
641*4882a593Smuzhiyun 	indent -= doint;
642*4882a593Smuzhiyun }
643*4882a593Smuzhiyun 
conf(struct menu * menu,struct menu * active_menu)644*4882a593Smuzhiyun static void conf(struct menu *menu, struct menu *active_menu)
645*4882a593Smuzhiyun {
646*4882a593Smuzhiyun 	struct menu *submenu;
647*4882a593Smuzhiyun 	const char *prompt = menu_get_prompt(menu);
648*4882a593Smuzhiyun 	struct subtitle_part stpart;
649*4882a593Smuzhiyun 	struct symbol *sym;
650*4882a593Smuzhiyun 	int res;
651*4882a593Smuzhiyun 	int s_scroll = 0;
652*4882a593Smuzhiyun 
653*4882a593Smuzhiyun 	if (menu != &rootmenu)
654*4882a593Smuzhiyun 		stpart.text = menu_get_prompt(menu);
655*4882a593Smuzhiyun 	else
656*4882a593Smuzhiyun 		stpart.text = NULL;
657*4882a593Smuzhiyun 	list_add_tail(&stpart.entries, &trail);
658*4882a593Smuzhiyun 
659*4882a593Smuzhiyun 	while (1) {
660*4882a593Smuzhiyun 		item_reset();
661*4882a593Smuzhiyun 		current_menu = menu;
662*4882a593Smuzhiyun 		build_conf(menu);
663*4882a593Smuzhiyun 		if (!child_count)
664*4882a593Smuzhiyun 			break;
665*4882a593Smuzhiyun 		set_subtitle();
666*4882a593Smuzhiyun 		dialog_clear();
667*4882a593Smuzhiyun 		res = dialog_menu(prompt ? prompt : "Main Menu",
668*4882a593Smuzhiyun 				  menu_instructions,
669*4882a593Smuzhiyun 				  active_menu, &s_scroll);
670*4882a593Smuzhiyun 		if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL)
671*4882a593Smuzhiyun 			break;
672*4882a593Smuzhiyun 		if (item_count() != 0) {
673*4882a593Smuzhiyun 			if (!item_activate_selected())
674*4882a593Smuzhiyun 				continue;
675*4882a593Smuzhiyun 			if (!item_tag())
676*4882a593Smuzhiyun 				continue;
677*4882a593Smuzhiyun 		}
678*4882a593Smuzhiyun 		submenu = item_data();
679*4882a593Smuzhiyun 		active_menu = item_data();
680*4882a593Smuzhiyun 		if (submenu)
681*4882a593Smuzhiyun 			sym = submenu->sym;
682*4882a593Smuzhiyun 		else
683*4882a593Smuzhiyun 			sym = NULL;
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun 		switch (res) {
686*4882a593Smuzhiyun 		case 0:
687*4882a593Smuzhiyun 			switch (item_tag()) {
688*4882a593Smuzhiyun 			case 'm':
689*4882a593Smuzhiyun 				if (single_menu_mode)
690*4882a593Smuzhiyun 					submenu->data = (void *) (long) !submenu->data;
691*4882a593Smuzhiyun 				else
692*4882a593Smuzhiyun 					conf(submenu, NULL);
693*4882a593Smuzhiyun 				break;
694*4882a593Smuzhiyun 			case 't':
695*4882a593Smuzhiyun 				if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
696*4882a593Smuzhiyun 					conf_choice(submenu);
697*4882a593Smuzhiyun 				else if (submenu->prompt->type == P_MENU)
698*4882a593Smuzhiyun 					conf(submenu, NULL);
699*4882a593Smuzhiyun 				break;
700*4882a593Smuzhiyun 			case 's':
701*4882a593Smuzhiyun 				conf_string(submenu);
702*4882a593Smuzhiyun 				break;
703*4882a593Smuzhiyun 			}
704*4882a593Smuzhiyun 			break;
705*4882a593Smuzhiyun 		case 2:
706*4882a593Smuzhiyun 			if (sym)
707*4882a593Smuzhiyun 				show_help(submenu);
708*4882a593Smuzhiyun 			else {
709*4882a593Smuzhiyun 				reset_subtitle();
710*4882a593Smuzhiyun 				show_helptext("README", mconf_readme);
711*4882a593Smuzhiyun 			}
712*4882a593Smuzhiyun 			break;
713*4882a593Smuzhiyun 		case 3:
714*4882a593Smuzhiyun 			reset_subtitle();
715*4882a593Smuzhiyun 			conf_save();
716*4882a593Smuzhiyun 			break;
717*4882a593Smuzhiyun 		case 4:
718*4882a593Smuzhiyun 			reset_subtitle();
719*4882a593Smuzhiyun 			conf_load();
720*4882a593Smuzhiyun 			break;
721*4882a593Smuzhiyun 		case 5:
722*4882a593Smuzhiyun 			if (item_is_tag('t')) {
723*4882a593Smuzhiyun 				if (sym_set_tristate_value(sym, yes))
724*4882a593Smuzhiyun 					break;
725*4882a593Smuzhiyun 				if (sym_set_tristate_value(sym, mod))
726*4882a593Smuzhiyun 					show_textbox(NULL, setmod_text, 6, 74);
727*4882a593Smuzhiyun 			}
728*4882a593Smuzhiyun 			break;
729*4882a593Smuzhiyun 		case 6:
730*4882a593Smuzhiyun 			if (item_is_tag('t'))
731*4882a593Smuzhiyun 				sym_set_tristate_value(sym, no);
732*4882a593Smuzhiyun 			break;
733*4882a593Smuzhiyun 		case 7:
734*4882a593Smuzhiyun 			if (item_is_tag('t'))
735*4882a593Smuzhiyun 				sym_set_tristate_value(sym, mod);
736*4882a593Smuzhiyun 			break;
737*4882a593Smuzhiyun 		case 8:
738*4882a593Smuzhiyun 			if (item_is_tag('t'))
739*4882a593Smuzhiyun 				sym_toggle_tristate_value(sym);
740*4882a593Smuzhiyun 			else if (item_is_tag('m'))
741*4882a593Smuzhiyun 				conf(submenu, NULL);
742*4882a593Smuzhiyun 			break;
743*4882a593Smuzhiyun 		case 9:
744*4882a593Smuzhiyun 			search_conf();
745*4882a593Smuzhiyun 			break;
746*4882a593Smuzhiyun 		case 10:
747*4882a593Smuzhiyun 			show_all_options = !show_all_options;
748*4882a593Smuzhiyun 			break;
749*4882a593Smuzhiyun 		}
750*4882a593Smuzhiyun 	}
751*4882a593Smuzhiyun 
752*4882a593Smuzhiyun 	list_del(trail.prev);
753*4882a593Smuzhiyun }
754*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)755*4882a593Smuzhiyun static int show_textbox_ext(const char *title, char *text, int r, int c, int
756*4882a593Smuzhiyun 			    *keys, int *vscroll, int *hscroll, update_text_fn
757*4882a593Smuzhiyun 			    update_text, void *data)
758*4882a593Smuzhiyun {
759*4882a593Smuzhiyun 	dialog_clear();
760*4882a593Smuzhiyun 	return dialog_textbox(title, text, r, c, keys, vscroll, hscroll,
761*4882a593Smuzhiyun 			      update_text, data);
762*4882a593Smuzhiyun }
763*4882a593Smuzhiyun 
show_textbox(const char * title,const char * text,int r,int c)764*4882a593Smuzhiyun static void show_textbox(const char *title, const char *text, int r, int c)
765*4882a593Smuzhiyun {
766*4882a593Smuzhiyun 	show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL,
767*4882a593Smuzhiyun 			 NULL, NULL);
768*4882a593Smuzhiyun }
769*4882a593Smuzhiyun 
show_helptext(const char * title,const char * text)770*4882a593Smuzhiyun static void show_helptext(const char *title, const char *text)
771*4882a593Smuzhiyun {
772*4882a593Smuzhiyun 	show_textbox(title, text, 0, 0);
773*4882a593Smuzhiyun }
774*4882a593Smuzhiyun 
conf_message_callback(const char * s)775*4882a593Smuzhiyun static void conf_message_callback(const char *s)
776*4882a593Smuzhiyun {
777*4882a593Smuzhiyun 	if (save_and_exit) {
778*4882a593Smuzhiyun 		if (!silent)
779*4882a593Smuzhiyun 			printf("%s", s);
780*4882a593Smuzhiyun 	} else {
781*4882a593Smuzhiyun 		show_textbox(NULL, s, 6, 60);
782*4882a593Smuzhiyun 	}
783*4882a593Smuzhiyun }
784*4882a593Smuzhiyun 
show_help(struct menu * menu)785*4882a593Smuzhiyun static void show_help(struct menu *menu)
786*4882a593Smuzhiyun {
787*4882a593Smuzhiyun 	struct gstr help = str_new();
788*4882a593Smuzhiyun 
789*4882a593Smuzhiyun 	help.max_width = getmaxx(stdscr) - 10;
790*4882a593Smuzhiyun 	menu_get_ext_help(menu, &help);
791*4882a593Smuzhiyun 
792*4882a593Smuzhiyun 	show_helptext(menu_get_prompt(menu), str_get(&help));
793*4882a593Smuzhiyun 	str_free(&help);
794*4882a593Smuzhiyun }
795*4882a593Smuzhiyun 
conf_choice(struct menu * menu)796*4882a593Smuzhiyun static void conf_choice(struct menu *menu)
797*4882a593Smuzhiyun {
798*4882a593Smuzhiyun 	const char *prompt = menu_get_prompt(menu);
799*4882a593Smuzhiyun 	struct menu *child;
800*4882a593Smuzhiyun 	struct symbol *active;
801*4882a593Smuzhiyun 
802*4882a593Smuzhiyun 	active = sym_get_choice_value(menu->sym);
803*4882a593Smuzhiyun 	while (1) {
804*4882a593Smuzhiyun 		int res;
805*4882a593Smuzhiyun 		int selected;
806*4882a593Smuzhiyun 		item_reset();
807*4882a593Smuzhiyun 
808*4882a593Smuzhiyun 		current_menu = menu;
809*4882a593Smuzhiyun 		for (child = menu->list; child; child = child->next) {
810*4882a593Smuzhiyun 			if (!menu_is_visible(child))
811*4882a593Smuzhiyun 				continue;
812*4882a593Smuzhiyun 			if (child->sym)
813*4882a593Smuzhiyun 				item_make("%s", menu_get_prompt(child));
814*4882a593Smuzhiyun 			else {
815*4882a593Smuzhiyun 				item_make("*** %s ***", menu_get_prompt(child));
816*4882a593Smuzhiyun 				item_set_tag(':');
817*4882a593Smuzhiyun 			}
818*4882a593Smuzhiyun 			item_set_data(child);
819*4882a593Smuzhiyun 			if (child->sym == active)
820*4882a593Smuzhiyun 				item_set_selected(1);
821*4882a593Smuzhiyun 			if (child->sym == sym_get_choice_value(menu->sym))
822*4882a593Smuzhiyun 				item_set_tag('X');
823*4882a593Smuzhiyun 		}
824*4882a593Smuzhiyun 		dialog_clear();
825*4882a593Smuzhiyun 		res = dialog_checklist(prompt ? prompt : "Main Menu",
826*4882a593Smuzhiyun 					radiolist_instructions,
827*4882a593Smuzhiyun 					MENUBOX_HEIGTH_MIN,
828*4882a593Smuzhiyun 					MENUBOX_WIDTH_MIN,
829*4882a593Smuzhiyun 					CHECKLIST_HEIGTH_MIN);
830*4882a593Smuzhiyun 		selected = item_activate_selected();
831*4882a593Smuzhiyun 		switch (res) {
832*4882a593Smuzhiyun 		case 0:
833*4882a593Smuzhiyun 			if (selected) {
834*4882a593Smuzhiyun 				child = item_data();
835*4882a593Smuzhiyun 				if (!child->sym)
836*4882a593Smuzhiyun 					break;
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun 				sym_set_tristate_value(child->sym, yes);
839*4882a593Smuzhiyun 			}
840*4882a593Smuzhiyun 			return;
841*4882a593Smuzhiyun 		case 1:
842*4882a593Smuzhiyun 			if (selected) {
843*4882a593Smuzhiyun 				child = item_data();
844*4882a593Smuzhiyun 				show_help(child);
845*4882a593Smuzhiyun 				active = child->sym;
846*4882a593Smuzhiyun 			} else
847*4882a593Smuzhiyun 				show_help(menu);
848*4882a593Smuzhiyun 			break;
849*4882a593Smuzhiyun 		case KEY_ESC:
850*4882a593Smuzhiyun 			return;
851*4882a593Smuzhiyun 		case -ERRDISPLAYTOOSMALL:
852*4882a593Smuzhiyun 			return;
853*4882a593Smuzhiyun 		}
854*4882a593Smuzhiyun 	}
855*4882a593Smuzhiyun }
856*4882a593Smuzhiyun 
conf_string(struct menu * menu)857*4882a593Smuzhiyun static void conf_string(struct menu *menu)
858*4882a593Smuzhiyun {
859*4882a593Smuzhiyun 	const char *prompt = menu_get_prompt(menu);
860*4882a593Smuzhiyun 
861*4882a593Smuzhiyun 	while (1) {
862*4882a593Smuzhiyun 		int res;
863*4882a593Smuzhiyun 		const char *heading;
864*4882a593Smuzhiyun 
865*4882a593Smuzhiyun 		switch (sym_get_type(menu->sym)) {
866*4882a593Smuzhiyun 		case S_INT:
867*4882a593Smuzhiyun 			heading = inputbox_instructions_int;
868*4882a593Smuzhiyun 			break;
869*4882a593Smuzhiyun 		case S_HEX:
870*4882a593Smuzhiyun 			heading = inputbox_instructions_hex;
871*4882a593Smuzhiyun 			break;
872*4882a593Smuzhiyun 		case S_STRING:
873*4882a593Smuzhiyun 			heading = inputbox_instructions_string;
874*4882a593Smuzhiyun 			break;
875*4882a593Smuzhiyun 		default:
876*4882a593Smuzhiyun 			heading = "Internal mconf error!";
877*4882a593Smuzhiyun 		}
878*4882a593Smuzhiyun 		dialog_clear();
879*4882a593Smuzhiyun 		res = dialog_inputbox(prompt ? prompt : "Main Menu",
880*4882a593Smuzhiyun 				      heading, 10, 75,
881*4882a593Smuzhiyun 				      sym_get_string_value(menu->sym));
882*4882a593Smuzhiyun 		switch (res) {
883*4882a593Smuzhiyun 		case 0:
884*4882a593Smuzhiyun 			if (sym_set_string_value(menu->sym, dialog_input_result))
885*4882a593Smuzhiyun 				return;
886*4882a593Smuzhiyun 			show_textbox(NULL, "You have made an invalid entry.", 5, 43);
887*4882a593Smuzhiyun 			break;
888*4882a593Smuzhiyun 		case 1:
889*4882a593Smuzhiyun 			show_help(menu);
890*4882a593Smuzhiyun 			break;
891*4882a593Smuzhiyun 		case KEY_ESC:
892*4882a593Smuzhiyun 			return;
893*4882a593Smuzhiyun 		}
894*4882a593Smuzhiyun 	}
895*4882a593Smuzhiyun }
896*4882a593Smuzhiyun 
conf_load(void)897*4882a593Smuzhiyun static void conf_load(void)
898*4882a593Smuzhiyun {
899*4882a593Smuzhiyun 
900*4882a593Smuzhiyun 	while (1) {
901*4882a593Smuzhiyun 		int res;
902*4882a593Smuzhiyun 		dialog_clear();
903*4882a593Smuzhiyun 		res = dialog_inputbox(NULL, load_config_text,
904*4882a593Smuzhiyun 				      11, 55, filename);
905*4882a593Smuzhiyun 		switch(res) {
906*4882a593Smuzhiyun 		case 0:
907*4882a593Smuzhiyun 			if (!dialog_input_result[0])
908*4882a593Smuzhiyun 				return;
909*4882a593Smuzhiyun 			if (!conf_read(dialog_input_result)) {
910*4882a593Smuzhiyun 				set_config_filename(dialog_input_result);
911*4882a593Smuzhiyun 				sym_set_change_count(1);
912*4882a593Smuzhiyun 				return;
913*4882a593Smuzhiyun 			}
914*4882a593Smuzhiyun 			show_textbox(NULL, "File does not exist!", 5, 38);
915*4882a593Smuzhiyun 			break;
916*4882a593Smuzhiyun 		case 1:
917*4882a593Smuzhiyun 			show_helptext("Load Alternate Configuration", load_config_help);
918*4882a593Smuzhiyun 			break;
919*4882a593Smuzhiyun 		case KEY_ESC:
920*4882a593Smuzhiyun 			return;
921*4882a593Smuzhiyun 		}
922*4882a593Smuzhiyun 	}
923*4882a593Smuzhiyun }
924*4882a593Smuzhiyun 
conf_save(void)925*4882a593Smuzhiyun static void conf_save(void)
926*4882a593Smuzhiyun {
927*4882a593Smuzhiyun 	while (1) {
928*4882a593Smuzhiyun 		int res;
929*4882a593Smuzhiyun 		dialog_clear();
930*4882a593Smuzhiyun 		res = dialog_inputbox(NULL, save_config_text,
931*4882a593Smuzhiyun 				      11, 55, filename);
932*4882a593Smuzhiyun 		switch(res) {
933*4882a593Smuzhiyun 		case 0:
934*4882a593Smuzhiyun 			if (!dialog_input_result[0])
935*4882a593Smuzhiyun 				return;
936*4882a593Smuzhiyun 			if (!conf_write(dialog_input_result)) {
937*4882a593Smuzhiyun 				set_config_filename(dialog_input_result);
938*4882a593Smuzhiyun 				return;
939*4882a593Smuzhiyun 			}
940*4882a593Smuzhiyun 			show_textbox(NULL, "Can't create file!", 5, 60);
941*4882a593Smuzhiyun 			break;
942*4882a593Smuzhiyun 		case 1:
943*4882a593Smuzhiyun 			show_helptext("Save Alternate Configuration", save_config_help);
944*4882a593Smuzhiyun 			break;
945*4882a593Smuzhiyun 		case KEY_ESC:
946*4882a593Smuzhiyun 			return;
947*4882a593Smuzhiyun 		}
948*4882a593Smuzhiyun 	}
949*4882a593Smuzhiyun }
950*4882a593Smuzhiyun 
handle_exit(void)951*4882a593Smuzhiyun static int handle_exit(void)
952*4882a593Smuzhiyun {
953*4882a593Smuzhiyun 	int res;
954*4882a593Smuzhiyun 
955*4882a593Smuzhiyun 	save_and_exit = 1;
956*4882a593Smuzhiyun 	reset_subtitle();
957*4882a593Smuzhiyun 	dialog_clear();
958*4882a593Smuzhiyun 	if (conf_get_changed())
959*4882a593Smuzhiyun 		res = dialog_yesno(NULL,
960*4882a593Smuzhiyun 				   "Do you wish to save your new configuration?\n"
961*4882a593Smuzhiyun 				     "(Press <ESC><ESC> to continue kernel configuration.)",
962*4882a593Smuzhiyun 				   6, 60);
963*4882a593Smuzhiyun 	else
964*4882a593Smuzhiyun 		res = -1;
965*4882a593Smuzhiyun 
966*4882a593Smuzhiyun 	end_dialog(saved_x, saved_y);
967*4882a593Smuzhiyun 
968*4882a593Smuzhiyun 	switch (res) {
969*4882a593Smuzhiyun 	case 0:
970*4882a593Smuzhiyun 		if (conf_write(filename)) {
971*4882a593Smuzhiyun 			fprintf(stderr, "\n\n"
972*4882a593Smuzhiyun 					  "Error while writing of the configuration.\n"
973*4882a593Smuzhiyun 					  "Your configuration changes were NOT saved."
974*4882a593Smuzhiyun 					  "\n\n");
975*4882a593Smuzhiyun 			return 1;
976*4882a593Smuzhiyun 		}
977*4882a593Smuzhiyun 		conf_write_autoconf(0);
978*4882a593Smuzhiyun 		/* fall through */
979*4882a593Smuzhiyun 	case -1:
980*4882a593Smuzhiyun 		if (!silent)
981*4882a593Smuzhiyun 			printf("\n\n"
982*4882a593Smuzhiyun 				 "*** End of the configuration.\n"
983*4882a593Smuzhiyun 				 "*** Execute 'make' to start the build or try 'make help'."
984*4882a593Smuzhiyun 				 "\n\n");
985*4882a593Smuzhiyun 		res = 0;
986*4882a593Smuzhiyun 		break;
987*4882a593Smuzhiyun 	default:
988*4882a593Smuzhiyun 		if (!silent)
989*4882a593Smuzhiyun 			fprintf(stderr, "\n\n"
990*4882a593Smuzhiyun 					  "Your configuration changes were NOT saved."
991*4882a593Smuzhiyun 					  "\n\n");
992*4882a593Smuzhiyun 		if (res != KEY_ESC)
993*4882a593Smuzhiyun 			res = 0;
994*4882a593Smuzhiyun 	}
995*4882a593Smuzhiyun 
996*4882a593Smuzhiyun 	return res;
997*4882a593Smuzhiyun }
998*4882a593Smuzhiyun 
sig_handler(int signo)999*4882a593Smuzhiyun static void sig_handler(int signo)
1000*4882a593Smuzhiyun {
1001*4882a593Smuzhiyun 	exit(handle_exit());
1002*4882a593Smuzhiyun }
1003*4882a593Smuzhiyun 
main(int ac,char ** av)1004*4882a593Smuzhiyun int main(int ac, char **av)
1005*4882a593Smuzhiyun {
1006*4882a593Smuzhiyun 	char *mode;
1007*4882a593Smuzhiyun 	int res;
1008*4882a593Smuzhiyun 
1009*4882a593Smuzhiyun 	signal(SIGINT, sig_handler);
1010*4882a593Smuzhiyun 
1011*4882a593Smuzhiyun 	if (ac > 1 && strcmp(av[1], "-s") == 0) {
1012*4882a593Smuzhiyun 		silent = 1;
1013*4882a593Smuzhiyun 		/* Silence conf_read() until the real callback is set up */
1014*4882a593Smuzhiyun 		conf_set_message_callback(NULL);
1015*4882a593Smuzhiyun 		av++;
1016*4882a593Smuzhiyun 	}
1017*4882a593Smuzhiyun 	conf_parse(av[1]);
1018*4882a593Smuzhiyun 	conf_read(NULL);
1019*4882a593Smuzhiyun 
1020*4882a593Smuzhiyun 	mode = getenv("MENUCONFIG_MODE");
1021*4882a593Smuzhiyun 	if (mode) {
1022*4882a593Smuzhiyun 		if (!strcasecmp(mode, "single_menu"))
1023*4882a593Smuzhiyun 			single_menu_mode = 1;
1024*4882a593Smuzhiyun 	}
1025*4882a593Smuzhiyun 
1026*4882a593Smuzhiyun 	if (init_dialog(NULL)) {
1027*4882a593Smuzhiyun 		fprintf(stderr, "Your display is too small to run Menuconfig!\n");
1028*4882a593Smuzhiyun 		fprintf(stderr, "It must be at least 19 lines by 80 columns.\n");
1029*4882a593Smuzhiyun 		return 1;
1030*4882a593Smuzhiyun 	}
1031*4882a593Smuzhiyun 
1032*4882a593Smuzhiyun 	set_config_filename(conf_get_configname());
1033*4882a593Smuzhiyun 	conf_set_message_callback(conf_message_callback);
1034*4882a593Smuzhiyun 	do {
1035*4882a593Smuzhiyun 		conf(&rootmenu, NULL);
1036*4882a593Smuzhiyun 		res = handle_exit();
1037*4882a593Smuzhiyun 	} while (res == KEY_ESC);
1038*4882a593Smuzhiyun 
1039*4882a593Smuzhiyun 	return res;
1040*4882a593Smuzhiyun }
1041