]> andersk Git - moira.git/blame - clients/moira/menu.c
posixify source
[moira.git] / clients / moira / menu.c
CommitLineData
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$
2aaf83c2 9 *
07c56447 10 * Generic menu system module.
11 *
12 * Basically, we define an enormous tree structure which represents the
13 * menu. Some extra pieces (ml_command, ma_doc) get thrown in so we can
14 * also use the structure for a command-based system.
15 *
16 * By making the menu descriptions so general, we can ease porting to just
17 * about anything.
18 */
19
2aaf83c2 20#ifndef lint
21static char rcsid_menu_c[] = "$Header$";
e9db439c 22
2aaf83c2 23#endif lint
24
babbc197 25#include <mit-copyright.h>
34f47457 26#include <sys/types.h>
07c56447 27#include <stdio.h>
cde7e985 28#include <string.h>
967b7c08 29#include <signal.h>
07c56447 30#include <curses.h>
6df34521 31#ifdef POSIX
cde7e985 32#include <unistd.h>
68ec9052 33#include <termios.h>
6df34521 34#endif /* POSIX */
2aaf83c2 35#include <ctype.h>
90e30045 36#ifndef sun
93b28238 37#include <varargs.h>
90e30045 38#endif
6298c97d 39#include <com_err.h>
cde7e985 40#include <moira.h>
07c56447 41#include "menu.h"
42
c13d1215 43#ifndef __STDC__
44#define const
45#endif
46
967b7c08 47#define MAX(A,B) ((A) > (B) ? (A) : (B))
48#define MIN(A,B) ((A) < (B) ? (A) : (B))
49#define CTL(ch) ((ch) & 037)
07c56447 50
51#define MIN_INPUT 2 /* Minimum number of lines for input window */
52
facd6784 53extern int interrupt; /* will be set if ^C is received */
859891c0 54extern FILE *fdopen();
55extern int getpid();
34f47457 56extern char *calloc();
859891c0 57extern char *whoami;
58
59FILE *log_file = (FILE *) NULL; /* file stream of log file */
e9db439c 60int more_flg = 1;
2aaf83c2 61
cde7e985 62#ifdef POSIX
63extern char *malloc();
64#endif
65
07c56447 66/* Structure for holding current displayed menu */
67struct menu_screen {
68 WINDOW *ms_screen; /* Window for this menu */
69 WINDOW *ms_title; /* Title subwindow */
70 WINDOW *ms_menu; /* Menu subwindow */
71 WINDOW *ms_input; /* Input subwindow */
72 int ms_input_y; /* Input subwindow reference coordinate */
e9db439c 73} *cur_ms;
07c56447 74
2aaf83c2 75#define NULLMS ((struct menu_screen *) 0)
76
77Menu *top_menu; /* Root for command search */
11317e48 78int parsed_argc; /* used by extern routines to get additional */
79char **parsed_argv; /* comand line input */
2aaf83c2 80
6298c97d 81/*
82 * Hook function to cause error messages to be printed through
22da5e41 83 * curses instead of around it. Takes at most 5 args to the
84 * printf string (crock...)
6298c97d 85 */
86
c13d1215 87void
22da5e41 88menu_com_err_hook(who, code, fmt, arg1, arg2, arg3, arg4, arg5)
c13d1215 89 const char *who;
90 long code;
91 const char *fmt;
22da5e41 92 caddr_t arg1, arg2, arg3, arg4, arg5;
6298c97d 93{
94 char buf[BUFSIZ], *cp;
95
6298c97d 96 (void) strcpy(buf, who);
97 for (cp = buf; *cp; cp++);
98 *cp++ = ':';
99 *cp++ = ' ';
100 if (code) {
101 (void) strcpy(cp, error_message(code));
102 while (*cp)
103 cp++;
104 }
22da5e41 105 sprintf(cp, fmt, arg1, arg2, arg3, arg4, arg5);
6298c97d 106 Put_message(buf);
107}
108
07c56447 109/*
110 * Start_menu takes a menu as an argument. It initializes curses u.s.w.,
111 * and a quit in any submenu should unwind back to here. (it might not,
112 * if user functions which run their own menus don't cooperate.)
113 * Start_menu should only be called once, at the start of the program.
114 */
115Start_menu(m)
e9db439c 116 Menu *m;
07c56447 117{
2aaf83c2 118 struct menu_screen *make_ms();
c13d1215 119#ifdef __STDC__
120 register void (*old_hook)(const char *, long, const char *, va_list) = set_com_err_hook(menu_com_err_hook);
121#else
122 register void (*old_hook)() = set_com_err_hook(menu_com_err_hook);
123#endif
6298c97d 124
24582af9 125 if (initscr() == (WINDOW *)ERR) {
07c56447 126 fputs("Can't initialize curses!\n", stderr);
2aaf83c2 127 Start_no_menu(m);
6298c97d 128 } else {
129 (void) raw(); /* We parse & print everything ourselves */
130 (void) noecho();
131 cur_ms = make_ms(0); /* So we always have some current */
73b2adba 132 /* menu_screen */
6298c97d 133 /* Run the menu */
134 (void) Do_menu(m, -1, (char **) NULL);
07c56447 135 }
6298c97d 136 (void) set_com_err_hook(old_hook);
967b7c08 137 Cleanup_menu();
138}
139
140Cleanup_menu()
141{
142 if (cur_ms) {
34f47457 143 (void) wclear(cur_ms->ms_screen);
144 (void) wrefresh(cur_ms->ms_screen);
967b7c08 145 }
07c56447 146 endwin();
147}
967b7c08 148
07c56447 149
2aaf83c2 150/* Like Start_menu, except it doesn't print menus and doesn't use curses */
151Start_no_menu(m)
e9db439c 152 Menu *m;
2aaf83c2 153{
154 cur_ms = NULLMS;
33a56ee9 155 COLS = 80;
74e7b641 156 /* Run the menu */
967b7c08 157 (void) Do_menu(m, -1, (char **) NULL);
2aaf83c2 158}
159
07c56447 160/*
161 * Create a new menu screen template with the specified menu length
162 * and return it.
163 */
e9db439c 164struct menu_screen *
165make_ms(length)
166 int length;
07c56447 167{
168 struct menu_screen *ms;
07c56447 169
e9db439c 170 if (MAX_TITLE + length + MIN_INPUT > LINES) {
07c56447 171 fputs("Menu too big!\n", stderr);
172 exit(2);
173 }
174
175 ms = (struct menu_screen *) malloc(sizeof(struct menu_screen));
176
177 ms->ms_screen = newwin(0, 0, 0, 0);
178 ms->ms_title = subwin(ms->ms_screen, MAX_TITLE, 0, 0, 0);
179 ms->ms_menu = subwin(ms->ms_screen,
180 length, 0, MAX_TITLE, 0);
181 ms->ms_input = subwin(ms->ms_screen, 0, 0,
182 ms->ms_input_y = MAX_TITLE + length,
183 0);
184
185 scrollok(ms->ms_input, TRUE);
2aaf83c2 186 (void) wmove(ms->ms_input, 0, 0);
187 (void) wclear(ms->ms_screen);
07c56447 188
e9db439c 189 return (ms);
07c56447 190}
191
192/*
193 * This routine destroys a menu_screen.
194 */
195destroy_ms(ms)
e9db439c 196 struct menu_screen *ms;
07c56447 197{
198 delwin(ms->ms_title);
199 delwin(ms->ms_menu);
200 delwin(ms->ms_input);
201 delwin(ms->ms_screen);
e9db439c 202 free((char *) ms);
07c56447 203}
204
205/*
206 * This guy actually puts up the menu
967b7c08 207 * Note: if margc < 0, no 'r' option will be displayed (i.e., on the
208 * top level menu)
07c56447 209 */
e9db439c 210int
74e7b641 211Do_menu(m, margc, margv)
e9db439c 212 Menu *m;
74e7b641 213 int margc;
214 char *margv[];
07c56447 215{
c13d1215 216 struct menu_screen *my_ms = NULLMS, *old_cur_ms = NULLMS;
07c56447 217 char argvals[MAX_ARGC][MAX_ARGLEN]; /* This is where args are stored */
2aaf83c2 218 char buf[MAX_ARGC * MAX_ARGLEN];
07c56447 219 char *argv[MAX_ARGC];
220 int line;
2aaf83c2 221 int i;
222 struct menu_line *command, *Find_command();
07c56447 223 int argc;
967b7c08 224 int quitflag, is_topmenu = (margc < 0);
859891c0 225 int toggle_logging();
967b7c08 226
07c56447 227 /* Entry function gets called with old menu_screen still current */
11317e48 228 if (m->m_entry != NULLFUNC) {
74e7b641 229 if (m->m_entry(m, margc, margv) == DM_QUIT)
230 return DM_NORMAL;
11317e48 231 if (parsed_argc > 0) {
232 margc = parsed_argc + 1;
233 margv = --parsed_argv;
b5b88538 234 } else {
235 margc--;
236 margv++;
11317e48 237 }
238 }
239
240 parsed_argc = 0;
07c56447 241
2aaf83c2 242 /* The following get run only in curses mode */
e9db439c 243 if (cur_ms != NULLMS) {
2aaf83c2 244 /* Get a menu_screen */
245 old_cur_ms = cur_ms;
859891c0 246 /* 2 is for the 2 obligatory lines; quit and toggle */
247 cur_ms = my_ms = make_ms(m->m_length + 2 + (is_topmenu ? 0 : 1));
07c56447 248
2aaf83c2 249 /* Now print the title and the menu */
e9db439c 250 (void) wclear(my_ms->ms_menu);
251 (void) wmove(my_ms->ms_title, 0, MAX(0, (COLS -
252 strlen(m->m_title)) >> 1));
2aaf83c2 253 (void) wstandout(my_ms->ms_title);
254 (void) waddstr(my_ms->ms_title, m->m_title);
255 (void) wstandend(my_ms->ms_title);
256
e9db439c 257 for (line = 0; line < m->m_length; line++) {
6298c97d 258 int len = strlen(m->m_lines[line].ml_command);
259 if (len > 12) len=12;
260
2aaf83c2 261 (void) wmove(my_ms->ms_menu, line, 0);
6298c97d 262
263 (void) wprintw(my_ms->ms_menu, "%2d. (%s)%*s %s.", line + 1,
e9db439c 264 m->m_lines[line].ml_command,
6298c97d 265 12-len, "",
e9db439c 266 m->m_lines[line].ml_doc);
2aaf83c2 267 }
268 (void) wmove(my_ms->ms_menu, line++, 0);
967b7c08 269 if (!is_topmenu) {
270 (void) waddstr(my_ms->ms_menu,
6298c97d 271 " r. (return) Return to previous menu.");
859891c0 272 (void) wmove(my_ms->ms_menu, line++, 0);
967b7c08 273 }
859891c0 274 (void) waddstr(my_ms->ms_menu,
275 " t. (toggle) Toggle logging on and off.");
276 (void) wmove(my_ms->ms_menu, line, 0);
6298c97d 277 (void) waddstr(my_ms->ms_menu, " q. (quit) Quit.");
33a56ee9 278 } else {
279 Put_message(m->m_title);
280 for (line = 0; line < m->m_length; line++) {
281 sprintf(buf, "%2d. (%s)%*s %s.", line + 1,
282 m->m_lines[line].ml_command,
283 12 - strlen(m->m_lines[line].ml_command), "",
284 m->m_lines[line].ml_doc);
285 Put_message(buf);
286 }
287 if (!is_topmenu)
288 Put_message(" r. (return) Return to previous menu.");
289 Put_message(" t. (toggle) Toggle logging on and off.");
290 Put_message(" q. (quit) Quit.");
291 Put_message(" ?. Print this information.");
07c56447 292 }
07c56447 293
e9db439c 294 for (;;) {
07c56447 295 /* This will be set by a return val from func or submenu */
296 quitflag = DM_NORMAL;
2aaf83c2 297 /* This is here because we may be coming from another menu */
e9db439c 298 if (cur_ms != NULL)
299 touchwin(my_ms->ms_screen);
11317e48 300 if (margc > 1) {
301 /* Initialize argv */
302 for (argc = 0; argc < MAX_ARGC; argc++)
303 argv[argc] = argvals[argc];
304 argc = margc - 1;
305 for (i = 1; i < margc; i++)
306 strcpy(argvals[i - 1], margv[i]);
307 margc = 0;
308 } else {
309 /* Get a command */
310 if (!Prompt_input("Command: ", buf, sizeof(buf))) {
311 if (cur_ms == NULLMS &&
312 feof(stdin))
313 sprintf(buf, "quit");
314 else
315 continue;
316 }
317 /* Parse it into the argument list */
318 /* If there's nothing there, try again */
319 /* Initialize argv */
320 for (argc = 0; argc < MAX_ARGC; argc++)
321 argv[argc] = argvals[argc];
322
323 if ((argc = Parse_words(buf, argv, MAX_ARGLEN)) == 0)
e85f474d 324 continue;
325 }
e9db439c 326 if ((line = atoi(argv[0])) > 0 && line <= m->m_length) {
327 command = &m->m_lines[line - 1];
328 }
967b7c08 329 else if ((!is_topmenu &&
859891c0 330 (!strcmp(argv[0], "r") || !strcmp(argv[0], "return")))
331 || !strcmp(argv[0], "q") || !strcmp(argv[0], "quit")) {
332
07c56447 333 /* here if it's either return or quit */
e9db439c 334 if (cur_ms != NULLMS) {
2aaf83c2 335 cur_ms = old_cur_ms;
336 destroy_ms(my_ms);
337 }
e9db439c 338 if (m->m_exit != NULLFUNC)
339 m->m_exit(m);
340 return (*argv[0] == 'r' ? DM_NORMAL : DM_QUIT);
e9db439c 341 }
33a56ee9 342 else if (argv[0][0] == '?') {
343 for (line = 0; line < m->m_length; line++) {
344 sprintf(buf, "%2d. (%s)%*s %s.", line + 1,
345 m->m_lines[line].ml_command,
346 12 - strlen(m->m_lines[line].ml_command), "",
347 m->m_lines[line].ml_doc);
348 Put_message(buf);
349 }
350 if (!is_topmenu)
351 Put_message(" r. (return) Return to previous menu.");
352 Put_message(" t. (toggle) Toggle logging on and off.");
353 Put_message(" q. (quit) Quit.");
354 continue;
355 }
859891c0 356 else if (!strcmp(argv[0], "t") || !strcmp(argv[0], "toggle")) {
357 toggle_logging(argc, argv);
358 continue;
359 }
360 /* finally, try to find it using Find_command */
73b2adba 361 else if ((command = Find_command(m, argvals[0])) ==
e9db439c 362 (struct menu_line *) 0) {
b5b88538 363 sprintf(buf, "Command not recognized: %s\n", argvals[0]);
364 Put_message(buf);
e9db439c 365 continue;
366 }
2aaf83c2 367 /* If we got to here, command is a valid menu_line */
368 /* Send the offical command name into the argv */
369 (void) strcpy(argvals[0], command->ml_command);
370 /* Show that we're working on it */
371 Put_message(command->ml_doc);
372 /* Print args that we've already got */
e9db439c 373 for (i = 1; i < argc; i++) {
374 if (command->ml_args[i].ma_prompt == NULL)
375 break;
2aaf83c2 376 (void) sprintf(buf, "%s%s", command->ml_args[i].ma_prompt,
377 argv[i]);
378 Put_message(buf);
379 }
380 /* Get remaining arguments, if any */
e9db439c 381 for (; argc < command->ml_argc; argc++) {
967b7c08 382 if (!Prompt_input(command->ml_args[argc].ma_prompt,
383 argvals[argc], sizeof(argvals[argc])))
384 goto punt_command;
2aaf83c2 385 }
11317e48 386 parsed_argc = argc - command->ml_argc;
387 parsed_argv = &(argv[command->ml_argc]);
e9db439c 388 if (command->ml_function != NULLFUNC) {
2aaf83c2 389 /* If it's got a function, call it */
390 quitflag = command->ml_function(argc, argv);
e9db439c 391 }
392 else if (command->ml_submenu != NULLMENU) {
2aaf83c2 393 /* Else see if it is a submenu */
74e7b641 394 quitflag = Do_menu(command->ml_submenu, argc, argv);
e9db439c 395 }
396 else {
2aaf83c2 397 /* If it's got neither, something is wrong */
398 Put_message("*INTERNAL ERROR: NO FUNCTION OR MENU FOR LINE*");
07c56447 399 }
e9db439c 400 if (quitflag == DM_QUIT) {
401 if (cur_ms != NULLMS) {
2aaf83c2 402 cur_ms = old_cur_ms;
403 destroy_ms(my_ms);
404 }
e9db439c 405 if (m->m_exit != NULLFUNC)
406 m->m_exit(m);
11317e48 407 parsed_argc = 0;
e9db439c 408 return (DM_QUIT);
07c56447 409 }
967b7c08 410 punt_command:
11317e48 411 parsed_argc = 0;
07c56447 412 }
413}
414
142e9b37 415refresh_screen()
416{
417 if (cur_ms != NULLMS) {
418 touchwin(cur_ms->ms_screen);
419 refresh_ms(cur_ms);
420 }
421}
422
423
07c56447 424/* Prompt the user for input in the input window of cur_ms */
967b7c08 425int Prompt_input(prompt, buf, buflen)
e9db439c 426 char *prompt;
427 char *buf;
428 int buflen;
07c56447 429{
430 int c;
431 char *p;
c13d1215 432 int y, x, oldx, oldy;
07c56447 433
e9db439c 434 if (cur_ms != NULLMS) {
435 more_flg = 1;
436 getyx(cur_ms->ms_input, y, x);
437 (void) wmove(cur_ms->ms_input, y, 0);
438
75cb4350 439 refresh_screen();
2aaf83c2 440 (void) waddstr(cur_ms->ms_input, prompt);
441 getyx(cur_ms->ms_input, y, x);
e9db439c 442
2aaf83c2 443 oldx = x;
c13d1215 444 oldy = y;
f659480d 445 p = buf;
446 while(1) {
2aaf83c2 447 (void) wmove(cur_ms->ms_input, y, x);
859891c0 448 (void) touchwin(cur_ms->ms_screen);
2aaf83c2 449 (void) wclrtoeol(cur_ms->ms_input);
75cb4350 450 (void) wrefresh(cur_ms->ms_input);
36606b78 451 c = getchar() & 0x7f;
2aaf83c2 452 switch (c) {
967b7c08 453 case CTL('C'):
0e8624c9 454 *p = '\0';
967b7c08 455 return 0;
456 case CTL('Z'):
34f47457 457 (void) kill(getpid(), SIGTSTP);
967b7c08 458 touchwin(curscr);
459 break;
460 case CTL('L'):
e9db439c 461 (void) wclear(cur_ms->ms_input);
462 (void) waddstr(cur_ms->ms_input, prompt);
b4e83c61 463 (void) touchwin(cur_ms->ms_input);
8fd71efe 464 (void) move(LINES - 1, 0);
b4e83c61 465 (void) wrefresh(curscr);
e9db439c 466 getyx(cur_ms->ms_input, y, x);
c13d1215 467 oldy = y;
468 oldx = x;
469 p = buf;
2aaf83c2 470 break;
6298c97d 471
e9db439c 472 case '\n':
473 case '\r':
f659480d 474 goto end_input;
6298c97d 475 /* these should be obtained by doing ioctl() on tty */
2aaf83c2 476 case '\b':
477 case '\177':
478 if (p > buf) {
479 p--;
480 x--;
c13d1215 481 if (x < 0) {
482 (void) wmove(cur_ms->ms_input, y, 0);
483 (void) wclrtoeol(cur_ms->ms_input);
484 y--;
485 x = cur_ms->ms_input->_maxx-1;
486 }
2aaf83c2 487 }
488 break;
967b7c08 489 case CTL('U'):
490 case CTL('G'):
491 case CTL('['):
2aaf83c2 492 x = oldx;
c13d1215 493 y = oldy;
e9db439c 494 p = buf;
2aaf83c2 495 break;
496 default:
9cbd2bba 497 /* (buflen - 1) leaves room for the \0 */
498 if (isprint(c) && (p - buf < buflen - 1)) {
967b7c08 499 (void) waddch(cur_ms->ms_input, c);
500 *p++ = c;
501 x++;
c13d1215 502 if (x >= cur_ms->ms_input->_maxx) {
503 x = 0;
504 y++;
505 }
967b7c08 506 } else
507 putchar(CTL('G'));
2aaf83c2 508 break;
07c56447 509 }
07c56447 510 }
f659480d 511 end_input:
512 (void) waddch(cur_ms->ms_input, '\n');
f659480d 513
514 (void) wclrtoeol(cur_ms->ms_input);
515 refresh_ms(cur_ms);
516 *p = '\0';
517 Start_paging();
6298c97d 518 goto gotit;
f659480d 519 } else {
2aaf83c2 520 printf("%s", prompt);
967b7c08 521 if (gets(buf) == NULL)
522 return 0;
facd6784 523 if (interrupt) {
524 interrupt = 0;
525 return 0;
526 }
2aaf83c2 527 Start_paging();
6298c97d 528 goto gotit;
07c56447 529 }
6298c97d 530gotit:
531 strcpy(buf, strtrim(buf));
532 return 1;
07c56447 533}
534
27de3061 535/* Prompt the user for input in the input window of cur_ms, but don't echo
536 and allow some control characters */
537int Password_input(prompt, buf, buflen)
538 char *prompt;
539 char *buf;
540 int buflen;
541{
542 int c;
543 char *p;
544 int y, x, oldx;
545
546 if (cur_ms != NULLMS) {
547 more_flg = 1;
548 getyx(cur_ms->ms_input, y, x);
549 (void) wmove(cur_ms->ms_input, y, 0);
550
551 touchwin(cur_ms->ms_screen);
552 refresh_ms(cur_ms);
553 (void) waddstr(cur_ms->ms_input, prompt);
554 getyx(cur_ms->ms_input, y, x);
555
556 oldx = x;
557 for (p = buf; p - buf < buflen;) {
558 (void) wmove(cur_ms->ms_input, y, x);
559 (void) wclrtoeol(cur_ms->ms_input);
560 refresh_ms(cur_ms);
36606b78 561 c = getchar() & 0x7f;
27de3061 562 switch (c) {
563 case CTL('C'):
564 return 0;
565 case CTL('Z'):
34f47457 566 (void) kill(getpid(), SIGTSTP);
27de3061 567 touchwin(curscr);
568 break;
569 case CTL('L'):
570 (void) wclear(cur_ms->ms_input);
571 (void) waddstr(cur_ms->ms_input, prompt);
76124208 572 refresh_ms(cur_ms);
8fd71efe 573 (void) move(LINES - 1, 0);
b4e83c61 574 (void) wrefresh(curscr);
27de3061 575 getyx(cur_ms->ms_input, y, x);
576 break;
577 case '\n':
578 case '\r':
579 (void) waddch(cur_ms->ms_input, '\n');
27de3061 580
581 (void) wclrtoeol(cur_ms->ms_input);
582 refresh_ms(cur_ms);
583 *p = '\0';
584 Start_paging();
585 return 1;
586 case '\b':
587 case '\177':
588 if (p > buf) {
589 p--;
590 x--;
591 }
592 break;
593 case CTL('U'):
594 x = oldx;
595 p = buf;
596 break;
597 default:
598 *p++ = c;
599 break;
600 }
601 }
602 }
603 else {
6df34521 604#ifdef POSIX
605 struct termios ttybuf, nttybuf;
98509c19 606#else
27de3061 607 struct sgttyb ttybuf, nttybuf;
6df34521 608#endif /* POSIX */
27de3061 609 printf("%s", prompt);
610 /* turn off echoing */
6df34521 611#ifdef POSIX
612 tcgetattr(0, &ttybuf);
98509c19 613 nttybuf = ttybuf;
614 nttybuf.c_lflag &= ~ECHO;
6df34521 615 tcsetattr(0, TCSANOW, &nttybuf);
98509c19 616 if (gets(buf) == NULL) {
6df34521 617 tcsetattr(0, TCSANOW, &ttybuf);
98509c19 618 putchar('\n');
619 return 0;
620 }
621 putchar('\n');
622 (void) ioctl(0, TCSETA, (char *)&ttybuf);
623#else
34f47457 624 (void) ioctl(0, TIOCGETP, (char *)&ttybuf);
27de3061 625 nttybuf = ttybuf;
626 nttybuf.sg_flags &= ~ECHO;
34f47457 627 (void)ioctl(0, TIOCSETP, (char *)&nttybuf);
27de3061 628 if (gets(buf) == NULL) {
34f47457 629 (void) ioctl(0, TIOCSETP, (char *)&ttybuf);
27de3061 630 putchar('\n');
631 return 0;
632 }
633 putchar('\n');
34f47457 634 (void) ioctl(0, TIOCSETP, (char *)&ttybuf);
6df34521 635#endif /* POSIX */
27de3061 636 Start_paging();
637 return 1;
638 }
34f47457 639 return 0;
27de3061 640}
641
2aaf83c2 642int lines_left;
643
644/* Start paging */
645/* This routine will cause the most recently put message to be the
646 one at the top of the screen when a ---More--- prompt is displayed */
647Start_paging()
648{
e9db439c 649 if (cur_ms != NULLMS) {
2aaf83c2 650 lines_left = LINES - cur_ms->ms_input_y - 1;
e9db439c 651 }
652 else {
2aaf83c2 653 lines_left = 23;
654 }
655}
656
657/* Turn off paging */
658Stop_paging()
659{
660 lines_left = -1;
661}
662
f659480d 663/* Print a message in the input window of cur_ms. */
07c56447 664Put_message(msg)
f659480d 665char *msg;
666{
667 char *copy, *line, *s;
668
34f47457 669 copy = (char *) malloc((u_int)COLS);
f659480d 670 s = line = msg;
859891c0 671 if (log_file) { /* if we're doing logging; we assume that the */
672 /* file has already been opened. */
673 (void) fprintf(log_file, "%s\n", msg);
674 fflush(log_file);
675 }
676
f659480d 677 while(*s++) {
678 if (s - line >= COLS-1) {
34f47457 679 (void) strncpy(copy, line, COLS-1);
f659480d 680 line += COLS-1;
681 } else if (*s == '\n') {
682 *s = '\0';
34f47457 683 (void) strcpy(copy, line);
f659480d 684 line = ++s;
685 } else
686 continue;
687 Put_line(copy);
688 }
689 Put_line(line);
690 free(copy);
691}
692
693/* Will be truncated to COLS characters. */
694Put_line(msg)
695char *msg;
07c56447 696{
e9db439c 697 int y, x, i;
698 char *msg1, chr;
699
700 if (!more_flg)
701 return;
2aaf83c2 702
e9db439c 703 if (lines_left >= 0) {
704 if (--lines_left == 0) {
2aaf83c2 705 /* Give the user a more prompt */
e9db439c 706 if (cur_ms != NULLMS) {
2aaf83c2 707 (void) wstandout(cur_ms->ms_input);
708 (void) wprintw(cur_ms->ms_input, "---More---");
709 (void) wstandend(cur_ms->ms_input);
710 refresh_ms(cur_ms);
36606b78 711 chr = getchar() & 0x7f;/* We do care what it is */
b5b88538 712 if (chr == 'q' || chr == 'Q' || chr == 3 /* ^C */) {
e9db439c 713 more_flg = 0;
714 return;
715 }
2aaf83c2 716 getyx(cur_ms->ms_input, y, x);
34f47457 717 /* x is a bitbucket; avoid lint problems */
718 x=x;
2aaf83c2 719 (void) wmove(cur_ms->ms_input, y, 0);
720 (void) wclrtoeol(cur_ms->ms_input);
e9db439c 721 }
722 else {
2aaf83c2 723 printf("---More (hit return)---");
d5d12a44 724 getchar();
2aaf83c2 725 }
726 Start_paging(); /* Reset lines_left */
727 }
728 }
e9db439c 729
730 if (cur_ms != NULLMS) {
34f47457 731 msg1 = (char *) calloc((u_int)COLS, 1);
f659480d 732 (void) strncpy(msg1, msg, COLS-1);
733 for (i = strlen(msg1); i < COLS - 1; i++)
e9db439c 734 msg1[i] = ' ';
735 (void) wprintw(cur_ms->ms_input, "%s\n", msg1);
e9db439c 736 }
737 else {
2aaf83c2 738 puts(msg);
739 }
07c56447 740}
741
742/* Refresh a menu_screen onto the real screen */
743refresh_ms(ms)
e9db439c 744 struct menu_screen *ms;
07c56447 745{
75cb4350 746 (void) wrefresh(ms->ms_title);
747 (void) wrefresh(ms->ms_menu);
748 (void) wrefresh(ms->ms_input);
2aaf83c2 749}
750
751/* Parse buf into a list of words, which will be placed in strings specified by
752 argv. Space for these strings must have already been allocated.
753 Only the first n characters of each word will be copied */
754Parse_words(buf, argv, n)
e9db439c 755 char *buf;
756 char *argv[];
2aaf83c2 757int n;
e9db439c 758
2aaf83c2 759{
760 char *start, *end; /* For sausage machine */
761 int argc;
762
763 start = buf;
e9db439c 764 for (argc = 0; argc < MAX_ARGC; argc++) {
765 while (isspace(*start))
766 start++; /* Kill whitespace */
767 if (*start == '\0')
768 break; /* Nothing left */
2aaf83c2 769 /* Now find the end of the word */
e9db439c 770 for (end = start; *end != '\0' && !isspace(*end); end++);
771 (void) strncpy(argv[argc], start, MIN(end - start, n)); /* Copy it */
772 argv[argc][MIN(end - start, n - 1)] = '\0'; /* Terminate */
2aaf83c2 773 start = end;
774 }
e9db439c 775 return (argc);
2aaf83c2 776}
777
778/* This is the internal form of Find_command, which recursively searches
779 for a menu_line with command command in the specified menu */
780/* It will search to a maximum depth of d */
e9db439c 781struct menu_line *
782find_command_from(c, m, d)
783 char *c;
784 struct menu *m;
785 int d;
2aaf83c2 786{
787 int line;
788 struct menu_line *maybe;
789
e9db439c 790 if (d < 0)
791 return ((struct menu_line *) 0); /* Too deep! */
792 for (line = 0; line < m->m_length; line++) {
793 if (!strcmp(c, m->m_lines[line].ml_command)) {
794 return (&m->m_lines[line]);
795 }
73b2adba 796 }
797 for (line = 0; line < m->m_length; line++) {
798 if (m->m_lines[line].ml_submenu != NULLMENU &&
799 (maybe = find_command_from(c, m->m_lines[line].ml_submenu, d - 1))
800 != (struct menu_line *) 0) {
e9db439c 801 return (maybe);
802 }
2aaf83c2 803 }
804 /* If we got to here, nothing works */
e9db439c 805 return ((struct menu_line *) 0);
07c56447 806}
2aaf83c2 807
808/* Find_command searches down the current menu tree */
809/* And returns a pointer to a menu_line with the specified command name */
810/* It returns (struct menu_line *) 0 if none is found */
e9db439c 811struct menu_line *
73b2adba 812Find_command(m, command)
813 Menu *m;
e9db439c 814 char *command;
2aaf83c2 815{
73b2adba 816 if (m == NULLMENU) {
e9db439c 817 return ((struct menu_line *) 0);
818 }
819 else {
73b2adba 820 return (find_command_from(command, m, MAX_MENU_DEPTH));
2aaf83c2 821 }
822}
22705d2b 823
859891c0 824/*ARGSUSED*/
825int
826toggle_logging(argc, argv)
827 int argc;
828 char *argv[];
829{
830 int pid;
831 char buf[BUFSIZ];
832
833 if (log_file == (FILE *) NULL) {
834 pid = getpid();
835 if (!whoami) {
859891c0 836 Put_message("I've lost my SENSE of DIRECTION! I have no IDEA who I AM!");
837 Put_message("My God... You've turned him into a DEMOCRAT!!");
838 Put_message(" -- Doonesbury");
839 Put_message("");
840 Put_message("translation: your log file can be found in \"/usr/tmp/a.out.pid\".");
841 whoami = "a.out";
842 (void) sprintf(buf, "/usr/tmp/%s-log.%d", whoami, pid);
843 }
844 else
845 (void) sprintf(buf, "/usr/tmp/%s-log.%d", whoami, pid);
846
847 /* open the file */
33a56ee9 848 log_file = fopen(buf,"a");
859891c0 849
850 if (log_file == (FILE *) NULL)
851 Put_message("Open of log file failed. Logging is not on.");
852 else
853 Put_message("Log file successfully opened.");
854 }
855 else { /* log_file is a valid pointer; turn off logging. */
856 (void) fflush(log_file);
857 (void) fclose(log_file);
858 log_file = (FILE *) NULL;
859 Put_message("Logging off.");
860 }
861 return(DM_NORMAL);
862}
This page took 0.369496 seconds and 5 git commands to generate.