aboutsummaryrefslogtreecommitdiffstats
path: root/build_tools/menuselect_curses.c
diff options
context:
space:
mode:
Diffstat (limited to 'build_tools/menuselect_curses.c')
-rw-r--r--build_tools/menuselect_curses.c312
1 files changed, 312 insertions, 0 deletions
diff --git a/build_tools/menuselect_curses.c b/build_tools/menuselect_curses.c
new file mode 100644
index 000000000..86efa6000
--- /dev/null
+++ b/build_tools/menuselect_curses.c
@@ -0,0 +1,312 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2005 - 2006, Russell Bryant
+ *
+ * Russell Bryant <russell@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*
+ * \file
+ *
+ * \author Russell Bryant <russell@digium.com>
+ *
+ * \brief curses frontend for Asterisk module selection
+ */
+
+#include "autoconfig.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <curses.h>
+
+#include "menuselect.h"
+
+#define MENU_TITLE1 "*************************************"
+#define MENU_TITLE2 "* Asterisk Module Selection *"
+#define MENU_TITLE3 "*************************************"
+
+#define TITLE_HEIGHT 5
+
+#define MIN_X 80
+#define MIN_Y 20
+
+#define PAGE_OFFSET 10
+
+
+/*! Maximum number of characters horizontally */
+int max_x = 0;
+/*! Maximum number of characters vertically */
+int max_y = 0;
+
+const char * const help_info[] = {
+ "scroll => up/down arrows",
+ "(de)select => Enter",
+ "select all => F8",
+ "deselect all => F7",
+ "back => left arrow",
+ "quit => q",
+ "save and quit => x",
+ "",
+ "XXX means dependencies have not been met"
+};
+
+void winch_handler(int sig);
+void show_help(WINDOW *win);
+void draw_main_menu(WINDOW *menu, int curopt);
+void draw_category_menu(WINDOW *menu, struct category *cat, int start, int end, int curopt);
+int run_category_menu(WINDOW *menu, int cat_num);
+int run_category_menu(WINDOW *menu, int cat_num);
+void draw_title_window(WINDOW *title);
+
+/*! \brief Handle a window resize in xterm */
+void winch_handler(int sig)
+{
+ getmaxyx(stdscr, max_y, max_x);
+
+ if (max_x < MIN_X - 1 || max_y < MIN_Y - 1) {
+ fprintf(stderr, "Terminal must be at least 80 x 25.\n");
+ max_x = MIN_X - 1;
+ max_y = MIN_Y - 1;
+ }
+}
+
+/*! \brief Display help information */
+void show_help(WINDOW *win)
+{
+ int i;
+
+ wclear(win);
+ for (i = 0; i < (sizeof(help_info) / sizeof(help_info[0])); i++) {
+ wmove(win, i, max_x / 2 - 15);
+ waddstr(win, help_info[i]);
+ }
+ wrefresh(win);
+ getch(); /* display the help until the user hits a key */
+}
+
+void draw_main_menu(WINDOW *menu, int curopt)
+{
+ struct category *cat;
+ char buf[64];
+ int i = 0;
+
+ wclear(menu);
+
+ AST_LIST_TRAVERSE(&categories, cat, list) {
+ wmove(menu, i++, max_x / 2 - 10);
+ if (!strlen_zero(cat->displayname))
+ snprintf(buf, sizeof(buf), "%d.%s %s", i, i < 10 ? " " : "", cat->displayname);
+ else
+ snprintf(buf, sizeof(buf), "%d.%s %s", i, i < 10 ? " " : "", cat->name);
+ waddstr(menu, buf);
+ }
+
+ wmove(menu, curopt, (max_x / 2) - 15);
+ waddstr(menu, "--->");
+ wmove(menu, 0, 0);
+
+ wrefresh(menu);
+}
+
+void draw_category_menu(WINDOW *menu, struct category *cat, int start, int end, int curopt)
+{
+ int i = 0;
+ int j = 0;
+ struct member *mem;
+ char buf[64];
+
+ wclear(menu);
+
+ AST_LIST_TRAVERSE(&cat->members, mem, list) {
+ if (i < start) {
+ i++;
+ continue;
+ }
+ wmove(menu, j++, max_x / 2 - 10);
+ i++;
+ if (mem->depsfailed)
+ snprintf(buf, sizeof(buf), "XXX %d.%s %s", i, i < 10 ? " " : "", mem->name);
+ else
+ snprintf(buf, sizeof(buf), "[%s] %d.%s %s", mem->enabled ? "*" : " ", i, i < 10 ? " " : "", mem->name);
+ waddstr(menu, buf);
+ if (i == end)
+ break;
+ }
+
+ wmove(menu, curopt - start, max_x / 2 - 9);
+
+ wrefresh(menu);
+}
+
+int run_category_menu(WINDOW *menu, int cat_num)
+{
+ struct category *cat;
+ int i = 0;
+ int start = 0;
+ int end = max_y - TITLE_HEIGHT - 2;
+ int c;
+ int curopt = 0;
+ int maxopt;
+
+ AST_LIST_TRAVERSE(&categories, cat, list) {
+ if (i++ == cat_num)
+ break;
+ }
+ if (!cat)
+ return -1;
+
+ maxopt = count_members(cat) - 1;
+
+ draw_category_menu(menu, cat, start, end, curopt);
+
+ while ((c = getch())) {
+ switch (c) {
+ case KEY_UP:
+ if (curopt > 0) {
+ curopt--;
+ if (curopt < start) {
+ start--;
+ end--;
+ }
+ }
+ break;
+ case KEY_DOWN:
+ if (curopt < maxopt) {
+ curopt++;
+ if (curopt > end - 1) {
+ start++;
+ end++;
+ }
+ }
+ break;
+ case KEY_NPAGE:
+ /* XXX Move down the list by PAGE_OFFSET */
+ break;
+ case KEY_PPAGE:
+ /* XXX Move up the list by PAGE_OFFSET */
+ break;
+ case KEY_LEFT:
+ return 0;
+ case KEY_RIGHT:
+ case KEY_ENTER:
+ case '\n':
+ case ' ':
+ toggle_enabled(cat, curopt);
+ break;
+ case 'h':
+ case 'H':
+ show_help(menu);
+ break;
+ case KEY_F(7):
+ set_all(cat, 0);
+ break;
+ case KEY_F(8):
+ set_all(cat, 1);
+ default:
+ break;
+ }
+ if (c == 'x' || c == 'q')
+ break;
+ draw_category_menu(menu, cat, start, end, curopt);
+ }
+
+ wrefresh(menu);
+
+ return c;
+}
+
+void draw_title_window(WINDOW *title)
+{
+ wmove(title, 1, (max_x / 2) - (strlen(MENU_TITLE1) / 2));
+ waddstr(title, MENU_TITLE1);
+ wmove(title, 2, (max_x / 2) - (strlen(MENU_TITLE2) / 2));
+ waddstr(title, MENU_TITLE2);
+ wmove(title, 3, (max_x / 2) - (strlen(MENU_TITLE3) / 2));
+ waddstr(title, MENU_TITLE3);
+ wmove(title, 0, 0);
+ wrefresh(title);
+}
+
+
+
+int run_menu(void)
+{
+ WINDOW *title;
+ WINDOW *menu;
+ int maxopt;
+ int curopt = 0;
+ int c;
+ int res = 0;
+
+ initscr();
+ getmaxyx(stdscr, max_y, max_x);
+ signal(SIGWINCH, winch_handler); /* handle window resizing in xterm */
+
+ if (max_x < MIN_X - 1 || max_y < MIN_Y - 1) {
+ fprintf(stderr, "Terminal must be at least %d x %d.\n", MIN_X, MIN_Y);
+ endwin();
+ return -1;
+ }
+
+ cbreak(); /* don't buffer input until the enter key is pressed */
+ noecho(); /* don't echo user input to the screen */
+ keypad(stdscr, TRUE); /* allow the use of arrow keys */
+ clear();
+ refresh();
+
+ maxopt = count_categories() - 1;
+
+ /* We have two windows - the title window at the top, and the menu window gets the rest */
+ title = newwin(TITLE_HEIGHT, max_x, 0, 0);
+ menu = newwin(max_y - TITLE_HEIGHT, max_x, TITLE_HEIGHT, 0);
+ draw_title_window(title);
+ draw_main_menu(menu, curopt);
+
+ while ((c = getch())) {
+ switch (c) {
+ case KEY_UP:
+ if (curopt > 0)
+ curopt--;
+ break;
+ case KEY_DOWN:
+ if (curopt < maxopt)
+ curopt++;
+ break;
+ case KEY_RIGHT:
+ case KEY_ENTER:
+ case '\n':
+ case ' ':
+ c = run_category_menu(menu, curopt);
+ break;
+ case 'h':
+ case 'H':
+ show_help(menu);
+ default:
+ break;
+ }
+ if (c == 'q') {
+ res = -1;
+ break;
+ }
+ if (c == 'x')
+ break;
+ draw_main_menu(menu, curopt);
+ }
+
+ endwin();
+
+ return res;
+}