]> andersk Git - moira.git/blobdiff - clients/moira/menu.c
randomized continuation lines
[moira.git] / clients / moira / menu.c
index b9e157ef74d26ffbadd40e8d4f16dd3dfacb0734..6c0ae53fc23bd50f5487ded3723adb36e37b8573 100644 (file)
@@ -22,30 +22,49 @@ static char rcsid_menu_c[] = "$Header$";
 
 #endif lint
 
+#include <mit-copyright.h>
 #include <sys/types.h>
 #include <stdio.h>
+#include <string.h>
 #include <signal.h>
 #include <curses.h>
+#ifdef POSIX
+#include <unistd.h>
+#include <termios.h>
+#endif /* POSIX */
 #include <ctype.h>
-#include <strings.h>
+#ifndef sun
 #include <varargs.h>
+#endif
 #include <com_err.h>
+#include <moira.h>
 #include "menu.h"
 
+#ifndef __STDC__
+#define const
+#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 int interrupt;          /* will be set if ^C is received */
 extern FILE *fdopen();
+#ifndef sgi
 extern int getpid();
+#endif
 extern char *calloc();
 extern char *whoami;
 
 FILE *log_file = (FILE *) NULL;                /* file stream of log file */
 int more_flg = 1;
 
+#ifdef POSIX
+extern char *malloc();
+#endif
+
 /* Structure for holding current displayed menu */
 struct menu_screen {
     WINDOW *ms_screen;         /* Window for this menu */
@@ -58,23 +77,24 @@ struct menu_screen {
 #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 */
 
 /*
  * Hook function to cause error messages to be printed through
- * curses instead of around it.
+ * curses instead of around it.  Takes at most 5 args to the
+ * printf string (crock...)
  */
 
-int
-menu_com_err_hook(who, code, fmt, args)
-    char *who;
-    int code;
-    char *fmt;
-    va_list args;
+void
+menu_com_err_hook(who, code, fmt, arg1, arg2, arg3, arg4, arg5)
+    const char *who;
+    long code;
+    const char *fmt;
+    caddr_t arg1, arg2, arg3, arg4, arg5;
 {
     char buf[BUFSIZ], *cp;
 
-    FILE _strbuf;
-
     (void) strcpy(buf, who);
     for (cp = buf; *cp; cp++);
     *cp++ = ':';
@@ -84,11 +104,7 @@ menu_com_err_hook(who, code, fmt, args)
        while (*cp)
            cp++;
     }
-    _strbuf._flag = _IOWRT + _IOSTRG;
-    _strbuf._ptr = cp;
-    _strbuf._cnt = BUFSIZ - (cp - buf);
-    _doprnt(fmt, args, &_strbuf);
-    (void) putc('\0', &_strbuf);
+    sprintf(cp, fmt, arg1, arg2, arg3, arg4, arg5);
     Put_message(buf);
 }
 
@@ -102,17 +118,20 @@ Start_menu(m)
     Menu *m;
 {
     struct menu_screen *make_ms();
-    register int (*old_hook)() = set_com_err_hook(menu_com_err_hook);
+#ifdef __STDC__
+    register void (*old_hook)(const char *, long, const char *, va_list) = set_com_err_hook(menu_com_err_hook);
+#else
+    register void (*old_hook)() = set_com_err_hook(menu_com_err_hook);
+#endif
     
-    if (initscr() == ERR) {
+    if (initscr() == (WINDOW *)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;
+                               /* menu_screen */ 
        /* Run the menu */
        (void) Do_menu(m, -1, (char **) NULL);
     }
@@ -136,7 +155,6 @@ Start_no_menu(m)
 {
     cur_ms = NULLMS;
     COLS = 80;
-    top_menu = m;
     /* Run the menu */
     (void) Do_menu(m, -1, (char **) NULL);
 }
@@ -150,7 +168,6 @@ make_ms(length)
     int length;
 {
     struct menu_screen *ms;
-    char *malloc();
 
     if (MAX_TITLE + length + MIN_INPUT > LINES) {
        fputs("Menu too big!\n", stderr);
@@ -198,7 +215,7 @@ Do_menu(m, margc, margv)
     int margc;
     char *margv[];
 {
-    struct menu_screen *my_ms, *old_cur_ms;
+    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];
@@ -210,9 +227,19 @@ Do_menu(m, margc, margv)
     int toggle_logging();
     
     /* Entry function gets called with old menu_screen still current */
-    if (m->m_entry != NULLFUNC)
+    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;
 
     /* The following get run only in curses mode */
     if (cur_ms != NULLMS) {
@@ -272,17 +299,32 @@ Do_menu(m, margc, margv)
        /* 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++)
-           argv[argc] = argvals[argc];
-
-       if ((argc = Parse_words(buf, argv, MAX_ARGLEN)) == 0)
-           continue;
+       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)
+             continue;
+       }
        if ((line = atoi(argv[0])) > 0 && line <= m->m_length) {
            command = &m->m_lines[line - 1];
        }
@@ -318,9 +360,10 @@ Do_menu(m, margc, margv)
            continue;
        } 
        /* finally, try to find it using Find_command */
-       else if ((command = Find_command(argvals[0])) ==
+       else if ((command = Find_command(m, argvals[0])) ==
                 (struct menu_line *) 0) {
-           Put_message("Command not recognized");
+           sprintf(buf, "Command not recognized: %s\n", argvals[0]);
+           Put_message(buf);
            continue;
        }
        /* If we got to here, command is a valid menu_line */
@@ -342,6 +385,8 @@ Do_menu(m, margc, margv)
                              argvals[argc], sizeof(argvals[argc])))
                goto punt_command;
        }
+       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);
@@ -361,13 +406,23 @@ Do_menu(m, margc, margv)
            }
            if (m->m_exit != NULLFUNC)
                m->m_exit(m);
+           parsed_argc = 0;
            return (DM_QUIT);
        }
     punt_command:
-       ;
+       parsed_argc = 0;
     }
 }
 
