Commit e14f1242 authored by Masahiro Yamada's avatar Masahiro Yamada

kconfig: menuconfig: simplify global jump key assignment

Commit 95ac9b3b ("menuconfig: Assign jump keys per-page instead
of globally") injected a lot of hacks to the bottom of the textbox
infrastructure.

I reverted many of them without changing the behavior. (almost)
Now, the key markers are inserted when constructing the search result
instead of updating the text buffer on-the-fly.

The buffer passed to the textbox got back to a constant string.
The ugly casts from (const char *) to (char *) went away.

A disadvantage is that the same key numbers might be displayed multiple
times in the dialog if you use a huge window (but I believe it is
unlikely to happen).
Signed-off-by: default avatarMasahiro Yamada <masahiroy@kernel.org>
Reviewed-by: default avatarJesse Taube <Mr.Bossman075@gmail.com>
parent 481461f5
...@@ -101,6 +101,7 @@ const char *menu_get_prompt(struct menu *menu); ...@@ -101,6 +101,7 @@ const char *menu_get_prompt(struct menu *menu);
struct menu *menu_get_parent_menu(struct menu *menu); struct menu *menu_get_parent_menu(struct menu *menu);
bool menu_has_help(struct menu *menu); bool menu_has_help(struct menu *menu);
const char *menu_get_help(struct menu *menu); const char *menu_get_help(struct menu *menu);
int get_jump_key_char(void);
struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head); struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head);
void menu_get_ext_help(struct menu *menu, struct gstr *help); void menu_get_ext_help(struct menu *menu, struct gstr *help);
......
...@@ -196,13 +196,9 @@ int first_alpha(const char *string, const char *exempt); ...@@ -196,13 +196,9 @@ int first_alpha(const char *string, const char *exempt);
int dialog_yesno(const char *title, const char *prompt, int height, int width); int dialog_yesno(const char *title, const char *prompt, int height, int width);
int dialog_msgbox(const char *title, const char *prompt, int height, int dialog_msgbox(const char *title, const char *prompt, int height,
int width, int pause); int width, int pause);
int dialog_textbox(const char *title, const char *tbuf, int initial_height,
int initial_width, int *_vscroll, int *_hscroll,
typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void int (*extra_key_cb)(int, size_t, size_t, void *), void *data);
*_data);
int dialog_textbox(const char *title, char *tbuf, int initial_height,
int initial_width, int *keys, int *_vscroll, int *_hscroll,
update_text_fn update_text, void *data);
int dialog_menu(const char *title, const char *prompt, int dialog_menu(const char *title, const char *prompt,
const void *selected, int *s_scroll); const void *selected, int *s_scroll);
int dialog_checklist(const char *title, const char *prompt, int height, int dialog_checklist(const char *title, const char *prompt, int height,
......
...@@ -10,8 +10,8 @@ ...@@ -10,8 +10,8 @@
static int hscroll; static int hscroll;
static int begin_reached, end_reached, page_length; static int begin_reached, end_reached, page_length;
static char *buf; static const char *buf, *page;
static char *page; static size_t start, end;
/* /*
* Go back 'n' lines in text. Called by dialog_textbox(). * Go back 'n' lines in text. Called by dialog_textbox().
...@@ -98,21 +98,10 @@ static void print_line(WINDOW *win, int row, int width) ...@@ -98,21 +98,10 @@ static void print_line(WINDOW *win, int row, int width)
/* /*
* Print a new page of text. * Print a new page of text.
*/ */
static void print_page(WINDOW *win, int height, int width, update_text_fn static void print_page(WINDOW *win, int height, int width)
update_text, void *data)
{ {
int i, passed_end = 0; int i, passed_end = 0;
if (update_text) {
char *end;
for (i = 0; i < height; i++)
get_line();
end = page;
back_lines(height);
update_text(buf, page - buf, end - buf, data);
}
page_length = 0; page_length = 0;
for (i = 0; i < height; i++) { for (i = 0; i < height; i++) {
print_line(win, i, width); print_line(win, i, width);
...@@ -142,24 +131,26 @@ static void print_position(WINDOW *win) ...@@ -142,24 +131,26 @@ static void print_position(WINDOW *win)
* refresh window content * refresh window content
*/ */
static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw, static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
int cur_y, int cur_x, update_text_fn update_text, int cur_y, int cur_x)
void *data)
{ {
print_page(box, boxh, boxw, update_text, data); start = page - buf;
print_page(box, boxh, boxw);
print_position(dialog); print_position(dialog);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */ wmove(dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh(dialog); wrefresh(dialog);
end = page - buf;
} }
/* /*
* Display text from a file in a dialog box. * Display text from a file in a dialog box.
* *
* keys is a null-terminated array * keys is a null-terminated array
* update_text() may not add or remove any '\n' or '\0' in tbuf
*/ */
int dialog_textbox(const char *title, char *tbuf, int initial_height, int dialog_textbox(const char *title, const char *tbuf, int initial_height,
int initial_width, int *keys, int *_vscroll, int *_hscroll, int initial_width, int *_vscroll, int *_hscroll,
update_text_fn update_text, void *data) int (*extra_key_cb)(int, size_t, size_t, void *), void *data)
{ {
int i, x, y, cur_x, cur_y, key = 0; int i, x, y, cur_x, cur_y, key = 0;
int height, width, boxh, boxw; int height, width, boxh, boxw;
...@@ -239,8 +230,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height, ...@@ -239,8 +230,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height,
/* Print first page of text */ /* Print first page of text */
attr_clear(box, boxh, boxw, dlg.dialog.atr); attr_clear(box, boxh, boxw, dlg.dialog.atr);
refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text, refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
data);
while (!done) { while (!done) {
key = wgetch(dialog); key = wgetch(dialog);
...@@ -259,8 +249,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height, ...@@ -259,8 +249,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height,
begin_reached = 1; begin_reached = 1;
page = buf; page = buf;
refresh_text_box(dialog, box, boxh, boxw, refresh_text_box(dialog, box, boxh, boxw,
cur_y, cur_x, update_text, cur_y, cur_x);
data);
} }
break; break;
case 'G': /* Last page */ case 'G': /* Last page */
...@@ -270,8 +259,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height, ...@@ -270,8 +259,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height,
/* point to last char in buf */ /* point to last char in buf */
page = buf + strlen(buf); page = buf + strlen(buf);
back_lines(boxh); back_lines(boxh);
refresh_text_box(dialog, box, boxh, boxw, cur_y, refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
cur_x, update_text, data);
break; break;
case 'K': /* Previous line */ case 'K': /* Previous line */
case 'k': case 'k':
...@@ -280,8 +268,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height, ...@@ -280,8 +268,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height,
break; break;
back_lines(page_length + 1); back_lines(page_length + 1);
refresh_text_box(dialog, box, boxh, boxw, cur_y, refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
cur_x, update_text, data);
break; break;
case 'B': /* Previous page */ case 'B': /* Previous page */
case 'b': case 'b':
...@@ -290,8 +277,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height, ...@@ -290,8 +277,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height,
if (begin_reached) if (begin_reached)
break; break;
back_lines(page_length + boxh); back_lines(page_length + boxh);
refresh_text_box(dialog, box, boxh, boxw, cur_y, refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
cur_x, update_text, data);
break; break;
case 'J': /* Next line */ case 'J': /* Next line */
case 'j': case 'j':
...@@ -300,8 +286,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height, ...@@ -300,8 +286,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height,
break; break;
back_lines(page_length - 1); back_lines(page_length - 1);
refresh_text_box(dialog, box, boxh, boxw, cur_y, refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
cur_x, update_text, data);
break; break;
case KEY_NPAGE: /* Next page */ case KEY_NPAGE: /* Next page */
case ' ': case ' ':
...@@ -310,8 +295,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height, ...@@ -310,8 +295,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height,
break; break;
begin_reached = 0; begin_reached = 0;
refresh_text_box(dialog, box, boxh, boxw, cur_y, refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
cur_x, update_text, data);
break; break;
case '0': /* Beginning of line */ case '0': /* Beginning of line */
case 'H': /* Scroll left */ case 'H': /* Scroll left */
...@@ -326,8 +310,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height, ...@@ -326,8 +310,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height,
hscroll--; hscroll--;
/* Reprint current page to scroll horizontally */ /* Reprint current page to scroll horizontally */
back_lines(page_length); back_lines(page_length);
refresh_text_box(dialog, box, boxh, boxw, cur_y, refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
cur_x, update_text, data);
break; break;
case 'L': /* Scroll right */ case 'L': /* Scroll right */
case 'l': case 'l':
...@@ -337,8 +320,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height, ...@@ -337,8 +320,7 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height,
hscroll++; hscroll++;
/* Reprint current page to scroll horizontally */ /* Reprint current page to scroll horizontally */
back_lines(page_length); back_lines(page_length);
refresh_text_box(dialog, box, boxh, boxw, cur_y, refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
cur_x, update_text, data);
break; break;
case KEY_ESC: case KEY_ESC:
if (on_key_esc(dialog) == KEY_ESC) if (on_key_esc(dialog) == KEY_ESC)
...@@ -351,14 +333,12 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height, ...@@ -351,14 +333,12 @@ int dialog_textbox(const char *title, char *tbuf, int initial_height,
on_key_resize(); on_key_resize();
goto do_resize; goto do_resize;
default: default:
for (i = 0; keys[i]; i++) { if (extra_key_cb && extra_key_cb(key, start, end, data)) {
if (key == keys[i]) {
done = true; done = true;
break; break;
} }
} }
} }
}
delwin(box); delwin(box);
delwin(dialog); delwin(dialog);
if (_vscroll) { if (_vscroll) {
......
...@@ -288,6 +288,7 @@ static int single_menu_mode; ...@@ -288,6 +288,7 @@ static int single_menu_mode;
static int show_all_options; static int show_all_options;
static int save_and_exit; static int save_and_exit;
static int silent; static int silent;
static int jump_key_char;
static void conf(struct menu *menu, struct menu *active_menu); static void conf(struct menu *menu, struct menu *active_menu);
...@@ -348,19 +349,19 @@ static void reset_subtitle(void) ...@@ -348,19 +349,19 @@ static void reset_subtitle(void)
set_dialog_subtitles(subtitles); set_dialog_subtitles(subtitles);
} }
static int show_textbox_ext(const char *title, char *text, int r, int c, int static int show_textbox_ext(const char *title, const char *text, int r, int c,
*keys, int *vscroll, int *hscroll, update_text_fn int *vscroll, int *hscroll,
update_text, void *data) int (*extra_key_cb)(int, size_t, size_t, void *),
void *data)
{ {
dialog_clear(); dialog_clear();
return dialog_textbox(title, text, r, c, keys, vscroll, hscroll, return dialog_textbox(title, text, r, c, vscroll, hscroll,
update_text, data); extra_key_cb, data);
} }
static void show_textbox(const char *title, const char *text, int r, int c) static void show_textbox(const char *title, const char *text, int r, int c)
{ {
show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL, show_textbox_ext(title, text, r, c, NULL, NULL, NULL, NULL);
NULL, NULL);
} }
static void show_helptext(const char *title, const char *text) static void show_helptext(const char *title, const char *text)
...@@ -381,35 +382,51 @@ static void show_help(struct menu *menu) ...@@ -381,35 +382,51 @@ static void show_help(struct menu *menu)
struct search_data { struct search_data {
struct list_head *head; struct list_head *head;
struct menu **targets; struct menu *target;
int *keys;
}; };
static void update_text(char *buf, size_t start, size_t end, void *_data) static int next_jump_key(int key)
{
if (key < '1' || key > '9')
return '1';
key++;
if (key > '9')
key = '1';
return key;
}
static int handle_search_keys(int key, size_t start, size_t end, void *_data)
{ {
struct search_data *data = _data; struct search_data *data = _data;
struct jump_key *pos; struct jump_key *pos;
int k = 0;
list_for_each_entry(pos, data->head, entries) { if (key < '1' || key > '9')
if (pos->offset >= start && pos->offset < end) { return 0;
char header[4];
if (k < JUMP_NB) { list_for_each_entry(pos, data->head, entries) {
int key = '0' + (pos->index % JUMP_NB) + 1; if (pos->offset < start)
continue;
sprintf(header, "(%c)", key); if (pos->offset >= end)
data->keys[k] = key; break;
data->targets[k] = pos->target;
k++;
} else {
sprintf(header, " ");
}
memcpy(buf + pos->offset, header, sizeof(header) - 1); if (key == '1' + (pos->index % JUMP_NB)) {
data->target = pos->target;
return 1;
} }
} }
data->keys[k] = 0;
return 0;
}
int get_jump_key_char(void)
{
jump_key_char = next_jump_key(jump_key_char);
return jump_key_char;
} }
static void search_conf(void) static void search_conf(void)
...@@ -456,24 +473,21 @@ static void search_conf(void) ...@@ -456,24 +473,21 @@ static void search_conf(void)
sym_arr = sym_re_search(dialog_input); sym_arr = sym_re_search(dialog_input);
do { do {
LIST_HEAD(head); LIST_HEAD(head);
struct menu *targets[JUMP_NB];
int keys[JUMP_NB + 1], i;
struct search_data data = { struct search_data data = {
.head = &head, .head = &head,
.targets = targets,
.keys = keys,
}; };
struct jump_key *pos, *tmp; struct jump_key *pos, *tmp;
jump_key_char = 0;
res = get_relations_str(sym_arr, &head); res = get_relations_str(sym_arr, &head);
set_subtitle(); set_subtitle();
dres = show_textbox_ext("Search Results", str_get(&res), 0, 0, dres = show_textbox_ext("Search Results", str_get(&res), 0, 0,
keys, &vscroll, &hscroll, &update_text, &vscroll, &hscroll,
&data); handle_search_keys, &data);
again = false; again = false;
for (i = 0; i < JUMP_NB && keys[i]; i++) if (dres >= '1' && dres <= '9') {
if (dres == keys[i]) { assert(data.target != NULL);
conf(targets[i]->parent, targets[i]); conf(data.target->parent, data.target);
again = true; again = true;
} }
str_free(&res); str_free(&res);
......
...@@ -701,6 +701,11 @@ static void get_dep_str(struct gstr *r, struct expr *expr, const char *prefix) ...@@ -701,6 +701,11 @@ static void get_dep_str(struct gstr *r, struct expr *expr, const char *prefix)
} }
} }
int __attribute__((weak)) get_jump_key_char(void)
{
return -1;
}
static void get_prompt_str(struct gstr *r, struct property *prop, static void get_prompt_str(struct gstr *r, struct property *prop,
struct list_head *head) struct list_head *head)
{ {
...@@ -743,11 +748,22 @@ static void get_prompt_str(struct gstr *r, struct property *prop, ...@@ -743,11 +748,22 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
} }
str_printf(r, " Location:\n"); str_printf(r, " Location:\n");
for (j = 4; --i >= 0; j += 2) { for (j = 0; --i >= 0; j++) {
int jk = -1;
int indent = 2 * j + 4;
menu = submenu[i]; menu = submenu[i];
if (jump && menu == location) if (jump && menu == location) {
jump->offset = strlen(r->s); jump->offset = strlen(r->s);
str_printf(r, "%*c-> %s", j, ' ', menu_get_prompt(menu)); jk = get_jump_key_char();
}
if (jk >= 0) {
str_printf(r, "(%c)", jk);
indent -= 3;
}
str_printf(r, "%*c-> %s", indent, ' ', menu_get_prompt(menu));
if (menu->sym) { if (menu->sym) {
str_printf(r, " (%s [=%s])", menu->sym->name ? str_printf(r, " (%s [=%s])", menu->sym->name ?
menu->sym->name : "<choice>", menu->sym->name : "<choice>",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment