1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/kconfig/nconf.c Thu Mar 15 13:20:34 2012 +0100
1.3 @@ -0,0 +1,1561 @@
1.4 +/*
1.5 + * Copyright (C) 2008 Nir Tzachar <nir.tzachar@gmail.com?
1.6 + * Released under the terms of the GNU GPL v2.0.
1.7 + *
1.8 + * Derived from menuconfig.
1.9 + *
1.10 + */
1.11 +#define _GNU_SOURCE
1.12 +#include <string.h>
1.13 +#define LKC_DIRECT_LINK
1.14 +#include "lkc.h"
1.15 +#include "nconf.h"
1.16 +#include <ctype.h>
1.17 +
1.18 +static const char nconf_readme[] = N_(
1.19 +"Overview\n"
1.20 +"--------\n"
1.21 +"This interface let you select features and parameters for the build.\n"
1.22 +"Features can either be built-in, modularized, or ignored. Parameters\n"
1.23 +"must be entered in as decimal or hexadecimal numbers or text.\n"
1.24 +"\n"
1.25 +"Menu items beginning with following braces represent features that\n"
1.26 +" [ ] can be built in or removed\n"
1.27 +" < > can be built in, modularized or removed\n"
1.28 +" { } can be built in or modularized (selected by other feature)\n"
1.29 +" - - are selected by other feature,\n"
1.30 +" XXX cannot be selected. Use Symbol Info to find out why,\n"
1.31 +"while *, M or whitespace inside braces means to build in, build as\n"
1.32 +"a module or to exclude the feature respectively.\n"
1.33 +"\n"
1.34 +"To change any of these features, highlight it with the cursor\n"
1.35 +"keys and press <Y> to build it in, <M> to make it a module or\n"
1.36 +"<N> to removed it. You may also press the <Space Bar> to cycle\n"
1.37 +"through the available options (ie. Y->N->M->Y).\n"
1.38 +"\n"
1.39 +"Some additional keyboard hints:\n"
1.40 +"\n"
1.41 +"Menus\n"
1.42 +"----------\n"
1.43 +"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n"
1.44 +" you wish to change use <Enter> or <Space>. Goto submenu by \n"
1.45 +" pressing <Enter> of <right-arrow>. Use <Esc> or <left-arrow> to go back.\n"
1.46 +" Submenus are designated by \"--->\".\n"
1.47 +"\n"
1.48 +" Searching: pressing '/' triggers interactive search mode.\n"
1.49 +" nconfig performs a case insensitive search for the string\n"
1.50 +" in the menu prompts (no regex support).\n"
1.51 +" Pressing the up/down keys highlights the previous/next\n"
1.52 +" matching item. Backspace removes one character from the\n"
1.53 +" match string. Pressing either '/' again or ESC exits\n"
1.54 +" search mode. All other keys behave normally.\n"
1.55 +"\n"
1.56 +" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
1.57 +" unseen options into view.\n"
1.58 +"\n"
1.59 +"o To exit a menu use the just press <ESC> <F5> <F8> or <left-arrow>.\n"
1.60 +"\n"
1.61 +"o To get help with an item, press <F1>\n"
1.62 +" Shortcut: Press <h> or <?>.\n"
1.63 +"\n"
1.64 +"\n"
1.65 +"Radiolists (Choice lists)\n"
1.66 +"-----------\n"
1.67 +"o Use the cursor keys to select the option you wish to set and press\n"
1.68 +" <S> or the <SPACE BAR>.\n"
1.69 +"\n"
1.70 +" Shortcut: Press the first letter of the option you wish to set then\n"
1.71 +" press <S> or <SPACE BAR>.\n"
1.72 +"\n"
1.73 +"o To see available help for the item, press <F1>\n"
1.74 +" Shortcut: Press <H> or <?>.\n"
1.75 +"\n"
1.76 +"\n"
1.77 +"Data Entry\n"
1.78 +"-----------\n"
1.79 +"o Enter the requested information and press <ENTER>\n"
1.80 +" If you are entering hexadecimal values, it is not necessary to\n"
1.81 +" add the '0x' prefix to the entry.\n"
1.82 +"\n"
1.83 +"o For help, press <F1>.\n"
1.84 +"\n"
1.85 +"\n"
1.86 +"Text Box (Help Window)\n"
1.87 +"--------\n"
1.88 +"o Use the cursor keys to scroll up/down/left/right. The VI editor\n"
1.89 +" keys h,j,k,l function here as do <SPACE BAR> for those\n"
1.90 +" who are familiar with less and lynx.\n"
1.91 +"\n"
1.92 +"o Press <Enter>, <F1>, <F5>, <F7> or <Esc> to exit.\n"
1.93 +"\n"
1.94 +"\n"
1.95 +"Alternate Configuration Files\n"
1.96 +"-----------------------------\n"
1.97 +"nconfig supports the use of alternate configuration files for\n"
1.98 +"those who, for various reasons, find it necessary to switch\n"
1.99 +"between different configurations.\n"
1.100 +"\n"
1.101 +"At the end of the main menu you will find two options. One is\n"
1.102 +"for saving the current configuration to a file of your choosing.\n"
1.103 +"The other option is for loading a previously saved alternate\n"
1.104 +"configuration.\n"
1.105 +"\n"
1.106 +"Even if you don't use alternate configuration files, but you\n"
1.107 +"find during a nconfig session that you have completely messed\n"
1.108 +"up your settings, you may use the \"Load Alternate...\" option to\n"
1.109 +"restore your previously saved settings from \".config\" without\n"
1.110 +"restarting nconfig.\n"
1.111 +"\n"
1.112 +"Other information\n"
1.113 +"-----------------\n"
1.114 +"If you use nconfig in an XTERM window make sure you have your\n"
1.115 +"$TERM variable set to point to a xterm definition which supports color.\n"
1.116 +"Otherwise, nconfig will look rather bad. nconfig will not\n"
1.117 +"display correctly in a RXVT window because rxvt displays only one\n"
1.118 +"intensity of color, bright.\n"
1.119 +"\n"
1.120 +"nconfig will display larger menus on screens or xterms which are\n"
1.121 +"set to display more than the standard 25 row by 80 column geometry.\n"
1.122 +"In order for this to work, the \"stty size\" command must be able to\n"
1.123 +"display the screen's current row and column geometry. I STRONGLY\n"
1.124 +"RECOMMEND that you make sure you do NOT have the shell variables\n"
1.125 +"LINES and COLUMNS exported into your environment. Some distributions\n"
1.126 +"export those variables via /etc/profile. Some ncurses programs can\n"
1.127 +"become confused when those variables (LINES & COLUMNS) don't reflect\n"
1.128 +"the true screen size.\n"
1.129 +"\n"
1.130 +"Optional personality available\n"
1.131 +"------------------------------\n"
1.132 +"If you prefer to have all of the options listed in a single menu, rather\n"
1.133 +"than the default multimenu hierarchy, run the nconfig with NCONFIG_MODE\n"
1.134 +"environment variable set to single_menu. Example:\n"
1.135 +"\n"
1.136 +"make NCONFIG_MODE=single_menu nconfig\n"
1.137 +"\n"
1.138 +"<Enter> will then unroll the appropriate category, or enfold it if it\n"
1.139 +"is already unrolled.\n"
1.140 +"\n"
1.141 +"Note that this mode can eventually be a little more CPU expensive\n"
1.142 +"(especially with a larger number of unrolled categories) than the\n"
1.143 +"default mode.\n"
1.144 +"\n"),
1.145 +menu_no_f_instructions[] = N_(
1.146 +" You do not have function keys support. Please follow the\n"
1.147 +" following instructions:\n"
1.148 +" Arrow keys navigate the menu.\n"
1.149 +" <Enter> or <right-arrow> selects submenus --->.\n"
1.150 +" Capital Letters are hotkeys.\n"
1.151 +" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
1.152 +" Pressing SpaceBar toggles between the above options.\n"
1.153 +" Press <Esc> or <left-arrow> to go back one menu,\n"
1.154 +" <?> or <h> for Help, </> for Search.\n"
1.155 +" <1> is interchangeable with <F1>, <2> with <F2>, etc.\n"
1.156 +" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
1.157 +" <Esc> always leaves the current window.\n"),
1.158 +menu_instructions[] = N_(
1.159 +" Arrow keys navigate the menu.\n"
1.160 +" <Enter> or <right-arrow> selects submenus --->.\n"
1.161 +" Capital Letters are hotkeys.\n"
1.162 +" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
1.163 +" Pressing SpaceBar toggles between the above options\n"
1.164 +" Press <Esc>, <F5> or <left-arrow> to go back one menu,\n"
1.165 +" <?>, <F1> or <h> for Help, </> for Search.\n"
1.166 +" <1> is interchangeable with <F1>, <2> with <F2>, etc.\n"
1.167 +" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
1.168 +" <Esc> always leaves the current window\n"),
1.169 +radiolist_instructions[] = N_(
1.170 +" Use the arrow keys to navigate this window or\n"
1.171 +" press the hotkey of the item you wish to select\n"
1.172 +" followed by the <SPACE BAR>.\n"
1.173 +" Press <?>, <F1> or <h> for additional information about this option.\n"),
1.174 +inputbox_instructions_int[] = N_(
1.175 +"Please enter a decimal value.\n"
1.176 +"Fractions will not be accepted.\n"
1.177 +"Press <RETURN> to accept, <ESC> to cancel."),
1.178 +inputbox_instructions_hex[] = N_(
1.179 +"Please enter a hexadecimal value.\n"
1.180 +"Press <RETURN> to accept, <ESC> to cancel."),
1.181 +inputbox_instructions_string[] = N_(
1.182 +"Please enter a string value.\n"
1.183 +"Press <RETURN> to accept, <ESC> to cancel."),
1.184 +setmod_text[] = N_(
1.185 +"This feature depends on another which\n"
1.186 +"has been configured as a module.\n"
1.187 +"As a result, this feature will be built as a module."),
1.188 +nohelp_text[] = N_(
1.189 +"There is no help available for this option.\n"),
1.190 +load_config_text[] = N_(
1.191 +"Enter the name of the configuration file you wish to load.\n"
1.192 +"Accept the name shown to restore the configuration you\n"
1.193 +"last retrieved. Leave blank to abort."),
1.194 +load_config_help[] = N_(
1.195 +"\n"
1.196 +"For various reasons, one may wish to keep several different\n"
1.197 +"configurations available on a single machine.\n"
1.198 +"\n"
1.199 +"If you have saved a previous configuration in a file other than the\n"
1.200 +"default one, entering its name here will allow you to modify that\n"
1.201 +"configuration.\n"
1.202 +"\n"
1.203 +"If you are uncertain, then you have probably never used alternate\n"
1.204 +"configuration files. You should therefor leave this blank to abort.\n"),
1.205 +save_config_text[] = N_(
1.206 +"Enter a filename to which this configuration should be saved\n"
1.207 +"as an alternate. Leave blank to abort."),
1.208 +save_config_help[] = N_(
1.209 +"\n"
1.210 +"For various reasons, one may wish to keep different configurations\n"
1.211 +"available on a single machine.\n"
1.212 +"\n"
1.213 +"Entering a file name here will allow you to later retrieve, modify\n"
1.214 +"and use the current configuration as an alternate to whatever\n"
1.215 +"configuration options you have selected at that time.\n"
1.216 +"\n"
1.217 +"If you are uncertain what all this means then you should probably\n"
1.218 +"leave this blank.\n"),
1.219 +search_help[] = N_(
1.220 +"\n"
1.221 +"Search for symbols and display their relations. Regular expressions\n"
1.222 +"are allowed.\n"
1.223 +"Example: search for \"^FOO\"\n"
1.224 +"Result:\n"
1.225 +"-----------------------------------------------------------------\n"
1.226 +"Symbol: FOO [ = m]\n"
1.227 +"Prompt: Foo bus is used to drive the bar HW\n"
1.228 +"Defined at drivers/pci/Kconfig:47\n"
1.229 +"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
1.230 +"Location:\n"
1.231 +" -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n"
1.232 +" -> PCI support (PCI [ = y])\n"
1.233 +" -> PCI access mode (<choice> [ = y])\n"
1.234 +"Selects: LIBCRC32\n"
1.235 +"Selected by: BAR\n"
1.236 +"-----------------------------------------------------------------\n"
1.237 +"o The line 'Prompt:' shows the text used in the menu structure for\n"
1.238 +" this symbol\n"
1.239 +"o The 'Defined at' line tell at what file / line number the symbol\n"
1.240 +" is defined\n"
1.241 +"o The 'Depends on:' line tell what symbols needs to be defined for\n"
1.242 +" this symbol to be visible in the menu (selectable)\n"
1.243 +"o The 'Location:' lines tell where in the menu structure this symbol\n"
1.244 +" is located\n"
1.245 +" A location followed by a [ = y] indicate that this is a selectable\n"
1.246 +" menu item - and current value is displayed inside brackets.\n"
1.247 +"o The 'Selects:' line tell what symbol will be automatically\n"
1.248 +" selected if this symbol is selected (y or m)\n"
1.249 +"o The 'Selected by' line tell what symbol has selected this symbol\n"
1.250 +"\n"
1.251 +"Only relevant lines are shown.\n"
1.252 +"\n\n"
1.253 +"Search examples:\n"
1.254 +"Examples: USB => find all symbols containing USB\n"
1.255 +" ^USB => find all symbols starting with USB\n"
1.256 +" USB$ => find all symbols ending with USB\n"
1.257 +"\n");
1.258 +
1.259 +struct mitem {
1.260 + char str[256];
1.261 + char tag;
1.262 + void *usrptr;
1.263 + int is_visible;
1.264 +};
1.265 +
1.266 +#define MAX_MENU_ITEMS 4096
1.267 +static int show_all_items;
1.268 +static int indent;
1.269 +static struct menu *current_menu;
1.270 +static int child_count;
1.271 +static int single_menu_mode;
1.272 +/* the window in which all information appears */
1.273 +static WINDOW *main_window;
1.274 +/* the largest size of the menu window */
1.275 +static int mwin_max_lines;
1.276 +static int mwin_max_cols;
1.277 +/* the window in which we show option buttons */
1.278 +static MENU *curses_menu;
1.279 +static ITEM *curses_menu_items[MAX_MENU_ITEMS];
1.280 +static struct mitem k_menu_items[MAX_MENU_ITEMS];
1.281 +static int items_num;
1.282 +static int global_exit;
1.283 +/* the currently selected button */
1.284 +const char *current_instructions = menu_instructions;
1.285 +
1.286 +static void conf(struct menu *menu);
1.287 +static void conf_choice(struct menu *menu);
1.288 +static void conf_string(struct menu *menu);
1.289 +static void conf_load(void);
1.290 +static void conf_save(void);
1.291 +static void show_help(struct menu *menu);
1.292 +static int do_exit(void);
1.293 +static void setup_windows(void);
1.294 +static void search_conf(void);
1.295 +
1.296 +typedef void (*function_key_handler_t)(int *key, struct menu *menu);
1.297 +static void handle_f1(int *key, struct menu *current_item);
1.298 +static void handle_f2(int *key, struct menu *current_item);
1.299 +static void handle_f3(int *key, struct menu *current_item);
1.300 +static void handle_f4(int *key, struct menu *current_item);
1.301 +static void handle_f5(int *key, struct menu *current_item);
1.302 +static void handle_f6(int *key, struct menu *current_item);
1.303 +static void handle_f7(int *key, struct menu *current_item);
1.304 +static void handle_f8(int *key, struct menu *current_item);
1.305 +static void handle_f9(int *key, struct menu *current_item);
1.306 +
1.307 +struct function_keys {
1.308 + const char *key_str;
1.309 + const char *func;
1.310 + function_key key;
1.311 + function_key_handler_t handler;
1.312 +};
1.313 +
1.314 +static const int function_keys_num = 9;
1.315 +struct function_keys function_keys[] = {
1.316 + {
1.317 + .key_str = "F1",
1.318 + .func = "Help",
1.319 + .key = F_HELP,
1.320 + .handler = handle_f1,
1.321 + },
1.322 + {
1.323 + .key_str = "F2",
1.324 + .func = "Sym Info",
1.325 + .key = F_SYMBOL,
1.326 + .handler = handle_f2,
1.327 + },
1.328 + {
1.329 + .key_str = "F3",
1.330 + .func = "Insts",
1.331 + .key = F_INSTS,
1.332 + .handler = handle_f3,
1.333 + },
1.334 + {
1.335 + .key_str = "F4",
1.336 + .func = "Config",
1.337 + .key = F_CONF,
1.338 + .handler = handle_f4,
1.339 + },
1.340 + {
1.341 + .key_str = "F5",
1.342 + .func = "Back",
1.343 + .key = F_BACK,
1.344 + .handler = handle_f5,
1.345 + },
1.346 + {
1.347 + .key_str = "F6",
1.348 + .func = "Save",
1.349 + .key = F_SAVE,
1.350 + .handler = handle_f6,
1.351 + },
1.352 + {
1.353 + .key_str = "F7",
1.354 + .func = "Load",
1.355 + .key = F_LOAD,
1.356 + .handler = handle_f7,
1.357 + },
1.358 + {
1.359 + .key_str = "F8",
1.360 + .func = "Sym Search",
1.361 + .key = F_SEARCH,
1.362 + .handler = handle_f8,
1.363 + },
1.364 + {
1.365 + .key_str = "F9",
1.366 + .func = "Exit",
1.367 + .key = F_EXIT,
1.368 + .handler = handle_f9,
1.369 + },
1.370 +};
1.371 +
1.372 +static void print_function_line(void)
1.373 +{
1.374 + int i;
1.375 + int offset = 1;
1.376 + const int skip = 1;
1.377 +
1.378 + for (i = 0; i < function_keys_num; i++) {
1.379 + (void) wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]);
1.380 + mvwprintw(main_window, LINES-3, offset,
1.381 + "%s",
1.382 + function_keys[i].key_str);
1.383 + (void) wattrset(main_window, attributes[FUNCTION_TEXT]);
1.384 + offset += strlen(function_keys[i].key_str);
1.385 + mvwprintw(main_window, LINES-3,
1.386 + offset, "%s",
1.387 + function_keys[i].func);
1.388 + offset += strlen(function_keys[i].func) + skip;
1.389 + }
1.390 + (void) wattrset(main_window, attributes[NORMAL]);
1.391 +}
1.392 +
1.393 +/* help */
1.394 +static void handle_f1(int *key, struct menu *current_item)
1.395 +{
1.396 + show_scroll_win(main_window,
1.397 + _("README"), _(nconf_readme));
1.398 + return;
1.399 +}
1.400 +
1.401 +/* symbole help */
1.402 +static void handle_f2(int *key, struct menu *current_item)
1.403 +{
1.404 + show_help(current_item);
1.405 + return;
1.406 +}
1.407 +
1.408 +/* instructions */
1.409 +static void handle_f3(int *key, struct menu *current_item)
1.410 +{
1.411 + show_scroll_win(main_window,
1.412 + _("Instructions"),
1.413 + _(current_instructions));
1.414 + return;
1.415 +}
1.416 +
1.417 +/* config */
1.418 +static void handle_f4(int *key, struct menu *current_item)
1.419 +{
1.420 + int res = btn_dialog(main_window,
1.421 + _("Show all symbols?"),
1.422 + 2,
1.423 + " <Show All> ",
1.424 + "<Don't show all>");
1.425 + if (res == 0)
1.426 + show_all_items = 1;
1.427 + else if (res == 1)
1.428 + show_all_items = 0;
1.429 +
1.430 + return;
1.431 +}
1.432 +
1.433 +/* back */
1.434 +static void handle_f5(int *key, struct menu *current_item)
1.435 +{
1.436 + *key = KEY_LEFT;
1.437 + return;
1.438 +}
1.439 +
1.440 +/* save */
1.441 +static void handle_f6(int *key, struct menu *current_item)
1.442 +{
1.443 + conf_save();
1.444 + return;
1.445 +}
1.446 +
1.447 +/* load */
1.448 +static void handle_f7(int *key, struct menu *current_item)
1.449 +{
1.450 + conf_load();
1.451 + return;
1.452 +}
1.453 +
1.454 +/* search */
1.455 +static void handle_f8(int *key, struct menu *current_item)
1.456 +{
1.457 + search_conf();
1.458 + return;
1.459 +}
1.460 +
1.461 +/* exit */
1.462 +static void handle_f9(int *key, struct menu *current_item)
1.463 +{
1.464 + do_exit();
1.465 + return;
1.466 +}
1.467 +
1.468 +/* return != 0 to indicate the key was handles */
1.469 +static int process_special_keys(int *key, struct menu *menu)
1.470 +{
1.471 + int i;
1.472 +
1.473 + if (*key == KEY_RESIZE) {
1.474 + setup_windows();
1.475 + return 1;
1.476 + }
1.477 +
1.478 + for (i = 0; i < function_keys_num; i++) {
1.479 + if (*key == KEY_F(function_keys[i].key) ||
1.480 + *key == '0' + function_keys[i].key){
1.481 + function_keys[i].handler(key, menu);
1.482 + return 1;
1.483 + }
1.484 + }
1.485 +
1.486 + return 0;
1.487 +}
1.488 +
1.489 +static void clean_items(void)
1.490 +{
1.491 + int i;
1.492 + for (i = 0; curses_menu_items[i]; i++)
1.493 + free_item(curses_menu_items[i]);
1.494 + bzero(curses_menu_items, sizeof(curses_menu_items));
1.495 + bzero(k_menu_items, sizeof(k_menu_items));
1.496 + items_num = 0;
1.497 +}
1.498 +
1.499 +typedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN,
1.500 + FIND_NEXT_MATCH_DOWN, FIND_NEXT_MATCH_UP} match_f;
1.501 +
1.502 +/* return the index of the matched item, or -1 if no such item exists */
1.503 +static int get_mext_match(const char *match_str, match_f flag)
1.504 +{
1.505 + int match_start = item_index(current_item(curses_menu));
1.506 + int index;
1.507 +
1.508 + if (flag == FIND_NEXT_MATCH_DOWN)
1.509 + ++match_start;
1.510 + else if (flag == FIND_NEXT_MATCH_UP)
1.511 + --match_start;
1.512 +
1.513 + index = match_start;
1.514 + index = (index + items_num) % items_num;
1.515 + while (true) {
1.516 + char *str = k_menu_items[index].str;
1.517 + if (strcasestr(str, match_str) != 0)
1.518 + return index;
1.519 + if (flag == FIND_NEXT_MATCH_UP ||
1.520 + flag == MATCH_TINKER_PATTERN_UP)
1.521 + --index;
1.522 + else
1.523 + ++index;
1.524 + index = (index + items_num) % items_num;
1.525 + if (index == match_start)
1.526 + return -1;
1.527 + }
1.528 +}
1.529 +
1.530 +/* Make a new item. */
1.531 +static void item_make(struct menu *menu, char tag, const char *fmt, ...)
1.532 +{
1.533 + va_list ap;
1.534 +
1.535 + if (items_num > MAX_MENU_ITEMS-1)
1.536 + return;
1.537 +
1.538 + bzero(&k_menu_items[items_num], sizeof(k_menu_items[0]));
1.539 + k_menu_items[items_num].tag = tag;
1.540 + k_menu_items[items_num].usrptr = menu;
1.541 + if (menu != NULL)
1.542 + k_menu_items[items_num].is_visible =
1.543 + menu_is_visible(menu);
1.544 + else
1.545 + k_menu_items[items_num].is_visible = 1;
1.546 +
1.547 + va_start(ap, fmt);
1.548 + vsnprintf(k_menu_items[items_num].str,
1.549 + sizeof(k_menu_items[items_num].str),
1.550 + fmt, ap);
1.551 + va_end(ap);
1.552 +
1.553 + if (!k_menu_items[items_num].is_visible)
1.554 + memcpy(k_menu_items[items_num].str, "XXX", 3);
1.555 +
1.556 + curses_menu_items[items_num] = new_item(
1.557 + k_menu_items[items_num].str,
1.558 + k_menu_items[items_num].str);
1.559 + set_item_userptr(curses_menu_items[items_num],
1.560 + &k_menu_items[items_num]);
1.561 + /*
1.562 + if (!k_menu_items[items_num].is_visible)
1.563 + item_opts_off(curses_menu_items[items_num], O_SELECTABLE);
1.564 + */
1.565 +
1.566 + items_num++;
1.567 + curses_menu_items[items_num] = NULL;
1.568 +}
1.569 +
1.570 +/* very hackish. adds a string to the last item added */
1.571 +static void item_add_str(const char *fmt, ...)
1.572 +{
1.573 + va_list ap;
1.574 + int index = items_num-1;
1.575 + char new_str[256];
1.576 + char tmp_str[256];
1.577 +
1.578 + if (index < 0)
1.579 + return;
1.580 +
1.581 + va_start(ap, fmt);
1.582 + vsnprintf(new_str, sizeof(new_str), fmt, ap);
1.583 + va_end(ap);
1.584 + snprintf(tmp_str, sizeof(tmp_str), "%s%s",
1.585 + k_menu_items[index].str, new_str);
1.586 + strncpy(k_menu_items[index].str,
1.587 + tmp_str,
1.588 + sizeof(k_menu_items[index].str));
1.589 +
1.590 + free_item(curses_menu_items[index]);
1.591 + curses_menu_items[index] = new_item(
1.592 + k_menu_items[index].str,
1.593 + k_menu_items[index].str);
1.594 + set_item_userptr(curses_menu_items[index],
1.595 + &k_menu_items[index]);
1.596 +}
1.597 +
1.598 +/* get the tag of the currently selected item */
1.599 +static char item_tag(void)
1.600 +{
1.601 + ITEM *cur;
1.602 + struct mitem *mcur;
1.603 +
1.604 + cur = current_item(curses_menu);
1.605 + if (cur == NULL)
1.606 + return 0;
1.607 + mcur = (struct mitem *) item_userptr(cur);
1.608 + return mcur->tag;
1.609 +}
1.610 +
1.611 +static int curses_item_index(void)
1.612 +{
1.613 + return item_index(current_item(curses_menu));
1.614 +}
1.615 +
1.616 +static void *item_data(void)
1.617 +{
1.618 + ITEM *cur;
1.619 + struct mitem *mcur;
1.620 +
1.621 + cur = current_item(curses_menu);
1.622 + if (!cur)
1.623 + return NULL;
1.624 + mcur = (struct mitem *) item_userptr(cur);
1.625 + return mcur->usrptr;
1.626 +
1.627 +}
1.628 +
1.629 +static int item_is_tag(char tag)
1.630 +{
1.631 + return item_tag() == tag;
1.632 +}
1.633 +
1.634 +static char filename[PATH_MAX+1];
1.635 +static char menu_backtitle[PATH_MAX+128];
1.636 +static const char *set_config_filename(const char *config_filename)
1.637 +{
1.638 + int size;
1.639 +
1.640 + size = snprintf(menu_backtitle, sizeof(menu_backtitle),
1.641 + "%s - %s", config_filename, rootmenu.prompt->text);
1.642 + if (size >= sizeof(menu_backtitle))
1.643 + menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
1.644 +
1.645 + size = snprintf(filename, sizeof(filename), "%s", config_filename);
1.646 + if (size >= sizeof(filename))
1.647 + filename[sizeof(filename)-1] = '\0';
1.648 + return menu_backtitle;
1.649 +}
1.650 +
1.651 +/* return = 0 means we are successful.
1.652 + * -1 means go on doing what you were doing
1.653 + */
1.654 +static int do_exit(void)
1.655 +{
1.656 + int res;
1.657 + if (!conf_get_changed()) {
1.658 + global_exit = 1;
1.659 + return 0;
1.660 + }
1.661 + res = btn_dialog(main_window,
1.662 + _("Do you wish to save your new configuration?\n"
1.663 + "<ESC> to cancel and resume nconfig."),
1.664 + 2,
1.665 + " <save> ",
1.666 + "<don't save>");
1.667 + if (res == KEY_EXIT) {
1.668 + global_exit = 0;
1.669 + return -1;
1.670 + }
1.671 +
1.672 + /* if we got here, the user really wants to exit */
1.673 + switch (res) {
1.674 + case 0:
1.675 + res = conf_write(filename);
1.676 + if (res)
1.677 + btn_dialog(
1.678 + main_window,
1.679 + _("Error during writing of configuration.\n"
1.680 + "Your configuration changes were NOT saved."),
1.681 + 1,
1.682 + "<OK>");
1.683 + break;
1.684 + default:
1.685 + btn_dialog(
1.686 + main_window,
1.687 + _("Your configuration changes were NOT saved."),
1.688 + 1,
1.689 + "<OK>");
1.690 + break;
1.691 + }
1.692 + global_exit = 1;
1.693 + return 0;
1.694 +}
1.695 +
1.696 +
1.697 +static void search_conf(void)
1.698 +{
1.699 + struct symbol **sym_arr;
1.700 + struct gstr res;
1.701 + char dialog_input_result[100];
1.702 + char *dialog_input;
1.703 + int dres;
1.704 +again:
1.705 + dres = dialog_inputbox(main_window,
1.706 + _("Search Configuration Parameter"),
1.707 + _("Enter " CONFIG_ " (sub)string to search for "
1.708 + "(with or without \"" CONFIG_ "\")"),
1.709 + "", dialog_input_result, 99);
1.710 + switch (dres) {
1.711 + case 0:
1.712 + break;
1.713 + case 1:
1.714 + show_scroll_win(main_window,
1.715 + _("Search Configuration"), search_help);
1.716 + goto again;
1.717 + default:
1.718 + return;
1.719 + }
1.720 +
1.721 + /* strip the prefix if necessary */
1.722 + dialog_input = dialog_input_result;
1.723 + if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
1.724 + dialog_input += strlen(CONFIG_);
1.725 +
1.726 + sym_arr = sym_re_search(dialog_input);
1.727 + res = get_relations_str(sym_arr);
1.728 + free(sym_arr);
1.729 + show_scroll_win(main_window,
1.730 + _("Search Results"), str_get(&res));
1.731 + str_free(&res);
1.732 +}
1.733 +
1.734 +
1.735 +static void build_conf(struct menu *menu)
1.736 +{
1.737 + struct symbol *sym;
1.738 + struct property *prop;
1.739 + struct menu *child;
1.740 + int type, tmp, doint = 2;
1.741 + tristate val;
1.742 + char ch;
1.743 +
1.744 + if (!menu || (!show_all_items && !menu_is_visible(menu)))
1.745 + return;
1.746 +
1.747 + sym = menu->sym;
1.748 + prop = menu->prompt;
1.749 + if (!sym) {
1.750 + if (prop && menu != current_menu) {
1.751 + const char *prompt = menu_get_prompt(menu);
1.752 + enum prop_type ptype;
1.753 + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN;
1.754 + switch (ptype) {
1.755 + case P_MENU:
1.756 + child_count++;
1.757 + prompt = _(prompt);
1.758 + if (single_menu_mode) {
1.759 + item_make(menu, 'm',
1.760 + "%s%*c%s",
1.761 + menu->data ? "-->" : "++>",
1.762 + indent + 1, ' ', prompt);
1.763 + } else
1.764 + item_make(menu, 'm',
1.765 + " %*c%s --->",
1.766 + indent + 1,
1.767 + ' ', prompt);
1.768 +
1.769 + if (single_menu_mode && menu->data)
1.770 + goto conf_childs;
1.771 + return;
1.772 + case P_COMMENT:
1.773 + if (prompt) {
1.774 + child_count++;
1.775 + item_make(menu, ':',
1.776 + " %*c*** %s ***",
1.777 + indent + 1, ' ',
1.778 + _(prompt));
1.779 + }
1.780 + break;
1.781 + default:
1.782 + if (prompt) {
1.783 + child_count++;
1.784 + item_make(menu, ':', "---%*c%s",
1.785 + indent + 1, ' ',
1.786 + _(prompt));
1.787 + }
1.788 + }
1.789 + } else
1.790 + doint = 0;
1.791 + goto conf_childs;
1.792 + }
1.793 +
1.794 + type = sym_get_type(sym);
1.795 + if (sym_is_choice(sym)) {
1.796 + struct symbol *def_sym = sym_get_choice_value(sym);
1.797 + struct menu *def_menu = NULL;
1.798 +
1.799 + child_count++;
1.800 + for (child = menu->list; child; child = child->next) {
1.801 + if (menu_is_visible(child) && child->sym == def_sym)
1.802 + def_menu = child;
1.803 + }
1.804 +
1.805 + val = sym_get_tristate_value(sym);
1.806 + if (sym_is_changable(sym)) {
1.807 + switch (type) {
1.808 + case S_BOOLEAN:
1.809 + item_make(menu, 't', "[%c]",
1.810 + val == no ? ' ' : '*');
1.811 + break;
1.812 + case S_TRISTATE:
1.813 + switch (val) {
1.814 + case yes:
1.815 + ch = '*';
1.816 + break;
1.817 + case mod:
1.818 + ch = 'M';
1.819 + break;
1.820 + default:
1.821 + ch = ' ';
1.822 + break;
1.823 + }
1.824 + item_make(menu, 't', "<%c>", ch);
1.825 + break;
1.826 + }
1.827 + } else {
1.828 + item_make(menu, def_menu ? 't' : ':', " ");
1.829 + }
1.830 +
1.831 + item_add_str("%*c%s", indent + 1,
1.832 + ' ', _(menu_get_prompt(menu)));
1.833 + if (val == yes) {
1.834 + if (def_menu) {
1.835 + item_add_str(" (%s)",
1.836 + _(menu_get_prompt(def_menu)));
1.837 + item_add_str(" --->");
1.838 + if (def_menu->list) {
1.839 + indent += 2;
1.840 + build_conf(def_menu);
1.841 + indent -= 2;
1.842 + }
1.843 + }
1.844 + return;
1.845 + }
1.846 + } else {
1.847 + if (menu == current_menu) {
1.848 + item_make(menu, ':',
1.849 + "---%*c%s", indent + 1,
1.850 + ' ', _(menu_get_prompt(menu)));
1.851 + goto conf_childs;
1.852 + }
1.853 + child_count++;
1.854 + val = sym_get_tristate_value(sym);
1.855 + if (sym_is_choice_value(sym) && val == yes) {
1.856 + item_make(menu, ':', " ");
1.857 + } else {
1.858 + switch (type) {
1.859 + case S_BOOLEAN:
1.860 + if (sym_is_changable(sym))
1.861 + item_make(menu, 't', "[%c]",
1.862 + val == no ? ' ' : '*');
1.863 + else
1.864 + item_make(menu, 't', "-%c-",
1.865 + val == no ? ' ' : '*');
1.866 + break;
1.867 + case S_TRISTATE:
1.868 + switch (val) {
1.869 + case yes:
1.870 + ch = '*';
1.871 + break;
1.872 + case mod:
1.873 + ch = 'M';
1.874 + break;
1.875 + default:
1.876 + ch = ' ';
1.877 + break;
1.878 + }
1.879 + if (sym_is_changable(sym)) {
1.880 + if (sym->rev_dep.tri == mod)
1.881 + item_make(menu,
1.882 + 't', "{%c}", ch);
1.883 + else
1.884 + item_make(menu,
1.885 + 't', "<%c>", ch);
1.886 + } else
1.887 + item_make(menu, 't', "-%c-", ch);
1.888 + break;
1.889 + default:
1.890 + tmp = 2 + strlen(sym_get_string_value(sym));
1.891 + item_make(menu, 's', " (%s)",
1.892 + sym_get_string_value(sym));
1.893 + tmp = indent - tmp + 4;
1.894 + if (tmp < 0)
1.895 + tmp = 0;
1.896 + item_add_str("%*c%s%s", tmp, ' ',
1.897 + _(menu_get_prompt(menu)),
1.898 + (sym_has_value(sym) ||
1.899 + !sym_is_changable(sym)) ? "" :
1.900 + _(" (NEW)"));
1.901 + goto conf_childs;
1.902 + }
1.903 + }
1.904 + item_add_str("%*c%s%s", indent + 1, ' ',
1.905 + _(menu_get_prompt(menu)),
1.906 + (sym_has_value(sym) || !sym_is_changable(sym)) ?
1.907 + "" : _(" (NEW)"));
1.908 + if (menu->prompt && menu->prompt->type == P_MENU) {
1.909 + item_add_str(" --->");
1.910 + return;
1.911 + }
1.912 + }
1.913 +
1.914 +conf_childs:
1.915 + indent += doint;
1.916 + for (child = menu->list; child; child = child->next)
1.917 + build_conf(child);
1.918 + indent -= doint;
1.919 +}
1.920 +
1.921 +static void reset_menu(void)
1.922 +{
1.923 + unpost_menu(curses_menu);
1.924 + clean_items();
1.925 +}
1.926 +
1.927 +/* adjust the menu to show this item.
1.928 + * prefer not to scroll the menu if possible*/
1.929 +static void center_item(int selected_index, int *last_top_row)
1.930 +{
1.931 + int toprow;
1.932 +
1.933 + set_top_row(curses_menu, *last_top_row);
1.934 + toprow = top_row(curses_menu);
1.935 + if (selected_index < toprow ||
1.936 + selected_index >= toprow+mwin_max_lines) {
1.937 + toprow = max(selected_index-mwin_max_lines/2, 0);
1.938 + if (toprow >= item_count(curses_menu)-mwin_max_lines)
1.939 + toprow = item_count(curses_menu)-mwin_max_lines;
1.940 + set_top_row(curses_menu, toprow);
1.941 + }
1.942 + set_current_item(curses_menu,
1.943 + curses_menu_items[selected_index]);
1.944 + *last_top_row = toprow;
1.945 + post_menu(curses_menu);
1.946 + refresh_all_windows(main_window);
1.947 +}
1.948 +
1.949 +/* this function assumes reset_menu has been called before */
1.950 +static void show_menu(const char *prompt, const char *instructions,
1.951 + int selected_index, int *last_top_row)
1.952 +{
1.953 + int maxx, maxy;
1.954 + WINDOW *menu_window;
1.955 +
1.956 + current_instructions = instructions;
1.957 +
1.958 + clear();
1.959 + (void) wattrset(main_window, attributes[NORMAL]);
1.960 + print_in_middle(stdscr, 1, 0, COLS,
1.961 + menu_backtitle,
1.962 + attributes[MAIN_HEADING]);
1.963 +
1.964 + (void) wattrset(main_window, attributes[MAIN_MENU_BOX]);
1.965 + box(main_window, 0, 0);
1.966 + (void) wattrset(main_window, attributes[MAIN_MENU_HEADING]);
1.967 + mvwprintw(main_window, 0, 3, " %s ", prompt);
1.968 + (void) wattrset(main_window, attributes[NORMAL]);
1.969 +
1.970 + set_menu_items(curses_menu, curses_menu_items);
1.971 +
1.972 + /* position the menu at the middle of the screen */
1.973 + scale_menu(curses_menu, &maxy, &maxx);
1.974 + maxx = min(maxx, mwin_max_cols-2);
1.975 + maxy = mwin_max_lines;
1.976 + menu_window = derwin(main_window,
1.977 + maxy,
1.978 + maxx,
1.979 + 2,
1.980 + (mwin_max_cols-maxx)/2);
1.981 + keypad(menu_window, TRUE);
1.982 + set_menu_win(curses_menu, menu_window);
1.983 + set_menu_sub(curses_menu, menu_window);
1.984 +
1.985 + /* must reassert this after changing items, otherwise returns to a
1.986 + * default of 16
1.987 + */
1.988 + set_menu_format(curses_menu, maxy, 1);
1.989 + center_item(selected_index, last_top_row);
1.990 + set_menu_format(curses_menu, maxy, 1);
1.991 +
1.992 + print_function_line();
1.993 +
1.994 + /* Post the menu */
1.995 + post_menu(curses_menu);
1.996 + refresh_all_windows(main_window);
1.997 +}
1.998 +
1.999 +static void adj_match_dir(match_f *match_direction)
1.1000 +{
1.1001 + if (*match_direction == FIND_NEXT_MATCH_DOWN)
1.1002 + *match_direction =
1.1003 + MATCH_TINKER_PATTERN_DOWN;
1.1004 + else if (*match_direction == FIND_NEXT_MATCH_UP)
1.1005 + *match_direction =
1.1006 + MATCH_TINKER_PATTERN_UP;
1.1007 + /* else, do no change.. */
1.1008 +}
1.1009 +
1.1010 +struct match_state
1.1011 +{
1.1012 + int in_search;
1.1013 + match_f match_direction;
1.1014 + char pattern[256];
1.1015 +};
1.1016 +
1.1017 +/* Return 0 means I have handled the key. In such a case, ans should hold the
1.1018 + * item to center, or -1 otherwise.
1.1019 + * Else return -1 .
1.1020 + */
1.1021 +static int do_match(int key, struct match_state *state, int *ans)
1.1022 +{
1.1023 + char c = (char) key;
1.1024 + int terminate_search = 0;
1.1025 + *ans = -1;
1.1026 + if (key == '/' || (state->in_search && key == 27)) {
1.1027 + move(0, 0);
1.1028 + refresh();
1.1029 + clrtoeol();
1.1030 + state->in_search = 1-state->in_search;
1.1031 + bzero(state->pattern, sizeof(state->pattern));
1.1032 + state->match_direction = MATCH_TINKER_PATTERN_DOWN;
1.1033 + return 0;
1.1034 + } else if (!state->in_search)
1.1035 + return 1;
1.1036 +
1.1037 + if (isalnum(c) || isgraph(c) || c == ' ') {
1.1038 + state->pattern[strlen(state->pattern)] = c;
1.1039 + state->pattern[strlen(state->pattern)] = '\0';
1.1040 + adj_match_dir(&state->match_direction);
1.1041 + *ans = get_mext_match(state->pattern,
1.1042 + state->match_direction);
1.1043 + } else if (key == KEY_DOWN) {
1.1044 + state->match_direction = FIND_NEXT_MATCH_DOWN;
1.1045 + *ans = get_mext_match(state->pattern,
1.1046 + state->match_direction);
1.1047 + } else if (key == KEY_UP) {
1.1048 + state->match_direction = FIND_NEXT_MATCH_UP;
1.1049 + *ans = get_mext_match(state->pattern,
1.1050 + state->match_direction);
1.1051 + } else if (key == KEY_BACKSPACE || key == 127) {
1.1052 + state->pattern[strlen(state->pattern)-1] = '\0';
1.1053 + adj_match_dir(&state->match_direction);
1.1054 + } else
1.1055 + terminate_search = 1;
1.1056 +
1.1057 + if (terminate_search) {
1.1058 + state->in_search = 0;
1.1059 + bzero(state->pattern, sizeof(state->pattern));
1.1060 + move(0, 0);
1.1061 + refresh();
1.1062 + clrtoeol();
1.1063 + return -1;
1.1064 + }
1.1065 + return 0;
1.1066 +}
1.1067 +
1.1068 +static void conf(struct menu *menu)
1.1069 +{
1.1070 + struct menu *submenu = 0;
1.1071 + const char *prompt = menu_get_prompt(menu);
1.1072 + struct symbol *sym;
1.1073 + struct menu *active_menu = NULL;
1.1074 + int res;
1.1075 + int current_index = 0;
1.1076 + int last_top_row = 0;
1.1077 + struct match_state match_state = {
1.1078 + .in_search = 0,
1.1079 + .match_direction = MATCH_TINKER_PATTERN_DOWN,
1.1080 + .pattern = "",
1.1081 + };
1.1082 +
1.1083 + while (!global_exit) {
1.1084 + reset_menu();
1.1085 + current_menu = menu;
1.1086 + build_conf(menu);
1.1087 + if (!child_count)
1.1088 + break;
1.1089 +
1.1090 + show_menu(prompt ? _(prompt) : _("Main Menu"),
1.1091 + _(menu_instructions),
1.1092 + current_index, &last_top_row);
1.1093 + keypad((menu_win(curses_menu)), TRUE);
1.1094 + while (!global_exit) {
1.1095 + if (match_state.in_search) {
1.1096 + mvprintw(0, 0,
1.1097 + "searching: %s", match_state.pattern);
1.1098 + clrtoeol();
1.1099 + }
1.1100 + refresh_all_windows(main_window);
1.1101 + res = wgetch(menu_win(curses_menu));
1.1102 + if (!res)
1.1103 + break;
1.1104 + if (do_match(res, &match_state, ¤t_index) == 0) {
1.1105 + if (current_index != -1)
1.1106 + center_item(current_index,
1.1107 + &last_top_row);
1.1108 + continue;
1.1109 + }
1.1110 + if (process_special_keys(&res,
1.1111 + (struct menu *) item_data()))
1.1112 + break;
1.1113 + switch (res) {
1.1114 + case KEY_DOWN:
1.1115 + menu_driver(curses_menu, REQ_DOWN_ITEM);
1.1116 + break;
1.1117 + case KEY_UP:
1.1118 + menu_driver(curses_menu, REQ_UP_ITEM);
1.1119 + break;
1.1120 + case KEY_NPAGE:
1.1121 + menu_driver(curses_menu, REQ_SCR_DPAGE);
1.1122 + break;
1.1123 + case KEY_PPAGE:
1.1124 + menu_driver(curses_menu, REQ_SCR_UPAGE);
1.1125 + break;
1.1126 + case KEY_HOME:
1.1127 + menu_driver(curses_menu, REQ_FIRST_ITEM);
1.1128 + break;
1.1129 + case KEY_END:
1.1130 + menu_driver(curses_menu, REQ_LAST_ITEM);
1.1131 + break;
1.1132 + case 'h':
1.1133 + case '?':
1.1134 + show_help((struct menu *) item_data());
1.1135 + break;
1.1136 + }
1.1137 + if (res == 10 || res == 27 ||
1.1138 + res == 32 || res == 'n' || res == 'y' ||
1.1139 + res == KEY_LEFT || res == KEY_RIGHT ||
1.1140 + res == 'm')
1.1141 + break;
1.1142 + refresh_all_windows(main_window);
1.1143 + }
1.1144 +
1.1145 + refresh_all_windows(main_window);
1.1146 + /* if ESC or left*/
1.1147 + if (res == 27 || (menu != &rootmenu && res == KEY_LEFT))
1.1148 + break;
1.1149 +
1.1150 + /* remember location in the menu */
1.1151 + last_top_row = top_row(curses_menu);
1.1152 + current_index = curses_item_index();
1.1153 +
1.1154 + if (!item_tag())
1.1155 + continue;
1.1156 +
1.1157 + submenu = (struct menu *) item_data();
1.1158 + active_menu = (struct menu *)item_data();
1.1159 + if (!submenu || !menu_is_visible(submenu))
1.1160 + continue;
1.1161 + if (submenu)
1.1162 + sym = submenu->sym;
1.1163 + else
1.1164 + sym = NULL;
1.1165 +
1.1166 + switch (res) {
1.1167 + case ' ':
1.1168 + if (item_is_tag('t'))
1.1169 + sym_toggle_tristate_value(sym);
1.1170 + else if (item_is_tag('m'))
1.1171 + conf(submenu);
1.1172 + break;
1.1173 + case KEY_RIGHT:
1.1174 + case 10: /* ENTER WAS PRESSED */
1.1175 + switch (item_tag()) {
1.1176 + case 'm':
1.1177 + if (single_menu_mode)
1.1178 + submenu->data =
1.1179 + (void *) (long) !submenu->data;
1.1180 + else
1.1181 + conf(submenu);
1.1182 + break;
1.1183 + case 't':
1.1184 + if (sym_is_choice(sym) &&
1.1185 + sym_get_tristate_value(sym) == yes)
1.1186 + conf_choice(submenu);
1.1187 + else if (submenu->prompt &&
1.1188 + submenu->prompt->type == P_MENU)
1.1189 + conf(submenu);
1.1190 + else if (res == 10)
1.1191 + sym_toggle_tristate_value(sym);
1.1192 + break;
1.1193 + case 's':
1.1194 + conf_string(submenu);
1.1195 + break;
1.1196 + }
1.1197 + break;
1.1198 + case 'y':
1.1199 + if (item_is_tag('t')) {
1.1200 + if (sym_set_tristate_value(sym, yes))
1.1201 + break;
1.1202 + if (sym_set_tristate_value(sym, mod))
1.1203 + btn_dialog(main_window, setmod_text, 0);
1.1204 + }
1.1205 + break;
1.1206 + case 'n':
1.1207 + if (item_is_tag('t'))
1.1208 + sym_set_tristate_value(sym, no);
1.1209 + break;
1.1210 + case 'm':
1.1211 + if (item_is_tag('t'))
1.1212 + sym_set_tristate_value(sym, mod);
1.1213 + break;
1.1214 + }
1.1215 + }
1.1216 +}
1.1217 +
1.1218 +static void conf_message_callback(const char *fmt, va_list ap)
1.1219 +{
1.1220 + char buf[1024];
1.1221 +
1.1222 + vsnprintf(buf, sizeof(buf), fmt, ap);
1.1223 + btn_dialog(main_window, buf, 1, "<OK>");
1.1224 +}
1.1225 +
1.1226 +static void show_help(struct menu *menu)
1.1227 +{
1.1228 + struct gstr help = str_new();
1.1229 +
1.1230 + if (menu && menu->sym && menu_has_help(menu)) {
1.1231 + if (menu->sym->name) {
1.1232 + str_printf(&help, "%s%s:\n\n", CONFIG_, menu->sym->name);
1.1233 + str_append(&help, _(menu_get_help(menu)));
1.1234 + str_append(&help, "\n");
1.1235 + get_symbol_str(&help, menu->sym);
1.1236 + } else {
1.1237 + str_append(&help, _(menu_get_help(menu)));
1.1238 + }
1.1239 + } else {
1.1240 + str_append(&help, nohelp_text);
1.1241 + }
1.1242 + show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help));
1.1243 + str_free(&help);
1.1244 +}
1.1245 +
1.1246 +static void conf_choice(struct menu *menu)
1.1247 +{
1.1248 + const char *prompt = _(menu_get_prompt(menu));
1.1249 + struct menu *child = 0;
1.1250 + struct symbol *active;
1.1251 + int selected_index = 0;
1.1252 + int last_top_row = 0;
1.1253 + int res, i = 0;
1.1254 + struct match_state match_state = {
1.1255 + .in_search = 0,
1.1256 + .match_direction = MATCH_TINKER_PATTERN_DOWN,
1.1257 + .pattern = "",
1.1258 + };
1.1259 +
1.1260 + active = sym_get_choice_value(menu->sym);
1.1261 + /* this is mostly duplicated from the conf() function. */
1.1262 + while (!global_exit) {
1.1263 + reset_menu();
1.1264 +
1.1265 + for (i = 0, child = menu->list; child; child = child->next) {
1.1266 + if (!show_all_items && !menu_is_visible(child))
1.1267 + continue;
1.1268 +
1.1269 + if (child->sym == sym_get_choice_value(menu->sym))
1.1270 + item_make(child, ':', "<X> %s",
1.1271 + _(menu_get_prompt(child)));
1.1272 + else if (child->sym)
1.1273 + item_make(child, ':', " %s",
1.1274 + _(menu_get_prompt(child)));
1.1275 + else
1.1276 + item_make(child, ':', "*** %s ***",
1.1277 + _(menu_get_prompt(child)));
1.1278 +
1.1279 + if (child->sym == active){
1.1280 + last_top_row = top_row(curses_menu);
1.1281 + selected_index = i;
1.1282 + }
1.1283 + i++;
1.1284 + }
1.1285 + show_menu(prompt ? _(prompt) : _("Choice Menu"),
1.1286 + _(radiolist_instructions),
1.1287 + selected_index,
1.1288 + &last_top_row);
1.1289 + while (!global_exit) {
1.1290 + if (match_state.in_search) {
1.1291 + mvprintw(0, 0, "searching: %s",
1.1292 + match_state.pattern);
1.1293 + clrtoeol();
1.1294 + }
1.1295 + refresh_all_windows(main_window);
1.1296 + res = wgetch(menu_win(curses_menu));
1.1297 + if (!res)
1.1298 + break;
1.1299 + if (do_match(res, &match_state, &selected_index) == 0) {
1.1300 + if (selected_index != -1)
1.1301 + center_item(selected_index,
1.1302 + &last_top_row);
1.1303 + continue;
1.1304 + }
1.1305 + if (process_special_keys(
1.1306 + &res,
1.1307 + (struct menu *) item_data()))
1.1308 + break;
1.1309 + switch (res) {
1.1310 + case KEY_DOWN:
1.1311 + menu_driver(curses_menu, REQ_DOWN_ITEM);
1.1312 + break;
1.1313 + case KEY_UP:
1.1314 + menu_driver(curses_menu, REQ_UP_ITEM);
1.1315 + break;
1.1316 + case KEY_NPAGE:
1.1317 + menu_driver(curses_menu, REQ_SCR_DPAGE);
1.1318 + break;
1.1319 + case KEY_PPAGE:
1.1320 + menu_driver(curses_menu, REQ_SCR_UPAGE);
1.1321 + break;
1.1322 + case KEY_HOME:
1.1323 + menu_driver(curses_menu, REQ_FIRST_ITEM);
1.1324 + break;
1.1325 + case KEY_END:
1.1326 + menu_driver(curses_menu, REQ_LAST_ITEM);
1.1327 + break;
1.1328 + case 'h':
1.1329 + case '?':
1.1330 + show_help((struct menu *) item_data());
1.1331 + break;
1.1332 + }
1.1333 + if (res == 10 || res == 27 || res == ' ' ||
1.1334 + res == KEY_LEFT){
1.1335 + break;
1.1336 + }
1.1337 + refresh_all_windows(main_window);
1.1338 + }
1.1339 + /* if ESC or left */
1.1340 + if (res == 27 || res == KEY_LEFT)
1.1341 + break;
1.1342 +
1.1343 + child = item_data();
1.1344 + if (!child || !menu_is_visible(child) || !child->sym)
1.1345 + continue;
1.1346 + switch (res) {
1.1347 + case ' ':
1.1348 + case 10:
1.1349 + case KEY_RIGHT:
1.1350 + sym_set_tristate_value(child->sym, yes);
1.1351 + return;
1.1352 + case 'h':
1.1353 + case '?':
1.1354 + show_help(child);
1.1355 + active = child->sym;
1.1356 + break;
1.1357 + case KEY_EXIT:
1.1358 + return;
1.1359 + }
1.1360 + }
1.1361 +}
1.1362 +
1.1363 +static void conf_string(struct menu *menu)
1.1364 +{
1.1365 + const char *prompt = menu_get_prompt(menu);
1.1366 + char dialog_input_result[256];
1.1367 +
1.1368 + while (1) {
1.1369 + int res;
1.1370 + const char *heading;
1.1371 +
1.1372 + switch (sym_get_type(menu->sym)) {
1.1373 + case S_INT:
1.1374 + heading = _(inputbox_instructions_int);
1.1375 + break;
1.1376 + case S_HEX:
1.1377 + heading = _(inputbox_instructions_hex);
1.1378 + break;
1.1379 + case S_STRING:
1.1380 + heading = _(inputbox_instructions_string);
1.1381 + break;
1.1382 + default:
1.1383 + heading = _("Internal nconf error!");
1.1384 + }
1.1385 + res = dialog_inputbox(main_window,
1.1386 + prompt ? _(prompt) : _("Main Menu"),
1.1387 + heading,
1.1388 + sym_get_string_value(menu->sym),
1.1389 + dialog_input_result,
1.1390 + sizeof(dialog_input_result));
1.1391 + switch (res) {
1.1392 + case 0:
1.1393 + if (sym_set_string_value(menu->sym,
1.1394 + dialog_input_result))
1.1395 + return;
1.1396 + btn_dialog(main_window,
1.1397 + _("You have made an invalid entry."), 0);
1.1398 + break;
1.1399 + case 1:
1.1400 + show_help(menu);
1.1401 + break;
1.1402 + case KEY_EXIT:
1.1403 + return;
1.1404 + }
1.1405 + }
1.1406 +}
1.1407 +
1.1408 +static void conf_load(void)
1.1409 +{
1.1410 + char dialog_input_result[256];
1.1411 + while (1) {
1.1412 + int res;
1.1413 + res = dialog_inputbox(main_window,
1.1414 + NULL, load_config_text,
1.1415 + filename,
1.1416 + dialog_input_result,
1.1417 + sizeof(dialog_input_result));
1.1418 + switch (res) {
1.1419 + case 0:
1.1420 + if (!dialog_input_result[0])
1.1421 + return;
1.1422 + if (!conf_read(dialog_input_result)) {
1.1423 + set_config_filename(dialog_input_result);
1.1424 + sym_set_change_count(1);
1.1425 + return;
1.1426 + }
1.1427 + btn_dialog(main_window, _("File does not exist!"), 0);
1.1428 + break;
1.1429 + case 1:
1.1430 + show_scroll_win(main_window,
1.1431 + _("Load Alternate Configuration"),
1.1432 + load_config_help);
1.1433 + break;
1.1434 + case KEY_EXIT:
1.1435 + return;
1.1436 + }
1.1437 + }
1.1438 +}
1.1439 +
1.1440 +static void conf_save(void)
1.1441 +{
1.1442 + char dialog_input_result[256];
1.1443 + while (1) {
1.1444 + int res;
1.1445 + res = dialog_inputbox(main_window,
1.1446 + NULL, save_config_text,
1.1447 + filename,
1.1448 + dialog_input_result,
1.1449 + sizeof(dialog_input_result));
1.1450 + switch (res) {
1.1451 + case 0:
1.1452 + if (!dialog_input_result[0])
1.1453 + return;
1.1454 + res = conf_write(dialog_input_result);
1.1455 + if (!res) {
1.1456 + set_config_filename(dialog_input_result);
1.1457 + return;
1.1458 + }
1.1459 + btn_dialog(main_window, _("Can't create file! "
1.1460 + "Probably a nonexistent directory."),
1.1461 + 1, "<OK>");
1.1462 + break;
1.1463 + case 1:
1.1464 + show_scroll_win(main_window,
1.1465 + _("Save Alternate Configuration"),
1.1466 + save_config_help);
1.1467 + break;
1.1468 + case KEY_EXIT:
1.1469 + return;
1.1470 + }
1.1471 + }
1.1472 +}
1.1473 +
1.1474 +void setup_windows(void)
1.1475 +{
1.1476 + if (main_window != NULL)
1.1477 + delwin(main_window);
1.1478 +
1.1479 + /* set up the menu and menu window */
1.1480 + main_window = newwin(LINES-2, COLS-2, 2, 1);
1.1481 + keypad(main_window, TRUE);
1.1482 + mwin_max_lines = LINES-7;
1.1483 + mwin_max_cols = COLS-6;
1.1484 +
1.1485 + /* panels order is from bottom to top */
1.1486 + new_panel(main_window);
1.1487 +}
1.1488 +
1.1489 +int main(int ac, char **av)
1.1490 +{
1.1491 + char *mode;
1.1492 +
1.1493 + setlocale(LC_ALL, "");
1.1494 + bindtextdomain(PACKAGE, LOCALEDIR);
1.1495 + textdomain(PACKAGE);
1.1496 +
1.1497 + conf_parse(av[1]);
1.1498 + conf_read(NULL);
1.1499 +
1.1500 + mode = getenv("NCONFIG_MODE");
1.1501 + if (mode) {
1.1502 + if (!strcasecmp(mode, "single_menu"))
1.1503 + single_menu_mode = 1;
1.1504 + }
1.1505 +
1.1506 + /* Initialize curses */
1.1507 + initscr();
1.1508 + /* set color theme */
1.1509 + set_colors();
1.1510 +
1.1511 + cbreak();
1.1512 + noecho();
1.1513 + keypad(stdscr, TRUE);
1.1514 + curs_set(0);
1.1515 +
1.1516 + if (COLS < 75 || LINES < 20) {
1.1517 + endwin();
1.1518 + printf("Your terminal should have at "
1.1519 + "least 20 lines and 75 columns\n");
1.1520 + return 1;
1.1521 + }
1.1522 +
1.1523 + notimeout(stdscr, FALSE);
1.1524 + ESCDELAY = 1;
1.1525 +
1.1526 + /* set btns menu */
1.1527 + curses_menu = new_menu(curses_menu_items);
1.1528 + menu_opts_off(curses_menu, O_SHOWDESC);
1.1529 + menu_opts_on(curses_menu, O_SHOWMATCH);
1.1530 + menu_opts_on(curses_menu, O_ONEVALUE);
1.1531 + menu_opts_on(curses_menu, O_NONCYCLIC);
1.1532 + menu_opts_on(curses_menu, O_IGNORECASE);
1.1533 + set_menu_mark(curses_menu, " ");
1.1534 + set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]);
1.1535 + set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]);
1.1536 + set_menu_grey(curses_menu, attributes[MAIN_MENU_GREY]);
1.1537 +
1.1538 + set_config_filename(conf_get_configname());
1.1539 + setup_windows();
1.1540 +
1.1541 + /* check for KEY_FUNC(1) */
1.1542 + if (has_key(KEY_F(1)) == FALSE) {
1.1543 + show_scroll_win(main_window,
1.1544 + _("Instructions"),
1.1545 + _(menu_no_f_instructions));
1.1546 + }
1.1547 +
1.1548 + conf_set_message_callback(conf_message_callback);
1.1549 + /* do the work */
1.1550 + while (!global_exit) {
1.1551 + conf(&rootmenu);
1.1552 + if (!global_exit && do_exit() == 0)
1.1553 + break;
1.1554 + }
1.1555 + /* ok, we are done */
1.1556 + unpost_menu(curses_menu);
1.1557 + free_menu(curses_menu);
1.1558 + delwin(main_window);
1.1559 + clear();
1.1560 + refresh();
1.1561 + endwin();
1.1562 + return 0;
1.1563 +}
1.1564 +