home *** CD-ROM | disk | FTP | other *** search
- /* ==( bench/option.c )== */
- /* ----------------------------------------------- */
- /* Pro-C Copyright (C) 1988 - 1990 Vestronix Inc. */
- /* Modification to this source is not supported */
- /* by Vestronix Inc. */
- /* All Rights Reserved */
- /* ----------------------------------------------- */
- /* Written Nig 1-Jan-87 */
- /* Modified SBF 5-Feb-90 see comments below */
- /* ----------------------------------------------- */
- /* %W% (%H% %T%) */
-
- /*
- * Modifications
- *
- * 11-Dec-89 Geo - V2 version
- * 25-Oct-89 Geo - 1.32 Merge
- * 23-Jan-90 Bob - general direction routine
- * 5-Feb-90 SBF - added space select for toggles
- */
-
- # include <stdio.h>
- # include <bench.h>
-
- # ifdef ANSI
- int keytrig(char *, int *);
- int get_direction(struct optab *, int, int);
- static void is_it_lower(int, int, int, struct optab *);
- static void is_it_left(int, int, int, struct optab *);
- # else
- int keytrig();
- int get_direction();
- static void is_it_lower();
- static void is_it_left();
- # endif
-
- int trigger_attr = BOLD;
-
- /*
- * Menu structure for selecting options
- * A simple list of row, col, and string
- * - the proceedure inits itself when the address
- * of the option table changes so it can be called
- * with different option lists
- * - the choice variable will be modified if it exceeds
- * the range of items available (cf. code)
- * - the list will terminate with a NULL, the row coord
- * is used as the normal attribute, the col coord is used
- * as the hi-light attribute
- */
-
- /* Hatty & Natty should be picked up each time ? allows dynamic highlighting */
- extern struct window_rec *winptr;
-
- /*
- * Flag set by dsp_opt to
- * be used in do_options to
- * indicated selection
- */
- int selattr = FALSE;
- static int ccol, crow, row, col, oldfunc;
- static int omin, omax, save;
-
- void dsp_opt(optabs, choice)
- struct optab optabs[];
- int *choice;
- {
- struct optab *optr;
- int hatty, norm;
- int posn, ch;
- int i;
-
- static struct optab *loptab = (struct optab *)0;
- static int lchoice = 0, cnt;
-
- char *forceupper();
-
- /* Reset the address */
- if (optabs == (struct optab *)0)
- {
- loptab = optabs;
- lchoice = 0;
- return;
- }
-
- /* Reset the counter && highlight attribute */
- for (optr = &optabs[0]; optr->text != NULL; optr++)
- ;
- hatty = (selattr == FALSE) ? optr->col : trigger_attr;
- norm = optr->row;
-
- cnt = (int)(optr - optabs);
- cnt--;
-
- /* Wrap around */
- if (*choice < 0)
- *choice = cnt;
- else if (*choice > cnt)
- *choice = 0;
-
- /* If a new structure change or a new window */
- if (loptab != optabs || W_NEWIN)
- {
- /* Set this baby up */
- loptab = optabs;
-
- for (i = 0, optr = &optabs[0]; i <= cnt; i++, optr++)
- {
- disp_w(optr->row, optr->col, norm, optr->text + ((*optr->text == '~') ? 1 : 0));
- /* High light the trigger character */
- ch = keytrig(optr->text, &posn);
- poke_w(optr->row, optr->col + posn, trigger_attr, ch);
- }
-
- for (i = 0, optr = &optabs[0]; i <= cnt; i++, optr++)
- if (i == *choice)
- {
- disp_w(optr->row, optr->col, hatty, optr->text + ((*optr->text == '~') ? 1 : 0));
- (void)keytrig(optr->text, &posn);
- moveto_w(optr->row, optr->col + posn);
- break;
- }
-
- lchoice = *choice;
- return;
- }
-
- /* Now high light one and blank the other
- * Must do this even if lchoice == *choice
- * cos it might have used selected highlight
- */
- optr = &optabs[lchoice];
- disp_w(optr->row, optr->col, norm, optr->text + ((*optr->text == '~') ? 1 : 0));
- /* High light the trigger character */
- ch = keytrig(optr->text, &posn);
- poke_w(optr->row, optr->col + posn, trigger_attr, ch);
-
- optr = &optabs[*choice];
- disp_w(optr->row, optr->col, hatty, optr->text + ((*optr->text == '~') ? 1 : 0));
- (void)keytrig(optr->text, &posn);
- moveto_w(optr->row, optr->col + posn);
-
- lchoice = *choice;
- }
-
- char *forceupper(str)
- char *str;
- {
- static char tmp[80];
-
- strcpy(tmp, str);
- strupr(tmp);
- return(tmp);
- }
-
- /* This is a hack until better menus arrive */
- /* High light thisun */
- void dsp_sel_opt(optabs, choice)
- struct optab optabs[];
- int *choice;
- {
- struct optab *optr;
- int posn;
-
- /* I assume all is okay */
-
- optr = &optabs[*choice];
- disp_w(optr->row, optr->col, trigger_attr, optr->text + ((*optr->text == '~') ? 1 : 0));
- (void)keytrig(optr->text, &posn);
- moveto_w(optr->row, optr->col + posn);
- }
-
- int do_options(options, curfunc, helpnum)
- struct optab options[];
- int curfunc, helpnum;
- {
- int cc, iopt, oldfunc;
- int dummy; /* Used to keep dummy happy */
-
- # ifdef MOUSE
- int r, c, w, h;
- mouse_level++;
- # endif
-
- ichar = 0; /* clear ichar */
- dsp_opt(options, &curfunc);
-
- do
- {
- keys_w(K_F1, help_prompt, K_CR, accept_prompt, K_ESC, exit_prompt, 0);
-
- cc = inchar();
- if (cc <= 'z') /* Only do this if it is near [a-z] */
- if (islower(cc)) /* this should trap >8bit values ! */
- cc = toupper(cc);
-
- /*
- * get absolute window coordinates
- */
- # ifdef MOUSE
- abs_w(&r, &c, &w, &h);
- # endif
-
- for (iopt = 0; options[iopt].text != NULL; iopt++)
- {
- # ifdef MOUSE
- int key;
-
- key = (int)keytrig(options[iopt].text, &dummy);
-
- mouse_add_object(
- (unsigned char)r + options[iopt].row,
- (unsigned char)c + options[iopt].col,
- (unsigned char)r + options[iopt].row,
- (unsigned char)c + options[iopt].col +
- strlen(options[iopt].text + ((*options[iopt].text == '~') ? 1 : 0)) - 1, key, iopt, NULL);
- # endif
-
- if (keytrig(options[iopt].text, &dummy) == cc)
- {
- /* Reset the display and set this alight */
- selattr = TRUE;
-
- dsp_opt(options, &iopt);
- selattr = FALSE; /* Does nothing when UNIX is active */
- # ifdef MOUSE
- mouse_delete_level(mouse_level--);
- # endif
- ichar = K_CR; /* like we actually pressed it */
- return(iopt);
- }
- }
-
- oldfunc = curfunc;
-
- switch (cc)
- {
- # ifdef MOUSE
- case M_PRESS :
- case M_RELEASE :
- if (!mouse_check_bounds())
- {
- int dummy;
-
- mouse_click(&dummy, cc);
- }
- else if (mouse_click(&curfunc, cc))
- dsp_opt(options, &curfunc);
- break;
- # endif
- case ' ':
- if (*options[curfunc].text == '~')
- {
- cc = K_CR;
- break;
- }
- else
- cc = K_RIGHT;
- case K_DOWN :
- case K_UP :
- case K_RIGHT :
- case K_LEFT :
- /*
- * find the next element base on the key pressed
- */
- curfunc = get_direction(options, curfunc, cc);
- dsp_opt(options, &curfunc);
- break;
-
- case '?' :
- case K_HELP :
- help_msg(helpnum);
- break;
- case K_TAB :
- case K_ESC :
- ichar = cc; /* set ichar in case anyone's interested */
- # ifdef MOUSE
- mouse_delete_level(mouse_level--);
- # endif
- return(-1);
- }
- }
- while (cc != K_CR && cc != M_ESC && cc != K_TAB);
-
- ichar = cc;
-
- /* Reset the display and set this alight */
- selattr = TRUE;
- dsp_opt(options, &curfunc);
- selattr = FALSE;
-
- # ifdef MOUSE
- mouse_delete_level(mouse_level--);
- # endif
- return(curfunc);
- }
-
- /*
- * Return Character which is used as a trigger
- * withinn a prompt string
- * - " coMpute " yields 'M'
- * - " nothing " yields 'N' 'cos no uppercase letter
- * - " !dos " yields '!' special case
- * - " 2choice " yields '2' special case for leading numbers. SMV
- */
- int keytrig(str, posn)
- char *str;
- int *posn;
- {
- int first;
- char *ptr = str;
-
- if (*str == '~')
- {
- str++;
- ptr++;
- }
- /* Point to first non-space */
- while (*str && isspace(*str))
- str++;
- *posn = (int)(str - ptr);
- first = *str;
-
- while (*str)
- {
- /* '!' often used for !Shell */
- if (isupper(*str) || *str == '!' || isdigit(*str))
- {
- *posn = (int)(str - ptr);
- return(*str);
- }
- str++;
- }
- if (first <= 'z' && islower(first)) /* See previous stuff */
- first = toupper(first);
- return(first);
- }
-
-
- /*
- * function to find the next element to move to based on which key was pressed
- * all movement is broken down into 4 direction UP, DOWN, LEFT, RIGHT
- *
- * if no match is found in the current direction then wrap around is tried.
- * if there is no wrap around then simple increment/decrement the current
- * index (RN, Jan 23, 1990)
- */
-
- int get_direction(options, curfunc, key)
- struct optab options[];
- int curfunc;
- int key;
- {
- int iopt, voffset, hoffset;
-
- crow = options[curfunc].row; /* current column */
- ccol = options[curfunc].col; /* current row */
- omin = omax = save = oldfunc = curfunc;
- voffset = (key == K_UP) ? -1 : 1; /* vertical offset */
- hoffset = (key == K_LEFT) ? -1 : 1; /* horizontal offset */
-
- if (key == K_UP || key == K_DOWN)
- {
- /*
- * in this section we deal with vertical movement up/down
- */
- for (iopt = 0; options[iopt].text != NULL; iopt++)
- {
- if (iopt != curfunc) /* we don't want the current index */
- {
- row = options[iopt].row;
- col = options[iopt].col;
- if (col == ccol) /* must be same column for a vertical match */
- {
- if (row == crow)
- {
- /*
- * if we have the same row then the object probably overlap
- * this case handles the "space select" type of action
- */
- if (iopt == (curfunc + voffset))
- return(iopt);
- }
- is_it_lower(key, iopt, curfunc, options);
- }
- }
- }
- /*
- * we must go through the list a second time to check all of the item
- * that don't match the col
- */
- for (iopt = 0; options[iopt].text != NULL; iopt++)
- {
- row = options[iopt].row;
- is_it_lower(key, iopt, curfunc, options);
- }
- if (oldfunc == save)
- if (omin == oldfunc && omax == oldfunc)
- save += voffset; /* no wrap index found (default) */
- else
- save = (voffset < 0) ? omax : omin; /* go to wrap index */
-
- return(save); /* return the new index */
- }
-
- /*
- * this section handles horizontal movement
- */
- for (iopt = 0; options[iopt].text != NULL; iopt++)
- {
- if (iopt != curfunc)
- {
- row = options[iopt].row;
- col = options[iopt].col;
- if (row == crow)
- is_it_left(key, iopt, curfunc, options);
- }
- }
-
- if (oldfunc == save)
- if (omin == oldfunc && omax == oldfunc)
- save += hoffset; /* no wrap index found (default) */
- else
- save = (hoffset < 0) ? omax : omin; /* go to wrap index */
-
- return(save); /* return the new index */
- }
-
- /*
- * This function check to see an optab item (iopt) is
- * above or below the current one.
- * Max and omin positions are also checked
- */
-
- static void is_it_lower(key, iopt, curfunc, options)
- int key, iopt, curfunc;
- struct optab options[];
- {
- if (row > crow)
- {
- if (key == K_DOWN)
- if (save == curfunc || (row < options[save].row))
- save = iopt; /* closest match so far */
- if (row > options[omax].row)
- omax = iopt; /* this is the lowest match so far */
- }
- else
- {
- if (row < crow)
- {
- /*
- * this element is above the current one
- */
- if (key == K_UP)
- if (save == curfunc || (row > options[save].row))
- save = iopt; /* closest match so far */
- if (row < options[omin].row)
- omin = iopt; /* this is the highest match so far */
- }
- }
- }
-
- /*
- * This function check to see an optab item (iopt) is
- * to the left or right of the current one.
- * Max and omin positions are also checked
- */
-
- static void is_it_left(key, iopt, curfunc, options)
- int key, iopt, curfunc;
- struct optab options[];
- {
- if (col > ccol)
- {
- /*
- * this item is to the right of the current one
- */
- if (key == K_RIGHT)
- if (save == curfunc || (col < options[save].col))
- save = iopt; /* good candidate so let's save it */
- if (col > options[omax].col)
- omax = iopt; /* furthest right so far */
- }
- if (col < ccol)
- {
- /*
- * this item is to the left of the current one
- */
- if (col < ccol)
- {
- if (key == K_LEFT)
- if (save == curfunc || (col > options[save].col))
- save = iopt; /* good candidate so let's save it */
- if (col < options[omin].col)
- omin = iopt; /* furthest left so far */
- }
- }
- }
-
-