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