]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - tack/menu.c
ncurses 5.0
[ncurses.git] / tack / menu.c
diff --git a/tack/menu.c b/tack/menu.c
new file mode 100644 (file)
index 0000000..a2bcc38
--- /dev/null
@@ -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.c,v 1.1 1998/01/10 00:29:30 tom Exp $")
+
+/*
+   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 precidence 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)
+**
+**     Recursivly 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)
+**
+**     Recursivly 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 = '?';
+}