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