Make the menu into a popup window that complements the status prompt. Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@xxxxxxxxx> --- We should probably consider using the high-level menu and panel features from ncurses if we want to do anything more complex. tig.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 115 insertions(+), 2 deletions(-) diff --git a/tig.c b/tig.c index 20a40b9..017b05f 100644 --- a/tig.c +++ b/tig.c @@ -6542,6 +6542,100 @@ utf8_length(const char **start, size_t skip, int *width, size_t max_width, int * return string - *start; } +/* + * Popup management + */ + +struct popup { + WINDOW *win; + int width; + bool hotkeys; + int selected; +}; + +static struct popup menu; + + +static void +menu_popup(void) +{ + wnoutrefresh(menu.win); +} + +static void +menu_popdown(void) +{ + delwin(menu.win); + menu.win = NULL; + redraw_display(FALSE); +} + +static void +menu_create(int height, int width, const char* title, bool hotkeys) +{ + WINDOW *win; + int ymax, xmax, top, left; + enum line_type type = LINE_TITLE_FOCUS; + + getmaxyx(stdscr, ymax, xmax); + top = (ymax - height)/2; + left = (xmax - width)/2; + if (top < 0) + top = 0; + if (left < 0) + left = 0; + + win = newwin(height, width, top, left); + wbkgd(win, COLOR_PAIR(type)); + + box(win, 0, 0); + wattrset(win, get_line_attr(type)); + mvwprintw(win, 0, (width-strlen(title))/2, " %s ", title); + + menu.win = win; + menu.width = width; + menu.hotkeys = hotkeys; + menu.selected = -1; +} + +static void +menu_set_line_attr(int index, enum line_type type) +{ + WINDOW *win = menu.win; + int width = menu.width-2; + mvwchgat(win, index+1, 1, width, + get_line_attr(type), type, NULL); +} + +static void +menu_putline(int index, const struct menu_item *item) +{ + WINDOW *win = menu.win; + bool hotkeys = menu.hotkeys; + if (hotkeys) { + if (item->hotkey) + mvwprintw(win, index+1, 2, "[%c] %s", (char) item->hotkey, item->text); + else + mvwprintw(win, index+1, 6, "%s", item->text); + } else { + mvwprintw(win, index+1, 2, "%s", item->text); + } +} + +static void +menu_select(int index) +{ + WINDOW *win = menu.win; + int width = menu.width-2; + if (menu.selected >= 0) { + menu_set_line_attr(menu.selected, LINE_TITLE_FOCUS); + } + if (index >= 0) { + menu_set_line_attr(index, LINE_CURSOR); + } + menu.selected = index; + menu_popup(); +} /* * Status management @@ -6836,14 +6930,30 @@ static bool prompt_menu(const char *prompt, const struct menu_item *items, int * { enum input_status status = INPUT_OK; int size = 0; + int width = strlen(prompt+2); + bool hotkeys = false; + int i; - while (items[size].text) + while (items[size].text) { + int w = strlen(items[size].text); + if (w > width) + width = w; + if (items[size].hotkey) + hotkeys = true; size++; + } + /* padding */ + width += hotkeys ? 8 : 4; + + menu_create(size+2, width, prompt, hotkeys); + for (i=0; i < size; ++i) + menu_putline(i, &items[i]); + menu_popup(); + while (status == INPUT_OK) { const struct menu_item *item = &items[*selected]; int key; - int i; mvwprintw(status_win, 0, 0, "%s (%d of %d) ", prompt, *selected + 1, size); @@ -6851,6 +6961,7 @@ static bool prompt_menu(const char *prompt, const struct menu_item *items, int * wprintw(status_win, "[%c] ", (char) item->hotkey); wprintw(status_win, "%s", item->text); wclrtoeol(status_win); + menu_select(*selected); key = get_input(COLS - 1); switch (key) { @@ -6886,6 +6997,8 @@ static bool prompt_menu(const char *prompt, const struct menu_item *items, int * } } + menu_popdown(); + /* Clear the status window */ status_empty = FALSE; report(""); -- 1.6.2.rc1.258.g1d592.dirty -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html