diff options
author | Matthew Jordan <mjordan@digium.com> | 2014-07-17 18:42:43 +0000 |
---|---|---|
committer | Matthew Jordan <mjordan@digium.com> | 2014-07-17 18:42:43 +0000 |
commit | c7d3570248cfee32fb35fdf9d683ccb23e8da10b (patch) | |
tree | 792b25aea89fbbebf8eee3914037448729760cc1 /menuselect/menuselect_newt.c | |
parent | cd6c7744568e07124bd2cbf01d57eb0e15c82013 (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.c | 427 |
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; +} |