home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************
- *
- * name : menu.c
- * use : user entrant function
- * date : Thu Feb 25 19:43:02 PST 1988
- * author : Mark Marsh
- *
- *********************************************************************/
-
- /*
- $Id: menu.c,v 1.11 90/04/28 16:49:59 mark Exp Locker: mark $
- $Log: menu.c,v $
- * Revision 1.11 90/04/28 16:49:59 mark
- * *** empty log message ***
- *
- * Revision 1.10 90/04/05 16:17:16 mark
- * corrected for lint
- *
- * Revision 1.9 90/03/20 11:21:15 mark
- * *** empty log message ***
- *
- * Revision 1.8 90/02/26 18:32:14 mark
- * *** empty log message ***
- *
- * Revision 1.7 90/02/26 14:32:20 mark
- * re-instate confirm on F10/Quit
- *
- * Revision 1.6 90/02/10 12:42:09 mark
- * *** empty log message ***
- *
- * Revision 1.5 90/02/02 23:21:13 mark
- * fix getstr and getps for terminals that map left arrow as back space
- *
- * Revision 1.4 90/01/25 00:44:49 mark
- * fix F10 exit
- *
- * Revision 1.3 90/01/24 23:32:29 mark
- * do not promp y/n on F10 quit
- *
- * Revision 1.2 90/01/24 23:17:42 mark
- *
- * added extern struct termio tsaved definition
- *
- * Revision 1.1 90/01/23 16:32:36 mark
- * Initial revision
- *
- */
-
- #include <ctype.h>
- #include <stdio.h>
- #include <string.h>
- #include <signal.h>
- #include "io.h"
- #include "proto.h"
-
- #ifdef DOS_IO
- #define EXEC_STRING ""
- #else
- #define EXEC_STRING "exec"
- #endif
-
- #define MAXPMPT 60 /* maximum number of prompts */
- #define MAXHIST 20 /* maximum number of history levels */
- #define STRSIZ 21 /* maximum string size */
- #define NSIZ 41 /* maximum string size */
- #define VSIZ 41 /* maximum string size */
-
- int li;
- int co;
- int sg;
-
- struct scr_rec { /* structure of a screen record element */
- int row;
- int col;
- char noun[NSIZ];
- char verb[VSIZ];
- char more;
- char wait;
- char adj;
- char pswd[STRSIZ];
- char help[STRSIZ];
- };
-
- struct scr_rec pmpt[MAXPMPT]; /* array of screen prompts */
- char hstry[MAXHIST][VSIZ]; /* history array of datafiles */
- char name[VSIZ]; /* current datafile name */
- int go = 1; /* controls main loop repitition */
- int elm = 0; /* active element of the screen array */
- int hist = 0; /* active element of the history array */
- int status = 0; /* number of prompts read from current datafile */
-
-
- #ifndef DOS_IO
- extern struct crt_stru crt;
- extern struct termio tsaved;
- #endif
-
- /*********************************************************************
- *
- * main
- * perform setup
- * call menu
- * perform cleanup
- *
- *********************************************************************/
- main(argc,argv)
- int argc;
- char *argv[];
- {
- /* check for argument -- quit if none */
- if(argc < 2) { die("Error! Usage: prog filename"); }
-
- /* set up the terminal -- parse screen data file */
- tsetup();
- #ifdef DOS_IO
- li = 25;
- co = 80;
- sg = 0;
- #else
- li = crt.li;
- co = crt.co;
- sg = crt.sg;
- #endif
-
- /* set history and current data file to argument */
- (void)strncpy(hstry[hist],argv[1],sizeof(hstry[hist])-1);
- (void)strncpy(name,argv[1],sizeof(hstry[hist])-1);
-
- /* display screen */
- screen(name);
-
- /* highlight first non-prompt -- do something abount an all prompt screen */
- while(pmpt[elm].adj == 'P') { down(); }
-
- /* execure the main procedure */
- menu();
-
- /* clean up and exit */
- cls();
- treset();
- return(0);
- }
-
- /*********************************************************************
- *
- * menu
- * this routine tests and acts upon valid user input
- *
- *********************************************************************/
- menu()
- {
- do {
- /* highlight active menu item */
- highlight(elm);
- tflush();
-
- /* test user input */
- switch(inkey()) {
- /* help */
- case F1:
- case 'H':
- case 'h':
- help(pmpt[elm].help);
- break;
-
- /* back one screen */
- case ESC:
- case F2:
- case '<':
- history(0);
- while(pmpt[elm].adj == 'P') { down(); }
- break;
-
- /* go up */
- case LEFT:
- case UP:
- case '8':
- case '4':
- lowlight(elm);
- do { up(); } while(pmpt[elm].adj == 'P');
- break;
-
- /* go down */
- case RIGHT:
- case DOWN:
- case '6':
- case '2':
- lowlight(elm);
- do { down(); } while(pmpt[elm].adj == 'P');
- break;
-
- /* top of page */
- case PGUP:
- case F7:
- case '9':
- lowlight(elm);
- elm = 0;
- while(pmpt[elm].adj == 'P') { down(); }
- break;
-
- /* bottom of page */
- case PGDN:
- case F8:
- case '3':
- lowlight(elm);
- elm = (status-1);
- while(pmpt[elm].adj == 'P') { up(); }
- break;
-
- /* refresh screen */
- case F9:
- case 'R':
- case 'r':
- screen(hstry[hist]);
- while(pmpt[elm].adj == 'P') { down(); }
- break;
-
- /* quit program */
- case 'Q':
- case 'q':
- case F10:
- if(getyn("Really quit?")) { go = 0; }
- /*go = 0;*/
- break;
-
- /* select menu util */
- /*case NL:*/
- case CR:
- select();
- break;
-
- /* unknown character */
- default: (void)fputc(BELL,stdout);
- break;
- }
- } while(go);
- }
-
- /*********************************************************************
- *
- * history
- * maintains the history of data files read in and out.
- *
- *********************************************************************/
- void history(num)
- int num;
- {
- switch(num) {
- case 1:
- if((++hist) >= MAXHIST) {
- --hist;
- message("Error! Maximum history level exceeded.");
- } else {
- (void)strncpy(name,pmpt[elm].verb,sizeof(name)-1);
- (void)strcpy(hstry[hist],name);
- }
- break;
-
- case 0:
- if((--hist) > (-1)) {
- (void)strcpy(name,hstry[hist]);
- screen(name);
- elm = 0;
- } else {
- go = 0;
- }
- break;
-
- default: break;
- }
- }
-
-
- /*********************************************************************
- *
- * screen
- * high level function to either paint the screen or
- * die with a complaint
- *
- *********************************************************************/
- void screen(fname)
- char *fname;
- {
- /* set the array to initial values */
- init_array();
-
- status = parse(fname);
- if(status) {
- cls();
- choices();
- putdata(status);
- } else {
- if(hist > 1) {
- message("Error opening data file!");
- history(0);
- } else {
- die("Error opening data file!");
- }
- }
-
- while(pmpt[elm].adj == 'P') { down(); }
- }
-
- /*********************************************************************
- *
- * choices
- * display a list of valid menu commands
- *
- *********************************************************************/
- void choices()
- {
- static char tbuf[128];
- static int first = 1;
-
- if(first) {
- first = 0;
- (void)sprintf(tbuf,"%s %s %s %s %s %s",
- "[Enter]select",
- "[F2]prev-screen",
- "[F7]top",
- "[F8]bottom",
- "[F9]refresh",
- "[F10]quit"
- );
- }
-
- cup(li-2,0);
- if(sg) {
- (void)printf("%-*.s",co-1,tbuf);
- } else {
- revvid();
- clreol();
- (void)printf("%s",tbuf);
- normvid();
- }
- }
-
- /*********************************************************************
- *
- * message
- * write a status message on the penultimate line
- * wait for user unput
- * cleanup status line
- *
- *********************************************************************/
- void message(s)
- char *s;
- {
- cup(li-3,0);
- clreol();
- (void)printf("%s",s);
- delay();
- cup(li-3,0);
- clreol();
- }
-
-
- /*********************************************************************
- *
- * select
- * determines the action(s) to be taken when the enter key is
- * pressed while highlighting a given menu option
- *
- *********************************************************************/
- void select()
- {
- char buff1[80], buff2[128];
- int access = 1;
-
- /* get a password if required */
- if(strcmp(pmpt[elm].pswd,"NULL") &&
- strcmp(pmpt[elm].pswd,"Null") &&
- strcmp(pmpt[elm].pswd,"null") &&
- strcmp(pmpt[elm].pswd," ")) {
- access = password();
-
- /* deny access - password incorrect */
- if(!access) {
- message("Incorrect password! Access denied!");
- choices();
- return;
- }
- }
-
- /* what type of menu item is this? */
- switch(pmpt[elm].adj) {
- /* execute a command */
- case 'C':
- /* prompt for more input to command? */
- if(pmpt[elm].more == 'Y') {
- cup(li-2,0); clreol();
- if(!sg) { revvid(); }
- (void)printf("Parameters: ");
- if(!sg) { normvid(); }
- buff1[0] = '\0';
- tflush();
- (void)get_str(&buff1[0],sizeof(buff1)-1);
- (void)sprintf(buff2,"%s %s %s",EXEC_STRING,pmpt[elm].verb,buff1);
- } else {
- (void)sprintf(buff2,"%s %s",EXEC_STRING,pmpt[elm].verb);
- }
-
- /* setup and execute command */
- cls();
- sanity();
- tflush();
- (void)system(buff2);
- revert();
-
- /* pause after command returns beforre repainging the screen? */
- if(pmpt[elm].wait == 'Y') delay2(buff2);
-
- /* repainf screen */
- screen(name);
- tflush();
- break;
-
- case 'D':
- /* set up history */
- history(1);
- elm = 0;
-
- /* read and display new screen */
- screen(name);
- break;
-
- /* prompt or other unknown */
- case 'P': break;
- default: break;
- }
- }
-
-
- /*********************************************************************
- *
- * parse
- * reads and parses the named file into an array of element records
- *
- *********************************************************************/
- int parse(fname)
- char *fname;
- {
- FILE *sdat;
- char *s1,sbuff[512];
- int lcnt = 0, fcnt = 1;
-
- /* can't open file */
- sdat = fopen(fname,"r");
- if((FILE *)sdat == (FILE *)0) {
- return(0);
- }
-
- while(!feof(sdat)) {
- /* test element array overflow */
- if(lcnt == (MAXPMPT-1)) {
- (void)fclose(sdat);
- die("Maximum number of prompts exceeded!");
- }
-
- /* read a line from the file to the input buffer */
- (void)fgets(sbuff,sizeof(sbuff),sdat);
-
- /*
- ignore lines beginning with an octothorpe or consisting
- only of a newline character
- */
- if(sbuff[0] == '#') continue;
- if(!strcmp(sbuff,"\n")) continue;
-
- /* tokenize the input buffer */
- s1 = strtok(sbuff,"|");
- while(strcmp(s1,(char *)NULL)) {
- if(!feof(sdat)) {
- switch(fcnt++) {
- case 1: pmpt[lcnt].row = atoi(s1);
- break;
- case 2: pmpt[lcnt].col = atoi(s1);
- break;
- case 3: (void)strncpy(pmpt[lcnt].noun,s1,sizeof(pmpt[lcnt].noun)-1);
- break;
- case 4: (void)strncpy(pmpt[lcnt].verb,s1,sizeof(pmpt[lcnt].verb)-1);
- break;
- case 5: pmpt[lcnt].more = toupper(s1[0]);
- break;
- case 6: pmpt[lcnt].wait = toupper(s1[0]);
- break;
- case 7: pmpt[lcnt].adj = toupper(s1[0]);
- break;
- case 8: (void)strncpy(pmpt[lcnt].pswd,s1,sizeof(pmpt[lcnt].pswd));
- break;
- case 9: (void)strncpy(pmpt[lcnt].help,s1,strlen(s1));
- break;
- default: break;
- }
- }
- s1 = strtok(0,"|");
- }
- fcnt = 1;
- lcnt++;
- }
-
- (void)fclose(sdat);
- return(--lcnt);
- }
-
-
- /*********************************************************************
- *
- * password
- * reads a non-echoed string from standard input
- *
- *********************************************************************/
- int password()
- {
- int code = 0;
- char response[80];
-
- response[0] = '\0';
-
- /* set up status line */
- cup(li-2,0);
- clreol();
- if(!sg) { revvid(); }
- (void)printf("Enter password: ");
- if(!sg) { normvid(); }
- tflush();
-
- /* get and test password */
- (void)get_ps(&response[0],sizeof(response)-1);
- (strcmp(pmpt[elm].pswd,response) == 0) ? (code = 1) : (code = 0);
-
- /* reset status line */
- cup(li-2,0);
- clreol();
-
- return(code);
- }
-
-
- /*********************************************************************
- *
- * delay
- * display message on the last line of the terminal, and wait for
- * a keypress
- *
- *********************************************************************/
- void delay()
- {
- cup(li-2,0);
- clreol();
- (void)printf("Press a key to continue...");
- tflush();
- inkey();
- cup(li-2,0);
- clreol();
- }
-
- /*********************************************************************
- *
- * delay2
- * prints a single user supplied string on the last line of the
- * terminal, and wait for a keypress
- *
- *********************************************************************/
- void delay2(s)
- char *s;
- {
- cup(li-2,0); clreol();
- (void)printf("End [%s] Press a key ...",s);
- tflush();
- inkey();
- cup(li-2,0); clreol();
- }
-
-
- /*********************************************************************
- *
- * help
- * display contents of the named helpfile on the terminal screen
- *
- *********************************************************************/
- void help(hfile)
- char *hfile;
- {
- char cmbuf[1024];
-
- if(!strcmp(pmpt[elm].help,"NULL") ||
- !strcmp(pmpt[elm].help,"Null") ||
- !strcmp(pmpt[elm].help,"null") ||
- !strcmp(pmpt[elm].help," ")) {
- cup(li-3,0); clreol();
- message("No help available for this option.");
- tflush();
- choices();
- return;
- }
-
- /* set up screen */
- cls();
- sanity();
- tflush();
-
- /* display help */
- (void)sprintf(cmbuf,"cat %s | more", hfile);
- (void)system(cmbuf);
-
- /* reset screen */
- revert();
- delay();
- screen(name);
- choices();
- }
-
-
- /*********************************************************************
- *
- * die
- * print error message on critical error, reset the terminal,
- * and exit immediately.
- *
- *********************************************************************/
- void die(s)
- char *s;
- {
- (void)printf("%s\n\r",s);
- treset();
- (void)exit(-1);
- }
-
- /*********************************************************************
- *
- * up
- * actions taken when the up arrow key is pressed
- *
- *********************************************************************/
- void up()
- {
- ((elm-1) < 0) ? (elm = (status-1)) : (elm--);
- }
-
- /*********************************************************************
- *
- * down
- * actions taken when the down arrow key is pressed
- *
- *********************************************************************/
- void down()
- {
- ((elm+1) >= status) ? (elm = 0) : (elm++);
- }
-
- /*********************************************************************
- *
- * lowlight
- * lowlights the previously highlighted prompt
- *
- *********************************************************************/
- void lowlight(_elm)
- int _elm;
- {
- cup(pmpt[_elm].row,pmpt[_elm].col);
- if(sg) {
- (void)printf(" %-*s ",strlen(pmpt[_elm].noun)+1,pmpt[_elm].noun);
- } else {
- normvid();
- (void)printf("%-*s",strlen(pmpt[_elm].noun)+1,pmpt[_elm].noun);
- }
- }
-
-
- /*********************************************************************
- *
- * highlight
- * highlights the current prompt
- *
- *********************************************************************/
- void highlight(_elm)
- int _elm;
- {
- cup(pmpt[_elm].row,pmpt[_elm].col);
- if(sg) {
- (void)printf("*%-*s*\b",strlen(pmpt[_elm].noun),pmpt[_elm].noun);
- } else {
- revvid();
- (void)printf("%-*s\b",strlen(pmpt[_elm].noun)+1,pmpt[_elm].noun);
- normvid();
- }
- }
-
- /*********************************************************************
- *
- * putdata
- * paint the screen with the data found in the prompt array
- *
- *********************************************************************/
- void putdata(_status)
- int _status;
- {
- int i = 0;
- for(i=0;i<_status;i++) {
- cup(pmpt[i].row,pmpt[i].col);
- if(sg) {
- (void)printf(" %s ",pmpt[i].noun);
- } else {
- (void)printf("%s",pmpt[i].noun);
- }
- }
- }
-
- /*********************************************************************
- *
- * init_array
- * initializes the prompt array to the character NULL
- *
- *********************************************************************/
- void init_array()
- {
- int i, j;
- for(i=0;i<MAXPMPT;i++) {
- pmpt[i].row = 0;
- pmpt[i].col = 0;
- for(j=0;j<sizeof(pmpt[i].noun);j++)
- pmpt[i].noun[j] = '\0';
- for(j=0;j<sizeof(pmpt[i].verb);j++)
- pmpt[i].verb[j] = '\0';
- pmpt[i].more = '\0';
- pmpt[i].wait = '\0';
- pmpt[i].adj = '\0';
- for(j=0;j<sizeof(pmpt[i].pswd);j++)
- pmpt[i].pswd[j] = '\0';
- for(j=0;j<sizeof(pmpt[i].help);j++)
- pmpt[i].help[j] = '\0';
- }
- }
-
-
- /*********************************************************************
- *
- * getyn
- * requires the user to enter a character int the set [yYnN]
- *
- *********************************************************************/
- char template[] = "YyNn";
- int getyn(s)
- char *s;
- {
- int ch;
- int ret;
-
- /* set up screen */
- lowlight(elm);
- if(!sg) { revvid(); }
- cup(li-2,0);
- clreol();
- (void)printf("%s (y/n) ",s);
- tflush();
-
- /* get input */
- do {
- ch = inkey();
- } while(!strchr(template,ch));
- (strchr("Yy",ch)) ? (ret = 1) : (ret = 0);
-
- /* reset screen */
- normvid();
- choices();
- highlight(elm);
- tflush();
- return(ret);
- }
-
- /*********************************************************************
- *
- * sanity
- * reset terminal to original mode
- *
- *********************************************************************/
- void sanity()
- {
- (void)signal(SIGINT,SIG_DFL);
- kbreset();
- tflush();
- }
-
- /*********************************************************************
- *
- * revert
- * set terminal into cbreak mode
- *
- *********************************************************************/
- void revert()
- {
- (void)signal(SIGINT,SIG_IGN);
- kbsetup();
- tflush();
- }
-
- /*********************************************************************
- *
- * get_str
- * read a string from the keyboard - echo
- *
- *********************************************************************/
- get_str(str,num)
- char *str;
- int num;
- {
- int ccnt = 0, _status = 1;
- char str_buf[80];
- BOOLEAN _go = TRUE;
- int ch;
-
- do {
- ch = inkey();
- switch(ch) {
- case LF :
- case BS :
- if(ccnt) {
- str_buf[ccnt--] = '\0';
- (void)fputc(BS,stdout);
- tflush();
- }
- break;
- case ESC :
- str_buf[0] = '\0';
- _status = 0;
- _go = FALSE;
- break;
- case NL :
- _go = FALSE;
- break;
- case CR :
- _go = FALSE;
- break;
- default :
- if((ch >= ' ') && (ch <= '~')) {
- str_buf[ccnt++] =ch ;
- (void)fputc(ch,stdout);
- tflush();
- }
- break;
- }
- if(ccnt == num) { _go = FALSE;}
- } while(_go == TRUE);
-
- str_buf[ccnt] = '\0';
- (void)strcat(str,str_buf);
- return(_status);
- }
-
-
- /*********************************************************************
- *
- * get_ps
- * read a string from the keyboard - no echo
- *
- *********************************************************************/
- get_ps(str,num)
- char *str;
- int num;
- {
- int ccnt = 0, _status = 1;
- char str_buf[80];
- BOOLEAN _go = TRUE;
- int ch;
-
- do {
- ch = inkey();
- switch(ch) {
- case LF :
- case BS :
- if(ccnt) {
- str_buf[ccnt--] = '\0';
- }
- break;
- case ESC :
- str_buf[0] = '\0';
- _status = 0;
- _go = FALSE;
- break;
- case NL :
- _go = FALSE;
- break;
- case CR :
- _go = FALSE;
- break;
- default :
- if((ch >= ' ') && (ch <= '~')) {
- str_buf[ccnt++] =ch ;
- }
- break;
- }
- if(ccnt == num) { _go = FALSE;}
- } while(_go == TRUE);
-
- str_buf[ccnt] = '\0';
- (void)strcat(str,str_buf);
- return(_status);
- }
-
-