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