summaryrefslogtreecommitdiff
path: root/menuselect/menuselect_newt.c
diff options
context:
space:
mode:
authorMatthew Jordan <mjordan@digium.com>2014-07-17 18:42:43 +0000
committerMatthew Jordan <mjordan@digium.com>2014-07-17 18:42:43 +0000
commitc7d3570248cfee32fb35fdf9d683ccb23e8da10b (patch)
tree792b25aea89fbbebf8eee3914037448729760cc1 /menuselect/menuselect_newt.c
parentcd6c7744568e07124bd2cbf01d57eb0e15c82013 (diff)
menuselect: Add menuselect to Asterisk trunk (Patch 1)
This is the first patch that adds menuselect to Asterisk trunk, and removes the svn:externals property. This is being done for two reasons: (1) The removal of external repositories eases a future migration to git (2) Asterisk is now the only thing that uses menuselect; as a result, there's little need to keep it in an external repository Subsequent patches will remove the mxml dependency from menuselect and tidy up the build system. ASTERISK-20703 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@418832 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'menuselect/menuselect_newt.c')
-rw-r--r--menuselect/menuselect_newt.c427
1 files changed, 427 insertions, 0 deletions
diff --git a/menuselect/menuselect_newt.c b/menuselect/menuselect_newt.c
new file mode 100644
index 000000000..fca558781
--- /dev/null
+++ b/menuselect/menuselect_newt.c
@@ -0,0 +1,427 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2008 Sean Bright
+ *
+ * Sean Bright <sean.bright@gmail.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 Sean Bright <sean.bright@gmail.com>
+ *
+ * \brief newt frontend for selection maintenance
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <newt.h>
+
+#include "menuselect.h"
+
+#define MIN_X 80
+#define MIN_Y 21
+
+#define MIN(a, b) ({ typeof(a) __a = (a); typeof(b) __b = (b); ((__a > __b) ? __b : __a);})
+#define MAX(a, b) ({ typeof(a) __a = (a); typeof(b) __b = (b); ((__a < __b) ? __b : __a);})
+
+extern int changes_made;
+
+static newtComponent rootOptions;
+static newtComponent subOptions;
+
+static newtComponent memberNameTextbox;
+static newtComponent dependsLabel;
+static newtComponent usesLabel;
+static newtComponent conflictsLabel;
+static newtComponent supportLevelLabel;
+static newtComponent dependsDataTextbox;
+static newtComponent usesDataTextbox;
+static newtComponent conflictsDataTextbox;
+static newtComponent supportLevelDataTextbox;
+
+static newtComponent exitButton;
+static newtComponent saveAndExitButton;
+
+static void build_members_menu(int overlay);
+static void root_menu_callback(newtComponent component, void *data);
+
+static void toggle_all_options(int select)
+{
+ struct category *cat = newtListboxGetCurrent(rootOptions);
+
+ set_all(cat, select);
+
+ /* Redraw */
+ build_members_menu(1);
+
+ return;
+}
+
+static void toggle_selected_option()
+{
+ int i;
+ struct member *mem = newtListboxGetCurrent(subOptions);
+
+ toggle_enabled(mem);
+
+ /* Redraw */
+ build_members_menu(1);
+
+ /* Select the next item in the list */
+ for (i = 0; i < newtListboxItemCount(subOptions); i++) {
+ struct member *cur;
+
+ newtListboxGetEntry(subOptions, i, NULL, (void **) &cur);
+
+ if (cur == mem) {
+ i = MIN(i + 1, newtListboxItemCount(subOptions) - 1);
+ break;
+ }
+ }
+
+ newtListboxSetCurrent(subOptions, i);
+
+ return;
+}
+
+static void reset_display()
+{
+ newtTextboxSetText(memberNameTextbox, "");
+ newtTextboxSetText(dependsDataTextbox, "");
+ newtTextboxSetText(usesDataTextbox, "");
+ newtTextboxSetText(conflictsDataTextbox, "");
+ newtTextboxSetText(supportLevelDataTextbox, "");
+ newtRefresh();
+}
+
+static void display_member_info(struct member *mem)
+{
+ char buffer[128] = { 0 };
+
+ struct reference *dep;
+ struct reference *con;
+ struct reference *uses;
+
+ reset_display();
+
+ if (mem->displayname) {
+ newtTextboxSetText(memberNameTextbox, mem->displayname);
+ }
+
+ if (AST_LIST_EMPTY(&mem->deps)) {
+ if (mem->is_separator) {
+ newtTextboxSetText(dependsDataTextbox, "");
+ } else {
+ newtTextboxSetText(dependsDataTextbox, "N/A");
+ }
+ } else {
+ strcpy(buffer, "");
+ AST_LIST_TRAVERSE(&mem->deps, dep, list) {
+ strncat(buffer, dep->displayname, sizeof(buffer) - strlen(buffer) - 1);
+ strncat(buffer, dep->member ? "(M)" : "(E)", sizeof(buffer) - strlen(buffer) - 1);
+ if (AST_LIST_NEXT(dep, list))
+ strncat(buffer, ", ", sizeof(buffer) - strlen(buffer) - 1);
+ }
+ newtTextboxSetText(dependsDataTextbox, buffer);
+ }
+
+ if (AST_LIST_EMPTY(&mem->uses)) {
+ if (mem->is_separator) {
+ newtTextboxSetText(usesDataTextbox, "");
+ } else {
+ newtTextboxSetText(usesDataTextbox, "N/A");
+ }
+ } else {
+ strcpy(buffer, "");
+ AST_LIST_TRAVERSE(&mem->uses, uses, list) {
+ strncat(buffer, uses->displayname, sizeof(buffer) - strlen(buffer) - 1);
+ strncat(buffer, uses->member ? "(M)" : "(E)", sizeof(buffer) - strlen(buffer) - 1);
+ if (AST_LIST_NEXT(uses, list))
+ strncat(buffer, ", ", sizeof(buffer) - strlen(buffer) - 1);
+ }
+ newtTextboxSetText(usesDataTextbox, buffer);
+ }
+
+ if (AST_LIST_EMPTY(&mem->conflicts)) {
+ if (!mem->is_separator) {
+ newtTextboxSetText(conflictsDataTextbox, "N/A");
+ } else {
+ newtTextboxSetText(conflictsDataTextbox, "");
+ }
+ } else {
+ strcpy(buffer, "");
+ AST_LIST_TRAVERSE(&mem->conflicts, con, list) {
+ strncat(buffer, con->displayname, sizeof(buffer) - strlen(buffer) - 1);
+ strncat(buffer, con->member ? "(M)" : "(E)", sizeof(buffer) - strlen(buffer) - 1);
+ if (AST_LIST_NEXT(con, list))
+ strncat(buffer, ", ", sizeof(buffer) - strlen(buffer) - 1);
+ }
+ newtTextboxSetText(conflictsDataTextbox, buffer);
+ }
+
+ { /* Support Level */
+ snprintf(buffer, sizeof(buffer), "%s", mem->support_level);
+ if (mem->replacement && *mem->replacement) {
+ char buf2[64];
+ snprintf(buf2, sizeof(buf2), ", Replaced by: %s", mem->replacement);
+ strncat(buffer, buf2, sizeof(buffer) - strlen(buffer) - 1);
+ }
+ if (mem->is_separator) {
+ newtTextboxSetText(supportLevelDataTextbox, "");
+ } else {
+ newtTextboxSetText(supportLevelDataTextbox, buffer);
+ }
+ }
+}
+
+static void build_members_menu(int overlay)
+{
+ struct category *cat;
+ struct member *mem;
+ char buf[64];
+ int i = 0;
+
+ if (!overlay) {
+ reset_display();
+ newtListboxClear(subOptions);
+ }
+
+ cat = newtListboxGetCurrent(rootOptions);
+
+ AST_LIST_TRAVERSE(&cat->members, mem, list) {
+
+ if ((mem->depsfailed == HARD_FAILURE) || (mem->conflictsfailed == HARD_FAILURE)) {
+ snprintf(buf, sizeof(buf), "XXX %s", mem->name);
+ } else if (mem->is_separator) {
+ snprintf(buf, sizeof(buf), " --- %s ---", mem->name);
+ } else if (mem->depsfailed == SOFT_FAILURE) {
+ snprintf(buf, sizeof(buf), "<%s> %s", mem->enabled ? "*" : " ", mem->name);
+ } else if (mem->conflictsfailed == SOFT_FAILURE) {
+ snprintf(buf, sizeof(buf), "(%s) %s", mem->enabled ? "*" : " ", mem->name);
+ } else {
+ snprintf(buf, sizeof(buf), "[%s] %s", mem->enabled ? "*" : " ", mem->name);
+ }
+
+ if (overlay) {
+ newtListboxSetEntry(subOptions, i, buf);
+ } else {
+ newtListboxAppendEntry(subOptions, buf, mem);
+ }
+
+ i++;
+ }
+
+ if (!overlay) {
+ display_member_info(AST_LIST_FIRST(&cat->members));
+ }
+
+ return;
+}
+
+static void build_main_menu()
+{
+ struct category *cat;
+ char buf[64];
+ int i = 1;
+
+ newtListboxClear(rootOptions);
+
+ AST_LIST_TRAVERSE(&categories, cat, list) {
+ if (!strlen_zero(cat->displayname))
+ snprintf(buf, sizeof(buf), " %s ", cat->displayname);
+ else
+ snprintf(buf, sizeof(buf), " %s ", cat->name);
+
+ newtListboxAppendEntry(rootOptions, buf, cat);
+
+ i++;
+ }
+}
+
+static void category_menu_callback(newtComponent component, void *data)
+{
+ display_member_info(newtListboxGetCurrent(subOptions));
+}
+
+static void root_menu_callback(newtComponent component, void *data)
+{
+ build_members_menu(0);
+}
+
+int run_confirmation_dialog(int *result)
+{
+ int res = newtWinTernary("Are You Sure?", "Discard changes & Exit", "Save & Exit", "Cancel",
+ "It appears you have made some changes, and you have opted to Quit "
+ "without saving these changes. Please choose \"Discard changes & Exit\" to exit "
+ "without saving; Choose \"Cancel\" to cancel your decision to quit, and keep "
+ "working in menuselect, or choose \"Save & Exit\" to save your changes, and exit.");
+
+ switch (res) {
+ case 1:
+ /* Discard and exit */
+ *result = -1;
+ return 1;
+ case 2:
+ /* Save and exit */
+ *result = 0;
+ return 1;
+ case 3:
+ /* They either chose "No" or they hit F12 */
+ default:
+ *result = -1;
+ return 0;
+ }
+}
+
+int run_menu(void)
+{
+ struct newtExitStruct es;
+ newtComponent form;
+ int x = 0, y = 0, res = 0;
+
+ newtInit();
+ newtCls();
+ newtGetScreenSize(&x, &y);
+
+ if (x < MIN_X || y < MIN_Y) {
+ newtFinished();
+ fprintf(stderr, "Terminal must be at least %d x %d.\n", MIN_X, MIN_Y);
+ return -1;
+ }
+
+ newtPushHelpLine(" <ENTER> toggles selection | <F12> saves & exits | <ESC> exits without save");
+ newtRefresh();
+
+ newtCenteredWindow(x - 8, y - 7, menu_name);
+ form = newtForm(NULL, NULL, 0);
+
+ /* F8 for select all */
+ newtFormAddHotKey(form, NEWT_KEY_F8);
+
+ /* F7 for deselect all */
+ newtFormAddHotKey(form, NEWT_KEY_F7);
+
+ newtFormSetTimer(form, 200);
+
+ rootOptions = newtListbox(2, 1, y - 15, 0);
+ newtListboxSetWidth(rootOptions, 34);
+ newtFormAddComponent(form, rootOptions);
+ newtComponentAddCallback(rootOptions, root_menu_callback, NULL);
+
+ subOptions = newtListbox(38, 1, y - 15, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT);
+ newtListboxSetWidth(subOptions, x - 47);
+ newtFormAddComponent(form, subOptions);
+ newtComponentAddCallback(subOptions, category_menu_callback, NULL);
+
+ memberNameTextbox = newtTextbox(2, y - 13, x - 10, 1, 0);
+ dependsLabel = newtLabel(2, y - 11, " Depends on:");
+ usesLabel = newtLabel(2, y - 10, " Can use:");
+ conflictsLabel = newtLabel(2, y - 9, "Conflicts with:");
+ supportLevelLabel = newtLabel(2, y - 8, " Support Level:");
+ dependsDataTextbox = newtTextbox(18, y - 11, x - 27, 1, 0);
+ usesDataTextbox = newtTextbox(18, y - 10, x - 27, 1, 0);
+ conflictsDataTextbox = newtTextbox(18, y - 9, x - 27, 1, 0);
+ supportLevelDataTextbox = newtTextbox(18, y - 8, x - 27, 1, 0);
+
+ exitButton = newtButton(x - 23, y - 11, " Exit ");
+ saveAndExitButton = newtButton(x - 43, y - 11, " Save & Exit ");
+
+ newtFormAddComponents(
+ form,
+ memberNameTextbox,
+ dependsLabel,
+ dependsDataTextbox,
+ usesLabel,
+ usesDataTextbox,
+ conflictsLabel,
+ conflictsDataTextbox,
+ supportLevelLabel,
+ supportLevelDataTextbox,
+ saveAndExitButton,
+ exitButton,
+ NULL);
+
+ build_main_menu();
+
+ root_menu_callback(rootOptions, AST_LIST_FIRST(&categories));
+
+ for (;;) {
+ do {
+ newtFormRun(form, &es);
+ } while (es.reason == NEWT_EXIT_TIMER);
+
+ if (es.reason == NEWT_EXIT_HOTKEY) {
+ int done = 1;
+
+ switch (es.u.key) {
+ case NEWT_KEY_F12:
+ res = 0;
+ break;
+ case NEWT_KEY_F7:
+ toggle_all_options(0);
+ done = 0;
+ break;
+ case NEWT_KEY_F8:
+ toggle_all_options(1);
+ done = 0;
+ break;
+ case NEWT_KEY_ESCAPE:
+ if (changes_made) {
+ done = run_confirmation_dialog(&res);
+ } else {
+ res = -1;
+ }
+ break;
+ default:
+ done = 0;
+ break;
+ }
+
+ if (done) {
+ break;
+ }
+ } else if (es.reason == NEWT_EXIT_COMPONENT) {
+ if (es.u.co == saveAndExitButton) {
+ res = 0;
+ break;
+ } else if (es.u.co == exitButton) {
+ int done = 1;
+
+ if (changes_made) {
+ done = run_confirmation_dialog(&res);
+ } else {
+ res = -1;
+ }
+
+ if (done) {
+ break;
+ }
+ } else if (es.u.co == subOptions) {
+ toggle_selected_option();
+ }
+ }
+ }
+
+ /* Cleanup */
+ reset_display();
+ newtFormDestroy(form);
+ newtPopWindow();
+ newtPopHelpLine();
+ newtCls();
+ newtFinished();
+
+ return res;
+}