]> andersk Git - moira.git/commitdiff
Here's another, which is probably better.
authorwesommer <wesommer>
Mon, 3 Aug 1987 04:16:51 +0000 (04:16 +0000)
committerwesommer <wesommer>
Mon, 3 Aug 1987 04:16:51 +0000 (04:16 +0000)
clients/moira/menu.c

index ee75bdeda726ebf908aec5bda723d1e4ebd820b7..513074b30289adc7ceef469f31ec9def0eaf9a6f 100644 (file)
@@ -1,4 +1,19 @@
 /*
+ * Copyright 1987 by the Massachusetts Institute of Technology.
+ * For copying and distribution information, see the file
+ * "mit-copyright.h".
+ *
+ * $Source$
+ * $Author$
+ * $Header$
+ * $Log$
+ * Revision 1.2  1987-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.
  *
  * Basically, we define an enormous tree structure which represents the
@@ -9,8 +24,13 @@
  * about anything.
  */
 
+#ifndef lint
+static char rcsid_menu_c[] = "$Header$";
+#endif lint
+
 #include <stdio.h>
 #include <curses.h>
+#include <ctype.h>
 #include "menu.h"
 
 #define MAX(A,B) ((A) > (B) ? (A) : (B))
@@ -18,6 +38,9 @@
 
 #define MIN_INPUT 2            /* Minimum number of lines for input window */
 
+char *strcpy();
+char *strncpy();
+
 /* Structure for holding current displayed menu */
 struct menu_screen {
     WINDOW *ms_screen;         /* Window for this menu */
@@ -27,6 +50,10 @@ struct menu_screen {
     int ms_input_y;            /* Input subwindow reference coordinate */
 } *cur_ms;
 
+#define NULLMS ((struct menu_screen *) 0)
+
+Menu *top_menu;                        /* Root for command search */
+
 /*
  * 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,
@@ -36,16 +63,29 @@ struct menu_screen {
 Start_menu(m)
 Menu *m;
 {
+    struct menu_screen *make_ms();
+
     if(initscr() == ERR) {
        fputs("Can't initialize curses!\n", stderr);
-       exit(1);
+       Start_no_menu(m);
     }
     raw();                     /* We parse & print everything ourselves */
     noecho();
-    Do_menu(m);                        /* Run the menu */
+    cur_ms = make_ms(0);       /* So we always have some current menu_screen */
+    top_menu = m;
+    (void) Do_menu(m);                 /* Run the menu */
     endwin();
 }
 
+/* Like Start_menu, except it doesn't print menus and doesn't use curses */
+Start_no_menu(m)
+Menu *m;
+{
+    cur_ms = NULLMS;
+    top_menu = m;
+    (void) Do_menu(m);
+}
+
 /*
  * Create a new menu screen template with the specified menu length
  * and return it.
@@ -72,8 +112,8 @@ int length;
                          0);
 
     scrollok(ms->ms_input, TRUE);
-    wmove(ms->ms_input, 0, 0);
-    wclear(ms->ms_screen);
+    (void) wmove(ms->ms_input, 0, 0);
+    (void) wclear(ms->ms_screen);
 
     return(ms);
 }
@@ -88,7 +128,7 @@ struct menu_screen *ms;
     delwin(ms->ms_menu);
     delwin(ms->ms_input);
     delwin(ms->ms_screen);
-    free(ms);
+    free((char *)ms);
 }
 
 /*
@@ -99,80 +139,106 @@ Menu *m;
 {
     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;
 
-    /* Initialize argv */
-    for(argc = 0; argc < MAX_ARGC; argc++) argv[argc] = argvals[argc];
-
     /* Entry function gets called with old menu_screen still current */
     if(m->m_entry != NULLFUNC) m->m_entry(m);
 
