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*/