menuconfig: Assign jump keys per-page instead of globally
authorBenjamin Poirier <bpoirier@suse.de>
Thu, 23 Aug 2012 18:55:08 +0000 (14:55 -0400)
committerMichal Marek <mmarek@suse.cz>
Thu, 27 Sep 2012 16:09:24 +0000 (18:09 +0200)
At the moment, keys 1-9 are assigned to the first 9 search results. This patch
makes them assigned to the first 9 results per-page instead. We are much less
likely to run out of keys that way.

Signed-off-by: Benjamin Poirier <bpoirier@suse.de>
Signed-off-by: Michal Marek <mmarek@suse.cz>
scripts/kconfig/expr.h
scripts/kconfig/lkc_proto.h
scripts/kconfig/lxdialog/dialog.h
scripts/kconfig/lxdialog/textbox.c
scripts/kconfig/mconf.c
scripts/kconfig/menu.c

index 52f4246bd34da608b2b90a7de56270af0b27aab3..bd2e098955532a26a3935e44ad58283598cbf673 100644 (file)
@@ -12,6 +12,7 @@ extern "C" {
 
 #include <assert.h>
 #include <stdio.h>
+#include <sys/queue.h>
 #ifndef __cplusplus
 #include <stdbool.h>
 #endif
@@ -173,6 +174,14 @@ struct menu {
 #define MENU_CHANGED           0x0001
 #define MENU_ROOT              0x0002
 
+struct jump_key {
+       CIRCLEQ_ENTRY(jump_key) entries;
+       size_t offset;
+       struct menu *target;
+       int index;
+};
+CIRCLEQ_HEAD(jk_head, jump_key);
+
 #define JUMP_NB                        9
 
 extern struct file *file_list;
index 946c2cb367f9fe1669ecec7767e778e763d7996c..1d1c08537f1e59b2cab76bd88437489fcbea393b 100644 (file)
@@ -21,10 +21,10 @@ P(menu_get_root_menu,struct menu *,(struct menu *menu));
 P(menu_get_parent_menu,struct menu *,(struct menu *menu));
 P(menu_has_help,bool,(struct menu *menu));
 P(menu_get_help,const char *,(struct menu *menu));
-P(get_symbol_str, int, (struct gstr *r, struct symbol *sym, struct menu
-                       **jumps, int jump_nb));
-P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct menu
-                                  **jumps));
+P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct jk_head
+                        *head));
+P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct jk_head
+                                  *head));
 P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));
 
 /* symbol.c */
index 2a01cdfae5a847e60cb616e9af502b9ae1d76e52..ee17a5264d5b456c0672a77b06964bfc1ccd29d7 100644 (file)
@@ -210,8 +210,13 @@ int first_alpha(const char *string, const char *exempt);
 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 width, int pause);
-int dialog_textbox(const char *title, const char *file, int height, int width,
-                  int *keys, int *_vscroll, int *_hscroll);
+
+
+typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void
+                              *_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,
                const void *selected, int *s_scroll);
 int dialog_checklist(const char *title, const char *prompt, int height,
index 3b3c5c470bf864ac7ad8c4afcd9ba2115720248f..a48bb93e09073f05ea14786fea9370202f5039f9 100644 (file)
 #include "dialog.h"
 
 static void back_lines(int n);
-static void print_page(WINDOW * win, int height, int width);
-static void print_line(WINDOW * win, int row, int width);
+static void print_page(WINDOW *win, int height, int width, update_text_fn
+                      update_text, void *data);
+static void print_line(WINDOW *win, int row, int width);
 static char *get_line(void);
 static void print_position(WINDOW * win);
 
 static int hscroll;
 static int begin_reached, end_reached, page_length;
-static const char *buf;
-static const char *page;
+static char *buf;
+static char *page;
 
 /*
  * refresh window content
  */
 static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
-                                                         int cur_y, int cur_x)
+                            int cur_y, int cur_x, update_text_fn update_text,
+                            void *data)
 {
-       print_page(box, boxh, boxw);
+       print_page(box, boxh, boxw, update_text, data);
        print_position(dialog);
        wmove(dialog, cur_y, cur_x);    /* Restore cursor position */
        wrefresh(dialog);
@@ -49,9 +51,11 @@ static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
  * Display text from a file in a dialog box.
  *
  * 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, const char *tbuf, int initial_height,
-                  int initial_width, int *keys, int *_vscroll, int *_hscroll)
+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 i, x, y, cur_x, cur_y, key = 0;
        int height, width, boxh, boxw;