+refresh_screen()
+{
+    if (cur_ms != NULLMS) {
+       touchwin(cur_ms->ms_screen);
+       refresh_ms(cur_ms);
+    }
+}
+
+
 /* Prompt the user for input in the input window of cur_ms */
 int Prompt_input(prompt, buf, buflen)
     char *prompt;
@@ -376,30 +431,29 @@ int Prompt_input(prompt, buf, buflen)
 {
     int c;
     char *p;
-    int y, x, oldx;
+    int y, x, oldx, oldy;
 
     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);
+       refresh_screen();
        (void) waddstr(cur_ms->ms_input, prompt);
        getyx(cur_ms->ms_input, y, x);
 
        oldx = x;
+       oldy = y;
        p = buf;
        while(1) {
            (void) wmove(cur_ms->ms_input, y, x);
                (void) touchwin(cur_ms->ms_screen);
-#ifdef notdef
            (void) wclrtoeol(cur_ms->ms_input);
-#endif notdef
-           refresh_ms(cur_ms);
+           (void) wrefresh(cur_ms->ms_input);
            c = getchar() & 0x7f;
            switch (c) {
            case CTL('C'):
+               *p = '\0';
                return 0;
            case CTL('Z'):
                (void) kill(getpid(), SIGTSTP);
@@ -408,11 +462,13 @@ int Prompt_input(prompt, buf, buflen)
            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
+               (void) touchwin(cur_ms->ms_input);
+               (void) move(LINES - 1, 0);
+               (void) wrefresh(curscr);
                getyx(cur_ms->ms_input, y, x);
+               oldy = y;
+               oldx = x;
+               p = buf;
                break;
 
            case '\n':
@@ -424,19 +480,31 @@ int Prompt_input(prompt, buf, buflen)
                if (p > buf) {
                    p--;
                    x--;
+                   if (x < 0) {
+                       (void) wmove(cur_ms->ms_input, y, 0);
+                       (void) wclrtoeol(cur_ms->ms_input);
+                       y--;
+                       x = cur_ms->ms_input->_maxx-1;
+                   }
                }
                break;
            case CTL('U'):
            case CTL('G'):
            case CTL('['):
                x = oldx;
+               y = oldy;
                p = buf;
                break;
            default:
-               if (isprint(c) && (p - buf < buflen)) {
+               /* (buflen - 1) leaves room for the \0 */
+               if (isprint(c) && (p - buf < buflen - 1)) {
                    (void) waddch(cur_ms->ms_input, c);
                    *p++ = c;
                    x++;
+                   if (x >= cur_ms->ms_input->_maxx) {
+                       x = 0;
+                       y++;
+                   }
                } else
                    putchar(CTL('G'));
                break;
@@ -444,7 +512,6 @@ int Prompt_input(prompt, buf, buflen)
        }
     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);
@@ -455,6 +522,10 @@ int Prompt_input(prompt, buf, buflen)
        printf("%s", prompt);
        if (gets(buf) == NULL)
            return 0;
+       if (interrupt) {
+           interrupt = 0;
+           return 0;
+       }
        Start_paging();
        goto gotit;
     }
