Listing 1

  1: /************************************************************
  2:  * Program: RMENU Menu Interpreter
  3:  *  Module: rmenu2.c
  4:  * Top-level menu processing
  5:  * Written by: Leor Zolman, 7/91
  6:  ************************************************************/
  7:
  8: #include "cmenu.h"
  9: #include "rcmenu.h"
 10:
 11: #if__STDC
 12: #pragma hdrstop
 13: #endif
 14:
 15: #include <ctype.h>
 16:
 17:
 18: /************************************************************
 19:  * sub_menu():
 20:  * Run a local menu at the given nesting level
 21:  * Default command/menu path is supplied via "path".
 22:  ***********************************************************/
 23:
 24: int sub_menu(mnum,path)
 25: int mnun;
 26: char *path;
 27: {
 28:    MENU2 *M2p = LMenus[nestlev].Menus[mnum];
 29:    MENU *Mp = &M2p -> Menu;
 30:    char newpath[MAX_PATH];
 31:
 32:    int cur_item = 0;
 33:    int sel_val = 0;
 34:    int factor;
 35:
 36:    draw_menu(M2p,cur_item);               /*display the menu   */
 37:
 38:    strcpy(newpath, make_path(path,Mp -> path));
 39:
 40:    while(1)
 41:    {
 42:       switch(get_cmd(Mp -> nitems, cur_item, &sel_val))
 43:       {
 44:          case KEY_UP:
 45:             draw_item(M2p, cur_item, NORMAL, NO);
 46:             cur_item = cur_item ? cur_item - 1 :
 47:                   Mp -> nitems - 1;
 44:             draw_item(M2p, cur_item, STANDOUT, YES);
 49:             break;
 50:
 51:          case KEY_DOWN:
 52:             draw_item(M2p, cur_item, NORMAL, NO);
 53:             cur_item= (cur_item == Mp -> nitems - 1) ? 0
 54:                   cur_item + 1;
 55:             draw_item(M2p, cur_item, STANDOUT, YES);
 56:             break;
 57:
 58:          case KEY_RIGHT:
 59:             if (Mp -> columns == 1)
 60:                   break;
 61:
 62:               draw_item(M2p, cur_item, NORMAL, NO);
 63:
 64:               factor = MAX_IROWS / Mp -> spacing;
 65:               if (cur_item + factor < Mp -> nitems)
 66:                  cur_item += factor;
 67:               else
 68:                  cur_item %= factor;
 69:
 70:               draw_item(M2p, cur_item, STANDOUT, YES);
 71:               break;
 72:
 73:          case KEY_LEFT:
 74:             if (Mp -> columns == 1)
 75:                break;
 76:             draw_item(M2p, cur_item, NORMAL, NO);
 77:
 78:             factor = MAX_IROWS / Mp -> spacing;
 79:             if (cur_item >= factor)
 80:                cur_item -= factor;
 81:             else
 82:                while (cur_item + factor < Mp -> nitems)
 83:                   cur_item += factor;
 84:
 85:             draw_item(M2p, cur_item, STANDOUT, YES);
 86:             break;
 87:
 88:          case KEY_SHOW:
 89:             show_item(M2p, cur_item, newpath);
 90:             break;
 91:
 92:          case KEY_RUN:
 93:             if (M2p -> Items[cur_item] -> acttyp == ACT_EXIT)
 94:                return OK;
 95:             if (do_item(M2p, cur_item, newpath) == EXITALL)
 96:                return EXITALL;
 97:
 98:             switch(M2p -> Items[cur_item] -> nextcode)
 99:             {
100:                case NXT_FIRST:
101:                   cur_item = 0;
102:                   break;
103:
104:                case NXT_LAST:
105:                   cur_item = M2p -> Menu.nitems - 1;
106:                   break;
107:
108:                case NXT_NEXT:
109:                   if (cur_item < M2p -> Menu.nitems - 1)
110:                      cur_item++;
111:                   break;
112:
113:                case NXT_DIRECT:
114:                   cur_item = M2p -> Items[cur_item] -> nextitem;
115:                    break;
116:             }
117:
118:           draw_menu(M2p, cur_item);           /* redisplay menu */
119:             break;
120:
121:          case K_DIRECT:
122:             if ((sel_val - 1) != cur_item)
123:             {
124:                draw_item(M2p, cur_item, NORMAL, NO);
125:                cur_item = sel_val - 1;
126:                draw_item(M2p, cur_item, STANDOUT, YES);
127:             }
128:             break;
129:
130:          case K_SHELL:
131:             if (M2p -> Menu.escape == YES ||
132:              (M2p -> Menu.escape == DEFAULT && DEF_ESCAPE == YES))
133:             {
134: #if SHELL_PROMPT
135:                if (put_msg(0, SH_PROMPT_STR) == ESC)
136:                   break;
137: #else
138:                move(ERR_ROW, 0);
139:                hlight_on();
140:                addstr("Invoking shell. . .");
141:                hlight_end();
142: #endif
143:
144:             pre_shell();          /* set up for shell call   */
145:             system(SysShell);     /* run a shell             */
146:             post_shell();         /* restore everything      */
147:
148:                draw_menu(M2p, cur_item);
149:             }
150:             else
151:               put_msg(1, "Sorry, shell escapes are disabled.");
152:             break;
153:
154:          case K_EXIT:
155:             return OK;
156:
157:          case K_EXITALL:
158:             return EXITALL;
159:
160:          case K_VERSION:
161:             put_msg(0, " RMENU Menu Interpreter v%s",
162:                       VERSION);
163:             break;
164:
165:          case K_UNKNOWN:
166:             beep();
167:       }
168:       refresh();
169:    }
170: }
171:
172:
173: /************************************************************
174:  * draw_menu():
175:  * Display the entire menu, including all prompts,
176:  * and titles and help text (if any) for current item
177:  * on the screen.
178:  ************************************************************/
179:
180: Void draw_menu(M2p, curr)
181: MENU2 *M2p;
182: int curr;
183: {
184:    MENU *Mp = &M2p -> Menu;
185:    int title_len = strlen(Mp -> title);
186:    int i, j;
187:
188:    clear();
189:
190:    move(TITLE_ROW, (SCREEN_COLS - title_len)/2);
191:   addstr(Mp -> title);                  /* Put up menu title */
192:
193:    for (i = 0; i < Mp -> nitems; i++)
194:       if (i != curr)
195:          draw_item(M2p, i, NORMAL, NO);
196:
197:    draw item(M2p, curr, STANDOUT, YES);
198:
199:    move(PROMPT_ROW, 0);
200:    addstr(MENU_OPTS);
201:    if (Mp -> escape == YES ||
202:          (Mp -> escape == DEFAULT && DEF_ESCAPE == YES))
203:       addstr(MENU_ SHELL);
204:    addstr(MENU_PROMPT);
205:    getyx(stdscr, echoy, echox); /* save coords of item # echo area */
206:
207:    refresh();                             /* display the window */
208:
209: }
210:
211:
212: /************************************************************
213:  * draw_item():
214:  * Display a single item (the current item) of the
215:  * specified menu, using the specified video mode.
216:  * Display assiciated help text only if "dohelp"
217:  * is TRUE.
218:  ***********************************************************/
219:
220: Void draw_item(M2p, item, vid_mode, dohelp)
221: MENU2 *M2p;
222: int item, vid_mode, dohelp;
223: {
224:    ITEM *Ip = M2p -> Items[item];
225:    COORDS *Cp = &M2p -> coords[item];
226:    int j;
227:    int help_len;
228:
229:    move (Cp->ypos, Cp->xpos);
230:    printw("%2d.", item + 1);
231:
232:    if (vid_mode == STANDOUT)
233:       hlight_on();
234:
235:    printw("%s", Ip -> text);
236:
237:    for (j = 0; j < Cp -> spaces_needed; j++)
238:          addch(' ');
239:
240:    if (vid_mode == STANDOUT)
241:       hlight_end();
242:
243:
244:    if (dohelp == YES)
245:    {
246:       move(HELP_ROWO, HELP_COLO);
247:        if (*Ip -> help)
248:        {
249:         addstr(" HELP: ");            /* display "HELP:" text */
250:
251:         move (HELP_ROW, 0); /* Erase preivous help text (if any) */
252:          clrtoeol();
253:
254:          help_len = strlen(Ip -> help);
255:          if (help_len > (SCREEN_COLS - 6))
256:             move (HELP_ROW, (80 - strlen(Ip -> help))/2);
257:          else
258:             move (HELP_ROW, (80 - help_len)/2 - 2);
259:
260:          hlight_on();
261:          if (help_len <= (SCREEN_COLS - 6))
262:             addstr(" ");
263:          addstr(Ip -> help);
264:          if (help_len <= (SCREEN_COLS - 6))
265:             addstr(" ");
266:          hlight_end();
267:          clrtoeol();
268:       }
269:       else
270:       {
271:        addstr("     ");             /* clear help text area */
272:          move(HELP_ROW, 0);
273:       }
274:       clrtoeol();
275:    }
276: }
277:
278:
279: /************************************************************
280:  * get_cmd()
281:  * Get a command from the user.
282:  * Arrow keys or space returns the appropriate K_ code.
283:  * Pressing Enter returns the K_RUN code.
284:  * Pressing ! returns the K_SHELL code.
285:  * Entering a direct number returns K_DIRECT,
286:  * and the sel_val is set (indirectly) to selection number
287:  * (1-based).
288:  ************************************************************/
289:
290: int get_cmd(nitems, curr, sel_val)
291: int nitems;
292: int curr;
293: int *sel_val;
294: {
295:    int ch;
296:    int newval;
297:    int savy, savx;
298:
299:   static int digits = FALSE;     /* true if digits being entered */
300:
301:   move(echoy, echox);                /* move to prompt location */
302:    printw("%d", curr + 1);
303:    getyx(stdscr, savy, savx);
304:    clrtoeol();
305:    move(savy, savx);
306:    refresh();
307:
308:    while (1)
309:    {
310:       ch = getch();
311:       if (!isdigit(ch))
312:          digits = FALSE;
313:       switch (ch)
314:       {
315:          case KEY_UP:
316:         case '\b':         /* WYSE 60s send this for left arrow */
317:              clrtoeol();
318:              return KEY_UP;
319:
320:          case ' ':
321:          case KEY_DOWN:
322: #if UNIX || XENIX
323:         case '\n':         /* WYSE 60s send this for down arrow */
324: #endif
325:              clrtoeol();
326:              return KEY_DOWN;
327:
328:           case KEY_RIGHT:
329:           case KEY_LEFT:
330:           case KEY_RUN:
331:           case KEY_SHOW:
332:              return ch;
333:
334:           case 'e':
335:           case 'E':
336:              return K_EXIT;
337:
338:           case 'x':
339:           case 'X':
340:              return K_EXITALL;
341:
342:           case 'v':
343:           case 'V':
344:              return K_VERSION;
345:
346:           case '!':
347:              return K_SHELL;
348:
349:         case ESC:                        /* clear digits area */
350:              digits = FALSE;
351:              move(echoy, echox);
352:              clrtoeol ();
353:              refresh();
354:              break;
355:
356:        default:                            /* handle digits */
357:              if (!isdigit (ch))
358:                 return K_UNKNOWN;
359:
360:              if (digits &&
361:                 (newval = *sel_val * 10 + (ch - '0')) <= nitems
362:                    && newval > 0)
363:              {
364:                 addch(ch);
365:                 refresh();
366:                 *sel_val =  newval;
367:                 return K_DIRECT;
368:              }
369:              else if ( (newval = ch - '0') && newval <= nitems)
370:              {
371:                 digits = TRUE;
372:                 move(echoy, echox);
373:                 addch(ch);
374:                 clrtoeo]();
375:                 refresh();
376:                 *sel_val = newval;
377:                 return K_DIRECT;
378:            }
379:            else
380:            {
381:                 digits = FALSE;
382:                 beep();
383:            }
384:       }
385:    }
386: }
/* End of File*/