@@ -131,7 +135,8 @@ do_resize:
 
        /* Print first page of text */
        attr_clear(box, boxh, boxw, dlg.dialog.atr);
-       refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
+       refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text,
+                        data);
 
        while (!done) {
                key = wgetch(dialog);
@@ -150,7 +155,8 @@ do_resize:
                                begin_reached = 1;
                                page = buf;
                                refresh_text_box(dialog, box, boxh, boxw,
-                                                cur_y, cur_x);
+                                                cur_y, cur_x, update_text,
+                                                data);
                        }
                        break;
                case 'G':       /* Last page */
@@ -160,8 +166,8 @@ do_resize:
                        /* point to last char in buf */
                        page = buf + strlen(buf);
                        back_lines(boxh);
-                       refresh_text_box(dialog, box, boxh, boxw,
-                                        cur_y, cur_x);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case 'K':       /* Previous line */
                case 'k':
@@ -171,7 +177,7 @@ do_resize:
 
                        back_lines(page_length + 1);
                        refresh_text_box(dialog, box, boxh, boxw, cur_y,
-                                        cur_x);
+                                        cur_x, update_text, data);
                        break;
                case 'B':       /* Previous page */
                case 'b':
@@ -180,8 +186,8 @@ do_resize:
                        if (begin_reached)
                                break;
                        back_lines(page_length + boxh);
-                       refresh_text_box(dialog, box, boxh, boxw,
-                                        cur_y, cur_x);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case 'J':       /* Next line */
                case 'j':
@@ -191,7 +197,7 @@ do_resize:
 
                        back_lines(page_length - 1);
                        refresh_text_box(dialog, box, boxh, boxw, cur_y,
-                                        cur_x);
+                                        cur_x, update_text, data);
                        break;
                case KEY_NPAGE: /* Next page */
                case ' ':
@@ -200,8 +206,8 @@ do_resize:
                                break;
 
                        begin_reached = 0;
-                       refresh_text_box(dialog, box, boxh, boxw,
-                                        cur_y, cur_x);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case '0':       /* Beginning of line */
                case 'H':       /* Scroll left */
@@ -216,8 +222,8 @@ do_resize:
                                hscroll--;
                        /* Reprint current page to scroll horizontally */
                        back_lines(page_length);
-                       refresh_text_box(dialog, box, boxh, boxw,
-                                        cur_y, cur_x);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case 'L':       /* Scroll right */
                case 'l':
@@ -227,8 +233,8 @@ do_resize:
                        hscroll++;
                        /* Reprint current page to scroll horizontally */
                        back_lines(page_length);
-                       refresh_text_box(dialog, box, boxh, boxw,
-                                        cur_y, cur_x);
+                       refresh_text_box(dialog, box, boxh, boxw, cur_y,
+                                        cur_x, update_text, data);
                        break;
                case KEY_ESC:
                        if (on_key_esc(dialog) == KEY_ESC)
@@ -301,12 +307,23 @@ static void back_lines(int n)
 }
 
 /*
- * Print a new page of text. Called by dialog_textbox().
+ * Print a new page of text.
  */
