more DUMPLOG lint
[aNetHack.git] / sys / amiga / winmenu.c
blob8558dbac5c4953eb9be92c9b654bd5384a02b0f9
1 /* NetHack 3.6 winmenu.c $NHDT-Date: 1432512796 2015/05/25 00:13:16 $ $NHDT-Branch: master $:$NHDT-Revision: 1.7 $ */
2 /* Copyright (c) Gregg Wonderly, Naperville, Illinois, 1991,1992,1993,1996.
3 */
4 /* NetHack may be freely redistributed. See license for details. */
6 #include "NH:sys/amiga/windefs.h"
7 #include "NH:sys/amiga/winext.h"
8 #include "NH:sys/amiga/winproto.h"
10 /* Start building the text for a menu */
11 void
12 amii_start_menu(window)
13 register winid window;
15 register int i;
16 register struct amii_WinDesc *cw;
17 register amii_menu_item *mip;
19 if (window == WIN_ERR || (cw = amii_wins[window]) == NULL
20 || cw->type != NHW_MENU)
21 panic(winpanicstr, window, "start_menu");
23 amii_clear_nhwindow(window);
25 if (cw->data && (cw->type == NHW_MESSAGE || cw->type == NHW_MENU
26 || cw->type == NHW_TEXT)) {
27 for (i = 0; i < cw->maxrow; ++i) {
28 if (cw->data[i])
29 free(cw->data[i]);
31 free(cw->data);
32 cw->data = NULL;
35 for (mip = cw->menu.items, i = 0;
36 (mip = cw->menu.items) && i < cw->menu.count; ++i) {
37 cw->menu.items = mip->next;
38 free(mip);
41 cw->menu.items = 0;
42 cw->menu.count = 0;
43 cw->menu.chr = 'a';
45 if (cw->morestr)
46 free(cw->morestr);
47 cw->morestr = NULL;
49 if (window == WIN_INVEN && cw->win != NULL) {
50 if (alwaysinvent)
51 cw->wasup = 1;
53 cw->cury = cw->rows = cw->maxrow = cw->maxcol = 0;
54 return;
57 /* Add a string to a menu */
58 void
59 amii_add_menu(window, glyph, id, ch, gch, attr, str, preselected)
60 register winid window;
61 register int glyph;
62 register const anything *id;
63 register char ch;
64 register char gch;
65 register int attr;
66 register const char *str;
67 register BOOLEAN_P preselected;
69 register struct amii_WinDesc *cw;
70 amii_menu_item *mip;
71 char buf[4 + BUFSZ];
73 if (str == NULL)
74 return;
76 if (window == WIN_ERR || (cw = amii_wins[window]) == NULL
77 || cw->type != NHW_MENU)
78 panic(winpanicstr, window, "add_menu");
80 mip = (amii_menu_item *) alloc(sizeof(*mip));
81 mip->identifier = *id;
82 mip->selected = preselected;
83 mip->attr = attr;
84 mip->glyph = Is_rogue_level(&u.uz) ? NO_GLYPH : glyph;
85 mip->selector = 0;
86 mip->gselector = gch;
87 mip->count = -1;
89 if (id->a_void && !ch && cw->menu.chr != 0) {
90 ch = cw->menu.chr++;
91 if (ch == 'z')
92 cw->menu.chr = 'A';
93 if (ch == 'Z')
94 cw->menu.chr = 0;
97 mip->canselect = (id->a_void != 0);
99 if (id->a_void && ch != '\0') {
100 Sprintf(buf, "%c - %s", ch, str);
101 str = buf;
102 mip->canselect = 1;
105 mip->selector = ch;
107 amii_putstr(window, attr, str);
109 mip->str = cw->data[cw->cury - 1];
110 cw->menu.count++;
112 mip->next = NULL;
114 if (cw->menu.items == 0)
115 cw->menu.last = cw->menu.items = mip;
116 else {
117 cw->menu.last->next = mip;
118 cw->menu.last = mip;
122 /* Done building a menu. */
124 void
125 amii_end_menu(window, morestr)
126 register winid window;
127 register const char *morestr;
129 register struct amii_WinDesc *cw;
131 if (window == WIN_ERR || (cw = amii_wins[window]) == NULL
132 || cw->type != NHW_MENU)
133 panic(winpanicstr, window, "end_menu");
135 if (morestr && *morestr) {
136 anything any;
137 #define PROMPTFIRST /* Define this to have prompt first */
138 #ifdef PROMPTFIRST
139 amii_menu_item *mip;
140 int i;
141 char *t;
142 mip = cw->menu.last;
143 #endif
144 any.a_void = 0;
145 amii_add_menu(window, NO_GLYPH, &any, 0, 0, ATR_NONE, morestr,
146 MENU_UNSELECTED);
147 #ifdef PROMPTFIRST /* Do some shuffling. Last first, push others one forward \
149 mip->next = NULL;
150 cw->menu.last->next = cw->menu.items;
151 cw->menu.items = cw->menu.last;
152 cw->menu.last = mip;
153 t = cw->data[cw->cury - 1];
154 for (i = cw->cury - 1; i > 0; i--) {
155 cw->data[i] = cw->data[i - 1];
157 cw->data[0] = t;
158 #endif
161 /* If prompt first, don't put same string in title where in most cases
162 it's not entirely visible anyway */
163 #ifndef PROMPTFIRST
164 if (morestr)
165 cw->morestr = strdup(morestr);
166 #endif
169 /* Select something from the menu. */
172 amii_select_menu(window, how, mip)
173 register winid window;
174 register int how;
175 register menu_item **mip;
177 int cnt;
178 register struct amii_WinDesc *cw;
180 if (window == WIN_ERR || (cw = amii_wins[window]) == NULL
181 || cw->type != NHW_MENU)
182 panic(winpanicstr, window, "select_menu");
184 cnt = DoMenuScroll(window, 1, how, mip);
186 /* This would allow the inventory window to stay open. */
187 if (!alwaysinvent || window != WIN_INVEN)
188 dismiss_nhwindow(window); /* Now tear it down */
189 return cnt;
192 amii_menu_item *
193 find_menu_item(register struct amii_WinDesc *cw, int idx)
195 amii_menu_item *mip;
196 for (mip = cw->menu.items; idx > 0 && mip; mip = mip->next)
197 --idx;
199 return (mip);
203 make_menu_items(register struct amii_WinDesc *cw, register menu_item **rmip)
205 register int idx = 0;
206 register amii_menu_item *mip;
207 register menu_item *mmip;
209 for (mip = cw->menu.items; mip; mip = mip->next) {
210 if (mip->selected)
211 ++idx;
214 if (idx) {
215 mmip = *rmip = (menu_item *) alloc(idx * sizeof(*mip));
216 for (mip = cw->menu.items; mip; mip = mip->next) {
217 if (mip->selected) {
218 mmip->item = mip->identifier;
219 mmip->count = mip->count;
220 mmip++;
224 cw->mi = *rmip;
226 return (idx);
230 DoMenuScroll(win, blocking, how, retmip)
231 int win, blocking, how;
232 menu_item **retmip;
234 amii_menu_item *amip;
235 register struct Window *w;
236 register struct NewWindow *nw;
237 struct PropInfo *pip;
238 register struct amii_WinDesc *cw;
239 struct IntuiMessage *imsg;
240 struct Gadget *gd;
241 register int wheight, xsize, ysize, aredone = 0;
242 register int txwd, txh;
243 long mics, secs, class, code;
244 long oldmics = 0, oldsecs = 0;
245 int aidx, oidx, topidx, hidden;
246 int totalvis;
247 SHORT mx, my;
248 static char title[100];
249 int dosize = 1;
250 struct Screen *scrn = HackScreen;
251 int x1, x2, y1, y2;
252 long counting = FALSE, count = 0, reset_counting = FALSE;
253 char countString[32];
255 if (win == WIN_ERR || (cw = amii_wins[win]) == NULL)
256 panic(winpanicstr, win, "DoMenuScroll");
258 /* Initial guess at window sizing values */
259 txwd = txwidth;
260 if (WINVERS_AMIV) {
261 if (win == WIN_INVEN)
262 txh = max(txheight, pictdata.ysize + 3); /* interline space */
263 else
264 txh = txheight; /* interline space */
265 } else
266 txh = txheight; /* interline space */
268 /* Check to see if we should open the window, should need to for
269 * TEXT and MENU but not MESSAGE.
272 w = cw->win;
273 topidx = 0;
275 if (w == NULL) {
276 #ifdef INTUI_NEW_LOOK
277 if (IntuitionBase->LibNode.lib_Version >= 37) {
278 PropScroll.Flags |= PROPNEWLOOK;
280 #endif
281 nw = (void *) DupNewWindow((void *) (&new_wins[cw->type].newwin));
282 if (!alwaysinvent || win != WIN_INVEN) {
283 xsize = scrn->WBorLeft + scrn->WBorRight + MenuScroll.Width + 1
284 + (txwd * cw->maxcol);
285 if (WINVERS_AMIV) {
286 if (win == WIN_INVEN)
287 xsize += pictdata.xsize + 4;
289 if (xsize > amiIDisplay->xpix)
290 xsize = amiIDisplay->xpix;
292 /* If next row not off window, use it, else use the bottom */
294 ysize = (txh * cw->maxrow) + /* The text space */
295 HackScreen->WBorTop + txheight + 1 + /* Top border */
296 HackScreen->WBorBottom + 3; /* The bottom border */
297 if (ysize > amiIDisplay->ypix)
298 ysize = amiIDisplay->ypix;
300 /* Adjust the size of the menu scroll gadget */
302 nw->TopEdge = 0;
303 if (cw->type == NHW_TEXT && ysize < amiIDisplay->ypix)
304 nw->TopEdge += (amiIDisplay->ypix - ysize) / 2;
305 nw->LeftEdge = amiIDisplay->xpix - xsize;
306 if (cw->type == NHW_MENU) {
307 if (nw->LeftEdge > 10)
308 nw->LeftEdge -= 10;
309 else
310 nw->LeftEdge = 0;
311 if (amiIDisplay->ypix - nw->Height > 10)
312 nw->TopEdge += 10;
313 else
314 nw->TopEdge = amiIDisplay->ypix - nw->Height - 1;
316 if (cw->type == NHW_TEXT && xsize < amiIDisplay->xpix)
317 nw->LeftEdge -= (amiIDisplay->xpix - xsize) / 2;
318 } else if (win == WIN_INVEN) {
319 struct Window *mw = amii_wins[WIN_MAP]->win;
320 struct Window *sw = amii_wins[WIN_STATUS]->win;
322 xsize = scrn->WBorLeft + scrn->WBorRight + MenuScroll.Width + 1
323 + (txwd * cw->maxcol);
325 /* Make space for the glyph to appear at the left of the
326 * description */
327 if (WINVERS_AMIV)
328 xsize += pictdata.xsize + 4;
330 if (xsize > amiIDisplay->xpix)
331 xsize = amiIDisplay->xpix;
333 /* If next row not off window, use it, else use the bottom */
335 ysize = sw->TopEdge - (mw->TopEdge + mw->Height) - 1;
336 if (ysize > amiIDisplay->ypix)
337 ysize = amiIDisplay->ypix;
339 /* Adjust the size of the menu scroll gadget */
341 nw->TopEdge = mw->TopEdge + mw->Height;
342 nw->LeftEdge = 0;
344 cw->newwin = (void *) nw;
345 if (nw == NULL)
346 panic("No NewWindow Allocated");
348 nw->Screen = HackScreen;
350 if (win == WIN_INVEN) {
351 sprintf(title, "%s the %s's Inventory", plname, pl_character);
352 nw->Title = title;
353 if (lastinvent.MaxX != 0) {
354 nw->LeftEdge = lastinvent.MinX;
355 nw->TopEdge = lastinvent.MinY;
356 nw->Width = lastinvent.MaxX;
357 nw->Height = lastinvent.MaxY;
359 } else if (cw->morestr)
360 nw->Title = cw->morestr;
362 /* Adjust the window coordinates and size now that we know
363 * how many items are to be displayed.
366 if ((xsize > amiIDisplay->xpix - nw->LeftEdge)
367 && (xsize < amiIDisplay->xpix)) {
368 nw->LeftEdge = amiIDisplay->xpix - xsize;
369 nw->Width = xsize;
370 } else {
371 nw->Width = min(xsize, amiIDisplay->xpix - nw->LeftEdge);
373 nw->Height = min(ysize, amiIDisplay->ypix - nw->TopEdge);
375 if (WINVERS_AMIV || WINVERS_AMII) {
376 /* Make sure we are using the correct hook structure */
377 nw->Extension = cw->wintags;
380 /* Now, open the window */
381 w = cw->win = OpenShWindow((void *) nw);
383 if (w == NULL) {
384 char buf[130];
386 sprintf(buf, "No Window Opened For Menu (%d,%d,%d-%d,%d-%d)",
387 nw->LeftEdge, nw->TopEdge, nw->Width, amiIDisplay->xpix,
388 nw->Height, amiIDisplay->ypix);
389 panic(buf);
392 #ifdef HACKFONT
393 if (TextsFont)
394 SetFont(w->RPort, TextsFont);
395 else if (HackFont)
396 SetFont(w->RPort, HackFont);
397 #endif
398 txwd = w->RPort->TxWidth;
399 if (WINVERS_AMIV) {
400 if (win == WIN_INVEN)
401 txh = max(w->RPort->TxHeight,
402 pictdata.ysize + 3); /* interline space */
403 else
404 txh = w->RPort->TxHeight; /* interline space */
405 } else
406 txh = w->RPort->TxHeight; /* interline space */
408 /* subtract 2 to account for spacing away from border (1 on each side)
410 wheight = (w->Height - w->BorderTop - w->BorderBottom - 2) / txh;
411 if (WINVERS_AMIV) {
412 if (win == WIN_INVEN) {
413 cw->cols = (w->Width - w->BorderLeft - w->BorderRight - 4
414 - pictdata.xsize - 3) / txwd;
415 } else {
416 cw->cols =
417 (w->Width - w->BorderLeft - w->BorderRight - 4) / txwd;
419 } else {
420 cw->cols = (w->Width - w->BorderLeft - w->BorderRight - 4) / txwd;
422 totalvis = CountLines(win);
423 } else {
424 txwd = w->RPort->TxWidth;
425 if (WINVERS_AMIV) {
426 if (win == WIN_INVEN)
427 txh = max(w->RPort->TxHeight,
428 pictdata.ysize + 3); /* interline space */
429 else
430 txh = w->RPort->TxHeight; /* interline space */
431 } else {
432 txh = w->RPort->TxHeight; /* interline space */
435 /* subtract 2 to account for spacing away from border (1 on each side)
437 wheight = (w->Height - w->BorderTop - w->BorderBottom - 2) / txh;
438 if (WINVERS_AMIV) {
439 if (win == WIN_INVEN) {
440 cw->cols = (w->Width - w->BorderLeft - w->BorderRight - 4
441 - pictdata.xsize - 3) / txwd;
442 } else
443 cw->cols =
444 (w->Width - w->BorderLeft - w->BorderRight - 4) / txwd;
445 } else {
446 cw->cols = (w->Width - w->BorderLeft - w->BorderRight - 4) / txwd;
449 totalvis = CountLines(win);
451 for (gd = w->FirstGadget; gd && gd->GadgetID != 1;)
452 gd = gd->NextGadget;
454 if (gd) {
455 pip = (struct PropInfo *) gd->SpecialInfo;
456 hidden = max(totalvis - wheight, 0);
457 topidx = (((ULONG) hidden * pip->VertPot) + (MAXPOT / 2)) >> 16;
461 for (gd = w->FirstGadget; gd && gd->GadgetID != 1;)
462 gd = gd->NextGadget;
464 if (!gd)
465 panic("Can't find scroll gadget");
467 morc = 0;
468 oidx = -1;
470 #if 0
471 /* Make sure there are no selections left over from last time. */
472 /* XXX potential problem for preselection if this is really needed */
473 for( amip = cw->menu.items; amip; amip = amip->next )
474 amip->selected = 0;
475 #endif
477 DisplayData(win, topidx);
479 /* Make the prop gadget the right size and place */
481 SetPropInfo(w, gd, wheight, totalvis, topidx);
482 oldsecs = oldmics = 0;
484 /* If window already up, don't stop to process events */
485 if (cw->wasup) {
486 aredone = 1;
487 cw->wasup = 0;
490 while (!aredone) {
491 /* Process window messages */
493 WaitPort(w->UserPort);
494 while (imsg = (struct IntuiMessage *) GetMsg(w->UserPort)) {
495 class = imsg->Class;
496 code = imsg->Code;
497 mics = imsg->Micros;
498 secs = imsg->Seconds;
499 gd = (struct Gadget *) imsg->IAddress;
500 mx = imsg->MouseX;
501 my = imsg->MouseY;
503 /* Only do our window or VANILLAKEY from other windows */
505 if (imsg->IDCMPWindow != w && class != VANILLAKEY
506 && class != RAWKEY) {
507 ReplyMsg((struct Message *) imsg);
508 continue;
511 /* Do DeadKeyConvert() stuff if RAWKEY... */
512 if (class == RAWKEY) {
513 class = VANILLAKEY;
514 code = ConvertKey(imsg);
516 ReplyMsg((struct Message *) imsg);
518 switch (class) {
519 case NEWSIZE:
522 * Ignore every other newsize, no action needed,
523 * except RefreshWindowFrame() in case borders got overwritten
524 * for some reason. It should not happen, but ...
527 if (!dosize) {
528 RefreshWindowFrame(w);
529 dosize = 1;
530 break;
533 if (win == WIN_INVEN) {
534 lastinvent.MinX = w->LeftEdge;
535 lastinvent.MinY = w->TopEdge;
536 lastinvent.MaxX = w->Width;
537 lastinvent.MaxY = w->Height;
538 } else if (win == WIN_MESSAGE) {
539 lastmsg.MinX = w->LeftEdge;
540 lastmsg.MinY = w->TopEdge;
541 lastmsg.MaxX = w->Width;
542 lastmsg.MaxY = w->Height;
545 /* Find the gadget */
547 for (gd = w->FirstGadget; gd && gd->GadgetID != 1;)
548 gd = gd->NextGadget;
550 if (!gd)
551 panic("Can't find scroll gadget");
553 totalvis = CountLines(win);
554 wheight =
555 (w->Height - w->BorderTop - w->BorderBottom - 2) / txh;
556 if (WINVERS_AMIV) {
557 if (win == WIN_INVEN) {
558 cw->cols = (w->Width - w->BorderLeft - w->BorderRight
559 - 4 - pictdata.xsize - 3) / txwd;
560 } else
561 cw->cols = (w->Width - w->BorderLeft - w->BorderRight
562 - 4) / txwd;
563 } else {
564 cw->cols = (w->Width - w->BorderLeft - w->BorderRight - 4)
565 / txwd;
568 if (wheight < 2)
569 wheight = 2;
572 * Clear the right side & bottom. Parts of letters are not
573 * erased by
574 * amii_cl_end if window shrinks and columns decrease.
577 if (WINVERS_AMII || WINVERS_AMIV) {
578 amii_setfillpens(w, cw->type);
579 SetDrMd(w->RPort, JAM2);
580 x2 = w->Width - w->BorderRight;
581 y2 = w->Height - w->BorderBottom;
582 x1 = x2 - w->IFont->tf_XSize - w->IFont->tf_XSize;
583 y1 = w->BorderTop;
584 if (x1 < w->BorderLeft)
585 x1 = w->BorderLeft;
586 RectFill(w->RPort, x1, y1, x2, y2);
587 x1 = w->BorderLeft;
588 y1 = y1 - w->IFont->tf_YSize;
589 RectFill(w->RPort, x1, y1, x2, y2);
590 RefreshWindowFrame(w);
593 /* Make the prop gadget the right size and place */
595 DisplayData(win, topidx);
596 SetPropInfo(w, gd, wheight, totalvis, topidx);
598 /* Force the window to a text line boundary <= to
599 * what the user dragged it to. This eliminates
600 * having to clean things up on the bottom edge.
603 SizeWindow(w, 0, (wheight * txh) + w->BorderTop
604 + w->BorderBottom + 2 - w->Height);
606 /* Don't do next NEWSIZE, we caused it */
607 dosize = 0;
608 oldsecs = oldmics = 0;
609 break;
611 case VANILLAKEY:
612 #define CTRL(x) ((x) - '@')
613 morc = code = map_menu_cmd(code);
614 if (code == MENU_SELECT_ALL) {
615 if (how == PICK_ANY) {
616 amip = cw->menu.items;
617 while (amip) {
618 if (amip->canselect && amip->selector) {
620 * Select those yet unselected
621 * and apply count if necessary
623 if (!amip->selected) {
624 amip->selected = TRUE;
625 if (counting) {
626 amip->count = count;
627 reset_counting = TRUE;
629 * This makes the assumption that
630 * the string is in format "X - foo"
631 * with additional selecting and
632 * formatting
633 * data in front (size SOFF)
635 amip->str[SOFF + 2] = '#';
636 } else {
637 amip->count = -1;
638 amip->str[SOFF + 2] = '-';
642 amip = amip->next;
644 DisplayData(win, topidx);
646 } else if (code == MENU_UNSELECT_ALL) {
647 if (how == PICK_ANY) {
648 amip = cw->menu.items;
649 while (amip) {
650 if (amip->selected) {
651 amip->selected = FALSE;
652 amip->count = -1;
653 amip->str[SOFF + 2] = '-';
655 amip = amip->next;
657 DisplayData(win, topidx);
659 } else if (code == MENU_INVERT_ALL) {
660 if (how == PICK_ANY) {
661 amip = cw->menu.items;
662 while (amip) {
663 if (amip->canselect && amip->selector) {
664 amip->selected = !amip->selected;
665 if (counting && amip->selected) {
666 amip->count = count;
667 amip->str[SOFF + 2] = '#';
668 reset_counting = TRUE;
669 } else {
670 amip->count = -1;
671 amip->str[SOFF + 2] = '-';
674 amip = amip->next;
676 DisplayData(win, topidx);
678 } else if (code == MENU_SELECT_PAGE) {
679 if (how == PICK_ANY) {
680 int i = 0;
681 amip = cw->menu.items;
682 while (amip && i++ < topidx)
683 amip = amip->next;
684 for (i = 0; i < wheight && amip;
685 i++, amip = amip->next) {
686 if (amip->canselect && amip->selector) {
687 if (!amip->selected) {
688 if (counting) {
689 amip->count = count;
690 reset_counting = TRUE;
691 amip->str[SOFF + 2] = '#';
692 } else {
693 amip->count = -1;
694 amip->str[SOFF + 2] = '-';
697 amip->selected = TRUE;
700 DisplayData(win, topidx);
702 } else if (code == MENU_UNSELECT_PAGE) {
703 if (how == PICK_ANY) {
704 int i = 0;
705 amip = cw->menu.items;
706 while (amip && i++ < topidx)
707 amip = amip->next;
708 for (i = 0; i < wheight && amip;
709 i++, amip = amip->next) {
710 if (amip->selected) {
711 amip->selected = FALSE;
712 amip->count = -1;
713 amip->str[SOFF + 2] = '-';
716 DisplayData(win, topidx);
718 } else if (code == MENU_INVERT_PAGE) {
719 if (how == PICK_ANY) {
720 int i = 0;
721 amip = cw->menu.items;
722 while (amip && i++ < topidx)
723 amip = amip->next;
724 for (i = 0; i < wheight && amip;
725 i++, amip = amip->next) {
726 if (amip->canselect && amip->selector) {
727 amip->selected = !amip->selected;
728 if (counting && amip->selected) {
729 amip->count = count;
730 amip->str[SOFF + 2] = '#';
731 reset_counting = TRUE;
732 } else {
733 amip->count = -1;
734 amip->str[SOFF + 2] = '-';
738 DisplayData(win, topidx);
740 } else if (code == MENU_SEARCH && cw->type == NHW_MENU) {
741 if (how == PICK_ONE || how == PICK_ANY) {
742 char buf[BUFSZ];
743 amip = cw->menu.items;
744 amii_getlin("Search for:", buf);
745 if (!*buf || *buf == '\033')
746 break;
747 while (amip) {
748 if (amip->canselect && amip->selector && amip->str
749 && strstri(&amip->str[SOFF], buf)) {
750 if (how == PICK_ONE) {
751 amip->selected = TRUE;
752 aredone = 1;
753 break;
755 amip->selected = !amip->selected;
756 if (counting && amip->selected) {
757 amip->count = count;
758 reset_counting = TRUE;
759 amip->str[SOFF + 2] = '#';
760 } else {
761 amip->count = -1;
762 reset_counting = TRUE;
763 amip->str[SOFF + 2] = '-';
766 amip = amip->next;
769 DisplayData(win, topidx);
770 } else if (how == PICK_ANY && isdigit(code)
771 && (counting || (!counting && code != '0'))) {
772 if (count < LARGEST_INT) {
773 count = count * 10 + (long) (code - '0');
774 if (count > LARGEST_INT)
775 count = LARGEST_INT;
776 if (count > 0) {
777 counting = TRUE;
778 reset_counting = FALSE;
779 } else {
780 reset_counting = TRUE;
782 sprintf(countString, "Count: %d", count);
783 pline(countString);
785 } else if (code == CTRL('D') || code == CTRL('U')
786 || code == MENU_NEXT_PAGE
787 || code == MENU_PREVIOUS_PAGE
788 || code == MENU_FIRST_PAGE
789 || code == MENU_LAST_PAGE) {
790 int endcnt, i;
792 for (gd = w->FirstGadget; gd && gd->GadgetID != 1;)
793 gd = gd->NextGadget;
795 if (!gd)
796 panic("Can't find scroll gadget");
798 endcnt = wheight; /* /2; */
799 if (endcnt == 0)
800 endcnt = 1;
802 if (code == MENU_FIRST_PAGE) {
803 topidx = 0;
804 } else if (code == MENU_LAST_PAGE) {
805 topidx = cw->maxrow - wheight;
806 } else
807 for (i = 0; i < endcnt; ++i) {
808 if (code == CTRL('D') || code == MENU_NEXT_PAGE) {
809 if (topidx + wheight < cw->maxrow)
810 ++topidx;
811 else
812 break;
813 } else if (code = CTRL('U')
814 || code == MENU_PREVIOUS_PAGE) {
815 if (topidx > 0)
816 --topidx;
817 else
818 break;
821 /* Make prop gadget the right size and place */
823 DisplayData(win, topidx);
824 SetPropInfo(w, gd, wheight, totalvis, topidx);
825 oldsecs = oldmics = 0;
826 } else if (code == '\b') {
827 for (gd = w->FirstGadget; gd && gd->GadgetID != 1;)
828 gd = gd->NextGadget;
830 if (!gd)
831 panic("Can't find scroll gadget");
833 if (topidx - wheight - 2 < 0) {
834 topidx = 0;
835 } else {
836 topidx -= wheight - 2;
838 DisplayData(win, topidx);
839 SetPropInfo(w, gd, wheight, totalvis, topidx);
840 oldsecs = oldmics = 0;
841 } else if (code == ' ') {
842 for (gd = w->FirstGadget; gd && gd->GadgetID != 1;)
843 gd = gd->NextGadget;
845 if (!gd)
846 panic("Can't find scroll gadget");
848 if (topidx + wheight >= cw->maxrow) {
849 morc = 0;
850 aredone = 1;
851 } else {
852 /* If there are still lines to be seen */
854 if (cw->maxrow > topidx + wheight) {
855 if (wheight > 2)
856 topidx += wheight - 2;
857 else
858 ++topidx;
859 DisplayData(win, topidx);
860 SetPropInfo(w, gd, wheight, totalvis, topidx);
862 oldsecs = oldmics = 0;
864 } else if (code == '\n' || code == '\r') {
865 for (gd = w->FirstGadget; gd && gd->GadgetID != 1;)
866 gd = gd->NextGadget;
868 if (!gd)
869 panic("Can't find scroll gadget");
871 /* If all line displayed, we are done */
873 if (topidx + wheight >= cw->maxrow) {
874 morc = 0;
875 aredone = 1;
876 } else {
877 /* If there are still lines to be seen */
879 if (cw->maxrow > topidx + 1) {
880 ++topidx;
881 DisplayData(win, topidx);
882 SetPropInfo(w, gd, wheight, totalvis, topidx);
884 oldsecs = oldmics = 0;
886 } else if (code == '\33') {
887 if (counting) {
888 reset_counting = TRUE;
889 } else {
890 aredone = 1;
892 } else {
893 int selected = FALSE;
894 for (amip = cw->menu.items; amip; amip = amip->next) {
895 if (amip->selector == code) {
896 if (how == PICK_ONE)
897 aredone = 1;
898 amip->selected = !amip->selected;
899 if (counting && amip->selected) {
900 amip->count = count;
901 reset_counting = TRUE;
902 amip->str[SOFF + 2] = '#';
903 } else {
904 amip->count = -1;
905 reset_counting = TRUE;
906 amip->str[SOFF + 2] = '-';
908 selected = TRUE;
909 } else if (amip->gselector == code) {
910 amip->selected = !amip->selected;
911 if (counting) {
912 amip->count = count;
913 reset_counting = TRUE;
914 amip->str[SOFF + 2] = '#';
915 } else {
916 amip->count = -1;
917 reset_counting = TRUE;
918 amip->str[SOFF + 2] = '-';
920 selected = TRUE;
923 if (selected)
924 DisplayData(win, topidx);
926 break;
928 case CLOSEWINDOW:
929 if (win == WIN_INVEN) {
930 lastinvent.MinX = w->LeftEdge;
931 lastinvent.MinY = w->TopEdge;
932 lastinvent.MaxX = w->Width;
933 lastinvent.MaxY = w->Height;
934 } else if (win == WIN_MESSAGE) {
935 lastmsg.MinX = w->LeftEdge;
936 lastmsg.MinY = w->TopEdge;
937 lastmsg.MaxX = w->Width;
938 lastmsg.MaxY = w->Height;
940 aredone = 1;
941 morc = '\33';
942 break;
944 case GADGETUP:
945 if (win == WIN_MESSAGE)
946 aredone = 1;
947 for (gd = w->FirstGadget; gd && gd->GadgetID != 1;)
948 gd = gd->NextGadget;
950 pip = (struct PropInfo *) gd->SpecialInfo;
951 totalvis = CountLines(win);
952 hidden = max(totalvis - wheight, 0);
953 aidx = (((ULONG) hidden * pip->VertPot) + (MAXPOT / 2)) >> 16;
954 if (aidx != topidx)
955 DisplayData(win, topidx = aidx);
956 break;
958 case MOUSEMOVE:
959 for (gd = w->FirstGadget; gd && gd->GadgetID != 1;)
960 gd = gd->NextGadget;
962 pip = (struct PropInfo *) gd->SpecialInfo;
963 totalvis = CountLines(win);
964 hidden = max(totalvis - wheight, 0);
965 aidx = (((ULONG) hidden * pip->VertPot) + (MAXPOT / 2)) >> 16;
966 if (aidx != topidx)
967 DisplayData(win, topidx = aidx);
968 break;
970 case INACTIVEWINDOW:
971 if (win == WIN_MESSAGE || (win == WIN_INVEN && alwaysinvent))
972 aredone = 1;
973 break;
975 case MOUSEBUTTONS:
976 if ((code == SELECTUP || code == SELECTDOWN)
977 && cw->type == NHW_MENU && how != PICK_NONE) {
978 /* Which one is the mouse pointing at? */
980 aidx = ((my - w->BorderTop - 1) / txh) + topidx;
982 /* If different lines, don't select double click */
984 if (aidx != oidx) {
985 oldsecs = 0;
986 oldmics = 0;
989 /* If releasing, check for double click */
991 if (code == SELECTUP) {
992 amip = find_menu_item(cw, aidx);
993 if (aidx == oidx) {
994 if (DoubleClick(oldsecs, oldmics, secs, mics)) {
995 aredone = 1;
997 oldsecs = secs;
998 oldmics = mics;
999 } else {
1000 amip = find_menu_item(cw, oidx);
1001 amip->selected = 0;
1002 amip->count = -1;
1003 reset_counting = TRUE;
1004 if (amip->canselect && amip->selector)
1005 amip->str[SOFF + 2] = '-';
1007 if (counting && amip->selected && amip->canselect
1008 && amip->selector) {
1009 amip->count = count;
1010 reset_counting = TRUE;
1011 amip->str[SOFF + 2] = '#';
1013 DisplayData(win, topidx);
1014 } else if (aidx - topidx < wheight && aidx < cw->maxrow
1015 && code == SELECTDOWN) {
1016 /* Remove old highlighting if visible */
1018 amip = find_menu_item(cw, oidx);
1019 if (amip && oidx != aidx
1020 && (oidx > topidx && oidx - topidx < wheight)) {
1021 if (how != PICK_ANY) {
1022 amip->selected = 0;
1023 amip->count = -1;
1024 reset_counting = TRUE;
1025 if (amip->canselect && amip->selector)
1026 amip->str[SOFF + 2] = '-';
1028 oidx = -1;
1030 amip = find_menu_item(cw, aidx);
1032 if (amip && amip->canselect && amip->selector
1033 && how != PICK_NONE) {
1034 oidx = aidx;
1035 if (!DoubleClick(oldsecs, oldmics, secs, mics)) {
1036 amip->selected = !amip->selected;
1037 if (counting && amip->selected) {
1038 amip->count = count;
1039 reset_counting = TRUE;
1040 amip->str[SOFF + 2] = '#';
1041 } else {
1042 amip->count = -1;
1043 reset_counting = TRUE;
1044 if (amip->canselect && amip->selector)
1045 amip->str[SOFF + 2] = '-';
1048 } else {
1049 DisplayBeep(NULL);
1050 oldsecs = 0;
1051 oldmics = 0;
1053 DisplayData(win, topidx);
1055 } else {
1056 DisplayBeep(NULL);
1058 break;
1060 if (!counting && morc == '\33') {
1061 amip = cw->menu.items;
1062 while (amip) {
1063 if (amip->canselect && amip->selector) {
1064 amip->selected = FALSE;
1065 amip->count = -1;
1066 amip->str[SOFF + 2] = '-';
1068 amip = amip->next;
1071 if (reset_counting) {
1072 count = 0;
1073 if (counting)
1074 pline("Count: 0");
1075 counting = FALSE;
1079 /* Force a cursor reposition before next message output */
1080 if (win == WIN_MESSAGE)
1081 cw->curx = -1;
1082 return (make_menu_items(cw, retmip));
1085 void
1086 ReDisplayData(win)
1087 winid win;
1089 int totalvis;
1090 register struct amii_WinDesc *cw;
1091 register struct Window *w;
1092 register struct Gadget *gd;
1093 unsigned long hidden, aidx, wheight;
1094 struct PropInfo *pip;
1096 if (win == WIN_ERR || !(cw = amii_wins[win]) || !(w = cw->win))
1097 return;
1099 for (gd = w->FirstGadget; gd && gd->GadgetID != 1;)
1100 gd = gd->NextGadget;
1102 if (!gd)
1103 return;
1105 wheight =
1106 (w->Height - w->BorderTop - w->BorderBottom - 2) / w->RPort->TxHeight;
1108 pip = (struct PropInfo *) gd->SpecialInfo;
1109 totalvis = CountLines(win);
1110 hidden = max(totalvis - wheight, 0);
1111 aidx = (((ULONG) hidden * pip->VertPot) + (MAXPOT / 2)) >> 16;
1112 clear_nhwindow(win);
1113 DisplayData(win, aidx);
1116 long
1117 FindLine(win, line)
1118 winid win;
1119 int line;
1121 int txwd;
1122 register char *t;
1123 register struct amii_WinDesc *cw;
1124 register struct Window *w;
1125 register int i, disprow, len;
1126 int col = -1;
1128 if (win == WIN_ERR || !(cw = amii_wins[win]) || !(w = cw->win)) {
1129 panic(winpanicstr, win, "No Window in FindLine");
1131 txwd = w->RPort->TxWidth;
1132 if (WINVERS_AMIV) {
1133 if (win == WIN_INVEN) {
1134 cw->cols = (w->Width - w->BorderLeft - w->BorderRight - 4
1135 - pictdata.xsize - 3) / txwd;
1136 } else
1137 cw->cols = (w->Width - w->BorderLeft - w->BorderRight - 4) / txwd;
1138 } else {
1139 cw->cols = (w->Width - w->BorderLeft - w->BorderRight - 4) / txwd;
1142 disprow = 0;
1143 for (col = i = 0; line > disprow && i < cw->maxrow; ++i) {
1144 t = cw->data[i] + SOFF;
1145 if (cw->data[i][1] >= 0) {
1146 ++disprow;
1147 col = 0;
1150 while (*t) {
1151 len = strlen(t);
1152 if (col + len > cw->cols)
1153 len = cw->cols - col;
1154 while (len > 0) {
1155 if (!t[len] || t[len] == ' ')
1156 break;
1157 --len;
1159 if (len == 0) {
1160 while (*t && *t != ' ') {
1161 t++;
1162 col++;
1164 } else {
1165 t += len;
1166 col += len;
1168 if (*t) {
1169 while (*t == ' ')
1170 ++t;
1171 col = 0;
1172 ++disprow;
1176 return (i);
1179 long
1180 CountLines(win)
1181 winid win;
1183 int txwd;
1184 amii_menu_item *mip;
1185 register char *t;
1186 register struct amii_WinDesc *cw;
1187 register struct Window *w;
1188 register int i, disprow, len;
1189 int col = -1;
1191 if (win == WIN_ERR || !(cw = amii_wins[win]) || !(w = cw->win)) {
1192 panic(winpanicstr, win, "No Window in CountLines");
1195 txwd = w->RPort->TxWidth;
1196 if (WINVERS_AMIV) {
1197 if (win == WIN_INVEN) {
1198 cw->cols = (w->Width - w->BorderLeft - w->BorderRight - 4
1199 - pictdata.xsize - 3) / txwd;
1200 } else
1201 cw->cols = (w->Width - w->BorderLeft - w->BorderRight - 4) / txwd;
1202 } else {
1203 cw->cols = (w->Width - w->BorderLeft - w->BorderRight - 4) / txwd;
1206 disprow = cw->maxrow;
1207 mip = cw->menu.items;
1208 for (col = i = 0; i < cw->maxrow; ++i) {
1209 t = cw->data[i] + SOFF;
1210 if (cw->type == NHW_MESSAGE && cw->data[i][SEL_ITEM] < 0)
1211 --disprow;
1212 else
1213 col = 0;
1214 while (*t) {
1215 len = strlen(t);
1216 if (col + len > cw->cols)
1217 len = cw->cols - col;
1218 while (len > 0) {
1219 if (!t[len] || t[len] == ' ')
1220 break;
1221 --len;
1223 if (len == 0) {
1224 while (*t && *t != ' ') {
1225 t++;
1226 col++;
1228 } else {
1229 t += len;
1230 col += len;
1232 if (*t) {
1233 while (*t == ' ')
1234 ++t;
1235 col = 0;
1236 ++disprow;
1240 return (disprow);
1243 void
1244 DisplayData(win, start)
1245 winid win;
1246 int start;
1248 int txwd;
1249 amii_menu_item *mip;
1250 register char *t;
1251 register struct amii_WinDesc *cw;
1252 register struct Window *w;
1253 register struct RastPort *rp;
1254 register int i, disprow, len, wheight;
1255 int whichcolor = -1;
1256 int col;
1258 if (win == WIN_ERR || !(cw = amii_wins[win]) || !(w = cw->win)) {
1259 panic(winpanicstr, win, "No Window in DisplayData");
1262 rp = w->RPort;
1263 SetDrMd(rp, JAM2);
1264 if (WINVERS_AMIV && win == WIN_INVEN) {
1265 wheight = (w->Height - w->BorderTop - w->BorderBottom - 2)
1266 / max(rp->TxHeight, pictdata.ysize + 3);
1267 } else {
1268 wheight =
1269 (w->Height - w->BorderTop - w->BorderBottom - 2) / rp->TxHeight;
1272 cw->rows = wheight;
1273 txwd = rp->TxWidth;
1274 if (WINVERS_AMIV) {
1275 if (win == WIN_INVEN) {
1276 cw->cols = (w->Width - w->BorderLeft - w->BorderRight - 4
1277 - pictdata.xsize - 3) / txwd;
1278 } else
1279 cw->cols = (w->Width - w->BorderLeft - w->BorderRight - 4) / txwd;
1280 } else {
1281 cw->cols = (w->Width - w->BorderLeft - w->BorderRight - 4) / txwd;
1284 /* Get the real line to display at */
1285 start = FindLine(win, start);
1287 mip = cw->menu.items;
1288 for (i = 0; mip && i < start; ++i) {
1289 mip = mip->next;
1292 /* Skip any initial response to a previous line */
1293 if (cw->type == NHW_MESSAGE && mip && mip->selected < 0)
1294 ++start;
1295 if (WINVERS_AMIV && cw->type == NHW_MESSAGE)
1296 SetAPen(rp, amii_msgAPen);
1298 for (disprow = i = start; disprow < wheight + start; i++) {
1299 /* Just erase unused lines in the window */
1300 if (i >= cw->maxrow) {
1301 if (WINVERS_AMIV && win == WIN_INVEN) {
1302 amii_curs(win, 0, disprow - start);
1303 amiga_print_glyph(win, 0, NO_GLYPH);
1305 amii_curs(win, 1, disprow - start);
1306 amii_cl_end(cw, 0);
1307 ++disprow;
1308 continue;
1311 /* Any string with a highlighted attribute goes
1312 * onto the end of the current line in the message window.
1314 if (cw->type == NHW_MESSAGE)
1315 SetAPen(rp, cw->data[i][SEL_ITEM] < 0 ? C_RED : amii_msgAPen);
1317 /* Selected text in the message window goes onto the end of the
1318 * current line */
1319 if (cw->type != NHW_MESSAGE || cw->data[i][SEL_ITEM] >= 0) {
1320 amii_curs(win, 1, disprow - start);
1321 if (WINVERS_AMIV && win == WIN_INVEN) {
1322 if (mip)
1323 amiga_print_glyph(win, 0, mip->glyph);
1324 amii_curs(win, 1, disprow - start);
1326 col = 0;
1329 /* If this entry is to be highlighted, do so */
1330 if (mip && mip->selected != 0) {
1331 if (whichcolor != 1) {
1332 SetDrMd(rp, JAM2);
1333 if (WINVERS_AMIV) {
1334 SetAPen(rp, amii_menuBPen);
1335 SetBPen(rp, C_BLUE);
1336 } else {
1337 SetAPen(rp, C_BLUE);
1338 SetBPen(rp, amii_menuAPen);
1340 whichcolor = 1;
1342 } else if (whichcolor != 2) {
1343 SetDrMd(rp, JAM2);
1344 if (cw->type == NHW_MESSAGE) {
1345 SetAPen(rp, amii_msgAPen);
1346 SetBPen(rp, amii_msgBPen);
1347 } else if (cw->type == NHW_MENU) {
1348 SetAPen(rp, amii_menuAPen);
1349 SetBPen(rp, amii_menuBPen);
1350 } else if (cw->type == NHW_TEXT) {
1351 SetAPen(rp, amii_textAPen);
1352 SetBPen(rp, amii_textBPen);
1354 whichcolor = 2;
1357 /* Next line out, wrap if too long */
1359 t = cw->data[i] + SOFF;
1360 ++disprow;
1361 col = 0;
1362 while (*t) {
1363 len = strlen(t);
1364 if (len > (cw->cols - col))
1365 len = cw->cols - col;
1366 while (len > 0) {
1367 if (!t[len] || t[len] == ' ')
1368 break;
1369 --len;
1371 if (len == 0) {
1372 Text(rp, t, cw->cols - col);
1373 while (*t && *t != ' ') {
1374 t++;
1375 col++;
1377 } else {
1378 Text(rp, t, len);
1379 t += len;
1380 col += len;
1382 amii_cl_end(cw, col);
1383 if (*t) {
1384 ++disprow;
1385 /* Stop at the bottom of the window */
1386 if (disprow > wheight + start)
1387 break;
1388 while (*t == ' ')
1389 ++t;
1390 amii_curs(win, 1, disprow - start - 1);
1391 if (mip && win == WIN_INVEN && WINVERS_AMIV) {
1392 /* Erase any previous glyph drawn here. */
1393 amiga_print_glyph(win, 0, NO_GLYPH);
1394 amii_curs(win, 1, disprow - start - 1);
1396 Text(rp, "+", 1);
1397 col = 1;
1401 if (cw->type == NHW_MESSAGE) {
1402 SetAPen(rp, amii_msgBPen);
1403 SetBPen(rp, amii_msgBPen);
1404 } else if (cw->type == NHW_MENU) {
1405 SetAPen(rp, amii_menuBPen);
1406 SetBPen(rp, amii_menuBPen);
1407 } else if (cw->type == NHW_TEXT) {
1408 SetAPen(rp, amii_textBPen);
1409 SetBPen(rp, amii_textBPen);
1411 amii_cl_end(cw, col);
1412 whichcolor = -1;
1413 if (mip)
1414 mip = mip->next;
1416 RefreshWindowFrame(w);
1417 return;
1420 void
1421 SetPropInfo(win, gad, vis, total, top)
1422 register struct Window *win;
1423 register struct Gadget *gad;
1424 register long vis, total, top;
1426 long mflags;
1427 register long hidden;
1428 register int body, pot;
1430 hidden = max(total - vis, 0);
1432 /* Force the last section to be just to the bottom */
1434 if (top > hidden)
1435 top = hidden;
1437 /* Scale the body position. */
1438 /* 2 lines overlap */
1440 if (hidden > 0 && total > 2)
1441 body = (ULONG)((vis - 2) * MAXBODY) / (total - 2);
1442 else
1443 body = MAXBODY;
1445 if (hidden > 0)
1446 pot = (ULONG)(top * MAXPOT) / hidden;
1447 else
1448 pot = 0;
1450 mflags = AUTOKNOB | FREEVERT;
1451 #ifdef INTUI_NEW_LOOK
1452 if (IntuitionBase->LibNode.lib_Version >= 37) {
1453 mflags |= PROPNEWLOOK;
1455 #endif
1457 NewModifyProp(gad, win, NULL, mflags, 0, pot, MAXBODY, body, 1);