Commit 9a69abf8 authored by Benjamin Poirier's avatar Benjamin Poirier Committed by Yann E. MORIN

menuconfig: Add "breadcrumbs" navigation aid

Displays a trail of the menu entries used to get to the current menu.
Signed-off-by: default avatarBenjamin Poirier <bpoirier@suse.de>
Tested-by: default avatar"Yann E. MORIN" <yann.morin.1998@free.fr>
[yann.morin.1998@free.fr: small, trivial code re-ordering]
Signed-off-by: default avatar"Yann E. MORIN" <yann.morin.1998@free.fr>
parent edb749f4
...@@ -101,4 +101,31 @@ static inline void list_add_tail(struct list_head *_new, struct list_head *head) ...@@ -101,4 +101,31 @@ static inline void list_add_tail(struct list_head *_new, struct list_head *head)
__list_add(_new, head->prev, head); __list_add(_new, head->prev, head);
} }
/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
next->prev = prev;
prev->next = next;
}
#define LIST_POISON1 ((void *) 0x00100100)
#define LIST_POISON2 ((void *) 0x00200200)
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}
#endif #endif
...@@ -106,8 +106,14 @@ struct dialog_color { ...@@ -106,8 +106,14 @@ struct dialog_color {
int hl; /* highlight this item */ int hl; /* highlight this item */
}; };
struct subtitle_list {
struct subtitle_list *next;
const char *text;
};
struct dialog_info { struct dialog_info {
const char *backtitle; const char *backtitle;
struct subtitle_list *subtitles;
struct dialog_color screen; struct dialog_color screen;
struct dialog_color shadow; struct dialog_color shadow;
struct dialog_color dialog; struct dialog_color dialog;
...@@ -196,6 +202,7 @@ int on_key_resize(void); ...@@ -196,6 +202,7 @@ int on_key_resize(void);
int init_dialog(const char *backtitle); int init_dialog(const char *backtitle);
void set_dialog_backtitle(const char *backtitle); void set_dialog_backtitle(const char *backtitle);
void set_dialog_subtitles(struct subtitle_list *subtitles);
void end_dialog(int x, int y); void end_dialog(int x, int y);
void attr_clear(WINDOW * win, int height, int width, chtype attr); void attr_clear(WINDOW * win, int height, int width, chtype attr);
void dialog_clear(void); void dialog_clear(void);
......
...@@ -257,12 +257,48 @@ void dialog_clear(void) ...@@ -257,12 +257,48 @@ void dialog_clear(void)
attr_clear(stdscr, LINES, COLS, dlg.screen.atr); attr_clear(stdscr, LINES, COLS, dlg.screen.atr);
/* Display background title if it exists ... - SLH */ /* Display background title if it exists ... - SLH */
if (dlg.backtitle != NULL) { if (dlg.backtitle != NULL) {
int i; int i, len = 0, skip = 0;
struct subtitle_list *pos;
wattrset(stdscr, dlg.screen.atr); wattrset(stdscr, dlg.screen.atr);
mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle); mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle);
for (pos = dlg.subtitles; pos != NULL; pos = pos->next) {
/* 3 is for the arrow and spaces */
len += strlen(pos->text) + 3;
}
wmove(stdscr, 1, 1); wmove(stdscr, 1, 1);
for (i = 1; i < COLS - 1; i++) if (len > COLS - 2) {
const char *ellipsis = "[...] ";
waddstr(stdscr, ellipsis);
skip = len - (COLS - 2 - strlen(ellipsis));
}
for (pos = dlg.subtitles; pos != NULL; pos = pos->next) {
if (skip == 0)
waddch(stdscr, ACS_RARROW);
else
skip--;
if (skip == 0)
waddch(stdscr, ' ');
else
skip--;
if (skip < strlen(pos->text)) {
waddstr(stdscr, pos->text + skip);
skip = 0;
} else
skip -= strlen(pos->text);
if (skip == 0)
waddch(stdscr, ' ');
else
skip--;
}
for (i = len + 1; i < COLS - 1; i++)
waddch(stdscr, ACS_HLINE); waddch(stdscr, ACS_HLINE);
} }
wnoutrefresh(stdscr); wnoutrefresh(stdscr);
...@@ -302,6 +338,11 @@ void set_dialog_backtitle(const char *backtitle) ...@@ -302,6 +338,11 @@ void set_dialog_backtitle(const char *backtitle)
dlg.backtitle = backtitle; dlg.backtitle = backtitle;
} }
void set_dialog_subtitles(struct subtitle_list *subtitles)
{
dlg.subtitles = subtitles;
}
/* /*
* End using dialog functions. * End using dialog functions.
*/ */
......
...@@ -311,6 +311,50 @@ static void set_config_filename(const char *config_filename) ...@@ -311,6 +311,50 @@ static void set_config_filename(const char *config_filename)
filename[sizeof(filename)-1] = '\0'; filename[sizeof(filename)-1] = '\0';
} }
struct subtitle_part {
struct list_head entries;
const char *text;
};
static LIST_HEAD(trail);
static struct subtitle_list *subtitles;
static void set_subtitle(void)
{
struct subtitle_part *sp;
struct subtitle_list *pos, *tmp;
for (pos = subtitles; pos != NULL; pos = tmp) {
tmp = pos->next;
free(pos);
}
subtitles = NULL;
list_for_each_entry(sp, &trail, entries) {
if (sp->text) {
if (pos) {
pos->next = xcalloc(sizeof(*pos), 1);
pos = pos->next;
} else {
subtitles = pos = xcalloc(sizeof(*pos), 1);
}
pos->text = sp->text;
}
}
set_dialog_subtitles(subtitles);
}
static void reset_subtitle(void)
{
struct subtitle_list *pos, *tmp;
for (pos = subtitles; pos != NULL; pos = tmp) {
tmp = pos->next;
free(pos);
}
subtitles = NULL;
set_dialog_subtitles(subtitles);
}
struct search_data { struct search_data {
struct list_head *head; struct list_head *head;
...@@ -353,6 +397,8 @@ static void search_conf(void) ...@@ -353,6 +397,8 @@ static void search_conf(void)
char *dialog_input; char *dialog_input;
int dres, vscroll = 0, hscroll = 0; int dres, vscroll = 0, hscroll = 0;
bool again; bool again;
struct gstr sttext;
struct subtitle_part stpart;
title = str_new(); title = str_new();
str_printf( &title, _("Enter %s (sub)string to search for " str_printf( &title, _("Enter %s (sub)string to search for "
...@@ -379,6 +425,11 @@ static void search_conf(void) ...@@ -379,6 +425,11 @@ static void search_conf(void)
if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0) if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
dialog_input += strlen(CONFIG_); dialog_input += strlen(CONFIG_);
sttext = str_new();
str_printf(&sttext, "Search (%s)", dialog_input_result);
stpart.text = str_get(&sttext);
list_add_tail(&stpart.entries, &trail);
sym_arr = sym_re_search(dialog_input); sym_arr = sym_re_search(dialog_input);
do { do {
LIST_HEAD(head); LIST_HEAD(head);
...@@ -392,6 +443,7 @@ static void search_conf(void) ...@@ -392,6 +443,7 @@ static void search_conf(void)
struct jump_key *pos, *tmp; struct jump_key *pos, *tmp;
res = get_relations_str(sym_arr, &head); res = get_relations_str(sym_arr, &head);
set_subtitle();
dres = show_textbox_ext(_("Search Results"), (char *) dres = show_textbox_ext(_("Search Results"), (char *)
str_get(&res), 0, 0, keys, &vscroll, str_get(&res), 0, 0, keys, &vscroll,
&hscroll, &update_text, (void *) &hscroll, &update_text, (void *)
...@@ -408,6 +460,8 @@ static void search_conf(void) ...@@ -408,6 +460,8 @@ static void search_conf(void)
} while (again); } while (again);
free(sym_arr); free(sym_arr);
str_free(&title); str_free(&title);
list_del(trail.prev);
str_free(&sttext);
} }
static void build_conf(struct menu *menu) static void build_conf(struct menu *menu)
...@@ -592,16 +646,24 @@ static void conf(struct menu *menu, struct menu *active_menu) ...@@ -592,16 +646,24 @@ static void conf(struct menu *menu, struct menu *active_menu)
{ {
struct menu *submenu; struct menu *submenu;
const char *prompt = menu_get_prompt(menu); const char *prompt = menu_get_prompt(menu);
struct subtitle_part stpart;
struct symbol *sym; struct symbol *sym;
int res; int res;
int s_scroll = 0; int s_scroll = 0;
if (menu != &rootmenu)
stpart.text = menu_get_prompt(menu);
else
stpart.text = NULL;
list_add_tail(&stpart.entries, &trail);
while (1) { while (1) {
item_reset(); item_reset();
current_menu = menu; current_menu = menu;
build_conf(menu); build_conf(menu);
if (!child_count) if (!child_count)
break; break;
set_subtitle();
dialog_clear(); dialog_clear();
res = dialog_menu(prompt ? _(prompt) : _("Main Menu"), res = dialog_menu(prompt ? _(prompt) : _("Main Menu"),
_(menu_instructions), _(menu_instructions),
...@@ -643,13 +705,17 @@ static void conf(struct menu *menu, struct menu *active_menu) ...@@ -643,13 +705,17 @@ static void conf(struct menu *menu, struct menu *active_menu)
case 2: case 2:
if (sym) if (sym)
show_help(submenu); show_help(submenu);
else else {
reset_subtitle();
show_helptext(_("README"), _(mconf_readme)); show_helptext(_("README"), _(mconf_readme));
}
break; break;
case 3: case 3:
reset_subtitle();
conf_save(); conf_save();
break; break;
case 4: case 4:
reset_subtitle();
conf_load(); conf_load();
break; break;
case 5: case 5:
...@@ -682,6 +748,8 @@ static void conf(struct menu *menu, struct menu *active_menu) ...@@ -682,6 +748,8 @@ static void conf(struct menu *menu, struct menu *active_menu)
break; break;
} }
} }
list_del(trail.prev);
} }
static int show_textbox_ext(const char *title, char *text, int r, int c, int static int show_textbox_ext(const char *title, char *text, int r, int c, int
...@@ -884,6 +952,7 @@ static int handle_exit(void) ...@@ -884,6 +952,7 @@ static int handle_exit(void)
int res; int res;
save_and_exit = 1; save_and_exit = 1;
reset_subtitle();
dialog_clear(); dialog_clear();
if (conf_get_changed()) if (conf_get_changed())
res = dialog_yesno(NULL, res = dialog_yesno(NULL,
......
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