diff options
Diffstat (limited to 'scripts/kconfig/nconf.c')
| -rw-r--r-- | scripts/kconfig/nconf.c | 858 |
1 files changed, 422 insertions, 436 deletions
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c index 2ba71bcd38e..984489ef2b4 100644 --- a/scripts/kconfig/nconf.c +++ b/scripts/kconfig/nconf.c @@ -5,214 +5,210 @@ * Derived from menuconfig. * */ -#define LKC_DIRECT_LINK +#define _GNU_SOURCE +#include <string.h> +#include <stdlib.h> + #include "lkc.h" #include "nconf.h" +#include <ctype.h> -static const char nconf_readme[] = N_( -"Overview\n" -"--------\n" -"Some kernel features may be built directly into the kernel.\n" -"Some may be made into loadable runtime modules. Some features\n" -"may be completely removed altogether. There are also certain\n" -"kernel parameters which are not really features, but must be\n" -"entered in as decimal or hexadecimal numbers or possibly text.\n" -"\n" -"Menu items beginning with following braces represent features that\n" -" [ ] can be built in or removed\n" -" < > can be built in, modularized or removed\n" -" { } can be built in or modularized (selected by other feature)\n" -" - - are selected by other feature,\n" -" XXX cannot be selected. use Symbol Info to find out why,\n" -"while *, M or whitespace inside braces means to build in, build as\n" -"a module or to exclude the feature respectively.\n" +static const char nconf_global_help[] = N_( +"Help windows\n" +"------------\n" +"o Global help: Unless in a data entry window, pressing <F1> will give \n" +" you the global help window, which you are just reading.\n" "\n" -"To change any of these features, highlight it with the cursor\n" -"keys and press <Y> to build it in, <M> to make it a module or\n" -"<N> to removed it. You may also press the <Space Bar> to cycle\n" -"through the available options (ie. Y->N->M->Y).\n" +"o A short version of the global help is available by pressing <F3>.\n" "\n" -"Some additional keyboard hints:\n" -"\n" -"Menus\n" -"----------\n" -"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n" -" you wish to change use <Enter> or <Space>. Goto submenu by \n" -" pressing <Enter> of <right-arrow>. Use <Esc> or <left-arrow> to go back.\n" -" Submenus are designated by \"--->\".\n" +"o Local help: To get help related to the current menu entry, use any\n" +" of <?> <h>, or if in a data entry window then press <F1>.\n" "\n" -" Shortcut: Press the option's highlighted letter (hotkey).\n" -" Pressing a hotkey more than once will sequence\n" -" through all visible items which use that hotkey.\n" "\n" -" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n" -" unseen options into view.\n" +"Menu entries\n" +"------------\n" +"This interface lets you select features and parameters for the kernel\n" +"build. Kernel features can either be built-in, modularized, or removed.\n" +"Parameters must be entered as text or decimal or hexadecimal numbers.\n" "\n" -"o To exit a menu use the just press <ESC> <F5> <F8> or <left-arrow>.\n" +"Menu entries beginning with following braces represent features that\n" +" [ ] can be built in or removed\n" +" < > can be built in, modularized or removed\n" +" { } can be built in or modularized, are selected by another feature\n" +" - - are selected by another feature\n" +" XXX cannot be selected. Symbol Info <F2> tells you why.\n" +"*, M or whitespace inside braces means to build in, build as a module\n" +"or to exclude the feature respectively.\n" "\n" -"o To get help with an item, press <F1>\n" -" Shortcut: Press <h> or <?>.\n" +"To change any of these features, highlight it with the movement keys\n" +"listed below and press <y> to build it in, <m> to make it a module or\n" +"<n> to remove it. You may press the <Space> key to cycle through the\n" +"available options.\n" "\n" +"A trailing \"--->\" designates a submenu, a trailing \"----\" an\n" +"empty submenu.\n" "\n" -"Radiolists (Choice lists)\n" -"-----------\n" -"o Use the cursor keys to select the option you wish to set and press\n" -" <S> or the <SPACE BAR>.\n" +"Menu navigation keys\n" +"----------------------------------------------------------------------\n" +"Linewise up <Up>\n" +"Linewise down <Down>\n" +"Pagewise up <Page Up>\n" +"Pagewise down <Page Down>\n" +"First entry <Home>\n" +"Last entry <End>\n" +"Enter a submenu <Right> <Enter>\n" +"Go back to parent menu <Left> <Esc> <F5>\n" +"Close a help window <Enter> <Esc> <F5>\n" +"Close entry window, apply <Enter>\n" +"Close entry window, forget <Esc> <F5>\n" +"Start incremental, case-insensitive search for STRING in menu entries,\n" +" no regex support, STRING is displayed in upper left corner\n" +" </>STRING\n" +" Remove last character <Backspace>\n" +" Jump to next hit <Down>\n" +" Jump to previous hit <Up>\n" +"Exit menu search mode </> <Esc>\n" +"Search for configuration variables with or without leading CONFIG_\n" +" <F8>RegExpr<Enter>\n" +"Verbose search help <F8><F1>\n" +"----------------------------------------------------------------------\n" "\n" -" Shortcut: Press the first letter of the option you wish to set then\n" -" press <S> or <SPACE BAR>.\n" +"Unless in a data entry window, key <1> may be used instead of <F1>,\n" +"<2> instead of <F2>, etc.\n" "\n" -"o To see available help for the item, press <F1>\n" -" Shortcut: Press <H> or <?>.\n" "\n" +"Radiolist (Choice list)\n" +"-----------------------\n" +"Use the movement keys listed above to select the option you wish to set\n" +"and press <Space>.\n" "\n" -"Data Entry\n" -"-----------\n" -"o Enter the requested information and press <ENTER>\n" -" If you are entering hexadecimal values, it is not necessary to\n" -" add the '0x' prefix to the entry.\n" "\n" -"o For help, press <F1>.\n" +"Data entry\n" +"----------\n" +"Enter the requested information and press <Enter>. Hexadecimal values\n" +"may be entered without the \"0x\" prefix.\n" "\n" "\n" -"Text Box (Help Window)\n" -"--------\n" -"o Use the cursor keys to scroll up/down/left/right. The VI editor\n" -" keys h,j,k,l function here as do <SPACE BAR> for those\n" -" who are familiar with less and lynx.\n" +"Text Box (Help Window)\n" +"----------------------\n" +"Use movement keys as listed in table above.\n" "\n" -"o Press <Enter>, <F1>, <F5>, <F7> or <Esc> to exit.\n" +"Press any of <Enter> <Esc> <q> <F5> <F9> to exit.\n" "\n" "\n" -"Alternate Configuration Files\n" +"Alternate configuration files\n" "-----------------------------\n" -"nconfig supports the use of alternate configuration files for\n" -"those who, for various reasons, find it necessary to switch\n" -"between different kernel configurations.\n" +"nconfig supports switching between different configurations.\n" +"Press <F6> to save your current configuration. Press <F7> and enter\n" +"a file name to load a previously saved configuration.\n" "\n" -"At the end of the main menu you will find two options. One is\n" -"for saving the current configuration to a file of your choosing.\n" -"The other option is for loading a previously saved alternate\n" -"configuration.\n" "\n" -"Even if you don't use alternate configuration files, but you\n" -"find during a nconfig session that you have completely messed\n" -"up your settings, you may use the \"Load Alternate...\" option to\n" -"restore your previously saved settings from \".config\" without\n" -"restarting nconfig.\n" +"Terminal configuration\n" +"----------------------\n" +"If you use nconfig in a xterm window, make sure your TERM environment\n" +"variable specifies a terminal configuration which supports at least\n" +"16 colors. Otherwise nconfig will look rather bad.\n" "\n" -"Other information\n" -"-----------------\n" -"If you use nconfig in an XTERM window make sure you have your\n" -"$TERM variable set to point to a xterm definition which supports color.\n" -"Otherwise, nconfig will look rather bad. nconfig will not\n" -"display correctly in a RXVT window because rxvt displays only one\n" -"intensity of color, bright.\n" +"If the \"stty size\" command reports the current terminalsize correctly,\n" +"nconfig will adapt to sizes larger than the traditional 80x25 \"standard\"\n" +"and display longer menus properly.\n" "\n" -"nconfig will display larger menus on screens or xterms which are\n" -"set to display more than the standard 25 row by 80 column geometry.\n" -"In order for this to work, the \"stty size\" command must be able to\n" -"display the screen's current row and column geometry. I STRONGLY\n" -"RECOMMEND that you make sure you do NOT have the shell variables\n" -"LINES and COLUMNS exported into your environment. Some distributions\n" -"export those variables via /etc/profile. Some ncurses programs can\n" -"become confused when those variables (LINES & COLUMNS) don't reflect\n" -"the true screen size.\n" "\n" -"Optional personality available\n" -"------------------------------\n" -"If you prefer to have all of the kernel options listed in a single\n" -"menu, rather than the default multimenu hierarchy, run the nconfig\n" -"with NCONFIG_MODE environment variable set to single_menu. Example:\n" +"Single menu mode\n" +"----------------\n" +"If you prefer to have all of the menu entries listed in a single menu,\n" +"rather than the default multimenu hierarchy, run nconfig with\n" +"NCONFIG_MODE environment variable set to single_menu. Example:\n" "\n" "make NCONFIG_MODE=single_menu nconfig\n" "\n" -"<Enter> will then unroll the appropriate category, or enfold it if it\n" -"is already unrolled.\n" +"<Enter> will then unfold the appropriate category, or fold it if it\n" +"is already unfolded. Folded menu entries will be designated by a\n" +"leading \"++>\" and unfolded entries by a leading \"-->\".\n" "\n" -"Note that this mode can eventually be a little more CPU expensive\n" -"(especially with a larger number of unrolled categories) than the\n" -"default mode.\n" +"Note that this mode can eventually be a little more CPU expensive than\n" +"the default mode, especially with a larger number of unfolded submenus.\n" "\n"), menu_no_f_instructions[] = N_( -" You do not have function keys support. Please follow the\n" -" following instructions:\n" -" Arrow keys navigate the menu.\n" -" <Enter> or <right-arrow> selects submenus --->.\n" -" Capital Letters are hotkeys.\n" -" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n" -" Pressing SpaceBar toggles between the above options\n" -" Press <Esc> or <left-arrow> to go back one menu, \n" -" <?> or <h> for Help, </> for Search.\n" -" <1> is interchangable with <F1>, <2> with <F2>, etc.\n" -" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n" -" <Esc> always leaves the current window\n"), +"Legend: [*] built-in [ ] excluded <M> module < > module capable.\n" +"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n" +"\n" +"Use the following keys to navigate the menus:\n" +"Move up or down with <Up> and <Down>.\n" +"Enter a submenu with <Enter> or <Right>.\n" +"Exit a submenu to its parent menu with <Esc> or <Left>.\n" +"Pressing <y> includes, <n> excludes, <m> modularizes features.\n" +"Pressing <Space> cycles through the available options.\n" +"To search for menu entries press </>.\n" +"<Esc> always leaves the current window.\n" +"\n" +"You do not have function keys support.\n" +"Press <1> instead of <F1>, <2> instead of <F2>, etc.\n" +"For verbose global help use key <1>.\n" +"For help related to the current menu entry press <?> or <h>.\n"), menu_instructions[] = N_( -" Arrow keys navigate the menu.\n" -" <Enter> or <right-arrow> selects submenus --->.\n" -" Capital Letters are hotkeys.\n" -" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n" -" Pressing SpaceBar toggles between the above options\n" -" Press <Esc>, <F3> or <left-arrow> to go back one menu, \n" -" <?>, <F1> or <h> for Help, </> for Search.\n" -" <1> is interchangable with <F1>, <2> with <F2>, etc.\n" -" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n" -" <Esc> always leaves the current window\n"), +"Legend: [*] built-in [ ] excluded <M> module < > module capable.\n" +"Submenus are designated by a trailing \"--->\", empty ones by \"----\".\n" +"\n" +"Use the following keys to navigate the menus:\n" +"Move up or down with <Up> or <Down>.\n" +"Enter a submenu with <Enter> or <Right>.\n" +"Exit a submenu to its parent menu with <Esc> or <Left>.\n" +"Pressing <y> includes, <n> excludes, <m> modularizes features.\n" +"Pressing <Space> cycles through the available options.\n" +"To search for menu entries press </>.\n" +"<Esc> always leaves the current window.\n" +"\n" +"Pressing <1> may be used instead of <F1>, <2> instead of <F2>, etc.\n" +"For verbose global help press <F1>.\n" +"For help related to the current menu entry press <?> or <h>.\n"), radiolist_instructions[] = N_( -" Use the arrow keys to navigate this window or\n" -" press the hotkey of the item you wish to select\n" -" followed by the <SPACE BAR>.\n" -" Press <?>, <F1> or <h> for additional information about this option.\n"), +"Press <Up>, <Down>, <Home> or <End> to navigate a radiolist, select\n" +"with <Space>.\n" +"For help related to the current entry press <?> or <h>.\n" +"For global help press <F1>.\n"), inputbox_instructions_int[] = N_( "Please enter a decimal value.\n" "Fractions will not be accepted.\n" -"Press <RETURN> to accept, <ESC> to cancel."), +"Press <Enter> to apply, <Esc> to cancel."), inputbox_instructions_hex[] = N_( "Please enter a hexadecimal value.\n" -"Press <RETURN> to accept, <ESC> to cancel."), +"Press <Enter> to apply, <Esc> to cancel."), inputbox_instructions_string[] = N_( "Please enter a string value.\n" -"Press <RETURN> to accept, <ESC> to cancel."), +"Press <Enter> to apply, <Esc> to cancel."), setmod_text[] = N_( -"This feature depends on another which\n" -"has been configured as a module.\n" -"As a result, this feature will be built as a module."), -nohelp_text[] = N_( -"There is no help available for this kernel option.\n"), +"This feature depends on another feature which has been configured as a\n" +"module. As a result, the current feature will be built as a module too."), load_config_text[] = N_( "Enter the name of the configuration file you wish to load.\n" -"Accept the name shown to restore the configuration you\n" -"last retrieved. Leave blank to abort."), +"Accept the name shown to restore the configuration you last\n" +"retrieved. Leave empty to abort."), load_config_help[] = N_( -"\n" -"For various reasons, one may wish to keep several different kernel\n" +"For various reasons, one may wish to keep several different\n" "configurations available on a single machine.\n" "\n" "If you have saved a previous configuration in a file other than the\n" -"kernel's default, entering the name of the file here will allow you\n" -"to modify that configuration.\n" +"default one, entering its name here will allow you to load and modify\n" +"that configuration.\n" "\n" -"If you are uncertain, then you have probably never used alternate\n" -"configuration files. You should therefor leave this blank to abort.\n"), +"Leave empty to abort.\n"), save_config_text[] = N_( "Enter a filename to which this configuration should be saved\n" -"as an alternate. Leave blank to abort."), +"as an alternate. Leave empty to abort."), save_config_help[] = N_( -"\n" -"For various reasons, one may wish to keep different kernel\n" +"For various reasons, one may wish to keep several different\n" "configurations available on a single machine.\n" "\n" "Entering a file name here will allow you to later retrieve, modify\n" "and use the current configuration as an alternate to whatever\n" "configuration options you have selected at that time.\n" "\n" -"If you are uncertain what all this means then you should probably\n" -"leave this blank.\n"), +"Leave empty to abort.\n"), search_help[] = N_( -"\n" -"Search for CONFIG_ symbols and display their relations.\n" -"Regular expressions are allowed.\n" -"Example: search for \"^FOO\"\n" +"Search for symbols (configuration variable names CONFIG_*) and display\n" +"their relations. Regular expressions are supported.\n" +"Example: Search for \"^FOO\".\n" "Result:\n" "-----------------------------------------------------------------\n" "Symbol: FOO [ = m]\n" @@ -220,39 +216,38 @@ search_help[] = N_( "Defined at drivers/pci/Kconfig:47\n" "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" "Location:\n" -" -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n" +" -> Bus options (PCI, PCMCIA, EISA, ISA)\n" " -> PCI support (PCI [ = y])\n" " -> PCI access mode (<choice> [ = y])\n" "Selects: LIBCRC32\n" "Selected by: BAR\n" "-----------------------------------------------------------------\n" -"o The line 'Prompt:' shows the text used in the menu structure for\n" -" this CONFIG_ symbol\n" -"o The 'Defined at' line tell at what file / line number the symbol\n" -" is defined\n" -"o The 'Depends on:' line tell what symbols needs to be defined for\n" -" this symbol to be visible in the menu (selectable)\n" -"o The 'Location:' lines tell where in the menu structure this symbol\n" -" is located\n" -" A location followed by a [ = y] indicate that this is a selectable\n" -" menu item - and current value is displayed inside brackets.\n" -"o The 'Selects:' line tell what symbol will be automatically\n" -" selected if this symbol is selected (y or m)\n" -"o The 'Selected by' line tell what symbol has selected this symbol\n" +"o The line 'Prompt:' shows the text displayed for this symbol in\n" +" the menu hierarchy.\n" +"o The 'Defined at' line tells at what file / line number the symbol is\n" +" defined.\n" +"o The 'Depends on:' line lists symbols that need to be defined for\n" +" this symbol to be visible and selectable in the menu.\n" +"o The 'Location:' lines tell, where in the menu structure this symbol\n" +" is located. A location followed by a [ = y] indicates that this is\n" +" a selectable menu item, and the current value is displayed inside\n" +" brackets.\n" +"o The 'Selects:' line tells, what symbol will be automatically selected\n" +" if this symbol is selected (y or m).\n" +"o The 'Selected by' line tells what symbol has selected this symbol.\n" "\n" "Only relevant lines are shown.\n" "\n\n" "Search examples:\n" -"Examples: USB = > find all CONFIG_ symbols containing USB\n" -" ^USB => find all CONFIG_ symbols starting with USB\n" -" USB$ => find all CONFIG_ symbols ending with USB\n" +"USB => find all symbols containing USB\n" +"^USB => find all symbols starting with USB\n" +"USB$ => find all symbols ending with USB\n" "\n"); struct mitem { char str[256]; char tag; void *usrptr; - int is_hot; int is_visible; }; @@ -275,14 +270,9 @@ static int items_num; static int global_exit; /* the currently selected button */ const char *current_instructions = menu_instructions; -/* this array is used to implement hot keys. it is updated in item_make and - * resetted in clean_items. It would be better to use a hash, but lets keep it - * simple... */ -#define MAX_SAME_KEY MAX_MENU_ITEMS -struct { - int count; - int ptrs[MAX_MENU_ITEMS]; -} hotkeys[1<<(sizeof(char)*8)]; + +static char *dialog_input_result; +static int dialog_input_result_len; static void conf(struct menu *menu); static void conf_choice(struct menu *menu); @@ -292,6 +282,7 @@ static void conf_save(void); static void show_help(struct menu *menu); static int do_exit(void); static void setup_windows(void); +static void search_conf(void); typedef void (*function_key_handler_t)(int *key, struct menu *menu); static void handle_f1(int *key, struct menu *current_item); @@ -302,6 +293,7 @@ static void handle_f5(int *key, struct menu *current_item); static void handle_f6(int *key, struct menu *current_item); static void handle_f7(int *key, struct menu *current_item); static void handle_f8(int *key, struct menu *current_item); +static void handle_f9(int *key, struct menu *current_item); struct function_keys { const char *key_str; @@ -310,7 +302,7 @@ struct function_keys { function_key_handler_t handler; }; -static const int function_keys_num = 8; +static const int function_keys_num = 9; struct function_keys function_keys[] = { { .key_str = "F1", @@ -320,19 +312,19 @@ struct function_keys function_keys[] = { }, { .key_str = "F2", - .func = "Symbol Info", + .func = "SymInfo", .key = F_SYMBOL, .handler = handle_f2, }, { .key_str = "F3", - .func = "Instructions", + .func = "Help 2", .key = F_INSTS, .handler = handle_f3, }, { .key_str = "F4", - .func = "Config", + .func = "ShowAll", .key = F_CONF, .handler = handle_f4, }, @@ -356,9 +348,15 @@ struct function_keys function_keys[] = { }, { .key_str = "F8", + .func = "SymSearch", + .key = F_SEARCH, + .handler = handle_f8, + }, + { + .key_str = "F9", .func = "Exit", .key = F_EXIT, - .handler = handle_f8, + .handler = handle_f9, }, }; @@ -367,27 +365,28 @@ static void print_function_line(void) int i; int offset = 1; const int skip = 1; + int lines = getmaxy(stdscr); for (i = 0; i < function_keys_num; i++) { - wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]); - mvwprintw(main_window, LINES-3, offset, + (void) wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]); + mvwprintw(main_window, lines-3, offset, "%s", function_keys[i].key_str); - wattrset(main_window, attributes[FUNCTION_TEXT]); + (void) wattrset(main_window, attributes[FUNCTION_TEXT]); offset += strlen(function_keys[i].key_str); - mvwprintw(main_window, LINES-3, + mvwprintw(main_window, lines-3, offset, "%s", function_keys[i].func); offset += strlen(function_keys[i].func) + skip; } - wattrset(main_window, attributes[NORMAL]); + (void) wattrset(main_window, attributes[NORMAL]); } /* help */ static void handle_f1(int *key, struct menu *current_item) { show_scroll_win(main_window, - _("README"), _(nconf_readme)); + _("Global help"), _(nconf_global_help)); return; } @@ -402,7 +401,7 @@ static void handle_f2(int *key, struct menu *current_item) static void handle_f3(int *key, struct menu *current_item) { show_scroll_win(main_window, - _("Instructions"), + _("Short help"), _(current_instructions)); return; } @@ -444,9 +443,16 @@ static void handle_f7(int *key, struct menu *current_item) return; } -/* exit */ +/* search */ static void handle_f8(int *key, struct menu *current_item) { + search_conf(); + return; +} + +/* exit */ +static void handle_f9(int *key, struct menu *current_item) +{ do_exit(); return; } @@ -479,110 +485,44 @@ static void clean_items(void) free_item(curses_menu_items[i]); bzero(curses_menu_items, sizeof(curses_menu_items)); bzero(k_menu_items, sizeof(k_menu_items)); - bzero(hotkeys, sizeof(hotkeys)); items_num = 0; } -/* return the index of the next hot item, or -1 if no such item exists */ -static int get_next_hot(int c) -{ - static int hot_index; - static int hot_char; - - if (c < 0 || c > 255 || hotkeys[c].count <= 0) - return -1; - - if (hot_char == c) { - hot_index = (hot_index+1)%hotkeys[c].count; - return hotkeys[c].ptrs[hot_index]; - } else { - hot_char = c; - hot_index = 0; - return hotkeys[c].ptrs[0]; - } -} - -/* can the char c be a hot key? no, if c is a common shortcut used elsewhere */ -static int canbhot(char c) -{ - c = tolower(c); - return isalnum(c) && c != 'y' && c != 'm' && c != 'h' && - c != 'n' && c != '?'; -} - -/* check if str already contains a hot key. */ -static int is_hot(int index) -{ - return k_menu_items[index].is_hot; -} +typedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN, + FIND_NEXT_MATCH_DOWN, FIND_NEXT_MATCH_UP} match_f; -/* find the first possible hot key, and mark it. - * index is the index of the item in the menu - * return 0 on success*/ -static int make_hot(char *dest, int len, const char *org, int index) +/* return the index of the matched item, or -1 if no such item exists */ +static int get_mext_match(const char *match_str, match_f flag) { - int position = -1; - int i; - int tmp; - int c; - int org_len = strlen(org); - - if (org == NULL || is_hot(index)) - return 1; - - /* make sure not to make hot keys out of markers. - * find where to start looking for a hot key - */ - i = 0; - /* skip white space */ - while (i < org_len && org[i] == ' ') - i++; - if (i == org_len) - return -1; - /* if encountering '(' or '<' or '[', find the match and look from there - **/ - if (org[i] == '[' || org[i] == '<' || org[i] == '(') { - i++; - for (; i < org_len; i++) - if (org[i] == ']' || org[i] == '>' || org[i] == ')') - break; - } - if (i == org_len) - return -1; - for (; i < org_len; i++) { - if (canbhot(org[i]) && org[i-1] != '<' && org[i-1] != '(') { - position = i; - break; - } + int match_start = item_index(current_item(curses_menu)); + int index; + + if (flag == FIND_NEXT_MATCH_DOWN) + ++match_start; + else if (flag == FIND_NEXT_MATCH_UP) + --match_start; + + index = match_start; + index = (index + items_num) % items_num; + while (true) { + char *str = k_menu_items[index].str; + if (strcasestr(str, match_str) != 0) + return index; + if (flag == FIND_NEXT_MATCH_UP || + flag == MATCH_TINKER_PATTERN_UP) + --index; + else + ++index; + index = (index + items_num) % items_num; + if (index == match_start) + return -1; } - if (position == -1) - return 1; - - /* ok, char at org[position] should be a hot key to this item */ - c = tolower(org[position]); - tmp = hotkeys[c].count; - hotkeys[c].ptrs[tmp] = index; - hotkeys[c].count++; - /* - snprintf(dest, len, "%.*s(%c)%s", position, org, org[position], - &org[position+1]); - */ - /* make org[position] uppercase, and all leading letter small case */ - strncpy(dest, org, len); - for (i = 0; i < position; i++) - dest[i] = tolower(dest[i]); - dest[position] = toupper(dest[position]); - k_menu_items[index].is_hot = 1; - return 0; } -/* Make a new item. Add a hotkey mark in the first possible letter. - * As ncurses does not allow any attributes inside menue item, we mark the - * hot key as the first capitalized letter in the string */ +/* Make a new item. */ static void item_make(struct menu *menu, char tag, const char *fmt, ...) { va_list ap; - char tmp_str[256]; if (items_num > MAX_MENU_ITEMS-1) return; @@ -597,16 +537,13 @@ static void item_make(struct menu *menu, char tag, const char *fmt, ...) k_menu_items[items_num].is_visible = 1; va_start(ap, fmt); - vsnprintf(tmp_str, sizeof(tmp_str), fmt, ap); - if (!k_menu_items[items_num].is_visible) - memcpy(tmp_str, "XXX", 3); + vsnprintf(k_menu_items[items_num].str, + sizeof(k_menu_items[items_num].str), + fmt, ap); va_end(ap); - if (make_hot( - k_menu_items[items_num].str, - sizeof(k_menu_items[items_num].str), tmp_str, items_num) != 0) - strncpy(k_menu_items[items_num].str, - tmp_str, - sizeof(k_menu_items[items_num].str)); + + if (!k_menu_items[items_num].is_visible) + memcpy(k_menu_items[items_num].str, "XXX", 3); curses_menu_items[items_num] = new_item( k_menu_items[items_num].str, @@ -638,11 +575,9 @@ static void item_add_str(const char *fmt, ...) va_end(ap); snprintf(tmp_str, sizeof(tmp_str), "%s%s", k_menu_items[index].str, new_str); - if (make_hot(k_menu_items[index].str, - sizeof(k_menu_items[index].str), tmp_str, index) != 0) - strncpy(k_menu_items[index].str, - tmp_str, - sizeof(k_menu_items[index].str)); + strncpy(k_menu_items[index].str, + tmp_str, + sizeof(k_menu_items[index].str)); free_item(curses_menu_items[index]); curses_menu_items[index] = new_item( @@ -693,13 +628,9 @@ static char menu_backtitle[PATH_MAX+128]; static const char *set_config_filename(const char *config_filename) { int size; - struct symbol *sym; - sym = sym_lookup("KERNELVERSION", 0); - sym_calc_value(sym); size = snprintf(menu_backtitle, sizeof(menu_backtitle), - _("%s - Linux Kernel v%s Configuration"), - config_filename, sym_get_string_value(sym)); + "%s - %s", config_filename, rootmenu.prompt->text); if (size >= sizeof(menu_backtitle)) menu_backtitle[sizeof(menu_backtitle)-1] = '\0'; @@ -709,25 +640,6 @@ static const char *set_config_filename(const char *config_filename) return menu_backtitle; } -/* command = 0 is supress, 1 is restore */ -static void supress_stdout(int command) -{ - static FILE *org_stdout; - static FILE *org_stderr; - - if (command == 0) { - org_stdout = stdout; - org_stderr = stderr; - stdout = fopen("/dev/null", "a"); - stderr = fopen("/dev/null", "a"); - } else { - fclose(stdout); - fclose(stderr); - stdout = org_stdout; - stderr = org_stderr; - } -} - /* return = 0 means we are successful. * -1 means go on doing what you were doing */ @@ -739,8 +651,7 @@ static int do_exit(void) return 0; } res = btn_dialog(main_window, - _("Do you wish to save your " - "new kernel configuration?\n" + _("Do you wish to save your new configuration?\n" "<ESC> to cancel and resume nconfig."), 2, " <save> ", @@ -753,36 +664,19 @@ static int do_exit(void) /* if we got here, the user really wants to exit */ switch (res) { case 0: - supress_stdout(0); res = conf_write(filename); - supress_stdout(1); if (res) btn_dialog( main_window, - _("Error during writing of the kernel " - "configuration.\n" - "Your kernel configuration " - "changes were NOT saved."), + _("Error during writing of configuration.\n" + "Your configuration changes were NOT saved."), 1, "<OK>"); - else { - char buf[1024]; - snprintf(buf, 1024, - _("Configuration written to %s\n" - "End of Linux kernel configuration.\n" - "Execute 'make' to build the kernel or try" - " 'make help'."), filename); - btn_dialog( - main_window, - buf, - 1, - "<OK>"); - } break; default: btn_dialog( main_window, - _("Your kernel configuration changes were NOT saved."), + _("Your configuration changes were NOT saved."), 1, "<OK>"); break; @@ -796,15 +690,19 @@ static void search_conf(void) { struct symbol **sym_arr; struct gstr res; - char dialog_input_result[100]; + struct gstr title; char *dialog_input; int dres; + + title = str_new(); + str_printf( &title, _("Enter (sub)string or regexp to search for " + "(with or without \"%s\")"), CONFIG_); + again: dres = dialog_inputbox(main_window, _("Search Configuration Parameter"), - _("Enter CONFIG_ (sub)string to search for " - "(with or without \"CONFIG\")"), - "", dialog_input_result, 99); + str_get(&title), + "", &dialog_input_result, &dialog_input_result_len); switch (dres) { case 0: break; @@ -813,20 +711,22 @@ again: _("Search Configuration"), search_help); goto again; default: + str_free(&title); return; } - /* strip CONFIG_ if necessary */ + /* strip the prefix if necessary */ dialog_input = dialog_input_result; - if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0) - dialog_input += 7; + if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0) + dialog_input += strlen(CONFIG_); sym_arr = sym_re_search(dialog_input); - res = get_relations_str(sym_arr); + res = get_relations_str(sym_arr, NULL); free(sym_arr); show_scroll_win(main_window, _("Search Results"), str_get(&res)); str_free(&res); + str_free(&title); } @@ -860,9 +760,9 @@ static void build_conf(struct menu *menu) indent + 1, ' ', prompt); } else item_make(menu, 'm', - " %*c%s --->", - indent + 1, - ' ', prompt); + " %*c%s %s", + indent + 1, ' ', prompt, + menu_is_empty(menu) ? "----" : "--->"); if (single_menu_mode && menu->data) goto conf_childs; @@ -1004,7 +904,7 @@ static void build_conf(struct menu *menu) (sym_has_value(sym) || !sym_is_changable(sym)) ? "" : _(" (NEW)")); if (menu->prompt && menu->prompt->type == P_MENU) { - item_add_str(" --->"); + item_add_str(" %s", menu_is_empty(menu) ? "----" : "--->"); return; } } @@ -1027,23 +927,18 @@ static void reset_menu(void) static void center_item(int selected_index, int *last_top_row) { int toprow; - int maxy, maxx; - scale_menu(curses_menu, &maxy, &maxx); set_top_row(curses_menu, *last_top_row); toprow = top_row(curses_menu); - if (selected_index >= toprow && selected_index < toprow+maxy) { - /* we can only move the selected item. no need to scroll */ - set_current_item(curses_menu, - curses_menu_items[selected_index]); - } else { - toprow = max(selected_index-maxy/2, 0); - if (toprow >= item_count(curses_menu)-maxy) + if (selected_index < toprow || + selected_index >= toprow+mwin_max_lines) { + toprow = max(selected_index-mwin_max_lines/2, 0); + if (toprow >= item_count(curses_menu)-mwin_max_lines) toprow = item_count(curses_menu)-mwin_max_lines; set_top_row(curses_menu, toprow); - set_current_item(curses_menu, - curses_menu_items[selected_index]); } + set_current_item(curses_menu, + curses_menu_items[selected_index]); *last_top_row = toprow; post_menu(curses_menu); refresh_all_windows(main_window); @@ -1059,23 +954,23 @@ static void show_menu(const char *prompt, const char *instructions, current_instructions = instructions; clear(); - wattrset(main_window, attributes[NORMAL]); - print_in_middle(stdscr, 1, 0, COLS, + (void) wattrset(main_window, attributes[NORMAL]); + print_in_middle(stdscr, 1, 0, getmaxx(stdscr), menu_backtitle, attributes[MAIN_HEADING]); - wattrset(main_window, attributes[MAIN_MENU_BOX]); + (void) wattrset(main_window, attributes[MAIN_MENU_BOX]); box(main_window, 0, 0); - wattrset(main_window, attributes[MAIN_MENU_HEADING]); + (void) wattrset(main_window, attributes[MAIN_MENU_HEADING]); mvwprintw(main_window, 0, 3, " %s ", prompt); - wattrset(main_window, attributes[NORMAL]); + (void) wattrset(main_window, attributes[NORMAL]); set_menu_items(curses_menu, curses_menu_items); /* position the menu at the middle of the screen */ scale_menu(curses_menu, &maxy, &maxx); maxx = min(maxx, mwin_max_cols-2); - maxy = mwin_max_lines-2; + maxy = mwin_max_lines; menu_window = derwin(main_window, maxy, maxx, @@ -1099,19 +994,88 @@ static void show_menu(const char *prompt, const char *instructions, refresh_all_windows(main_window); } +static void adj_match_dir(match_f *match_direction) +{ + if (*match_direction == FIND_NEXT_MATCH_DOWN) + *match_direction = + MATCH_TINKER_PATTERN_DOWN; + else if (*match_direction == FIND_NEXT_MATCH_UP) + *match_direction = + MATCH_TINKER_PATTERN_UP; + /* else, do no change.. */ +} -static void conf(struct menu *menu) +struct match_state { + int in_search; + match_f match_direction; char pattern[256]; +}; + +/* Return 0 means I have handled the key. In such a case, ans should hold the + * item to center, or -1 otherwise. + * Else return -1 . + */ +static int do_match(int key, struct match_state *state, int *ans) +{ + char c = (char) key; + int terminate_search = 0; + *ans = -1; + if (key == '/' || (state->in_search && key == 27)) { + move(0, 0); + refresh(); + clrtoeol(); + state->in_search = 1-state->in_search; + bzero(state->pattern, sizeof(state->pattern)); + state->match_direction = MATCH_TINKER_PATTERN_DOWN; + return 0; + } else if (!state->in_search) + return 1; + + if (isalnum(c) || isgraph(c) || c == ' ') { + state->pattern[strlen(state->pattern)] = c; + state->pattern[strlen(state->pattern)] = '\0'; + adj_match_dir(&state->match_direction); + *ans = get_mext_match(state->pattern, + state->match_direction); + } else if (key == KEY_DOWN) { + state->match_direction = FIND_NEXT_MATCH_DOWN; + *ans = get_mext_match(state->pattern, + state->match_direction); + } else if (key == KEY_UP) { + state->match_direction = FIND_NEXT_MATCH_UP; + *ans = get_mext_match(state->pattern, + state->match_direction); + } else if (key == KEY_BACKSPACE || key == 127) { + state->pattern[strlen(state->pattern)-1] = '\0'; + adj_match_dir(&state->match_direction); + } else + terminate_search = 1; + + if (terminate_search) { + state->in_search = 0; + bzero(state->pattern, sizeof(state->pattern)); + move(0, 0); + refresh(); + clrtoeol(); + return -1; + } + return 0; +} + +static void conf(struct menu *menu) +{ struct menu *submenu = 0; const char *prompt = menu_get_prompt(menu); struct symbol *sym; - struct menu *active_menu = NULL; int res; int current_index = 0; int last_top_row = 0; - - bzero(pattern, sizeof(pattern)); + struct match_state match_state = { + .in_search = 0, + .match_direction = MATCH_TINKER_PATTERN_DOWN, + .pattern = "", + }; while (!global_exit) { reset_menu(); @@ -1124,7 +1088,22 @@ static void conf(struct menu *menu) _(menu_instructions), current_index, &last_top_row); keypad((menu_win(curses_menu)), TRUE); - while (!global_exit && (res = wgetch(menu_win(curses_menu)))) { + while (!global_exit) { + if (match_state.in_search) { + mvprintw(0, 0, + "searching: %s", match_state.pattern); + clrtoeol(); + } + refresh_all_windows(main_window); + res = wgetch(menu_win(curses_menu)); + if (!res) + break; + if (do_match(res, &match_state, ¤t_index) == 0) { + if (current_index != -1) + center_item(current_index, + &last_top_row); + continue; + } if (process_special_keys(&res, (struct menu *) item_data())) break; @@ -1155,19 +1134,13 @@ static void conf(struct menu *menu) if (res == 10 || res == 27 || res == 32 || res == 'n' || res == 'y' || res == KEY_LEFT || res == KEY_RIGHT || - res == 'm' || res == '/') + res == 'm') break; - else if (canbhot(res)) { - /* check for hot keys: */ - int tmp = get_next_hot(res); - if (tmp != -1) - center_item(tmp, &last_top_row); - } refresh_all_windows(main_window); } refresh_all_windows(main_window); - /* if ESC or left*/ + /* if ESC or left*/ if (res == 27 || (menu != &rootmenu && res == KEY_LEFT)) break; @@ -1179,13 +1152,9 @@ static void conf(struct menu *menu) continue; submenu = (struct menu *) item_data(); - active_menu = (struct menu *)item_data(); if (!submenu || !menu_is_visible(submenu)) continue; - if (submenu) - sym = submenu->sym; - else - sym = NULL; + sym = submenu->sym; switch (res) { case ' ': @@ -1235,27 +1204,27 @@ static void conf(struct menu *menu) if (item_is_tag('t')) sym_set_tristate_value(sym, mod); break; - case '/': - search_conf(); - break; } } } +static void conf_message_callback(const char *fmt, va_list ap) +{ + char buf[1024]; + + vsnprintf(buf, sizeof(buf), fmt, ap); + btn_dialog(main_window, buf, 1, "<OK>"); +} + static void show_help(struct menu *menu) { - struct gstr help = str_new(); - - if (menu && menu->sym && menu_has_help(menu)) { - if (menu->sym->name) { - str_printf(&help, "CONFIG_%s:\n\n", menu->sym->name); - str_append(&help, _(menu_get_help(menu))); - str_append(&help, "\n"); - get_symbol_str(&help, menu->sym); - } - } else { - str_append(&help, nohelp_text); - } + struct gstr help; + + if (!menu) + return; + + help = str_new(); + menu_get_ext_help(menu, &help); show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help)); str_free(&help); } @@ -1268,6 +1237,11 @@ static void conf_choice(struct menu *menu) int selected_index = 0; int last_top_row = 0; int res, i = 0; + struct match_state match_state = { + .in_search = 0, + .match_direction = MATCH_TINKER_PATTERN_DOWN, + .pattern = "", + }; active = sym_get_choice_value(menu->sym); /* this is mostly duplicated from the conf() function. */ @@ -1281,9 +1255,13 @@ static void conf_choice(struct menu *menu) if (child->sym == sym_get_choice_value(menu->sym)) item_make(child, ':', "<X> %s", _(menu_get_prompt(child))); - else + else if (child->sym) item_make(child, ':', " %s", _(menu_get_prompt(child))); + else + item_make(child, ':', "*** %s ***", + _(menu_get_prompt(child))); + if (child->sym == active){ last_top_row = top_row(curses_menu); selected_index = i; @@ -1294,7 +1272,22 @@ static void conf_choice(struct menu *menu) _(radiolist_instructions), selected_index, &last_top_row); - while (!global_exit && (res = wgetch(menu_win(curses_menu)))) { + while (!global_exit) { + if (match_state.in_search) { + mvprintw(0, 0, "searching: %s", + match_state.pattern); + clrtoeol(); + } + refresh_all_windows(main_window); + res = wgetch(menu_win(curses_menu)); + if (!res) + break; + if (do_match(res, &match_state, &selected_index) == 0) { + if (selected_index != -1) + center_item(selected_index, + &last_top_row); + continue; + } if (process_special_keys( &res, (struct menu *) item_data())) @@ -1324,13 +1317,8 @@ static void conf_choice(struct menu *menu) break; } if (res == 10 || res == 27 || res == ' ' || - res == KEY_LEFT) + res == KEY_LEFT){ break; - else if (canbhot(res)) { - /* check for hot keys: */ - int tmp = get_next_hot(res); - if (tmp != -1) - center_item(tmp, &last_top_row); } refresh_all_windows(main_window); } @@ -1339,7 +1327,7 @@ static void conf_choice(struct menu *menu) break; child = item_data(); - if (!child || !menu_is_visible(child)) + if (!child || !menu_is_visible(child) || !child->sym) continue; switch (res) { case ' ': @@ -1361,7 +1349,6 @@ static void conf_choice(struct menu *menu) static void conf_string(struct menu *menu) { const char *prompt = menu_get_prompt(menu); - char dialog_input_result[256]; while (1) { int res; @@ -1384,8 +1371,8 @@ static void conf_string(struct menu *menu) prompt ? _(prompt) : _("Main Menu"), heading, sym_get_string_value(menu->sym), - dialog_input_result, - sizeof(dialog_input_result)); + &dialog_input_result, + &dialog_input_result_len); switch (res) { case 0: if (sym_set_string_value(menu->sym, @@ -1405,14 +1392,13 @@ static void conf_string(struct menu *menu) static void conf_load(void) { - char dialog_input_result[256]; while (1) { int res; res = dialog_inputbox(main_window, NULL, load_config_text, filename, - dialog_input_result, - sizeof(dialog_input_result)); + &dialog_input_result, + &dialog_input_result_len); switch (res) { case 0: if (!dialog_input_result[0]) @@ -1437,28 +1423,19 @@ static void conf_load(void) static void conf_save(void) { - char dialog_input_result[256]; while (1) { int res; res = dialog_inputbox(main_window, NULL, save_config_text, filename, - dialog_input_result, - sizeof(dialog_input_result)); + &dialog_input_result, + &dialog_input_result_len); switch (res) { case 0: if (!dialog_input_result[0]) return; - supress_stdout(0); res = conf_write(dialog_input_result); - supress_stdout(1); if (!res) { - char buf[1024]; - sprintf(buf, "%s %s", - _("configuration file saved to: "), - dialog_input_result); - btn_dialog(main_window, - buf, 1, "<OK>"); set_config_filename(dialog_input_result); return; } @@ -1479,14 +1456,18 @@ static void conf_save(void) void setup_windows(void) { + int lines, columns; + + getmaxyx(stdscr, lines, columns); + if (main_window != NULL) delwin(main_window); /* set up the menu and menu window */ - main_window = newwin(LINES-2, COLS-2, 2, 1); + main_window = newwin(lines-2, columns-2, 2, 1); keypad(main_window, TRUE); - mwin_max_lines = LINES-6; - mwin_max_cols = COLS-6; + mwin_max_lines = lines-7; + mwin_max_cols = columns-6; /* panels order is from bottom to top */ new_panel(main_window); @@ -1494,6 +1475,7 @@ void setup_windows(void) int main(int ac, char **av) { + int lines, columns; char *mode; setlocale(LC_ALL, ""); @@ -1519,7 +1501,8 @@ int main(int ac, char **av) keypad(stdscr, TRUE); curs_set(0); - if (COLS < 75 || LINES < 20) { + getmaxyx(stdscr, lines, columns); + if (columns < 75 || lines < 20) { endwin(); printf("Your terminal should have at " "least 20 lines and 75 columns\n"); @@ -1527,14 +1510,19 @@ int main(int ac, char **av) } notimeout(stdscr, FALSE); +#if NCURSES_REENTRANT + set_escdelay(1); +#else ESCDELAY = 1; +#endif /* set btns menu */ curses_menu = new_menu(curses_menu_items); menu_opts_off(curses_menu, O_SHOWDESC); - menu_opts_off(curses_menu, O_SHOWMATCH); + menu_opts_on(curses_menu, O_SHOWMATCH); menu_opts_on(curses_menu, O_ONEVALUE); menu_opts_on(curses_menu, O_NONCYCLIC); + menu_opts_on(curses_menu, O_IGNORECASE); set_menu_mark(curses_menu, " "); set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]); set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]); @@ -1550,8 +1538,7 @@ int main(int ac, char **av) _(menu_no_f_instructions)); } - - + conf_set_message_callback(conf_message_callback); /* do the work */ while (!global_exit) { conf(&rootmenu); @@ -1567,4 +1554,3 @@ int main(int ac, char **av) endwin(); return 0; } - |
