aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/kconfig/nconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/kconfig/nconf.c')
-rw-r--r--scripts/kconfig/nconf.c489
1 files changed, 239 insertions, 250 deletions
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
index 762caf80ce37..272a987f23e0 100644
--- a/scripts/kconfig/nconf.c
+++ b/scripts/kconfig/nconf.c
@@ -5,25 +5,26 @@
5 * Derived from menuconfig. 5 * Derived from menuconfig.
6 * 6 *
7 */ 7 */
8#define _GNU_SOURCE
9#include <string.h>
8#define LKC_DIRECT_LINK 10#define LKC_DIRECT_LINK
9#include "lkc.h" 11#include "lkc.h"
10#include "nconf.h" 12#include "nconf.h"
13#include <ctype.h>
11 14
12static const char nconf_readme[] = N_( 15static const char nconf_readme[] = N_(
13"Overview\n" 16"Overview\n"
14"--------\n" 17"--------\n"
15"Some kernel features may be built directly into the kernel.\n" 18"This interface let you select features and parameters for the build.\n"
16"Some may be made into loadable runtime modules. Some features\n" 19"Features can either be built-in, modularized, or ignored. Parameters\n"
17"may be completely removed altogether. There are also certain\n" 20"must be entered in as decimal or hexadecimal numbers or text.\n"
18"kernel parameters which are not really features, but must be\n"
19"entered in as decimal or hexadecimal numbers or possibly text.\n"
20"\n" 21"\n"
21"Menu items beginning with following braces represent features that\n" 22"Menu items beginning with following braces represent features that\n"
22" [ ] can be built in or removed\n" 23" [ ] can be built in or removed\n"
23" < > can be built in, modularized or removed\n" 24" < > can be built in, modularized or removed\n"
24" { } can be built in or modularized (selected by other feature)\n" 25" { } can be built in or modularized (selected by other feature)\n"
25" - - are selected by other feature,\n" 26" - - are selected by other feature,\n"
26" XXX cannot be selected. use Symbol Info to find out why,\n" 27" XXX cannot be selected. Use Symbol Info to find out why,\n"
27"while *, M or whitespace inside braces means to build in, build as\n" 28"while *, M or whitespace inside braces means to build in, build as\n"
28"a module or to exclude the feature respectively.\n" 29"a module or to exclude the feature respectively.\n"
29"\n" 30"\n"
@@ -41,9 +42,13 @@ static const char nconf_readme[] = N_(
41" pressing <Enter> of <right-arrow>. Use <Esc> or <left-arrow> to go back.\n" 42" pressing <Enter> of <right-arrow>. Use <Esc> or <left-arrow> to go back.\n"
42" Submenus are designated by \"--->\".\n" 43" Submenus are designated by \"--->\".\n"
43"\n" 44"\n"
44" Shortcut: Press the option's highlighted letter (hotkey).\n" 45" Searching: pressing '/' triggers interactive search mode.\n"
45" Pressing a hotkey more than once will sequence\n" 46" nconfig performs a case insensitive search for the string\n"
46" through all visible items which use that hotkey.\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"
47"\n" 52"\n"
48" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n" 53" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
49" unseen options into view.\n" 54" unseen options into view.\n"
@@ -88,7 +93,7 @@ static const char nconf_readme[] = N_(
88"-----------------------------\n" 93"-----------------------------\n"
89"nconfig supports the use of alternate configuration files for\n" 94"nconfig supports the use of alternate configuration files for\n"
90"those who, for various reasons, find it necessary to switch\n" 95"those who, for various reasons, find it necessary to switch\n"
91"between different kernel configurations.\n" 96"between different configurations.\n"
92"\n" 97"\n"
93"At the end of the main menu you will find two options. One is\n" 98"At the end of the main menu you will find two options. One is\n"
94"for saving the current configuration to a file of your choosing.\n" 99"for saving the current configuration to a file of your choosing.\n"
@@ -121,9 +126,9 @@ static const char nconf_readme[] = N_(
121"\n" 126"\n"
122"Optional personality available\n" 127"Optional personality available\n"
123"------------------------------\n" 128"------------------------------\n"
124"If you prefer to have all of the kernel options listed in a single\n" 129"If you prefer to have all of the options listed in a single menu, rather\n"
125"menu, rather than the default multimenu hierarchy, run the nconfig\n" 130"than the default multimenu hierarchy, run the nconfig with NCONFIG_MODE\n"
126"with NCONFIG_MODE environment variable set to single_menu. Example:\n" 131"environment variable set to single_menu. Example:\n"
127"\n" 132"\n"
128"make NCONFIG_MODE=single_menu nconfig\n" 133"make NCONFIG_MODE=single_menu nconfig\n"
129"\n" 134"\n"
@@ -141,21 +146,21 @@ menu_no_f_instructions[] = N_(
141" <Enter> or <right-arrow> selects submenus --->.\n" 146" <Enter> or <right-arrow> selects submenus --->.\n"
142" Capital Letters are hotkeys.\n" 147" Capital Letters are hotkeys.\n"
143" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n" 148" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
144" Pressing SpaceBar toggles between the above options\n" 149" Pressing SpaceBar toggles between the above options.\n"
145" Press <Esc> or <left-arrow> to go back one menu, \n" 150" Press <Esc> or <left-arrow> to go back one menu,\n"
146" <?> or <h> for Help, </> for Search.\n" 151" <?> or <h> for Help, </> for Search.\n"
147" <1> is interchangable with <F1>, <2> with <F2>, etc.\n" 152" <1> is interchangeable with <F1>, <2> with <F2>, etc.\n"
148" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n" 153" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
149" <Esc> always leaves the current window\n"), 154" <Esc> always leaves the current window.\n"),
150menu_instructions[] = N_( 155menu_instructions[] = N_(
151" Arrow keys navigate the menu.\n" 156" Arrow keys navigate the menu.\n"
152" <Enter> or <right-arrow> selects submenus --->.\n" 157" <Enter> or <right-arrow> selects submenus --->.\n"
153" Capital Letters are hotkeys.\n" 158" Capital Letters are hotkeys.\n"
154" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n" 159" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
155" Pressing SpaceBar toggles between the above options\n" 160" Pressing SpaceBar toggles between the above options\n"
156" Press <Esc>, <F3> or <left-arrow> to go back one menu, \n" 161" Press <Esc>, <F5> or <left-arrow> to go back one menu,\n"
157" <?>, <F1> or <h> for Help, </> for Search.\n" 162" <?>, <F1> or <h> for Help, </> for Search.\n"
158" <1> is interchangable with <F1>, <2> with <F2>, etc.\n" 163" <1> is interchangeable with <F1>, <2> with <F2>, etc.\n"
159" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n" 164" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
160" <Esc> always leaves the current window\n"), 165" <Esc> always leaves the current window\n"),
161radiolist_instructions[] = N_( 166radiolist_instructions[] = N_(
@@ -178,19 +183,19 @@ setmod_text[] = N_(
178"has been configured as a module.\n" 183"has been configured as a module.\n"
179"As a result, this feature will be built as a module."), 184"As a result, this feature will be built as a module."),
180nohelp_text[] = N_( 185nohelp_text[] = N_(
181"There is no help available for this kernel option.\n"), 186"There is no help available for this option.\n"),
182load_config_text[] = N_( 187load_config_text[] = N_(
183"Enter the name of the configuration file you wish to load.\n" 188"Enter the name of the configuration file you wish to load.\n"
184"Accept the name shown to restore the configuration you\n" 189"Accept the name shown to restore the configuration you\n"
185"last retrieved. Leave blank to abort."), 190"last retrieved. Leave blank to abort."),
186load_config_help[] = N_( 191load_config_help[] = N_(
187"\n" 192"\n"
188"For various reasons, one may wish to keep several different kernel\n" 193"For various reasons, one may wish to keep several different\n"
189"configurations available on a single machine.\n" 194"configurations available on a single machine.\n"
190"\n" 195"\n"
191"If you have saved a previous configuration in a file other than the\n" 196"If you have saved a previous configuration in a file other than the\n"
192"kernel's default, entering the name of the file here will allow you\n" 197"default one, entering its name here will allow you to modify that\n"
193"to modify that configuration.\n" 198"configuration.\n"
194"\n" 199"\n"
195"If you are uncertain, then you have probably never used alternate\n" 200"If you are uncertain, then you have probably never used alternate\n"
196"configuration files. You should therefor leave this blank to abort.\n"), 201"configuration files. You should therefor leave this blank to abort.\n"),
@@ -199,8 +204,8 @@ save_config_text[] = N_(
199"as an alternate. Leave blank to abort."), 204"as an alternate. Leave blank to abort."),
200save_config_help[] = N_( 205save_config_help[] = N_(
201"\n" 206"\n"
202"For various reasons, one may wish to keep different kernel\n" 207"For various reasons, one may wish to keep different configurations\n"
203"configurations available on a single machine.\n" 208"available on a single machine.\n"
204"\n" 209"\n"
205"Entering a file name here will allow you to later retrieve, modify\n" 210"Entering a file name here will allow you to later retrieve, modify\n"
206"and use the current configuration as an alternate to whatever\n" 211"and use the current configuration as an alternate to whatever\n"
@@ -210,8 +215,8 @@ save_config_help[] = N_(
210"leave this blank.\n"), 215"leave this blank.\n"),
211search_help[] = N_( 216search_help[] = N_(
212"\n" 217"\n"
213"Search for CONFIG_ symbols and display their relations.\n" 218"Search for symbols and display their relations. Regular expressions\n"
214"Regular expressions are allowed.\n" 219"are allowed.\n"
215"Example: search for \"^FOO\"\n" 220"Example: search for \"^FOO\"\n"
216"Result:\n" 221"Result:\n"
217"-----------------------------------------------------------------\n" 222"-----------------------------------------------------------------\n"
@@ -227,7 +232,7 @@ search_help[] = N_(
227"Selected by: BAR\n" 232"Selected by: BAR\n"
228"-----------------------------------------------------------------\n" 233"-----------------------------------------------------------------\n"
229"o The line 'Prompt:' shows the text used in the menu structure for\n" 234"o The line 'Prompt:' shows the text used in the menu structure for\n"
230" this CONFIG_ symbol\n" 235" this symbol\n"
231"o The 'Defined at' line tell at what file / line number the symbol\n" 236"o The 'Defined at' line tell at what file / line number the symbol\n"
232" is defined\n" 237" is defined\n"
233"o The 'Depends on:' line tell what symbols needs to be defined for\n" 238"o The 'Depends on:' line tell what symbols needs to be defined for\n"
@@ -243,16 +248,15 @@ search_help[] = N_(
243"Only relevant lines are shown.\n" 248"Only relevant lines are shown.\n"
244"\n\n" 249"\n\n"
245"Search examples:\n" 250"Search examples:\n"
246"Examples: USB = > find all CONFIG_ symbols containing USB\n" 251"Examples: USB = > find all symbols containing USB\n"
247" ^USB => find all CONFIG_ symbols starting with USB\n" 252" ^USB => find all symbols starting with USB\n"
248" USB$ => find all CONFIG_ symbols ending with USB\n" 253" USB$ => find all symbols ending with USB\n"
249"\n"); 254"\n");
250 255
251struct mitem { 256struct mitem {
252 char str[256]; 257 char str[256];
253 char tag; 258 char tag;
254 void *usrptr; 259 void *usrptr;
255 int is_hot;
256 int is_visible; 260 int is_visible;
257}; 261};
258 262
@@ -275,14 +279,6 @@ static int items_num;
275static int global_exit; 279static int global_exit;
276/* the currently selected button */ 280/* the currently selected button */
277const char *current_instructions = menu_instructions; 281const char *current_instructions = menu_instructions;
278/* this array is used to implement hot keys. it is updated in item_make and
279 * resetted in clean_items. It would be better to use a hash, but lets keep it
280 * simple... */
281#define MAX_SAME_KEY MAX_MENU_ITEMS
282struct {
283 int count;
284 int ptrs[MAX_MENU_ITEMS];
285} hotkeys[1<<(sizeof(char)*8)];
286 282
287static void conf(struct menu *menu); 283static void conf(struct menu *menu);
288static void conf_choice(struct menu *menu); 284static void conf_choice(struct menu *menu);
@@ -292,6 +288,7 @@ static void conf_save(void);
292static void show_help(struct menu *menu); 288static void show_help(struct menu *menu);
293static int do_exit(void); 289static int do_exit(void);
294static void setup_windows(void); 290static void setup_windows(void);
291static void search_conf(void);
295 292
296typedef void (*function_key_handler_t)(int *key, struct menu *menu); 293typedef void (*function_key_handler_t)(int *key, struct menu *menu);
297static void handle_f1(int *key, struct menu *current_item); 294static void handle_f1(int *key, struct menu *current_item);
@@ -302,6 +299,7 @@ static void handle_f5(int *key, struct menu *current_item);
302static void handle_f6(int *key, struct menu *current_item); 299static void handle_f6(int *key, struct menu *current_item);
303static void handle_f7(int *key, struct menu *current_item); 300static void handle_f7(int *key, struct menu *current_item);
304static void handle_f8(int *key, struct menu *current_item); 301static void handle_f8(int *key, struct menu *current_item);
302static void handle_f9(int *key, struct menu *current_item);
305 303
306struct function_keys { 304struct function_keys {
307 const char *key_str; 305 const char *key_str;
@@ -310,7 +308,7 @@ struct function_keys {
310 function_key_handler_t handler; 308 function_key_handler_t handler;
311}; 309};
312 310
313static const int function_keys_num = 8; 311static const int function_keys_num = 9;
314struct function_keys function_keys[] = { 312struct function_keys function_keys[] = {
315 { 313 {
316 .key_str = "F1", 314 .key_str = "F1",
@@ -320,13 +318,13 @@ struct function_keys function_keys[] = {
320 }, 318 },
321 { 319 {
322 .key_str = "F2", 320 .key_str = "F2",
323 .func = "Symbol Info", 321 .func = "Sym Info",
324 .key = F_SYMBOL, 322 .key = F_SYMBOL,
325 .handler = handle_f2, 323 .handler = handle_f2,
326 }, 324 },
327 { 325 {
328 .key_str = "F3", 326 .key_str = "F3",
329 .func = "Instructions", 327 .func = "Insts",
330 .key = F_INSTS, 328 .key = F_INSTS,
331 .handler = handle_f3, 329 .handler = handle_f3,
332 }, 330 },
@@ -356,9 +354,15 @@ struct function_keys function_keys[] = {
356 }, 354 },
357 { 355 {
358 .key_str = "F8", 356 .key_str = "F8",
357 .func = "Sym Search",
358 .key = F_SEARCH,
359 .handler = handle_f8,
360 },
361 {
362 .key_str = "F9",
359 .func = "Exit", 363 .func = "Exit",
360 .key = F_EXIT, 364 .key = F_EXIT,
361 .handler = handle_f8, 365 .handler = handle_f9,
362 }, 366 },
363}; 367};
364 368
@@ -444,9 +448,16 @@ static void handle_f7(int *key, struct menu *current_item)
444 return; 448 return;
445} 449}
446 450
447/* exit */ 451/* search */
448static void handle_f8(int *key, struct menu *current_item) 452static void handle_f8(int *key, struct menu *current_item)
449{ 453{
454 search_conf();
455 return;
456}
457
458/* exit */
459static void handle_f9(int *key, struct menu *current_item)
460{
450 do_exit(); 461 do_exit();
451 return; 462 return;
452} 463}
@@ -479,110 +490,44 @@ static void clean_items(void)
479 free_item(curses_menu_items[i]); 490 free_item(curses_menu_items[i]);
480 bzero(curses_menu_items, sizeof(curses_menu_items)); 491 bzero(curses_menu_items, sizeof(curses_menu_items));
481 bzero(k_menu_items, sizeof(k_menu_items)); 492 bzero(k_menu_items, sizeof(k_menu_items));
482 bzero(hotkeys, sizeof(hotkeys));
483 items_num = 0; 493 items_num = 0;
484} 494}
485 495
486/* return the index of the next hot item, or -1 if no such item exists */ 496typedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN,
487static int get_next_hot(int c) 497 FIND_NEXT_MATCH_DOWN, FIND_NEXT_MATCH_UP} match_f;
488{
489 static int hot_index;
490 static int hot_char;
491
492 if (c < 0 || c > 255 || hotkeys[c].count <= 0)
493 return -1;
494
495 if (hot_char == c) {
496 hot_index = (hot_index+1)%hotkeys[c].count;
497 return hotkeys[c].ptrs[hot_index];
498 } else {
499 hot_char = c;
500 hot_index = 0;
501 return hotkeys[c].ptrs[0];
502 }
503}
504
505/* can the char c be a hot key? no, if c is a common shortcut used elsewhere */
506static int canbhot(char c)
507{
508 c = tolower(c);
509 return isalnum(c) && c != 'y' && c != 'm' && c != 'h' &&
510 c != 'n' && c != '?';
511}
512
513/* check if str already contains a hot key. */
514static int is_hot(int index)
515{
516 return k_menu_items[index].is_hot;
517}
518 498
519/* find the first possible hot key, and mark it. 499/* return the index of the matched item, or -1 if no such item exists */
520 * index is the index of the item in the menu 500static int get_mext_match(const char *match_str, match_f flag)
521 * return 0 on success*/
522static int make_hot(char *dest, int len, const char *org, int index)
523{ 501{
524 int position = -1; 502 int match_start = item_index(current_item(curses_menu));
525 int i; 503 int index;
526 int tmp; 504
527 int c; 505 if (flag == FIND_NEXT_MATCH_DOWN)
528 int org_len = strlen(org); 506 ++match_start;
529 507 else if (flag == FIND_NEXT_MATCH_UP)
530 if (org == NULL || is_hot(index)) 508 --match_start;
531 return 1; 509
532 510 index = match_start;
533 /* make sure not to make hot keys out of markers. 511 index = (index + items_num) % items_num;
534 * find where to start looking for a hot key 512 while (true) {
535 */ 513 char *str = k_menu_items[index].str;
536 i = 0; 514 if (strcasestr(str, match_str) != 0)
537 /* skip white space */ 515 return index;
538 while (i < org_len && org[i] == ' ') 516 if (flag == FIND_NEXT_MATCH_UP ||
539 i++; 517 flag == MATCH_TINKER_PATTERN_UP)
540 if (i == org_len) 518 --index;
541 return -1; 519 else
542 /* if encountering '(' or '<' or '[', find the match and look from there 520 ++index;
543 **/ 521 index = (index + items_num) % items_num;
544 if (org[i] == '[' || org[i] == '<' || org[i] == '(') { 522 if (index == match_start)
545 i++; 523 return -1;
546 for (; i < org_len; i++)
547 if (org[i] == ']' || org[i] == '>' || org[i] == ')')
548 break;
549 }
550 if (i == org_len)
551 return -1;
552 for (; i < org_len; i++) {
553 if (canbhot(org[i]) && org[i-1] != '<' && org[i-1] != '(') {
554 position = i;
555 break;
556 }
557 } 524 }
558 if (position == -1)
559 return 1;
560
561 /* ok, char at org[position] should be a hot key to this item */
562 c = tolower(org[position]);
563 tmp = hotkeys[c].count;
564 hotkeys[c].ptrs[tmp] = index;
565 hotkeys[c].count++;
566 /*
567 snprintf(dest, len, "%.*s(%c)%s", position, org, org[position],
568 &org[position+1]);
569 */
570 /* make org[position] uppercase, and all leading letter small case */
571 strncpy(dest, org, len);
572 for (i = 0; i < position; i++)
573 dest[i] = tolower(dest[i]);
574 dest[position] = toupper(dest[position]);
575 k_menu_items[index].is_hot = 1;
576 return 0;
577} 525}
578 526
579/* Make a new item. Add a hotkey mark in the first possible letter. 527/* Make a new item. */
580 * As ncurses does not allow any attributes inside menue item, we mark the
581 * hot key as the first capitalized letter in the string */
582static void item_make(struct menu *menu, char tag, const char *fmt, ...) 528static void item_make(struct menu *menu, char tag, const char *fmt, ...)
583{ 529{
584 va_list ap; 530 va_list ap;
585 char tmp_str[256];
586 531
587 if (items_num > MAX_MENU_ITEMS-1) 532 if (items_num > MAX_MENU_ITEMS-1)
588 return; 533 return;
@@ -597,16 +542,13 @@ static void item_make(struct menu *menu, char tag, const char *fmt, ...)
597 k_menu_items[items_num].is_visible = 1; 542 k_menu_items[items_num].is_visible = 1;
598 543
599 va_start(ap, fmt); 544 va_start(ap, fmt);
600 vsnprintf(tmp_str, sizeof(tmp_str), fmt, ap); 545 vsnprintf(k_menu_items[items_num].str,
601 if (!k_menu_items[items_num].is_visible) 546 sizeof(k_menu_items[items_num].str),
602 memcpy(tmp_str, "XXX", 3); 547 fmt, ap);
603 va_end(ap); 548 va_end(ap);
604 if (make_hot( 549
605 k_menu_items[items_num].str, 550 if (!k_menu_items[items_num].is_visible)
606 sizeof(k_menu_items[items_num].str), tmp_str, items_num) != 0) 551 memcpy(k_menu_items[items_num].str, "XXX", 3);
607 strncpy(k_menu_items[items_num].str,
608 tmp_str,
609 sizeof(k_menu_items[items_num].str));
610 552
611 curses_menu_items[items_num] = new_item( 553 curses_menu_items[items_num] = new_item(
612 k_menu_items[items_num].str, 554 k_menu_items[items_num].str,
@@ -638,11 +580,9 @@ static void item_add_str(const char *fmt, ...)
638 va_end(ap); 580 va_end(ap);
639 snprintf(tmp_str, sizeof(tmp_str), "%s%s", 581 snprintf(tmp_str, sizeof(tmp_str), "%s%s",
640 k_menu_items[index].str, new_str); 582 k_menu_items[index].str, new_str);
641 if (make_hot(k_menu_items[index].str, 583 strncpy(k_menu_items[index].str,
642 sizeof(k_menu_items[index].str), tmp_str, index) != 0) 584 tmp_str,
643 strncpy(k_menu_items[index].str, 585 sizeof(k_menu_items[index].str));
644 tmp_str,
645 sizeof(k_menu_items[index].str));
646 586
647 free_item(curses_menu_items[index]); 587 free_item(curses_menu_items[index]);
648 curses_menu_items[index] = new_item( 588 curses_menu_items[index] = new_item(
@@ -676,6 +616,8 @@ static void *item_data(void)
676 struct mitem *mcur; 616 struct mitem *mcur;
677 617
678 cur = current_item(curses_menu); 618 cur = current_item(curses_menu);
619 if (!cur)
620 return NULL;
679 mcur = (struct mitem *) item_userptr(cur); 621 mcur = (struct mitem *) item_userptr(cur);
680 return mcur->usrptr; 622 return mcur->usrptr;
681 623
@@ -691,13 +633,9 @@ static char menu_backtitle[PATH_MAX+128];
691static const char *set_config_filename(const char *config_filename) 633static const char *set_config_filename(const char *config_filename)
692{ 634{
693 int size; 635 int size;
694 struct symbol *sym;
695 636
696 sym = sym_lookup("KERNELVERSION", 0);
697 sym_calc_value(sym);
698 size = snprintf(menu_backtitle, sizeof(menu_backtitle), 637 size = snprintf(menu_backtitle, sizeof(menu_backtitle),
699 _("%s - Linux Kernel v%s Configuration"), 638 "%s - %s", config_filename, rootmenu.prompt->text);
700 config_filename, sym_get_string_value(sym));
701 if (size >= sizeof(menu_backtitle)) 639 if (size >= sizeof(menu_backtitle))
702 menu_backtitle[sizeof(menu_backtitle)-1] = '\0'; 640 menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
703 641
@@ -707,25 +645,6 @@ static const char *set_config_filename(const char *config_filename)
707 return menu_backtitle; 645 return menu_backtitle;
708} 646}
709 647
710/* command = 0 is supress, 1 is restore */
711static void supress_stdout(int command)
712{
713 static FILE *org_stdout;
714 static FILE *org_stderr;
715
716 if (command == 0) {
717 org_stdout = stdout;
718 org_stderr = stderr;
719 stdout = fopen("/dev/null", "a");
720 stderr = fopen("/dev/null", "a");
721 } else {
722 fclose(stdout);
723 fclose(stderr);
724 stdout = org_stdout;
725 stderr = org_stderr;
726 }
727}
728
729/* return = 0 means we are successful. 648/* return = 0 means we are successful.
730 * -1 means go on doing what you were doing 649 * -1 means go on doing what you were doing
731 */ 650 */
@@ -737,8 +656,7 @@ static int do_exit(void)
737 return 0; 656 return 0;
738 } 657 }
739 res = btn_dialog(main_window, 658 res = btn_dialog(main_window,
740 _("Do you wish to save your " 659 _("Do you wish to save your new configuration?\n"
741 "new kernel configuration?\n"
742 "<ESC> to cancel and resume nconfig."), 660 "<ESC> to cancel and resume nconfig."),
743 2, 661 2,
744 " <save> ", 662 " <save> ",
@@ -751,36 +669,19 @@ static int do_exit(void)
751 /* if we got here, the user really wants to exit */ 669 /* if we got here, the user really wants to exit */
752 switch (res) { 670 switch (res) {
753 case 0: 671 case 0:
754 supress_stdout(0);
755 res = conf_write(filename); 672 res = conf_write(filename);
756 supress_stdout(1);
757 if (res) 673 if (res)
758 btn_dialog( 674 btn_dialog(
759 main_window, 675 main_window,
760 _("Error during writing of the kernel " 676 _("Error during writing of configuration.\n"
761 "configuration.\n" 677 "Your configuration changes were NOT saved."),
762 "Your kernel configuration "
763 "changes were NOT saved."),
764 1, 678 1,
765 "<OK>"); 679 "<OK>");
766 else {
767 char buf[1024];
768 snprintf(buf, 1024,
769 _("Configuration written to %s\n"
770 "End of Linux kernel configuration.\n"
771 "Execute 'make' to build the kernel or try"
772 " 'make help'."), filename);
773 btn_dialog(
774 main_window,
775 buf,
776 1,
777 "<OK>");
778 }
779 break; 680 break;
780 default: 681 default:
781 btn_dialog( 682 btn_dialog(
782 main_window, 683 main_window,
783 _("Your kernel configuration changes were NOT saved."), 684 _("Your configuration changes were NOT saved."),
784 1, 685 1,
785 "<OK>"); 686 "<OK>");
786 break; 687 break;
@@ -800,8 +701,8 @@ static void search_conf(void)
800again: 701again:
801 dres = dialog_inputbox(main_window, 702 dres = dialog_inputbox(main_window,
802 _("Search Configuration Parameter"), 703 _("Search Configuration Parameter"),
803 _("Enter CONFIG_ (sub)string to search for " 704 _("Enter " CONFIG_ " (sub)string to search for "
804 "(with or without \"CONFIG\")"), 705 "(with or without \"" CONFIG_ "\")"),
805 "", dialog_input_result, 99); 706 "", dialog_input_result, 99);
806 switch (dres) { 707 switch (dres) {
807 case 0: 708 case 0:
@@ -814,10 +715,10 @@ again:
814 return; 715 return;
815 } 716 }
816 717
817 /* strip CONFIG_ if necessary */ 718 /* strip the prefix if necessary */
818 dialog_input = dialog_input_result; 719 dialog_input = dialog_input_result;
819 if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0) 720 if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
820 dialog_input += 7; 721 dialog_input += strlen(CONFIG_);
821 722
822 sym_arr = sym_re_search(dialog_input); 723 sym_arr = sym_re_search(dialog_input);
823 res = get_relations_str(sym_arr); 724 res = get_relations_str(sym_arr);
@@ -1025,23 +926,18 @@ static void reset_menu(void)
1025static void center_item(int selected_index, int *last_top_row) 926static void center_item(int selected_index, int *last_top_row)
1026{ 927{
1027 int toprow; 928 int toprow;
1028 int maxy, maxx;
1029 929
1030 scale_menu(curses_menu, &maxy, &maxx);
1031 set_top_row(curses_menu, *last_top_row); 930 set_top_row(curses_menu, *last_top_row);
1032 toprow = top_row(curses_menu); 931 toprow = top_row(curses_menu);
1033 if (selected_index >= toprow && selected_index < toprow+maxy) { 932 if (selected_index < toprow ||
1034 /* we can only move the selected item. no need to scroll */ 933 selected_index >= toprow+mwin_max_lines) {
1035 set_current_item(curses_menu, 934 toprow = max(selected_index-mwin_max_lines/2, 0);
1036 curses_menu_items[selected_index]); 935 if (toprow >= item_count(curses_menu)-mwin_max_lines)
1037 } else {
1038 toprow = max(selected_index-maxy/2, 0);
1039 if (toprow >= item_count(curses_menu)-maxy)
1040 toprow = item_count(curses_menu)-mwin_max_lines; 936 toprow = item_count(curses_menu)-mwin_max_lines;
1041 set_top_row(curses_menu, toprow); 937 set_top_row(curses_menu, toprow);
1042 set_current_item(curses_menu,
1043 curses_menu_items[selected_index]);
1044 } 938 }
939 set_current_item(curses_menu,
940 curses_menu_items[selected_index]);
1045 *last_top_row = toprow; 941 *last_top_row = toprow;
1046 post_menu(curses_menu); 942 post_menu(curses_menu);
1047 refresh_all_windows(main_window); 943 refresh_all_windows(main_window);
@@ -1073,7 +969,7 @@ static void show_menu(const char *prompt, const char *instructions,
1073 /* position the menu at the middle of the screen */ 969 /* position the menu at the middle of the screen */
1074 scale_menu(curses_menu, &maxy, &maxx); 970 scale_menu(curses_menu, &maxy, &maxx);
1075 maxx = min(maxx, mwin_max_cols-2); 971 maxx = min(maxx, mwin_max_cols-2);
1076 maxy = mwin_max_lines-2; 972 maxy = mwin_max_lines;
1077 menu_window = derwin(main_window, 973 menu_window = derwin(main_window,
1078 maxy, 974 maxy,
1079 maxx, 975 maxx,
@@ -1097,10 +993,77 @@ static void show_menu(const char *prompt, const char *instructions,
1097 refresh_all_windows(main_window); 993 refresh_all_windows(main_window);
1098} 994}
1099 995
996static 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}
1100 1006
1101static void conf(struct menu *menu) 1007struct match_state
1102{ 1008{
1009 int in_search;
1010 match_f match_direction;
1103 char pattern[256]; 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 */
1018static 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
1065static void conf(struct menu *menu)
1066{
1104 struct menu *submenu = 0; 1067 struct menu *submenu = 0;
1105 const char *prompt = menu_get_prompt(menu); 1068 const char *prompt = menu_get_prompt(menu);
1106 struct symbol *sym; 1069 struct symbol *sym;
@@ -1108,8 +1071,11 @@ static void conf(struct menu *menu)
1108 int res; 1071 int res;
1109 int current_index = 0; 1072 int current_index = 0;
1110 int last_top_row = 0; 1073 int last_top_row = 0;
1111 1074 struct match_state match_state = {
1112 bzero(pattern, sizeof(pattern)); 1075 .in_search = 0,
1076 .match_direction = MATCH_TINKER_PATTERN_DOWN,
1077 .pattern = "",
1078 };
1113 1079
1114 while (!global_exit) { 1080 while (!global_exit) {
1115 reset_menu(); 1081 reset_menu();
@@ -1122,7 +1088,22 @@ static void conf(struct menu *menu)
1122 _(menu_instructions), 1088 _(menu_instructions),
1123 current_index, &last_top_row); 1089 current_index, &last_top_row);
1124 keypad((menu_win(curses_menu)), TRUE); 1090 keypad((menu_win(curses_menu)), TRUE);
1125 while (!global_exit && (res = wgetch(menu_win(curses_menu)))) { 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 }
1126 if (process_special_keys(&res, 1107 if (process_special_keys(&res,
1127 (struct menu *) item_data())) 1108 (struct menu *) item_data()))
1128 break; 1109 break;
@@ -1153,19 +1134,13 @@ static void conf(struct menu *menu)
1153 if (res == 10 || res == 27 || 1134 if (res == 10 || res == 27 ||
1154 res == 32 || res == 'n' || res == 'y' || 1135 res == 32 || res == 'n' || res == 'y' ||
1155 res == KEY_LEFT || res == KEY_RIGHT || 1136 res == KEY_LEFT || res == KEY_RIGHT ||
1156 res == 'm' || res == '/') 1137 res == 'm')
1157 break; 1138 break;
1158 else if (canbhot(res)) {
1159 /* check for hot keys: */
1160 int tmp = get_next_hot(res);
1161 if (tmp != -1)
1162 center_item(tmp, &last_top_row);
1163 }
1164 refresh_all_windows(main_window); 1139 refresh_all_windows(main_window);
1165 } 1140 }
1166 1141
1167 refresh_all_windows(main_window); 1142 refresh_all_windows(main_window);
1168 /* if ESC or left*/ 1143 /* if ESC or left*/
1169 if (res == 27 || (menu != &rootmenu && res == KEY_LEFT)) 1144 if (res == 27 || (menu != &rootmenu && res == KEY_LEFT))
1170 break; 1145 break;
1171 1146
@@ -1233,23 +1208,30 @@ static void conf(struct menu *menu)
1233 if (item_is_tag('t')) 1208 if (item_is_tag('t'))
1234 sym_set_tristate_value(sym, mod); 1209 sym_set_tristate_value(sym, mod);
1235 break; 1210 break;
1236 case '/':
1237 search_conf();
1238 break;
1239 } 1211 }
1240 } 1212 }
1241} 1213}
1242 1214
1215static 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
1243static void show_help(struct menu *menu) 1223static void show_help(struct menu *menu)
1244{ 1224{
1245 struct gstr help = str_new(); 1225 struct gstr help = str_new();
1246 1226
1247 if (menu && menu->sym && menu_has_help(menu)) { 1227 if (menu && menu->sym && menu_has_help(menu)) {
1248 if (menu->sym->name) { 1228 if (menu->sym->name) {
1249 str_printf(&help, "CONFIG_%s:\n\n", menu->sym->name); 1229 str_printf(&help, "%s%s:\n\n", CONFIG_, menu->sym->name);
1250 str_append(&help, _(menu_get_help(menu))); 1230 str_append(&help, _(menu_get_help(menu)));
1251 str_append(&help, "\n"); 1231 str_append(&help, "\n");
1252 get_symbol_str(&help, menu->sym); 1232 get_symbol_str(&help, menu->sym);
1233 } else {
1234 str_append(&help, _(menu_get_help(menu)));
1253 } 1235 }
1254 } else { 1236 } else {
1255 str_append(&help, nohelp_text); 1237 str_append(&help, nohelp_text);
@@ -1266,6 +1248,11 @@ static void conf_choice(struct menu *menu)
1266 int selected_index = 0; 1248 int selected_index = 0;
1267 int last_top_row = 0; 1249 int last_top_row = 0;
1268 int res, i = 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 };
1269 1256
1270 active = sym_get_choice_value(menu->sym); 1257 active = sym_get_choice_value(menu->sym);
1271 /* this is mostly duplicated from the conf() function. */ 1258 /* this is mostly duplicated from the conf() function. */
@@ -1292,7 +1279,22 @@ static void conf_choice(struct menu *menu)
1292 _(radiolist_instructions), 1279 _(radiolist_instructions),
1293 selected_index, 1280 selected_index,
1294 &last_top_row); 1281 &last_top_row);
1295 while (!global_exit && (res = wgetch(menu_win(curses_menu)))) { 1282 while (!global_exit) {
1283 if (match_state.in_search) {
1284 mvprintw(0, 0, "searching: %s",
1285 match_state.pattern);
1286 clrtoeol();
1287 }
1288 refresh_all_windows(main_window);
1289 res = wgetch(menu_win(curses_menu));
1290 if (!res)
1291 break;
1292 if (do_match(res, &match_state, &selected_index) == 0) {
1293 if (selected_index != -1)
1294 center_item(selected_index,
1295 &last_top_row);
1296 continue;
1297 }
1296 if (process_special_keys( 1298 if (process_special_keys(
1297 &res, 1299 &res,
1298 (struct menu *) item_data())) 1300 (struct menu *) item_data()))
@@ -1322,13 +1324,8 @@ static void conf_choice(struct menu *menu)
1322 break; 1324 break;
1323 } 1325 }
1324 if (res == 10 || res == 27 || res == ' ' || 1326 if (res == 10 || res == 27 || res == ' ' ||
1325 res == KEY_LEFT) 1327 res == KEY_LEFT){
1326 break; 1328 break;
1327 else if (canbhot(res)) {
1328 /* check for hot keys: */
1329 int tmp = get_next_hot(res);
1330 if (tmp != -1)
1331 center_item(tmp, &last_top_row);
1332 } 1329 }
1333 refresh_all_windows(main_window); 1330 refresh_all_windows(main_window);
1334 } 1331 }
@@ -1447,16 +1444,8 @@ static void conf_save(void)
1447 case 0: 1444 case 0:
1448 if (!dialog_input_result[0]) 1445 if (!dialog_input_result[0])
1449 return; 1446 return;
1450 supress_stdout(0);
1451 res = conf_write(dialog_input_result); 1447 res = conf_write(dialog_input_result);
1452 supress_stdout(1);
1453 if (!res) { 1448 if (!res) {
1454 char buf[1024];
1455 sprintf(buf, "%s %s",
1456 _("configuration file saved to: "),
1457 dialog_input_result);
1458 btn_dialog(main_window,
1459 buf, 1, "<OK>");
1460 set_config_filename(dialog_input_result); 1449 set_config_filename(dialog_input_result);
1461 return; 1450 return;
1462 } 1451 }
@@ -1483,7 +1472,7 @@ void setup_windows(void)
1483 /* set up the menu and menu window */ 1472 /* set up the menu and menu window */
1484 main_window = newwin(LINES-2, COLS-2, 2, 1); 1473 main_window = newwin(LINES-2, COLS-2, 2, 1);
1485 keypad(main_window, TRUE); 1474 keypad(main_window, TRUE);
1486 mwin_max_lines = LINES-6; 1475 mwin_max_lines = LINES-7;
1487 mwin_max_cols = COLS-6; 1476 mwin_max_cols = COLS-6;
1488 1477
1489 /* panels order is from bottom to top */ 1478 /* panels order is from bottom to top */
@@ -1530,9 +1519,10 @@ int main(int ac, char **av)
1530 /* set btns menu */ 1519 /* set btns menu */
1531 curses_menu = new_menu(curses_menu_items); 1520 curses_menu = new_menu(curses_menu_items);
1532 menu_opts_off(curses_menu, O_SHOWDESC); 1521 menu_opts_off(curses_menu, O_SHOWDESC);
1533 menu_opts_off(curses_menu, O_SHOWMATCH); 1522 menu_opts_on(curses_menu, O_SHOWMATCH);
1534 menu_opts_on(curses_menu, O_ONEVALUE); 1523 menu_opts_on(curses_menu, O_ONEVALUE);
1535 menu_opts_on(curses_menu, O_NONCYCLIC); 1524 menu_opts_on(curses_menu, O_NONCYCLIC);
1525 menu_opts_on(curses_menu, O_IGNORECASE);
1536 set_menu_mark(curses_menu, " "); 1526 set_menu_mark(curses_menu, " ");
1537 set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]); 1527 set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]);
1538 set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]); 1528 set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]);
@@ -1548,8 +1538,7 @@ int main(int ac, char **av)
1548 _(menu_no_f_instructions)); 1538 _(menu_no_f_instructions));
1549 } 1539 }
1550 1540
1551 1541 conf_set_message_callback(conf_message_callback);
1552
1553 /* do the work */ 1542 /* do the work */
1554 while (!global_exit) { 1543 while (!global_exit) {
1555 conf(&rootmenu); 1544 conf(&rootmenu);