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> selects a feature, while <N> excludes a feature. "
180*4882a593Smuzhiyun "Press <Esc><Esc> to exit, <?> for Help, </> for Search. "
181*4882a593Smuzhiyun "Legend: [*] feature is selected [ ] feature is excluded"),
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 (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 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 Buildroot 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