]> Git Repo - J-linux.git/blob - scripts/kconfig/nconf.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / scripts / kconfig / nconf.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2008 Nir Tzachar <[email protected]>
4  *
5  * Derived from menuconfig.
6  */
7 #ifndef _GNU_SOURCE
8 #define _GNU_SOURCE
9 #endif
10 #include <string.h>
11 #include <strings.h>
12 #include <stdlib.h>
13
14 #include <list.h>
15 #include <xalloc.h>
16 #include "lkc.h"
17 #include "mnconf-common.h"
18 #include "nconf.h"
19 #include <ctype.h>
20
21 static const char nconf_global_help[] =
22 "Help windows\n"
23 "------------\n"
24 "o  Global help:  Unless in a data entry window, pressing <F1> will give \n"
25 "   you the global help window, which you are just reading.\n"
26 "\n"
27 "o  A short version of the global help is available by pressing <F3>.\n"
28 "\n"
29 "o  Local help:  To get help related to the current menu entry, use any\n"
30 "   of <?> <h>, or if in a data entry window then press <F1>.\n"
31 "\n"
32 "\n"
33 "Menu entries\n"
34 "------------\n"
35 "This interface lets you select features and parameters for the kernel\n"
36 "build.  Kernel features can either be built-in, modularized, or removed.\n"
37 "Parameters must be entered as text or decimal or hexadecimal numbers.\n"
38 "\n"
39 "Menu entries beginning with following braces represent features that\n"
40 "  [ ]  can be built in or removed\n"
41 "  < >  can be built in, modularized or removed\n"
42 "  { }  can be built in or modularized, are selected by another feature\n"
43 "  - -  are selected by another feature\n"
44 "  XXX  cannot be selected.  Symbol Info <F2> tells you why.\n"
45 "*, M or whitespace inside braces means to build in, build as a module\n"
46 "or to exclude the feature respectively.\n"
47 "\n"
48 "To change any of these features, highlight it with the movement keys\n"
49 "listed below and press <y> to build it in, <m> to make it a module or\n"
50 "<n> to remove it.  You may press the <Space> key to cycle through the\n"
51 "available options.\n"
52 "\n"
53 "A trailing \"--->\" designates a submenu, a trailing \"----\" an\n"
54 "empty submenu.\n"
55 "\n"
56 "Menu navigation keys\n"
57 "----------------------------------------------------------------------\n"
58 "Linewise up                 <Up>    <k>\n"
59 "Linewise down               <Down>  <j>\n"
60 "Pagewise up                 <Page Up>\n"
61 "Pagewise down               <Page Down>\n"
62 "First entry                 <Home>\n"
63 "Last entry                  <End>\n"
64 "Enter a submenu             <Right>  <Enter>\n"
65 "Go back to parent menu      <Left>   <Esc>  <F5>\n"
66 "Close a help window         <Enter>  <Esc>  <F5>\n"
67 "Close entry window, apply   <Enter>\n"
68 "Close entry window, forget  <Esc>  <F5>\n"
69 "Start incremental, case-insensitive search for STRING in menu entries,\n"
70 "    no regex support, STRING is displayed in upper left corner\n"
71 "                            </>STRING\n"
72 "    Remove last character   <Backspace>\n"
73 "    Jump to next hit        <Down>\n"
74 "    Jump to previous hit    <Up>\n"
75 "Exit menu search mode       </>  <Esc>\n"
76 "Search for configuration variables with or without leading CONFIG_\n"
77 "                            <F8>RegExpr<Enter>\n"
78 "Verbose search help         <F8><F1>\n"
79 "----------------------------------------------------------------------\n"
80 "\n"
81 "Unless in a data entry window, key <1> may be used instead of <F1>,\n"
82 "<2> instead of <F2>, etc.\n"
83 "\n"
84 "\n"
85 "Radiolist (Choice list)\n"
86 "-----------------------\n"
87 "Use the movement keys listed above to select the option you wish to set\n"
88 "and press <Space>.\n"
89 "\n"
90 "\n"
91 "Data entry\n"
92 "----------\n"
93 "Enter the requested information and press <Enter>.  Hexadecimal values\n"
94 "may be entered without the \"0x\" prefix.\n"
95 "\n"
96 "\n"
97 "Text Box (Help Window)\n"
98 "----------------------\n"
99 "Use movement keys as listed in table above.\n"
100 "\n"
101 "Press any of <Enter> <Esc> <q> <F5> <F9> to exit.\n"
102 "\n"
103 "\n"
104 "Alternate configuration files\n"
105 "-----------------------------\n"
106 "nconfig supports switching between different configurations.\n"
107 "Press <F6> to save your current configuration.  Press <F7> and enter\n"
108 "a file name to load a previously saved configuration.\n"
109 "\n"
110 "\n"
111 "Terminal configuration\n"
112 "----------------------\n"
113 "If you use nconfig in a xterm window, make sure your TERM environment\n"
114 "variable specifies a terminal configuration which supports at least\n"
115 "16 colors.  Otherwise nconfig will look rather bad.\n"
116 "\n"
117 "If the \"stty size\" command reports the current terminalsize correctly,\n"
118 "nconfig will adapt to sizes larger than the traditional 80x25 \"standard\"\n"
119 "and display longer menus properly.\n"
120 "\n"
121 "\n"
122 "Single menu mode\n"
123 "----------------\n"
124 "If you prefer to have all of the menu entries listed in a single menu,\n"
125 "rather than the default multimenu hierarchy, run nconfig with\n"
126 "NCONFIG_MODE environment variable set to single_menu.  Example:\n"
127 "\n"
128 "make NCONFIG_MODE=single_menu nconfig\n"
129 "\n"
130 "<Enter> will then unfold the appropriate category, or fold it if it\n"
131 "is already unfolded.  Folded menu entries will be designated by a\n"
132 "leading \"++>\" and unfolded entries by a leading \"-->\".\n"
133 "\n"
134 "Note that this mode can eventually be a little more CPU expensive than\n"
135 "the default mode, especially with a larger number of unfolded submenus.\n"
136 "\n",
137 menu_no_f_instructions[] =
138 "Legend:  [*] built-in  [ ] excluded  <M> module  < > module capable.\n"
139 "Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n"
140 "\n"
141 "Use the following keys to navigate the menus:\n"
142 "Move up or down with <Up> and <Down>.\n"
143 "Enter a submenu with <Enter> or <Right>.\n"
144 "Exit a submenu to its parent menu with <Esc> or <Left>.\n"
145 "Pressing <y> includes, <n> excludes, <m> modularizes features.\n"
146 "Pressing <Space> cycles through the available options.\n"
147 "To search for menu entries press </>.\n"
148 "<Esc> always leaves the current window.\n"
149 "\n"
150 "You do not have function keys support.\n"
151 "Press <1> instead of <F1>, <2> instead of <F2>, etc.\n"
152 "For verbose global help use key <1>.\n"
153 "For help related to the current menu entry press <?> or <h>.\n",
154 menu_instructions[] =
155 "Legend:  [*] built-in  [ ] excluded  <M> module  < > module capable.\n"
156 "Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n"
157 "\n"
158 "Use the following keys to navigate the menus:\n"
159 "Move up or down with <Up> or <Down>.\n"
160 "Enter a submenu with <Enter> or <Right>.\n"
161 "Exit a submenu to its parent menu with <Esc> or <Left>.\n"
162 "Pressing <y> includes, <n> excludes, <m> modularizes features.\n"
163 "Pressing <Space> cycles through the available options.\n"
164 "To search for menu entries press </>.\n"
165 "<Esc> always leaves the current window.\n"
166 "\n"
167 "Pressing <1> may be used instead of <F1>, <2> instead of <F2>, etc.\n"
168 "For verbose global help press <F1>.\n"
169 "For help related to the current menu entry press <?> or <h>.\n",
170 radiolist_instructions[] =
171 "Press <Up>, <Down>, <Home> or <End> to navigate a radiolist, select\n"
172 "with <Space>.\n"
173 "For help related to the current entry press <?> or <h>.\n"
174 "For global help press <F1>.\n",
175 inputbox_instructions_int[] =
176 "Please enter a decimal value.\n"
177 "Fractions will not be accepted.\n"
178 "Press <Enter> to apply, <Esc> to cancel.",
179 inputbox_instructions_hex[] =
180 "Please enter a hexadecimal value.\n"
181 "Press <Enter> to apply, <Esc> to cancel.",
182 inputbox_instructions_string[] =
183 "Please enter a string value.\n"
184 "Press <Enter> to apply, <Esc> to cancel.",
185 setmod_text[] =
186 "This feature depends on another feature which has been configured as a\n"
187 "module.  As a result, the current feature will be built as a module too.",
188 load_config_text[] =
189 "Enter the name of the configuration file you wish to load.\n"
190 "Accept the name shown to restore the configuration you last\n"
191 "retrieved.  Leave empty to abort.",
192 load_config_help[] =
193 "For various reasons, one may wish to keep several different\n"
194 "configurations available on a single machine.\n"
195 "\n"
196 "If you have saved a previous configuration in a file other than the\n"
197 "default one, entering its name here will allow you to load and modify\n"
198 "that configuration.\n"
199 "\n"
200 "Leave empty to abort.\n",
201 save_config_text[] =
202 "Enter a filename to which this configuration should be saved\n"
203 "as an alternate.  Leave empty to abort.",
204 save_config_help[] =
205 "For various reasons, one may wish to keep several different\n"
206 "configurations available on a single machine.\n"
207 "\n"
208 "Entering a file name here will allow you to later retrieve, modify\n"
209 "and use the current configuration as an alternate to whatever\n"
210 "configuration options you have selected at that time.\n"
211 "\n"
212 "Leave empty to abort.\n",
213 search_help[] =
214 "Search for symbols (configuration variable names CONFIG_*) and display\n"
215 "their relations.  Regular expressions are supported.\n"
216 "Example:  Search for \"^FOO\".\n"
217 "Result:\n"
218 "-----------------------------------------------------------------\n"
219 "Symbol: FOO [ = m]\n"
220 "Prompt: Foo bus is used to drive the bar HW\n"
221 "Defined at drivers/pci/Kconfig:47\n"
222 "Depends on: X86_LOCAL_APIC && X86_IO_APIC\n"
223 "Location:\n"
224 "  -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
225 "    -> PCI support (PCI [ = y])\n"
226 "(1)   -> PCI access mode (<choice> [ = y])\n"
227 "Selects: LIBCRC32\n"
228 "Selected by: BAR\n"
229 "-----------------------------------------------------------------\n"
230 "o  The line 'Prompt:' shows the text displayed for this symbol in\n"
231 "   the menu hierarchy.\n"
232 "o  The 'Defined at' line tells at what file / line number the symbol is\n"
233 "   defined.\n"
234 "o  The 'Depends on:' line lists symbols that need to be defined for\n"
235 "   this symbol to be visible and selectable in the menu.\n"
236 "o  The 'Location:' lines tell, where in the menu structure this symbol\n"
237 "   is located.\n"
238 "     A location followed by a [ = y] indicates that this is\n"
239 "     a selectable menu item, and the current value is displayed inside\n"
240 "     brackets.\n"
241 "     Press the key in the (#) prefix to jump directly to that\n"
242 "     location. You will be returned to the current search results\n"
243 "     after exiting this new menu.\n"
244 "o  The 'Selects:' line tells, what symbol will be automatically selected\n"
245 "   if this symbol is selected (y or m).\n"
246 "o  The 'Selected by' line tells what symbol has selected this symbol.\n"
247 "\n"
248 "Only relevant lines are shown.\n"
249 "\n\n"
250 "Search examples:\n"
251 "USB  => find all symbols containing USB\n"
252 "^USB => find all symbols starting with USB\n"
253 "USB$ => find all symbols ending with USB\n"
254 "\n";
255
256 struct mitem {
257         char str[256];
258         char tag;
259         void *usrptr;
260         int is_visible;
261 };
262
263 #define MAX_MENU_ITEMS 4096
264 static int show_all_items;
265 static int indent;
266 static struct menu *current_menu;
267 static int child_count;
268 static int single_menu_mode;
269 /* the window in which all information appears */
270 static WINDOW *main_window;
271 /* the largest size of the menu window */
272 static int mwin_max_lines;
273 static int mwin_max_cols;
274 /* the window in which we show option buttons */
275 static MENU *curses_menu;
276 static ITEM *curses_menu_items[MAX_MENU_ITEMS];
277 static struct mitem k_menu_items[MAX_MENU_ITEMS];
278 static unsigned int items_num;
279 static int global_exit;
280 /* the currently selected button */
281 static const char *current_instructions = menu_instructions;
282
283 static char *dialog_input_result;
284 static int dialog_input_result_len;
285
286 static void selected_conf(struct menu *menu, struct menu *active_menu);
287 static void conf(struct menu *menu);
288 static void conf_choice(struct menu *menu);
289 static void conf_string(struct menu *menu);
290 static void conf_load(void);
291 static void conf_save(void);
292 static void show_help(struct menu *menu);
293 static int do_exit(void);
294 static void setup_windows(void);
295 static void search_conf(void);
296
297 typedef void (*function_key_handler_t)(int *key, struct menu *menu);
298 static void handle_f1(int *key, struct menu *current_item);
299 static void handle_f2(int *key, struct menu *current_item);
300 static void handle_f3(int *key, struct menu *current_item);
301 static void handle_f4(int *key, struct menu *current_item);
302 static void handle_f5(int *key, struct menu *current_item);
303 static void handle_f6(int *key, struct menu *current_item);
304 static void handle_f7(int *key, struct menu *current_item);
305 static void handle_f8(int *key, struct menu *current_item);
306 static void handle_f9(int *key, struct menu *current_item);
307
308 struct function_keys {
309         const char *key_str;
310         const char *func;
311         function_key key;
312         function_key_handler_t handler;
313 };
314
315 static const int function_keys_num = 9;
316 static struct function_keys function_keys[] = {
317         {
318                 .key_str = "F1",
319                 .func = "Help",
320                 .key = F_HELP,
321                 .handler = handle_f1,
322         },
323         {
324                 .key_str = "F2",
325                 .func = "SymInfo",
326                 .key = F_SYMBOL,
327                 .handler = handle_f2,
328         },
329         {
330                 .key_str = "F3",
331                 .func = "Help 2",
332                 .key = F_INSTS,
333                 .handler = handle_f3,
334         },
335         {
336                 .key_str = "F4",
337                 .func = "ShowAll",
338                 .key = F_CONF,
339                 .handler = handle_f4,
340         },
341         {
342                 .key_str = "F5",
343                 .func = "Back",
344                 .key = F_BACK,
345                 .handler = handle_f5,
346         },
347         {
348                 .key_str = "F6",
349                 .func = "Save",
350                 .key = F_SAVE,
351                 .handler = handle_f6,
352         },
353         {
354                 .key_str = "F7",
355                 .func = "Load",
356                 .key = F_LOAD,
357                 .handler = handle_f7,
358         },
359         {
360                 .key_str = "F8",
361                 .func = "SymSearch",
362                 .key = F_SEARCH,
363                 .handler = handle_f8,
364         },
365         {
366                 .key_str = "F9",
367                 .func = "Exit",
368                 .key = F_EXIT,
369                 .handler = handle_f9,
370         },
371 };
372
373 static void print_function_line(void)
374 {
375         int i;
376         int offset = 1;
377         const int skip = 1;
378         int lines = getmaxy(stdscr);
379
380         for (i = 0; i < function_keys_num; i++) {
381                 wattrset(main_window, attr_function_highlight);
382                 mvwprintw(main_window, lines-3, offset,
383                                 "%s",
384                                 function_keys[i].key_str);
385                 wattrset(main_window, attr_function_text);
386                 offset += strlen(function_keys[i].key_str);
387                 mvwprintw(main_window, lines-3,
388                                 offset, "%s",
389                                 function_keys[i].func);
390                 offset += strlen(function_keys[i].func) + skip;
391         }
392         wattrset(main_window, attr_normal);
393 }
394
395 /* help */
396 static void handle_f1(int *key, struct menu *current_item)
397 {
398         show_scroll_win(main_window,
399                         "Global help", nconf_global_help);
400         return;
401 }
402
403 /* symbole help */
404 static void handle_f2(int *key, struct menu *current_item)
405 {
406         show_help(current_item);
407         return;
408 }
409
410 /* instructions */
411 static void handle_f3(int *key, struct menu *current_item)
412 {
413         show_scroll_win(main_window,
414                         "Short help",
415                         current_instructions);
416         return;
417 }
418
419 /* config */
420 static void handle_f4(int *key, struct menu *current_item)
421 {
422         int res = btn_dialog(main_window,
423                         "Show all symbols?",
424                         2,
425                         "   <Show All>   ",
426                         "<Don't show all>");
427         if (res == 0)
428                 show_all_items = 1;
429         else if (res == 1)
430                 show_all_items = 0;
431
432         return;
433 }
434
435 /* back */
436 static void handle_f5(int *key, struct menu *current_item)
437 {
438         *key = KEY_LEFT;
439         return;
440 }
441
442 /* save */
443 static void handle_f6(int *key, struct menu *current_item)
444 {
445         conf_save();
446         return;
447 }
448
449 /* load */
450 static void handle_f7(int *key, struct menu *current_item)
451 {
452         conf_load();
453         return;
454 }
455
456 /* search */
457 static void handle_f8(int *key, struct menu *current_item)
458 {
459         search_conf();
460         return;
461 }
462
463 /* exit */
464 static void handle_f9(int *key, struct menu *current_item)
465 {
466         do_exit();
467         return;
468 }
469
470 /* return != 0 to indicate the key was handled */
471 static int process_special_keys(int *key, struct menu *menu)
472 {
473         int i;
474
475         if (*key == KEY_RESIZE) {
476                 setup_windows();
477                 return 1;
478         }
479
480         for (i = 0; i < function_keys_num; i++) {
481                 if (*key == KEY_F(function_keys[i].key) ||
482                     *key == '0' + function_keys[i].key){
483                         function_keys[i].handler(key, menu);
484                         return 1;
485                 }
486         }
487
488         return 0;
489 }
490
491 static void clean_items(void)
492 {
493         int i;
494         for (i = 0; curses_menu_items[i]; i++)
495                 free_item(curses_menu_items[i]);
496         bzero(curses_menu_items, sizeof(curses_menu_items));
497         bzero(k_menu_items, sizeof(k_menu_items));
498         items_num = 0;
499 }
500
501 typedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN,
502         FIND_NEXT_MATCH_DOWN, FIND_NEXT_MATCH_UP} match_f;
503
504 /* return the index of the matched item, or -1 if no such item exists */
505 static int get_mext_match(const char *match_str, match_f flag)
506 {
507         int match_start, index;
508
509         /* Do not search if the menu is empty (i.e. items_num == 0) */
510         match_start = item_index(current_item(curses_menu));
511         if (match_start == ERR)
512                 return -1;
513
514         if (flag == FIND_NEXT_MATCH_DOWN)
515                 ++match_start;
516         else if (flag == FIND_NEXT_MATCH_UP)
517                 --match_start;
518
519         match_start = (match_start + items_num) % items_num;
520         index = match_start;
521         while (true) {
522                 char *str = k_menu_items[index].str;
523                 if (strcasestr(str, match_str) != NULL)
524                         return index;
525                 if (flag == FIND_NEXT_MATCH_UP ||
526                     flag == MATCH_TINKER_PATTERN_UP)
527                         --index;
528                 else
529                         ++index;
530                 index = (index + items_num) % items_num;
531                 if (index == match_start)
532                         return -1;
533         }
534 }
535
536 /* Make a new item. */
537 static void item_make(struct menu *menu, char tag, const char *fmt, ...)
538 {
539         va_list ap;
540
541         if (items_num > MAX_MENU_ITEMS-1)
542                 return;
543
544         bzero(&k_menu_items[items_num], sizeof(k_menu_items[0]));
545         k_menu_items[items_num].tag = tag;
546         k_menu_items[items_num].usrptr = menu;
547         if (menu != NULL)
548                 k_menu_items[items_num].is_visible =
549                         menu_is_visible(menu);
550         else
551                 k_menu_items[items_num].is_visible = 1;
552
553         va_start(ap, fmt);
554         vsnprintf(k_menu_items[items_num].str,
555                   sizeof(k_menu_items[items_num].str),
556                   fmt, ap);
557         va_end(ap);
558
559         if (!k_menu_items[items_num].is_visible)
560                 memcpy(k_menu_items[items_num].str, "XXX", 3);
561
562         curses_menu_items[items_num] = new_item(
563                         k_menu_items[items_num].str,
564                         k_menu_items[items_num].str);
565         set_item_userptr(curses_menu_items[items_num],
566                         &k_menu_items[items_num]);
567         /*
568         if (!k_menu_items[items_num].is_visible)
569                 item_opts_off(curses_menu_items[items_num], O_SELECTABLE);
570         */
571
572         items_num++;
573         curses_menu_items[items_num] = NULL;
574 }
575
576 /* very hackish. adds a string to the last item added */
577 static void item_add_str(const char *fmt, ...)
578 {
579         va_list ap;
580         int index = items_num-1;
581         char new_str[256];
582         char tmp_str[256];
583
584         if (index < 0)
585                 return;
586
587         va_start(ap, fmt);
588         vsnprintf(new_str, sizeof(new_str), fmt, ap);
589         va_end(ap);
590         snprintf(tmp_str, sizeof(tmp_str), "%s%s",
591                         k_menu_items[index].str, new_str);
592         strncpy(k_menu_items[index].str,
593                 tmp_str,
594                 sizeof(k_menu_items[index].str));
595
596         free_item(curses_menu_items[index]);
597         curses_menu_items[index] = new_item(
598                         k_menu_items[index].str,
599                         k_menu_items[index].str);
600         set_item_userptr(curses_menu_items[index],
601                         &k_menu_items[index]);
602 }
603
604 /* get the tag of the currently selected item */
605 static char item_tag(void)
606 {
607         ITEM *cur;
608         struct mitem *mcur;
609
610         cur = current_item(curses_menu);
611         if (cur == NULL)
612                 return 0;
613         mcur = (struct mitem *) item_userptr(cur);
614         return mcur->tag;
615 }
616
617 static int curses_item_index(void)
618 {
619         return  item_index(current_item(curses_menu));
620 }
621
622 static void *item_data(void)
623 {
624         ITEM *cur;
625         struct mitem *mcur;
626
627         cur = current_item(curses_menu);
628         if (!cur)
629                 return NULL;
630         mcur = (struct mitem *) item_userptr(cur);
631         return mcur->usrptr;
632
633 }
634
635 static int item_is_tag(char tag)
636 {
637         return item_tag() == tag;
638 }
639
640 static char filename[PATH_MAX+1];
641 static char menu_backtitle[PATH_MAX+128];
642 static void set_config_filename(const char *config_filename)
643 {
644         snprintf(menu_backtitle, sizeof(menu_backtitle), "%s - %s",
645                  config_filename, rootmenu.prompt->text);
646
647         snprintf(filename, sizeof(filename), "%s", config_filename);
648 }
649
650 /* return = 0 means we are successful.
651  * -1 means go on doing what you were doing
652  */
653 static int do_exit(void)
654 {
655         int res;
656         if (!conf_get_changed()) {
657                 global_exit = 1;
658                 return 0;
659         }
660         res = btn_dialog(main_window,
661                         "Do you wish to save your new configuration?\n"
662                                 "<ESC> to cancel and resume nconfig.",
663                         2,
664                         "   <save>   ",
665                         "<don't save>");
666         if (res == KEY_EXIT) {
667                 global_exit = 0;
668                 return -1;
669         }
670
671         /* if we got here, the user really wants to exit */
672         switch (res) {
673         case 0:
674                 res = conf_write(filename);
675                 if (res)
676                         btn_dialog(
677                                 main_window,
678                                 "Error during writing of configuration.\n"
679                                   "Your configuration changes were NOT saved.",
680                                   1,
681                                   "<OK>");
682                 conf_write_autoconf(0);
683                 break;
684         default:
685                 btn_dialog(
686                         main_window,
687                         "Your configuration changes were NOT saved.",
688                         1,
689                         "<OK>");
690                 break;
691         }
692         global_exit = 1;
693         return 0;
694 }
695
696
697 static void search_conf(void)
698 {
699         struct symbol **sym_arr;
700         struct gstr res;
701         struct gstr title;
702         char *dialog_input;
703         int dres, vscroll = 0, hscroll = 0;
704         bool again;
705
706         title = str_new();
707         str_printf( &title, "Enter (sub)string or regexp to search for "
708                               "(with or without \"%s\")", CONFIG_);
709
710 again:
711         dres = dialog_inputbox(main_window,
712                         "Search Configuration Parameter",
713                         str_get(&title),
714                         "", &dialog_input_result, &dialog_input_result_len);
715         switch (dres) {
716         case 0:
717                 break;
718         case 1:
719                 show_scroll_win(main_window,
720                                 "Search Configuration", search_help);
721                 goto again;
722         default:
723                 str_free(&title);
724                 return;
725         }
726
727         /* strip the prefix if necessary */
728         dialog_input = dialog_input_result;
729         if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
730                 dialog_input += strlen(CONFIG_);
731
732         sym_arr = sym_re_search(dialog_input);
733
734         do {
735                 LIST_HEAD(head);
736                 struct search_data data = {
737                         .head = &head,
738                         .target = NULL,
739                 };
740                 jump_key_char = 0;
741                 res = get_relations_str(sym_arr, &head);
742                 dres = show_scroll_win_ext(main_window,
743                                 "Search Results", str_get(&res),
744                                 &vscroll, &hscroll,
745                                 handle_search_keys, &data);
746                 again = false;
747                 if (dres >= '1' && dres <= '9') {
748                         assert(data.target != NULL);
749                         selected_conf(data.target->parent, data.target);
750                         again = true;
751                 }
752                 str_free(&res);
753         } while (again);
754         free(sym_arr);
755         str_free(&title);
756 }
757
758
759 static void build_conf(struct menu *menu)
760 {
761         struct symbol *sym;
762         struct property *prop;
763         struct menu *child;
764         int type, tmp, doint = 2;
765         tristate val;
766         char ch;
767
768         if (!menu || (!show_all_items && !menu_is_visible(menu)))
769                 return;
770
771         sym = menu->sym;
772         prop = menu->prompt;
773         if (!sym) {
774                 if (prop && menu != current_menu) {
775                         const char *prompt = menu_get_prompt(menu);
776                         enum prop_type ptype;
777                         ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
778                         switch (ptype) {
779                         case P_MENU:
780                                 child_count++;
781                                 if (single_menu_mode) {
782                                         item_make(menu, 'm',
783                                                 "%s%*c%s",
784                                                 menu->data ? "-->" : "++>",
785                                                 indent + 1, ' ', prompt);
786                                 } else
787                                         item_make(menu, 'm',
788                                                   "   %*c%s  %s",
789                                                   indent + 1, ' ', prompt,
790                                                   menu_is_empty(menu) ? "----" : "--->");
791
792                                 if (single_menu_mode && menu->data)
793                                         goto conf_childs;
794                                 return;
795                         case P_COMMENT:
796                                 if (prompt) {
797                                         child_count++;
798                                         item_make(menu, ':',
799                                                 "   %*c*** %s ***",
800                                                 indent + 1, ' ',
801                                                 prompt);
802                                 }
803                                 break;
804                         default:
805                                 if (prompt) {
806                                         child_count++;
807                                         item_make(menu, ':', "---%*c%s",
808                                                 indent + 1, ' ',
809                                                 prompt);
810                                 }
811                         }
812                 } else
813                         doint = 0;
814                 goto conf_childs;
815         }
816
817         type = sym_get_type(sym);
818         if (sym_is_choice(sym)) {
819                 struct symbol *def_sym = sym_calc_choice(menu);
820                 struct menu *def_menu = NULL;
821
822                 child_count++;
823                 for (child = menu->list; child; child = child->next) {
824                         if (menu_is_visible(child) && child->sym == def_sym)
825                                 def_menu = child;
826                 }
827
828                 val = sym_get_tristate_value(sym);
829                 item_make(menu, def_menu ? 't' : ':', "   ");
830
831                 item_add_str("%*c%s", indent + 1,
832                                 ' ', menu_get_prompt(menu));
833                 if (def_menu)
834                         item_add_str(" (%s)  --->", menu_get_prompt(def_menu));
835                 return;
836         } else {
837                 if (menu == current_menu) {
838                         item_make(menu, ':',
839                                 "---%*c%s", indent + 1,
840                                 ' ', menu_get_prompt(menu));
841                         goto conf_childs;
842                 }
843                 child_count++;
844                 val = sym_get_tristate_value(sym);
845                 switch (type) {
846                 case S_BOOLEAN:
847                         if (sym_is_changeable(sym))
848                                 item_make(menu, 't', "[%c]",
849                                           val == no ? ' ' : '*');
850                         else
851                                 item_make(menu, 't', "-%c-",
852                                           val == no ? ' ' : '*');
853                         break;
854                 case S_TRISTATE:
855                         switch (val) {
856                         case yes:
857                                 ch = '*';
858                                 break;
859                         case mod:
860                                 ch = 'M';
861                                 break;
862                         default:
863                                 ch = ' ';
864                                 break;
865                         }
866                         if (sym_is_changeable(sym)) {
867                                 if (sym->rev_dep.tri == mod)
868                                         item_make(menu, 't', "{%c}", ch);
869                                 else
870                                         item_make(menu, 't', "<%c>", ch);
871                         } else
872                                 item_make(menu, 't', "-%c-", ch);
873                         break;
874                 default:
875                         tmp = 2 + strlen(sym_get_string_value(sym));
876                         item_make(menu, 's', "    (%s)",
877                                   sym_get_string_value(sym));
878                         tmp = indent - tmp + 4;
879                         if (tmp < 0)
880                                 tmp = 0;
881                         item_add_str("%*c%s%s", tmp, ' ', menu_get_prompt(menu),
882                                      (sym_has_value(sym) ||
883                                       !sym_is_changeable(sym)) ? "" : " (NEW)");
884                         goto conf_childs;
885                 }
886                 item_add_str("%*c%s%s", indent + 1, ' ',
887                                 menu_get_prompt(menu),
888                                 (sym_has_value(sym) || !sym_is_changeable(sym)) ?
889                                 "" : " (NEW)");
890                 if (menu->prompt && menu->prompt->type == P_MENU) {
891                         item_add_str("  %s", menu_is_empty(menu) ? "----" : "--->");
892                         return;
893                 }
894         }
895
896 conf_childs:
897         indent += doint;
898         for (child = menu->list; child; child = child->next)
899                 build_conf(child);
900         indent -= doint;
901 }
902
903 static void reset_menu(void)
904 {
905         unpost_menu(curses_menu);
906         clean_items();
907 }
908
909 /* adjust the menu to show this item.
910  * prefer not to scroll the menu if possible*/
911 static void center_item(int selected_index, int *last_top_row)
912 {
913         int toprow;
914
915         set_top_row(curses_menu, *last_top_row);
916         toprow = top_row(curses_menu);
917         if (selected_index < toprow ||
918             selected_index >= toprow+mwin_max_lines) {
919                 toprow = max(selected_index-mwin_max_lines/2, 0);
920                 if (toprow >= item_count(curses_menu)-mwin_max_lines)
921                         toprow = item_count(curses_menu)-mwin_max_lines;
922                 set_top_row(curses_menu, toprow);
923         }
924         set_current_item(curses_menu,
925                         curses_menu_items[selected_index]);
926         *last_top_row = toprow;
927         post_menu(curses_menu);
928         refresh_all_windows(main_window);
929 }
930
931 /* this function assumes reset_menu has been called before */
932 static void show_menu(const char *prompt, const char *instructions,
933                 int selected_index, int *last_top_row)
934 {
935         int maxx, maxy;
936         WINDOW *menu_window;
937
938         current_instructions = instructions;
939
940         clear();
941         print_in_middle(stdscr, 1, getmaxx(stdscr),
942                         menu_backtitle,
943                         attr_main_heading);
944
945         wattrset(main_window, attr_main_menu_box);
946         box(main_window, 0, 0);
947         wattrset(main_window, attr_main_menu_heading);
948         mvwprintw(main_window, 0, 3, " %s ", prompt);
949         wattrset(main_window, attr_normal);
950
951         set_menu_items(curses_menu, curses_menu_items);
952
953         /* position the menu at the middle of the screen */
954         scale_menu(curses_menu, &maxy, &maxx);
955         maxx = min(maxx, mwin_max_cols-2);
956         maxy = mwin_max_lines;
957         menu_window = derwin(main_window,
958                         maxy,
959                         maxx,
960                         2,
961                         (mwin_max_cols-maxx)/2);
962         keypad(menu_window, TRUE);
963         set_menu_win(curses_menu, menu_window);
964         set_menu_sub(curses_menu, menu_window);
965
966         /* must reassert this after changing items, otherwise returns to a
967          * default of 16
968          */
969         set_menu_format(curses_menu, maxy, 1);
970         center_item(selected_index, last_top_row);
971         set_menu_format(curses_menu, maxy, 1);
972
973         print_function_line();
974
975         /* Post the menu */
976         post_menu(curses_menu);
977         refresh_all_windows(main_window);
978 }
979
980 static void adj_match_dir(match_f *match_direction)
981 {
982         if (*match_direction == FIND_NEXT_MATCH_DOWN)
983                 *match_direction =
984                         MATCH_TINKER_PATTERN_DOWN;
985         else if (*match_direction == FIND_NEXT_MATCH_UP)
986                 *match_direction =
987                         MATCH_TINKER_PATTERN_UP;
988         /* else, do no change.. */
989 }
990
991 struct match_state
992 {
993         int in_search;
994         match_f match_direction;
995         char pattern[256];
996 };
997
998 /* Return 0 means I have handled the key. In such a case, ans should hold the
999  * item to center, or -1 otherwise.
1000  * Else return -1 .
1001  */
1002 static int do_match(int key, struct match_state *state, int *ans)
1003 {
1004         char c = (char) key;
1005         int terminate_search = 0;
1006         *ans = -1;
1007         if (key == '/' || (state->in_search && key == 27)) {
1008                 move(0, 0);
1009                 refresh();
1010                 clrtoeol();
1011                 state->in_search = 1-state->in_search;
1012                 bzero(state->pattern, sizeof(state->pattern));
1013                 state->match_direction = MATCH_TINKER_PATTERN_DOWN;
1014                 return 0;
1015         } else if (!state->in_search)
1016                 return 1;
1017
1018         if (isalnum(c) || isgraph(c) || c == ' ') {
1019                 state->pattern[strlen(state->pattern)] = c;
1020                 state->pattern[strlen(state->pattern)] = '\0';
1021                 adj_match_dir(&state->match_direction);
1022                 *ans = get_mext_match(state->pattern,
1023                                 state->match_direction);
1024         } else if (key == KEY_DOWN) {
1025                 state->match_direction = FIND_NEXT_MATCH_DOWN;
1026                 *ans = get_mext_match(state->pattern,
1027                                 state->match_direction);
1028         } else if (key == KEY_UP) {
1029                 state->match_direction = FIND_NEXT_MATCH_UP;
1030                 *ans = get_mext_match(state->pattern,
1031                                 state->match_direction);
1032         } else if (key == KEY_BACKSPACE || key == 8 || key == 127) {
1033                 state->pattern[strlen(state->pattern)-1] = '\0';
1034                 adj_match_dir(&state->match_direction);
1035         } else
1036                 terminate_search = 1;
1037
1038         if (terminate_search) {
1039                 state->in_search = 0;
1040                 bzero(state->pattern, sizeof(state->pattern));
1041                 move(0, 0);
1042                 refresh();
1043                 clrtoeol();
1044                 return -1;
1045         }
1046         return 0;
1047 }
1048
1049 static void conf(struct menu *menu)
1050 {
1051         selected_conf(menu, NULL);
1052 }
1053
1054 static void selected_conf(struct menu *menu, struct menu *active_menu)
1055 {
1056         struct menu *submenu = NULL;
1057         struct symbol *sym;
1058         int i, res;
1059         int current_index = 0;
1060         int last_top_row = 0;
1061         struct match_state match_state = {
1062                 .in_search = 0,
1063                 .match_direction = MATCH_TINKER_PATTERN_DOWN,
1064                 .pattern = "",
1065         };
1066
1067         while (!global_exit) {
1068                 reset_menu();
1069                 current_menu = menu;
1070                 build_conf(menu);
1071                 if (!child_count)
1072                         break;
1073
1074                 if (active_menu != NULL) {
1075                         for (i = 0; i < items_num; i++) {
1076                                 struct mitem *mcur;
1077
1078                                 mcur = (struct mitem *) item_userptr(curses_menu_items[i]);
1079                                 if ((struct menu *) mcur->usrptr == active_menu) {
1080                                         current_index = i;
1081                                         break;
1082                                 }
1083                         }
1084                         active_menu = NULL;
1085                 }
1086
1087                 show_menu(menu_get_prompt(menu), menu_instructions,
1088                           current_index, &last_top_row);
1089                 keypad((menu_win(curses_menu)), TRUE);
1090                 while (!global_exit) {
1091                         if (match_state.in_search) {
1092                                 mvprintw(0, 0,
1093                                         "searching: %s", match_state.pattern);
1094                                 clrtoeol();
1095                         }
1096                         refresh_all_windows(main_window);
1097                         res = wgetch(menu_win(curses_menu));
1098                         if (!res)
1099                                 break;
1100                         if (do_match(res, &match_state, &current_index) == 0) {
1101                                 if (current_index != -1)
1102                                         center_item(current_index,
1103                                                     &last_top_row);
1104                                 continue;
1105                         }
1106                         if (process_special_keys(&res,
1107                                                 (struct menu *) item_data()))
1108                                 break;
1109                         switch (res) {
1110                         case KEY_DOWN:
1111                         case 'j':
1112                                 menu_driver(curses_menu, REQ_DOWN_ITEM);
1113                                 break;
1114                         case KEY_UP:
1115                         case 'k':
1116                                 menu_driver(curses_menu, REQ_UP_ITEM);
1117                                 break;
1118                         case KEY_NPAGE:
1119                                 menu_driver(curses_menu, REQ_SCR_DPAGE);
1120                                 break;
1121                         case KEY_PPAGE:
1122                                 menu_driver(curses_menu, REQ_SCR_UPAGE);
1123                                 break;
1124                         case KEY_HOME:
1125                                 menu_driver(curses_menu, REQ_FIRST_ITEM);
1126                                 break;
1127                         case KEY_END:
1128                                 menu_driver(curses_menu, REQ_LAST_ITEM);
1129                                 break;
1130                         case 'h':
1131                         case '?':
1132                                 show_help((struct menu *) item_data());
1133                                 break;
1134                         }
1135                         if (res == 10 || res == 27 ||
1136                                 res == 32 || res == 'n' || res == 'y' ||
1137                                 res == KEY_LEFT || res == KEY_RIGHT ||
1138                                 res == 'm')
1139                                 break;
1140                         refresh_all_windows(main_window);
1141                 }
1142
1143                 refresh_all_windows(main_window);
1144                 /* if ESC or left*/
1145                 if (res == 27 || (menu != &rootmenu && res == KEY_LEFT))
1146                         break;
1147
1148                 /* remember location in the menu */
1149                 last_top_row = top_row(curses_menu);
1150                 current_index = curses_item_index();
1151
1152                 if (!item_tag())
1153                         continue;
1154
1155                 submenu = (struct menu *) item_data();
1156                 if (!submenu || !menu_is_visible(submenu))
1157                         continue;
1158                 sym = submenu->sym;
1159
1160                 switch (res) {
1161                 case ' ':
1162                         if (item_is_tag('t'))
1163                                 sym_toggle_tristate_value(sym);
1164                         else if (item_is_tag('m'))
1165                                 conf(submenu);
1166                         break;
1167                 case KEY_RIGHT:
1168                 case 10: /* ENTER WAS PRESSED */
1169                         switch (item_tag()) {
1170                         case 'm':
1171                                 if (single_menu_mode)
1172                                         submenu->data =
1173                                                 (void *) (long) !submenu->data;
1174                                 else
1175                                         conf(submenu);
1176                                 break;
1177                         case 't':
1178                                 if (sym_is_choice(sym))
1179                                         conf_choice(submenu);
1180                                 else if (submenu->prompt &&
1181                                          submenu->prompt->type == P_MENU)
1182                                         conf(submenu);
1183                                 else if (res == 10)
1184                                         sym_toggle_tristate_value(sym);
1185                                 break;
1186                         case 's':
1187                                 conf_string(submenu);
1188                                 break;
1189                         }
1190                         break;
1191                 case 'y':
1192                         if (item_is_tag('t')) {
1193                                 if (sym_set_tristate_value(sym, yes))
1194                                         break;
1195                                 if (sym_set_tristate_value(sym, mod))
1196                                         btn_dialog(main_window, setmod_text, 0);
1197                         }
1198                         break;
1199                 case 'n':
1200                         if (item_is_tag('t'))
1201                                 sym_set_tristate_value(sym, no);
1202                         break;
1203                 case 'm':
1204                         if (item_is_tag('t'))
1205                                 sym_set_tristate_value(sym, mod);
1206                         break;
1207                 }
1208         }
1209 }
1210
1211 static void conf_message_callback(const char *s)
1212 {
1213         btn_dialog(main_window, s, 1, "<OK>");
1214 }
1215
1216 static void show_help(struct menu *menu)
1217 {
1218         struct gstr help;
1219
1220         if (!menu)
1221                 return;
1222
1223         help = str_new();
1224         menu_get_ext_help(menu, &help);
1225         show_scroll_win(main_window, menu_get_prompt(menu), str_get(&help));
1226         str_free(&help);
1227 }
1228
1229 static void conf_choice(struct menu *menu)
1230 {
1231         const char *prompt = menu_get_prompt(menu);
1232         struct menu *child = NULL;
1233         struct symbol *active;
1234         int selected_index = 0;
1235         int last_top_row = 0;
1236         int res, i = 0;
1237         struct match_state match_state = {
1238                 .in_search = 0,
1239                 .match_direction = MATCH_TINKER_PATTERN_DOWN,
1240                 .pattern = "",
1241         };
1242
1243         active = sym_calc_choice(menu);
1244         /* this is mostly duplicated from the conf() function. */
1245         while (!global_exit) {
1246                 reset_menu();
1247
1248                 for (i = 0, child = menu->list; child; child = child->next) {
1249                         if (!show_all_items && !menu_is_visible(child))
1250                                 continue;
1251
1252                         if (child->sym == sym_calc_choice(menu))
1253                                 item_make(child, ':', "<X> %s",
1254                                                 menu_get_prompt(child));
1255                         else if (child->sym)
1256                                 item_make(child, ':', "    %s",
1257                                                 menu_get_prompt(child));
1258                         else
1259                                 item_make(child, ':', "*** %s ***",
1260                                                 menu_get_prompt(child));
1261
1262                         if (child->sym == active){
1263                                 last_top_row = top_row(curses_menu);
1264                                 selected_index = i;
1265                         }
1266                         i++;
1267                 }
1268                 show_menu(prompt ? prompt : "Choice Menu",
1269                                 radiolist_instructions,
1270                                 selected_index,
1271                                 &last_top_row);
1272                 while (!global_exit) {
1273                         if (match_state.in_search) {
1274                                 mvprintw(0, 0, "searching: %s",
1275                                          match_state.pattern);
1276                                 clrtoeol();
1277                         }
1278                         refresh_all_windows(main_window);
1279                         res = wgetch(menu_win(curses_menu));
1280                         if (!res)
1281                                 break;
1282                         if (do_match(res, &match_state, &selected_index) == 0) {
1283                                 if (selected_index != -1)
1284                                         center_item(selected_index,
1285                                                     &last_top_row);
1286                                 continue;
1287                         }
1288                         if (process_special_keys(
1289                                                 &res,
1290                                                 (struct menu *) item_data()))
1291                                 break;
1292                         switch (res) {
1293                         case KEY_DOWN:
1294                         case 'j':
1295                                 menu_driver(curses_menu, REQ_DOWN_ITEM);
1296                                 break;
1297                         case KEY_UP:
1298                         case 'k':
1299                                 menu_driver(curses_menu, REQ_UP_ITEM);
1300                                 break;
1301                         case KEY_NPAGE:
1302                                 menu_driver(curses_menu, REQ_SCR_DPAGE);
1303                                 break;
1304                         case KEY_PPAGE:
1305                                 menu_driver(curses_menu, REQ_SCR_UPAGE);
1306                                 break;
1307                         case KEY_HOME:
1308                                 menu_driver(curses_menu, REQ_FIRST_ITEM);
1309                                 break;
1310                         case KEY_END:
1311                                 menu_driver(curses_menu, REQ_LAST_ITEM);
1312                                 break;
1313                         case 'h':
1314                         case '?':
1315                                 show_help((struct menu *) item_data());
1316                                 break;
1317                         }
1318                         if (res == 10 || res == 27 || res == ' ' ||
1319                                         res == KEY_LEFT){
1320                                 break;
1321                         }
1322                         refresh_all_windows(main_window);
1323                 }
1324                 /* if ESC or left */
1325                 if (res == 27 || res == KEY_LEFT)
1326                         break;
1327
1328                 child = item_data();
1329                 if (!child || !menu_is_visible(child) || !child->sym)
1330                         continue;
1331                 switch (res) {
1332                 case ' ':
1333                 case  10:
1334                 case KEY_RIGHT:
1335                         choice_set_value(menu, child->sym);
1336                         return;
1337                 case 'h':
1338                 case '?':
1339                         show_help(child);
1340                         active = child->sym;
1341                         break;
1342                 case KEY_EXIT:
1343                         return;
1344                 }
1345         }
1346 }
1347
1348 static void conf_string(struct menu *menu)
1349 {
1350         const char *prompt = menu_get_prompt(menu);
1351
1352         while (1) {
1353                 int res;
1354                 const char *heading;
1355
1356                 switch (sym_get_type(menu->sym)) {
1357                 case S_INT:
1358                         heading = inputbox_instructions_int;
1359                         break;
1360                 case S_HEX:
1361                         heading = inputbox_instructions_hex;
1362                         break;
1363                 case S_STRING:
1364                         heading = inputbox_instructions_string;
1365                         break;
1366                 default:
1367                         heading = "Internal nconf error!";
1368                 }
1369                 res = dialog_inputbox(main_window,
1370                                 prompt ? prompt : "Main Menu",
1371                                 heading,
1372                                 sym_get_string_value(menu->sym),
1373                                 &dialog_input_result,
1374                                 &dialog_input_result_len);
1375                 switch (res) {
1376                 case 0:
1377                         if (sym_set_string_value(menu->sym,
1378                                                 dialog_input_result))
1379                                 return;
1380                         btn_dialog(main_window,
1381                                 "You have made an invalid entry.", 0);
1382                         break;
1383                 case 1:
1384                         show_help(menu);
1385                         break;
1386                 case KEY_EXIT:
1387                         return;
1388                 }
1389         }
1390 }
1391
1392 static void conf_load(void)
1393 {
1394         while (1) {
1395                 int res;
1396                 res = dialog_inputbox(main_window,
1397                                 NULL, load_config_text,
1398                                 filename,
1399                                 &dialog_input_result,
1400                                 &dialog_input_result_len);
1401                 switch (res) {
1402                 case 0:
1403                         if (!dialog_input_result[0])
1404                                 return;
1405                         if (!conf_read(dialog_input_result)) {
1406                                 set_config_filename(dialog_input_result);
1407                                 conf_set_changed(true);
1408                                 return;
1409                         }
1410                         btn_dialog(main_window, "File does not exist!", 0);
1411                         break;
1412                 case 1:
1413                         show_scroll_win(main_window,
1414                                         "Load Alternate Configuration",
1415                                         load_config_help);
1416                         break;
1417                 case KEY_EXIT:
1418                         return;
1419                 }
1420         }
1421 }
1422
1423 static void conf_save(void)
1424 {
1425         while (1) {
1426                 int res;
1427                 res = dialog_inputbox(main_window,
1428                                 NULL, save_config_text,
1429                                 filename,
1430                                 &dialog_input_result,
1431                                 &dialog_input_result_len);
1432                 switch (res) {
1433                 case 0:
1434                         if (!dialog_input_result[0])
1435                                 return;
1436                         res = conf_write(dialog_input_result);
1437                         if (!res) {
1438                                 set_config_filename(dialog_input_result);
1439                                 return;
1440                         }
1441                         btn_dialog(main_window, "Can't create file!",
1442                                 1, "<OK>");
1443                         break;
1444                 case 1:
1445                         show_scroll_win(main_window,
1446                                 "Save Alternate Configuration",
1447                                 save_config_help);
1448                         break;
1449                 case KEY_EXIT:
1450                         return;
1451                 }
1452         }
1453 }
1454
1455 static void setup_windows(void)
1456 {
1457         int lines, columns;
1458
1459         getmaxyx(stdscr, lines, columns);
1460
1461         if (main_window != NULL)
1462                 delwin(main_window);
1463
1464         /* set up the menu and menu window */
1465         main_window = newwin(lines-2, columns-2, 2, 1);
1466         keypad(main_window, TRUE);
1467         mwin_max_lines = lines-7;
1468         mwin_max_cols = columns-6;
1469
1470         /* panels order is from bottom to top */
1471         new_panel(main_window);
1472 }
1473
1474 int main(int ac, char **av)
1475 {
1476         int lines, columns;
1477         char *mode;
1478
1479         if (ac > 1 && strcmp(av[1], "-s") == 0) {
1480                 /* Silence conf_read() until the real callback is set up */
1481                 conf_set_message_callback(NULL);
1482                 av++;
1483         }
1484         conf_parse(av[1]);
1485         conf_read(NULL);
1486
1487         mode = getenv("NCONFIG_MODE");
1488         if (mode) {
1489                 if (!strcasecmp(mode, "single_menu"))
1490                         single_menu_mode = 1;
1491         }
1492
1493         /* Initialize curses */
1494         initscr();
1495         /* set color theme */
1496         set_colors();
1497
1498         cbreak();
1499         noecho();
1500         keypad(stdscr, TRUE);
1501         curs_set(0);
1502
1503         getmaxyx(stdscr, lines, columns);
1504         if (columns < 75 || lines < 20) {
1505                 endwin();
1506                 printf("Your terminal should have at "
1507                         "least 20 lines and 75 columns\n");
1508                 return 1;
1509         }
1510
1511         notimeout(stdscr, FALSE);
1512 #if NCURSES_REENTRANT
1513         set_escdelay(1);
1514 #else
1515         ESCDELAY = 1;
1516 #endif
1517
1518         /* set btns menu */
1519         curses_menu = new_menu(curses_menu_items);
1520         menu_opts_off(curses_menu, O_SHOWDESC);
1521         menu_opts_on(curses_menu, O_SHOWMATCH);
1522         menu_opts_on(curses_menu, O_ONEVALUE);
1523         menu_opts_on(curses_menu, O_NONCYCLIC);
1524         menu_opts_on(curses_menu, O_IGNORECASE);
1525         set_menu_mark(curses_menu, " ");
1526         set_menu_fore(curses_menu, attr_main_menu_fore);
1527         set_menu_back(curses_menu, attr_main_menu_back);
1528         set_menu_grey(curses_menu, attr_main_menu_grey);
1529
1530         set_config_filename(conf_get_configname());
1531         setup_windows();
1532
1533         /* check for KEY_FUNC(1) */
1534         if (has_key(KEY_F(1)) == FALSE) {
1535                 show_scroll_win(main_window,
1536                                 "Instructions",
1537                                 menu_no_f_instructions);
1538         }
1539
1540         conf_set_message_callback(conf_message_callback);
1541         /* do the work */
1542         while (!global_exit) {
1543                 conf(&rootmenu);
1544                 if (!global_exit && do_exit() == 0)
1545                         break;
1546         }
1547         /* ok, we are done */
1548         unpost_menu(curses_menu);
1549         free_menu(curses_menu);
1550         delwin(main_window);
1551         clear();
1552         refresh();
1553         endwin();
1554         return 0;
1555 }
This page took 0.115886 seconds and 4 git commands to generate.