* $Source$
* $Author$
* $Header$
- * $Log$
- * Revision 1.6 1987-08-17 11:55:23 jtkohl
- * changes made by poto. Looks like cleanup
- *
- * Revision 1.5 87/08/07 18:09:46 poto
- * will not enter menu if ->m_entry returns DM_QUIT;
- * the command args from a submenu command will be passed on to ->m_entry();
- *
- * Revision 1.4 87/08/05 14:48:04 ambar
- * added latest set of hackery, to fix missing
- * newlines, and not being able to quit out of
- * the pager.
- *
- * Revision 1.3 87/08/03 05:10:34 wesommer
- * This one appears to work.
- *
- * Revision 1.2 87/08/03 04:16:51 wesommer
- * Here's another, which is probably better.
- *
- * Revision 1.1 87/07/31 18:02:23 ambar
- * Initial revision
- *
*
* Generic menu system module.
*
#endif lint
+#include <mit-copyright.h>
+#include <sys/types.h>
#include <stdio.h>
#include <signal.h>
#include <curses.h>
#include <ctype.h>
+#include <strings.h>
+#include <varargs.h>
+#include <com_err.h>
#include "menu.h"
#define MAX(A,B) ((A) > (B) ? (A) : (B))
#define MIN_INPUT 2 /* Minimum number of lines for input window */
-char *strcpy();
-char *strncpy();
+extern FILE *fdopen();
+extern int getpid();
+extern char *calloc();
+extern char *whoami;
+
+FILE *log_file = (FILE *) NULL; /* file stream of log file */
int more_flg = 1;
/* Structure for holding current displayed menu */
Menu *top_menu; /* Root for command search */
+/*
+ * Hook function to cause error messages to be printed through
+ * curses instead of around it.
+ */
+
+int
+menu_com_err_hook(who, code, fmt, args)
+ char *who;
+ int code;
+ char *fmt;
+ va_list args;
+{
+ char buf[BUFSIZ], *cp;
+
+ FILE _strbuf;
+
+ (void) strcpy(buf, who);
+ for (cp = buf; *cp; cp++);
+ *cp++ = ':';
+ *cp++ = ' ';
+ if (code) {
+ (void) strcpy(cp, error_message(code));
+ while (*cp)
+ cp++;
+ }
+ _strbuf._flag = _IOWRT + _IOSTRG;
+ _strbuf._ptr = cp;
+ _strbuf._cnt = BUFSIZ - (cp - buf);
+ _doprnt(fmt, args, &_strbuf);
+ (void) putc('\0', &_strbuf);
+ Put_message(buf);
+}
+
/*
* Start_menu takes a menu as an argument. It initializes curses u.s.w.,
* and a quit in any submenu should unwind back to here. (it might not,
Menu *m;
{
struct menu_screen *make_ms();
-
+ register int (*old_hook)() = set_com_err_hook(menu_com_err_hook);
+
if (initscr() == ERR) {
fputs("Can't initialize curses!\n", stderr);
Start_no_menu(m);
- }
- raw(); /* We parse & print everything ourselves */
- noecho();
- cur_ms = make_ms(0); /* So we always have some current */
+ } else {
+ (void) raw(); /* We parse & print everything ourselves */
+ (void) noecho();
+ cur_ms = make_ms(0); /* So we always have some current */
/* menu_screen */
- top_menu = m;
- /* Run the menu */
- (void) Do_menu(m, -1, (char **) NULL);
+ /* Run the menu */
+ (void) Do_menu(m, -1, (char **) NULL);
+ }
+ (void) set_com_err_hook(old_hook);
Cleanup_menu();
}
Cleanup_menu()
{
if (cur_ms) {
- wclear(cur_ms->ms_screen);
- wrefresh(cur_ms->ms_screen);
+ (void) wclear(cur_ms->ms_screen);
+ (void) wrefresh(cur_ms->ms_screen);
}
endwin();
}
Menu *m;
{
cur_ms = NULLMS;
- top_menu = m;
+ COLS = 80;
/* Run the menu */
(void) Do_menu(m, -1, (char **) NULL);
}
struct menu_line *command, *Find_command();
int argc;
int quitflag, is_topmenu = (margc < 0);
+ int toggle_logging();
/* Entry function gets called with old menu_screen still current */
if (m->m_entry != NULLFUNC)
if (cur_ms != NULLMS) {
/* Get a menu_screen */
old_cur_ms = cur_ms;
- cur_ms = my_ms = make_ms(m->m_length + 1 + (is_topmenu?0:1));
+ /* 2 is for the 2 obligatory lines; quit and toggle */
+ cur_ms = my_ms = make_ms(m->m_length + 2 + (is_topmenu ? 0 : 1));
/* Now print the title and the menu */
(void) wclear(my_ms->ms_menu);
(void) wstandend(my_ms->ms_title);
for (line = 0; line < m->m_length; line++) {
+ int len = strlen(m->m_lines[line].ml_command);
+ if (len > 12) len=12;
+
(void) wmove(my_ms->ms_menu, line, 0);
- (void) wprintw(my_ms->ms_menu, "%2d. (%-12s) %s.", line + 1,
+
+ (void) wprintw(my_ms->ms_menu, "%2d. (%s)%*s %s.", line + 1,
m->m_lines[line].ml_command,
+ 12-len, "",
m->m_lines[line].ml_doc);
}
(void) wmove(my_ms->ms_menu, line++, 0);
if (!is_topmenu) {
(void) waddstr(my_ms->ms_menu,
- " r. (return ) Return to previous menu.");
- (void) wmove(my_ms->ms_menu, line, 0);
+ " r. (return) Return to previous menu.");
+ (void) wmove(my_ms->ms_menu, line++, 0);
}
- (void) waddstr(my_ms->ms_menu, " q. (quit ) Quit.");
-
+ (void) waddstr(my_ms->ms_menu,
+ " t. (toggle) Toggle logging on and off.");
+ (void) wmove(my_ms->ms_menu, line, 0);
+ (void) waddstr(my_ms->ms_menu, " q. (quit) Quit.");
+ } else {
+ Put_message(m->m_title);
+ for (line = 0; line < m->m_length; line++) {
+ sprintf(buf, "%2d. (%s)%*s %s.", line + 1,
+ m->m_lines[line].ml_command,
+ 12 - strlen(m->m_lines[line].ml_command), "",
+ m->m_lines[line].ml_doc);
+ Put_message(buf);
+ }
+ if (!is_topmenu)
+ Put_message(" r. (return) Return to previous menu.");
+ Put_message(" t. (toggle) Toggle logging on and off.");
+ Put_message(" q. (quit) Quit.");
+ Put_message(" ?. Print this information.");
}
for (;;) {
command = &m->m_lines[line - 1];
}
else if ((!is_topmenu &&
- (!strcmp(argv[0], "r")
- || !strcmp(argv[0], "return")))
- || !strcmp(argv[0], "q")
- || !strcmp(argv[0], "quit")) {
+ (!strcmp(argv[0], "r") || !strcmp(argv[0], "return")))
+ || !strcmp(argv[0], "q") || !strcmp(argv[0], "quit")) {
+
/* here if it's either return or quit */
if (cur_ms != NULLMS) {
cur_ms = old_cur_ms;
if (m->m_exit != NULLFUNC)
m->m_exit(m);
return (*argv[0] == 'r' ? DM_NORMAL : DM_QUIT);
- /* finally, try to find it using Find_command */
}
- else if ((command = Find_command(argvals[0])) ==
+ else if (argv[0][0] == '?') {
+ for (line = 0; line < m->m_length; line++) {
+ sprintf(buf, "%2d. (%s)%*s %s.", line + 1,
+ m->m_lines[line].ml_command,
+ 12 - strlen(m->m_lines[line].ml_command), "",
+ m->m_lines[line].ml_doc);
+ Put_message(buf);
+ }
+ if (!is_topmenu)
+ Put_message(" r. (return) Return to previous menu.");
+ Put_message(" t. (toggle) Toggle logging on and off.");
+ Put_message(" q. (quit) Quit.");
+ continue;
+ }
+ else if (!strcmp(argv[0], "t") || !strcmp(argv[0], "toggle")) {
+ toggle_logging(argc, argv);
+ continue;
+ }
+ /* finally, try to find it using Find_command */
+ else if ((command = Find_command(m, argvals[0])) ==
(struct menu_line *) 0) {
Put_message("Command not recognized");
continue;
char *p;
int y, x, oldx;
+ if (cur_ms != NULLMS) {
+ more_flg = 1;
+ getyx(cur_ms->ms_input, y, x);
+ (void) wmove(cur_ms->ms_input, y, 0);
+
+ touchwin(cur_ms->ms_screen);
+ refresh_ms(cur_ms);
+ (void) waddstr(cur_ms->ms_input, prompt);
+ getyx(cur_ms->ms_input, y, x);
+
+ oldx = x;
+ p = buf;
+ while(1) {
+ (void) wmove(cur_ms->ms_input, y, x);
+ (void) touchwin(cur_ms->ms_screen);
+ (void) wclrtoeol(cur_ms->ms_input);
+ refresh_ms(cur_ms);
+ c = getchar() & 0x7f;
+ switch (c) {
+ case CTL('C'):
+ *p = '\0';
+ return 0;
+ case CTL('Z'):
+ (void) kill(getpid(), SIGTSTP);
+ touchwin(curscr);
+ break;
+ case CTL('L'):
+ (void) wclear(cur_ms->ms_input);
+ (void) waddstr(cur_ms->ms_input, prompt);
+ (void) touchwin(cur_ms->ms_screen);
+#ifdef notdef
+ refresh_ms(cur_ms);
+#endif notdef
+ getyx(cur_ms->ms_input, y, x);
+ break;
+
+ case '\n':
+ case '\r':
+ goto end_input;
+ /* these should be obtained by doing ioctl() on tty */
+ case '\b':
+ case '\177':
+ if (p > buf) {
+ p--;
+ x--;
+ }
+ break;
+ case CTL('U'):
+ case CTL('G'):
+ case CTL('['):
+ x = oldx;
+ p = buf;
+ break;
+ default:
+ /* (buflen - 1) leaves room for the \0 */
+ if (isprint(c) && (p - buf < buflen - 1)) {
+ (void) waddch(cur_ms->ms_input, c);
+ *p++ = c;
+ x++;
+ } else
+ putchar(CTL('G'));
+ break;
+ }
+ }
+ end_input:
+ (void) waddch(cur_ms->ms_input, '\n');
+ (void) waddch(cur_ms->ms_input, '\r');
+
+ (void) wclrtoeol(cur_ms->ms_input);
+ refresh_ms(cur_ms);
+ *p = '\0';
+ Start_paging();
+ goto gotit;
+ } else {
+ printf("%s", prompt);
+ if (gets(buf) == NULL)
+ return 0;
+ Start_paging();
+ goto gotit;
+ }
+gotit:
+ strcpy(buf, strtrim(buf));
+ return 1;
+}
+
+/* Prompt the user for input in the input window of cur_ms, but don't echo
+ and allow some control characters */
+int Password_input(prompt, buf, buflen)
+ char *prompt;
+ char *buf;
+ int buflen;
+{
+ int c;
+ char *p;
+ int y, x, oldx;
+
if (cur_ms != NULLMS) {
more_flg = 1;
getyx(cur_ms->ms_input, y, x);
(void) wmove(cur_ms->ms_input, y, x);
(void) wclrtoeol(cur_ms->ms_input);
refresh_ms(cur_ms);
- c = getchar();
+ c = getchar() & 0x7f;
switch (c) {
case CTL('C'):
return 0;
case CTL('Z'):
- kill(getpid(), SIGTSTP);
+ (void) kill(getpid(), SIGTSTP);
touchwin(curscr);
break;
case CTL('L'):
(void) wclear(cur_ms->ms_input);
(void) waddstr(cur_ms->ms_input, prompt);
- wrefresh(curscr);
+ refresh_ms(cur_ms);
getyx(cur_ms->ms_input, y, x);
break;
case '\n':
}
break;
case CTL('U'):
- case CTL('G'):
- case CTL('['):
x = oldx;
p = buf;
break;
default:
- if (isprint(c)) {
- (void) waddch(cur_ms->ms_input, c);
- *p++ = c;
- x++;
- } else
- putchar(CTL('G'));
+ *p++ = c;
break;
}
}
}
else {
+ struct sgttyb ttybuf, nttybuf;
printf("%s", prompt);
- if (gets(buf) == NULL)
+ /* turn off echoing */
+ (void) ioctl(0, TIOCGETP, (char *)&ttybuf);
+ nttybuf = ttybuf;
+ nttybuf.sg_flags &= ~ECHO;
+ (void)ioctl(0, TIOCSETP, (char *)&nttybuf);
+ if (gets(buf) == NULL) {
+ (void) ioctl(0, TIOCSETP, (char *)&ttybuf);
+ putchar('\n');
return 0;
+ }
+ putchar('\n');
+ (void) ioctl(0, TIOCSETP, (char *)&ttybuf);
Start_paging();
return 1;
}
+ return 0;
}
int lines_left;
lines_left = -1;
}
-/* Print a message in the input window of cur_ms */
+/* Print a message in the input window of cur_ms. */
Put_message(msg)
- char *msg;
+char *msg;
+{
+ char *copy, *line, *s;
+
+ copy = (char *) malloc((u_int)COLS);
+ s = line = msg;
+ if (log_file) { /* if we're doing logging; we assume that the */
+ /* file has already been opened. */
+ (void) fprintf(log_file, "%s\n", msg);
+ fflush(log_file);
+ }
+
+ while(*s++) {
+ if (s - line >= COLS-1) {
+ (void) strncpy(copy, line, COLS-1);
+ line += COLS-1;
+ } else if (*s == '\n') {
+ *s = '\0';
+ (void) strcpy(copy, line);
+ line = ++s;
+ } else
+ continue;
+ Put_line(copy);
+ }
+ Put_line(line);
+ free(copy);
+}
+
+/* Will be truncated to COLS characters. */
+Put_line(msg)
+char *msg;
{
int y, x, i;
char *msg1, chr;
(void) wprintw(cur_ms->ms_input, "---More---");
(void) wstandend(cur_ms->ms_input);
refresh_ms(cur_ms);
- chr = getchar();/* We do care what it is */
+ chr = getchar() & 0x7f;/* We do care what it is */
if (chr == 'q' || chr == 'Q') {
more_flg = 0;
return;
}
getyx(cur_ms->ms_input, y, x);
+ /* x is a bitbucket; avoid lint problems */
+ x=x;
(void) wmove(cur_ms->ms_input, y, 0);
(void) wclrtoeol(cur_ms->ms_input);
}
else {
printf("---More (hit return)---");
- (void) getchar();
+ getchar();
}
Start_paging(); /* Reset lines_left */
}
}
if (cur_ms != NULLMS) {
- msg1 = (char *) calloc(COLS, 1);
- (void) strcpy(msg1, msg);
- for (i = strlen(msg); i < COLS - 1; i++)
+ msg1 = (char *) calloc((u_int)COLS, 1);
+ (void) strncpy(msg1, msg, COLS-1);
+ for (i = strlen(msg1); i < COLS - 1; i++)
msg1[i] = ' ';
(void) wprintw(cur_ms->ms_input, "%s\n", msg1);
/* refresh_ms(cur_ms); */
if (!strcmp(c, m->m_lines[line].ml_command)) {
return (&m->m_lines[line]);
}
- else if (m->m_lines[line].ml_submenu != NULLMENU
- && (maybe =
- find_command_from(c, m->m_lines[line].ml_submenu, d - 1))
- != (struct menu_line *) 0) {
+ }
+ for (line = 0; line < m->m_length; line++) {
+ if (m->m_lines[line].ml_submenu != NULLMENU &&
+ (maybe = find_command_from(c, m->m_lines[line].ml_submenu, d - 1))
+ != (struct menu_line *) 0) {
return (maybe);
}
}
/* And returns a pointer to a menu_line with the specified command name */
/* It returns (struct menu_line *) 0 if none is found */
struct menu_line *
-Find_command(command)
+Find_command(m, command)
+ Menu *m;
char *command;
{
- if (top_menu == NULLMENU) {
+ if (m == NULLMENU) {
return ((struct menu_line *) 0);
}
else {
- return (find_command_from(command, top_menu, MAX_MENU_DEPTH));
+ return (find_command_from(command, m, MAX_MENU_DEPTH));
}
}
-/*
- * Local Variables:
- * mode: c
- * c-indent-level: 4
- * c-continued-statement-offset: 4
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * End:
- */
+/*ARGSUSED*/
+int
+toggle_logging(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int pid;
+ char buf[BUFSIZ];
+
+ if (log_file == (FILE *) NULL) {
+ pid = getpid();
+ if (!whoami) {
+ Put_message("I've lost my SENSE of DIRECTION! I have no IDEA who I AM!");
+ Put_message("My God... You've turned him into a DEMOCRAT!!");
+ Put_message(" -- Doonesbury");
+ Put_message("");
+ Put_message("translation: your log file can be found in \"/usr/tmp/a.out.pid\".");
+ whoami = "a.out";
+ (void) sprintf(buf, "/usr/tmp/%s-log.%d", whoami, pid);
+ }
+ else
+ (void) sprintf(buf, "/usr/tmp/%s-log.%d", whoami, pid);
+
+ /* open the file */
+ log_file = fopen(buf,"a");
+
+ if (log_file == (FILE *) NULL)
+ Put_message("Open of log file failed. Logging is not on.");
+ else
+ Put_message("Log file successfully opened.");
+ }
+ else { /* log_file is a valid pointer; turn off logging. */
+ (void) fflush(log_file);
+ (void) fclose(log_file);
+ log_file = (FILE *) NULL;
+ Put_message("Logging off.");
+ }
+ return(DM_NORMAL);
+}