]>
Commit | Line | Data |
---|---|---|
07c56447 | 1 | /* |
2aaf83c2 | 2 | * Copyright 1987 by the Massachusetts Institute of Technology. |
3 | * For copying and distribution information, see the file | |
4 | * "mit-copyright.h". | |
5 | * | |
6 | * $Source$ | |
7 | * $Author$ | |
8 | * $Header$ | |
9 | * $Log$ | |
f659480d | 10 | * Revision 1.8 1987-08-21 22:52:37 wesommer |
11 | * [changes from poto] | |
967b7c08 | 12 | * |
f659480d | 13 | * Revision 1.7 87/08/17 14:23:05 jtkohl |
14 | * add Password_input | |
15 | * | |
27de3061 | 16 | * Revision 1.6 87/08/17 11:55:23 jtkohl |
17 | * changes made by poto. Looks like cleanup | |
18 | * | |
967b7c08 | 19 | * Revision 1.5 87/08/07 18:09:46 poto |
74e7b641 | 20 | * will not enter menu if ->m_entry returns DM_QUIT; |
21 | * the command args from a submenu command will be passed on to ->m_entry(); | |
967b7c08 | 22 | * |
74e7b641 | 23 | * Revision 1.4 87/08/05 14:48:04 ambar |
e9db439c | 24 | * added latest set of hackery, to fix missing |
25 | * newlines, and not being able to quit out of | |
26 | * the pager. | |
74e7b641 | 27 | * |
e9db439c | 28 | * Revision 1.3 87/08/03 05:10:34 wesommer |
29 | * This one appears to work. | |
30 | * | |
33a6b7f2 | 31 | * Revision 1.2 87/08/03 04:16:51 wesommer |
32 | * Here's another, which is probably better. | |
33 | * | |
2aaf83c2 | 34 | * Revision 1.1 87/07/31 18:02:23 ambar |
35 | * Initial revision | |
36 | * | |
37 | * | |
07c56447 | 38 | * Generic menu system module. |
39 | * | |
40 | * Basically, we define an enormous tree structure which represents the | |
41 | * menu. Some extra pieces (ml_command, ma_doc) get thrown in so we can | |
42 | * also use the structure for a command-based system. | |
43 | * | |
44 | * By making the menu descriptions so general, we can ease porting to just | |
45 | * about anything. | |
46 | */ | |
47 | ||
2aaf83c2 | 48 | #ifndef lint |
49 | static char rcsid_menu_c[] = "$Header$"; | |
e9db439c | 50 | |
2aaf83c2 | 51 | #endif lint |
52 | ||
07c56447 | 53 | #include <stdio.h> |
967b7c08 | 54 | #include <signal.h> |
07c56447 | 55 | #include <curses.h> |
2aaf83c2 | 56 | #include <ctype.h> |
07c56447 | 57 | #include "menu.h" |
58 | ||
967b7c08 | 59 | #define MAX(A,B) ((A) > (B) ? (A) : (B)) |
60 | #define MIN(A,B) ((A) < (B) ? (A) : (B)) | |
61 | #define CTL(ch) ((ch) & 037) | |
07c56447 | 62 | |
63 | #define MIN_INPUT 2 /* Minimum number of lines for input window */ | |
64 | ||
2aaf83c2 | 65 | char *strcpy(); |
66 | char *strncpy(); | |
e9db439c | 67 | int more_flg = 1; |
2aaf83c2 | 68 | |
07c56447 | 69 | /* Structure for holding current displayed menu */ |
70 | struct menu_screen { | |
71 | WINDOW *ms_screen; /* Window for this menu */ | |
72 | WINDOW *ms_title; /* Title subwindow */ | |
73 | WINDOW *ms_menu; /* Menu subwindow */ | |
74 | WINDOW *ms_input; /* Input subwindow */ | |
75 | int ms_input_y; /* Input subwindow reference coordinate */ | |
e9db439c | 76 | } *cur_ms; |
07c56447 | 77 | |
2aaf83c2 | 78 | #define NULLMS ((struct menu_screen *) 0) |
79 | ||
80 | Menu *top_menu; /* Root for command search */ | |
81 | ||
07c56447 | 82 | /* |
83 | * Start_menu takes a menu as an argument. It initializes curses u.s.w., | |
84 | * and a quit in any submenu should unwind back to here. (it might not, | |
85 | * if user functions which run their own menus don't cooperate.) | |
86 | * Start_menu should only be called once, at the start of the program. | |
87 | */ | |
88 | Start_menu(m) | |
e9db439c | 89 | Menu *m; |
07c56447 | 90 | { |
2aaf83c2 | 91 | struct menu_screen *make_ms(); |
92 | ||
e9db439c | 93 | if (initscr() == ERR) { |
07c56447 | 94 | fputs("Can't initialize curses!\n", stderr); |
2aaf83c2 | 95 | Start_no_menu(m); |
07c56447 | 96 | } |
97 | raw(); /* We parse & print everything ourselves */ | |
98 | noecho(); | |
967b7c08 | 99 | cur_ms = make_ms(0); /* So we always have some current */ |
100 | /* menu_screen */ | |
2aaf83c2 | 101 | top_menu = m; |
74e7b641 | 102 | /* Run the menu */ |
967b7c08 | 103 | (void) Do_menu(m, -1, (char **) NULL); |
104 | Cleanup_menu(); | |
105 | } | |
106 | ||
107 | Cleanup_menu() | |
108 | { | |
109 | if (cur_ms) { | |
110 | wclear(cur_ms->ms_screen); | |
111 | wrefresh(cur_ms->ms_screen); | |
112 | } | |
07c56447 | 113 | endwin(); |
114 | } | |
967b7c08 | 115 | |
07c56447 | 116 | |
2aaf83c2 | 117 | /* Like Start_menu, except it doesn't print menus and doesn't use curses */ |
118 | Start_no_menu(m) | |
e9db439c | 119 | Menu *m; |
2aaf83c2 | 120 | { |
121 | cur_ms = NULLMS; | |
122 | top_menu = m; | |
74e7b641 | 123 | /* Run the menu */ |
967b7c08 | 124 | (void) Do_menu(m, -1, (char **) NULL); |
2aaf83c2 | 125 | } |
126 | ||
07c56447 | 127 | /* |
128 | * Create a new menu screen template with the specified menu length | |
129 | * and return it. | |
130 | */ | |
e9db439c | 131 | struct menu_screen * |
132 | make_ms(length) | |
133 | int length; | |
07c56447 | 134 | { |
135 | struct menu_screen *ms; | |
136 | char *malloc(); | |
137 | ||
e9db439c | 138 | if (MAX_TITLE + length + MIN_INPUT > LINES) { |
07c56447 | 139 | fputs("Menu too big!\n", stderr); |
140 | exit(2); | |
141 | } | |
142 | ||
143 | ms = (struct menu_screen *) malloc(sizeof(struct menu_screen)); | |
144 | ||
145 | ms->ms_screen = newwin(0, 0, 0, 0); | |
146 | ms->ms_title = subwin(ms->ms_screen, MAX_TITLE, 0, 0, 0); | |
147 | ms->ms_menu = subwin(ms->ms_screen, | |
148 | length, 0, MAX_TITLE, 0); | |
149 | ms->ms_input = subwin(ms->ms_screen, 0, 0, | |
150 | ms->ms_input_y = MAX_TITLE + length, | |
151 | 0); | |
152 | ||
153 | scrollok(ms->ms_input, TRUE); | |
2aaf83c2 | 154 | (void) wmove(ms->ms_input, 0, 0); |
155 | (void) wclear(ms->ms_screen); | |
07c56447 | 156 | |
e9db439c | 157 | return (ms); |
07c56447 | 158 | } |
159 | ||
160 | /* | |
161 | * This routine destroys a menu_screen. | |
162 | */ | |
163 | destroy_ms(ms) | |
e9db439c | 164 | struct menu_screen *ms; |
07c56447 | 165 | { |
166 | delwin(ms->ms_title); | |
167 | delwin(ms->ms_menu); | |
168 | delwin(ms->ms_input); | |
169 | delwin(ms->ms_screen); | |
e9db439c | 170 | free((char *) ms); |
07c56447 | 171 | } |
172 | ||
173 | /* | |
174 | * This guy actually puts up the menu | |
967b7c08 | 175 | * Note: if margc < 0, no 'r' option will be displayed (i.e., on the |
176 | * top level menu) | |
07c56447 | 177 | */ |
e9db439c | 178 | int |
74e7b641 | 179 | Do_menu(m, margc, margv) |
e9db439c | 180 | Menu *m; |
74e7b641 | 181 | int margc; |
182 | char *margv[]; | |
07c56447 | 183 | { |
184 | struct menu_screen *my_ms, *old_cur_ms; | |
185 | char argvals[MAX_ARGC][MAX_ARGLEN]; /* This is where args are stored */ | |
2aaf83c2 | 186 | char buf[MAX_ARGC * MAX_ARGLEN]; |
07c56447 | 187 | char *argv[MAX_ARGC]; |
188 | int line; | |
2aaf83c2 | 189 | int i; |
190 | struct menu_line *command, *Find_command(); | |
07c56447 | 191 | int argc; |
967b7c08 | 192 | int quitflag, is_topmenu = (margc < 0); |
193 | ||
07c56447 | 194 | /* Entry function gets called with old menu_screen still current */ |
e9db439c | 195 | if (m->m_entry != NULLFUNC) |
74e7b641 | 196 | if (m->m_entry(m, margc, margv) == DM_QUIT) |
197 | return DM_NORMAL; | |
07c56447 | 198 | |
2aaf83c2 | 199 | /* The following get run only in curses mode */ |
e9db439c | 200 | if (cur_ms != NULLMS) { |
2aaf83c2 | 201 | /* Get a menu_screen */ |
202 | old_cur_ms = cur_ms; | |
967b7c08 | 203 | cur_ms = my_ms = make_ms(m->m_length + 1 + (is_topmenu?0:1)); |
07c56447 | 204 | |
2aaf83c2 | 205 | /* Now print the title and the menu */ |
e9db439c | 206 | (void) wclear(my_ms->ms_menu); |
207 | (void) wmove(my_ms->ms_title, 0, MAX(0, (COLS - | |
208 | strlen(m->m_title)) >> 1)); | |
2aaf83c2 | 209 | (void) wstandout(my_ms->ms_title); |
210 | (void) waddstr(my_ms->ms_title, m->m_title); | |
211 | (void) wstandend(my_ms->ms_title); | |
212 | ||
e9db439c | 213 | for (line = 0; line < m->m_length; line++) { |
2aaf83c2 | 214 | (void) wmove(my_ms->ms_menu, line, 0); |
e9db439c | 215 | (void) wprintw(my_ms->ms_menu, "%2d. (%-12s) %s.", line + 1, |
216 | m->m_lines[line].ml_command, | |
217 | m->m_lines[line].ml_doc); | |
2aaf83c2 | 218 | } |
219 | (void) wmove(my_ms->ms_menu, line++, 0); | |
967b7c08 | 220 | if (!is_topmenu) { |
221 | (void) waddstr(my_ms->ms_menu, | |
222 | " r. (return ) Return to previous menu."); | |
223 | (void) wmove(my_ms->ms_menu, line, 0); | |
224 | } | |
2aaf83c2 | 225 | (void) waddstr(my_ms->ms_menu, " q. (quit ) Quit."); |
07c56447 | 226 | |
07c56447 | 227 | } |
07c56447 | 228 | |
e9db439c | 229 | for (;;) { |
07c56447 | 230 | /* This will be set by a return val from func or submenu */ |
231 | quitflag = DM_NORMAL; | |
2aaf83c2 | 232 | /* This is here because we may be coming from another menu */ |
e9db439c | 233 | if (cur_ms != NULL) |
234 | touchwin(my_ms->ms_screen); | |
07c56447 | 235 | /* Get a command */ |
967b7c08 | 236 | if (!Prompt_input("Command: ", buf, sizeof(buf))) |
237 | continue; | |
2aaf83c2 | 238 | /* Parse it into the argument list */ |
239 | /* If there's nothing there, try again */ | |
240 | /* Initialize argv */ | |
e9db439c | 241 | for (argc = 0; argc < MAX_ARGC; argc++) |
242 | argv[argc] = argvals[argc]; | |
243 | ||
244 | if ((argc = Parse_words(buf, argv, MAX_ARGLEN)) == 0) | |
245 | continue; | |
246 | if ((line = atoi(argv[0])) > 0 && line <= m->m_length) { | |
247 | command = &m->m_lines[line - 1]; | |
248 | } | |
967b7c08 | 249 | else if ((!is_topmenu && |
250 | (!strcmp(argv[0], "r") | |
251 | || !strcmp(argv[0], "return"))) | |
e9db439c | 252 | || !strcmp(argv[0], "q") |
e9db439c | 253 | || !strcmp(argv[0], "quit")) { |
07c56447 | 254 | /* here if it's either return or quit */ |
e9db439c | 255 | if (cur_ms != NULLMS) { |
2aaf83c2 | 256 | cur_ms = old_cur_ms; |
257 | destroy_ms(my_ms); | |
258 | } | |
e9db439c | 259 | if (m->m_exit != NULLFUNC) |
260 | m->m_exit(m); | |
261 | return (*argv[0] == 'r' ? DM_NORMAL : DM_QUIT); | |
262 | /* finally, try to find it using Find_command */ | |
263 | } | |
264 | else if ((command = Find_command(argvals[0])) == | |
265 | (struct menu_line *) 0) { | |
266 | Put_message("Command not recognized"); | |
267 | continue; | |
268 | } | |
2aaf83c2 | 269 | /* If we got to here, command is a valid menu_line */ |
270 | /* Send the offical command name into the argv */ | |
271 | (void) strcpy(argvals[0], command->ml_command); | |
272 | /* Show that we're working on it */ | |
273 | Put_message(command->ml_doc); | |
274 | /* Print args that we've already got */ | |
e9db439c | 275 | for (i = 1; i < argc; i++) { |
276 | if (command->ml_args[i].ma_prompt == NULL) | |
277 | break; | |
2aaf83c2 | 278 | (void) sprintf(buf, "%s%s", command->ml_args[i].ma_prompt, |
279 | argv[i]); | |
280 | Put_message(buf); | |
281 | } | |
282 | /* Get remaining arguments, if any */ | |
e9db439c | 283 | for (; argc < command->ml_argc; argc++) { |
967b7c08 | 284 | if (!Prompt_input(command->ml_args[argc].ma_prompt, |
285 | argvals[argc], sizeof(argvals[argc]))) | |
286 | goto punt_command; | |
2aaf83c2 | 287 | } |
e9db439c | 288 | if (command->ml_function != NULLFUNC) { |
2aaf83c2 | 289 | /* If it's got a function, call it */ |
290 | quitflag = command->ml_function(argc, argv); | |
e9db439c | 291 | } |
292 | else if (command->ml_submenu != NULLMENU) { | |
2aaf83c2 | 293 | /* Else see if it is a submenu */ |
74e7b641 | 294 | quitflag = Do_menu(command->ml_submenu, argc, argv); |
e9db439c | 295 | } |
296 | else { | |
2aaf83c2 | 297 | /* If it's got neither, something is wrong */ |
298 | Put_message("*INTERNAL ERROR: NO FUNCTION OR MENU FOR LINE*"); | |
07c56447 | 299 | } |
e9db439c | 300 | if (quitflag == DM_QUIT) { |
301 | if (cur_ms != NULLMS) { | |
2aaf83c2 | 302 | cur_ms = old_cur_ms; |
303 | destroy_ms(my_ms); | |
304 | } | |
e9db439c | 305 | if (m->m_exit != NULLFUNC) |
306 | m->m_exit(m); | |
307 | return (DM_QUIT); | |
07c56447 | 308 | } |
967b7c08 | 309 | punt_command: |
310 | ; | |
07c56447 | 311 | } |
312 | } | |
313 | ||
314 | /* Prompt the user for input in the input window of cur_ms */ | |
967b7c08 | 315 | int Prompt_input(prompt, buf, buflen) |
e9db439c | 316 | char *prompt; |
317 | char *buf; | |
318 | int buflen; | |
07c56447 | 319 | { |
320 | int c; | |
321 | char *p; | |
322 | int y, x, oldx; | |
323 | ||
e9db439c | 324 | if (cur_ms != NULLMS) { |
325 | more_flg = 1; | |
326 | getyx(cur_ms->ms_input, y, x); | |
327 | (void) wmove(cur_ms->ms_input, y, 0); | |
328 | ||
329 | touchwin(cur_ms->ms_screen); | |
330 | refresh_ms(cur_ms); | |
2aaf83c2 | 331 | (void) waddstr(cur_ms->ms_input, prompt); |
332 | getyx(cur_ms->ms_input, y, x); | |
e9db439c | 333 | |
2aaf83c2 | 334 | oldx = x; |
f659480d | 335 | p = buf; |
336 | while(1) { | |
337 | /* for (p = buf; p - buf < buflen;) { */ | |
2aaf83c2 | 338 | (void) wmove(cur_ms->ms_input, y, x); |
339 | (void) wclrtoeol(cur_ms->ms_input); | |
340 | refresh_ms(cur_ms); | |
341 | c = getchar(); | |
342 | switch (c) { | |
967b7c08 | 343 | case CTL('C'): |
344 | return 0; | |
345 | case CTL('Z'): | |
346 | kill(getpid(), SIGTSTP); | |
347 | touchwin(curscr); | |
348 | break; | |
349 | case CTL('L'): | |
e9db439c | 350 | (void) wclear(cur_ms->ms_input); |
351 | (void) waddstr(cur_ms->ms_input, prompt); | |
967b7c08 | 352 | wrefresh(curscr); |
e9db439c | 353 | getyx(cur_ms->ms_input, y, x); |
2aaf83c2 | 354 | break; |
e9db439c | 355 | case '\n': |
356 | case '\r': | |
f659480d | 357 | goto end_input; |
2aaf83c2 | 358 | case '\b': |
359 | case '\177': | |
360 | if (p > buf) { | |
361 | p--; | |
362 | x--; | |
363 | } | |
364 | break; | |
967b7c08 | 365 | case CTL('U'): |
366 | case CTL('G'): | |
367 | case CTL('['): | |
2aaf83c2 | 368 | x = oldx; |
e9db439c | 369 | p = buf; |
2aaf83c2 | 370 | break; |
371 | default: | |
f659480d | 372 | if (isprint(c) && (p - buf < buflen)) { |
967b7c08 | 373 | (void) waddch(cur_ms->ms_input, c); |
374 | *p++ = c; | |
375 | x++; | |
376 | } else | |
377 | putchar(CTL('G')); | |
2aaf83c2 | 378 | break; |
07c56447 | 379 | } |
07c56447 | 380 | } |
f659480d | 381 | end_input: |
382 | (void) waddch(cur_ms->ms_input, '\n'); | |
383 | (void) waddch(cur_ms->ms_input, '\r'); | |
384 | ||
385 | (void) wclrtoeol(cur_ms->ms_input); | |
386 | refresh_ms(cur_ms); | |
387 | *p = '\0'; | |
388 | Start_paging(); | |
389 | return 1; | |
390 | } else { | |
2aaf83c2 | 391 | printf("%s", prompt); |
967b7c08 | 392 | if (gets(buf) == NULL) |
393 | return 0; | |
2aaf83c2 | 394 | Start_paging(); |
967b7c08 | 395 | return 1; |
07c56447 | 396 | } |
397 | } | |
398 | ||
27de3061 | 399 | /* Prompt the user for input in the input window of cur_ms, but don't echo |
400 | and allow some control characters */ | |
401 | int Password_input(prompt, buf, buflen) | |
402 | char *prompt; | |
403 | char *buf; | |
404 | int buflen; | |
405 | { | |
406 | int c; | |
407 | char *p; | |
408 | int y, x, oldx; | |
409 | ||
410 | if (cur_ms != NULLMS) { | |
411 | more_flg = 1; | |
412 | getyx(cur_ms->ms_input, y, x); | |
413 | (void) wmove(cur_ms->ms_input, y, 0); | |
414 | ||
415 | touchwin(cur_ms->ms_screen); | |
416 | refresh_ms(cur_ms); | |
417 | (void) waddstr(cur_ms->ms_input, prompt); | |
418 | getyx(cur_ms->ms_input, y, x); | |
419 | ||
420 | oldx = x; | |
421 | for (p = buf; p - buf < buflen;) { | |
422 | (void) wmove(cur_ms->ms_input, y, x); | |
423 | (void) wclrtoeol(cur_ms->ms_input); | |
424 | refresh_ms(cur_ms); | |
425 | c = getchar(); | |
426 | switch (c) { | |
427 | case CTL('C'): | |
428 | return 0; | |
429 | case CTL('Z'): | |
430 | kill(getpid(), SIGTSTP); | |
431 | touchwin(curscr); | |
432 | break; | |
433 | case CTL('L'): | |
434 | (void) wclear(cur_ms->ms_input); | |
435 | (void) waddstr(cur_ms->ms_input, prompt); | |
436 | wrefresh(curscr); | |
437 | getyx(cur_ms->ms_input, y, x); | |
438 | break; | |
439 | case '\n': | |
440 | case '\r': | |
441 | (void) waddch(cur_ms->ms_input, '\n'); | |
442 | (void) waddch(cur_ms->ms_input, '\r'); | |
443 | ||
444 | (void) wclrtoeol(cur_ms->ms_input); | |
445 | refresh_ms(cur_ms); | |
446 | *p = '\0'; | |
447 | Start_paging(); | |
448 | return 1; | |
449 | case '\b': | |
450 | case '\177': | |
451 | if (p > buf) { | |
452 | p--; | |
453 | x--; | |
454 | } | |
455 | break; | |
456 | case CTL('U'): | |
457 | x = oldx; | |
458 | p = buf; | |
459 | break; | |
460 | default: | |
461 | *p++ = c; | |
462 | break; | |
463 | } | |
464 | } | |
465 | } | |
466 | else { | |
467 | struct sgttyb ttybuf, nttybuf; | |
468 | printf("%s", prompt); | |
469 | /* turn off echoing */ | |
470 | (void) ioctl(0, TIOCGETP, &ttybuf); | |
471 | nttybuf = ttybuf; | |
472 | nttybuf.sg_flags &= ~ECHO; | |
473 | (void)ioctl(0, TIOCSETP, &nttybuf); | |
474 | if (gets(buf) == NULL) { | |
475 | (void) ioctl(0, TIOCSETP, &ttybuf); | |
476 | putchar('\n'); | |
477 | return 0; | |
478 | } | |
479 | putchar('\n'); | |
480 | (void) ioctl(0, TIOCSETP, &ttybuf); | |
481 | Start_paging(); | |
482 | return 1; | |
483 | } | |
484 | } | |
485 | ||
2aaf83c2 | 486 | int lines_left; |
487 | ||
488 | /* Start paging */ | |
489 | /* This routine will cause the most recently put message to be the | |
490 | one at the top of the screen when a ---More--- prompt is displayed */ | |
491 | Start_paging() | |
492 | { | |
e9db439c | 493 | if (cur_ms != NULLMS) { |
2aaf83c2 | 494 | lines_left = LINES - cur_ms->ms_input_y - 1; |
e9db439c | 495 | } |
496 | else { | |
2aaf83c2 | 497 | lines_left = 23; |
498 | } | |
499 | } | |
500 | ||
501 | /* Turn off paging */ | |
502 | Stop_paging() | |
503 | { | |
504 | lines_left = -1; | |
505 | } | |
506 | ||
f659480d | 507 | /* Print a message in the input window of cur_ms. */ |
07c56447 | 508 | Put_message(msg) |
f659480d | 509 | char *msg; |
510 | { | |
511 | char *copy, *line, *s; | |
512 | ||
513 | copy = (char *) malloc(COLS); | |
514 | s = line = msg; | |
515 | while(*s++) { | |
516 | if (s - line >= COLS-1) { | |
517 | strncpy(copy, line, COLS-1); | |
518 | line += COLS-1; | |
519 | } else if (*s == '\n') { | |
520 | *s = '\0'; | |
521 | strcpy(copy, line); | |
522 | line = ++s; | |
523 | } else | |
524 | continue; | |
525 | Put_line(copy); | |
526 | } | |
527 | Put_line(line); | |
528 | free(copy); | |
529 | } | |
530 | ||
531 | /* Will be truncated to COLS characters. */ | |
532 | Put_line(msg) | |
533 | char *msg; | |
07c56447 | 534 | { |
e9db439c | 535 | int y, x, i; |
536 | char *msg1, chr; | |
537 | ||
538 | if (!more_flg) | |
539 | return; | |
2aaf83c2 | 540 | |
e9db439c | 541 | if (lines_left >= 0) { |
542 | if (--lines_left == 0) { | |
2aaf83c2 | 543 | /* Give the user a more prompt */ |
e9db439c | 544 | if (cur_ms != NULLMS) { |
2aaf83c2 | 545 | (void) wstandout(cur_ms->ms_input); |
546 | (void) wprintw(cur_ms->ms_input, "---More---"); | |
547 | (void) wstandend(cur_ms->ms_input); | |
548 | refresh_ms(cur_ms); | |
e9db439c | 549 | chr = getchar();/* We do care what it is */ |
550 | if (chr == 'q' || chr == 'Q') { | |
551 | more_flg = 0; | |
552 | return; | |
553 | } | |
2aaf83c2 | 554 | getyx(cur_ms->ms_input, y, x); |
555 | (void) wmove(cur_ms->ms_input, y, 0); | |
556 | (void) wclrtoeol(cur_ms->ms_input); | |
e9db439c | 557 | } |
558 | else { | |
2aaf83c2 | 559 | printf("---More (hit return)---"); |
560 | (void) getchar(); | |
561 | } | |
562 | Start_paging(); /* Reset lines_left */ | |
563 | } | |
564 | } | |
e9db439c | 565 | |
566 | if (cur_ms != NULLMS) { | |
567 | msg1 = (char *) calloc(COLS, 1); | |
f659480d | 568 | (void) strncpy(msg1, msg, COLS-1); |
569 | for (i = strlen(msg1); i < COLS - 1; i++) | |
e9db439c | 570 | msg1[i] = ' '; |
571 | (void) wprintw(cur_ms->ms_input, "%s\n", msg1); | |
2aaf83c2 | 572 | /* refresh_ms(cur_ms); */ |
e9db439c | 573 | } |
574 | else { | |
2aaf83c2 | 575 | puts(msg); |
576 | } | |
07c56447 | 577 | } |
578 | ||
579 | /* Refresh a menu_screen onto the real screen */ | |
580 | refresh_ms(ms) | |
e9db439c | 581 | struct menu_screen *ms; |
07c56447 | 582 | { |
583 | int y, x; | |
584 | ||
585 | getyx(ms->ms_input, y, x); | |
2aaf83c2 | 586 | (void) wmove(ms->ms_screen, y + ms->ms_input_y, x); |
587 | (void) wrefresh(ms->ms_screen); | |
588 | } | |
589 | ||
590 | /* Parse buf into a list of words, which will be placed in strings specified by | |
591 | argv. Space for these strings must have already been allocated. | |
592 | Only the first n characters of each word will be copied */ | |
593 | Parse_words(buf, argv, n) | |
e9db439c | 594 | char *buf; |
595 | char *argv[]; | |
2aaf83c2 | 596 | int n; |
e9db439c | 597 | |
2aaf83c2 | 598 | { |
599 | char *start, *end; /* For sausage machine */ | |
600 | int argc; | |
601 | ||
602 | start = buf; | |
e9db439c | 603 | for (argc = 0; argc < MAX_ARGC; argc++) { |
604 | while (isspace(*start)) | |
605 | start++; /* Kill whitespace */ | |
606 | if (*start == '\0') | |
607 | break; /* Nothing left */ | |
2aaf83c2 | 608 | /* Now find the end of the word */ |
e9db439c | 609 | for (end = start; *end != '\0' && !isspace(*end); end++); |
610 | (void) strncpy(argv[argc], start, MIN(end - start, n)); /* Copy it */ | |
611 | argv[argc][MIN(end - start, n - 1)] = '\0'; /* Terminate */ | |
2aaf83c2 | 612 | start = end; |
613 | } | |
e9db439c | 614 | return (argc); |
2aaf83c2 | 615 | } |
616 | ||
617 | /* This is the internal form of Find_command, which recursively searches | |
618 | for a menu_line with command command in the specified menu */ | |
619 | /* It will search to a maximum depth of d */ | |
e9db439c | 620 | struct menu_line * |
621 | find_command_from(c, m, d) | |
622 | char *c; | |
623 | struct menu *m; | |
624 | int d; | |
2aaf83c2 | 625 | { |
626 | int line; | |
627 | struct menu_line *maybe; | |
628 | ||
e9db439c | 629 | if (d < 0) |
630 | return ((struct menu_line *) 0); /* Too deep! */ | |
631 | for (line = 0; line < m->m_length; line++) { | |
632 | if (!strcmp(c, m->m_lines[line].ml_command)) { | |
633 | return (&m->m_lines[line]); | |
634 | } | |
635 | else if (m->m_lines[line].ml_submenu != NULLMENU | |
636 | && (maybe = | |
637 | find_command_from(c, m->m_lines[line].ml_submenu, d - 1)) | |
638 | != (struct menu_line *) 0) { | |
639 | return (maybe); | |
640 | } | |
2aaf83c2 | 641 | } |
642 | /* If we got to here, nothing works */ | |
e9db439c | 643 | return ((struct menu_line *) 0); |
07c56447 | 644 | } |
2aaf83c2 | 645 | |
646 | /* Find_command searches down the current menu tree */ | |
647 | /* And returns a pointer to a menu_line with the specified command name */ | |
648 | /* It returns (struct menu_line *) 0 if none is found */ | |
e9db439c | 649 | struct menu_line * |
650 | Find_command(command) | |
651 | char *command; | |
2aaf83c2 | 652 | { |
e9db439c | 653 | if (top_menu == NULLMENU) { |
654 | return ((struct menu_line *) 0); | |
655 | } | |
656 | else { | |
657 | return (find_command_from(command, top_menu, MAX_MENU_DEPTH)); | |
2aaf83c2 | 658 | } |
659 | } |