Annotation of qemu/roms/seabios/tools/kconfig/nconf.c, revision 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.