git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] Popup menu

From
Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
Date
Feb 22, 2009, 11:40 UTC
Message-ID
<1235302820-32526-1-git-send-email-giuseppe.bilotta@gmail.com>
Make the menu into a popup window that complements the status prompt.
Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
---

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
Next: Giuseppe Bilotta
Message 1 of 6 in “Popup menu”
  1. Popup menuGiuseppe Bilotta, Feb 22, 2009
  2. 'tig branch' opens tig in branch viewGiuseppe Bilotta, Feb 22, 2009
  3. Jonas FonsecaFeb 22, 2009
  4. Giuseppe BilottaFeb 22, 2009
  5. Felipe ContrerasFeb 22, 2009
  6. Giuseppe BilottaFeb 22, 2009

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.