aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-11 21:28:52 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-11 21:28:52 -0400
commit35e9a274fdc9c8feb763e4970a32d7089f51393c (patch)
treed67ae81b870cb4531a92cbf44c07210f4ad124c7 /scripts
parentae3e4628287de0ab90545c14076657aeee38506b (diff)
parentfb16d8912db5268f29706010ecafff74b971c58d (diff)
Merge branch 'kconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild
Pull kconfig changes from Michal Marek: "kconfig in v3.7 is going to - initialize ncurses only once in menuconfig - be able to jump to a search result in menuconfig - change the misnomer oldnoconfig to a more meaningful name olddefconfig, keeping the old name as alias" * 'kconfig' of git://git.kernel.org/pub/scm/linux/kernel/git/mmarek/kbuild: kconfig: replace 'oldnoconfig' with 'olddefconfig', and keep the old name as an alias menuconfig: Assign jump keys per-page instead of globally menuconfig: Do not open code textbox scroll up/down menuconfig: Add jump keys to search results menuconfig: Extend dialog_textbox so that it can return to a scrolled position menuconfig: Extend dialog_textbox so that it can exit on arbitrary keypresses menuconfig: Remove superfluous conditionnal kconfig: document oldnoconfig to what it really does in conf.c kconfig/mconf.c: revision of curses initialization.
Diffstat (limited to 'scripts')
-rw-r--r--scripts/kconfig/Makefile12
-rw-r--r--scripts/kconfig/conf.c25
-rw-r--r--scripts/kconfig/expr.h11
-rw-r--r--scripts/kconfig/lkc_proto.h6
-rw-r--r--scripts/kconfig/lxdialog/dialog.h9
-rw-r--r--scripts/kconfig/lxdialog/textbox.c171
-rw-r--r--scripts/kconfig/lxdialog/util.c7
-rw-r--r--scripts/kconfig/mconf.c123
-rw-r--r--scripts/kconfig/menu.c53
-rw-r--r--scripts/kconfig/nconf.c2
10 files changed, 289 insertions, 130 deletions
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 77d53999ffb9..3091794e9354 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -76,11 +76,17 @@ PHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig
76allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf 76allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf
77 $< --$@ $(Kconfig) 77 $< --$@ $(Kconfig)
78 78
79PHONY += listnewconfig oldnoconfig savedefconfig defconfig 79PHONY += listnewconfig olddefconfig oldnoconfig savedefconfig defconfig
80 80
81listnewconfig oldnoconfig: $(obj)/conf 81listnewconfig olddefconfig: $(obj)/conf
82 $< --$@ $(Kconfig) 82 $< --$@ $(Kconfig)
83 83
84# oldnoconfig is an alias of olddefconfig, because people already are dependent
85# on its behavior(sets new symbols to their default value but not 'n') with the
86# counter-intuitive name.
87oldnoconfig: $(obj)/conf
88 $< --olddefconfig $(Kconfig)
89
84savedefconfig: $(obj)/conf 90savedefconfig: $(obj)/conf
85 $< --$@=defconfig $(Kconfig) 91 $< --$@=defconfig $(Kconfig)
86 92
@@ -114,7 +120,7 @@ help:
114 @echo ' alldefconfig - New config with all symbols set to default' 120 @echo ' alldefconfig - New config with all symbols set to default'
115 @echo ' randconfig - New config with random answer to all options' 121 @echo ' randconfig - New config with random answer to all options'
116 @echo ' listnewconfig - List new options' 122 @echo ' listnewconfig - List new options'
117 @echo ' oldnoconfig - Same as silentoldconfig but sets new symbols to their default value' 123 @echo ' olddefconfig - Same as silentoldconfig but sets new symbols to their default value'
118 124
119# lxdialog stuff 125# lxdialog stuff
120check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh 126check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 0dc4a2c779b1..4da3b4adfad2 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -32,7 +32,7 @@ enum input_mode {
32 defconfig, 32 defconfig,
33 savedefconfig, 33 savedefconfig,
34 listnewconfig, 34 listnewconfig,
35 oldnoconfig, 35 olddefconfig,
36} input_mode = oldaskconfig; 36} input_mode = oldaskconfig;
37 37
38static int indent = 1; 38static int indent = 1;
@@ -365,7 +365,7 @@ static void conf(struct menu *menu)
365 case P_MENU: 365 case P_MENU:
366 if ((input_mode == silentoldconfig || 366 if ((input_mode == silentoldconfig ||
367 input_mode == listnewconfig || 367 input_mode == listnewconfig ||
368 input_mode == oldnoconfig) && 368 input_mode == olddefconfig) &&
369 rootEntry != menu) { 369 rootEntry != menu) {
370 check_conf(menu); 370 check_conf(menu);
371 return; 371 return;
@@ -429,7 +429,7 @@ static void check_conf(struct menu *menu)
429 if (sym->name && !sym_is_choice_value(sym)) { 429 if (sym->name && !sym_is_choice_value(sym)) {
430 printf("%s%s\n", CONFIG_, sym->name); 430 printf("%s%s\n", CONFIG_, sym->name);
431 } 431 }
432 } else if (input_mode != oldnoconfig) { 432 } else if (input_mode != olddefconfig) {
433 if (!conf_cnt++) 433 if (!conf_cnt++)
434 printf(_("*\n* Restart config...\n*\n")); 434 printf(_("*\n* Restart config...\n*\n"));
435 rootEntry = menu_get_parent_menu(menu); 435 rootEntry = menu_get_parent_menu(menu);
@@ -454,7 +454,13 @@ static struct option long_opts[] = {
454 {"alldefconfig", no_argument, NULL, alldefconfig}, 454 {"alldefconfig", no_argument, NULL, alldefconfig},
455 {"randconfig", no_argument, NULL, randconfig}, 455 {"randconfig", no_argument, NULL, randconfig},
456 {"listnewconfig", no_argument, NULL, listnewconfig}, 456 {"listnewconfig", no_argument, NULL, listnewconfig},
457 {"oldnoconfig", no_argument, NULL, oldnoconfig}, 457 {"olddefconfig", no_argument, NULL, olddefconfig},
458 /*
459 * oldnoconfig is an alias of olddefconfig, because people already
460 * are dependent on its behavior(sets new symbols to their default
461 * value but not 'n') with the counter-intuitive name.
462 */
463 {"oldnoconfig", no_argument, NULL, olddefconfig},
458 {NULL, 0, NULL, 0} 464 {NULL, 0, NULL, 0}
459}; 465};
460 466
@@ -467,7 +473,8 @@ static void conf_usage(const char *progname)
467 printf(" --oldaskconfig Start a new configuration using a line-oriented program\n"); 473 printf(" --oldaskconfig Start a new configuration using a line-oriented program\n");
468 printf(" --oldconfig Update a configuration using a provided .config as base\n"); 474 printf(" --oldconfig Update a configuration using a provided .config as base\n");
469 printf(" --silentoldconfig Same as oldconfig, but quietly, additionally update deps\n"); 475 printf(" --silentoldconfig Same as oldconfig, but quietly, additionally update deps\n");
470 printf(" --oldnoconfig Same as silentoldconfig but set new symbols to no\n"); 476 printf(" --olddefconfig Same as silentoldconfig but sets new symbols to their default value\n");
477 printf(" --oldnoconfig An alias of olddefconfig\n");
471 printf(" --defconfig <file> New config with default defined in <file>\n"); 478 printf(" --defconfig <file> New config with default defined in <file>\n");
472 printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n"); 479 printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n");
473 printf(" --allnoconfig New config where all options are answered with no\n"); 480 printf(" --allnoconfig New config where all options are answered with no\n");
@@ -520,7 +527,7 @@ int main(int ac, char **av)
520 case allmodconfig: 527 case allmodconfig:
521 case alldefconfig: 528 case alldefconfig:
522 case listnewconfig: 529 case listnewconfig:
523 case oldnoconfig: 530 case olddefconfig:
524 break; 531 break;
525 case '?': 532 case '?':
526 conf_usage(progname); 533 conf_usage(progname);
@@ -565,7 +572,7 @@ int main(int ac, char **av)
565 case oldaskconfig: 572 case oldaskconfig:
566 case oldconfig: 573 case oldconfig:
567 case listnewconfig: 574 case listnewconfig:
568 case oldnoconfig: 575 case olddefconfig:
569 conf_read(NULL); 576 conf_read(NULL);
570 break; 577 break;
571 case allnoconfig: 578 case allnoconfig:
@@ -645,7 +652,7 @@ int main(int ac, char **av)
645 /* fall through */ 652 /* fall through */
646 case oldconfig: 653 case oldconfig:
647 case listnewconfig: 654 case listnewconfig:
648 case oldnoconfig: 655 case olddefconfig:
649 case silentoldconfig: 656 case silentoldconfig:
650 /* Update until a loop caused no more changes */ 657 /* Update until a loop caused no more changes */
651 do { 658 do {
@@ -653,7 +660,7 @@ int main(int ac, char **av)
653 check_conf(&rootmenu); 660 check_conf(&rootmenu);
654 } while (conf_cnt && 661 } while (conf_cnt &&
655 (input_mode != listnewconfig && 662 (input_mode != listnewconfig &&
656 input_mode != oldnoconfig)); 663 input_mode != olddefconfig));
657 break; 664 break;
658 } 665 }
659 666
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index d4ecce8bc3a6..bd2e09895553 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -12,6 +12,7 @@ extern "C" {
12 12
13#include <assert.h> 13#include <assert.h>
14#include <stdio.h> 14#include <stdio.h>
15#include <sys/queue.h>
15#ifndef __cplusplus 16#ifndef __cplusplus
16#include <stdbool.h> 17#include <stdbool.h>
17#endif 18#endif
@@ -173,6 +174,16 @@ struct menu {
173#define MENU_CHANGED 0x0001 174#define MENU_CHANGED 0x0001
174#define MENU_ROOT 0x0002 175#define MENU_ROOT 0x0002
175 176
177struct jump_key {
178 CIRCLEQ_ENTRY(jump_key) entries;
179 size_t offset;
180 struct menu *target;
181 int index;
182};
183CIRCLEQ_HEAD(jk_head, jump_key);
184
185#define JUMP_NB 9
186
176extern struct file *file_list; 187extern struct file *file_list;
177extern struct file *current_file; 188extern struct file *current_file;
178struct file *lookup_file(const char *name); 189struct file *lookup_file(const char *name);
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index 47fe9c340f9a..1d1c08537f1e 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -21,8 +21,10 @@ P(menu_get_root_menu,struct menu *,(struct menu *menu));
21P(menu_get_parent_menu,struct menu *,(struct menu *menu)); 21P(menu_get_parent_menu,struct menu *,(struct menu *menu));
22P(menu_has_help,bool,(struct menu *menu)); 22P(menu_has_help,bool,(struct menu *menu));
23P(menu_get_help,const char *,(struct menu *menu)); 23P(menu_get_help,const char *,(struct menu *menu));
24P(get_symbol_str, void, (struct gstr *r, struct symbol *sym)); 24P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct jk_head
25P(get_relations_str, struct gstr, (struct symbol **sym_arr)); 25 *head));
26P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct jk_head
27 *head));
26P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help)); 28P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));
27 29
28/* symbol.c */ 30/* symbol.c */
diff --git a/scripts/kconfig/lxdialog/dialog.h b/scripts/kconfig/lxdialog/dialog.h
index b5211fce0d94..ee17a5264d5b 100644
--- a/scripts/kconfig/lxdialog/dialog.h
+++ b/scripts/kconfig/lxdialog/dialog.h
@@ -144,6 +144,7 @@ struct dialog_info {
144 */ 144 */
145extern struct dialog_info dlg; 145extern struct dialog_info dlg;
146extern char dialog_input_result[]; 146extern char dialog_input_result[];
147extern int saved_x, saved_y; /* Needed in signal handler in mconf.c */
147 148
148/* 149/*
149 * Function prototypes 150 * Function prototypes
@@ -209,7 +210,13 @@ int first_alpha(const char *string, const char *exempt);
209int dialog_yesno(const char *title, const char *prompt, int height, int width); 210int dialog_yesno(const char *title, const char *prompt, int height, int width);
210int dialog_msgbox(const char *title, const char *prompt, int height, 211int dialog_msgbox(const char *title, const char *prompt, int height,
211 int width, int pause); 212 int width, int pause);
212int dialog_textbox(const char *title, const char *file, int height, int width); 213
214
215typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void
216 *_data);
217int dialog_textbox(const char *title, char *tbuf, int initial_height,
218 int initial_width, int *keys, int *_vscroll, int *_hscroll,
219 update_text_fn update_text, void *data);
213int dialog_menu(const char *title, const char *prompt, 220int dialog_menu(const char *title, const char *prompt,
214 const void *selected, int *s_scroll); 221 const void *selected, int *s_scroll);
215int dialog_checklist(const char *title, const char *prompt, int height, 222int dialog_checklist(const char *title, const char *prompt, int height,
diff --git a/scripts/kconfig/lxdialog/textbox.c b/scripts/kconfig/lxdialog/textbox.c
index 4e5de60a0c0d..a48bb93e0907 100644
--- a/scripts/kconfig/lxdialog/textbox.c
+++ b/scripts/kconfig/lxdialog/textbox.c
@@ -22,23 +22,25 @@
22#include "dialog.h" 22#include "dialog.h"
23 23
24static void back_lines(int n); 24static void back_lines(int n);
25static void print_page(WINDOW * win, int height, int width); 25static void print_page(WINDOW *win, int height, int width, update_text_fn
26static void print_line(WINDOW * win, int row, int width); 26 update_text, void *data);
27static void print_line(WINDOW *win, int row, int width);
27static char *get_line(void); 28static char *get_line(void);
28static void print_position(WINDOW * win); 29static void print_position(WINDOW * win);
29 30
30static int hscroll; 31static int hscroll;
31static int begin_reached, end_reached, page_length; 32static int begin_reached, end_reached, page_length;
32static const char *buf; 33static char *buf;
33static const char *page; 34static char *page;
34 35
35/* 36/*
36 * refresh window content 37 * refresh window content
37 */ 38 */
38static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw, 39static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
39 int cur_y, int cur_x) 40 int cur_y, int cur_x, update_text_fn update_text,
41 void *data)
40{ 42{
41 print_page(box, boxh, boxw); 43 print_page(box, boxh, boxw, update_text, data);
42 print_position(dialog); 44 print_position(dialog);
43 wmove(dialog, cur_y, cur_x); /* Restore cursor position */ 45 wmove(dialog, cur_y, cur_x); /* Restore cursor position */
44 wrefresh(dialog); 46 wrefresh(dialog);
@@ -47,14 +49,18 @@ static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
47 49
48/* 50/*
49 * Display text from a file in a dialog box. 51 * Display text from a file in a dialog box.
52 *
53 * keys is a null-terminated array
54 * update_text() may not add or remove any '\n' or '\0' in tbuf
50 */ 55 */
51int dialog_textbox(const char *title, const char *tbuf, 56int dialog_textbox(const char *title, char *tbuf, int initial_height,
52 int initial_height, int initial_width) 57 int initial_width, int *keys, int *_vscroll, int *_hscroll,
58 update_text_fn update_text, void *data)
53{ 59{
54 int i, x, y, cur_x, cur_y, key = 0; 60 int i, x, y, cur_x, cur_y, key = 0;
55 int height, width, boxh, boxw; 61 int height, width, boxh, boxw;
56 int passed_end;
57 WINDOW *dialog, *box; 62 WINDOW *dialog, *box;
63 bool done = false;
58 64
59 begin_reached = 1; 65 begin_reached = 1;
60 end_reached = 0; 66 end_reached = 0;
@@ -63,6 +69,15 @@ int dialog_textbox(const char *title, const char *tbuf,
63 buf = tbuf; 69 buf = tbuf;
64 page = buf; /* page is pointer to start of page to be displayed */ 70 page = buf; /* page is pointer to start of page to be displayed */
65 71
72 if (_vscroll && *_vscroll) {
73 begin_reached = 0;
74
75 for (i = 0; i < *_vscroll; i++)
76 get_line();
77 }
78 if (_hscroll)
79 hscroll = *_hscroll;
80
66do_resize: 81do_resize:
67 getmaxyx(stdscr, height, width); 82 getmaxyx(stdscr, height, width);
68 if (height < 8 || width < 8) 83 if (height < 8 || width < 8)
@@ -120,9 +135,10 @@ do_resize:
120 135
121 /* Print first page of text */ 136 /* Print first page of text */
122 attr_clear(box, boxh, boxw, dlg.dialog.atr); 137 attr_clear(box, boxh, boxw, dlg.dialog.atr);
123 refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x); 138 refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text,
139 data);
124 140
125 while ((key != KEY_ESC) && (key != '\n')) { 141 while (!done) {
126 key = wgetch(dialog); 142 key = wgetch(dialog);
127 switch (key) { 143 switch (key) {
128 case 'E': /* Exit */ 144 case 'E': /* Exit */
@@ -130,16 +146,17 @@ do_resize:
130 case 'X': 146 case 'X':
131 case 'x': 147 case 'x':
132 case 'q': 148 case 'q':
133 delwin(box); 149 case '\n':
134 delwin(dialog); 150 done = true;
135 return 0; 151 break;
136 case 'g': /* First page */ 152 case 'g': /* First page */
137 case KEY_HOME: 153 case KEY_HOME:
138 if (!begin_reached) { 154 if (!begin_reached) {
139 begin_reached = 1; 155 begin_reached = 1;
140 page = buf; 156 page = buf;
141 refresh_text_box(dialog, box, boxh, boxw, 157 refresh_text_box(dialog, box, boxh, boxw,
142 cur_y, cur_x); 158 cur_y, cur_x, update_text,
159 data);
143 } 160 }
144 break; 161 break;
145 case 'G': /* Last page */ 162 case 'G': /* Last page */
@@ -149,45 +166,18 @@ do_resize:
149 /* point to last char in buf */ 166 /* point to last char in buf */
150 page = buf + strlen(buf); 167 page = buf + strlen(buf);
151 back_lines(boxh); 168 back_lines(boxh);
152 refresh_text_box(dialog, box, boxh, boxw, 169 refresh_text_box(dialog, box, boxh, boxw, cur_y,
153 cur_y, cur_x); 170 cur_x, update_text, data);
154 break; 171 break;
155 case 'K': /* Previous line */ 172 case 'K': /* Previous line */
156 case 'k': 173 case 'k':
157 case KEY_UP: 174 case KEY_UP:
158 if (!begin_reached) { 175 if (begin_reached)
159 back_lines(page_length + 1); 176 break;
160
161 /* We don't call print_page() here but use
162 * scrolling to ensure faster screen update.
163 * However, 'end_reached' and 'page_length'
164 * should still be updated, and 'page' should
165 * point to start of next page. This is done
166 * by calling get_line() in the following
167 * 'for' loop. */
168 scrollok(box, TRUE);
169 wscrl(box, -1); /* Scroll box region down one line */
170 scrollok(box, FALSE);
171 page_length = 0;
172 passed_end = 0;
173 for (i = 0; i < boxh; i++) {
174 if (!i) {
175 /* print first line of page */
176 print_line(box, 0, boxw);
177 wnoutrefresh(box);
178 } else
179 /* Called to update 'end_reached' and 'page' */
180 get_line();
181 if (!passed_end)
182 page_length++;
183 if (end_reached && !passed_end)
184 passed_end = 1;
185 }
186 177
187 print_position(dialog); 178 back_lines(page_length + 1);
188 wmove(dialog, cur_y, cur_x); /* Restore cursor position */ 179 refresh_text_box(dialog, box, boxh, boxw, cur_y,
189 wrefresh(dialog); 180 cur_x, update_text, data);
190 }
191 break; 181 break;
192 case 'B': /* Previous page */ 182 case 'B': /* Previous page */
193 case 'b': 183 case 'b':
@@ -196,23 +186,18 @@ do_resize:
196 if (begin_reached) 186 if (begin_reached)
197 break; 187 break;
198 back_lines(page_length + boxh); 188 back_lines(page_length + boxh);
199 refresh_text_box(dialog, box, boxh, boxw, 189 refresh_text_box(dialog, box, boxh, boxw, cur_y,
200 cur_y, cur_x); 190 cur_x, update_text, data);
201 break; 191 break;
202 case 'J': /* Next line */ 192 case 'J': /* Next line */
203 case 'j': 193 case 'j':
204 case KEY_DOWN: 194 case KEY_DOWN:
205 if (!end_reached) { 195 if (end_reached)
206 begin_reached = 0; 196 break;
207 scrollok(box, TRUE); 197
208 scroll(box); /* Scroll box region up one line */ 198 back_lines(page_length - 1);
209 scrollok(box, FALSE); 199 refresh_text_box(dialog, box, boxh, boxw, cur_y,
210 print_line(box, boxh - 1, boxw); 200 cur_x, update_text, data);
211 wnoutrefresh(box);
212 print_position(dialog);
213 wmove(dialog, cur_y, cur_x); /* Restore cursor position */
214 wrefresh(dialog);
215 }
216 break; 201 break;
217 case KEY_NPAGE: /* Next page */ 202 case KEY_NPAGE: /* Next page */
218 case ' ': 203 case ' ':
@@ -221,8 +206,8 @@ do_resize:
221 break; 206 break;
222 207
223 begin_reached = 0; 208 begin_reached = 0;
224 refresh_text_box(dialog, box, boxh, boxw, 209 refresh_text_box(dialog, box, boxh, boxw, cur_y,
225 cur_y, cur_x); 210 cur_x, update_text, data);
226 break; 211 break;
227 case '0': /* Beginning of line */ 212 case '0': /* Beginning of line */
228 case 'H': /* Scroll left */ 213 case 'H': /* Scroll left */
@@ -237,8 +222,8 @@ do_resize:
237 hscroll--; 222 hscroll--;
238 /* Reprint current page to scroll horizontally */ 223 /* Reprint current page to scroll horizontally */
239 back_lines(page_length); 224 back_lines(page_length);
240 refresh_text_box(dialog, box, boxh, boxw, 225 refresh_text_box(dialog, box, boxh, boxw, cur_y,
241 cur_y, cur_x); 226 cur_x, update_text, data);
242 break; 227 break;
243 case 'L': /* Scroll right */ 228 case 'L': /* Scroll right */
244 case 'l': 229 case 'l':
@@ -248,11 +233,12 @@ do_resize:
248 hscroll++; 233 hscroll++;
249 /* Reprint current page to scroll horizontally */ 234 /* Reprint current page to scroll horizontally */
250 back_lines(page_length); 235 back_lines(page_length);
251 refresh_text_box(dialog, box, boxh, boxw, 236 refresh_text_box(dialog, box, boxh, boxw, cur_y,
252 cur_y, cur_x); 237 cur_x, update_text, data);
253 break; 238 break;
254 case KEY_ESC: 239 case KEY_ESC:
255 key = on_key_esc(dialog); 240 if (on_key_esc(dialog) == KEY_ESC)
241 done = true;
256 break; 242 break;
257 case KEY_RESIZE: 243 case KEY_RESIZE:
258 back_lines(height); 244 back_lines(height);
@@ -260,11 +246,31 @@ do_resize:
260 delwin(dialog); 246 delwin(dialog);
261 on_key_resize(); 247 on_key_resize();
262 goto do_resize; 248 goto do_resize;
249 default:
250 for (i = 0; keys[i]; i++) {
251 if (key == keys[i]) {
252 done = true;
253 break;
254 }
255 }
263 } 256 }
264 } 257 }
265 delwin(box); 258 delwin(box);
266 delwin(dialog); 259 delwin(dialog);
267 return key; /* ESC pressed */ 260 if (_vscroll) {
261 const char *s;
262
263 s = buf;
264 *_vscroll = 0;
265 back_lines(page_length);
266 while (s < page && (s = strchr(s, '\n'))) {
267 (*_vscroll)++;
268 s++;
269 }
270 }
271 if (_hscroll)
272 *_hscroll = hscroll;
273 return key;
268} 274}
269 275
270/* 276/*
@@ -301,12 +307,23 @@ static void back_lines(int n)
301} 307}
302 308
303/* 309/*
304 * Print a new page of text. Called by dialog_textbox(). 310 * Print a new page of text.
305 */ 311 */
306static void print_page(WINDOW * win, int height, int width) 312static void print_page(WINDOW *win, int height, int width, update_text_fn
313 update_text, void *data)
307{ 314{
308 int i, passed_end = 0; 315 int i, passed_end = 0;
309 316
317 if (update_text) {
318 char *end;
319
320 for (i = 0; i < height; i++)
321 get_line();
322 end = page;
323 back_lines(height);
324 update_text(buf, page - buf, end - buf, data);
325 }
326
310 page_length = 0; 327 page_length = 0;
311 for (i = 0; i < height; i++) { 328 for (i = 0; i < height; i++) {
312 print_line(win, i, width); 329 print_line(win, i, width);
@@ -319,7 +336,7 @@ static void print_page(WINDOW * win, int height, int width)
319} 336}
320 337
321/* 338/*
322 * Print a new line of text. Called by dialog_textbox() and print_page(). 339 * Print a new line of text.
323 */ 340 */
324static void print_line(WINDOW * win, int row, int width) 341static void print_line(WINDOW * win, int row, int width)
325{ 342{
@@ -357,10 +374,8 @@ static char *get_line(void)
357 end_reached = 0; 374 end_reached = 0;
358 while (*page != '\n') { 375 while (*page != '\n') {
359 if (*page == '\0') { 376 if (*page == '\0') {
360 if (!end_reached) { 377 end_reached = 1;
361 end_reached = 1; 378 break;
362 break;
363 }
364 } else if (i < MAX_LEN) 379 } else if (i < MAX_LEN)
365 line[i++] = *(page++); 380 line[i++] = *(page++);
366 else { 381 else {
@@ -373,7 +388,7 @@ static char *get_line(void)
373 if (i <= MAX_LEN) 388 if (i <= MAX_LEN)
374 line[i] = '\0'; 389 line[i] = '\0';
375 if (!end_reached) 390 if (!end_reached)
376 page++; /* move pass '\n' */ 391 page++; /* move past '\n' */
377 392
378 return line; 393 return line;
379} 394}
diff --git a/scripts/kconfig/lxdialog/util.c b/scripts/kconfig/lxdialog/util.c
index f2375ad7ebc9..109d53117d22 100644
--- a/scripts/kconfig/lxdialog/util.c
+++ b/scripts/kconfig/lxdialog/util.c
@@ -23,6 +23,9 @@
23 23
24#include "dialog.h" 24#include "dialog.h"
25 25
26/* Needed in signal handler in mconf.c */
27int saved_x, saved_y;
28
26struct dialog_info dlg; 29struct dialog_info dlg;
27 30
28static void set_mono_theme(void) 31static void set_mono_theme(void)
@@ -273,6 +276,10 @@ int init_dialog(const char *backtitle)
273 int height, width; 276 int height, width;
274 277
275 initscr(); /* Init curses */ 278 initscr(); /* Init curses */
279
280 /* Get current cursor position for signal handler in mconf.c */
281 getyx(stdscr, saved_y, saved_x);
282
276 getmaxyx(stdscr, height, width); 283 getmaxyx(stdscr, height, width);
277 if (height < 19 || width < 80) { 284 if (height < 19 || width < 80) {
278 endwin(); 285 endwin();
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index f584a281bb4c..48f67448af7b 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -236,16 +236,19 @@ search_help[] = N_(
236 "Result:\n" 236 "Result:\n"
237 "-----------------------------------------------------------------\n" 237 "-----------------------------------------------------------------\n"
238 "Symbol: FOO [=m]\n" 238 "Symbol: FOO [=m]\n"
239 "Type : tristate\n"
239 "Prompt: Foo bus is used to drive the bar HW\n" 240 "Prompt: Foo bus is used to drive the bar HW\n"
240 "Defined at drivers/pci/Kconfig:47\n" 241 " Defined at drivers/pci/Kconfig:47\n"
241 "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" 242 " Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
242 "Location:\n" 243 " Location:\n"
243 " -> Bus options (PCI, PCMCIA, EISA, ISA)\n" 244 " -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
244 " -> PCI support (PCI [=y])\n" 245 " -> PCI support (PCI [=y])\n"
245 " -> PCI access mode (<choice> [=y])\n" 246 "(1) -> PCI access mode (<choice> [=y])\n"
246 "Selects: LIBCRC32\n" 247 " Selects: LIBCRC32\n"
247 "Selected by: BAR\n" 248 " Selected by: BAR\n"
248 "-----------------------------------------------------------------\n" 249 "-----------------------------------------------------------------\n"
250 "o The line 'Type:' shows the type of the configuration option for\n"
251 " this symbol (boolean, tristate, string, ...)\n"
249 "o The line 'Prompt:' shows the text used in the menu structure for\n" 252 "o The line 'Prompt:' shows the text used in the menu structure for\n"
250 " this symbol\n" 253 " this symbol\n"
251 "o The 'Defined at' line tell at what file / line number the symbol\n" 254 "o The 'Defined at' line tell at what file / line number the symbol\n"
@@ -254,8 +257,12 @@ search_help[] = N_(
254 " this symbol to be visible in the menu (selectable)\n" 257 " this symbol to be visible in the menu (selectable)\n"
255 "o The 'Location:' lines tell where in the menu structure this symbol\n" 258 "o The 'Location:' lines tell where in the menu structure this symbol\n"
256 " is located\n" 259 " is located\n"
257 " A location followed by a [=y] indicate that this is a selectable\n" 260 " A location followed by a [=y] indicates that this is a\n"
258 " menu item - and current value is displayed inside brackets.\n" 261 " selectable menu item - and the current value is displayed inside\n"
262 " brackets.\n"
263 " Press the key in the (#) prefix to jump directly to that\n"
264 " location. You will be returned to the current search results\n"
265 " after exiting this new menu.\n"
259 "o The 'Selects:' line tell what symbol will be automatically\n" 266 "o The 'Selects:' line tell what symbol will be automatically\n"
260 " selected if this symbol is selected (y or m)\n" 267 " selected if this symbol is selected (y or m)\n"
261 "o The 'Selected by' line tell what symbol has selected this symbol\n" 268 "o The 'Selected by' line tell what symbol has selected this symbol\n"
@@ -273,13 +280,15 @@ static struct menu *current_menu;
273static int child_count; 280static int child_count;
274static int single_menu_mode; 281static int single_menu_mode;
275static int show_all_options; 282static int show_all_options;
276static int saved_x, saved_y;
277 283
278static void conf(struct menu *menu); 284static void conf(struct menu *menu, struct menu *active_menu);
279static void conf_choice(struct menu *menu); 285static void conf_choice(struct menu *menu);
280static void conf_string(struct menu *menu); 286static void conf_string(struct menu *menu);
281static void conf_load(void); 287static void conf_load(void);
282static void conf_save(void); 288static void conf_save(void);
289static int show_textbox_ext(const char *title, char *text, int r, int c,
290 int *keys, int *vscroll, int *hscroll,
291 update_text_fn update_text, void *data);
283static void show_textbox(const char *title, const char *text, int r, int c); 292static void show_textbox(const char *title, const char *text, int r, int c);
284static void show_helptext(const char *title, const char *text); 293static void show_helptext(const char *title, const char *text);
285static void show_help(struct menu *menu); 294static void show_help(struct menu *menu);
@@ -302,12 +311,47 @@ static void set_config_filename(const char *config_filename)
302} 311}
303 312
304 313
314struct search_data {
315 struct jk_head *head;
316 struct menu **targets;
317 int *keys;
318};
319
320static void update_text(char *buf, size_t start, size_t end, void *_data)
321{
322 struct search_data *data = _data;
323 struct jump_key *pos;
324 int k = 0;
325
326 CIRCLEQ_FOREACH(pos, data->head, entries) {
327 if (pos->offset >= start && pos->offset < end) {
328 char header[4];
329
330 if (k < JUMP_NB) {
331 int key = '0' + (pos->index % JUMP_NB) + 1;
332
333 sprintf(header, "(%c)", key);
334 data->keys[k] = key;
335 data->targets[k] = pos->target;
336 k++;
337 } else {
338 sprintf(header, " ");
339 }
340
341 memcpy(buf + pos->offset, header, sizeof(header) - 1);
342 }
343 }
344 data->keys[k] = 0;
345}
346
305static void search_conf(void) 347static void search_conf(void)
306{ 348{
307 struct symbol **sym_arr; 349 struct symbol **sym_arr;
308 struct gstr res; 350 struct gstr res;
309 char *dialog_input; 351 char *dialog_input;
310 int dres; 352 int dres, vscroll = 0, hscroll = 0;
353 bool again;
354
311again: 355again:
312 dialog_clear(); 356 dialog_clear();
313 dres = dialog_inputbox(_("Search Configuration Parameter"), 357 dres = dialog_inputbox(_("Search Configuration Parameter"),
@@ -330,10 +374,30 @@ again:
330 dialog_input += strlen(CONFIG_); 374 dialog_input += strlen(CONFIG_);
331 375
332 sym_arr = sym_re_search(dialog_input); 376 sym_arr = sym_re_search(dialog_input);
333 res = get_relations_str(sym_arr); 377 do {
378 struct jk_head head = CIRCLEQ_HEAD_INITIALIZER(head);
379 struct menu *targets[JUMP_NB];
380 int keys[JUMP_NB + 1], i;
381 struct search_data data = {
382 .head = &head,
383 .targets = targets,
384 .keys = keys,
385 };
386
387 res = get_relations_str(sym_arr, &head);
388 dres = show_textbox_ext(_("Search Results"), (char *)
389 str_get(&res), 0, 0, keys, &vscroll,
390 &hscroll, &update_text, (void *)
391 &data);
392 again = false;
393 for (i = 0; i < JUMP_NB && keys[i]; i++)
394 if (dres == keys[i]) {
395 conf(targets[i]->parent, targets[i]);
396 again = true;
397 }
398 str_free(&res);
399 } while (again);
334 free(sym_arr); 400 free(sym_arr);
335 show_textbox(_("Search Results"), str_get(&res), 0, 0);
336 str_free(&res);
337} 401}
338 402
339static void build_conf(struct menu *menu) 403static void build_conf(struct menu *menu)
@@ -514,12 +578,11 @@ conf_childs:
514 indent -= doint; 578 indent -= doint;
515} 579}
516 580
517static void conf(struct menu *menu) 581static void conf(struct menu *menu, struct menu *active_menu)
518{ 582{
519 struct menu *submenu; 583 struct menu *submenu;
520 const char *prompt = menu_get_prompt(menu); 584 const char *prompt = menu_get_prompt(menu);
521 struct symbol *sym; 585 struct symbol *sym;
522 struct menu *active_menu = NULL;
523 int res; 586 int res;
524 int s_scroll = 0; 587 int s_scroll = 0;
525 588
@@ -562,13 +625,13 @@ static void conf(struct menu *menu)
562 if (single_menu_mode) 625 if (single_menu_mode)
563 submenu->data = (void *) (long) !submenu->data; 626 submenu->data = (void *) (long) !submenu->data;
564 else 627 else
565 conf(submenu); 628 conf(submenu, NULL);
566 break; 629 break;
567 case 't': 630 case 't':
568 if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes) 631 if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
569 conf_choice(submenu); 632 conf_choice(submenu);
570 else if (submenu->prompt->type == P_MENU) 633 else if (submenu->prompt->type == P_MENU)
571 conf(submenu); 634 conf(submenu, NULL);
572 break; 635 break;
573 case 's': 636 case 's':
574 conf_string(submenu); 637 conf_string(submenu);
@@ -607,7 +670,7 @@ static void conf(struct menu *menu)
607 if (item_is_tag('t')) 670 if (item_is_tag('t'))
608 sym_toggle_tristate_value(sym); 671 sym_toggle_tristate_value(sym);
609 else if (item_is_tag('m')) 672 else if (item_is_tag('m'))
610 conf(submenu); 673 conf(submenu, NULL);
611 break; 674 break;
612 case 7: 675 case 7:
613 search_conf(); 676 search_conf();
@@ -619,10 +682,19 @@ static void conf(struct menu *menu)
619 } 682 }
620} 683}
621 684
622static void show_textbox(const char *title, const char *text, int r, int c) 685static int show_textbox_ext(const char *title, char *text, int r, int c, int
686 *keys, int *vscroll, int *hscroll, update_text_fn
687 update_text, void *data)
623{ 688{
624 dialog_clear(); 689 dialog_clear();
625 dialog_textbox(title, text, r, c); 690 return dialog_textbox(title, text, r, c, keys, vscroll, hscroll,
691 update_text, data);
692}
693
694static void show_textbox(const char *title, const char *text, int r, int c)
695{
696 show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL,
697 NULL, NULL);
626} 698}
627 699
628static void show_helptext(const char *title, const char *text) 700static void show_helptext(const char *title, const char *text)
@@ -862,9 +934,6 @@ int main(int ac, char **av)
862 single_menu_mode = 1; 934 single_menu_mode = 1;
863 } 935 }
864 936
865 initscr();
866
867 getyx(stdscr, saved_y, saved_x);
868 if (init_dialog(NULL)) { 937 if (init_dialog(NULL)) {
869 fprintf(stderr, N_("Your display is too small to run Menuconfig!\n")); 938 fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
870 fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n")); 939 fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
@@ -873,7 +942,7 @@ int main(int ac, char **av)
873 942
874 set_config_filename(conf_get_configname()); 943 set_config_filename(conf_get_configname());
875 do { 944 do {
876 conf(&rootmenu); 945 conf(&rootmenu, NULL);
877 res = handle_exit(); 946 res = handle_exit();
878 } while (res == KEY_ESC); 947 } while (res == KEY_ESC);
879 948
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 8c2a97e60faf..a3cade659f89 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -507,10 +507,12 @@ const char *menu_get_help(struct menu *menu)
507 return ""; 507 return "";
508} 508}
509 509
510static void get_prompt_str(struct gstr *r, struct property *prop) 510static void get_prompt_str(struct gstr *r, struct property *prop,
511 struct jk_head *head)
511{ 512{
512 int i, j; 513 int i, j;
513 struct menu *submenu[8], *menu; 514 struct menu *submenu[8], *menu, *location = NULL;
515 struct jump_key *jump;
514 516
515 str_printf(r, _("Prompt: %s\n"), _(prop->text)); 517 str_printf(r, _("Prompt: %s\n"), _(prop->text));
516 str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name, 518 str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name,
@@ -521,13 +523,43 @@ static void get_prompt_str(struct gstr *r, struct property *prop)
521 str_append(r, "\n"); 523 str_append(r, "\n");
522 } 524 }
523 menu = prop->menu->parent; 525 menu = prop->menu->parent;
524 for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) 526 for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
527 bool accessible = menu_is_visible(menu);
528
525 submenu[i++] = menu; 529 submenu[i++] = menu;
530 if (location == NULL && accessible)
531 location = menu;
532 }
533 if (head && location) {
534 jump = malloc(sizeof(struct jump_key));
535
536 if (menu_is_visible(prop->menu)) {
537 /*
538 * There is not enough room to put the hint at the
539 * beginning of the "Prompt" line. Put the hint on the
540 * last "Location" line even when it would belong on
541 * the former.
542 */
543 jump->target = prop->menu;
544 } else
545 jump->target = location;
546
547 if (CIRCLEQ_EMPTY(head))
548 jump->index = 0;
549 else
550 jump->index = CIRCLEQ_LAST(head)->index + 1;
551
552 CIRCLEQ_INSERT_TAIL(head, jump, entries);
553 }
554
526 if (i > 0) { 555 if (i > 0) {
527 str_printf(r, _(" Location:\n")); 556 str_printf(r, _(" Location:\n"));
528 for (j = 4; --i >= 0; j += 2) { 557 for (j = 4; --i >= 0; j += 2) {
529 menu = submenu[i]; 558 menu = submenu[i];
530 str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu))); 559 if (head && location && menu == location)
560 jump->offset = r->len - 1;
561 str_printf(r, "%*c-> %s", j, ' ',
562 _(menu_get_prompt(menu)));
531 if (menu->sym) { 563 if (menu->sym) {
532 str_printf(r, " (%s [=%s])", menu->sym->name ? 564 str_printf(r, " (%s [=%s])", menu->sym->name ?
533 menu->sym->name : _("<choice>"), 565 menu->sym->name : _("<choice>"),
@@ -538,7 +570,10 @@ static void get_prompt_str(struct gstr *r, struct property *prop)
538 } 570 }
539} 571}
540 572
541void get_symbol_str(struct gstr *r, struct symbol *sym) 573/*
574 * head is optional and may be NULL
575 */
576void get_symbol_str(struct gstr *r, struct symbol *sym, struct jk_head *head)
542{ 577{
543 bool hit; 578 bool hit;
544 struct property *prop; 579 struct property *prop;
@@ -557,7 +592,7 @@ void get_symbol_str(struct gstr *r, struct symbol *sym)
557 } 592 }
558 } 593 }
559 for_all_prompts(sym, prop) 594 for_all_prompts(sym, prop)
560 get_prompt_str(r, prop); 595 get_prompt_str(r, prop, head);
561 hit = false; 596 hit = false;
562 for_all_properties(sym, prop, P_SELECT) { 597 for_all_properties(sym, prop, P_SELECT) {
563 if (!hit) { 598 if (!hit) {
@@ -577,14 +612,14 @@ void get_symbol_str(struct gstr *r, struct symbol *sym)
577 str_append(r, "\n\n"); 612 str_append(r, "\n\n");
578} 613}
579 614
580struct gstr get_relations_str(struct symbol **sym_arr) 615struct gstr get_relations_str(struct symbol **sym_arr, struct jk_head *head)
581{ 616{
582 struct symbol *sym; 617 struct symbol *sym;
583 struct gstr res = str_new(); 618 struct gstr res = str_new();
584 int i; 619 int i;
585 620
586 for (i = 0; sym_arr && (sym = sym_arr[i]); i++) 621 for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
587 get_symbol_str(&res, sym); 622 get_symbol_str(&res, sym, head);
588 if (!i) 623 if (!i)
589 str_append(&res, _("No matches found.\n")); 624 str_append(&res, _("No matches found.\n"));
590 return res; 625 return res;
@@ -603,5 +638,5 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
603 } 638 }
604 str_printf(help, "%s\n", _(help_text)); 639 str_printf(help, "%s\n", _(help_text));
605 if (sym) 640 if (sym)
606 get_symbol_str(help, sym); 641 get_symbol_str(help, sym, NULL);
607} 642}
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
index 1704a8562a5d..87d4b15da951 100644
--- a/scripts/kconfig/nconf.c
+++ b/scripts/kconfig/nconf.c
@@ -721,7 +721,7 @@ again:
721 dialog_input += strlen(CONFIG_); 721 dialog_input += strlen(CONFIG_);
722 722
723 sym_arr = sym_re_search(dialog_input); 723 sym_arr = sym_re_search(dialog_input);
724 res = get_relations_str(sym_arr); 724 res = get_relations_str(sym_arr, NULL);
725 free(sym_arr); 725 free(sym_arr);
726 show_scroll_win(main_window, 726 show_scroll_win(main_window,
727 _("Search Results"), str_get(&res)); 727 _("Search Results"), str_get(&res));