home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1555 / menu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-28  |  18.1 KB  |  901 lines

  1. /*********************************************************************
  2. *
  3. *    name     : menu.c
  4. *    use     : user entrant function
  5. *    date     :    Thu Feb 25 19:43:02 PST 1988
  6. *    author : Mark Marsh
  7. *
  8. *********************************************************************/
  9.  
  10. /*
  11. $Id: menu.c,v 1.11 90/04/28 16:49:59 mark Exp Locker: mark $
  12. $Log:    menu.c,v $
  13.  * Revision 1.11  90/04/28  16:49:59  mark
  14.  * *** empty log message ***
  15.  * 
  16.  * Revision 1.10  90/04/05  16:17:16  mark
  17.  * corrected for lint
  18.  * 
  19.  * Revision 1.9  90/03/20  11:21:15  mark
  20.  * *** empty log message ***
  21.  * 
  22.  * Revision 1.8  90/02/26  18:32:14  mark
  23.  * *** empty log message ***
  24.  * 
  25.  * Revision 1.7  90/02/26  14:32:20  mark
  26.  * re-instate confirm on F10/Quit
  27.  * 
  28.  * Revision 1.6  90/02/10  12:42:09  mark
  29.  * *** empty log message ***
  30.  * 
  31.  * Revision 1.5  90/02/02  23:21:13  mark
  32.  * fix getstr and getps for terminals that map left arrow as back space
  33.  * 
  34.  * Revision 1.4  90/01/25  00:44:49  mark
  35.  * fix F10 exit
  36.  * 
  37.  * Revision 1.3  90/01/24  23:32:29  mark
  38.  * do not promp y/n on F10 quit
  39.  * 
  40.  * Revision 1.2  90/01/24  23:17:42  mark
  41.  * 
  42.  * added extern struct termio tsaved definition
  43.  * 
  44.  * Revision 1.1  90/01/23  16:32:36  mark
  45.  * Initial revision
  46.  * 
  47. */
  48.  
  49. #include <ctype.h>
  50. #include <stdio.h>
  51. #include <string.h>
  52. #include <signal.h>
  53. #include "io.h"
  54. #include "proto.h"
  55.  
  56. #ifdef DOS_IO
  57. #define EXEC_STRING ""
  58. #else
  59. #define  EXEC_STRING "exec"
  60. #endif
  61.  
  62. #define    MAXPMPT 60     /* maximum number of prompts */
  63. #define    MAXHIST 20        /* maximum number of history levels */
  64. #define    STRSIZ  21        /* maximum string size */
  65. #define    NSIZ    41        /* maximum string size */
  66. #define    VSIZ    41        /* maximum string size */
  67.  
  68. int li;
  69. int co;
  70. int sg;
  71.  
  72. struct scr_rec {        /* structure of a screen record element */
  73.     int    row;
  74.     int    col;
  75.     char    noun[NSIZ];
  76.     char    verb[VSIZ];
  77.     char    more;
  78.     char    wait;
  79.     char    adj;
  80.     char    pswd[STRSIZ];
  81.     char    help[STRSIZ];
  82. };
  83.  
  84. struct scr_rec pmpt[MAXPMPT]; /* array of screen prompts */
  85. char hstry[MAXHIST][VSIZ];    /* history array of datafiles */
  86. char name[VSIZ];              /* current datafile name */
  87. int go = 1;                   /* controls main loop repitition */
  88. int elm = 0;                  /* active element of the screen array */
  89. int hist = 0;                 /* active element of the history array */
  90. int status = 0;               /* number of prompts read from current datafile */
  91.  
  92.  
  93. #ifndef DOS_IO
  94.     extern struct crt_stru crt;
  95.     extern struct termio tsaved;
  96. #endif
  97.  
  98. /*********************************************************************
  99. *
  100. *    main
  101. *        perform setup
  102. *        call menu
  103. *        perform cleanup
  104. *
  105. *********************************************************************/
  106. main(argc,argv)
  107. int argc;
  108. char *argv[];
  109. {
  110.     /* check for argument -- quit if none */
  111.     if(argc < 2) { die("Error! Usage: prog filename"); }
  112.  
  113.     /* set up the  terminal -- parse screen data file */
  114.     tsetup();
  115. #ifdef DOS_IO
  116.     li = 25;
  117.     co = 80;
  118.     sg = 0;
  119. #else
  120.     li = crt.li;
  121.     co = crt.co;
  122.     sg = crt.sg;
  123. #endif
  124.  
  125.     /* set history and current data file to argument */
  126.     (void)strncpy(hstry[hist],argv[1],sizeof(hstry[hist])-1);
  127.     (void)strncpy(name,argv[1],sizeof(hstry[hist])-1);
  128.  
  129.     /* display screen */
  130.     screen(name);
  131.  
  132.     /* highlight first non-prompt -- do something abount an all prompt screen */
  133.     while(pmpt[elm].adj == 'P') { down(); }
  134.     
  135.     /* execure the main procedure */
  136.     menu();
  137.  
  138.     /* clean up and exit */
  139.     cls();
  140.     treset();
  141.     return(0);
  142. }
  143.  
  144. /*********************************************************************
  145. *
  146. *    menu
  147. *        this routine tests and acts upon valid user input
  148. *
  149. *********************************************************************/
  150. menu()
  151. {
  152.     do {
  153.         /* highlight active menu item */
  154.         highlight(elm);
  155.         tflush();
  156.  
  157.         /* test user input */
  158.         switch(inkey()) {
  159.             /* help */
  160.             case   F1:
  161.             case  'H':
  162.             case  'h':
  163.                 help(pmpt[elm].help);
  164.                 break;
  165.  
  166.             /* back one screen */
  167.             case  ESC:
  168.             case   F2:
  169.             case  '<':
  170.                 history(0);
  171.                 while(pmpt[elm].adj == 'P') { down(); }
  172.                 break;
  173.  
  174.             /* go up */
  175.             case LEFT:
  176.             case   UP:
  177.             case  '8':
  178.             case  '4':
  179.                 lowlight(elm);
  180.                 do { up(); } while(pmpt[elm].adj == 'P');
  181.                 break;
  182.  
  183.             /* go down */
  184.             case RIGHT:
  185.             case  DOWN:
  186.             case   '6':
  187.             case   '2':
  188.                 lowlight(elm);
  189.                 do { down(); } while(pmpt[elm].adj == 'P');
  190.                 break;
  191.  
  192.             /* top of page */
  193.             case  PGUP:
  194.             case    F7:
  195.             case   '9':
  196.                 lowlight(elm);
  197.                 elm = 0;
  198.                 while(pmpt[elm].adj == 'P') { down(); }
  199.                 break;
  200.  
  201.             /* bottom of page */
  202.             case PGDN:
  203.             case   F8:
  204.             case  '3':
  205.                 lowlight(elm);
  206.                 elm = (status-1);
  207.                 while(pmpt[elm].adj == 'P') { up(); }
  208.                 break;
  209.  
  210.             /* refresh screen */
  211.             case   F9:    
  212.             case  'R':    
  213.             case  'r':    
  214.                 screen(hstry[hist]);
  215.                 while(pmpt[elm].adj == 'P') { down(); }
  216.                 break;
  217.  
  218.             /* quit program */
  219.             case  'Q':
  220.             case  'q':
  221.             case  F10:
  222.                 if(getyn("Really quit?")) { go = 0; }
  223.                 /*go = 0;*/
  224.                 break;
  225.  
  226.             /* select menu util */
  227.             /*case NL:*/
  228.             case CR:
  229.                 select();
  230.                 break;
  231.  
  232.             /* unknown character */
  233.             default: (void)fputc(BELL,stdout); 
  234.                         break;
  235.         } 
  236.     } while(go);
  237. }
  238.  
  239. /*********************************************************************
  240. *
  241. *    history
  242. *        maintains the history of data files read in and out.
  243. *
  244. *********************************************************************/
  245. void history(num)
  246. int num;
  247. {
  248.     switch(num) {
  249.         case  1:
  250.             if((++hist) >= MAXHIST) {
  251.                 --hist;
  252.                 message("Error! Maximum history level exceeded.");
  253.             } else {
  254.                 (void)strncpy(name,pmpt[elm].verb,sizeof(name)-1);
  255.                 (void)strcpy(hstry[hist],name);
  256.             }
  257.             break;
  258.  
  259.         case  0:
  260.             if((--hist) > (-1)) {
  261.                 (void)strcpy(name,hstry[hist]);    
  262.                 screen(name);
  263.                 elm = 0;
  264.             } else {
  265.                 go = 0;
  266.             }
  267.             break;
  268.  
  269.         default: break;
  270.     }
  271. }
  272.  
  273.  
  274. /*********************************************************************
  275. *
  276. *    screen
  277. *        high level function to either paint the screen or
  278. *        die with a complaint
  279. *
  280. *********************************************************************/
  281. void screen(fname)
  282. char *fname;
  283. {
  284.     /* set the array to initial values */
  285.     init_array();   
  286.  
  287.     status = parse(fname);
  288.     if(status) {
  289.         cls();
  290.         choices();
  291.         putdata(status);
  292.     } else {
  293.         if(hist > 1) {
  294.             message("Error opening data file!");
  295.              history(0);
  296.         } else {
  297.             die("Error opening data file!");
  298.         }
  299.     }
  300.  
  301.     while(pmpt[elm].adj == 'P') { down(); }
  302. }
  303.  
  304. /*********************************************************************
  305. *
  306. *    choices
  307. *        display a list of valid menu commands
  308. *
  309. *********************************************************************/
  310. void choices()
  311. {
  312.     static char tbuf[128];
  313.     static int first = 1;
  314.  
  315.     if(first) {
  316.         first = 0;
  317.         (void)sprintf(tbuf,"%s %s %s %s %s %s",
  318.                 "[Enter]select",
  319.                 "[F2]prev-screen",
  320.                 "[F7]top",
  321.                 "[F8]bottom",
  322.                 "[F9]refresh",
  323.                 "[F10]quit"
  324.         );
  325.     } 
  326.  
  327.     cup(li-2,0);
  328.     if(sg) {
  329.         (void)printf("%-*.s",co-1,tbuf);
  330.     } else {
  331.         revvid();
  332.         clreol();
  333.         (void)printf("%s",tbuf);
  334.         normvid();
  335.     }
  336. }
  337.  
  338. /*********************************************************************
  339. *
  340. *    message
  341. *        write a status message on the penultimate line
  342. *        wait for user unput
  343. *        cleanup status line
  344. *
  345. *********************************************************************/
  346. void message(s)
  347. char *s;
  348. {
  349.     cup(li-3,0);
  350.     clreol();
  351.     (void)printf("%s",s);
  352.     delay();
  353.     cup(li-3,0);
  354.     clreol();
  355. }
  356.  
  357.  
  358. /*********************************************************************
  359. *
  360. *    select
  361. *        determines the action(s) to be taken when the enter key is
  362. *        pressed while highlighting a given menu option
  363. *
  364. *********************************************************************/
  365. void select()
  366. {
  367.     char buff1[80], buff2[128];
  368.     int access = 1;
  369.  
  370.     /* get a password if required */
  371.     if(strcmp(pmpt[elm].pswd,"NULL") &&
  372.         strcmp(pmpt[elm].pswd,"Null") &&
  373.         strcmp(pmpt[elm].pswd,"null") &&
  374.         strcmp(pmpt[elm].pswd," ")) {
  375.         access = password();
  376.         
  377.         /* deny access - password incorrect */
  378.         if(!access) {
  379.             message("Incorrect password! Access denied!");
  380.             choices();
  381.             return;
  382.         }
  383.     }
  384.  
  385.     /* what type of menu item is this? */
  386.     switch(pmpt[elm].adj) {
  387.         /* execute a command */
  388.         case 'C':
  389.             /* prompt for more input to command? */
  390.             if(pmpt[elm].more == 'Y') {
  391.                 cup(li-2,0); clreol();
  392.                 if(!sg) { revvid(); }
  393.                 (void)printf("Parameters: ");    
  394.                 if(!sg) { normvid(); }
  395.                 buff1[0] = '\0';
  396.                 tflush();
  397.                 (void)get_str(&buff1[0],sizeof(buff1)-1);
  398.                 (void)sprintf(buff2,"%s %s %s",EXEC_STRING,pmpt[elm].verb,buff1);
  399.             } else {
  400.                 (void)sprintf(buff2,"%s %s",EXEC_STRING,pmpt[elm].verb);
  401.             }
  402.  
  403.             /* setup and execute command */
  404.             cls(); 
  405.             sanity();
  406.             tflush();
  407.             (void)system(buff2); 
  408.             revert();
  409.  
  410.             /* pause after command returns beforre repainging the screen? */
  411.             if(pmpt[elm].wait == 'Y') delay2(buff2);
  412.  
  413.             /* repainf screen */
  414.             screen(name);
  415.             tflush();
  416.             break;
  417.  
  418.         case 'D':
  419.             /* set up history */
  420.             history(1); 
  421.             elm = 0; 
  422.  
  423.             /* read and display new screen */
  424.             screen(name);
  425.             break;
  426.  
  427.         /* prompt or other unknown */
  428.         case 'P':    break;
  429.         default:        break;
  430.     }
  431. }
  432.  
  433.  
  434. /*********************************************************************
  435. *
  436. *    parse
  437. *        reads and parses the named file into an array of element records
  438. *
  439. *********************************************************************/
  440. int parse(fname)
  441. char *fname;
  442. {
  443.     FILE *sdat;
  444.     char *s1,sbuff[512];
  445.     int lcnt = 0, fcnt = 1;
  446.  
  447.     /* can't open file */
  448.     sdat = fopen(fname,"r");
  449.     if((FILE *)sdat == (FILE *)0) {
  450.         return(0);
  451.     }
  452.  
  453.     while(!feof(sdat)) {
  454.         /* test element array overflow */
  455.         if(lcnt == (MAXPMPT-1)) {
  456.             (void)fclose(sdat);
  457.             die("Maximum number of prompts exceeded!");
  458.         }
  459.  
  460.         /* read a line from the file to the input buffer */
  461.         (void)fgets(sbuff,sizeof(sbuff),sdat);
  462.  
  463.         /*
  464.             ignore lines beginning with an octothorpe or consisting
  465.             only of a newline character 
  466.         */
  467.         if(sbuff[0] == '#') continue;
  468.         if(!strcmp(sbuff,"\n")) continue;
  469.  
  470.         /* tokenize the input buffer */
  471.         s1 = strtok(sbuff,"|");
  472.         while(strcmp(s1,(char *)NULL)) {
  473.             if(!feof(sdat)) {
  474.                 switch(fcnt++) {
  475.                     case 1:    pmpt[lcnt].row = atoi(s1);
  476.                                 break;
  477.                     case 2:    pmpt[lcnt].col = atoi(s1);
  478.                                 break;
  479.                     case 3:    (void)strncpy(pmpt[lcnt].noun,s1,sizeof(pmpt[lcnt].noun)-1);
  480.                                 break;
  481.                     case 4:    (void)strncpy(pmpt[lcnt].verb,s1,sizeof(pmpt[lcnt].verb)-1);
  482.                                 break;
  483.                     case 5:    pmpt[lcnt].more = toupper(s1[0]);
  484.                                 break;
  485.                     case 6:    pmpt[lcnt].wait = toupper(s1[0]);
  486.                                 break;
  487.                     case 7:    pmpt[lcnt].adj = toupper(s1[0]);
  488.                                 break;
  489.                     case 8:    (void)strncpy(pmpt[lcnt].pswd,s1,sizeof(pmpt[lcnt].pswd));
  490.                                 break;
  491.                     case 9:    (void)strncpy(pmpt[lcnt].help,s1,strlen(s1));
  492.                                 break;
  493.                     default: break;
  494.                 }
  495.             }
  496.             s1 = strtok(0,"|");            
  497.         }
  498.         fcnt = 1;
  499.         lcnt++;
  500.     }
  501.  
  502.     (void)fclose(sdat);
  503.     return(--lcnt);
  504. }
  505.  
  506.  
  507. /*********************************************************************
  508. *
  509. *    password
  510. *        reads a non-echoed string from standard input
  511. *
  512. *********************************************************************/
  513. int password()
  514. {
  515.     int code = 0;
  516.     char response[80];
  517.  
  518.     response[0] = '\0';
  519.  
  520.     /* set up status line */
  521.     cup(li-2,0);
  522.     clreol();
  523.     if(!sg) { revvid(); }
  524.     (void)printf("Enter password: ");
  525.     if(!sg) { normvid(); }
  526.     tflush();
  527.  
  528.     /* get and test password */
  529.     (void)get_ps(&response[0],sizeof(response)-1);
  530.     (strcmp(pmpt[elm].pswd,response) == 0) ? (code = 1) : (code = 0);    
  531.  
  532.     /* reset status line */
  533.     cup(li-2,0); 
  534.     clreol();
  535.  
  536.     return(code);
  537. }
  538.  
  539.  
  540. /*********************************************************************
  541. *
  542. *    delay
  543. *        display message on the last line of the terminal, and wait for 
  544. *        a keypress
  545. *
  546. *********************************************************************/
  547. void delay()
  548. {
  549.     cup(li-2,0);
  550.     clreol(); 
  551.     (void)printf("Press a key to continue...");
  552.     tflush();
  553.     inkey();
  554.     cup(li-2,0);
  555.     clreol(); 
  556. }
  557.  
  558. /*********************************************************************
  559. *
  560. *    delay2
  561. *        prints a single user supplied string on the last line of the
  562. *        terminal, and wait for a keypress
  563. *
  564. *********************************************************************/
  565. void delay2(s)
  566. char *s;
  567. {
  568.     cup(li-2,0); clreol(); 
  569.     (void)printf("End [%s] Press a key ...",s);
  570.     tflush();
  571.     inkey();
  572.     cup(li-2,0); clreol(); 
  573. }
  574.  
  575.  
  576. /*********************************************************************
  577. *
  578. *    help
  579. *        display contents of the named helpfile on the terminal screen
  580. *
  581. *********************************************************************/
  582. void help(hfile)
  583. char *hfile;
  584. {
  585.     char cmbuf[1024];
  586.  
  587.     if(!strcmp(pmpt[elm].help,"NULL") ||
  588.         !strcmp(pmpt[elm].help,"Null") ||
  589.         !strcmp(pmpt[elm].help,"null") ||
  590.         !strcmp(pmpt[elm].help," ")) {
  591.         cup(li-3,0); clreol();
  592.         message("No help available for this option.");    
  593.         tflush();
  594.         choices();
  595.         return;
  596.     }
  597.  
  598.     /* set up screen */
  599.     cls();
  600.     sanity(); 
  601.     tflush();
  602.  
  603.     /* display help */
  604.     (void)sprintf(cmbuf,"cat %s | more", hfile);
  605.     (void)system(cmbuf);
  606.  
  607.     /* reset screen */
  608.     revert();
  609.     delay();
  610.     screen(name);
  611.     choices();
  612. }
  613.  
  614.  
  615. /*********************************************************************
  616. *
  617. *    die
  618. *        print error message on critical error, reset the terminal, 
  619. *        and exit immediately.
  620. *
  621. *********************************************************************/
  622. void die(s)
  623. char *s;
  624. {
  625.     (void)printf("%s\n\r",s);
  626.     treset();
  627.     (void)exit(-1);
  628. }
  629.  
  630. /*********************************************************************
  631. *
  632. *    up
  633. *        actions taken when the up arrow key is pressed
  634. *
  635. *********************************************************************/
  636. void up()
  637. {
  638.     ((elm-1) < 0) ? (elm = (status-1)) : (elm--);
  639. }
  640.  
  641. /*********************************************************************
  642. *
  643. *    down
  644. *        actions taken when the down arrow key is pressed
  645. *
  646. *********************************************************************/
  647. void down()
  648. {
  649.     ((elm+1) >= status) ? (elm = 0) : (elm++);
  650. }
  651.  
  652. /*********************************************************************
  653. *
  654. *    lowlight
  655. *        lowlights the previously highlighted prompt
  656. *
  657. *********************************************************************/
  658. void lowlight(_elm)
  659. int _elm;
  660. {
  661.     cup(pmpt[_elm].row,pmpt[_elm].col);
  662.     if(sg) {
  663.         (void)printf(" %-*s ",strlen(pmpt[_elm].noun)+1,pmpt[_elm].noun);
  664.     } else {
  665.         normvid();
  666.         (void)printf("%-*s",strlen(pmpt[_elm].noun)+1,pmpt[_elm].noun);
  667.     }
  668. }
  669.  
  670.  
  671. /*********************************************************************
  672. *
  673. *    highlight
  674. *        highlights the current prompt
  675. *
  676. *********************************************************************/
  677. void highlight(_elm)
  678. int _elm;
  679. {
  680.     cup(pmpt[_elm].row,pmpt[_elm].col);
  681.     if(sg) {
  682.         (void)printf("*%-*s*\b",strlen(pmpt[_elm].noun),pmpt[_elm].noun);
  683.     } else {
  684.         revvid();
  685.         (void)printf("%-*s\b",strlen(pmpt[_elm].noun)+1,pmpt[_elm].noun);
  686.         normvid();
  687.     }
  688. }
  689.  
  690. /*********************************************************************
  691. *
  692. *    putdata
  693. *        paint the screen with the data found in the prompt array
  694. *
  695. *********************************************************************/
  696. void putdata(_status)
  697. int _status;
  698. {
  699.     int i = 0;
  700.     for(i=0;i<_status;i++) {
  701.         cup(pmpt[i].row,pmpt[i].col); 
  702.         if(sg) {
  703.             (void)printf(" %s ",pmpt[i].noun);
  704.         } else {
  705.             (void)printf("%s",pmpt[i].noun);
  706.         }
  707.     }
  708. }
  709.  
  710. /*********************************************************************
  711. *
  712. *    init_array
  713. *        initializes the prompt array to the character NULL
  714. *
  715. *********************************************************************/
  716. void init_array()
  717. {
  718.     int i, j;    
  719.     for(i=0;i<MAXPMPT;i++) {
  720.         pmpt[i].row = 0;
  721.         pmpt[i].col = 0;
  722.         for(j=0;j<sizeof(pmpt[i].noun);j++)
  723.             pmpt[i].noun[j] = '\0';
  724.         for(j=0;j<sizeof(pmpt[i].verb);j++)
  725.             pmpt[i].verb[j] = '\0';
  726.         pmpt[i].more = '\0';
  727.         pmpt[i].wait = '\0';
  728.         pmpt[i].adj = '\0';
  729.         for(j=0;j<sizeof(pmpt[i].pswd);j++)
  730.             pmpt[i].pswd[j] = '\0';
  731.         for(j=0;j<sizeof(pmpt[i].help);j++)
  732.             pmpt[i].help[j] = '\0';
  733.     }
  734. }
  735.  
  736.  
  737. /*********************************************************************
  738. *
  739. *    getyn
  740. *        requires the user to enter a character int the set [yYnN]
  741. *
  742. *********************************************************************/
  743. char template[] = "YyNn";
  744. int getyn(s)
  745. char *s;
  746. {
  747.    int ch;
  748.    int ret;
  749.  
  750.     /* set up screen */
  751.    lowlight(elm);
  752.     if(!sg) { revvid(); }
  753.    cup(li-2,0);
  754.     clreol();
  755.     (void)printf("%s (y/n) ",s);
  756.     tflush();
  757.  
  758.     /* get input */
  759.    do {
  760.         ch = inkey();
  761.    } while(!strchr(template,ch));
  762.    (strchr("Yy",ch)) ? (ret = 1) : (ret = 0);
  763.  
  764.     /* reset screen */
  765.    normvid();
  766.     choices();
  767.    highlight(elm);
  768.     tflush();
  769.    return(ret);
  770. }
  771.  
  772. /*********************************************************************
  773. *
  774. *    sanity
  775. *        reset terminal to original mode
  776. *
  777. *********************************************************************/
  778. void sanity()
  779. {
  780.     (void)signal(SIGINT,SIG_DFL);
  781.     kbreset();
  782.     tflush();
  783. }
  784.  
  785. /*********************************************************************
  786. *
  787. *    revert 
  788. *        set terminal into cbreak mode
  789. *
  790. *********************************************************************/
  791. void revert()
  792. {
  793.     (void)signal(SIGINT,SIG_IGN);
  794.     kbsetup();
  795.     tflush();
  796. }
  797.  
  798. /*********************************************************************
  799. *
  800. *    get_str
  801. *        read a string from the keyboard - echo
  802. *
  803. *********************************************************************/
  804. get_str(str,num)
  805. char *str;
  806. int num;
  807. {
  808.     int ccnt = 0, _status = 1;
  809.     char str_buf[80];
  810.     BOOLEAN _go = TRUE;
  811.     int ch;
  812.  
  813.     do {
  814.         ch = inkey();
  815.         switch(ch) {
  816.             case LF  :
  817.             case BS  :
  818.                 if(ccnt) {
  819.                     str_buf[ccnt--] = '\0';
  820.                     (void)fputc(BS,stdout);
  821.                     tflush();
  822.                 }
  823.                 break;
  824.             case ESC :
  825.                 str_buf[0] = '\0';
  826.                 _status = 0;
  827.                 _go = FALSE;
  828.                 break;
  829.             case NL  :
  830.                 _go = FALSE;
  831.                 break;
  832.             case CR  :
  833.                 _go = FALSE;
  834.                 break;
  835.             default  :
  836.                 if((ch >= ' ') && (ch <= '~')) {
  837.                     str_buf[ccnt++] =ch ; 
  838.                     (void)fputc(ch,stdout); 
  839.                     tflush();
  840.                 }
  841.                 break;
  842.         }
  843.         if(ccnt == num) { _go = FALSE;}
  844.     } while(_go == TRUE);
  845.  
  846.     str_buf[ccnt] = '\0';
  847.     (void)strcat(str,str_buf);
  848.     return(_status);
  849. }
  850.  
  851.  
  852. /*********************************************************************
  853. *
  854. *    get_ps
  855. *        read a string from the keyboard - no echo
  856. *
  857. *********************************************************************/
  858. get_ps(str,num)
  859. char *str;
  860. int num;
  861. {
  862.     int ccnt = 0, _status = 1;
  863.     char str_buf[80];
  864.     BOOLEAN _go = TRUE;
  865.     int ch;
  866.  
  867.     do {
  868.         ch = inkey();
  869.         switch(ch) {
  870.             case LF  :
  871.             case BS  :
  872.                 if(ccnt) {
  873.                     str_buf[ccnt--] = '\0';
  874.                 }
  875.                 break;
  876.             case ESC :
  877.                 str_buf[0] = '\0';
  878.                 _status = 0;
  879.                 _go = FALSE;
  880.                 break;
  881.             case NL  :
  882.                 _go = FALSE;
  883.                 break;
  884.             case CR  :
  885.                 _go = FALSE;
  886.                 break;
  887.             default  :
  888.                 if((ch >= ' ') && (ch <= '~')) {
  889.                     str_buf[ccnt++] =ch ; 
  890.                 }
  891.                 break;
  892.         }
  893.         if(ccnt == num) { _go = FALSE;}
  894.     } while(_go == TRUE);
  895.  
  896.     str_buf[ccnt] = '\0';
  897.     (void)strcat(str,str_buf);
  898.     return(_status);
  899. }
  900.  
  901.