home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume4 / rolodex / part3 / toolsdir / menu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-11-30  |  7.5 KB  |  345 lines

  1. #include <stdio.h>
  2. #include <varargs.h>
  3. #include "ctools.h"
  4. #include "menu.h"
  5. #include "sys5.h"
  6.  
  7.  
  8. static char line[MAX_MENU_RESPONSE_LENGTH];
  9.  
  10.  
  11. menu_match (
  12.  
  13.      ptr_rval,ptr_ur,prompt,casetest,isub,r_no_match,r_ambiguous,n_options,
  14.      va_alist
  15.      
  16.    )
  17.  
  18.   int *ptr_rval;
  19.   char **ptr_ur;
  20.   char *prompt;
  21.   int casetest;
  22.   int isub;
  23.   int r_no_match;
  24.   int r_ambiguous;
  25.   int n_options;
  26.   va_dcl
  27.     
  28. {
  29.  
  30.   char sline[MAX_MENU_RESPONSE_LENGTH];
  31.   char *option, *options[MAX_MENU_OPTIONS];
  32.   int rvals[MAX_MENU_OPTIONS];
  33.   int j,found,*addr,len,optionlen,rval,compare,blankindex;
  34.   va_list pvar;
  35.         
  36.   if (n_options > MAX_MENU_OPTIONS) return(MENU_ERROR);
  37.   for (j = 0; j < MAX_MENU_RESPONSE_LENGTH; j++) line[j] = ' ';
  38.   
  39.   /* grab all the menu options and return values.  */
  40.   
  41.   blankindex = -1;
  42.   va_start(pvar);
  43.   for (j = 0; j < n_options; j++) {
  44.       options[j] = va_arg(pvar,char *);
  45.       if (0 == strlen(options[j])) {
  46.          if (blankindex == -1) blankindex = j;
  47.       }
  48.       rvals[j] = va_arg(pvar,int);
  49.   }
  50.   va_end(pvar);
  51.   
  52.   try_again :
  53.   
  54.   /* get the user's response */
  55.   
  56.   printf("%s",prompt);
  57.   switch (rval = getline(stdin,line,MAX_MENU_RESPONSE_LENGTH)) {
  58.     case AT_EOF :
  59.       return(MENU_EOF);
  60.       break;
  61.     case TOO_MANY_CHARS :
  62.      fprintf(stderr,"Response is too long to handle.  Please try again\n");
  63.      goto try_again;
  64.      break;
  65.    default :
  66.      *ptr_ur = line;
  67.      remove_excess_blanks(sline,line);
  68.      len = strlen(sline);
  69.      break;
  70.  }
  71.     
  72.   found = 0;
  73.   rval = MENU_NO_MATCH;
  74.   
  75.   if (all_whitespace(sline)) {
  76.      if (blankindex == -1) goto try_again;
  77.      rval = MENU_MATCH;
  78.      *ptr_rval = rvals[blankindex];
  79.      goto rtn;
  80.   }     
  81.   
  82.   for (j = 0; j < n_options; j ++) {
  83.  
  84.       /* if what he typed in is longer than any option it can't match */
  85.         
  86.       optionlen = strlen(options[j]);
  87.       if (len > optionlen) continue;  
  88.       
  89.       /* if we aren't matching initial substrings, the response must */
  90.       /* match exactly. */
  91.       
  92.       if (!isub && len != optionlen) continue;
  93.       
  94.       /* use different comparision functions depending on whether case */
  95.       /* is important or not. */
  96.       
  97.       compare = casetest ? 
  98.                 strncmp(sline,options[j],len) : 
  99.                 nocase_compare(sline,len,options[j],len);
  100.                 
  101.       /* if we must match exactly, if we find a match exit immediately. */
  102.       /* if we can match on an initial substring, if we've already found */
  103.       /* a match then we have an ambiguity, otherwise note that we've */
  104.       /* matched and continue looking in case of ambiguities */
  105.                 
  106.       if (0 == compare) {
  107.          if (!isub) {
  108.             found = 1;
  109.             *ptr_rval = rvals[j];
  110.             rval = MENU_MATCH;
  111.             break;
  112.          }
  113.          if (found && isub) {
  114.             rval = MENU_AMBIGUOUS;
  115.             break;
  116.          }
  117.          else {
  118.             found = 1;
  119.             *ptr_rval = rvals[j];
  120.             rval = MENU_MATCH;
  121.          }
  122.       }
  123.       else {
  124.          continue;
  125.       }
  126.   }
  127.  
  128.   rtn :
  129.   
  130.   switch (rval) {
  131.     case MENU_MATCH :
  132.       break;
  133.     case MENU_NO_MATCH :
  134.       if (r_no_match) {
  135.          printf("Your response does not match any option.  Try again\n");
  136.          goto try_again;
  137.       }
  138.       break;
  139.     case MENU_AMBIGUOUS :
  140.       if (r_ambiguous) {
  141.          printf("Your response is ambiguous.  Try again\n");
  142.          goto try_again;
  143.       }
  144.       break;
  145.     default :
  146.       fprintf(stderr,"Impossible case value in menu_match\n");
  147.       exit(-1);
  148.   }
  149.       
  150.   return(rval);
  151.   
  152. }
  153.  
  154.  
  155. menu_yes_no (prompt,allow_help) char *prompt; int allow_help;
  156.  
  157. {
  158.   int menuval,rval;
  159.   char *response;
  160.   
  161.   redo :
  162.   
  163.   if (!allow_help) {
  164.      rval = menu_match (
  165.           &menuval,&response,
  166.           prompt,
  167.           0,1,0,0,2,
  168.           "Yes",MENU_YES,
  169.           "No",MENU_NO
  170.        );
  171.   }
  172.   else {
  173.      rval = menu_match (
  174.           &menuval,&response,
  175.           prompt,
  176.           0,1,0,0,4,
  177.           "Yes",MENU_YES,
  178.           "No",MENU_NO,
  179.           "?",MENU_HELP,
  180.           "Help",MENU_HELP
  181.        );
  182.   }
  183.   switch (rval) {
  184.     case MENU_MATCH :
  185.       return(menuval);
  186.       break;
  187.     case MENU_NO_MATCH :
  188.       fprintf(stderr,"Please type 'Yes' or 'No'...\n");
  189.       goto redo;
  190.       break;
  191.     case MENU_EOF :
  192.       return(MENU_EOF);
  193.       break;
  194.     default :
  195.       fprintf(stderr,"Fatal error:  Impossible return in menu_yes_no\n");
  196.       exit(-1);
  197.   }
  198. }
  199.  
  200.  
  201. extern int menu_data_help_or_abort (prompt,abortstring,ptr_response)
  202.  
  203.   char *prompt, *abortstring, **ptr_response;
  204.  
  205. {
  206.   int rval,menuval;
  207.   rval = menu_match (
  208.        &menuval,ptr_response,
  209.        prompt,
  210.        0,1,0,1,3,
  211.        abortstring,MENU_ABORT,
  212.        "?",MENU_HELP,
  213.        "Help",MENU_HELP
  214.     );
  215.   switch (rval) {
  216.     case MENU_NO_MATCH :
  217.       return(MENU_DATA);
  218.       break;
  219.     case MENU_MATCH :
  220.       return(menuval);
  221.       break;
  222.     case MENU_EOF :
  223.       return(MENU_EOF);
  224.       break;
  225.     default :
  226.       fprintf(stderr,"Impossible return from menu_data_help_or_abort\n");
  227.       exit(-1);
  228.   }
  229. }
  230.  
  231.  
  232. menu_number_help_or_abort (prompt,abortstring,low,high,ptr_ival)
  233.  
  234.   char *prompt, *abortstring;
  235.   int low,high,*ptr_ival;
  236.  
  237. {
  238.   char *response,errprompt[80],numstring[MAX_MENU_RESPONSE_LENGTH];
  239.   int rval,check;
  240.   
  241.   if (!(check = (low <= high)))
  242.      nbuffconcat(errprompt,1,"Please enter a non-negative number...\n");
  243.   else
  244.      sprintf(errprompt,"Please enter a number between %d and %d\n",low,high);
  245.   
  246.   reask :     
  247.      
  248.   rval = menu_data_help_or_abort(prompt,abortstring,&response);
  249.   switch (rval) {
  250.     case MENU_EOF :
  251.     case MENU_ABORT :
  252.     case MENU_HELP :
  253.       return(rval);
  254.       break;
  255.     case MENU_DATA :
  256.       remove_excess_blanks(numstring,response);
  257.       switch (*ptr_ival = str_to_pos_int(numstring,0,MAXINT)) {
  258.         case -1:
  259.         case -2:
  260.           fprintf(stderr,"%s",errprompt);
  261.           goto reask;
  262.           break;
  263.         default:
  264.           return(MENU_DATA);
  265.           break;
  266.       }
  267.   }
  268.  
  269. }
  270.  
  271.  
  272. menu_yes_no_abort_or_help (prompt,abortstring,helpallowed,return_for_yes)
  273.  
  274. /*
  275.     Returns one of MENU_YES, MENU_NO, MENU_ABORT or MENU_HELP.
  276.     If !helpallowed, MENU_HELP will not be returned.  
  277.     If return_for_yes is 0, hitting return will re-prompt.
  278.     If it is 1, hitting return is like typing yes.
  279.     If it is any other value, hitting return is like typing no.
  280. */
  281.  
  282.   char *prompt;
  283.   char *abortstring;
  284.   int helpallowed; 
  285.   int return_for_yes;
  286.  
  287. {
  288.   int menuval,rval;
  289.   char *response;
  290.   
  291.   redo :
  292.   
  293.   if (!helpallowed) {
  294.      rval = menu_match (
  295.           &menuval,&response,
  296.           prompt,
  297.           0,1,0,0,4,
  298.           "Yes",MENU_YES,
  299.           "No",MENU_NO,
  300.           abortstring,MENU_ABORT,
  301.           "",MENU_RETURN
  302.        );
  303.   }
  304.   else {
  305.      rval = menu_match (
  306.           &menuval,&response,
  307.           prompt,
  308.           0,1,0,0,6,
  309.           "Yes",MENU_YES,
  310.           "No",MENU_NO,
  311.           "?",MENU_HELP,
  312.           "Help",MENU_HELP,
  313.           abortstring,MENU_ABORT,
  314.           "",MENU_RETURN
  315.        );
  316.   }
  317.   switch (rval) {
  318.     case MENU_MATCH :
  319.       if (menuval != MENU_RETURN) return(menuval);
  320.       switch (return_for_yes) {
  321.         case NO_DEFAULT :
  322.           goto redo;
  323.           break;
  324.         case DEFAULT_YES :
  325.           return(MENU_YES);
  326.           break;
  327.         default :
  328.           return(MENU_NO);
  329.           break;
  330.       }
  331.       break;
  332.     case MENU_NO_MATCH :
  333.       printf("Please type 'Yes' or 'No'...\n");
  334.       goto redo;
  335.       break;
  336.     case MENU_EOF :
  337.       return(MENU_EOF);
  338.       break;
  339.     default :
  340.       fprintf(stderr,"Fatal error:  Impossible return in menu_yes_no\n");
  341.       exit(-1);
  342.   }
  343. }
  344.  
  345.