Annotation of qemu/roms/seabios/tools/kconfig/nconf.c, revision 1.1.1.1

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, &current_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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.