1 /*
2 * MENU.C
3 *
4 * Written on 10-Jul-94 by John Dennis and released to the public domain.
5 *
6 * Moving bar menu code for Msged.
7 */
8
9 #include <stdio.h>
10 #include <string.h>
11 #include <ctype.h>
12 #include <time.h>
13 #include "winsys.h"
14 #include "unused.h"
15 #include "menu.h"
16 #include "addr.h"
17 #include "nedit.h"
18 #include "msged.h"
19 #include "main.h"
20 #include "keys.h"
21 #include "strextra.h"
22 #include "areas.h"
23 #include "memextra.h"
24
SelShowItem(char * text,int y,int len,int Attr,int indent)25 void SelShowItem(char *text, int y, int len, int Attr, int indent)
26 {
27 char line[256];
28 memset(line, ' ', 40);
29 strcpy(line + indent, text);
30 WndPutsn(indent, y, len, Attr, line);
31 }
32
SelShowPage(char ** text,int top,int bot,int len,int pos,int Attr,int indent)33 void SelShowPage(char **text, int top, int bot, int len, int pos, int Attr, int indent)
34 {
35 int i;
36 int y = top;
37
38 for (i = pos; text[i] != NULL; i++)
39 {
40 if (y > bot)
41 {
42 break;
43 }
44
45 SelShowItem(text[i], y++, len, Attr, indent);
46 }
47 if (y <= bot)
48 {
49 while (y <= bot)
50 {
51 SelShowItem(" ", y++, len, Attr, indent);
52 }
53 }
54 }
55
CalcDef(int max,int cur,int * top,int miny,int maxy,int * y)56 void CalcDef(int max, int cur, int *top, int miny, int maxy, int *y)
57 {
58 int dif = maxy - miny;
59
60 unused(cur);
61 if (max - 1 - *top < dif && max > dif)
62 {
63 *y = maxy;
64 *top = (max - 1) - dif;
65 }
66 }
67
SelBox(char ** Itms,int y1,int y2,int len,int def,WND * hPrev,WND * hWnd,int Sel,int Norm,int selbox_id,char * topMsg)68 int SelBox(char **Itms, int y1, int y2, int len, int def, WND * hPrev, WND * hWnd, int Sel, int Norm, int selbox_id, char *topMsg)
69 {
70 EVT e;
71 char find[30];
72 int itemCnt, Stuff, done, curY, Msg, currItem, Top, page, i;
73
74 itemCnt = 0;
75 Stuff = 0;
76 for (i = 0; Itms[i] != NULL; i++)
77 {
78 itemCnt++;
79 }
80
81 if (itemCnt < y2)
82 {
83 y2 = itemCnt;
84 }
85 currItem = def;
86 curY = y1;
87 page = y2 - y1;
88 Top = currItem;
89
90 if (currItem + y1 < y1)
91 {
92 curY = y1 + currItem;
93 Top = 0;
94 }
95 else
96 {
97 if (itemCnt - currItem <= y2 - y1)
98 {
99 Top -= ((y2 - y1 + 1) - (itemCnt - Top));
100 curY = y1 + def - Top;
101 if (Top < 0)
102 {
103 Top = 0;
104 curY--;
105 }
106 }
107 }
108 done = 0;
109
110 SelShowPage(Itms, y1, y2, len, Top, Norm, 1);
111 SelShowItem(Itms[currItem], curY, len, Sel, 1);
112
113 /* clear input queue */
114 TTClearQue();
115
116 memset(find, '\0', sizeof find);
117 while (!done)
118 {
119 if (*topMsg && selbox_id == SELBOX_REPLYOTH && !*find)
120 {
121 WndCurr(hPrev);
122 WndClear(strlen(topMsg) + 3, 0, maxx - 32, 0, cm[MN_NTXT]);
123 WndPrintf(0, 0, cm[MN_NTXT], ">>%s:", topMsg);
124 WndCurr(hWnd);
125 }
126 if (!Stuff)
127 {
128 Msg = MnuGetMsg(&e, hWnd->wid);
129 }
130 else
131 {
132 e.msgtype = WND_WM_CHAR;
133 Msg = Stuff;
134 Stuff = 0;
135 }
136
137 switch (e.msgtype)
138 {
139 case WND_WM_MOUSE:
140 switch (Msg)
141 {
142 case RMOU_CLCK:
143 case MOU_RBTUP:
144 return -1;
145
146 case LMOU_RPT:
147 case MOU_LBTDN:
148 case LMOU_CLCK:
149 {
150 int x, y;
151
152 WndGetRel(e.x, e.y, &x, &y);
153 if (y >= y1 && y <= y2) /* in window */
154 {
155 Stuff = 0;
156 if (x >= 0 && x < len)
157 {
158 if (y == curY)
159 {
160 if (Msg == LMOU_CLCK || Msg == MOU_LBTUP)
161 {
162 return currItem;
163 }
164 else
165 {
166 continue;
167 }
168 }
169 SelShowItem(Itms[currItem], curY, len, Norm, 1);
170
171 if (y > curY)
172 {
173 currItem += y - curY;
174 }
175 else
176 {
177 currItem -= curY - y;
178 }
179
180 curY = y;
181
182 SelShowItem(Itms[currItem], curY, len, Sel, 1);
183
184 if (Msg == LMOU_CLCK || Msg == MOU_LBTUP)
185 {
186 return currItem;
187 }
188 }
189 }
190 else
191 {
192 if (Msg != LMOU_CLCK)
193 {
194 if (y < y1)
195 {
196 Stuff = Key_Up;
197 }
198 else
199 {
200 Stuff = Key_Dwn;
201 }
202 }
203 }
204 }
205 memset(find, '\0', sizeof find);
206 break;
207
208 default:
209 break;
210 }
211 break;
212
213 case WND_WM_CHAR:
214 switch (Msg)
215 {
216 case Key_Home:
217 if (!currItem)
218 {
219 break;
220 }
221 SelShowItem(Itms[currItem], curY, len, Norm, 1);
222 currItem = 0;
223 Top = 0;
224 curY = y1;
225 SelShowPage(Itms, y1, y2, len, Top, Norm, 1);
226 SelShowItem(Itms[currItem], curY, len, Sel, 1);
227 memset(find, '\0', sizeof find);
228 break;
229
230 case Key_End:
231 if (currItem == itemCnt - 1)
232 {
233 break;
234 }
235 SelShowItem(Itms[currItem], curY, len, Norm, 1);
236 currItem = itemCnt - 1;
237 while (currItem && currItem >= itemCnt - page)
238 {
239 currItem--;
240 }
241 Top = currItem;
242 currItem = itemCnt - 1;
243 curY = currItem - Top + y1;
244 CalcDef(itemCnt, currItem, &Top, y1, y2, &curY);
245 SelShowPage(Itms, y1, y2, len, Top, Norm, 1);
246 SelShowItem(Itms[currItem], curY, len, Sel, 1);
247 memset(find, '\0', sizeof find);
248 break;
249
250 case Key_Dwn:
251 if (currItem == itemCnt - 1)
252 {
253 break;
254 }
255
256 SelShowItem(Itms[currItem], curY, len, Norm, 1);
257 currItem++;
258 if (curY == y2)
259 {
260 WndScroll(1, y1, len, y2, 1);
261 Top++;
262 }
263 else
264 {
265 curY++;
266 }
267 SelShowItem(Itms[currItem], curY, len, Sel, 1);
268 memset(find, '\0', sizeof find);
269 break;
270
271 case Key_Up:
272 if (!currItem)
273 {
274 break;
275 }
276 SelShowItem(Itms[currItem], curY, len, Norm, 1);
277 currItem--;
278 if (curY == y1)
279 {
280 WndScroll(1, y1, len, y2, 0);
281 if (Top)
282 {
283 Top--;
284 }
285 }
286 else
287 {
288 curY--;
289 }
290 SelShowItem(Itms[currItem], curY, len, Sel, 1);
291 memset(find, '\0', sizeof find);
292 break;
293
294 case Key_PgUp:
295 if (!currItem)
296 {
297 break;
298 }
299 SelShowItem(Itms[currItem], curY, len, Norm, 1);
300 currItem -= page;
301 if (currItem < 0)
302 {
303 currItem = 0;
304 }
305 Top = currItem;
306 curY = y1;
307 SelShowPage(Itms, y1, y2, len, Top, Norm, 1);
308 SelShowItem(Itms[currItem], curY, len, Sel, 1);
309 memset(find, '\0', sizeof find);
310 break;
311
312 case Key_PgDn:
313 if (currItem == itemCnt - 1)
314 {
315 break;
316 }
317 SelShowItem(Itms[currItem], curY, len, Norm, 1);
318 Top = currItem;
319 currItem += page;
320 if (currItem > itemCnt - 1)
321 {
322 currItem = itemCnt - 1;
323 }
324 curY = currItem - Top + y1;
325 CalcDef(itemCnt, currItem, &Top, y1, y2, &curY);
326 SelShowPage(Itms, y1, y2, len, Top, Norm, 1);
327 SelShowItem(Itms[currItem], curY, len, Sel, 1);
328 memset(find, '\0', sizeof find);
329 break;
330
331 case Key_Rgt:
332 case Key_Ent:
333 {
334 size_t i;
335 i = (size_t) strchr(Itms[currItem] + 1, ' ') - 1 -
336 (size_t) Itms[currItem];
337
338 if (i > 28)
339 {
340 i = 28;
341 }
342 strncpy(find, Itms[currItem] + 1, i);
343 *(find + i) = '\0';
344 strupr(find);
345 /* I did figure out that this code produces garbage on
346 screen. I did not figure out however, in
347 when situations it is necessary. So I
348 decided to comment it out and see what
349 happens ...
350 WndCurr(hPrev);
351 WndWriteStr(strlen(topMsg) + 4, 0, cm[MN_NTXT], find);
352 */
353 WndCurr(hWnd);
354 return currItem;
355 }
356
357 case Key_A_X:
358 case Key_Esc:
359 return -1;
360
361 case '*':
362 case Key_A_S:
363 if (selbox_id == SELBOX_REPLYOTH)
364 {
365 arealist_area_scan(1);
366 for (i = 0; i < SW->areas; i++)
367 {
368 xfree(alist2[i]);
369 }
370 xfree(alist2);
371 BuildList(&alist2);
372 Itms = alist2;
373 SelShowPage(Itms, y1, y2, len, Top, Norm, 1);
374 SelShowItem(Itms[currItem], curY, len, Sel, 1);
375 memset(find, '\0', sizeof find);
376 CurArea.messages = MsgAreaOpen(&CurArea);
377 }
378 break;
379
380 default:
381 if (Msg > 32 && Msg < 127)
382 {
383 if (*topMsg && selbox_id == SELBOX_REPLYOTH)
384 {
385 if (strlen(find) >= 28)
386 {
387 break;
388 }
389 *(find + strlen(find)) = (char)toupper((char)Msg);
390 WndCurr(hPrev);
391 WndWriteStr(strlen(topMsg) + 4, 0, cm[MN_NTXT], find);
392 WndCurr(hWnd);
393 }
394 else
395 {
396 *find = (char)toupper((char)Msg);
397 }
398
399 i = currItem;
400
401 while (i < itemCnt)
402 {
403 if (selbox_id == SELBOX_REPLYOTH)
404 {
405 if (stristr(Itms[i] + 1, find) == Itms[i] + 1)
406 {
407 break;
408 }
409 }
410 else
411 {
412 if (toupper(*Itms[i]) == *find)
413 {
414 if (selbox_id == SELBOX_MOVEMSG ||
415 selbox_id == SELBOX_WRTMODE ||
416 selbox_id == SELBOX_WRTOVER)
417 {
418 SelShowItem(Itms[currItem], curY, len, Norm, 1);
419 return i;
420 }
421 }
422 }
423 i++;
424 }
425 if (i == itemCnt)
426 {
427 for (i = 0; i < currItem; i++)
428 {
429 if (selbox_id == SELBOX_REPLYOTH)
430 {
431 if (stristr(Itms[i] + 1, find) == Itms[i] + 1)
432 {
433 break;
434 }
435 }
436 else
437 {
438 if (toupper(*Itms[i]) == *find)
439 {
440 if (selbox_id == SELBOX_MOVEMSG ||
441 selbox_id == SELBOX_WRTMODE ||
442 selbox_id == SELBOX_WRTOVER)
443 {
444 SelShowItem(Itms[currItem], curY, len, Norm, 1);
445 return i;
446 }
447 }
448 }
449 }
450 }
451 if (i != currItem)
452 {
453 SelShowItem(Itms[currItem], curY, len, Norm, 1);
454 currItem = i;
455 curY = y1;
456 Top = currItem;
457
458 /* Get the cursor position right... */
459
460 if (itemCnt - 1 - currItem < y2 - y1)
461 {
462 if (currItem > y2 - y1)
463 {
464 curY = y2;
465 Top = currItem - (y2 - y1);
466 }
467 else
468 {
469 curY = currItem + y1;
470 Top = 0;
471 }
472 }
473 SelShowPage(Itms, y1, y2, len, Top, Norm, 1);
474 SelShowItem(Itms[currItem], curY, len, Sel, 1);
475 }
476 }
477 else if (Msg == '\b' && *find)
478 {
479 if (*topMsg && selbox_id == SELBOX_REPLYOTH)
480 {
481 *(find + strlen(find) - 1) = '\0';
482 WndCurr(hPrev);
483 WndClear(strlen(topMsg) + 3 + strlen(find), 0, maxx - 32, 0, cm[MN_NTXT]);
484 WndCurr(hWnd);
485 }
486 }
487 else
488 {
489 memset(find, '\0', sizeof find);
490 }
491 break;
492
493 }
494 break;
495 }
496 }
497 return -1;
498 }
499
500 #ifndef NODOMENU
501
DoMenu(int x1,int y1,int x2,int y2,char ** Itms,int def,int selbox_id,char * topMsg)502 int DoMenu(int x1, int y1, int x2, int y2, char **Itms, int def, int selbox_id, char *topMsg)
503 {
504 WND *hCurr, *hWnd;
505 int ret;
506
507 hCurr = WndTop();
508 hWnd = WndOpen(x1 - 1, y1 - 1, x2 + 3, y2 + 1, DBDR | SHADOW, cm[MN_BTXT], cm[MN_NTXT]);
509
510 if (!hWnd)
511 {
512 return -1;
513 }
514
515 if (selbox_id >= SELBOX_CHARSET)
516 {
517 WndTitle(topMsg, cm[MN_TTXT]);
518 }
519
520 ret = SelBox(Itms, 0, y2 - y1, x2 - x1 + 2, def, hCurr, hWnd, cm[MN_STXT], cm[MN_NTXT], selbox_id, topMsg);
521
522 WndClose(hWnd);
523 WndCurr(hCurr);
524
525 return ret;
526 }
527
528 #endif
529