-/*
- * Copyright 1987 by the Massachusetts Institute of Technology.
- * For copying and distribution information, see the file
- * "mit-copyright.h".
- *
- * $Source$
- * $Author$
- * $Header$
+/* $Id$
*
* Generic menu system module.
*
- * Basically, we define an enormous tree structure which represents the
- * menu. Some extra pieces (ml_command, ma_doc) get thrown in so we can
- * also use the structure for a command-based system.
- *
- * By making the menu descriptions so general, we can ease porting to just
- * about anything.
+ * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, see the file
+ * <mit-copyright.h>.
*/
-#ifndef lint
-static char rcsid_menu_c[] = "$Header$";
-
-#endif lint
-
-#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 <mit-copyright.h>
+#include <moira.h>
#include "menu.h"
-#define MAX(A,B) ((A) > (B) ? (A) : (B))
-#define MIN(A,B) ((A) < (B) ? (A) : (B))
+#include <ctype.h>
+#ifdef HAVE_CURSES
+#include <curses.h>
+#endif
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#include <conio.h>
+#include <process.h>
+#ifdef getchar
+#undef getchar
+#endif
+#define getchar() _getch()
+#define getpid _getpid
+#endif /* _WIN32 */
+
+RCSID("$Header$");
+
+#ifdef MAX
+#undef MAX
+#undef MIN
+#endif
+#define MAX(A, B) ((A) > (B) ? (A) : (B))
+#define MIN(A, B) ((A) < (B) ? (A) : (B))
#define CTL(ch) ((ch) & 037)
#define MIN_INPUT 2 /* Minimum number of lines for input window */
-extern FILE *fdopen();
-extern int getpid();
-extern char *calloc();
+extern int interrupt; /* will be set if ^C is received */
extern char *whoami;
FILE *log_file = (FILE *) NULL; /* file stream of log file */
/* Structure for holding current displayed menu */
struct menu_screen {
- WINDOW *ms_screen; /* Window for this menu */
- WINDOW *ms_title; /* Title subwindow */
- WINDOW *ms_menu; /* Menu subwindow */
- WINDOW *ms_input; /* Input subwindow */
- int ms_input_y; /* Input subwindow reference coordinate */
-} *cur_ms;
+#ifdef HAVE_CURSES
+ WINDOW *ms_screen; /* Window for this menu */
+ WINDOW *ms_title; /* Title subwindow */
+ WINDOW *ms_menu; /* Menu subwindow */
+ WINDOW *ms_input; /* Input subwindow */
+#endif /* HAVE_CURSES */
+ int ms_input_y; /* Input subwindow reference coordinate */
+} *cur_ms;
+
+#ifndef HAVE_CURSES
+int COLS;
+#endif
#define NULLMS ((struct menu_screen *) 0)
Menu *top_menu; /* Root for command search */
+int parsed_argc; /* used by extern routines to get additional */
+char **parsed_argv; /* comand line input */
+
+int Parse_words(char *buf, char *argv[], int n);
+void refresh_ms(struct menu_screen *ms);
+void Put_line(char *msg);
+void menu_com_err_hook(const char *who, long code,
+ const char *fmt, va_list ap);
+struct menu_screen *make_ms(int length);
+void destroy_ms(struct menu_screen *ms);
+struct menu_line *find_command_from(char *c, struct menu *m, int d);
+struct menu_line *Find_command(Menu *m, char *command);
+int toggle_logging(int argc, char *argv[]);
/*
* 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;
+void menu_com_err_hook(const char *who, long code, const char *fmt, va_list ap)
{
- 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++;
+ char buf[BUFSIZ], *cp;
+
+ if (who)
+ {
+ strcpy(buf, who);
+ for (cp = buf; *cp; cp++)
+ ;
+ *cp++ = ':';
+ *cp++ = ' ';
+ }
+ else
+ {
+ cp = buf;
+ *cp = '\0';
}
- _strbuf._flag = _IOWRT + _IOSTRG;
- _strbuf._ptr = cp;
- _strbuf._cnt = BUFSIZ - (cp - buf);
- _doprnt(fmt, args, &_strbuf);
- (void) putc('\0', &_strbuf);
- Put_message(buf);
+ if (code)
+ {
+ strcpy(cp, error_message(code));
+ while (*cp)
+ cp++;
+ }
+ vsprintf(cp, fmt, ap);
+ Put_message(buf);
}
+#ifdef HAVE_CURSES
/*
* 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,
* if user functions which run their own menus don't cooperate.)
* Start_menu should only be called once, at the start of the program.
*/
-Start_menu(m)
- Menu *m;
+void Start_menu(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);
- } 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);
+ void (*old_hook)(const char *, long, const char *, va_list) =
+ set_com_err_hook(menu_com_err_hook);
+#ifdef CURSES_HAS_NEWTERM
+ SCREEN *scrn = newterm(NULL, stdout, stdin);
+#else
+ WINDOW *scrn = initscr();
+#endif
+ if (!scrn)
+ {
+ fputs("Can't initialize curses!\nReverting to -nomenu mode\n\n", stderr);
+ Start_no_menu(m);
}
- (void) set_com_err_hook(old_hook);
- Cleanup_menu();
-}
-
-Cleanup_menu()
-{
- if (cur_ms) {
- (void) wclear(cur_ms->ms_screen);
- (void) wrefresh(cur_ms->ms_screen);
+ else
+ {
+#ifdef CURSES_HAS_NEWTERM
+ set_term(scrn);
+ endwin();
+ initscr();
+#endif
+ raw(); /* We parse & print everything ourselves */
+ noecho();
+ cur_ms = make_ms(0); /* So we always have some current */
+ /* menu_screen */
+ /* Run the menu */
+ Do_menu(m, -1, NULL);
+ Cleanup_menu();
}
- endwin();
+ set_com_err_hook(old_hook);
}
-
-/* Like Start_menu, except it doesn't print menus and doesn't use curses */
-Start_no_menu(m)
- Menu *m;
+void Cleanup_menu(void)
{
- cur_ms = NULLMS;
- COLS = 80;
- top_menu = m;
- /* Run the menu */
- (void) Do_menu(m, -1, (char **) NULL);
+ if (cur_ms)
+ {
+ wclear(cur_ms->ms_screen);
+ wrefresh(cur_ms->ms_screen);
+ endwin();
+ }
}
/*
* Create a new menu screen template with the specified menu length
* and return it.
*/
-struct menu_screen *
-make_ms(length)
- int length;
+struct menu_screen *make_ms(int length)
{
- struct menu_screen *ms;
- char *malloc();
+ struct menu_screen *ms;
- if (MAX_TITLE + length + MIN_INPUT > LINES) {
- fputs("Menu too big!\n", stderr);
- exit(2);
+ if (MAX_TITLE + length + MIN_INPUT > LINES)
+ {
+ fputs("Menu too big!\n", stderr);
+ exit(2);
}
- ms = (struct menu_screen *) malloc(sizeof(struct menu_screen));
+ ms = malloc(sizeof(struct menu_screen));
- ms->ms_screen = newwin(0, 0, 0, 0);
- ms->ms_title = subwin(ms->ms_screen, MAX_TITLE, 0, 0, 0);
- ms->ms_menu = subwin(ms->ms_screen,
- length, 0, MAX_TITLE, 0);
- ms->ms_input = subwin(ms->ms_screen, 0, 0,
- ms->ms_input_y = MAX_TITLE + length,
- 0);
+ ms->ms_screen = newwin(0, 0, 0, 0);
+ ms->ms_title = subwin(ms->ms_screen, MAX_TITLE, 0, 0, 0);
+ ms->ms_menu = subwin(ms->ms_screen, length, 0, MAX_TITLE, 0);
+ ms->ms_input = subwin(ms->ms_screen, 0, 0,
+ ms->ms_input_y = MAX_TITLE + length,
+ 0);
- scrollok(ms->ms_input, TRUE);
- (void) wmove(ms->ms_input, 0, 0);
- (void) wclear(ms->ms_screen);
+ scrollok(ms->ms_input, TRUE);
+ wmove(ms->ms_input, 0, 0);
+ wclear(ms->ms_screen);
- return (ms);
+ return ms;
}
/*
* This routine destroys a menu_screen.
*/
-destroy_ms(ms)
- struct menu_screen *ms;
+void destroy_ms(struct menu_screen *ms)
{
- delwin(ms->ms_title);
- delwin(ms->ms_menu);
- delwin(ms->ms_input);
- delwin(ms->ms_screen);
- free((char *) ms);
+ delwin(ms->ms_title);
+ delwin(ms->ms_menu);
+ delwin(ms->ms_input);
+ delwin(ms->ms_screen);
+ free(ms);
+}
+#endif /* HAVE_CURSES */
+
+/* Like Start_menu, except it doesn't print menus and doesn't use curses */
+void Start_no_menu(Menu *m)
+{
+ cur_ms = NULLMS;
+ COLS = 80;
+ /* Run the menu */
+ Do_menu(m, -1, NULL);
}
/*
* Note: if margc < 0, no 'r' option will be displayed (i.e., on the
* top level menu)
*/
-int
-Do_menu(m, margc, margv)
- Menu *m;
- int margc;
- char *margv[];
+int Do_menu(Menu *m, int margc, char *margv[])
{
- struct menu_screen *my_ms, *old_cur_ms;
- char argvals[MAX_ARGC][MAX_ARGLEN]; /* This is where args are stored */
- char buf[MAX_ARGC * MAX_ARGLEN];
- char *argv[MAX_ARGC];
- int line;
- int i;
- 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 (m->m_entry(m, margc, margv) == DM_QUIT)
- return DM_NORMAL;
-
- /* The following get run only in curses mode */
- if (cur_ms != NULLMS) {
- /* Get a menu_screen */
- old_cur_ms = cur_ms;
- /* 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) wmove(my_ms->ms_title, 0, MAX(0, (COLS -
- strlen(m->m_title)) >> 1));
- (void) wstandout(my_ms->ms_title);
- (void) waddstr(my_ms->ms_title, m->m_title);
- (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. (%s)%*s %s.", line + 1,
- m->m_lines[line].ml_command,
- 12-len, "",
- m->m_lines[line].ml_doc);
+ struct menu_screen *my_ms = NULLMS, *old_cur_ms = NULLMS;
+ char argvals[MAX_ARGC][MAX_ARGLEN]; /* This is where args are stored */
+ char buf[MAX_ARGC * MAX_ARGLEN];
+ char *argv[MAX_ARGC];
+ int line;
+ int i;
+ struct menu_line *command;
+ int argc;
+ int quitflag, is_topmenu = (margc < 0);
+
+ /* Entry function gets called with old menu_screen still current */
+ if (m->m_entry != NULLFUNC)
+ {
+ if (m->m_entry(m, margc, margv) == DM_QUIT)
+ return DM_NORMAL;
+ if (parsed_argc > 0)
+ {
+ margc = parsed_argc + 1;
+ margv = --parsed_argv;
+ }
+ else
+ {
+ margc--;
+ margv++;
+ }
+ }
+
+ parsed_argc = 0;
+
+#ifdef HAVE_CURSES
+ /* The following get run only in curses mode */
+ if (cur_ms != NULLMS)
+ {
+ /* Get a menu_screen */
+ old_cur_ms = cur_ms;
+ /* 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 */
+ wclear(my_ms->ms_screen);
+ wrefresh(my_ms->ms_screen);
+ wmove(my_ms->ms_title, 0, MAX(0, (COLS - (int)strlen(m->m_title)) >> 1));
+ wstandout(my_ms->ms_title);
+ waddstr(my_ms->ms_title, m->m_title);
+ 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;
+
+ wmove(my_ms->ms_menu, line, 0);
+
+ 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);
+ wmove(my_ms->ms_menu, line++, 0);
+ if (!is_topmenu)
+ {
+ waddstr(my_ms->ms_menu,
+ " r. (return) Return to previous menu.");
+ wmove(my_ms->ms_menu, line++, 0);
}
- (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);
+ waddstr(my_ms->ms_menu, " t. (toggle) Toggle logging on and off.");
+ wmove(my_ms->ms_menu, line, 0);
+ waddstr(my_ms->ms_menu, " q. (quit) Quit.");
+ }
+ else
+#endif /* HAVE_CURSES */
+ {
+ 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.");
+ 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 (;;) {
- /* This will be set by a return val from func or submenu */
- quitflag = DM_NORMAL;
- /* This is here because we may be coming from another menu */
- if (cur_ms != NULL)
- touchwin(my_ms->ms_screen);
- /* Get a command */
- if (!Prompt_input("Command: ", buf, sizeof(buf)))
- continue;
- /* Parse it into the argument list */
- /* If there's nothing there, try again */
- /* Initialize argv */
- for (argc = 0; argc < MAX_ARGC; argc++)
+ for (;;)
+ {
+ /* This will be set by a return val from func or submenu */
+ quitflag = DM_NORMAL;
+#ifdef HAVE_CURSES
+ /* This is here because we may be coming from another menu */
+ if (cur_ms != NULL)
+ {
+ touchwin(my_ms->ms_screen);
+ wrefresh(my_ms->ms_screen);
+ }
+#endif /* HAVE_CURSES */
+ if (margc > 1)
+ {
+ /* Initialize argv */
+ for (argc = 0; argc < MAX_ARGC; argc++)
+ argv[argc] = argvals[argc];
+ argc = margc - 1;
+ for (i = 1; i < margc; i++)
+ strcpy(argvals[i - 1], margv[i]);
+ margc = 0;
+ }
+ else
+ {
+ /* Get a command */
+ if (!Prompt_input("Command: ", buf, sizeof(buf)))
+ {
+ if (cur_ms == NULLMS && feof(stdin))
+ sprintf(buf, "quit");
+ else
+ continue;
+ }
+ /* Parse it into the argument list */
+ /* If there's nothing there, try again */
+ /* Initialize argv */
+ for (argc = 0; argc < MAX_ARGC; argc++)
argv[argc] = argvals[argc];
- if ((argc = Parse_words(buf, argv, MAX_ARGLEN)) == 0)
+ if ((argc = Parse_words(buf, argv, MAX_ARGLEN)) == 0)
continue;
- if ((line = atoi(argv[0])) > 0 && line <= m->m_length) {
- 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")) {
-
- /* here if it's either return or quit */
- if (cur_ms != NULLMS) {
- cur_ms = old_cur_ms;
- destroy_ms(my_ms);
+ if ((line = atoi(argv[0])) > 0 && line <= m->m_length)
+ 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"))
+ {
+ /* here if it's either return or quit */
+#ifdef HAVE_CURSES
+ if (cur_ms != NULLMS)
+ {
+ cur_ms = old_cur_ms;
+ destroy_ms(my_ms);
}
- if (m->m_exit != NULLFUNC)
- m->m_exit(m);
- return (*argv[0] == 'r' ? DM_NORMAL : DM_QUIT);
+#endif /* HAVE_CURSES */
+ if (m->m_exit != NULLFUNC)
+ m->m_exit(m);
+ return *argv[0] == 'r' ? DM_NORMAL : DM_QUIT;
}
- 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);
+ 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;
+ 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(argvals[0])) ==
- (struct menu_line *) 0) {
- Put_message("Command not recognized");
- 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])))
+ {
+ sprintf(buf, "Command not recognized: %s\n", argvals[0]);
+ Put_message(buf);
+ continue;
}
- /* If we got to here, command is a valid menu_line */
- /* Send the offical command name into the argv */
- (void) strcpy(argvals[0], command->ml_command);
- /* Show that we're working on it */
- Put_message(command->ml_doc);
- /* Print args that we've already got */
- for (i = 1; i < argc; i++) {
- if (command->ml_args[i].ma_prompt == NULL)
- break;
- (void) sprintf(buf, "%s%s", command->ml_args[i].ma_prompt,
- argv[i]);
- Put_message(buf);
+ /* If we got to here, command is a valid menu_line */
+ /* Send the offical command name into the argv */
+ strcpy(argvals[0], command->ml_command);
+ /* Show that we're working on it */
+ Put_message(command->ml_doc);
+ /* Print args that we've already got */
+ for (i = 1; i < argc; i++)
+ {
+ if (!command->ml_args[i].ma_prompt)
+ break;
+ sprintf(buf, "%s%s", command->ml_args[i].ma_prompt, argv[i]);
+ Put_message(buf);
}
- /* Get remaining arguments, if any */
- for (; argc < command->ml_argc; argc++) {
- if (!Prompt_input(command->ml_args[argc].ma_prompt,
- argvals[argc], sizeof(argvals[argc])))
- goto punt_command;
+ /* Get remaining arguments, if any */
+ for (; argc < command->ml_argc; argc++)
+ {
+ if (!Prompt_input(command->ml_args[argc].ma_prompt,
+ argvals[argc], sizeof(argvals[argc])))
+ goto punt_command;
}
- if (command->ml_function != NULLFUNC) {
- /* If it's got a function, call it */
- quitflag = command->ml_function(argc, argv);
+ parsed_argc = argc - command->ml_argc;
+ parsed_argv = &(argv[command->ml_argc]);
+ if (command->ml_function != NULLFUNC)
+ {
+ /* If it's got a function, call it */
+ quitflag = command->ml_function(argc, argv);
}
- else if (command->ml_submenu != NULLMENU) {
- /* Else see if it is a submenu */
- quitflag = Do_menu(command->ml_submenu, argc, argv);
+ else if (command->ml_submenu != NULLMENU)
+ {
+ /* Else see if it is a submenu */
+ quitflag = Do_menu(command->ml_submenu, argc, argv);
}
- else {
- /* If it's got neither, something is wrong */
- Put_message("*INTERNAL ERROR: NO FUNCTION OR MENU FOR LINE*");
+ else
+ {
+ /* If it's got neither, something is wrong */
+ Put_message("*INTERNAL ERROR: NO FUNCTION OR MENU FOR LINE*");
}
- if (quitflag == DM_QUIT) {
- if (cur_ms != NULLMS) {
- cur_ms = old_cur_ms;
- destroy_ms(my_ms);
+ if (quitflag == DM_QUIT)
+ {
+#ifdef HAVE_CURSES
+ if (cur_ms != NULLMS)
+ {
+ cur_ms = old_cur_ms;
+ destroy_ms(my_ms);
}
- if (m->m_exit != NULLFUNC)
- m->m_exit(m);
- return (DM_QUIT);
+#endif /* HAVE_CURSES */
+ if (m->m_exit != NULLFUNC)
+ m->m_exit(m);
+ parsed_argc = 0;
+ return DM_QUIT;
}
punt_command:
- ;
+ parsed_argc = 0;
+ }
+}
+
+void refresh_screen(void)
+{
+#ifdef HAVE_CURSES
+ if (cur_ms != NULLMS)
+ {
+ touchwin(cur_ms->ms_screen);
+ refresh_ms(cur_ms);
}
+#endif /* HAVE_CURSES */
}
+
/* Prompt the user for input in the input window of cur_ms */
-int Prompt_input(prompt, buf, buflen)
- char *prompt;
- char *buf;
- int buflen;
+int Prompt_input(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, 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) {
+#ifdef HAVE_CURSES
+ int c;
+ char *p;
+ int y, x, oldx, oldy;
+
+ if (cur_ms != NULLMS)
+ {
+ more_flg = 1;
+ getyx(cur_ms->ms_input, y, x);
+ wmove(cur_ms->ms_input, y, 0);
+
+ refresh_screen();
+ waddstr(cur_ms->ms_input, prompt);
+ getyx(cur_ms->ms_input, y, x);
+
+ oldx = x;
+ oldy = y;
+ p = buf;
+ while (1)
+ {
+ wmove(cur_ms->ms_input, y, x);
+ touchwin(cur_ms->ms_screen);
+ wclrtoeol(cur_ms->ms_input);
+ wrefresh(cur_ms->ms_input);
+ c = getchar() & 0x7f;
+ switch (c)
+ {
case CTL('C'):
- return 0;
+ *p = '\0';
+ return 0;
case CTL('Z'):
- (void) kill(getpid(), SIGTSTP);
- touchwin(curscr);
- break;
+ kill(getpid(), SIGTSTP);
+ touchwin(cur_ms->ms_screen);
+ 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;
+ wclear(cur_ms->ms_input);
+ wmove(cur_ms->ms_input, 0, 0);
+ waddstr(cur_ms->ms_input, prompt);
+ touchwin(cur_ms->ms_input);
+ wrefresh(cur_ms->ms_screen);
+ getyx(cur_ms->ms_input, y, x);
+ oldy = y;
+ oldx = x;
+ p = buf;
+ break;
case '\n':
case '\r':
- goto end_input;
- /* these should be obtained by doing ioctl() on tty */
+ goto end_input;
+ /* these should be obtained by doing ioctl() on tty */
case '\b':
case '\177':
- if (p > buf) {
- p--;
- x--;
+ if (p > buf)
+ {
+ p--;
+ x--;
+ if (x < 0)
+ {
+ wmove(cur_ms->ms_input, y, 0);
+ wclrtoeol(cur_ms->ms_input);
+ y--;
+ x = getmaxx(cur_ms->ms_input) - 1;
+ }
}
- break;
+ break;
case CTL('U'):
case CTL('G'):
case CTL('['):
- x = oldx;
- p = buf;
- break;
+ x = oldx;
+ y = oldy;
+ p = buf;
+ break;
default:
- if (isprint(c) && (p - buf < buflen)) {
- (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, 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;
- for (p = buf; p - buf < buflen;) {
- (void) wmove(cur_ms->ms_input, y, x);
- (void) wclrtoeol(cur_ms->ms_input);
- refresh_ms(cur_ms);
- c = getchar() & 0x7f;
- switch (c) {
- case CTL('C'):
- 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);
- refresh_ms(cur_ms);
- getyx(cur_ms->ms_input, y, x);
- break;
- case '\n':
- case '\r':
- (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();
- return 1;
- case '\b':
- case '\177':
- if (p > buf) {
- p--;
- x--;
+ /* (buflen - 1) leaves room for the \0 */
+ if (isprint(c) && (p - buf < buflen - 1))
+ {
+ waddch(cur_ms->ms_input, c);
+ *p++ = c;
+ x++;
+ if (x >= getmaxx(cur_ms->ms_input))
+ {
+ x = 0;
+ y++;
+ }
}
- break;
- case CTL('U'):
- x = oldx;
- p = buf;
- break;
- default:
- *p++ = c;
- break;
+ else
+ putchar(CTL('G'));
+ break;
}
}
+ end_input:
+ waddch(cur_ms->ms_input, '\n');
+
+ wclrtoeol(cur_ms->ms_input);
+ refresh_ms(cur_ms);
+ *p = '\0';
+ Start_paging();
+ strcpy(buf, strtrim(buf));
+ return 1;
}
- else {
- struct sgttyb ttybuf, nttybuf;
- printf("%s", prompt);
- /* 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;
+ else
+#endif /* HAVE_CURSES */
+ {
+ char bigbuf[BUFSIZ];
+
+ printf("%s", prompt);
+ if (!fgets(bigbuf, BUFSIZ, stdin))
+ return 0;
+ if (interrupt)
+ {
+ interrupt = 0;
+ return 0;
}
- putchar('\n');
- (void) ioctl(0, TIOCSETP, (char *)&ttybuf);
- Start_paging();
- return 1;
+ Start_paging();
+ strncpy(buf, strtrim(bigbuf), buflen);
+ if (strchr(buf, '\n'))
+ *strchr(buf, '\n') = '\0';
+ else
+ buf[buflen - 1] = '\0';
+ return 1;
}
- return 0;
}
int lines_left;
/* Start paging */
/* This routine will cause the most recently put message to be the
one at the top of the screen when a ---More--- prompt is displayed */
-Start_paging()
+void Start_paging(void)
{
- if (cur_ms != NULLMS) {
- lines_left = LINES - cur_ms->ms_input_y - 1;
- }
- else {
- lines_left = 23;
- }
+#ifdef HAVE_CURSES
+ if (cur_ms != NULLMS)
+ lines_left = LINES - cur_ms->ms_input_y - 1;
+ else
+#endif /* HAVE_CURSES */
+ lines_left = 23;
}
/* Turn off paging */
-Stop_paging()
+void Stop_paging(void)
{
- lines_left = -1;
+ lines_left = -1;
}
/* Print a message in the input window of cur_ms. */
-Put_message(msg)
-char *msg;
+void Put_message(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);
+ char *copy, *line, *s;
+
+ copy = malloc(COLS);
+ s = line = msg;
+ if (log_file)
+ {
+ /* if we're doing logging; we assume that the file has already
+ been opened. */
+ fprintf(log_file, "%s\n", msg);
+ fflush(log_file);
}
- Put_line(line);
- free(copy);
+
+ while (*s++)
+ {
+ if (s - line >= COLS - 1)
+ {
+ strncpy(copy, line, COLS - 1);
+ copy[COLS - 1] = '\0';
+ line += COLS - 1;
+ }
+ else if (*s == '\n')
+ {
+ *s = '\0';
+ 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;
+void Put_line(char *msg)
{
- int y, x, i;
- char *msg1, chr;
-
- if (!more_flg)
- return;
-
- if (lines_left >= 0) {
- if (--lines_left == 0) {
- /* Give the user a more prompt */
- if (cur_ms != NULLMS) {
- (void) wstandout(cur_ms->ms_input);
- (void) wprintw(cur_ms->ms_input, "---More---");
- (void) wstandend(cur_ms->ms_input);
- refresh_ms(cur_ms);
- chr = getchar() & 0x7f;/* We do care what it is */
- if (chr == 'q' || chr == 'Q') {
- more_flg = 0;
- return;
+ if (!more_flg)
+ return;
+
+ if (lines_left >= 0)
+ {
+ if (--lines_left == 0)
+ {
+ /* Give the user a more prompt */
+#ifdef HAVE_CURSES
+ if (cur_ms != NULLMS)
+ {
+ int x, y;
+ char chr;
+
+ wstandout(cur_ms->ms_input);
+ wprintw(cur_ms->ms_input, "---More---");
+ wstandend(cur_ms->ms_input);
+ refresh_ms(cur_ms);
+ chr = getchar() & 0x7f;/* We do care what it is */
+ if (chr == 'q' || chr == 'Q' || chr == 3 /* ^C */)
+ {
+ 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);
+ getyx(cur_ms->ms_input, y, x);
+ /* x is a bitbucket; avoid lint problems */
+ x = x;
+ wmove(cur_ms->ms_input, y, 0);
+ wclrtoeol(cur_ms->ms_input);
}
- else {
- printf("---More (hit return)---");
- getchar() & 0x7f;
+ else
+#endif /* HAVE_CURSES */
+ {
+ printf("---More (hit return)---");
+ getchar();
}
- Start_paging(); /* Reset lines_left */
+ Start_paging(); /* Reset lines_left */
}
}
- if (cur_ms != NULLMS) {
- 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); */
- }
- else {
- puts(msg);
+#ifdef HAVE_CURSES
+ if (cur_ms != NULLMS)
+ {
+ int i;
+ char *msg1;
+
+ msg1 = calloc(COLS, 1);
+ strncpy(msg1, msg, COLS - 1);
+ for (i = strlen(msg1); i < COLS - 1; i++)
+ msg1[i] = ' ';
+ wprintw(cur_ms->ms_input, "%s\n", msg1);
}
+ else
+#endif /* HAVE_CURSES */
+ puts(msg);
}
+#ifdef HAVE_CURSES
/* Refresh a menu_screen onto the real screen */
-refresh_ms(ms)
- struct menu_screen *ms;
+void refresh_ms(struct menu_screen *ms)
{
- int y, x;
-
- getyx(ms->ms_input, y, x);
- (void) wmove(ms->ms_screen, y + ms->ms_input_y, x);
- (void) wrefresh(ms->ms_screen);
+ wrefresh(ms->ms_title);
+ wrefresh(ms->ms_menu);
+ wrefresh(ms->ms_input);
}
+#endif /* HAVE_CURSES */
/* Parse buf into a list of words, which will be placed in strings specified by
argv. Space for these strings must have already been allocated.
Only the first n characters of each word will be copied */
-Parse_words(buf, argv, n)
- char *buf;
- char *argv[];
-int n;
-
+int Parse_words(char *buf, char *argv[], int n)
{
- char *start, *end; /* For sausage machine */
- int argc;
-
- start = buf;
- for (argc = 0; argc < MAX_ARGC; argc++) {
- while (isspace(*start))
- start++; /* Kill whitespace */
- if (*start == '\0')
- break; /* Nothing left */
- /* Now find the end of the word */
- for (end = start; *end != '\0' && !isspace(*end); end++);
- (void) strncpy(argv[argc], start, MIN(end - start, n)); /* Copy it */
- argv[argc][MIN(end - start, n - 1)] = '\0'; /* Terminate */
- start = end;
+ char *start, *end; /* For sausage machine */
+ int argc;
+
+ start = buf;
+ for (argc = 0; argc < MAX_ARGC; argc++)
+ {
+ while (isspace(*start))
+ start++; /* Kill whitespace */
+ if (*start == '\0')
+ break; /* Nothing left */
+ /* Now find the end of the word */
+ for (end = start; *end != '\0' && !isspace(*end); end++)
+ ;
+ strncpy(argv[argc], start, MIN(end - start, n)); /* Copy it */
+ argv[argc][MIN(end - start, n - 1)] = '\0'; /* Terminate */
+ start = end;
}
- return (argc);
+ return argc;
}
/* This is the internal form of Find_command, which recursively searches
for a menu_line with command command in the specified menu */
/* It will search to a maximum depth of d */
-struct menu_line *
-find_command_from(c, m, d)
- char *c;
- struct menu *m;
- int d;
+struct menu_line *find_command_from(char *c, struct menu *m, int d)
{
- int line;
- struct menu_line *maybe;
-
- if (d < 0)
- return ((struct menu_line *) 0); /* Too deep! */
- for (line = 0; line < m->m_length; line++) {
- 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) {
- return (maybe);
- }
+ int line;
+ struct menu_line *maybe;
+
+ if (d < 0)
+ return NULL; /* Too deep! */
+ for (line = 0; line < m->m_length; line++)
+ {
+ if (!strcmp(c, m->m_lines[line].ml_command))
+ return &m->m_lines[line];
}
- /* If we got to here, nothing works */
- return ((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)))
+ return maybe;
+ }
+ /* If we got to here, nothing works */
+ return NULL;
}
/* Find_command searches down the current menu tree */
/* 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)
- char *command;
+struct menu_line *Find_command(Menu *m, char *command)
{
- if (top_menu == NULLMENU) {
- return ((struct menu_line *) 0);
- }
- else {
- return (find_command_from(command, top_menu, MAX_MENU_DEPTH));
- }
+ if (m == NULLMENU)
+ return NULL;
+ else
+ return find_command_from(command, m, MAX_MENU_DEPTH);
}
-/*ARGSUSED*/
-int
-toggle_logging(argc, argv)
- int argc;
- char *argv[];
+static char *get_tmp_dir(void)
{
- int pid;
- char buf[BUFSIZ];
-
- if (log_file == (FILE *) NULL) {
- pid = getpid();
- if (!whoami) {
- char *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.");
+#ifdef _WIN32
+ static char tmp[BUFSIZ];
+ DWORD len;
+ if (!tmp[0])
+ {
+ len = GetTempPath(sizeof(tmp), tmp);
+ if (!len || (len > sizeof(tmp)))
+ strcpy(tmp, ".");
}
- return(DM_NORMAL);
-}
+ return tmp;
+#else
+ return "/var/tmp";
+#endif
+}
-/*
- * 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:
- */
+int toggle_logging(int argc, char *argv[])
+{
+ char buf[BUFSIZ];
+
+ if (!log_file)
+ {
+ sprintf(buf, "%s/%s-log.%ld", get_tmp_dir(), whoami, (long)getpid());
+
+ /* open the file */
+ log_file = fopen(buf, "a");
+
+ if (!log_file)
+ 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. */
+ fflush(log_file);
+ fclose(log_file);
+ log_file = NULL;
+ Put_message("Logging off.");
+ }
+ return DM_NORMAL;
+}