source: trunk/ncurses/tack/menu.c@ 2622

Last change on this file since 2622 was 2621, checked in by bird, 19 years ago

GNU ncurses 5.5

File size: 8.4 KB
Line 
1/*
2** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
3**
4** This file is part of TACK.
5**
6** TACK is free software; you can redistribute it and/or modify
7** it under the terms of the GNU General Public License as published by
8** the Free Software Foundation; either version 2, or (at your option)
9** any later version.
10**
11** TACK is distributed in the hope that it will be useful,
12** but WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14** GNU General Public License for more details.
15**
16** You should have received a copy of the GNU General Public License
17** along with TACK; see the file COPYING. If not, write to
18** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19** Boston, MA 02110-1301, USA
20*/
21
22#include <tack.h>
23
24MODULE_ID("$Id: menu.c,v 1.3 2005/09/17 19:49:16 tom Exp $")
25
26/*
27 Menu control
28 */
29
30static void test_byname(struct test_menu *, int *, int *);
31
32struct test_list *augment_test;
33char prompt_string[80]; /* menu prompt storage */
34
35/*
36** menu_prompt()
37**
38** Print the menu prompt string.
39*/
40void
41menu_prompt(void)
42{
43 ptext(&prompt_string[1]);
44}
45
46/*
47** menu_test_loop(test-structure, state, control-character)
48**
49** This function implements the repeat test function.
50*/
51static void
52menu_test_loop(
53 struct test_list *test,
54 int *state,
55 int *ch)
56{
57 int nch, p;
58
59 if ((test->flags & MENU_REP_MASK) && (augment_test != test)) {
60 /* set the augment variable (first time only) */
61 p = (test->flags >> 8) & 15;
62 if ((test->flags & MENU_REP_MASK) == MENU_LM1) {
63 augment = lines - 1;
64 } else
65 if ((test->flags & MENU_ONE_MASK) == MENU_ONE) {
66 augment = 1;
67 } else
68 if ((test->flags & MENU_LC_MASK) == MENU_lines) {
69 augment = lines * p / 10;
70 } else
71 if ((test->flags & MENU_LC_MASK) == MENU_columns) {
72 augment = columns * p / 10;
73 } else {
74 augment = 1;
75 }
76 augment_test = test;
77 set_augment_txt();
78 }
79 do {
80 if ((test->flags | *state) & MENU_CLEAR) {
81 put_clear();
82 } else
83 if (line_count + test->lines_needed >= lines) {
84 put_clear();
85 }
86 nch = 0;
87 if (test->test_procedure) {
88 /* The procedure takes precedence so I can pass
89 the menu entry as an argument.
90 */
91 can_test(test->caps_done, FLAG_TESTED);
92 can_test(test->caps_tested, FLAG_TESTED);
93 test->test_procedure(test, state, &nch);
94 } else
95 if (test->sub_menu) {
96 /* nested menu's */
97 menu_display(test->sub_menu, &nch);
98 *state = 0;
99 if (nch == 'q' || nch == 's') {
100 /* Quit and skip are killed here */
101 nch = '?';
102 }
103 } else {
104 break; /* cya */
105 }
106 if (nch == '\r' || nch == '\n' || nch == 'n') {
107 nch = 0;
108 break;
109 }
110 } while (nch == 'r');
111 *ch = nch;
112}
113
114/*
115** menu_display(menu-structure, flags)
116**
117** This function implements menu control.
118*/
119void
120menu_display(
121 struct test_menu *menu,
122 int *last_ch)
123{
124 int test_state = 0, run_standard_tests;
125 int hot_topic, ch = 0, nch = 0;
126 struct test_list *mt;
127 struct test_list *repeat_tests = 0;
128 int repeat_state = 0;
129 int prompt_length;
130
131 prompt_length = strlen(prompt_string);
132 if (menu->ident) {
133 sprintf(&prompt_string[prompt_length], "/%s", menu->ident);
134 }
135 hot_topic = menu->default_action;
136 run_standard_tests = menu->standard_tests ?
137 menu->standard_tests[0] : -1;
138 if (!last_ch) {
139 last_ch = &ch;
140 }
141 while (1) {
142 if (ch == 0) {
143 /* Display the menu */
144 put_crlf();
145 if (menu->menu_function) {
146 /*
147 this function may be used to restrict menu
148 entries. If used it must print the title.
149 */
150 menu->menu_function(menu);
151 } else
152 if (menu->menu_title) {
153 ptextln(menu->menu_title);
154 }
155 for (mt = menu->tests; (mt->flags & MENU_LAST) == 0; mt++) {
156 if (mt->menu_entry) {
157 ptext(" ");
158 ptextln(mt->menu_entry);
159 }
160 }
161 if (menu->standard_tests) {
162 ptext(" ");
163 ptextln(menu->standard_tests);
164 ptextln(" r) repeat test");
165 ptextln(" s) skip to next test");
166 }
167 ptextln(" q) quit");
168 ptextln(" ?) help");
169 }
170 if (ch == 0 || ch == REQUEST_PROMPT) {
171 put_crlf();
172 ptext(&prompt_string[1]);
173 if (hot_topic) {
174 ptext(" [");
175 putchp(hot_topic);
176 ptext("]");
177 }
178 ptext(" > ");
179 /* read a character */
180 ch = wait_here();
181 }
182 if (ch == '\r' || ch == '\n') {
183 ch = hot_topic;
184 }
185 if (ch == 'q') {
186 break;
187 }
188 if (ch == '?') {
189 ch = 0;
190 continue;
191 }
192 nch = ch;
193 ch = 0;
194 /* Run one of the standard tests (by request) */
195 for (mt = menu->tests; (mt->flags & MENU_LAST) == 0; mt++) {
196 if (mt->menu_entry && (nch == mt->menu_entry[0])) {
197 if (mt->flags & MENU_MENU) {
198 test_byname(menu, &test_state, &nch);
199 } else {
200 menu_test_loop(mt, &test_state, &nch);
201 }
202 ch = nch;
203 if ((mt->flags & MENU_COMPLETE) && ch == 0) {
204 /* top level */
205 hot_topic = 'q';
206 ch = '?';
207 }
208 }
209 }
210 if (menu->standard_tests && nch == 'r') {
211 menu->resume_tests = repeat_tests;
212 test_state = repeat_state;
213 nch = run_standard_tests;
214 }
215 if (nch == run_standard_tests) {
216 if (!(mt = menu->resume_tests)) {
217 mt = menu->tests;
218 }
219 if (mt->flags & MENU_LAST) {
220 mt = menu->tests;
221 }
222 /* Run the standard test suite */
223 for ( ; (mt->flags & MENU_LAST) == 0; ) {
224 if ((mt->flags & MENU_NEXT) == MENU_NEXT) {
225 repeat_tests = mt;
226 repeat_state = test_state;
227 nch = run_standard_tests;
228 menu_test_loop(mt, &test_state, &nch);
229 if (nch != 0 && nch != 'n') {
230 ch = nch;
231 break;
232 }
233 if (test_state & MENU_STOP) {
234 break;
235 }
236 }
237 mt++;
238 }
239 if (ch == 0) {
240 ch = hot_topic;
241 }
242 menu->resume_tests = mt;
243 menu->resume_state = test_state;
244 menu->resume_char = ch;
245
246 if (ch == run_standard_tests) {
247 /* pop up a level */
248 break;
249 }
250 }
251 }
252 *last_ch = ch;
253 prompt_string[prompt_length] = '\0';
254}
255
256/*
257** generic_done_message(test_list)
258**
259** Print the Done message and request input.
260*/
261void
262generic_done_message(
263 struct test_list *test,
264 int *state,
265 int *ch)
266{
267 char done_message[128];
268
269 if (test->caps_done) {
270 sprintf(done_message, "(%s) Done ", test->caps_done);
271 ptext(done_message);
272 } else {
273 ptext("Done ");
274 }
275 *ch = wait_here();
276 if (*ch == '\r' || *ch == '\n' || *ch == 'n') {
277 *ch = 0;
278 }
279 if (*ch == 's') {
280 *state |= MENU_STOP;
281 *ch = 0;
282 }
283}
284
285/*
286** menu_clear_screen(test, state, ch)
287**
288** Just clear the screen.
289*/
290void
291menu_clear_screen(
292 struct test_list *test GCC_UNUSED,
293 int *state GCC_UNUSED,
294 int *ch GCC_UNUSED)
295{
296 put_clear();
297}
298
299/*
300** menu_reset_init(test, state, ch)
301**
302** Send the reset and init strings.
303*/
304void
305menu_reset_init(
306 struct test_list *test GCC_UNUSED,
307 int *state GCC_UNUSED,
308 int *ch GCC_UNUSED)
309{
310 reset_init();
311 put_crlf();
312}
313
314/*
315** subtest_menu(test, state, ch)
316**
317** Scan the menu looking for something to execute
318** Return TRUE if we found anything.
319*/
320int
321subtest_menu(
322 struct test_list *test,
323 int *state,
324 int *ch)
325{
326 struct test_list *mt;
327
328 if (*ch) {
329 for (mt = test; (mt->flags & MENU_LAST) == 0; mt++) {
330 if (mt->menu_entry && (*ch == mt->menu_entry[0])) {
331 *ch = 0;
332 menu_test_loop(mt, state, ch);
333 return TRUE;
334 }
335 }
336 }
337 return FALSE;
338}
339
340/*
341** menu_can_scan(menu-structure)
342**
343** Recursively scan the menu tree and find which cap names can be tested.
344*/
345void
346menu_can_scan(
347 const struct test_menu *menu)
348{
349 struct test_list *mt;
350
351 for (mt = menu->tests; (mt->flags & MENU_LAST) == 0; mt++) {
352 can_test(mt->caps_done, FLAG_CAN_TEST);
353 can_test(mt->caps_tested, FLAG_CAN_TEST);
354 if (!(mt->test_procedure)) {
355 if (mt->sub_menu) {
356 menu_can_scan(mt->sub_menu);
357 }
358 }
359 }
360}
361
362/*
363** menu_search(menu-structure, cap)
364**
365** Recursively search the menu tree and execute any tests that use cap.
366*/
367static void
368menu_search(
369 struct test_menu *menu,
370 int *state,
371 int *ch,
372 char *cap)
373{
374 struct test_list *mt;
375 int nch;
376
377 for (mt = menu->tests; (mt->flags & MENU_LAST) == 0; mt++) {
378 nch = 0;
379 if (cap_match(mt->caps_done, cap)
380 || cap_match(mt->caps_tested, cap)) {
381 menu_test_loop(mt, state, &nch);
382 }
383 if (!(mt->test_procedure)) {
384 if (mt->sub_menu) {
385 menu_search(mt->sub_menu, state, &nch, cap);
386 }
387 }
388 if (*state & MENU_STOP) {
389 break;
390 }
391 if (nch != 0 && nch != 'n') {
392 *ch = nch;
393 break;
394 }
395 }
396}
397
398/*
399** test_byname(menu, state, ch)
400**
401** Get a cap name then run all tests that use that cap.
402*/
403static void
404test_byname(
405 struct test_menu *menu,
406 int *state GCC_UNUSED,
407 int *ch)
408{
409 int test_state = 0;
410 char cap[32];
411
412 if (tty_can_sync == SYNC_NOT_TESTED) {
413 verify_time();
414 }
415 ptext("enter name: ");
416 read_string(cap, sizeof(cap));
417 if (cap[0]) {
418 menu_search(menu, &test_state, ch, cap);
419 }
420 *ch = '?';
421}
Note: See TracBrowser for help on using the repository browser.