summaryrefslogtreecommitdiffstats
path: root/ncurses-5.3/tack/menu.c
diff options
context:
space:
mode:
Diffstat (limited to 'ncurses-5.3/tack/menu.c')
-rw-r--r--ncurses-5.3/tack/menu.c421
1 files changed, 421 insertions, 0 deletions
diff --git a/ncurses-5.3/tack/menu.c b/ncurses-5.3/tack/menu.c
new file mode 100644
index 0000000..d5e0f68
--- /dev/null
+++ b/ncurses-5.3/tack/menu.c
@@ -0,0 +1,421 @@
+/*
+** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
+**
+** This file is part of TACK.
+**
+** TACK is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2, or (at your option)
+** any later version.
+**
+** TACK is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with TACK; see the file COPYING. If not, write to
+** the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+** Boston, MA 02111-1307, USA.
+*/
+
+#include <tack.h>
+
+MODULE_ID("$Id$")
+
+/*
+ Menu control
+ */
+
+static void test_byname(struct test_menu *, int *, int *);
+
+struct test_list *augment_test;
+char prompt_string[80]; /* menu prompt storage */
+
+/*
+** menu_prompt()
+**
+** Print the menu prompt string.
+*/
+void
+menu_prompt(void)
+{
+ ptext(&prompt_string[1]);
+}
+
+/*
+** menu_test_loop(test-structure, state, control-character)
+**
+** This function implements the repeat test function.
+*/
+static void
+menu_test_loop(
+ struct test_list *test,
+ int *state,
+ int *ch)
+{
+ int nch, p;
+
+ if ((test->flags & MENU_REP_MASK) && (augment_test != test)) {
+ /* set the augment variable (first time only) */
+ p = (test->flags >> 8) & 15;
+ if ((test->flags & MENU_REP_MASK) == MENU_LM1) {
+ augment = lines - 1;
+ } else
+ if ((test->flags & MENU_ONE_MASK) == MENU_ONE) {
+ augment = 1;
+ } else
+ if ((test->flags & MENU_LC_MASK) == MENU_lines) {
+ augment = lines * p / 10;
+ } else
+ if ((test->flags & MENU_LC_MASK) == MENU_columns) {
+ augment = columns * p / 10;
+ } else {
+ augment = 1;
+ }
+ augment_test = test;
+ set_augment_txt();
+ }
+ do {
+ if ((test->flags | *state) & MENU_CLEAR) {
+ put_clear();
+ } else
+ if (line_count + test->lines_needed >= lines) {
+ put_clear();
+ }
+ nch = 0;
+ if (test->test_procedure) {
+ /* The procedure takes precedence so I can pass
+ the menu entry as an argument.
+ */
+ can_test(test->caps_done, FLAG_TESTED);
+ can_test(test->caps_tested, FLAG_TESTED);
+ test->test_procedure(test, state, &nch);
+ } else
+ if (test->sub_menu) {
+ /* nested menu's */
+ menu_display(test->sub_menu, &nch);
+ *state = 0;
+ if (nch == 'q' || nch == 's') {
+ /* Quit and skip are killed here */
+ nch = '?';
+ }
+ } else {
+ break; /* cya */
+ }
+ if (nch == '\r' || nch == '\n' || nch == 'n') {
+ nch = 0;
+ break;
+ }
+ } while (nch == 'r');
+ *ch = nch;
+}
+
+/*
+** menu_display(menu-structure, flags)
+**
+** This function implements menu control.
+*/
+void
+menu_display(
+ struct test_menu *menu,
+ int *last_ch)
+{
+ int test_state = 0, run_standard_tests;
+ int hot_topic, ch = 0, nch = 0;
+ struct test_list *mt;
+ struct test_list *repeat_tests = 0;
+ int repeat_state = 0;
+ int prompt_length;
+
+ prompt_length = strlen(prompt_string);
+ if (menu->ident) {
+ sprintf(&prompt_string[prompt_length], "/%s", menu->ident);
+ }
+ hot_topic = menu->default_action;
+ run_standard_tests = menu->standard_tests ?
+ menu->standard_tests[0] : -1;
+ if (!last_ch) {
+ last_ch = &ch;
+ }
+ while (1) {
+ if (ch == 0) {
+ /* Display the menu */
+ put_crlf();
+ if (menu->menu_function) {
+ /*
+ this function may be used to restrict menu
+ entries. If used it must print the title.
+ */
+ menu->menu_function(menu);
+ } else
+ if (menu->menu_title) {
+ ptextln(menu->menu_title);
+ }
+ for (mt = menu->tests; (mt->flags & MENU_LAST) == 0; mt++) {
+ if (mt->menu_entry) {
+ ptext(" ");
+ ptextln(mt->menu_entry);
+ }
+ }
+ if (menu->standard_tests) {
+ ptext(" ");
+ ptextln(menu->standard_tests);
+ ptextln(" r) repeat test");
+ ptextln(" s) skip to next test");
+ }
+ ptextln(" q) quit");
+ ptextln(" ?) help");
+ }
+ if (ch == 0 || ch == REQUEST_PROMPT) {
+ put_crlf();
+ ptext(&prompt_string[1]);
+ if (hot_topic) {
+ ptext(" [");
+ putchp(hot_topic);
+ ptext("]");
+ }
+ ptext(" > ");
+ /* read a character */
+ ch = wait_here();
+ }
+ if (ch == '\r' || ch == '\n') {
+ ch = hot_topic;
+ }
+ if (ch == 'q') {
+ break;
+ }
+ if (ch == '?') {
+ ch = 0;
+ continue;
+ }
+ nch = ch;
+ ch = 0;
+ /* Run one of the standard tests (by request) */
+ for (mt = menu->tests; (mt->flags & MENU_LAST) == 0; mt++) {
+ if (mt->menu_entry && (nch == mt->menu_entry[0])) {
+ if (mt->flags & MENU_MENU) {
+ test_byname(menu, &test_state, &nch);
+ } else {
+ menu_test_loop(mt, &test_state, &nch);
+ }
+ ch = nch;
+ if ((mt->flags & MENU_COMPLETE) && ch == 0) {
+ /* top level */
+ hot_topic = 'q';
+ ch = '?';
+ }
+ }
+ }
+ if (menu->standard_tests && nch == 'r') {
+ menu->resume_tests = repeat_tests;
+ test_state = repeat_state;
+ nch = run_standard_tests;
+ }
+ if (nch == run_standard_tests) {
+ if (!(mt = menu->resume_tests)) {
+ mt = menu->tests;
+ }
+ if (mt->flags & MENU_LAST) {
+ mt = menu->tests;
+ }
+ /* Run the standard test suite */
+ for ( ; (mt->flags & MENU_LAST) == 0; ) {
+ if ((mt->flags & MENU_NEXT) == MENU_NEXT) {
+ repeat_tests = mt;
+ repeat_state = test_state;
+ nch = run_standard_tests;
+ menu_test_loop(mt, &test_state, &nch);
+ if (nch != 0 && nch != 'n') {
+ ch = nch;
+ break;
+ }
+ if (test_state & MENU_STOP) {
+ break;
+ }
+ }
+ mt++;
+ }
+ if (ch == 0) {
+ ch = hot_topic;
+ }
+ menu->resume_tests = mt;
+ menu->resume_state = test_state;
+ menu->resume_char = ch;
+
+ if (ch == run_standard_tests) {
+ /* pop up a level */
+ break;
+ }
+ }
+ }
+ *last_ch = ch;
+ prompt_string[prompt_length] = '\0';
+}
+
+/*
+** generic_done_message(test_list)
+**
+** Print the Done message and request input.
+*/
+void
+generic_done_message(
+ struct test_list *test,
+ int *state,
+ int *ch)
+{
+ char done_message[128];
+
+ if (test->caps_done) {
+ sprintf(done_message, "(%s) Done ", test->caps_done);
+ ptext(done_message);
+ } else {
+ ptext("Done ");
+ }
+ *ch = wait_here();
+ if (*ch == '\r' || *ch == '\n' || *ch == 'n') {
+ *ch = 0;
+ }
+ if (*ch == 's') {
+ *state |= MENU_STOP;
+ *ch = 0;
+ }
+}
+
+/*
+** menu_clear_screen(test, state, ch)
+**
+** Just clear the screen.
+*/
+void
+menu_clear_screen(
+ struct test_list *test GCC_UNUSED,
+ int *state GCC_UNUSED,
+ int *ch GCC_UNUSED)
+{
+ put_clear();
+}
+
+/*
+** menu_reset_init(test, state, ch)
+**
+** Send the reset and init strings.
+*/
+void
+menu_reset_init(
+ struct test_list *test GCC_UNUSED,
+ int *state GCC_UNUSED,
+ int *ch GCC_UNUSED)
+{
+ reset_init();
+ put_crlf();
+}
+
+/*
+** subtest_menu(test, state, ch)
+**
+** Scan the menu looking for something to execute
+** Return TRUE if we found anything.
+*/
+int
+subtest_menu(
+ struct test_list *test,
+ int *state,
+ int *ch)
+{
+ struct test_list *mt;
+
+ if (*ch) {
+ for (mt = test; (mt->flags & MENU_LAST) == 0; mt++) {
+ if (mt->menu_entry && (*ch == mt->menu_entry[0])) {
+ *ch = 0;
+ menu_test_loop(mt, state, ch);
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/*
+** menu_can_scan(menu-structure)
+**
+** Recursively scan the menu tree and find which cap names can be tested.
+*/
+void
+menu_can_scan(
+ const struct test_menu *menu)
+{
+ struct test_list *mt;
+
+ for (mt = menu->tests; (mt->flags & MENU_LAST) == 0; mt++) {
+ can_test(mt->caps_done, FLAG_CAN_TEST);
+ can_test(mt->caps_tested, FLAG_CAN_TEST);
+ if (!(mt->test_procedure)) {
+ if (mt->sub_menu) {
+ menu_can_scan(mt->sub_menu);
+ }
+ }
+ }
+}
+
+/*
+** menu_search(menu-structure, cap)
+**
+** Recursively search the menu tree and execute any tests that use cap.
+*/
+static void
+menu_search(
+ struct test_menu *menu,
+ int *state,
+ int *ch,
+ char *cap)
+{
+ struct test_list *mt;
+ int nch;
+
+ for (mt = menu->tests; (mt->flags & MENU_LAST) == 0; mt++) {
+ nch = 0;
+ if (cap_match(mt->caps_done, cap)
+ || cap_match(mt->caps_tested, cap)) {
+ menu_test_loop(mt, state, &nch);
+ }
+ if (!(mt->test_procedure)) {
+ if (mt->sub_menu) {
+ menu_search(mt->sub_menu, state, &nch, cap);
+ }
+ }
+ if (*state & MENU_STOP) {
+ break;
+ }
+ if (nch != 0 && nch != 'n') {
+ *ch = nch;
+ break;
+ }
+ }
+}
+
+/*
+** test_byname(menu, state, ch)
+**
+** Get a cap name then run all tests that use that cap.
+*/
+static void
+test_byname(
+ struct test_menu *menu,
+ int *state GCC_UNUSED,
+ int *ch)
+{
+ int test_state = 0;
+ char cap[32];
+
+ if (tty_can_sync == SYNC_NOT_TESTED) {
+ verify_time();
+ }
+ ptext("enter name: ");
+ read_string(cap, sizeof(cap));
+ if (cap[0]) {
+ menu_search(menu, &test_state, ch, cap);
+ }
+ *ch = '?';
+}