~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/scripts/kconfig/nconf.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php