1 /*
2 * MNU.C
3 *
4 * Written on 10-Jul-94 by John Dennis and released to the public domain.
5 *
6 * Routines to display horizontal and vertical menus with full drag/browse
7 * mouse support.
8 */
9
10 #include <string.h>
11 #include <stdlib.h>
12 #include "winsys.h"
13 #include "keys.h"
14 #include "menu.h"
15
16 int PullDown = 0;
17 int ExitType = 0;
18
19 static int bc = WHITE | _CYAN;
20 static int nc = BLACK | _CYAN;
21 static int sc = WHITE | _BLACK;
22
GetFocus(cmd * cmdtab,int num,int id)23 static int GetFocus(cmd * cmdtab, int num, int id)
24 {
25 int i;
26
27 for (i = 0; i < num; i++)
28 {
29 if (cmdtab[i].id == id)
30 {
31 return i;
32 }
33 }
34
35 return -1;
36 }
37
DispItem(cmd * c,unsigned char attr,int indent,int slen,int type)38 static void DispItem(cmd * c, unsigned char attr, int indent, int slen, int type)
39 {
40 char text[255];
41 int len;
42
43 if (!c || !c->itmtxt)
44 {
45 return;
46 }
47
48 len = strlen(c->itmtxt);
49 memset(text, ' ', slen + 2);
50 strncpy(text + indent, c->itmtxt, len);
51 *(text + slen) = '\0';
52 if (type == CMD_VER)
53 {
54 WndPutsn(0, c->row, slen, attr, text);
55 }
56 else
57 {
58 WndPutsn(c->col, c->row, slen, attr, text);
59 }
60 }
61
NextItem(int num,int cur)62 static int NextItem(int num, int cur)
63 {
64 cur++;
65 if (cur == num)
66 {
67 cur = 0;
68 }
69 return cur;
70 }
71
PrevItem(int num,int cur)72 static int PrevItem(int num, int cur)
73 {
74 cur--;
75 if (cur < 0)
76 {
77 cur = num - 1;
78 }
79 return cur;
80 }
81
82 /*
83 * Displays a horizontal menu in a window, according to the info in
84 * the passed MC structure.
85 *
86 * The current mouse position is passed to the function to pinpoint
87 * the item where the mouse hit before calling this function.
88 */
89
ProcessMenu(MC * m,EVT * event,int show)90 int ProcessMenu(MC * m, EVT * event, int show)
91 {
92 HotGroup Hot;
93 WND *hCurr, *hWnd = NULL;
94 cmd *cmdtab = m->cmdtab;
95 int num = m->num;
96 int Focus = m->cur;
97 int mnu = m->mode;
98 int len = m->len;
99 int OldFoc;
100 int done = 0;
101 int select = 0;
102 int Msg; /* Msg is used unitialised here. I did not yet
103 investigate it. FIXME! */
104 int NewFoc;
105 int i, j;
106
107 if (m->btype & INSBDR)
108 {
109 m->btype = SBDR;
110 }
111
112 hCurr = WndTop();
113 if (!show && !(m->mode & CMD_PRT))
114 {
115 hWnd = WndOpen(m->x1, m->y1, m->x2, m->y2, m->btype, bc, nc);
116 if (hWnd == NULL)
117 {
118 WndCurr(hCurr);
119 return WND_ERROR;
120 }
121 }
122
123 if (m->btype & NBDR)
124 {
125 j = 0;
126 }
127 else
128 {
129 j = 1;
130 }
131
132 for (i = 0; i < num; i++)
133 {
134 Hot.harr[i].id = cmdtab[i].id;
135 Hot.harr[i].x1 = m->x1 + j + cmdtab[i].col;
136 Hot.harr[i].x2 = m->x1 + j + cmdtab[i].col + len;
137 Hot.harr[i].y1 = m->y1 + j + cmdtab[i].row;
138 Hot.harr[i].y2 = m->y1 + j + cmdtab[i].row;
139 DispItem(&cmdtab[i], (unsigned char)nc, m->indent, m->len, mnu);
140 }
141
142 if (show)
143 {
144 return 0;
145 }
146
147 Hot.num = num;
148 Hot.wid = WND_WN_MENU;
149
150 PushHotGroup(&Hot);
151
152 if (event->msg)
153 {
154 if (event->msgtype == WND_WM_COMMAND)
155 {
156 Focus = GetFocus(cmdtab, m->num, event->id);
157 }
158 else
159 {
160 if (event->msgtype == WND_WM_MOUSE)
161 {
162 Focus = LocateHotItem(event->x, event->y, WND_WN_MENU);
163 if (Focus)
164 {
165 Focus = GetFocus(cmdtab, m->num, Focus);
166 }
167 }
168 }
169 if (Focus == -1)
170 {
171 Focus = 0;
172 }
173 }
174
175 DispItem(&cmdtab[Focus], (unsigned char)sc, m->indent, m->len, mnu);
176
177 while (!done)
178 {
179 if (select)
180 {
181 if (cmdtab[Focus].m_sub)
182 {
183 ProcessMenu(cmdtab[Focus].m_sub, event, 0);
184 }
185 else
186 {
187 if (cmdtab[Focus].flags & CMD_EXIT)
188 {
189 done = TRUE;
190 continue;
191 }
192 else
193 {
194 if (cmdtab[Focus].itmfunc != NULL)
195 {
196 (*cmdtab[Focus].itmfunc) ();
197 }
198 done = TRUE; /* should we exit here? */
199 continue;
200 }
201 }
202 select = 0;
203 }
204 else
205 {
206 Msg = MnuGetMsg(event, WND_WN_MENU);
207 }
208
209 OldFoc = Focus;
210
211 switch (event->msgtype)
212 {
213 case WND_WM_COMMAND:
214 NewFoc = GetFocus(cmdtab, m->num, event->id);
215 if (NewFoc != -1)
216 {
217 switch (Msg)
218 {
219 case MOU_LBTUP:
220 case LMOU_CLCK:
221 Focus = NewFoc;
222 select = TRUE;
223 break;
224
225 case MOU_LBTDN:
226 case LMOU_RPT:
227 case MOUSE_EVT:
228 Focus = NewFoc;
229 if (cmdtab[Focus].m_sub)
230 {
231 select = TRUE;
232 }
233 break;
234
235 default:
236 break;
237 }
238 }
239 else
240 {
241 if (mnu == CMD_VER && event->msg != m->parent)
242 {
243 done = TRUE;
244 }
245 }
246 break;
247
248 case WND_WM_MOUSE:
249 switch (Msg)
250 {
251 case LMOU_CLCK:
252 case MOU_LBTUP:
253 done = TRUE;
254 break;
255
256 default:
257 break;
258 }
259 break;
260
261 case WND_WM_CHAR:
262 switch (Msg)
263 {
264 case Key_Up:
265 if (mnu == CMD_VER)
266 {
267 Focus = PrevItem(m->num, Focus);
268 }
269 break;
270
271 case Key_Dwn:
272 if (cmdtab[Focus].m_sub)
273 {
274 select = TRUE;
275 }
276 if (mnu == CMD_VER)
277 {
278 Focus = NextItem(m->num, Focus);
279 }
280 break;
281
282 case Key_Lft:
283 if (mnu == CMD_HOR)
284 {
285 Focus = PrevItem(m->num, Focus);
286 }
287 else
288 {
289 done = TRUE;
290 }
291 break;
292
293 case Key_Rgt:
294 if (mnu == CMD_HOR)
295 {
296 Focus = NextItem(m->num, Focus);
297 }
298 else
299 {
300 done = TRUE;
301 }
302 break;
303
304 case Key_Esc:
305 done = TRUE;
306 break;
307
308 case Key_Ent:
309 select = TRUE;
310 break;
311
312 default:
313 break;
314 }
315 break;
316
317 default:
318 break;
319 }
320 if (Focus != OldFoc)
321 {
322 DispItem(&cmdtab[OldFoc], (unsigned char)nc, m->indent, m->len, mnu);
323 DispItem(&cmdtab[Focus], (unsigned char)sc, m->indent, m->len, mnu);
324 }
325 }
326 DispItem(&cmdtab[Focus], (unsigned char)nc, m->indent, m->len, mnu);
327 PopHotGroup();
328 if (!(m->mode & CMD_PRT))
329 {
330 WndClose(hWnd);
331 WndCurr(hCurr);
332 }
333 if (cmdtab[Focus].flags & CMD_EXIT && select)
334 {
335 /* then return the ID of ret item */
336
337 event->msgtype = WND_WM_CHAR;
338 event->msg = 0;
339
340 return cmdtab[Focus].id;
341 }
342 else
343 {
344 return 0;
345 }
346 }
347
MnuSetColours(int nbc,int nnc,int nsc)348 void MnuSetColours(int nbc, int nnc, int nsc)
349 {
350 bc = nbc;
351 nc = nnc;
352 sc = nsc;
353 }
354