Home | History | Annotate | Line # | Download | only in menuc
menu_sys.def revision 1.1.1.1.2.1
      1  1.1.1.1.2.1  mellon /*	$NetBSD: menu_sys.def,v 1.1.1.1.2.1 1997/11/09 21:14:02 mellon Exp $	*/
      2          1.1    phil 
      3          1.1    phil /*
      4          1.1    phil  * Copyright 1997 Piermont Information Systems Inc.
      5          1.1    phil  * All rights reserved.
      6          1.1    phil  *
      7          1.1    phil  * Written by Philip A. Nelson for Piermont Information Systems Inc.
      8          1.1    phil  *
      9          1.1    phil  * Redistribution and use in source and binary forms, with or without
     10          1.1    phil  * modification, are permitted provided that the following conditions
     11          1.1    phil  * are met:
     12          1.1    phil  * 1. Redistributions of source code must retain the above copyright
     13          1.1    phil  *    notice, this list of conditions and the following disclaimer.
     14          1.1    phil  * 2. Redistributions in binary form must reproduce the above copyright
     15          1.1    phil  *    notice, this list of conditions and the following disclaimer in the
     16          1.1    phil  *    documentation and/or other materials provided with the distribution.
     17          1.1    phil  * 3. All advertising materials mentioning features or use of this software
     18          1.1    phil  *    must display the following acknowledgement:
     19          1.1    phil  *      This product includes software develooped for the NetBSD Project by
     20          1.1    phil  *      Piermont Information Systems Inc.
     21          1.1    phil  * 4. The name of Piermont Information Systems Inc. may not be used to endorse
     22          1.1    phil  *    or promote products derived from this software without specific prior
     23          1.1    phil  *    written permission.
     24          1.1    phil  *
     25          1.1    phil  * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
     26          1.1    phil  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     27          1.1    phil  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     28          1.1    phil  * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
     29          1.1    phil  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30          1.1    phil  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31          1.1    phil  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32          1.1    phil  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33          1.1    phil  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34          1.1    phil  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     35          1.1    phil  * THE POSSIBILITY OF SUCH DAMAGE.
     36          1.1    phil  *
     37          1.1    phil  */
     38          1.1    phil 
     39          1.1    phil /* menu_sys.defs -- Menu system standard routines. */
     40          1.1    phil 
     41          1.1    phil #include <string.h>
     42          1.1    phil #include <ctype.h>
     43          1.1    phil 
     44          1.1    phil #define REQ_EXECUTE   1000
     45          1.1    phil #define REQ_NEXT_ITEM 1001
     46          1.1    phil #define REQ_PREV_ITEM 1002
     47          1.1    phil 
     48          1.1    phil #define KEYPAD_DOWN_ARROW 256
     49          1.1    phil #define KEYPAD_UP_ARROW   257
     50          1.1    phil 
     51          1.1    phil #define MAX(x,y) ((x)>(y)?(x):(y))
     52          1.1    phil 
     53          1.1    phil /* Initialization state. */
     54          1.1    phil static int __menu_init = 0;
     55          1.1    phil int __m_endwin = 0;
     56          1.1    phil 
     57          1.1    phil /* prototypes for in here! */
     58          1.1    phil 
     59          1.1    phil static void init_menu (struct menudesc *m);
     60          1.1    phil static void post_menu (struct menudesc *m);
     61          1.1    phil static void process_req (struct menudesc *m, int req);
     62          1.1    phil static void mbeep (void);
     63          1.1    phil static int menucmd (WINDOW *w);
     64          1.1    phil 
     65          1.1    phil #ifndef NULL
     66          1.1    phil #define NULL (void *)0
     67          1.1    phil #endif
     68          1.1    phil 
     69          1.1    phil /* menu system processing routines */
     70          1.1    phil 
     71          1.1    phil static void mbeep (void)
     72          1.1    phil {
     73          1.1    phil 	fprintf (stderr,"\a");
     74          1.1    phil }
     75          1.1    phil 
     76          1.1    phil static int mgetch(WINDOW *w)
     77          1.1    phil {
     78          1.1    phil 	static char buf[20];
     79          1.1    phil 	static int  num = 0;
     80          1.1    phil 
     81          1.1    phil 	int i, ret;
     82          1.1    phil 
     83          1.1    phil 	for (i=0; i< strlen(KD); i++) {
     84          1.1    phil 		if (i >= num)
     85          1.1    phil 			buf[num++] = wgetch(w);
     86          1.1    phil 		if (buf[i] != KD[i])
     87          1.1    phil 			break;
     88          1.1    phil 	}
     89          1.1    phil 	if (i == strlen(KD)) {
     90          1.1    phil 		num = 0;
     91          1.1    phil 		return KEYPAD_DOWN_ARROW;
     92          1.1    phil 	}
     93          1.1    phil 
     94          1.1    phil 	for (i=0; i< strlen(KU); i++) {
     95          1.1    phil 		if (i >= num)
     96          1.1    phil 			buf[num++] = wgetch(w);
     97          1.1    phil 		if (buf[i] != KU[i])
     98          1.1    phil 			break;
     99          1.1    phil 	}
    100          1.1    phil 	if (i == strlen(KU)) {
    101          1.1    phil 		num = 0;
    102          1.1    phil 		return KEYPAD_UP_ARROW;
    103          1.1    phil 	}
    104          1.1    phil 
    105          1.1    phil 	ret = buf[0];
    106          1.1    phil 	for (i = 0; i < strlen(buf); i++)
    107          1.1    phil 		buf[i] = buf[i+1];
    108          1.1    phil 	num--;
    109          1.1    phil 	return ret;
    110          1.1    phil }
    111          1.1    phil 
    112          1.1    phil static int menucmd (WINDOW *w)
    113          1.1    phil {
    114          1.1    phil 	int ch;
    115          1.1    phil 
    116          1.1    phil 	while (TRUE) {
    117          1.1    phil 		ch = mgetch(w);
    118          1.1    phil 
    119          1.1    phil 		switch (ch) {
    120          1.1    phil 		case '\n':
    121          1.1    phil 			return REQ_EXECUTE;
    122          1.1    phil 		case '\016':
    123          1.1    phil 		case KEYPAD_DOWN_ARROW:
    124          1.1    phil 			return REQ_NEXT_ITEM;
    125          1.1    phil 		case '\020':
    126          1.1    phil 		case KEYPAD_UP_ARROW:
    127          1.1    phil 			return REQ_PREV_ITEM;
    128          1.1    phil 		}
    129          1.1    phil 
    130          1.1    phil 		if (isalpha(ch))
    131          1.1    phil 			return (ch);
    132          1.1    phil 
    133          1.1    phil 		mbeep();
    134          1.1    phil 		wrefresh(w);
    135          1.1    phil 	}
    136          1.1    phil }
    137          1.1    phil 
    138          1.1    phil static void init_menu (struct menudesc *m)
    139          1.1    phil {
    140          1.1    phil 	int max;
    141          1.1    phil 	char **p;
    142          1.1    phil 	int add=4;
    143          1.1    phil 
    144          1.1    phil 	if (m->mopt & NOBOX)
    145          1.1    phil 		add = 2;
    146          1.1    phil 
    147          1.1    phil 	max = strlen(m->title);
    148          1.1    phil 
    149          1.1    phil 	/* Calculate h? */
    150          1.1    phil 	if (m->h == 0) {
    151          1.1    phil 		m->h = m->numopts + ((m->mopt & NOEXITOPT) ? 0 : 1)
    152          1.1    phil 			- (max ? 0 : 2);
    153          1.1    phil 	}
    154          1.1    phil 
    155          1.1    phil 
    156          1.1    phil 	/* Calculate w? */
    157          1.1    phil 	if (m->w == 0) {
    158          1.1    phil 		p = m->opts;
    159          1.1    phil 		while (*p) {
    160          1.1    phil 			max = MAX(max,strlen(*p));
    161          1.1    phil 			p++;
    162          1.1    phil 		}
    163          1.1    phil 		m->w = max;
    164          1.1    phil 	}
    165          1.1    phil 
    166          1.1    phil 	/* Get the windows. */
    167          1.1    phil 	m->mw = newwin(m->h+add, m->w+add, m->y, m->x);
    168          1.1    phil 
    169          1.1    phil 	if (m->mw == NULL) {
    170          1.1    phil 		endwin();
    171          1.1    phil 		(void) fprintf (stderr,
    172          1.1    phil 			"Could not create window for window with title "
    173          1.1    phil 			" \"%s\"\n", m->title);
    174          1.1    phil 		exit(1);
    175          1.1    phil 	}
    176          1.1    phil }
    177          1.1    phil 
    178          1.1    phil static void post_menu (struct menudesc *m)
    179          1.1    phil {
    180          1.1    phil 	int i;
    181          1.1    phil 	int hasbox, cury;
    182          1.1    phil 	int tadd;
    183          1.1    phil 
    184          1.1    phil 	if (m->mopt & NOBOX) {
    185          1.1    phil 		cury = 0;
    186          1.1    phil 		hasbox = 0;
    187          1.1    phil 	} else {
    188          1.1    phil 		cury = 1;
    189          1.1    phil 		hasbox = 1;
    190          1.1    phil 	}
    191          1.1    phil 
    192          1.1    phil 	tadd = strlen(m->title) ? 2 : 0;
    193          1.1    phil 
    194          1.1    phil 	if (tadd) {
    195          1.1    phil 		mvwaddstr(m->mw, cury, cury, m->title);
    196          1.1    phil 		cury += 2;
    197          1.1    phil 	}
    198          1.1    phil 
    199          1.1    phil 	for (i=0; i<m->numopts; i++, cury++) {
    200          1.1    phil 		if (m->cursel == i) {
    201          1.1    phil 			mvwaddstr (m->mw, cury, hasbox, ">");
    202          1.1    phil 			wstandout(m->mw);
    203          1.1    phil 		} else
    204          1.1    phil 			mvwaddstr (m->mw, cury, hasbox, " ");
    205          1.1    phil 		waddstr (m->mw, m->opts[i]);
    206          1.1    phil 		if (m->cursel == i)
    207          1.1    phil 			wstandend(m->mw);
    208          1.1    phil 	}
    209          1.1    phil 	if (!(m->mopt & NOEXITOPT))
    210          1.1    phil 		mvwaddstr (m->mw, cury, hasbox, " x: Exit");
    211          1.1    phil 
    212          1.1    phil 	if (!(m->mopt & NOBOX))
    213          1.1    phil 		box(m->mw, '*', '*');
    214          1.1    phil 
    215          1.1    phil 	wmove(m->mw,tadd+hasbox+m->cursel, hasbox);
    216          1.1    phil }
    217          1.1    phil 
    218          1.1    phil static void process_req (struct menudesc *m, int req)
    219          1.1    phil {
    220          1.1    phil 	int ch;
    221          1.1    phil 	int lastsel = m->cursel;
    222          1.1    phil 	int hasexit = (m->mopt & NOEXITOPT ? 0 : 1 );
    223          1.1    phil 	int hasbox = (m->mopt & NOBOX ? 0 : 1);
    224          1.1    phil 	int tadd = strlen(m->title) ? 2 : 0;
    225          1.1    phil 
    226          1.1    phil 	if (req == REQ_EXECUTE)
    227          1.1    phil 		return;
    228          1.1    phil 	else if (req == REQ_NEXT_ITEM) {
    229          1.1    phil 		if (m->cursel < m->numopts + hasexit - 1)
    230          1.1    phil 			m->cursel++;
    231          1.1    phil 		else
    232          1.1    phil 			mbeep();
    233          1.1    phil 	} else if (req == REQ_PREV_ITEM) {
    234          1.1    phil 		if (m->cursel > 0)
    235          1.1    phil 			m->cursel--;
    236          1.1    phil 		else
    237          1.1    phil 			mbeep();
    238          1.1    phil 	} else {
    239          1.1    phil 		ch = tolower (req);
    240          1.1    phil 		if (ch == 'x' && hasexit)
    241          1.1    phil 			m->cursel = m->numopts;
    242          1.1    phil 		else {
    243          1.1    phil 			ch = ch - 'a';
    244          1.1    phil 			if (ch < 0 || ch >= m->numopts)
    245          1.1    phil 				mbeep();
    246          1.1    phil 			else
    247          1.1    phil 				m->cursel = ch;
    248          1.1    phil 		}
    249          1.1    phil 	}
    250          1.1    phil 	if (m->cursel != lastsel) {
    251          1.1    phil 		mvwaddstr (m->mw, lastsel+tadd+hasbox, hasbox, " ");
    252          1.1    phil 		if (lastsel < m->numopts)
    253          1.1    phil 			waddstr (m->mw, m->opts[lastsel]);
    254          1.1    phil 		else
    255          1.1    phil 			waddstr (m->mw, "x: Exit");
    256          1.1    phil 		mvwaddstr (m->mw, m->cursel+tadd+hasbox, hasbox, ">");
    257          1.1    phil 		wstandout(m->mw);
    258          1.1    phil 		if (m->cursel < m->numopts)
    259          1.1    phil 			waddstr (m->mw, m->opts[m->cursel]);
    260          1.1    phil 		else
    261          1.1    phil 			waddstr (m->mw, "x: Exit");
    262          1.1    phil 		wstandend(m->mw);
    263          1.1    phil 		wmove(m->mw,tadd+hasbox+m->cursel, hasbox);
    264          1.1    phil 		wrefresh(m->mw);
    265          1.1    phil 	}
    266          1.1    phil }
    267          1.1    phil 
    268          1.1    phil void process_menu (int num)
    269          1.1    phil {
    270          1.1    phil 	int sel = 0;
    271          1.1    phil 	int req, done;
    272          1.1    phil 	int last_num;
    273          1.1    phil 
    274          1.1    phil 	struct menudesc *m = &menus[num];
    275          1.1    phil 
    276          1.1    phil 	done = FALSE;
    277          1.1    phil 
    278          1.1    phil 	/* Initialize? */
    279          1.1    phil 	if (!__menu_init) {
    280  1.1.1.1.2.1  mellon 		if (initscr() == NULL) {
    281  1.1.1.1.2.1  mellon 			__menu_initerror();
    282  1.1.1.1.2.1  mellon 			return;
    283  1.1.1.1.2.1  mellon 		}
    284          1.1    phil 		cbreak();
    285          1.1    phil 		noecho();
    286          1.1    phil 		__menu_init = 1;
    287          1.1    phil 	}
    288          1.1    phil 	if (__m_endwin) {
    289          1.1    phil      	        wclear(stdscr);
    290          1.1    phil 		wrefresh(stdscr);
    291          1.1    phil 		__m_endwin = 0;
    292          1.1    phil 	}
    293          1.1    phil 	if (m->mw == NULL)
    294          1.1    phil 		init_menu (m);
    295          1.1    phil 
    296          1.1    phil 	/* Always preselect 0! */
    297          1.1    phil 	m->cursel = 0;
    298          1.1    phil 
    299          1.1    phil 	while (!done) {
    300          1.1    phil 		last_num = num;
    301          1.1    phil 		if (__m_endwin) {
    302          1.1    phil 			wclear(stdscr);
    303          1.1    phil 			wrefresh(stdscr);
    304          1.1    phil 			__m_endwin = 0;
    305          1.1    phil 		}
    306          1.1    phil 		/* Process the display action */
    307          1.1    phil 		process_item (&num, -2);
    308          1.1    phil 		post_menu (m);
    309          1.1    phil 		wrefresh (m->mw);
    310          1.1    phil 
    311          1.1    phil 		while ((req = menucmd (m->mw)) != REQ_EXECUTE)
    312          1.1    phil 			process_req (m, req);
    313          1.1    phil 
    314          1.1    phil 		sel = m->cursel;
    315          1.1    phil 		wclear (m->mw);
    316          1.1    phil 		wrefresh (m->mw);
    317          1.1    phil 
    318          1.1    phil 		/* Process the items */
    319          1.1    phil 		if (sel < m->numopts)
    320          1.1    phil 			done = process_item (&num, sel);
    321          1.1    phil 		else
    322          1.1    phil 			done = TRUE;
    323          1.1    phil 
    324          1.1    phil 		/* Reselect m just in case */
    325          1.1    phil 		if (num != last_num) {
    326          1.1    phil 			m = &menus[num];
    327          1.1    phil 			/* Initialize? */
    328          1.1    phil 			if (m->mw == NULL)
    329          1.1    phil 				init_menu (m);
    330          1.1    phil 			process_item (&num, -2);
    331          1.1    phil 		}
    332          1.1    phil 	}
    333          1.1    phil 
    334          1.1    phil 	/* Process the exit action */
    335          1.1    phil 	process_item (&num, -1);
    336          1.1    phil }
    337