@@ -501,12 +572,13 @@ int Password_input(prompt, buf, buflen)
                (void) wclear(cur_ms->ms_input);
                (void) waddstr(cur_ms->ms_input, prompt);
                refresh_ms(cur_ms);
+               (void) move(LINES - 1, 0);
+               (void) wrefresh(curscr);
                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);
@@ -531,9 +603,26 @@ int Password_input(prompt, buf, buflen)
        }
     }
     else {
+#ifdef POSIX
+       struct termios ttybuf, nttybuf;
+#else
        struct sgttyb ttybuf, nttybuf;
+#endif /* POSIX */
        printf("%s", prompt);
        /* turn off echoing */
+#ifdef POSIX
+       tcgetattr(0, &ttybuf);
+       nttybuf = ttybuf;
+       nttybuf.c_lflag &= ~ECHO;
+       tcsetattr(0, TCSANOW, &nttybuf);
+       if (gets(buf) == NULL) {
+           tcsetattr(0, TCSANOW, &ttybuf);
+           putchar('\n');
+           return 0;
+       }
+       putchar('\n');
+       (void) ioctl(0, TCSETA, (char *)&ttybuf);
+#else
        (void) ioctl(0, TIOCGETP, (char *)&ttybuf);
        nttybuf = ttybuf;
        nttybuf.sg_flags &= ~ECHO;
@@ -545,6 +634,7 @@ int Password_input(prompt, buf, buflen)
        }
        putchar('\n');
        (void) ioctl(0, TIOCSETP, (char *)&ttybuf);
+#endif /* POSIX */
        Start_paging();
        return 1;
     }
@@ -621,7 +711,7 @@ char *msg;
                (void) wstandend(cur_ms->ms_input);
                refresh_ms(cur_ms);
                chr = getchar() & 0x7f;/* We do care what it is */
-               if (chr == 'q' || chr == 'Q') {
+               if (chr == 'q' || chr == 'Q' || chr == 3 /* ^C */) {
                    more_flg = 0;
                    return;
                }
@@ -633,7 +723,7 @@ char *msg;
            }
            else {
                printf("---More (hit return)---");
-               (void) getchar() & 0x7f;
+               getchar();
            }
            Start_paging();     /* Reset lines_left */
        }
@@ -645,7 +735,6 @@ char *msg;
        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);
@@ -656,11 +745,9 @@ char *msg;
 refresh_ms(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);
+    (void) wrefresh(ms->ms_title);
+    (void) wrefresh(ms->ms_menu);
+    (void) wrefresh(ms->ms_input);
 }
 
 /* Parse buf into a list of words, which will be placed in strings specified by
@@ -708,10 +795,11 @@ find_command_from(c, m, d)
        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);
        }
     }
@@ -723,14 +811,15 @@ find_command_from(c, m, d)
 /* 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));
     }
 }
 
@@ -746,7 +835,6 @@ toggle_logging(argc, argv)
     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");
@@ -774,14 +862,3 @@ toggle_logging(argc, argv)
     }
     return(DM_NORMAL);
 } 
-
-/*
- * 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:
- */
This page took 0.048561 seconds and 4 git commands to generate.