#include <tack.h>
MODULE_ID("$Id: menu.c,v 1.2 2000/03/04 21:13:53 tom Exp $")
static void test_byname(struct test_menu *, int *, int *);
struct test_list *augment_test;
char prompt_string[80];
void
menu_prompt(void)
{
ptext(&prompt_string[1]);
}
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)) {
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) {
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) {
menu_display(test->sub_menu, &nch);
*state = 0;
if (nch == 'q' || nch == 's') {
nch = '?';
}
} else {
break;
}
if (nch == '\r' || nch == '\n' || nch == 'n') {
nch = 0;
break;
}
} while (nch == 'r');
*ch = nch;
}
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) {
put_crlf();
if (menu->menu_function) {
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(" > ");
ch = wait_here();
}
if (ch == '\r' || ch == '\n') {
ch = hot_topic;
}
if (ch == 'q') {
break;
}
if (ch == '?') {
ch = 0;
continue;
}
nch = ch;
ch = 0;
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) {
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;
}
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) {
break;
}
}
}
*last_ch = ch;
prompt_string[prompt_length] = '\0';
}
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;
}
}
void
menu_clear_screen(
struct test_list *test GCC_UNUSED,
int *state GCC_UNUSED,
int *ch GCC_UNUSED)
{
put_clear();
}
void
menu_reset_init(
struct test_list *test GCC_UNUSED,
int *state GCC_UNUSED,
int *ch GCC_UNUSED)
{
reset_init();
put_crlf();
}
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;
}
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);
}
}
}
}
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;
}
}
}
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 = '?';
}