Home | History | Annotate | Line # | Download | only in menuc
menu_sys.def revision 1.1.1.1.2.2
      1  1.1.1.1.2.2  mellon /*	$NetBSD: menu_sys.def,v 1.1.1.1.2.2 1997/11/18 01:46:33 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.1.1.2.2  mellon #define REQ_EXECUTE    1000
     45  1.1.1.1.2.2  mellon #define REQ_NEXT_ITEM  1001
     46  1.1.1.1.2.2  mellon #define REQ_PREV_ITEM  1002
     47  1.1.1.1.2.2  mellon #define REQ_REDISPLAY  1003
     48          1.1    phil 
     49          1.1    phil #define KEYPAD_DOWN_ARROW 256
     50          1.1    phil #define KEYPAD_UP_ARROW   257
     51          1.1    phil 
     52          1.1    phil #define MAX(x,y) ((x)>(y)?(x):(y))
     53          1.1    phil 
     54          1.1    phil /* Initialization state. */
     55          1.1    phil static int __menu_init = 0;
     56          1.1    phil int __m_endwin = 0;
     57          1.1    phil 
     58          1.1    phil /* prototypes for in here! */
     59          1.1    phil 
     60          1.1    phil static void init_menu (struct menudesc *m);
     61          1.1    phil static void post_menu (struct menudesc *m);
     62  1.1.1.1.2.2  mellon static void process_req (struct menudesc *m, int num, int req);
     63          1.1    phil static void mbeep (void);
     64          1.1    phil static int menucmd (WINDOW *w);
     65          1.1    phil 
     66          1.1    phil #ifndef NULL
     67          1.1    phil #define NULL (void *)0
     68          1.1    phil #endif
     69          1.1    phil 
     70          1.1    phil /* menu system processing routines */
     71          1.1    phil 
     72          1.1    phil static void mbeep (void)
     73          1.1    phil {
     74          1.1    phil 	fprintf (stderr,"\a");
     75          1.1    phil }
     76          1.1    phil 
     77          1.1    phil static int mgetch(WINDOW *w)
     78          1.1    phil {
     79          1.1    phil 	static char buf[20];
     80          1.1    phil 	static int  num = 0;
     81          1.1    phil 
     82          1.1    phil 	int i, ret;
     83          1.1    phil 
     84          1.1    phil 	for (i=0; i< strlen(KD); i++) {
     85          1.1    phil 		if (i >= num)
     86          1.1    phil 			buf[num++] = wgetch(w);
     87          1.1    phil 		if (buf[i] != KD[i])
     88          1.1    phil 			break;
     89          1.1    phil 	}
     90          1.1    phil 	if (i == strlen(KD)) {
     91          1.1    phil 		num = 0;
     92          1.1    phil 		return KEYPAD_DOWN_ARROW;
     93          1.1    phil 	}
     94          1.1    phil 
     95          1.1    phil 	for (i=0; i< strlen(KU); i++) {
     96          1.1    phil 		if (i >= num)
     97          1.1    phil 			buf[num++] = wgetch(w);
     98          1.1    phil 		if (buf[i] != KU[i])
     99          1.1    phil 			break;
    100          1.1    phil 	}
    101          1.1    phil 	if (i == strlen(KU)) {
    102          1.1    phil 		num = 0;
    103          1.1    phil 		return KEYPAD_UP_ARROW;
    104          1.1    phil 	}
    105          1.1    phil 
    106          1.1    phil 	ret = buf[0];
    107          1.1    phil 	for (i = 0; i < strlen(buf); i++)
    108          1.1    phil 		buf[i] = buf[i+1];
    109          1.1    phil 	num--;
    110          1.1    phil 	return ret;
    111          1.1    phil }
    112          1.1    phil 
    113          1.1    phil static int menucmd (WINDOW *w)
    114          1.1    phil {
    115          1.1    phil 	int ch;
    116          1.1    phil 
    117          1.1    phil 	while (TRUE) {
    118          1.1    phil 		ch = mgetch(w);
    119          1.1    phil 
    120          1.1    phil 		switch (ch) {
    121          1.1    phil 		case '\n':
    122          1.1    phil 			return REQ_EXECUTE;
    123          1.1    phil 		case '\016':
    124          1.1    phil 		case KEYPAD_DOWN_ARROW:
    125          1.1    phil 			return REQ_NEXT_ITEM;
    126          1.1    phil 		case '\020':
    127          1.1    phil 		case KEYPAD_UP_ARROW:
    128          1.1    phil 			return REQ_PREV_ITEM;
    129  1.1.1.1.2.2  mellon 		case '\014':
    130  1.1.1.1.2.2  mellon 		        return REQ_REDISPLAY;
    131          1.1    phil 		}
    132          1.1    phil 
    133          1.1    phil 		if (isalpha(ch))
    134          1.1    phil 			return (ch);
    135          1.1    phil 
    136          1.1    phil 		mbeep();
    137          1.1    phil 		wrefresh(w);
    138          1.1    phil 	}
    139          1.1    phil }
    140          1.1    phil 
    141          1.1    phil static void init_menu (struct menudesc *m)
    142          1.1    phil {
    143          1.1    phil 	int max;
    144          1.1    phil 	char **p;
    145          1.1    phil 	int add=4;
    146          1.1    phil 
    147          1.1    phil 	if (m->mopt & NOBOX)
    148          1.1    phil 		add = 2;
    149          1.1    phil 
    150          1.1    phil 	max = strlen(m->title);
    151          1.1    phil 
    152          1.1    phil 	/* Calculate h? */
    153          1.1    phil 	if (m->h == 0) {
    154          1.1    phil 		m->h = m->numopts + ((m->mopt & NOEXITOPT) ? 0 : 1)
    155          1.1    phil 			- (max ? 0 : 2);
    156          1.1    phil 	}
    157          1.1    phil 
    158          1.1    phil 
    159          1.1    phil 	/* Calculate w? */
    160          1.1    phil 	if (m->w == 0) {
    161          1.1    phil 		p = m->opts;
    162          1.1    phil 		while (*p) {
    163          1.1    phil 			max = MAX(max,strlen(*p));
    164          1.1    phil 			p++;
    165          1.1    phil 		}
    166          1.1    phil 		m->w = max;
    167          1.1    phil 	}
    168          1.1    phil 
    169          1.1    phil 	/* Get the windows. */
    170          1.1    phil 	m->mw = newwin(m->h+add, m->w+add, m->y, m->x);
    171          1.1    phil 
    172          1.1    phil 	if (m->mw == NULL) {
    173          1.1    phil 		endwin();
    174          1.1    phil 		(void) fprintf (stderr,
    175          1.1    phil 			"Could not create window for window with title "
    176          1.1    phil 			" \"%s\"\n", m->title);
    177          1.1    phil 		exit(1);
    178          1.1    phil 	}
    179          1.1    phil }
    180          1.1    phil 
    181          1.1    phil static void post_menu (struct menudesc *m)
    182          1.1    phil {
    183          1.1    phil 	int i;
    184          1.1    phil 	int hasbox, cury;
    185          1.1    phil 	int tadd;
    186          1.1    phil 
    187          1.1    phil 	if (m->mopt & NOBOX) {
    188          1.1    phil 		cury = 0;
    189          1.1    phil 		hasbox = 0;
    190          1.1    phil 	} else {
    191          1.1    phil 		cury = 1;
    192          1.1    phil 		hasbox = 1;
    193          1.1    phil 	}
    194          1.1    phil 
    195          1.1    phil 	tadd = strlen(m->title) ? 2 : 0;
    196          1.1    phil 
    197          1.1    phil 	if (tadd) {
    198          1.1    phil 		mvwaddstr(m->mw, cury, cury, m->title);
    199          1.1    phil 		cury += 2;
    200          1.1    phil 	}
    201          1.1    phil 
    202          1.1    phil 	for (i=0; i<m->numopts; i++, cury++) {
    203          1.1    phil 		if (m->cursel == i) {
    204          1.1    phil 			mvwaddstr (m->mw, cury, hasbox, ">");
    205          1.1    phil 			wstandout(m->mw);
    206          1.1    phil 		} else
    207          1.1    phil 			mvwaddstr (m->mw, cury, hasbox, " ");
    208          1.1    phil 		waddstr (m->mw, m->opts[i]);
    209          1.1    phil 		if (m->cursel == i)
    210          1.1    phil 			wstandend(m->mw);
    211          1.1    phil 	}
    212          1.1    phil 	if (!(m->mopt & NOEXITOPT))
    213          1.1    phil 		mvwaddstr (m->mw, cury, hasbox, " x: Exit");
    214          1.1    phil 
    215          1.1    phil 	if (!(m->mopt & NOBOX))
    216          1.1    phil 		box(m->mw, '*', '*');
    217          1.1    phil 
    218          1.1    phil 	wmove(m->mw,tadd+hasbox+m->cursel, hasbox);
    219          1.1    phil }
    220          1.1    phil 
    221  1.1.1.1.2.2  mellon static void process_req (struct menudesc *m, int num, int req)
    222          1.1    phil {
    223          1.1    phil 	int ch;
    224          1.1    phil 	int lastsel = m->cursel;
    225          1.1    phil 	int hasexit = (m->mopt & NOEXITOPT ? 0 : 1 );
    226          1.1    phil 	int hasbox = (m->mopt & NOBOX ? 0 : 1);
    227          1.1    phil 	int tadd = strlen(m->title) ? 2 : 0;
    228          1.1    phil 
    229          1.1    phil 	if (req == REQ_EXECUTE)
    230          1.1    phil 		return;
    231          1.1    phil 	else if (req == REQ_NEXT_ITEM) {
    232          1.1    phil 		if (m->cursel < m->numopts + hasexit - 1)
    233          1.1    phil 			m->cursel++;
    234          1.1    phil 		else
    235          1.1    phil 			mbeep();
    236          1.1    phil 	} else if (req == REQ_PREV_ITEM) {
    237          1.1    phil 		if (m->cursel > 0)
    238          1.1    phil 			m->cursel--;
    239          1.1    phil 		else
    240          1.1    phil 			mbeep();
    241  1.1.1.1.2.2  mellon 
    242  1.1.1.1.2.2  mellon 	} else if (req == REQ_REDISPLAY) {
    243  1.1.1.1.2.2  mellon 		wclear(stdscr);
    244  1.1.1.1.2.2  mellon 		wrefresh(stdscr);
    245  1.1.1.1.2.2  mellon 		process_item (&num, -2);
    246  1.1.1.1.2.2  mellon 		post_menu (m);
    247  1.1.1.1.2.2  mellon 		wrefresh (m->mw);
    248  1.1.1.1.2.2  mellon 
    249          1.1    phil 	} else {
    250          1.1    phil 		ch = tolower (req);
    251          1.1    phil 		if (ch == 'x' && hasexit)
    252          1.1    phil 			m->cursel = m->numopts;
    253          1.1    phil 		else {
    254          1.1    phil 			ch = ch - 'a';
    255          1.1    phil 			if (ch < 0 || ch >= m->numopts)
    256          1.1    phil 				mbeep();
    257          1.1    phil 			else
    258          1.1    phil 				m->cursel = ch;
    259          1.1    phil 		}
    260          1.1    phil 	}
    261          1.1    phil 	if (m->cursel != lastsel) {
    262          1.1    phil 		mvwaddstr (m->mw, lastsel+tadd+hasbox, hasbox, " ");
    263          1.1    phil 		if (lastsel < m->numopts)
    264          1.1    phil 			waddstr (m->mw, m->opts[lastsel]);
    265          1.1    phil 		else
    266          1.1    phil 			waddstr (m->mw, "x: Exit");
    267          1.1    phil 		mvwaddstr (m->mw, m->cursel+tadd+hasbox, hasbox, ">");
    268          1.1    phil 		wstandout(m->mw);
    269          1.1    phil 		if (m->cursel < m->numopts)
    270          1.1    phil 			waddstr (m->mw, m->opts[m->cursel]);
    271          1.1    phil 		else
    272          1.1    phil 			waddstr (m->mw, "x: Exit");
    273          1.1    phil 		wstandend(m->mw);
    274          1.1    phil 		wmove(m->mw,tadd+hasbox+m->cursel, hasbox);
    275          1.1    phil 		wrefresh(m->mw);
    276          1.1    phil 	}
    277          1.1    phil }
    278          1.1    phil 
    279          1.1    phil void process_menu (int num)
    280          1.1    phil {
    281          1.1    phil 	int sel = 0;
    282          1.1    phil 	int req, done;
    283          1.1    phil 	int last_num;
    284          1.1    phil 
    285          1.1    phil 	struct menudesc *m = &menus[num];
    286          1.1    phil 
    287          1.1    phil 	done = FALSE;
    288          1.1    phil 
    289          1.1    phil 	/* Initialize? */
    290          1.1    phil 	if (!__menu_init) {
    291  1.1.1.1.2.1  mellon 		if (initscr() == NULL) {
    292  1.1.1.1.2.1  mellon 			__menu_initerror();
    293  1.1.1.1.2.1  mellon 			return;
    294  1.1.1.1.2.1  mellon 		}
    295          1.1    phil 		cbreak();
    296          1.1    phil 		noecho();
    297          1.1    phil 		__menu_init = 1;
    298          1.1    phil 	}
    299          1.1    phil 	if (__m_endwin) {
    300          1.1    phil      	        wclear(stdscr);
    301          1.1    phil 		wrefresh(stdscr);
    302          1.1    phil 		__m_endwin = 0;
    303          1.1    phil 	}
    304          1.1    phil 	if (m->mw == NULL)
    305          1.1    phil 		init_menu (m);
    306          1.1    phil 
    307          1.1    phil 	/* Always preselect 0! */
    308          1.1    phil 	m->cursel = 0;
    309          1.1    phil 
    310          1.1    phil 	while (!done) {
    311          1.1    phil 		last_num = num;
    312          1.1    phil 		if (__m_endwin) {
    313          1.1    phil 			wclear(stdscr);
    314          1.1    phil 			wrefresh(stdscr);
    315          1.1    phil 			__m_endwin = 0;
    316          1.1    phil 		}
    317          1.1    phil 		/* Process the display action */
    318          1.1    phil 		process_item (&num, -2);
    319          1.1    phil 		post_menu (m);
    320          1.1    phil 		wrefresh (m->mw);
    321          1.1    phil 
    322          1.1    phil 		while ((req = menucmd (m->mw)) != REQ_EXECUTE)
    323  1.1.1.1.2.2  mellon 			process_req (m, num, req);
    324          1.1    phil 
    325          1.1    phil 		sel = m->cursel;
    326          1.1    phil 		wclear (m->mw);
    327          1.1    phil 		wrefresh (m->mw);
    328          1.1    phil 
    329          1.1    phil 		/* Process the items */
    330          1.1    phil 		if (sel < m->numopts)
    331          1.1    phil 			done = process_item (&num, sel);
    332          1.1    phil 		else
    333          1.1    phil 			done = TRUE;
    334          1.1    phil 
    335          1.1    phil 		/* Reselect m just in case */
    336          1.1    phil 		if (num != last_num) {
    337          1.1    phil 			m = &menus[num];
    338          1.1    phil 			/* Initialize? */
    339          1.1    phil 			if (m->mw == NULL)
    340          1.1    phil 				init_menu (m);
    341          1.1    phil 			process_item (&num, -2);
    342          1.1    phil 		}
    343          1.1    phil 	}
    344          1.1    phil 
    345          1.1    phil 	/* Process the exit action */
    346          1.1    phil 	process_item (&num, -1);
    347          1.1    phil }
    348