home *** CD-ROM | disk | FTP | other *** search
-
- /*+
- * File: select.c
- *
- * Description:
- * Display a list of items for selection.
- *
- * This module is the proprietary property of Cottege Computing
- * copyright 1989, all rights reserved.
- *
- * Audit Trail:
- * SCCSID = @(#) select.c 1.2 11/20/89 15:05:06
- * Dan Flak - 11/7/89
- *
- -*/
-
- /* #includes */
- #include <curses.h>
-
- /* #defines */
- #define SAY printf
-
- #define RETURN '\015'
- #define ESC '\033'
- #define BACKSPACE '\010'
-
- #define MAX(x,y) (((x) < (y)) ? y : x)
- #define MIN(x,y) (((x) > (y)) ? y : x)
- #define WINLEN 20
- #define ARRAYPOS linenum + irow + lastline * icol
-
- #define UP 1
- #define DOWN 2
- #define LEFT 3
- #define RIGHT 4
-
- #define ON 1
- #define OFF 0
-
- /* external variables */
-
- /* referenced external functions */
-
- /* referenced internal functions */
- char *closewin();
- char *select();
- int do_esc();
- void errormsg();
- void newpage();
- void homecursor();
- void putcursor();
- void mvcursor();
- void scroll();
- void redraw();
- void wrap();
-
- /* global variables */
-
- char *rtnstr = NULL; /* return string (item selected) */
- char cmdstr[32]; /* printf format string */
-
- int arraypos = 0; /* item position in array */
- int center; /* center of the screen */
- int column = 0; /* column number */
- int lastline; /* last line in the array */
- int linenum = 0; /* line number */
- int ncol = 1; /* number of columns */
- int screenx = 0, screeny = 0; /* x and y screen positions */
-
- WINDOW *win1, *win2, *win3; /* information, command and work- */
- /* ing windows */
-
-
- /* static variables */
-
-
- /*<
- * Function: select (array, narray, width)
- *
- * Description:
- * Select an item from an array.
- *
- * Data Type: char *
- *
- * Arguments:
- * array - the array containing the selection items
- * narray - number of items in the array.
- * width - string length of items in the array.
- *
- * Returns:
- * pointer to a string containing the item name.
- *
- * Side Effects:
- *
- * Calls:
- *
- * PDL:
- *
- >*/
-
- char *
- select (array, narray, width)
- char *array[];
- int narray;
- int width;
- {
- int i;
-
- ncol = 80 / (6 + width); /* determine number of columns */
- center = 40 - (6 + width) / 2;
-
- if (ncol > 10 || ncol < 1) /* will display fit on screen? */
- {
- return (closewin (-2));
- }
-
- lastline = narray / ncol; /* compute total number of lines */
- if (narray % ncol)
- {
- lastline++;
- }
-
- sprintf (cmdstr, "%c3d %c-%d.%ds", '%', '%', width, width);
-
- initscr();
- crmode ();
- noecho ();
- nonl();
-
- win1 = newwin ( 2, 80, 0, 0); /* top information window */
- win2 = newwin (WINLEN, 80, 2, 0); /* working window */
- win3 = newwin ( 2, 80, 22, 0); /* command window */
-
- wmove (win1, 0, 0); /* print instructions */
- waddstr (win1, "Use arrow keys and <RETURN> to select from menu or");
- wmove (win1, 1, 0);
- waddstr (win1, "'#' to enter number or <SPACE> to enter name. <ESC>Q quits");
- wrefresh (win1);
-
- wclear (win2);
- redraw (array, narray); /* show intial set of items */
- homecursor(array);
-
- while (getcmds(array, narray)) /* get commands */
- {
- homecursor(array); /* put cursor at bottom of screen */
- }
-
- return (closewin(0));
- }
-
-
- /*<
- * Function: getcmds (array narray)
- *
- * Description:
- * Get cursor commands
- *
- * Data Type: int
- *
- * Arguments:
- * array - the array containing the items
- * narray - the number of elements in the array
- *
- * Returns:
- * 0 - upon <ESC>q.
- * 0 - upon confirmation of selection.
- * 1 - all other cases.
- *
- * Side Effects:
- *
- * Calls:
- *
- * PDL:
- *
- >*/
-
- int
- getcmds (array, narray)
- char *array[];
- int narray;
- {
- int c;
-
- c = wgetch (win3);
-
- switch (c)
- {
- case ESC:
- return (do_esc(array, narray));
- break;
- case ' ':
- return (do_string (array, narray));
- break;
- case '#':
- return (do_number(array, narray));
- break;
- case RETURN:
- rtnstr = array[arraypos];
- return (confirm());
- break;
- default:
- return (1);
- break;
- }
- }
-
-
- /*<
- * Function: do_esc (array, narray)
- *
- * Description:
- * Evaluate ESC sequences for cursor moves, scroll, wrap and
- * paging.
- *
- * Data Type: int
- *
- * Arguments:
- * array - array of display items
- * narray - number of elements in array
- *
- * Returns:
- * 0 for <ESC>Q
- * 1 for anything else
- *
- * Side Effects:
- *
- * Calls:
- *
- * PDL:
- *
- >*/
-
- int
- do_esc (array, narray)
- char *array[];
- int narray;
- {
- int c;
-
- c = wgetch (win3);
-
- if (c == '[') /* it's an arrow key */
- {
- c = wgetch (win3);
- switch (c)
- {
- case 'A': /* up arrow */
- if (screeny == 0 && linenum > 0)
- { /* if at top with items above */
- scroll (UP, array, narray);
- }
- else if (screeny > 0) /* cursor below top line */
- {
- mvcursor (UP, array, narray);
- }
- break;
- case 'B': /* down arrow */
- if (screeny == WINLEN -1 && linenum + WINLEN < lastline)
- { /* if on bottom with items below */
- scroll (DOWN, array, narray);
- }
- else if (screeny < MIN (WINLEN - 1, lastline - 1))
- { /* cursor above bottom line */
- mvcursor (DOWN, array, narray);
- }
- break;
- case 'C': /* right arrow */
- if (screenx < (80 * (ncol - 1)) / ncol)
- { /* if not in right column */
- mvcursor (RIGHT, array, narray);
- }
- else if (screenx == (80 * (ncol - 1)) / ncol)
- { /* if in right column */
- wrap (RIGHT, array, narray);
- }
- break;
- case 'D': /* left arrow */
- if (screenx > 0)
- { /* if not in left column */
- mvcursor (LEFT, array, narray);
- }
- else
- { /* in left column */
- wrap (LEFT, array, narray);
- }
- break;
- }
- } /* end case arrow */
- else
- {
- switch (c)
- {
- case 'N': case 'n': /* Next page */
- linenum = MIN (linenum + 2 * WINLEN, lastline) - WINLEN;
- newpage ();
- redraw (array, narray);
- break;
- case 'P': case 'p': /* Previous page */
- linenum = MAX (0, linenum - WINLEN);
- newpage ();
- redraw (array, narray);
- break;
- case 'T': case 't': /* Top of scroll */
- linenum = 0;
- newpage ();
- redraw (array, narray);
- break;
- case 'B': case 'b': /* Bottom of scroll */
- linenum = MAX(0, lastline - WINLEN);
- newpage ();
- redraw (array, narray);
- break;
- case 'R': case 'r':
- wclear (win2);
- redraw (array, narray);
- break;
- case 'Q': case 'q': /* Quit */
- return (0);
- break;
- }
- } /* end case anything else */
- return (1);
- }
-
-
- /*<
- * Function: closewin (n)
- *
- * Description:
- * Close the windows gracefully
- *
- * Data Type: char *
- *
- * Arguments:
- * n = exit code
- *
- * Returns:
- *
- * Side Effects:
- *
- * Calls:
- *
- * PDL:
- *
- >*/
-
- char *
- closewin (n)
- int n;
- {
- werase (win1);
- werase (win2);
- werase (win3);
-
- wrefresh (win1);
- wrefresh (win2);
- wrefresh (win3);
-
- endwin ();
-
- if (n) /* If error */
- {
- return (NULL); /* Return pointer to a null */
- }
- else
- {
- return (rtnstr); /* Return pointer to selected item */
- }
- }
-
-
- /*<
- * Function: redraw (array, narray)
- *
- * Description:
- * Redraw the working screen
- *
- * Data Type: void
- *
- * Arguments:
- * array - array of items to display.
- * narray - number of elements in the array
- *
- * Returns: None
- *
- * Side Effects:
- *
- * Calls:
- *
- * PDL:
- *
- >*/
-
- void
- redraw(array, narray)
- char *array[];
- int narray;
- {
- int irow, icol; /* screen row and column number */
-
- for (irow = 0; irow < MIN (lastline, WINLEN); irow++)
- {
- for (icol = 0; icol < ncol; icol++) /* for each row and column */
- {
- wmove (win2, irow, (80 * icol) / ncol);
- if (ARRAYPOS == arraypos) /* highlight the selection */
- {
- wstandout (win2);
- }
- else
- {
- wstandend (win2);
- }
- if ((irow + linenum < lastline) + ncol && icol == ncol -1)
- { /* clear old items in last column */
- wclrtoeol (win2);
- }
- if (ARRAYPOS < narray) /* Print all if you can */
- {
- wprintw (win2, cmdstr, ARRAYPOS + 1, array[ARRAYPOS]);
- }
- }
- }
- wrefresh (win2);
- }
-
-
- /*<
- * Function: mvcursor (n, array, narray)
- *
- * Description:
- * Move the cursor in the indicated direction.
- *
- * Data Type: void
- *
- * Arguments:
- * n = direction to move the cursor
- * array = array of display items
- * narray = number of items in the array
- *
- * Returns:
- *
- * Side Effects:
- *
- * Calls:
- *
- * PDL:
- *
- >*/
-
- void
- mvcursor (n, array, narray)
- int n;
- char *array[];
- int narray;
- {
- putcursor (OFF, array);
-
- switch (n)
- {
- case UP:
- screeny--;
- arraypos--;
- break;
- case DOWN:
- if (arraypos + 1 < narray)
- {
- screeny++;
- arraypos++;
- }
- break;
- case LEFT:
- column--;
- screenx = (80 * column) / ncol;
- arraypos -= lastline;
- break;
- case RIGHT:
- if (arraypos + lastline < narray)
- {
- column++;
- screenx = (80 * column) / ncol;
- arraypos += lastline;
- }
- break;
- }
- putcursor (ON, array);
- }
-
-
- /*<
- * Function: putcursor (n, array)
- *
- * Description:
- * Print an item in normal or highlight mode.
- *
- * Data Type: void
- *
- * Arguments:
- * n = highlight mode (0 = off, 1 = on)
- * array = array of display items.
- *
- * Returns:
- *
- * Side Effects:
- *
- * Calls:
- *
- * PDL:
- *
- >*/
-
- void
- putcursor (n, array)
- int n;
- char *array[];
- {
- wmove (win2, screeny, screenx);
- if (n)
- {
- wstandout (win2);
- }
- else
- {
- wstandend (win2);
- }
-
- wprintw (win2, cmdstr, arraypos + 1, array[arraypos]);
- wrefresh (win2);
- }
-
-
- /*<
- * Function: scroll (n, array, narray)
- *
- * Description:
- * Scroll the page.
- *
- * Data Type: void
- *
- * Arguments:
- * n = direction of scroll
- * array = array of display items
- * narray = number of items in the array
- *
- * Returns:
- *
- * Side Effects:
- *
- * Calls:
- *
- * PDL:
- *
- >*/
-
- void
- scroll (n, array, narray)
- int n;
- char *array[];
- int narray;
- {
- switch (n)
- {
- case UP:
- linenum--;
- arraypos--;
- break;
- case DOWN:
- linenum++;
- arraypos++;
- break;
- }
- redraw (array, narray);
- }
-
-
- /*<
- * Function: wrap (n, array, narray)
- *
- * Description:
- * Wrap the cursor
- *
- * Data Type: void
- *
- * Arguments:
- * n = direction of wrap
- * array = display items
- * narray = number of items in the array
- *
- * Returns:
- *
- * Side Effects:
- *
- * Calls:
- *
- * PDL:
- *
- >*/
-
- void
- wrap (n, array, narray)
- int n;
- char *array[];
- int narray;
- {
- putcursor (OFF, array);
-
- switch (n)
- {
- case LEFT:
- if (arraypos + lastline * (ncol - 1) < narray)
- {
- column = ncol - 1;
- screenx = (80 * column) / ncol;
- arraypos += lastline * (ncol - 1);
- }
- break;
- case RIGHT:
- column = 0;
- screenx = 0;
- arraypos -= lastline * (ncol - 1);
- break;
- }
-
- putcursor (ON, array);
- }
-
-
- /*<
- * Function: do_number (array, narray)
- *
- * Description:
- * Get a number from the keyboard and match it to an item selection.
- *
- * Data Type: int
- *
- * Arguments:
- * array = array of display items
- * narray = numbr of elements in the array.
- *
- * Returns:
- * 0 - if item is confirmed
- * 1 - if item is not confirmed
- * 1 - if item is not found.
- *
- * Side Effects:
- *
- * Calls:
- *
- * PDL
- *
- >*/
-
- int
- do_number (array, narray)
- char *array[];
- int narray;
- {
- char number[16];
- int n;
-
- echo ();
- nl();
-
- werase (win3); /* clear the window */
- wmove (win3, 0, 0); /* position the cursor */
- waddstr (win3, "ENTER ITEM NUMBER: "); /* write the prompt */
- wmove (win3, 0, 19); /* position the cursor */
- wrefresh (win3); /* redraw the window */
- wgetstr (win3, number); /* get a string */
- wrefresh (win3); werase (win3); wrefresh (win3);
-
- noecho();
- nonl();
-
- wmove (win3, 0, center); /* move the cursor */
-
- n = atoi (number);
- if (n > 0 && n <= narray)
- {
- wprintw (win3, cmdstr , n, array [n-1]);
- rtnstr = array [n-1];
- return (confirm ());
- }
- else
- {
- wprintw (win3, "%3d is not a good item number", n);
- errormsg();
- return (1);
- }
- }
-
-
- /*<
- * Function: do_string (array, narray)
- *
- * Description:
- * Get a name from the keyboard and match it to an item selection.
- *
- * Data Type: int
- *
- * Arguments:
- * array = array of display items
- * narray = numbr of elements in the array.
- *
- * Returns:
- * 0 - if item is confirmed
- * 1 - if item is not confirmed
- * 1 - if item is not found.
- *
- * Side Effects:
- *
- * Calls:
- *
- * PDL
- *
- >*/
-
- int
- do_string (array, narray)
- char *array[];
- int narray;
- {
- int i;
- int found = 0;
- char name[128];
-
- echo ();
- nl();
-
- werase (win3); /* clear the window */
- wmove (win3, 0, 0); /* position the cursor */
- waddstr (win3, "ENTER ITEM NAME:"); /* write the prompt */
- wmove (win3, 0, 18); /* position the cursor */
- wrefresh (win3); /* redraw the window */
- wgetstr (win3, name); /* get a string */
- wrefresh (win3); werase (win3); wrefresh (win3);
-
- noecho();
- nonl();
-
- wmove (win3, 0, center); /* move the cursor */
-
- for (i = 0; i < narray; i++)
- {
- if (strcmp (name, array[i]) == 0)
- {
- found = 1;
- break;
- }
- }
-
- if (found)
- {
- wprintw (win3, cmdstr , i + 1, array [i]);
- rtnstr = array [i];
- return (confirm ());
- }
- else
- {
- wprintw (win3, "%s is not a good item name", name);
- errormsg();
- return (1);
- }
- }
-
-
- /*<
- * Function: homecursor (array)
- *
- * Description:
- * Print the current slection in win3
- *
- * Data Type: void
- *
- * Arguments:
- * array - the array containing the select items
- *
- * Returns:
- *
- * Side Effects:
- *
- * Calls:
- *
- * PDL:
- *
- >*/
-
- void
- homecursor (array)
- char *array[];
- {
- wmove (win3, 0, center);
- wprintw (win3, cmdstr, arraypos + 1, array[arraypos]);
- wrefresh (win3);
- }
-
-
- /*<
- * Function: newpage ()
- *
- * Description:
- * Set up fresh page on <ESC> T, B, N and P.
- *
- * Data Type: void
- *
- * Arguments: globals
- *
- * Returns: globals
- *
- * Side Effects:
- *
- * Calls:
- *
- * PDL:
- *
- >*/
-
- void
- newpage ()
- {
- if (isonpage ())
- { /* item still on page */
- screeny = arraypos - linenum - column * lastline;
- }
- else
- { /* item scrolled off page */
- arraypos = linenum; /* "home" the item number */
- column = 0; /* and everthing else */
- screenx = 0;
- screeny = 0;
- }
- }
-
-
- /*<
- * Function: isonpage ()
- *
- * Description:
- * Determine if an item is still on the page after paging.
- *
- * Data Type: int
- *
- * Arguments: globals
- *
- * Returns: globals
- *
- * Side Effects:
- *
- * Calls:
- *
- * PDL
- *
- >*/
-
- int
- isonpage ()
- {
- int i;
-
- for (i = 0; i < ncol; i++)
- {
- if (arraypos >= linenum + i * lastline &&
- arraypos <= linenum + WINLEN - 1 + i * lastline)
- {
- return (1);
- }
- }
- return (0);
- }
-
-
- /*<
- * Function: confirm ()
- *
- * Description:
- * Confirm a user's selection.
- *
- * Data Type: int
- *
- * Arguments:
- *
- * Returns:
- * 0 - if the item is confirmed
- * 1 - if the item is not confirmed
- *
- * Side Effects:
- *
- * Calls:
- *
- * PDL
- *
- >*/
-
- int
- confirm ()
- {
- int c;
-
- wmove (win3, 1, 20);
- waddstr (win3, "Do you wish to select this item? (y/n) ");
- wrefresh (win3);
-
- c = wgetch (win3);
-
- if (c == 'y' || c == 'Y')
- {
- return (0);
- }
- else
- {
- werase (win3);
- wrefresh (win3);
- rtnstr = NULL;
- return (1);
- }
- }
-
-
- /*<
- * Function: errormsg()
- *
- * Description:
- * Pause the processing to let the user read an error message. Wait
- * for a keystroke.
- *
- * Data Type: void
- *
- * Arguments:
- *
- * Returns:
- *
- * Side Effects:
- *
- * Calls:
- *
- * PDL
- *
- >*/
-
- void
- errormsg()
- {
- wmove (win3, 1, 28);
- waddstr (win3, "Press any key to continue");
- wrefresh (win3);
- wgetch (win3);
- werase (win3); wrefresh (win3);
- }
-