-    /* Get a menu_screen */
-    old_cur_ms = cur_ms;
-    cur_ms = my_ms = make_ms(m->m_length + 2);
+    /* The following get run only in curses mode */
+    if(cur_ms != NULLMS) {
+       /* Get a menu_screen */
+       old_cur_ms = cur_ms;
+       cur_ms = my_ms = make_ms(m->m_length + 2);
 
-    /* Now print the title and the menu */
-    wmove(my_ms->ms_title, 0, MAX(0, (COLS - strlen(m->m_title))>>1));
-    wstandout(my_ms->ms_title);
-    waddstr(my_ms->ms_title, m->m_title);
-    wstandend(my_ms->ms_title);
+       /* Now print the title and the 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++) {
+           (void) wmove(my_ms->ms_menu, line, 0);
+           (void) wprintw(my_ms->ms_menu, "%2d. (%-12s) %s.", line+1,
+                   m->m_lines[line].ml_command,
+                   m->m_lines[line].ml_doc);
+       }
+       (void) wmove(my_ms->ms_menu, line++, 0);
+       (void) waddstr(my_ms->ms_menu, " r. (return      ) Return to previous menu.");
+       (void) wmove(my_ms->ms_menu, line, 0);
+       (void) waddstr(my_ms->ms_menu, " q. (quit        ) Quit.");
 
-    for(line = 0; line < m->m_length; line++) {
-       wmove(my_ms->ms_menu, line, 0);
-       wprintw(my_ms->ms_menu, "%2d. (%-8s) %s.", line+1,
-               m->m_lines[line].ml_command,
-               m->m_lines[line].ml_doc);
     }
-    wmove(my_ms->ms_menu, line++, 0);
-    waddstr(my_ms->ms_menu, " r. (return  ) Return to previous menu.");
-    wmove(my_ms->ms_menu, line, 0);
-    waddstr(my_ms->ms_menu, " q. (quit    ) Quit.");
 
-    refresh_ms(my_ms);
     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 */
-       Prompt_input("Command: ", argvals[0], sizeof(argvals[0]));
-       /* See if it matches anything (this is kind of dumb, for now) */
-       if((line = atoi(argvals[0])) > 0 && line <= m->m_length) {
-           line--;
-           /* Send the command into the argv */
-           strcpy(argvals[0], m->m_lines[line].ml_command);
-           /* Show that we're working on it */
-           Put_message(m->m_lines[line].ml_doc);
-           /* Get arguments, if any */
-           for(argc = 1; argc < m->m_lines[line].ml_argc; argc++) {
-               Prompt_input(m->m_lines[line].ml_args[argc].ma_prompt,
-                            argvals[argc], sizeof(argvals[argc]));
-           }
-           if(m->m_lines[line].ml_function != NULLFUNC) {
-               /* If it's got a function, call it */
-               quitflag = m->m_lines[line].ml_function(argv, argc);
-           } else if(m->m_lines[line].ml_submenu != NULLMENU) {
-               /* Else see if it is a submenu */
-               quitflag = Do_menu(m->m_lines[line].ml_submenu);
-           } else {
-               /* If it's got neither, something is wrong */
-               Put_message("*INTERNAL ERROR: NO FUNCTION OR MENU FOR LINE*");
-           }
-       } else if(!strcmp(argv[0], "r") || !strcmp(argv[0], "q")) {
+       Prompt_input("Command: ", buf, sizeof(buf));
+       /* 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];
+       } else if(!strcmp(argv[0], "r")
+           || !strcmp(argv[0], "q")
+               || !strcmp(argv[0], "return")
+                   || !strcmp(argv[0], "quit")) {
            /* here if it's either return or quit */
-           cur_ms = old_cur_ms;
-           destroy_ms(my_ms);
+           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);
+    /* 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;
+    }
+       /* 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);
+       }
+       /* Get remaining arguments, if any */
+       for(; argc < command->ml_argc; argc++) {
+           Prompt_input(command->ml_args[argc].ma_prompt,
+                        argvals[argc], sizeof(argvals[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);
        } else {
-           /* Couldn't find it, give up */
-           Put_message("Command not recognized");
-           continue;           /* No good */
+           /* If it's got neither, something is wrong */
+           Put_message("*INTERNAL ERROR: NO FUNCTION OR MENU FOR LINE*");
        }
        if(quitflag == DM_QUIT) {
-           cur_ms = old_cur_ms;
-           destroy_ms(my_ms);
+           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);
        }
@@ -189,47 +255,101 @@ int buflen;
     char *p;
     int y, x, oldx;
 
-    waddstr(cur_ms->ms_input, prompt);
-    getyx(cur_ms->ms_input, y, x);
-    oldx = x;
-    for (p = buf; p - buf < buflen; ) {
-       wmove(cur_ms->ms_input, y, x);
-       wclrtoeol(cur_ms->ms_input);
-       refresh_ms(cur_ms);
-       c = getchar();
-       switch (c) {
-       case 'L' & 037:
-           touchwin(cur_ms->ms_screen);
-           break;
-       case '\n': case '\r':
-           waddch(cur_ms->ms_input, '\n');
-           *p = '\0';
-           return;
-       case '\b':
-       case '\177':
-           if (p > buf) {
-               p--;
-               x--;
+    if(cur_ms != NULLMS) {
+       (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();
+           switch (c) {
+           case 'L' & 037:
+               touchwin(cur_ms->ms_screen);
+               break;
+           case '\n': case '\r':
+               (void) waddch(cur_ms->ms_input, '\n');
+               *p = '\0';
+               Start_paging();
+               return;
+           case '\b':
+           case '\177':
+               if (p > buf) {
+                   p--;
+                   x--;
+               }
+               break;
+           case 'U' & 037: case '\007': case '\033':
+               x = oldx;
+               break;
+           default:
+               (void) waddch(cur_ms->ms_input, c);
+               *p++ = c;
+               x++;
+               break;
            }
-           break;
-       case 'U' & 037: case '\007': case '\033':
-           x = oldx;
-           break;
-       default:
-           waddch(cur_ms->ms_input, c);
-           *p++ = c;
-           x++;
-           break;
        }
+    } else {
+       printf("%s", prompt);
+       (void) gets(buf);
+       Start_paging();
+       return;
     }
 }
 
+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()
+{
+    if(cur_ms != NULLMS) {
+       lines_left = LINES - cur_ms->ms_input_y - 1;
+    } else {
+       lines_left = 23;
+    }
+}
+
+/* Turn off paging */
+Stop_paging()
+{
+    lines_left = -1;
+}
+
 /* Print a message in the input window of cur_ms */
 Put_message(msg)
 char *msg;
 {
-    wprintw(cur_ms->ms_input, "%s\n", msg);
-    refresh_ms(cur_ms);
+    int y, x;
+
+    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);
+               (void) getchar(); /* We don't care what it is */
+               getyx(cur_ms->ms_input, y, x);
+               (void) wmove(cur_ms->ms_input, y, 0);
+               (void) wclrtoeol(cur_ms->ms_input);
+           } else {
+               printf("---More (hit return)---");
+               (void) getchar();
+           }
+           Start_paging();     /* Reset lines_left */
+       }
+    }
+    
+    if(cur_ms != NULLMS) {
+       (void) wprintw(cur_ms->ms_input, "%s\n", msg);
+/*     refresh_ms(cur_ms); */
+    } else {
+       puts(msg);
+    }
 }
 
 /* Refresh a menu_screen onto the real screen */
@@ -239,7 +359,80 @@ struct menu_screen *ms;
     int y, x;
 
     getyx(ms->ms_input, y, x);
-    wmove(ms->ms_screen, y + ms->ms_input_y, x);
-    touchwin(ms->ms_screen);
-    wrefresh(ms->ms_screen);
+    (void) wmove(ms->ms_screen, y + ms->ms_input_y, x);
+    (void) wrefresh(ms->ms_screen);
+}
+
+/* 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;
+{
+    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;
+    }
+    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;
+{
+    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);
+                    }
+    }
+    /* If we got to here, nothing works */
+    return((struct menu_line *) 0);
 }
+
+/* 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;
+{
+    if(top_menu == NULLMENU) {
+       return((struct menu_line *) 0);
+    } else {
+       return(find_command_from(command, top_menu, 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:
+ */
This page took 0.081845 seconds and 5 git commands to generate.