-static void print_page(WINDOW * win, int height, int width)
+static void print_page(WINDOW *win, int height, int width, update_text_fn
+                      update_text, void *data)
 {
        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;
        for (i = 0; i < height; i++) {
                print_line(win, i, width);
@@ -319,7 +336,7 @@ static void print_page(WINDOW * win, int height, int width)
 }
 
 /*
- * Print a new line of text. Called by dialog_textbox() and print_page().
+ * Print a new line of text.
  */
 static void print_line(WINDOW * win, int row, int width)
 {
index 6f409745b3736b2e0cccda9c2bc83176b1e2f1fb..48f67448af7b67cf6c8df7394702a65767891992 100644 (file)
@@ -286,8 +286,9 @@ static void conf_choice(struct menu *menu);
 static void conf_string(struct menu *menu);
 static void conf_load(void);
 static void conf_save(void);
-static int show_textbox_ext(const char *title, const char *text, int r, int c,
-                           int *keys, int *vscroll, int *hscroll);
+static int show_textbox_ext(const char *title, char *text, int r, int c,
+                           int *keys, int *vscroll, int *hscroll,
+                           update_text_fn update_text, void *data);
 static void show_textbox(const char *title, const char *text, int r, int c);
 static void show_helptext(const char *title, const char *text);
 static void show_help(struct menu *menu);
@@ -310,6 +311,39 @@ static void set_config_filename(const char *config_filename)
 }
 
 
+struct search_data {
+       struct jk_head *head;
+       struct menu **targets;
+       int *keys;
+};
+
+static void update_text(char *buf, size_t start, size_t end, void *_data)
+{
+       struct search_data *data = _data;
+       struct jump_key *pos;
+       int k = 0;
+
+       CIRCLEQ_FOREACH(pos, data->head, entries) {
+               if (pos->offset >= start && pos->offset < end) {
+                       char header[4];
+
+                       if (k < JUMP_NB) {
+                               int key = '0' + (pos->index % JUMP_NB) + 1;
+
+                               sprintf(header, "(%c)", key);
+                               data->keys[k] = key;
+                               data->targets[k] = pos->target;
+                               k++;
+                       } else {
+                               sprintf(header, "   ");
+                       }
+
+                       memcpy(buf + pos->offset, header, sizeof(header) - 1);
+               }
+       }
+       data->keys[k] = 0;
+}
+
 static void search_conf(void)
 {
        struct symbol **sym_arr;
@@ -341,18 +375,24 @@ again:
 
        sym_arr = sym_re_search(dialog_input);
        do {
-               struct menu *jumps[JUMP_NB] = {0};
-               int keys[JUMP_NB + 1] = {0}, i;
-
-               res = get_relations_str(sym_arr, jumps);
-               for (i = 0; i < JUMP_NB && jumps[i]; i++)
-                       keys[i] = '1' + i;
-               dres = show_textbox_ext(_("Search Results"), str_get(&res), 0,
-                                       0, keys, &vscroll, &hscroll);
+               struct jk_head head = CIRCLEQ_HEAD_INITIALIZER(head);
+               struct menu *targets[JUMP_NB];
+               int keys[JUMP_NB + 1], i;
+               struct search_data data = {
+                       .head = &head,
+                       .targets = targets,
+                       .keys = keys,
+               };
+
+               res = get_relations_str(sym_arr, &head);
+               dres = show_textbox_ext(_("Search Results"), (char *)
+                                       str_get(&res), 0, 0, keys, &vscroll,
+                                       &hscroll, &update_text, (void *)
+                                       &data);
                again = false;
-               for (i = 0; i < JUMP_NB && jumps[i]; i++)
+               for (i = 0; i < JUMP_NB && keys[i]; i++)
                        if (dres == keys[i]) {
-                               conf(jumps[i]->parent, jumps[i]);
+                               conf(targets[i]->parent, targets[i]);
                                again = true;
                        }
                str_free(&res);
@@ -642,16 +682,19 @@ static void conf(struct menu *menu, struct menu *active_menu)
        }
 }
 
-static int show_textbox_ext(const char *title, const char *text, int r, int c,
-                           int *keys, int *vscroll, int *hscroll)
+static int show_textbox_ext(const char *title, char *text, int r, int c, int
+                           *keys, int *vscroll, int *hscroll, update_text_fn
+                           update_text, void *data)
 {
        dialog_clear();
-       return dialog_textbox(title, text, r, c, keys, vscroll, hscroll);
+       return dialog_textbox(title, text, r, c, keys, vscroll, hscroll,
+                             update_text, data);
 }
 
 static void show_textbox(const char *title, const char *text, int r, int c)
 {
-       show_textbox_ext(title, text, r, c, (int []) {0}, NULL, NULL);
+       show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL,
+                        NULL, NULL);
 }
 
 static void show_helptext(const char *title, const char *text)
index a5241859326a90cd1828734121c465bd01704b17..a3cade659f89cb5f67828b797ae49b9311bf1d98 100644 (file)
@@ -507,12 +507,12 @@ const char *menu_get_help(struct menu *menu)
                return "";
 }
 
