1 /*	SCCS Id: @(#)winmenu.c	3.2	96/02/17	*/
2 /* Copyright (c) Gregg Wonderly, Naperville, Illinois,  1991,1992,1993,1996. */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 #include "NH:sys/amiga/windefs.h"
6 #include "NH:sys/amiga/winext.h"
7 #include "NH:sys/amiga/winproto.h"
8 
9 /* Start building the text for a menu */
10 void
amii_start_menu(window)11 amii_start_menu(window)
12     register winid window;
13 {
14     register int i;
15     register struct amii_WinDesc *cw;
16     register amii_menu_item *mip;
17 
18     if(window == WIN_ERR || (cw = amii_wins[window]) == NULL || cw->type != NHW_MENU)
19 	panic(winpanicstr,window, "start_menu");
20 
21     amii_clear_nhwindow(window);
22 
23     if( cw->data && ( cw->type == NHW_MESSAGE ||
24 	    cw->type == NHW_MENU || cw->type == NHW_TEXT ) )
25     {
26 	for( i = 0; i < cw->maxrow; ++i )
27 	{
28 	    if( cw->data[ i ] )
29 		free( cw->data[ i ] );
30 	}
31 	free( cw->data );
32 	cw->data = NULL;
33     }
34 
35     for( mip = cw->menu.items, i = 0; (mip = cw->menu.items) && i < cw->menu.count; ++i )
36     {
37 	cw->menu.items = mip->next;
38     	free( mip );
39     }
40 
41     cw->menu.items = 0;
42     cw->menu.count = 0;
43     cw->menu.chr = 'a';
44 
45     if( cw->morestr ) free( cw->morestr );
46     cw->morestr = NULL;
47 
48     if( window == WIN_INVEN && cw->win != NULL )
49     {
50 	if( alwaysinvent )
51 	    cw->wasup = 1;
52     }
53     cw->cury = cw->rows = cw->maxrow = cw->maxcol = 0;
54     return;
55 }
56 
57 /* Add a string to a menu */
58 void
amii_add_menu(window,glyph,id,ch,gch,attr,str,preselected)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;
68 {
69     register struct amii_WinDesc *cw;
70     amii_menu_item *mip;
71     char buf[ 4+BUFSZ ];
72 
73     if(str == NULL)return;
74 
75     if(window == WIN_ERR || (cw = amii_wins[window]) == NULL || cw->type != NHW_MENU)
76 	panic(winpanicstr,window, "add_menu");
77 
78     mip = (amii_menu_item *)alloc( sizeof( *mip ) );
79     mip->identifier = *id;
80     mip->selected = preselected;
81     mip->attr = attr;
82     mip->glyph = Is_rogue_level(&u.uz) ? NO_GLYPH : glyph;
83     mip->selector = 0;
84     mip->gselector = gch;
85     mip->count = -1;
86 
87     if (id->a_void && !ch && cw->menu.chr != 0)
88     {
89 	ch = cw->menu.chr++;
90 	if( ch == 'z' )
91 	    cw->menu.chr = 'A';
92 	if( ch == 'Z' )
93 	    cw->menu.chr = 0;
94     }
95 
96     mip->canselect = ( id->a_void != 0 );
97 
98     if( id->a_void && ch != '\0')
99     {
100 	Sprintf( buf, "%c - %s", ch, str );
101 	str = buf;
102 	mip->canselect = 1;
103     }
104 
105     mip->selector = ch;
106 
107     amii_putstr( window, attr, str );
108 
109     mip->str = cw->data[ cw->cury - 1 ];
110     cw->menu.count++;
111 
112     mip->next = NULL;
113 
114     if( cw->menu.items == 0 )
115     	cw->menu.last = cw->menu.items = mip;
116     else
117     {
118 	cw->menu.last->next = mip;
119 	cw->menu.last = mip;
120     }
121 }
122 
123 /* Done building a menu. */
124 
125 void
amii_end_menu(window,morestr)126 amii_end_menu(window,morestr)
127     register winid window;
128     register const char *morestr;
129 {
130     register struct amii_WinDesc *cw;
131 
132     if(window == WIN_ERR || (cw=amii_wins[window]) == NULL
133        || cw->type != NHW_MENU )
134 	panic(winpanicstr,window, "end_menu");
135 
136     if( morestr && *morestr )
137     {
138 	anything any;
139 #define PROMPTFIRST /* Define this to have prompt first */
140 #ifdef PROMPTFIRST
141 	amii_menu_item *mip;
142 	int i;
143 	char *t;
144 	mip = cw->menu.last;
145 #endif
146 	any.a_void = 0;
147 	amii_add_menu( window, NO_GLYPH, &any, 0, 0, ATR_NONE, morestr,
148 	   MENU_UNSELECTED);
149 #ifdef PROMPTFIRST /* Do some shuffling. Last first, push others one forward */
150 	mip->next = NULL;
151 	cw->menu.last->next = cw->menu.items;
152 	cw->menu.items = cw->menu.last;
153 	cw->menu.last = mip;
154 	t = cw->data[cw->cury-1];
155 	for (i=cw->cury-1; i>0; i--) {
156 	    cw->data[i] = cw->data[i-1];
157 	}
158 	cw->data[0] = t;
159 #endif
160     }
161 
162     /* If prompt first, don't put same string in title where in most cases
163        it's not entirely visible anyway */
164 #ifndef PROMPTFIRST
165     if( morestr )
166 	cw->morestr = strdup( morestr );
167 #endif
168 }
169 
170 /* Select something from the menu. */
171 
172 int
amii_select_menu(window,how,mip)173 amii_select_menu(window, how, mip )
174     register winid window;
175     register int how;
176     register menu_item **mip;
177 {
178     int cnt;
179     register struct amii_WinDesc *cw;
180 
181     if( window == WIN_ERR || ( cw=amii_wins[window] ) == NULL ||
182 	  cw->type != NHW_MENU )
183 	panic(winpanicstr,window, "select_menu");
184 
185     cnt = DoMenuScroll( window, 1, how, mip );
186 
187     /* This would allow the inventory window to stay open. */
188     if( !alwaysinvent || window != WIN_INVEN )
189 	dismiss_nhwindow(window);       /* Now tear it down */
190     return cnt;
191 }
192 
193 amii_menu_item *
find_menu_item(register struct amii_WinDesc * cw,int idx)194 find_menu_item( register struct amii_WinDesc *cw, int idx )
195 {
196     amii_menu_item *mip;
197     for( mip = cw->menu.items; idx > 0 && mip; mip = mip->next )
198 	--idx;
199 
200     return( mip );
201 }
202 
203 int
make_menu_items(register struct amii_WinDesc * cw,register menu_item ** rmip)204 make_menu_items( register struct amii_WinDesc *cw, register menu_item **rmip )
205 {
206     register int idx = 0;
207     register amii_menu_item *mip;
208     register menu_item *mmip;
209 
210     for( mip = cw->menu.items; mip; mip = mip->next )
211     {
212 	if( mip->selected )
213 	    ++idx;
214     }
215 
216     if( idx )
217     {
218 	mmip = *rmip = (menu_item *)alloc( idx * sizeof( *mip ) );
219 	for( mip = cw->menu.items; mip; mip = mip->next )
220 	{
221 	    if( mip->selected )
222 	    {
223 		mmip->item = mip->identifier;
224 		mmip->count = mip->count;
225 		mmip++;
226 	    }
227 	}
228 
229 	cw->mi = *rmip;
230     }
231     return( idx );
232 }
233 
234 int
DoMenuScroll(win,blocking,how,retmip)235 DoMenuScroll( win, blocking, how, retmip )
236     int win, blocking, how;
237     menu_item **retmip;
238 {
239     amii_menu_item *amip;
240     register struct Window *w;
241     register struct NewWindow *nw;
242     struct PropInfo *pip;
243     register struct amii_WinDesc *cw;
244     struct IntuiMessage *imsg;
245     struct Gadget *gd;
246     register int wheight, xsize, ysize, aredone = 0;
247     register int txwd, txh;
248     long mics, secs, class, code;
249     long oldmics = 0, oldsecs = 0;
250     int aidx, oidx, topidx, hidden;
251     int totalvis;
252     SHORT mx, my;
253     static char title[ 100 ];
254     int dosize = 1;
255     struct Screen *scrn = HackScreen;
256     int x1,x2,y1,y2;
257     long counting = FALSE, count = 0, reset_counting = FALSE;
258     char countString[32];
259 
260     if( win == WIN_ERR || ( cw = amii_wins[ win ] ) == NULL )
261 	panic(winpanicstr,win,"DoMenuScroll");
262 
263     /*  Initial guess at window sizing values */
264     txwd = txwidth;
265     if( WINVERS_AMIV )
266     {
267 	if( win == WIN_INVEN )
268 	    txh = max( txheight, pictdata.ysize + 3 ); /* interline space */
269 	else
270 	    txh = txheight; /* interline space */
271     }
272     else
273 	txh = txheight; /* interline space */
274 
275     /* Check to see if we should open the window, should need to for
276      * TEXT and MENU but not MESSAGE.
277      */
278 
279     w = cw->win;
280     topidx = 0;
281 
282     if( w == NULL )
283     {
284 
285 #ifdef  INTUI_NEW_LOOK
286 	if( IntuitionBase->LibNode.lib_Version >= 37 )
287 	{
288 	    PropScroll.Flags |= PROPNEWLOOK;
289 	}
290 #endif
291 	nw = (void *)DupNewWindow( (void *)(&new_wins[ cw->type ].newwin) );
292 	if( !alwaysinvent || win != WIN_INVEN )
293 	{
294 	    xsize = scrn->WBorLeft + scrn->WBorRight + MenuScroll.Width + 1 +
295 				(txwd * cw->maxcol);
296 	    if( WINVERS_AMIV )
297 	    {
298 		if( win == WIN_INVEN )
299 		    xsize += pictdata.xsize + 4;
300 	    }
301 	    if( xsize > amiIDisplay->xpix )
302 		xsize = amiIDisplay->xpix;
303 
304 	    /* If next row not off window, use it, else use the bottom */
305 
306 	    ysize = ( txh * cw->maxrow ) +          	  /* The text space */
307 		    HackScreen->WBorTop + txheight + 1 +  /* Top border */
308 		    HackScreen->WBorBottom + 3;     	  /* The bottom border */
309 	    if( ysize > amiIDisplay->ypix )
310 		ysize = amiIDisplay->ypix;
311 
312 	    /* Adjust the size of the menu scroll gadget */
313 
314 	    nw->TopEdge = 0;
315 	    if( cw->type == NHW_TEXT && ysize < amiIDisplay->ypix )
316 		nw->TopEdge += ( amiIDisplay->ypix - ysize ) / 2;
317 	    nw->LeftEdge = amiIDisplay->xpix - xsize;
318 	    if( cw->type == NHW_MENU )
319 	    {
320 		if( nw->LeftEdge > 10 )
321 		    nw->LeftEdge -= 10;
322 		else
323 		    nw->LeftEdge = 0;
324 		if( amiIDisplay->ypix - nw->Height > 10 )
325 		    nw->TopEdge += 10;
326 		else
327 		    nw->TopEdge = amiIDisplay->ypix - nw->Height - 1;
328 	    }
329 	    if( cw->type == NHW_TEXT && xsize < amiIDisplay->xpix )
330 		nw->LeftEdge -= ( amiIDisplay->xpix - xsize ) / 2;
331 	}
332 	else if( win == WIN_INVEN )
333 	{
334 	    struct Window *mw = amii_wins[ WIN_MAP ]->win;
335 	    struct Window *sw = amii_wins[ WIN_STATUS ]->win;
336 
337 	    xsize = scrn->WBorLeft + scrn->WBorRight + MenuScroll.Width + 1 +
338 				(txwd * cw->maxcol);
339 
340 	    /* Make space for the glyph to appear at the left of the description */
341 	    if( WINVERS_AMIV )
342 		xsize += pictdata.xsize + 4;
343 
344 	    if( xsize > amiIDisplay->xpix )
345 		xsize = amiIDisplay->xpix;
346 
347 	    /* If next row not off window, use it, else use the bottom */
348 
349 	    ysize = sw->TopEdge - (mw->TopEdge + mw->Height) - 1;
350 	    if( ysize > amiIDisplay->ypix )
351 		ysize = amiIDisplay->ypix;
352 
353 	    /* Adjust the size of the menu scroll gadget */
354 
355 	    nw->TopEdge = mw->TopEdge + mw->Height;
356 	    nw->LeftEdge = 0;
357 	}
358 	cw->newwin = (void *)nw;
359 	if( nw == NULL )
360 	    panic("No NewWindow Allocated" );
361 
362 	nw->Screen = HackScreen;
363 
364 	if( win == WIN_INVEN )
365 	{
366 	    sprintf( title, "%s the %s's Inventory", plname, pl_character );
367 	    nw->Title = title;
368 	    if( lastinvent.MaxX != 0 )
369 	    {
370 		nw->LeftEdge = lastinvent.MinX;
371 		nw->TopEdge = lastinvent.MinY;
372 		nw->Width = lastinvent.MaxX;
373 		nw->Height = lastinvent.MaxY;
374 	    }
375 	}
376 	else if( cw->morestr )
377 	    nw->Title = cw->morestr;
378 
379 	/* Adjust the window coordinates and size now that we know
380 	 * how many items are to be displayed.
381 	 */
382 
383 	if( ( xsize > amiIDisplay->xpix - nw->LeftEdge ) &&
384 	    ( xsize < amiIDisplay->xpix ) )
385 	{
386 	    nw->LeftEdge = amiIDisplay->xpix - xsize;
387 	    nw->Width = xsize;
388 	}
389 	else
390 	{
391 	    nw->Width = min( xsize, amiIDisplay->xpix - nw->LeftEdge );
392 	}
393 	nw->Height = min( ysize, amiIDisplay->ypix - nw->TopEdge );
394 
395 	if( WINVERS_AMIV || WINVERS_AMII )
396 	{
397 	    /* Make sure we are using the correct hook structure */
398 	    nw->Extension = cw->wintags;
399 	}
400 
401 	/* Now, open the window */
402 	w = cw->win = OpenShWindow( (void *)nw );
403 
404 	if( w == NULL )
405 	{
406 	    char buf[ 130 ];
407 
408 	    sprintf( buf, "No Window Opened For Menu (%d,%d,%d-%d,%d-%d)",
409 		nw->LeftEdge, nw->TopEdge, nw->Width, amiIDisplay->xpix,
410 		nw->Height, amiIDisplay->ypix );
411 	    panic( buf );
412 	}
413 
414 #ifdef HACKFONT
415 	if( TextsFont )
416 	    SetFont(w->RPort, TextsFont );
417 	else if( HackFont )
418 	    SetFont(w->RPort, HackFont );
419 #endif
420 	txwd = w->RPort->TxWidth;
421 	if( WINVERS_AMIV )
422 	{
423 	    if( win == WIN_INVEN )
424 		txh = max( w->RPort->TxHeight, pictdata.ysize + 3 ); /* interline space */
425 	    else
426 		txh = w->RPort->TxHeight; /* interline space */
427 	}
428 	else
429 	    txh = w->RPort->TxHeight; /* interline space */
430 
431 	/* subtract 2 to account for spacing away from border (1 on each side) */
432 	wheight = ( w->Height - w->BorderTop - w->BorderBottom - 2 ) / txh;
433 	if( WINVERS_AMIV )
434 	{
435 	    if( win == WIN_INVEN )
436 	    {
437 		cw->cols = ( w->Width - w->BorderLeft -
438 			    w->BorderRight - 4 - pictdata.xsize - 3 ) / txwd;
439 	    }
440 	    else
441 	    {
442 		cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd;
443 	    }
444    	}
445 	else
446 	{
447 	    cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd;
448 	}
449 	totalvis = CountLines( win );
450     }
451     else
452     {
453 	txwd = w->RPort->TxWidth;
454 	if( WINVERS_AMIV )
455 	{
456 	    if( win == WIN_INVEN )
457 		txh = max( w->RPort->TxHeight, pictdata.ysize + 3 ); /* interline space */
458 	    else
459 		txh = w->RPort->TxHeight; /* interline space */
460 	}
461 	else
462 	{
463 	    txh = w->RPort->TxHeight; /* interline space */
464 	}
465 
466 	/* subtract 2 to account for spacing away from border (1 on each side) */
467 	wheight = ( w->Height - w->BorderTop - w->BorderBottom - 2 ) / txh;
468 	if( WINVERS_AMIV )
469 	{
470 	    if( win == WIN_INVEN )
471 	    {
472 		cw->cols = ( w->Width - w->BorderLeft -
473 			    w->BorderRight - 4 - pictdata.xsize - 3) / txwd;
474 	    }
475 	    else
476 		cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd;
477 	}
478 	else
479 	{
480 	    cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd;
481 	}
482 
483 	totalvis = CountLines( win );
484 
485 	for( gd = w->FirstGadget; gd && gd->GadgetID != 1; )
486 	    gd = gd->NextGadget;
487 
488 	if( gd )
489 	{
490 	    pip = (struct PropInfo *)gd->SpecialInfo;
491 	    hidden = max( totalvis - wheight, 0 );
492 	    topidx = (((ULONG)hidden * pip->VertPot) + (MAXPOT/2)) >> 16;
493 	}
494     }
495 
496     for( gd = w->FirstGadget; gd && gd->GadgetID != 1; )
497 	gd = gd->NextGadget;
498 
499     if( !gd ) panic("Can't find scroll gadget" );
500 
501     morc = 0;
502     oidx = -1;
503 
504 #if 0
505     /* Make sure there are no selections left over from last time. */
506 /* XXX potential problem for preselection if this is really needed */
507   for( amip = cw->menu.items; amip; amip = amip->next )
508 	amip->selected = 0;
509 #endif
510 
511     DisplayData( win, topidx );
512 
513     /* Make the prop gadget the right size and place */
514 
515     SetPropInfo( w, gd, wheight, totalvis, topidx );
516     oldsecs = oldmics = 0;
517 
518     /* If window already up, don't stop to process events */
519     if( cw->wasup )
520     {
521     	aredone = 1;
522     	cw->wasup = 0;
523     }
524 
525     while( !aredone )
526     {
527 	/* Process window messages */
528 
529 	WaitPort( w->UserPort );
530 	while( imsg = (struct IntuiMessage * ) GetMsg( w->UserPort ) )
531 	{
532 	    class = imsg->Class;
533 	    code = imsg->Code;
534 	    mics = imsg->Micros;
535 	    secs = imsg->Seconds;
536 	    gd = (struct Gadget *) imsg->IAddress;
537 	    mx = imsg->MouseX;
538 	    my = imsg->MouseY;
539 
540 	    /* Only do our window or VANILLAKEY from other windows */
541 
542 	    if( imsg->IDCMPWindow != w && class != VANILLAKEY &&
543 							class != RAWKEY )
544 	    {
545 		ReplyMsg( (struct Message *) imsg );
546 		continue;
547 	    }
548 
549 	    /* Do DeadKeyConvert() stuff if RAWKEY... */
550 	    if( class == RAWKEY )
551 	    {
552 		class = VANILLAKEY;
553 		code = ConvertKey( imsg );
554 	    }
555 	    ReplyMsg( (struct Message *) imsg );
556 
557 	    switch( class )
558 	    {
559 		case NEWSIZE:
560 
561 		    /*
562 		     * Ignore every other newsize, no action needed,
563 		     * except RefreshWindowFrame() in case borders got overwritten
564 		     * for some reason. It should not happen, but ...
565 		     */
566 
567 		    if( !dosize )
568 		    {
569 			RefreshWindowFrame(w);
570 			dosize = 1;
571 			break;
572 		    }
573 
574 		    if( win == WIN_INVEN )
575 		    {
576 			lastinvent.MinX = w->LeftEdge;
577 			lastinvent.MinY = w->TopEdge;
578 			lastinvent.MaxX = w->Width;
579 			lastinvent.MaxY = w->Height;
580 		    }
581 		    else if( win == WIN_MESSAGE )
582 		    {
583 			lastmsg.MinX = w->LeftEdge;
584 			lastmsg.MinY = w->TopEdge;
585 			lastmsg.MaxX = w->Width;
586 			lastmsg.MaxY = w->Height;
587 		    }
588 
589 		    /* Find the gadget */
590 
591 		    for( gd = w->FirstGadget; gd && gd->GadgetID != 1; )
592 			gd = gd->NextGadget;
593 
594 		    if( !gd )
595 			panic("Can't find scroll gadget" );
596 
597 		    totalvis = CountLines( win );
598 		    wheight = ( w->Height - w->BorderTop -
599 						w->BorderBottom - 2) / txh;
600 		    if( WINVERS_AMIV )
601 		    {
602 			if( win == WIN_INVEN )
603 			{
604 			    cw->cols = ( w->Width - w->BorderLeft -
605 					w->BorderRight - 4 - pictdata.xsize - 3) / txwd;
606 			}
607 			else
608 			    cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd;
609 		    }
610 		    else
611 		    {
612 			cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd;
613 		    }
614 
615 		    if( wheight < 2 )
616 			wheight = 2;
617 
618 		    /*
619 		     * Clear the right side & bottom. Parts of letters are not erased by
620 		     * amii_cl_end if window shrinks and columns decrease.
621 		     */
622 
623 		    if ( WINVERS_AMII || WINVERS_AMIV ) {
624 			amii_setfillpens(w, cw->type);
625 			SetDrMd(w->RPort, JAM2);
626 			x2 = w->Width - w->BorderRight;
627 			y2 = w->Height - w->BorderBottom;
628 			x1 = x2 - w->IFont->tf_XSize - w->IFont->tf_XSize;
629 			y1 = w->BorderTop;
630 			if (x1 < w->BorderLeft)
631 			    x1 = w->BorderLeft;
632 			RectFill(w->RPort, x1, y1, x2, y2);
633 			x1 = w->BorderLeft;
634 			y1 = y1 - w->IFont->tf_YSize;
635 			RectFill(w->RPort, x1, y1, x2, y2);
636 			RefreshWindowFrame(w);
637 		    }
638 
639 		    /* Make the prop gadget the right size and place */
640 
641 		    DisplayData( win, topidx );
642 		    SetPropInfo( w, gd, wheight, totalvis, topidx );
643 
644 		    /* Force the window to a text line boundary <= to
645 		     * what the user dragged it to.  This eliminates
646 		     * having to clean things up on the bottom edge.
647 		     */
648 
649 		    SizeWindow( w, 0, ( wheight * txh) +
650 			    w->BorderTop + w->BorderBottom + 2 - w->Height );
651 
652 		    /* Don't do next NEWSIZE, we caused it */
653 		    dosize = 0;
654 		    oldsecs = oldmics = 0;
655 		    break;
656 
657 		case VANILLAKEY:
658 #define CTRL(x)     ((x)-'@')
659 		    morc = code = map_menu_cmd(code);
660 		    if (code == MENU_SELECT_ALL) {
661 			if (how == PICK_ANY) {
662 			    amip = cw->menu.items;
663 			    while (amip) {
664 				if (amip->canselect && amip->selector) {
665 				/*
666 				 * Select those yet unselected
667 				 * and apply count if necessary
668 				 */
669 				    if (!amip->selected) {
670 					amip->selected = TRUE;
671 					if (counting) {
672 					    amip->count = count;
673 					    reset_counting = TRUE;
674 					/*
675 					 * This makes the assumption that
676 					 * the string is in format "X - foo"
677 					 * with additional selecting and formatting
678 					 * data in front (size SOFF)
679 					 */
680 					    amip->str[SOFF+2] = '#';
681 					} else {
682 					    amip->count = -1;
683 					    amip->str[SOFF+2] = '-';
684 					}
685 				    }
686 				}
687 				amip=amip->next;
688 			    }
689 			    DisplayData(win, topidx);
690 			}
691 		    } else if (code == MENU_UNSELECT_ALL) {
692 			if (how == PICK_ANY) {
693 			    amip = cw->menu.items;
694 			    while (amip) {
695 				if (amip->selected) {
696 				    amip->selected = FALSE;
697 				    amip->count = -1;
698 				    amip->str[SOFF+2] = '-';
699 				}
700 				amip=amip->next;
701 			    }
702 			    DisplayData(win, topidx);
703 			}
704 		    } else if (code == MENU_INVERT_ALL) {
705 			if (how == PICK_ANY) {
706 			    amip = cw->menu.items;
707 			    while (amip) {
708 				if (amip->canselect && amip->selector) {
709 				    amip->selected = !amip->selected;
710 				    if (counting && amip->selected) {
711 					amip->count = count;
712 					amip->str[SOFF+2] = '#';
713 					reset_counting = TRUE;
714 				    } else {
715 					amip->count = -1;
716 					amip->str[SOFF+2] = '-';
717 				    }
718 				}
719 				amip=amip->next;
720 			    }
721 			    DisplayData(win, topidx);
722 			}
723 		    } else if (code == MENU_SELECT_PAGE) {
724 			if (how == PICK_ANY) {
725 			    int i = 0;
726 			    amip = cw->menu.items;
727 			    while (amip && i++ < topidx)
728 				amip = amip->next;
729 			    for (i=0;i < wheight && amip; i++, amip=amip->next) {
730 				if (amip->canselect && amip->selector) {
731 				    if (!amip->selected) {
732 					if (counting) {
733 					    amip->count = count;
734 					    reset_counting = TRUE;
735 					    amip->str[SOFF+2] = '#';
736 					} else {
737 					    amip->count = -1;
738 					    amip->str[SOFF+2] = '-';
739 					}
740 				    }
741 	 			    amip->selected = TRUE;
742 				}
743 			    }
744 			    DisplayData(win, topidx);
745 			}
746 		    } else if (code == MENU_UNSELECT_PAGE) {
747 			if (how == PICK_ANY) {
748 			    int i = 0;
749 			    amip = cw->menu.items;
750 			    while (amip && i++ < topidx)
751 				amip = amip->next;
752 			    for (i=0;i < wheight && amip; i++, amip=amip->next) {
753 				if (amip->selected) {
754 				    amip->selected = FALSE;
755 				    amip->count = -1;
756 				    amip->str[SOFF+2] = '-';
757 				}
758 			    }
759 			    DisplayData(win, topidx);
760 			}
761 		    } else if (code == MENU_INVERT_PAGE) {
762 			if (how == PICK_ANY) {
763 			    int i = 0;
764 			    amip = cw->menu.items;
765 			    while (amip && i++ < topidx)
766 				amip = amip->next;
767 			    for (i=0;i < wheight && amip; i++, amip=amip->next) {
768 				if (amip->canselect && amip->selector) {
769 				    amip->selected = !amip->selected;
770 				    if (counting && amip->selected) {
771 					amip->count = count;
772 					amip->str[SOFF+2] = '#';
773 					reset_counting = TRUE;
774 				    } else {
775 					amip->count = -1;
776 					amip->str[SOFF+2] = '-';
777 				    }
778 				}
779 			    }
780 			    DisplayData(win, topidx);
781 			}
782 		    } else if (code == MENU_SEARCH && cw->type == NHW_MENU) {
783 			if (how == PICK_ONE || how == PICK_ANY) {
784 			    char buf[BUFSZ];
785 			    amip = cw->menu.items;
786 			    amii_getlin("Search for:", buf);
787 			    if (!*buf || *buf == '\033')
788 				break;
789 			    while (amip) {
790 				if (amip->canselect && amip->selector && amip->str &&
791 				    strstri(&amip->str[SOFF], buf)) {
792 				    if (how == PICK_ONE) {
793 					amip->selected = TRUE;
794 					aredone = 1;
795 					break;
796 				    }
797 				    amip->selected = !amip->selected;
798 				    if (counting && amip->selected) {
799 					amip->count = count;
800 					reset_counting = TRUE;
801 					amip->str[SOFF+2] = '#';
802 				    } else {
803 					amip->count = -1;
804 					reset_counting = TRUE;
805 					amip->str[SOFF+2] = '-';
806 				    }
807 				}
808 				amip = amip->next;
809 			    }
810 			}
811 			DisplayData(win, topidx);
812 		    } else if (how == PICK_ANY && isdigit(code) &&
813 			       (counting || (!counting && code !='0'))) {
814 			if (count < LARGEST_INT) {
815 			    count = count*10 + (long)(code-'0');
816 			    if (count > LARGEST_INT)
817 				count = LARGEST_INT;
818 			    if (count > 0) {
819 				counting = TRUE;
820 				reset_counting = FALSE;
821 			    } else {
822 				reset_counting = TRUE;
823 			    }
824 			    sprintf(countString, "Count: %d", count);
825 			    pline(countString);
826 			}
827 		    } else if( code == CTRL('D') || code == CTRL('U') ||
828 			       code == MENU_NEXT_PAGE || code == MENU_PREVIOUS_PAGE ||
829 			       code == MENU_FIRST_PAGE || code == MENU_LAST_PAGE )
830 		    {
831 			int endcnt, i;
832 
833 			for( gd = w->FirstGadget; gd && gd->GadgetID != 1; )
834 			    gd = gd->NextGadget;
835 
836 			if( !gd )
837 			    panic("Can't find scroll gadget" );
838 
839 			endcnt = wheight; /* /2; */
840 			if( endcnt == 0 )
841 			    endcnt = 1;
842 
843 			if (code == MENU_FIRST_PAGE) {
844 			    topidx = 0;
845 			} else if (code == MENU_LAST_PAGE) {
846 			    topidx = cw->maxrow - wheight;
847 			} else for( i = 0; i < endcnt; ++i )
848 			{
849 			    if (code == CTRL('D') || code == MENU_NEXT_PAGE)
850 			    {
851 				if( topidx + wheight < cw->maxrow )
852 				    ++topidx;
853 				else
854 				    break;
855 			    }
856 			    else if (code = CTRL('U') || code == MENU_PREVIOUS_PAGE)
857 			    {
858 				if( topidx > 0 )
859 				    --topidx;
860 				else
861 				    break;
862 			    }
863 			}
864 			/* Make prop gadget the right size and place */
865 
866 			DisplayData( win, topidx );
867 			SetPropInfo( w,gd, wheight, totalvis, topidx );
868 			oldsecs = oldmics = 0;
869 		    }
870 		    else if( code == '\b' )
871 		    {
872 			for( gd = w->FirstGadget; gd && gd->GadgetID != 1; )
873 			    gd = gd->NextGadget;
874 
875 			if( !gd )
876 			    panic("Can't find scroll gadget" );
877 
878 			if( topidx - wheight - 2 < 0 )
879 			{
880 			    topidx = 0;
881 			}
882 			else
883 			{
884 			    topidx -= wheight - 2;
885 			}
886 			DisplayData( win, topidx );
887 			SetPropInfo( w, gd, wheight, totalvis, topidx );
888 			oldsecs = oldmics = 0;
889 		    }
890 		    else if( code == ' ' )
891 		    {
892 			for( gd = w->FirstGadget; gd && gd->GadgetID != 1; )
893 			    gd = gd->NextGadget;
894 
895 			if( !gd )
896 			    panic("Can't find scroll gadget" );
897 
898 			if( topidx + wheight >= cw->maxrow )
899 			{
900 			    morc = 0;
901 			    aredone = 1;
902 			}
903 			else
904 			{
905 			    /*  If there are still lines to be seen */
906 
907 			    if( cw->maxrow > topidx + wheight )
908 			    {
909 				if( wheight > 2 )
910 				    topidx += wheight - 2;
911 				else
912 				    ++topidx;
913 				DisplayData( win, topidx );
914 				SetPropInfo( w, gd, wheight,
915 						    totalvis, topidx );
916 			    }
917 			    oldsecs = oldmics = 0;
918 			}
919 		    }
920 		    else if( code == '\n' || code == '\r' )
921 		    {
922 			for( gd = w->FirstGadget; gd && gd->GadgetID != 1; )
923 			    gd = gd->NextGadget;
924 
925 			if( !gd )
926 			    panic("Can't find scroll gadget" );
927 
928 			/* If all line displayed, we are done */
929 
930 			if( topidx + wheight >= cw->maxrow )
931 			{
932 			    morc = 0;
933 			    aredone = 1;
934 			}
935 			else
936 			{
937 			    /*  If there are still lines to be seen */
938 
939 			    if( cw->maxrow > topidx + 1 )
940 			    {
941 				++topidx;
942 				DisplayData( win, topidx );
943 				SetPropInfo( w, gd, wheight,
944 						    totalvis, topidx );
945 			    }
946 			    oldsecs = oldmics = 0;
947 			}
948 		    }
949 		    else if( code == '\33' )
950 		    {
951 			if (counting) {
952 			    reset_counting = TRUE;
953 			} else {
954 			    aredone = 1;
955 			}
956 		    }
957 		    else
958 		    {
959 			int selected = FALSE;
960 			for( amip = cw->menu.items; amip; amip = amip->next )
961 			{
962 			    if( amip->selector == code )
963 			    {
964 				if( how == PICK_ONE )
965 				    aredone = 1;
966 				amip->selected = !amip->selected;
967 				if (counting && amip->selected) {
968 				    amip->count = count;
969 				    reset_counting = TRUE;
970 				    amip->str[SOFF+2] = '#';
971 				} else {
972 				    amip->count = -1;
973 				    reset_counting = TRUE;
974 				    amip->str[SOFF+2] = '-';
975 				}
976 				selected = TRUE;
977 			    } else if (amip->gselector == code )
978 			    {
979 				amip->selected = !amip->selected;
980 				if (counting) {
981 				    amip->count = count;
982 				    reset_counting = TRUE;
983 				    amip->str[SOFF+2] = '#';
984 				} else {
985 				    amip->count = -1;
986 				    reset_counting = TRUE;
987 				    amip->str[SOFF+2] = '-';
988 				}
989 				selected = TRUE;
990 			    }
991 			}
992 			if (selected)
993 			    DisplayData( win, topidx );
994 		    }
995 		    break;
996 
997 		case CLOSEWINDOW:
998 		    if( win == WIN_INVEN )
999 		    {
1000 			lastinvent.MinX = w->LeftEdge;
1001 			lastinvent.MinY = w->TopEdge;
1002 			lastinvent.MaxX = w->Width;
1003 			lastinvent.MaxY = w->Height;
1004 		    }
1005 		    else if( win == WIN_MESSAGE )
1006 		    {
1007 			lastmsg.MinX = w->LeftEdge;
1008 			lastmsg.MinY = w->TopEdge;
1009 			lastmsg.MaxX = w->Width;
1010 			lastmsg.MaxY = w->Height;
1011 		    }
1012 		    aredone = 1;
1013 		    morc = '\33';
1014 		    break;
1015 
1016 		case GADGETUP:
1017 		    if( win == WIN_MESSAGE )
1018 			aredone = 1;
1019 		    for( gd = w->FirstGadget; gd && gd->GadgetID != 1; )
1020 			gd = gd->NextGadget;
1021 
1022 		    pip = (struct PropInfo *)gd->SpecialInfo;
1023 		    totalvis = CountLines( win );
1024 		    hidden = max( totalvis - wheight, 0 );
1025 		    aidx = (((ULONG)hidden * pip->VertPot) + (MAXPOT/2)) >> 16;
1026 		    if( aidx != topidx )
1027 			DisplayData( win, topidx = aidx );
1028 		    break;
1029 
1030 		case MOUSEMOVE:
1031 		    for( gd = w->FirstGadget; gd && gd->GadgetID != 1; )
1032 			gd = gd->NextGadget;
1033 
1034 		    pip = (struct PropInfo *)gd->SpecialInfo;
1035 		    totalvis = CountLines( win );
1036 		    hidden = max( totalvis - wheight, 0 );
1037 		    aidx = (((ULONG)hidden * pip->VertPot) + (MAXPOT/2)) >> 16;
1038 		    if( aidx != topidx )
1039 			DisplayData( win, topidx = aidx );
1040 		    break;
1041 
1042 		case INACTIVEWINDOW:
1043 		    if( win == WIN_MESSAGE || ( win == WIN_INVEN && alwaysinvent ) )
1044 			aredone = 1;
1045 		    break;
1046 
1047 		case MOUSEBUTTONS:
1048 		    if( ( code == SELECTUP || code == SELECTDOWN ) &&
1049 					cw->type == NHW_MENU && how != PICK_NONE )
1050 		    {
1051 			/* Which one is the mouse pointing at? */
1052 
1053 			aidx = ( ( my - w->BorderTop - 1 ) / txh ) + topidx;
1054 
1055 			/* If different lines, don't select double click */
1056 
1057 			if( aidx != oidx )
1058 			{
1059 			    oldsecs = 0;
1060 			    oldmics = 0;
1061 			}
1062 
1063 			/* If releasing, check for double click */
1064 
1065 			if( code == SELECTUP )
1066 			{
1067 			    amip = find_menu_item( cw, aidx );
1068 			    if( aidx == oidx )
1069 			    {
1070 				if( DoubleClick( oldsecs,
1071 						    oldmics, secs, mics ) )
1072 				{
1073 				    aredone = 1;
1074 				}
1075 				oldsecs = secs;
1076 				oldmics = mics;
1077 			    }
1078 			    else
1079 			    {
1080 				amip = find_menu_item( cw, oidx );
1081 				amip->selected = 0;
1082 				amip->count = -1;
1083 				reset_counting = TRUE;
1084 				if (amip->canselect && amip->selector)
1085 				    amip->str[SOFF+2] = '-';
1086 			    }
1087 			    if (counting && amip->selected && amip->canselect && amip->selector) {
1088 				amip->count = count;
1089 				reset_counting = TRUE;
1090 				amip->str[SOFF+2] = '#';
1091 			    }
1092 			    DisplayData( win, topidx );
1093 			}
1094 			else if( aidx - topidx < wheight &&
1095 				aidx < cw->maxrow && code == SELECTDOWN )
1096 			{
1097 			    /* Remove old highlighting if visible */
1098 
1099 			    amip = find_menu_item( cw, oidx );
1100 			    if( amip && oidx != aidx &&
1101 				    ( oidx > topidx && oidx - topidx < wheight ) )
1102 			    {
1103 				if( how != PICK_ANY ) {
1104 				    amip->selected = 0;
1105 				    amip->count = -1;
1106 				    reset_counting = TRUE;
1107 				    if (amip->canselect && amip->selector)
1108 					amip->str[SOFF+2] = '-';
1109 				}
1110 				oidx = -1;
1111 			    }
1112 			    amip = find_menu_item( cw, aidx );
1113 
1114 			    if( amip && amip->canselect && amip->selector && how != PICK_NONE )
1115 			    {
1116 				oidx = aidx;
1117 				if( !DoubleClick( oldsecs,
1118 						    oldmics, secs, mics ) )
1119 				{
1120 				    amip->selected = !amip->selected;
1121 				    if (counting && amip->selected) {
1122 					amip->count = count;
1123 					reset_counting = TRUE;
1124 					amip->str[SOFF+2] = '#';
1125 				    } else {
1126 					amip->count = -1;
1127 					reset_counting = TRUE;
1128 					if (amip->canselect && amip->selector)
1129 					    amip->str[SOFF+2] = '-';
1130 				    }
1131 				}
1132 			    }
1133 			    else
1134 			    {
1135 				DisplayBeep( NULL );
1136 				oldsecs = 0;
1137 				oldmics = 0;
1138 			    }
1139 			    DisplayData( win, topidx );
1140 			}
1141 		    }
1142 		    else
1143 		    {
1144 			DisplayBeep( NULL );
1145 		    }
1146 		    break;
1147 	    }
1148 	    if (!counting && morc == '\33') {
1149 		amip = cw->menu.items;
1150 		while (amip) {
1151 		    if (amip->canselect && amip->selector) {
1152 			amip->selected = FALSE;
1153 			amip->count = -1;
1154 			amip->str[SOFF+2] = '-';
1155 		    }
1156 		    amip=amip->next;
1157 		}
1158 	    }
1159 	    if (reset_counting) {
1160 		count = 0;
1161 		if (counting)
1162 		    pline("Count: 0");
1163 		counting = FALSE;
1164 	    }
1165 	}
1166     }
1167     /* Force a cursor reposition before next message output */
1168     if( win == WIN_MESSAGE )
1169 	cw->curx = -1;
1170     return( make_menu_items( cw, retmip ) );
1171 }
1172 
1173 void
ReDisplayData(win)1174 ReDisplayData( win )
1175     winid win;
1176 {
1177     int totalvis;
1178     register struct amii_WinDesc *cw;
1179     register struct Window *w;
1180     register struct Gadget *gd;
1181     unsigned long hidden, aidx, wheight;
1182     struct PropInfo *pip;
1183 
1184     if( win == WIN_ERR || !(cw = amii_wins[win]) || !( w = cw->win ) )
1185 	return;
1186 
1187     for( gd = w->FirstGadget; gd && gd->GadgetID != 1; )
1188 	gd = gd->NextGadget;
1189 
1190     if( !gd )
1191 	return;
1192 
1193     wheight = (w->Height - w->BorderTop - w->BorderBottom-2)/w->RPort->TxHeight;
1194 
1195     pip = (struct PropInfo *)gd->SpecialInfo;
1196     totalvis = CountLines( win );
1197     hidden = max( totalvis - wheight, 0 );
1198     aidx = (((ULONG)hidden * pip->VertPot) + (MAXPOT/2)) >> 16;
1199     clear_nhwindow( win );
1200     DisplayData( win, aidx );
1201 }
1202 
1203 long
FindLine(win,line)1204 FindLine( win, line )
1205     winid win;
1206     int line;
1207 {
1208     int txwd;
1209     register char *t;
1210     register struct amii_WinDesc *cw;
1211     register struct Window *w;
1212     register int i, disprow, len;
1213     int col = -1;
1214 
1215     if( win == WIN_ERR || !(cw = amii_wins[win]) || !( w = cw->win ) )
1216     {
1217 	panic( winpanicstr, win, "No Window in FindLine" );
1218     }
1219     txwd = w->RPort->TxWidth;
1220     if( WINVERS_AMIV )
1221     {
1222 	if( win == WIN_INVEN )
1223 	{
1224 	    cw->cols = ( w->Width - w->BorderLeft -
1225 			w->BorderRight - 4 - pictdata.xsize - 3) / txwd;
1226 	}
1227 	else
1228 	    cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd;
1229     }
1230     else
1231     {
1232 	cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd;
1233     }
1234 
1235     disprow = 0;
1236     for( col = i = 0; line > disprow && i < cw->maxrow; ++i )
1237     {
1238 	t = cw->data[ i ] + SOFF;
1239 	if( cw->data[i][1] >= 0 )
1240 	{
1241 	    ++disprow;
1242 	    col = 0;
1243 	}
1244 
1245 	while( *t )
1246 	{
1247 	    len = strlen( t );
1248 	    if( col + len > cw->cols )
1249 		len = cw->cols - col;
1250 	    while( len > 0 )
1251 	    {
1252 	    	if( !t[len] || t[len] == ' ' )
1253 		    break;
1254 	    	--len;
1255 	    }
1256 	    if( len == 0 ) {
1257 		while ( *t && *t != ' ') {
1258 		    t++; col++;
1259 		}
1260 	    } else {
1261 		t += len;
1262 		col += len;
1263 	    }
1264 	    if( *t )
1265 	    {
1266 		while( *t == ' ' )
1267 		    ++t;
1268 		col = 0;
1269 		++disprow;
1270 	    }
1271 	}
1272     }
1273     return( i );
1274 }
1275 
1276 long
CountLines(win)1277 CountLines( win )
1278     winid win;
1279 {
1280     int txwd;
1281     amii_menu_item *mip;
1282     register char *t;
1283     register struct amii_WinDesc *cw;
1284     register struct Window *w;
1285     register int i, disprow, len;
1286     int col = -1;
1287 
1288     if( win == WIN_ERR || !(cw = amii_wins[win]) || !( w = cw->win ) )
1289     {
1290 	panic( winpanicstr, win, "No Window in CountLines" );
1291     }
1292 
1293     txwd = w->RPort->TxWidth;
1294     if( WINVERS_AMIV )
1295     {
1296 	if( win == WIN_INVEN )
1297 	{
1298 	    cw->cols = ( w->Width - w->BorderLeft -
1299 			w->BorderRight - 4 - pictdata.xsize - 3) / txwd;
1300 	}
1301 	else
1302 	    cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd;
1303     }
1304     else
1305     {
1306 	cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd;
1307     }
1308 
1309     disprow = cw->maxrow;
1310     mip = cw->menu.items;
1311     for( col = i = 0; i < cw->maxrow; ++i )
1312     {
1313 	t = cw->data[ i ] + SOFF;
1314 	if( cw->type == NHW_MESSAGE && cw->data[ i ][ SEL_ITEM ] < 0 )
1315 	    --disprow;
1316 	else
1317 	    col = 0;
1318 	while( *t )
1319 	{
1320 	    len = strlen( t );
1321 	    if( col + len > cw->cols )
1322 		len = cw->cols - col;
1323 	    while( len > 0 )
1324 	    {
1325 	    	if( !t[len] || t[len] == ' ' )
1326 		    break;
1327 	    	--len;
1328 	    }
1329 	    if( len == 0 ) {
1330 		while ( *t && *t != ' ') {
1331 		    t++; col++;
1332 		}
1333 	    } else {
1334 		t += len;
1335 		col += len;
1336 	    }
1337 	    if( *t )
1338 	    {
1339 		while( *t == ' ' )
1340 		    ++t;
1341 		col = 0;
1342 		++disprow;
1343 	    }
1344 	}
1345     }
1346     return( disprow );
1347 }
1348 
1349 void
DisplayData(win,start)1350 DisplayData( win, start )
1351     winid win;
1352     int start;
1353 {
1354     int txwd;
1355     amii_menu_item *mip;
1356     register char *t;
1357     register struct amii_WinDesc *cw;
1358     register struct Window *w;
1359     register struct RastPort *rp;
1360     register int i, disprow, len, wheight;
1361     int whichcolor = -1;
1362     int col;
1363 
1364     if( win == WIN_ERR || !(cw = amii_wins[win]) || !( w = cw->win ) )
1365     {
1366 	panic( winpanicstr, win, "No Window in DisplayData" );
1367     }
1368 
1369     rp = w->RPort;
1370     SetDrMd( rp, JAM2 );
1371     if( WINVERS_AMIV && win == WIN_INVEN )
1372     {
1373 	wheight = ( w->Height - w->BorderTop - w->BorderBottom - 2 ) /
1374 		    max( rp->TxHeight, pictdata.ysize + 3 );
1375     }
1376     else
1377     {
1378 	wheight = ( w->Height - w->BorderTop - w->BorderBottom - 2 ) /
1379 		    rp->TxHeight;
1380     }
1381 
1382     cw->rows = wheight;
1383     txwd = rp->TxWidth;
1384     if( WINVERS_AMIV )
1385     {
1386 	if( win == WIN_INVEN )
1387 	{
1388 	    cw->cols = ( w->Width - w->BorderLeft -
1389 			w->BorderRight - 4 - pictdata.xsize - 3) / txwd;
1390 	}
1391 	else
1392 	    cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd;
1393     }
1394     else
1395     {
1396 	cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd;
1397     }
1398 
1399     /* Get the real line to display at */
1400     start = FindLine( win, start );
1401 
1402     mip = cw->menu.items;
1403     for( i = 0; mip && i < start; ++i )
1404     {
1405 	mip = mip->next;
1406     }
1407 
1408     /* Skip any initial response to a previous line */
1409     if( cw->type == NHW_MESSAGE && mip && mip->selected < 0 )
1410 	++start;
1411     if( WINVERS_AMIV && cw->type == NHW_MESSAGE )
1412 	SetAPen( rp, amii_msgAPen );
1413 
1414     for( disprow = i = start; disprow < wheight + start; i++ )
1415     {
1416 	/* Just erase unused lines in the window */
1417     	if( i >= cw->maxrow )
1418     	{
1419 	    if (WINVERS_AMIV && win == WIN_INVEN) {
1420 		amii_curs( win, 0, disprow - start );
1421 		amiga_print_glyph( win, 0, NO_GLYPH);
1422 	    }
1423 	    amii_curs( win, 1, disprow - start );
1424 	    amii_cl_end( cw, 0 );
1425 	    ++disprow;
1426 	    continue;
1427     	}
1428 
1429 	/* Any string with a highlighted attribute goes
1430 	 * onto the end of the current line in the message window.
1431 	 */
1432 	if( cw->type == NHW_MESSAGE )
1433 	    SetAPen( rp, cw->data[ i ][ SEL_ITEM ] < 0 ? C_RED : amii_msgAPen );
1434 
1435 	/* Selected text in the message window goes onto the end of the current line */
1436 	if( cw->type != NHW_MESSAGE || cw->data[ i ][ SEL_ITEM ] >= 0 )
1437 	{
1438 	    amii_curs( win, 1, disprow - start );
1439 	    if( WINVERS_AMIV && win == WIN_INVEN )
1440 	    {
1441 		if( mip )
1442 		    amiga_print_glyph( win, 0, mip->glyph );
1443 		amii_curs( win, 1, disprow - start );
1444 	    }
1445 	    col = 0;
1446 	}
1447 
1448 	/* If this entry is to be highlighted, do so */
1449 	if( mip && mip->selected != 0 )
1450 	{
1451 	    if( whichcolor != 1 )
1452 	    {
1453 		SetDrMd( rp, JAM2 );
1454 		if( WINVERS_AMIV )
1455 		{
1456 		    SetAPen( rp, amii_menuBPen );
1457 		    SetBPen( rp, C_BLUE );
1458 		}
1459 		else
1460 		{
1461 		    SetAPen( rp, C_BLUE );
1462 		    SetBPen( rp, amii_menuAPen );
1463 		}
1464 		whichcolor = 1;
1465 	    }
1466 	}
1467 	else if( whichcolor != 2 )
1468 	{
1469 	    SetDrMd( rp, JAM2 );
1470 	    if( cw->type == NHW_MESSAGE )
1471 	    {
1472 		SetAPen( rp, amii_msgAPen );
1473 		SetBPen( rp, amii_msgBPen );
1474 	    }
1475 	    else if( cw->type == NHW_MENU )
1476 	    {
1477 		SetAPen( rp, amii_menuAPen );
1478 		SetBPen( rp, amii_menuBPen );
1479 	    }
1480 	    else if( cw->type == NHW_TEXT )
1481 	    {
1482 		SetAPen( rp, amii_textAPen );
1483 		SetBPen( rp, amii_textBPen );
1484 	    }
1485 	    whichcolor = 2;
1486 	}
1487 
1488 	/* Next line out, wrap if too long */
1489 
1490 	t = cw->data[ i ] + SOFF;
1491 	++disprow;
1492 	col = 0;
1493 	while( *t )
1494 	{
1495 	    len = strlen( t );
1496 	    if( len > (cw->cols - col) )
1497 		len = cw->cols - col;
1498 	    while( len > 0 )
1499 	    {
1500 	    	if( !t[len] || t[len] == ' ' )
1501 		    break;
1502 	    	--len;
1503 	    }
1504 	    if( len == 0 ) {
1505 		Text( rp, t, cw->cols - col );
1506 		while ( *t && *t != ' ') {
1507 		    t++; col++;
1508 		}
1509 	    } else {
1510 		Text( rp, t, len );
1511 		t += len;
1512 		col += len;
1513 	    }
1514 	    amii_cl_end( cw, col );
1515 	    if( *t )
1516 	    {
1517 		++disprow;
1518 		/* Stop at the bottom of the window */
1519 		if( disprow > wheight + start )
1520 		    break;
1521 		while( *t == ' ' )
1522 		    ++t;
1523 		amii_curs( win, 1, disprow - start - 1 );
1524 		if( mip && win == WIN_INVEN && WINVERS_AMIV )
1525 		{
1526 		    /* Erase any previous glyph drawn here. */
1527 		    amiga_print_glyph( win, 0, NO_GLYPH );
1528 		    amii_curs( win, 1, disprow - start - 1 );
1529 		}
1530 		Text( rp, "+", 1 );
1531 		col = 1;
1532 	    }
1533 	}
1534 
1535 	if( cw->type == NHW_MESSAGE )
1536 	{
1537 	    SetAPen( rp, amii_msgBPen );
1538 	    SetBPen( rp, amii_msgBPen );
1539 	}
1540 	else if( cw->type == NHW_MENU )
1541 	{
1542 	    SetAPen( rp, amii_menuBPen );
1543 	    SetBPen( rp, amii_menuBPen );
1544 	}
1545 	else if( cw->type == NHW_TEXT )
1546 	{
1547 	    SetAPen( rp, amii_textBPen );
1548 	    SetBPen( rp, amii_textBPen );
1549 	}
1550  	amii_cl_end( cw, col );
1551 	whichcolor = -1;
1552 	if( mip ) mip = mip->next;
1553     }
1554     RefreshWindowFrame(w);
1555     return;
1556 }
1557 
SetPropInfo(win,gad,vis,total,top)1558 void SetPropInfo( win, gad, vis, total, top )
1559     register struct Window *win;
1560     register struct Gadget *gad;
1561     register long vis, total, top;
1562 {
1563     long mflags;
1564     register long hidden;
1565     register int body, pot;
1566 
1567     hidden = max( total-vis, 0 );
1568 
1569     /* Force the last section to be just to the bottom */
1570 
1571     if( top > hidden )
1572 	top = hidden;
1573 
1574     /* Scale the body position. */
1575     /* 2 lines overlap */
1576 
1577     if( hidden > 0 && total > 2)
1578 	body = (ULONG) ((vis - 2) * MAXBODY) / (total - 2);
1579     else
1580 	body = MAXBODY;
1581 
1582     if( hidden > 0 )
1583 	pot = (ULONG) (top * MAXPOT) / hidden;
1584     else
1585 	pot = 0;
1586 
1587     mflags = AUTOKNOB|FREEVERT;
1588 #ifdef  INTUI_NEW_LOOK
1589     if( IntuitionBase->LibNode.lib_Version >= 37 )
1590     {
1591 	mflags |= PROPNEWLOOK;
1592     }
1593 #endif
1594 
1595     NewModifyProp( gad, win, NULL,
1596 			    mflags, 0, pot, MAXBODY, body, 1 );
1597 }
1598