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