-static int get_prompt_str(struct gstr *r, struct property *prop, struct menu
-                         **jumps, int jump_nb)
+static void get_prompt_str(struct gstr *r, struct property *prop,
+                          struct jk_head *head)
 {
        int i, j;
-       char header[4];
        struct menu *submenu[8], *menu, *location = NULL;
+       struct jump_key *jump;
 
        str_printf(r, _("Prompt: %s\n"), _(prop->text));
        str_printf(r, _("  Defined at %s:%d\n"), prop->menu->file->name,
@@ -530,7 +530,9 @@ static int get_prompt_str(struct gstr *r, struct property *prop, struct menu
                if (location == NULL && accessible)
                        location = menu;
        }
-       if (jumps && jump_nb < JUMP_NB && location) {
+       if (head && location) {
+               jump = malloc(sizeof(struct jump_key));
+
                if (menu_is_visible(prop->menu)) {
                        /*
                         * There is not enough room to put the hint at the
@@ -538,19 +540,26 @@ static int get_prompt_str(struct gstr *r, struct property *prop, struct menu
                         * last "Location" line even when it would belong on
                         * the former.
                         */
-                       jumps[jump_nb] = prop->menu;
+                       jump->target = prop->menu;
                } else
-                       jumps[jump_nb] = location;
-               snprintf(header, 4, "(%d)", jump_nb + 1);
-       } else
-               location = NULL;
+                       jump->target = location;
+
+               if (CIRCLEQ_EMPTY(head))
+                       jump->index = 0;
+               else
+                       jump->index = CIRCLEQ_LAST(head)->index + 1;
+
+               CIRCLEQ_INSERT_TAIL(head, jump, entries);
+       }
 
        if (i > 0) {
                str_printf(r, _("  Location:\n"));
-               for (j = 1; --i >= 0; j += 2) {
+               for (j = 4; --i >= 0; j += 2) {
                        menu = submenu[i];
-                       str_printf(r, "%s%*c-> %s", menu == location ? header
-                                  : "   ", j, ' ', _(menu_get_prompt(menu)));
+                       if (head && location && menu == location)
+                               jump->offset = r->len - 1;
+                       str_printf(r, "%*c-> %s", j, ' ',
+                                  _(menu_get_prompt(menu)));
                        if (menu->sym) {
                                str_printf(r, " (%s [=%s])", menu->sym->name ?
                                        menu->sym->name : _("<choice>"),
@@ -559,20 +568,15 @@ static int get_prompt_str(struct gstr *r, struct property *prop, struct menu
                        str_append(r, "\n");
                }
        }
-
-       return location ? 1 : 0;
 }
 
 /*
- * jumps is optional and may be NULL
- * returns the number of jumps inserted
+ * head is optional and may be NULL
  */
-int get_symbol_str(struct gstr *r, struct symbol *sym, struct menu **jumps,
-                  int jump_nb)
+void get_symbol_str(struct gstr *r, struct symbol *sym, struct jk_head *head)
 {
        bool hit;
        struct property *prop;
-       int i = 0;
 
        if (sym && sym->name) {
                str_printf(r, "Symbol: %s [=%s]\n", sym->name,
@@ -588,7 +592,7 @@ int get_symbol_str(struct gstr *r, struct symbol *sym, struct menu **jumps,
                }
        }
        for_all_prompts(sym, prop)
-               i += get_prompt_str(r, prop, jumps, jump_nb + i);
+               get_prompt_str(r, prop, head);
        hit = false;
        for_all_properties(sym, prop, P_SELECT) {
                if (!hit) {
@@ -606,18 +610,16 @@ int get_symbol_str(struct gstr *r, struct symbol *sym, struct menu **jumps,
                str_append(r, "\n");
        }
        str_append(r, "\n\n");
-
-       return i;
 }
 
-struct gstr get_relations_str(struct symbol **sym_arr, struct menu **jumps)
+struct gstr get_relations_str(struct symbol **sym_arr, struct jk_head *head)
 {
        struct symbol *sym;
        struct gstr res = str_new();
-       int i, jump_nb = 0;
+       int i;
 
        for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
-               jump_nb += get_symbol_str(&res, sym, jumps, jump_nb);
+               get_symbol_str(&res, sym, head);
        if (!i)
                str_append(&res, _("No matches found.\n"));
        return res;
@@ -636,5 +638,5 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
        }
        str_printf(help, "%s\n", _(help_text));
        if (sym)
-               get_symbol_str(help, sym, NULL, 0);
+               get_symbol_str(help, sym, NULL);
 }