home *** CD-ROM | disk | FTP | other *** search
/ Jason Aller Floppy Collection / 125.img / PRO-C4.ZIP / BENCH1.ZIP / BENCH / OPTION.C < prev    next >
C/C++ Source or Header  |  1990-05-28  |  12KB  |  500 lines

  1. /* ==( bench/option.c )== */
  2. /* ----------------------------------------------- */
  3. /* Pro-C  Copyright (C) 1988 - 1990 Vestronix Inc. */
  4. /* Modification to this source is not supported    */
  5. /* by Vestronix Inc.                               */
  6. /*            All Rights Reserved                  */
  7. /* ----------------------------------------------- */
  8. /* Written   Nig   1-Jan-87                        */
  9. /* Modified  SBF   5-Feb-90  see comments below    */
  10. /* ----------------------------------------------- */
  11. /* %W%  (%H% %T%) */
  12.  
  13. /*
  14.  * Modifications
  15.  *
  16.  * 11-Dec-89 Geo - V2 version
  17.  * 25-Oct-89 Geo - 1.32 Merge
  18.  * 23-Jan-90 Bob - general direction routine
  19.  *  5-Feb-90 SBF - added space select for toggles
  20. */
  21.  
  22. # include <stdio.h>
  23. # include <bench.h>
  24.  
  25. # ifdef ANSI
  26. int keytrig(char *, int *);
  27. int get_direction(struct optab *, int, int);
  28. static void is_it_lower(int, int, int, struct optab *);
  29. static void is_it_left(int, int, int, struct optab *);
  30. # else
  31. int keytrig();
  32. int get_direction();
  33. static void is_it_lower();
  34. static void is_it_left();
  35. # endif
  36.  
  37. int trigger_attr = BOLD;
  38.  
  39. /*
  40.  * Menu structure for selecting options
  41.  * A simple list of row, col, and string
  42.  * - the proceedure inits itself when the address
  43.  *   of the option table changes so it can be called
  44.  *   with different option lists
  45.  * - the choice variable will be modified if it exceeds
  46.  *   the range of items available (cf. code)
  47.  * - the list will terminate with a NULL, the row coord
  48.  *   is used as the normal attribute, the col coord is used
  49.  *   as the hi-light attribute
  50. */
  51.  
  52. /* Hatty & Natty should be picked up each time ? allows dynamic highlighting */
  53. extern struct window_rec *winptr;
  54.  
  55. /*
  56.  * Flag set by dsp_opt to
  57.  * be used in do_options to
  58.  * indicated selection
  59. */
  60. int selattr = FALSE;
  61. static int ccol, crow, row, col, oldfunc;
  62. static int omin, omax, save;
  63.  
  64. void dsp_opt(optabs, choice)
  65. struct optab optabs[];
  66. int *choice;
  67. {
  68.     struct optab *optr;
  69.     int hatty, norm;
  70.     int posn, ch;
  71.     int i;
  72.  
  73.     static struct optab *loptab = (struct optab *)0;
  74.     static int lchoice = 0, cnt;
  75.  
  76.     char *forceupper();
  77.  
  78.     /* Reset the address */
  79.     if (optabs == (struct optab *)0)
  80.     {
  81.         loptab = optabs;
  82.         lchoice = 0;
  83.         return;
  84.     }
  85.  
  86.     /* Reset the counter && highlight attribute */
  87.     for (optr = &optabs[0]; optr->text != NULL; optr++)
  88.         ;
  89.     hatty = (selattr == FALSE) ? optr->col : trigger_attr;
  90.     norm = optr->row;
  91.  
  92.     cnt = (int)(optr - optabs);
  93.     cnt--;
  94.  
  95.     /* Wrap around */
  96.     if (*choice < 0)
  97.         *choice = cnt;
  98.     else if (*choice > cnt)
  99.         *choice = 0;
  100.  
  101.     /* If a new structure change or a new window */
  102.     if (loptab != optabs || W_NEWIN)
  103.     {
  104.         /* Set this baby up */
  105.         loptab = optabs;
  106.  
  107.         for (i = 0, optr = &optabs[0]; i <= cnt; i++, optr++)
  108.         {
  109.             disp_w(optr->row, optr->col, norm, optr->text + ((*optr->text == '~') ? 1 : 0));
  110.             /* High light the trigger character */
  111.             ch = keytrig(optr->text, &posn);
  112.             poke_w(optr->row, optr->col + posn, trigger_attr, ch);
  113.         }
  114.  
  115.         for (i = 0, optr = &optabs[0]; i <= cnt; i++, optr++)
  116.             if (i == *choice)
  117.             {
  118.                 disp_w(optr->row, optr->col, hatty, optr->text + ((*optr->text == '~') ? 1 : 0));
  119.                 (void)keytrig(optr->text, &posn);
  120.                 moveto_w(optr->row, optr->col + posn);
  121.                 break;
  122.             }
  123.  
  124.         lchoice = *choice;
  125.         return;
  126.     }
  127.  
  128.     /* Now high light one and blank the other
  129.      * Must do this even if lchoice == *choice
  130.      * cos it might have used selected highlight
  131.     */
  132.     optr = &optabs[lchoice];
  133.     disp_w(optr->row, optr->col, norm, optr->text + ((*optr->text == '~') ? 1 : 0));
  134.     /* High light the trigger character */
  135.     ch = keytrig(optr->text, &posn);
  136.     poke_w(optr->row, optr->col + posn, trigger_attr, ch);
  137.  
  138.     optr = &optabs[*choice];
  139.     disp_w(optr->row, optr->col, hatty, optr->text + ((*optr->text == '~') ? 1 : 0));
  140.     (void)keytrig(optr->text, &posn);
  141.     moveto_w(optr->row, optr->col + posn);
  142.  
  143.     lchoice = *choice;
  144. }
  145.  
  146. char *forceupper(str)
  147. char *str;
  148. {
  149.     static char tmp[80];
  150.  
  151.     strcpy(tmp, str);
  152.     strupr(tmp);
  153.     return(tmp);
  154. }
  155.  
  156. /* This is a hack until better menus arrive */
  157. /* High light thisun */
  158. void dsp_sel_opt(optabs, choice)
  159. struct optab optabs[];
  160. int *choice;
  161. {
  162.     struct optab *optr;
  163.     int posn;
  164.  
  165. /* I assume all is okay */
  166.  
  167.     optr = &optabs[*choice];
  168.     disp_w(optr->row, optr->col, trigger_attr, optr->text + ((*optr->text == '~') ? 1 : 0));
  169.     (void)keytrig(optr->text, &posn);
  170.     moveto_w(optr->row, optr->col + posn);
  171. }
  172.  
  173. int do_options(options, curfunc, helpnum)
  174. struct optab options[];
  175. int curfunc, helpnum;
  176. {
  177.     int cc, iopt, oldfunc;
  178.     int dummy; /* Used to keep dummy happy */
  179.  
  180. # ifdef MOUSE
  181.     int r, c, w, h;
  182.     mouse_level++;
  183. # endif
  184.  
  185.     ichar = 0; /* clear ichar */
  186.     dsp_opt(options, &curfunc);
  187.  
  188.     do
  189.     {
  190.         keys_w(K_F1, help_prompt, K_CR, accept_prompt, K_ESC, exit_prompt, 0);
  191.  
  192.         cc = inchar();
  193.         if (cc <= 'z') /* Only do this if it is near [a-z] */
  194.             if (islower(cc)) /* this should trap >8bit values ! */
  195.                 cc = toupper(cc);
  196.  
  197.         /*
  198.         * get absolute window coordinates
  199.         */
  200. # ifdef MOUSE
  201.         abs_w(&r, &c, &w, &h);
  202. # endif
  203.  
  204.         for (iopt = 0; options[iopt].text != NULL; iopt++)
  205.         {
  206. # ifdef MOUSE
  207.         int key;
  208.  
  209.             key = (int)keytrig(options[iopt].text, &dummy);
  210.  
  211.             mouse_add_object(
  212.                 (unsigned char)r + options[iopt].row, 
  213.                 (unsigned char)c + options[iopt].col, 
  214.                 (unsigned char)r + options[iopt].row, 
  215.                 (unsigned char)c + options[iopt].col +
  216.                 strlen(options[iopt].text + ((*options[iopt].text == '~') ? 1 : 0)) - 1, key, iopt, NULL);
  217. # endif
  218.  
  219.             if (keytrig(options[iopt].text, &dummy) == cc)
  220.             {
  221.                 /* Reset the display and set this alight */
  222.                 selattr = TRUE;
  223.  
  224.                 dsp_opt(options, &iopt);
  225.                 selattr = FALSE; /* Does nothing when UNIX is active */
  226. # ifdef MOUSE
  227.                 mouse_delete_level(mouse_level--);
  228. # endif
  229.                 ichar = K_CR;   /* like we actually pressed it */
  230.                 return(iopt);
  231.             }
  232.         }
  233.  
  234.         oldfunc = curfunc;
  235.  
  236.         switch (cc)
  237.         {
  238. # ifdef MOUSE
  239.         case M_PRESS :
  240.         case M_RELEASE :
  241.             if (!mouse_check_bounds())
  242.             {
  243.                 int dummy;
  244.  
  245.                 mouse_click(&dummy, cc);
  246.             }
  247.             else if (mouse_click(&curfunc, cc))
  248.                 dsp_opt(options, &curfunc);
  249.             break;
  250. # endif
  251.         case ' ':
  252.             if (*options[curfunc].text == '~')
  253.             {
  254.                 cc = K_CR;
  255.                 break;
  256.             }
  257.             else
  258.                 cc = K_RIGHT;
  259.         case K_DOWN :
  260.         case K_UP :
  261.         case K_RIGHT :
  262.         case K_LEFT :
  263.             /*
  264.             * find the next element base on the key pressed 
  265.             */
  266.             curfunc = get_direction(options, curfunc, cc);
  267.             dsp_opt(options, &curfunc);
  268.             break;
  269.  
  270.         case '?' :
  271.         case K_HELP :
  272.             help_msg(helpnum);
  273.             break;
  274.         case K_TAB :
  275.         case K_ESC :
  276.             ichar = cc; /* set ichar in case anyone's interested */
  277. # ifdef MOUSE
  278.             mouse_delete_level(mouse_level--);
  279. # endif
  280.             return(-1);
  281.         }
  282.     }
  283.     while (cc != K_CR && cc != M_ESC && cc != K_TAB);
  284.  
  285.     ichar = cc;
  286.  
  287.     /* Reset the display and set this alight */
  288.     selattr = TRUE;
  289.     dsp_opt(options, &curfunc);
  290.     selattr = FALSE;
  291.  
  292. # ifdef MOUSE
  293.     mouse_delete_level(mouse_level--);
  294. # endif
  295.     return(curfunc);
  296. }
  297.  
  298. /*
  299.  * Return Character which is used as a trigger
  300.  * withinn a prompt string
  301.  * - " coMpute " yields 'M'
  302.  * - " nothing " yields 'N' 'cos no uppercase letter
  303.  * - " !dos "    yields '!' special case
  304.  * - " 2choice " yields '2' special case for leading numbers. SMV
  305. */
  306. int keytrig(str, posn)
  307. char *str;
  308. int *posn;
  309. {
  310.     int first;
  311.     char *ptr = str;
  312.  
  313.     if (*str == '~')
  314.     {
  315.         str++;
  316.         ptr++;
  317.     }
  318.     /* Point to first non-space */
  319.     while (*str && isspace(*str))
  320.         str++;
  321.     *posn = (int)(str - ptr);
  322.     first = *str;
  323.  
  324.     while (*str)
  325.     {
  326.         /* '!' often used for !Shell */
  327.         if (isupper(*str) || *str == '!' || isdigit(*str))
  328.         {
  329.             *posn = (int)(str - ptr);
  330.             return(*str);
  331.         }
  332.         str++;
  333.     }
  334.     if (first <= 'z' && islower(first)) /* See previous stuff */
  335.         first = toupper(first);
  336.     return(first);
  337. }
  338.  
  339.  
  340. /*
  341. * function to find the next element to move to based on which key was pressed
  342. * all movement is broken down into 4 direction UP, DOWN, LEFT, RIGHT
  343. *
  344. * if no match is found in the current direction then wrap around is tried.
  345. * if there is no wrap around then simple increment/decrement the current
  346. * index (RN, Jan 23, 1990)
  347. */
  348.  
  349. int get_direction(options, curfunc, key)
  350. struct optab options[];
  351. int curfunc;
  352. int key;
  353. {
  354.     int iopt, voffset, hoffset;
  355.  
  356.     crow = options[curfunc].row;            /* current column */
  357.     ccol = options[curfunc].col;               /* current row */
  358.     omin = omax = save = oldfunc = curfunc;
  359.     voffset = (key == K_UP) ? -1 : 1;      /* vertical offset */
  360.     hoffset = (key == K_LEFT) ? -1 : 1;  /* horizontal offset */
  361.     
  362.     if (key == K_UP || key == K_DOWN)
  363.     {
  364.         /*
  365.         * in this section we deal with vertical movement up/down
  366.         */
  367.         for (iopt = 0; options[iopt].text != NULL; iopt++)
  368.         {
  369.             if (iopt != curfunc)          /* we don't want the current index */
  370.             {
  371.                 row = options[iopt].row;
  372.                 col = options[iopt].col;
  373.                 if (col == ccol)  /* must be same column for a vertical match */
  374.                 {
  375.                     if (row == crow)
  376.                     {
  377.                         /* 
  378.                         * if we have the same row then the object probably overlap
  379.                         * this case handles the "space select" type of action
  380.                         */
  381.                         if (iopt == (curfunc + voffset))
  382.                             return(iopt);
  383.                     }
  384.                     is_it_lower(key, iopt, curfunc, options);
  385.                 }
  386.             }
  387.         }
  388.         /*
  389.         * we must go through the list a second time to check all of the item
  390.         * that don't match the col
  391.         */
  392.         for (iopt = 0; options[iopt].text != NULL; iopt++)
  393.         {
  394.             row = options[iopt].row;
  395.             is_it_lower(key, iopt, curfunc, options);
  396.         }
  397.         if (oldfunc == save)
  398.             if (omin == oldfunc && omax == oldfunc)
  399.                 save += voffset;     /* no wrap index found (default) */
  400.             else
  401.                 save = (voffset < 0) ? omax : omin; /* go to wrap index */
  402.  
  403.         return(save); /* return the new index */
  404.     }
  405.  
  406.     /*
  407.     * this section handles horizontal movement 
  408.     */
  409.     for (iopt = 0; options[iopt].text != NULL; iopt++)
  410.     {
  411.         if (iopt != curfunc)
  412.         {
  413.             row = options[iopt].row;
  414.             col = options[iopt].col;
  415.             if (row == crow)
  416.                 is_it_left(key, iopt, curfunc, options);
  417.         }
  418.     }
  419.  
  420.     if (oldfunc == save)
  421.         if (omin == oldfunc && omax == oldfunc)
  422.             save += hoffset;     /* no wrap index found (default) */
  423.         else
  424.             save = (hoffset < 0) ? omax : omin; /* go to wrap index */
  425.  
  426.     return(save); /* return the new index */
  427. }
  428.  
  429. /*
  430. * This function check to see an optab item (iopt) is
  431. * above or below the current one.
  432. * Max and omin positions are also checked
  433. */
  434.  
  435. static void is_it_lower(key, iopt, curfunc, options)
  436. int key, iopt, curfunc;
  437. struct optab options[];
  438. {
  439.     if (row > crow)
  440.     {
  441.         if (key == K_DOWN)
  442.             if (save == curfunc || (row < options[save].row))
  443.                 save = iopt; /* closest match so far */
  444.         if (row > options[omax].row)
  445.             omax = iopt;  /* this is the lowest match so far */
  446.     }
  447.     else
  448.     {
  449.         if (row < crow)
  450.         {
  451.             /*
  452.             * this element is above the current one 
  453.             */
  454.             if (key == K_UP)
  455.                 if (save == curfunc || (row > options[save].row))
  456.                     save = iopt; /* closest match so far */
  457.             if (row < options[omin].row)
  458.                 omin = iopt;   /* this is the highest match so far */
  459.         }
  460.     }
  461. }
  462.  
  463. /*
  464. * This function check to see an optab item (iopt) is
  465. * to the left or right of the current one.
  466. * Max and omin positions are also checked
  467. */
  468.  
  469. static void is_it_left(key, iopt, curfunc, options)
  470. int key, iopt, curfunc;
  471. struct optab options[];
  472. {
  473.     if (col > ccol)
  474.     {
  475.         /*
  476.         *  this item is to the right of the current one 
  477.         */
  478.         if (key == K_RIGHT)
  479.             if (save == curfunc || (col < options[save].col))
  480.                 save = iopt; /* good candidate so let's save it */
  481.         if (col > options[omax].col)
  482.             omax = iopt; /* furthest right so far */
  483.     }
  484.     if (col < ccol)
  485.     {
  486.         /*
  487.         *  this item is to the left of the current one 
  488.         */
  489.         if (col < ccol)
  490.         {
  491.             if (key == K_LEFT)
  492.                 if (save == curfunc || (col > options[save].col))
  493.                     save = iopt; /* good candidate so let's save it */
  494.             if (col < options[omin].col)
  495.                 omin = iopt; /* furthest left so far */
  496.         }
  497.     }
  498. }
  499.  
  500.