diff options
Diffstat (limited to 'contrib/ncurses/tack/menu.c')
-rw-r--r-- | contrib/ncurses/tack/menu.c | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/contrib/ncurses/tack/menu.c b/contrib/ncurses/tack/menu.c new file mode 100644 index 000000000000..a2bcc3809054 --- /dev/null +++ b/contrib/ncurses/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.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 = '?'; +} |