menu_sys.def revision 1.3 1 1.3 phil /* $NetBSD: menu_sys.def,v 1.3 1997/11/14 16:31:45 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.3 phil #define REQ_EXECUTE 1000
45 1.3 phil #define REQ_NEXT_ITEM 1001
46 1.3 phil #define REQ_PREV_ITEM 1002
47 1.3 phil #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 phil static void process_req (struct menudesc *m, 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.3 phil case '\014':
130 1.3 phil 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 phil static void process_req (struct menudesc *m, 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.3 phil int num;
229 1.1 phil
230 1.1 phil if (req == REQ_EXECUTE)
231 1.1 phil return;
232 1.1 phil else if (req == REQ_NEXT_ITEM) {
233 1.1 phil if (m->cursel < m->numopts + hasexit - 1)
234 1.1 phil m->cursel++;
235 1.1 phil else
236 1.1 phil mbeep();
237 1.1 phil } else if (req == REQ_PREV_ITEM) {
238 1.1 phil if (m->cursel > 0)
239 1.1 phil m->cursel--;
240 1.1 phil else
241 1.1 phil mbeep();
242 1.3 phil
243 1.3 phil } else if (req == REQ_REDISPLAY) {
244 1.3 phil wclear(stdscr);
245 1.3 phil wrefresh(stdscr);
246 1.3 phil process_item (&num, -2);
247 1.3 phil post_menu (m);
248 1.3 phil wrefresh (m->mw);
249 1.3 phil
250 1.1 phil } else {
251 1.1 phil ch = tolower (req);
252 1.1 phil if (ch == 'x' && hasexit)
253 1.1 phil m->cursel = m->numopts;
254 1.1 phil else {
255 1.1 phil ch = ch - 'a';
256 1.1 phil if (ch < 0 || ch >= m->numopts)
257 1.1 phil mbeep();
258 1.1 phil else
259 1.1 phil m->cursel = ch;
260 1.1 phil }
261 1.1 phil }
262 1.1 phil if (m->cursel != lastsel) {
263 1.1 phil mvwaddstr (m->mw, lastsel+tadd+hasbox, hasbox, " ");
264 1.1 phil if (lastsel < m->numopts)
265 1.1 phil waddstr (m->mw, m->opts[lastsel]);
266 1.1 phil else
267 1.1 phil waddstr (m->mw, "x: Exit");
268 1.1 phil mvwaddstr (m->mw, m->cursel+tadd+hasbox, hasbox, ">");
269 1.1 phil wstandout(m->mw);
270 1.1 phil if (m->cursel < m->numopts)
271 1.1 phil waddstr (m->mw, m->opts[m->cursel]);
272 1.1 phil else
273 1.1 phil waddstr (m->mw, "x: Exit");
274 1.1 phil wstandend(m->mw);
275 1.1 phil wmove(m->mw,tadd+hasbox+m->cursel, hasbox);
276 1.1 phil wrefresh(m->mw);
277 1.1 phil }
278 1.1 phil }
279 1.1 phil
280 1.1 phil void process_menu (int num)
281 1.1 phil {
282 1.1 phil int sel = 0;
283 1.1 phil int req, done;
284 1.1 phil int last_num;
285 1.1 phil
286 1.1 phil struct menudesc *m = &menus[num];
287 1.1 phil
288 1.1 phil done = FALSE;
289 1.1 phil
290 1.1 phil /* Initialize? */
291 1.1 phil if (!__menu_init) {
292 1.2 phil if (initscr() == NULL) {
293 1.2 phil __menu_initerror();
294 1.2 phil return;
295 1.2 phil }
296 1.1 phil cbreak();
297 1.1 phil noecho();
298 1.1 phil __menu_init = 1;
299 1.1 phil }
300 1.1 phil if (__m_endwin) {
301 1.1 phil wclear(stdscr);
302 1.1 phil wrefresh(stdscr);
303 1.1 phil __m_endwin = 0;
304 1.1 phil }
305 1.1 phil if (m->mw == NULL)
306 1.1 phil init_menu (m);
307 1.1 phil
308 1.1 phil /* Always preselect 0! */
309 1.1 phil m->cursel = 0;
310 1.1 phil
311 1.1 phil while (!done) {
312 1.1 phil last_num = num;
313 1.1 phil if (__m_endwin) {
314 1.1 phil wclear(stdscr);
315 1.1 phil wrefresh(stdscr);
316 1.1 phil __m_endwin = 0;
317 1.1 phil }
318 1.1 phil /* Process the display action */
319 1.1 phil process_item (&num, -2);
320 1.1 phil post_menu (m);
321 1.1 phil wrefresh (m->mw);
322 1.1 phil
323 1.1 phil while ((req = menucmd (m->mw)) != REQ_EXECUTE)
324 1.1 phil process_req (m, req);
325 1.1 phil
326 1.1 phil sel = m->cursel;
327 1.1 phil wclear (m->mw);
328 1.1 phil wrefresh (m->mw);
329 1.1 phil
330 1.1 phil /* Process the items */
331 1.1 phil if (sel < m->numopts)
332 1.1 phil done = process_item (&num, sel);
333 1.1 phil else
334 1.1 phil done = TRUE;
335 1.1 phil
336 1.1 phil /* Reselect m just in case */
337 1.1 phil if (num != last_num) {
338 1.1 phil m = &menus[num];
339 1.1 phil /* Initialize? */
340 1.1 phil if (m->mw == NULL)
341 1.1 phil init_menu (m);
342 1.1 phil process_item (&num, -2);
343 1.1 phil }
344 1.1 phil }
345 1.1 phil
346 1.1 phil /* Process the exit action */
347 1.1 phil process_item (&num, -1);
348 1.1 phil }
349