menu_sys.def revision 1.1 1 1.1 phil /* $NetBSD: menu_sys.def,v 1.1 1997/09/26 17:54:09 phil 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 phil initscr();
281 1.1 phil cbreak();
282 1.1 phil noecho();
283 1.1 phil __menu_init = 1;
284 1.1 phil }
285 1.1 phil if (__m_endwin) {
286 1.1 phil wclear(stdscr);
287 1.1 phil wrefresh(stdscr);
288 1.1 phil __m_endwin = 0;
289 1.1 phil }
290 1.1 phil if (m->mw == NULL)
291 1.1 phil init_menu (m);
292 1.1 phil
293 1.1 phil /* Always preselect 0! */
294 1.1 phil m->cursel = 0;
295 1.1 phil
296 1.1 phil while (!done) {
297 1.1 phil last_num = num;
298 1.1 phil if (__m_endwin) {
299 1.1 phil wclear(stdscr);
300 1.1 phil wrefresh(stdscr);
301 1.1 phil __m_endwin = 0;
302 1.1 phil }
303 1.1 phil /* Process the display action */
304 1.1 phil process_item (&num, -2);
305 1.1 phil post_menu (m);
306 1.1 phil wrefresh (m->mw);
307 1.1 phil
308 1.1 phil while ((req = menucmd (m->mw)) != REQ_EXECUTE)
309 1.1 phil process_req (m, req);
310 1.1 phil
311 1.1 phil sel = m->cursel;
312 1.1 phil wclear (m->mw);
313 1.1 phil wrefresh (m->mw);
314 1.1 phil
315 1.1 phil /* Process the items */
316 1.1 phil if (sel < m->numopts)
317 1.1 phil done = process_item (&num, sel);
318 1.1 phil else
319 1.1 phil done = TRUE;
320 1.1 phil
321 1.1 phil /* Reselect m just in case */
322 1.1 phil if (num != last_num) {
323 1.1 phil m = &menus[num];
324 1.1 phil /* Initialize? */
325 1.1 phil if (m->mw == NULL)
326 1.1 phil init_menu (m);
327 1.1 phil process_item (&num, -2);
328 1.1 phil }
329 1.1 phil }
330 1.1 phil
331 1.1 phil /* Process the exit action */
332 1.1 phil process_item (&num, -1);
333 1.1 phil }
334