OSDN Git Service

no bone
[nethackexpress/trunk.git] / sys / amiga / winfuncs.c
1 /*    SCCS Id: @(#)winfuncs.c    3.1    2000/01/12 */
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 #include "patchlevel.h"
9
10 extern struct TagItem scrntags[];
11
12 static BitMapHeader amii_bmhd;
13 static void cursor_common(struct RastPort *, int, int);
14
15 #ifdef  CLIPPING
16 int CO, LI;
17
18 /* Changing clipping region, skip clear of screen in overview window. */
19 int reclip;
20
21 /* Must be set to at least two or you will get stuck! */
22 int xclipbord = 4, yclipbord = 2;
23 #endif
24
25 int mxsize, mysize;
26 struct Rectangle amii_oldover;
27 struct Rectangle amii_oldmsg;
28
29 extern struct TextFont *RogueFont;
30
31 int amii_msgAPen;
32 int amii_msgBPen;
33 int amii_statAPen;
34 int amii_statBPen;
35 int amii_menuAPen;
36 int amii_menuBPen;
37 int amii_textAPen;
38 int amii_textBPen;
39 int amii_otherAPen;
40 int amii_otherBPen;
41 long amii_libvers = LIBRARY_FONT_VERSION;
42
43 void
44 ami_wininit_data( void )
45 {
46     extern unsigned short amii_init_map[ AMII_MAXCOLORS ];
47     extern unsigned short amiv_init_map[ AMII_MAXCOLORS ];
48     if( !WINVERS_AMIV )
49     {
50 # ifdef TEXTCOLOR
51         amii_numcolors = 8;
52 # else
53         amii_numcolors = 4;
54 # endif
55         amii_defpens[ 0 ] = C_BLACK;    /* DETAILPEN        */
56         amii_defpens[ 1 ] = C_BLUE;     /* BLOCKPEN         */
57         amii_defpens[ 2 ] = C_BROWN;    /* TEXTPEN          */
58         amii_defpens[ 3 ] = C_WHITE;    /* SHINEPEN         */
59         amii_defpens[ 4 ] = C_BLUE;     /* SHADOWPEN        */
60         amii_defpens[ 5 ] = C_CYAN;     /* FILLPEN          */
61         amii_defpens[ 6 ] = C_WHITE;    /* FILLTEXTPEN      */
62         amii_defpens[ 7 ] = C_CYAN;     /* BACKGROUNDPEN    */
63         amii_defpens[ 8 ] = C_RED;      /* HIGHLIGHTTEXTPEN */
64         amii_defpens[ 9 ] = C_WHITE;    /* BARDETAILPEN     */
65         amii_defpens[ 10 ] = C_CYAN;    /* BARBLOCKPEN      */
66         amii_defpens[ 11 ] = C_BLUE;    /* BARTRIMPEN       */
67         amii_defpens[ 12 ] = (unsigned short) ~0;
68
69         amii_msgAPen = C_WHITE;
70         amii_msgBPen = C_BLACK;
71         amii_statAPen = C_WHITE;
72         amii_statBPen = C_BLACK;
73         amii_menuAPen = C_WHITE;
74         amii_menuBPen = C_BLACK;
75         amii_textAPen = C_WHITE;
76         amii_textBPen = C_BLACK;
77         amii_otherAPen = C_RED;
78         amii_otherBPen = C_BLACK;
79
80         mxsize = 8;
81         mysize = 8;
82
83         amii_libvers = LIBRARY_FONT_VERSION;
84         memcpy( amii_initmap, amii_init_map, sizeof( amii_initmap ) );
85     }
86     else
87     {
88         mxsize = 16;
89         mysize = 16;
90
91         amii_numcolors = 16;
92
93         amii_defpens[ 0 ] = C_BLACK;    /* DETAILPEN        */
94         amii_defpens[ 1 ] = C_WHITE;    /* BLOCKPEN         */
95         amii_defpens[ 2 ] = C_BLACK;    /* TEXTPEN          */
96         amii_defpens[ 3 ] = C_CYAN;     /* SHINEPEN         */
97         amii_defpens[ 4 ] = C_BLUE;     /* SHADOWPEN        */
98         amii_defpens[ 5 ] = C_GREYBLUE; /* FILLPEN          */
99         amii_defpens[ 6 ] = C_LTGREY;   /* FILLTEXTPEN      */
100         amii_defpens[ 7 ] = C_GREYBLUE; /* BACKGROUNDPEN    */
101         amii_defpens[ 8 ] = C_RED;      /* HIGHLIGHTTEXTPEN */
102         amii_defpens[ 9 ] = C_WHITE;    /* BARDETAILPEN     */
103         amii_defpens[ 10] = C_GREYBLUE; /* BARBLOCKPEN      */
104         amii_defpens[ 11] = C_BLUE;     /* BARTRIMPEN       */
105         amii_defpens[ 12] = (unsigned short) ~0;
106
107         amii_msgAPen = C_WHITE;
108         amii_msgBPen = C_GREYBLUE;
109         amii_statAPen = C_WHITE;
110         amii_statBPen = C_GREYBLUE;
111         amii_menuAPen = C_BLACK;
112         amii_menuBPen = C_LTGREY;
113         amii_textAPen = C_BLACK;
114         amii_textBPen = C_LTGREY;
115         amii_otherAPen = C_RED;
116         amii_otherBPen = C_BLACK;
117         amii_libvers = LIBRARY_TILE_VERSION;
118
119         memcpy( amii_initmap, amiv_init_map, sizeof( amii_initmap ) );
120     }
121 #ifdef OPT_DISPMAP
122     dispmap_sanity();
123 #endif
124     memcpy(flags.amii_dripens,amii_defpens,sizeof(flags.amii_dripens));
125 }
126
127 # ifdef INTUI_NEW_LOOK
128 struct Hook SM_FilterHook;
129 struct Hook fillhook;
130 struct TagItem wintags[] =
131 {
132         { WA_BackFill, (ULONG)&fillhook },
133         { WA_PubScreenName, (ULONG)"NetHack" },
134         { TAG_END, 0 },
135 };
136 # endif
137
138 void
139 amii_destroy_nhwindow(win)      /* just hide */
140     register winid win;
141 {
142     int i;
143     int type;
144     register struct amii_WinDesc *cw;
145
146     if( win == WIN_ERR || ( cw = amii_wins[win] ) == NULL )
147     {
148         panic(winpanicstr,win,"destroy_nhwindow");
149     }
150
151     if( WINVERS_AMIV )
152     {
153         if( cw->type == NHW_MAP )
154         {
155             /* If inventory is up, close it now, it will be freed later */
156             if( alwaysinvent && WIN_INVEN != WIN_ERR &&
157                                 amii_wins[ WIN_INVEN ] &&
158                                 amii_wins[ WIN_INVEN ]->win )
159             {
160                 dismiss_nhwindow( WIN_INVEN );
161             }
162
163             /* Tear down overview window if it is up */
164             if( WIN_OVER != WIN_ERR )
165             {
166                 amii_destroy_nhwindow( WIN_OVER );
167                 WIN_OVER = WIN_ERR;
168             }
169         }
170         else if( cw->type == NHW_OVER )
171         {
172             struct Window *w = amii_wins[ WIN_OVER ]->win;
173             amii_oldover.MinX = w->LeftEdge;
174             amii_oldover.MinY = w->TopEdge;
175             amii_oldover.MaxX = w->Width;
176             amii_oldover.MaxY = w->Height;
177
178             if( WIN_MESSAGE != WIN_ERR && amii_wins[ WIN_MESSAGE ] )
179             {
180                 w = amii_wins[ WIN_MESSAGE ]->win;
181                 amii_oldmsg.MinX = w->LeftEdge;
182                 amii_oldmsg.MinY = w->TopEdge;
183                 amii_oldmsg.MaxX = w->Width;
184                 amii_oldmsg.MaxY = w->Height;
185                 SizeWindow( amii_wins[ WIN_MESSAGE ]->win,
186                         (amiIDisplay->xpix -
187                         amii_wins[ WIN_MESSAGE ]->win->LeftEdge) -
188                         amii_wins[ WIN_MESSAGE ]->win->Width,
189                         0 );
190             }
191         }
192     }
193
194     /* Tear down the Intuition stuff */
195     dismiss_nhwindow(win);
196     type = cw->type;
197
198     if( cw->resp ) {
199         free( cw->resp );
200         cw->resp = NULL;
201     }
202     if( cw->canresp ) {
203         free( cw->canresp );
204         cw->canresp = NULL;
205     }
206     if( cw->morestr ) {
207         free( cw->morestr );
208         cw->morestr = NULL;
209     }
210     if( cw->hook ) {
211         free( cw->hook );
212         cw->hook = NULL;
213     }
214
215     if( cw->data && ( cw->type == NHW_MESSAGE ||
216                             cw->type == NHW_MENU || cw->type == NHW_TEXT ) )
217     {
218         for( i = 0; i < cw->maxrow; ++i )
219         {
220             if( cw->data[ i ] )
221                 free( cw->data[ i ] );
222         }
223         free( cw->data );
224     }
225
226     free( cw );
227     amii_wins[win] = NULL;
228
229     /* Set globals to WIN_ERR for known one-of-a-kind windows. */
230     if( win == WIN_MAP) WIN_MAP = WIN_ERR;
231     else if( win == WIN_STATUS) WIN_STATUS = WIN_ERR;
232     else if( win == WIN_MESSAGE) WIN_MESSAGE = WIN_ERR;
233     else if( win == WIN_INVEN) WIN_INVEN = WIN_ERR;
234
235 }
236
237 #ifdef INTUI_NEW_LOOK
238 struct FillParams
239 {
240         struct Layer *layer;
241         struct Rectangle bounds;
242         WORD offsetx;
243         WORD offsety;
244 };
245
246 #ifdef __GNUC__
247 #ifdef __PPC__
248 void PPC_LayerFillHook(void);
249 struct EmulLibEntry LayerFillHook = {TRAP_LIB, 0, (void (*)(void)) PPC_LayerFillHook};
250 void PPC_LayerFillHook(void) {
251    struct Hook *hk = (struct Hook*)REG_A0;
252    struct RastPort *rp = (struct RastPort *)REG_A2;
253    struct FillParams *fp = (struct FillParams*)REG_A1;
254 #else
255 void LayerFillHook(void) {
256     register struct Hook *hk asm("a0");
257     register struct RastPort *rp asm("a2");
258     register struct FillParams *fp asm("a1");
259 #endif
260 #else
261 void
262 #ifndef _DCC
263 __interrupt
264 #endif
265 __saveds __asm LayerFillHook(
266     register __a0 struct Hook *hk,
267     register __a2 struct RastPort *rp,
268     register __a1 struct FillParams *fp )
269 {
270 #endif
271
272     register long x, y, xmax, ymax;
273     register int apen;
274     struct RastPort rptmp;
275
276     memcpy(&rptmp, rp, sizeof(struct RastPort));
277     rptmp.Layer = NULL;
278
279     switch( (int)hk->h_Data )
280     {
281     case NHW_STATUS:
282         apen = amii_statBPen;
283         break;
284     case NHW_MESSAGE:
285         apen = amii_msgBPen;
286         break;
287     case NHW_TEXT:
288         apen = amii_textBPen;
289         break;
290     case NHW_MENU:
291         apen = amii_menuBPen;
292         break;
293     case -2:
294         apen = amii_otherBPen;
295         break;
296     case NHW_BASE:
297     case NHW_MAP:
298     case NHW_OVER:
299     default:
300         apen = C_BLACK;
301         break;
302     }
303
304     x = fp->bounds.MinX;
305     y = fp->bounds.MinY;
306     xmax = fp->bounds.MaxX;
307     ymax = fp->bounds.MaxY;
308
309     SetAPen(&rptmp, apen);
310     SetBPen(&rptmp, apen);
311     SetDrMd(&rptmp, JAM2);
312     RectFill(&rptmp, x, y, xmax, ymax);
313 }
314 #endif
315
316
317 amii_create_nhwindow(type)
318     register int type;
319 {
320     register struct Window *w = NULL;
321     register struct NewWindow *nw = NULL;
322     register struct amii_WinDesc *wd = NULL;
323     struct Window *mapwin = NULL, *stwin = NULL, *msgwin = NULL;
324     register int newid;
325     int maph, stath, scrfontysize;
326
327     scrfontysize = HackScreen->Font->ta_YSize;
328
329     /*
330      * Initial mapwindow height, this might change later in tilemode
331      * and low screen
332      */
333     maph = ( 21 * mxsize ) + 2 + (bigscreen ?
334         HackScreen->WBorTop + HackScreen->WBorBottom + scrfontysize + 1 : 0);
335
336     /* Status window height, avoids having to calculate many times */
337     stath = txheight * 2 + 2 + (WINVERS_AMIV || bigscreen ?
338         HackScreen->WBorTop + HackScreen->WBorBottom +
339         ( bigscreen ? scrfontysize + 1 : 0 ) : 0);
340
341     if( WIN_STATUS != WIN_ERR && amii_wins[ WIN_STATUS ] )
342         stwin = amii_wins[ WIN_STATUS ]->win;
343
344     if( WIN_MESSAGE != WIN_ERR && amii_wins[ WIN_MESSAGE ] )
345         msgwin = amii_wins[ WIN_MESSAGE ]->win;
346
347     if( WIN_MAP != WIN_ERR && amii_wins[ WIN_MAP ] )
348         mapwin = amii_wins[ WIN_MAP ]->win;
349
350     /* Create Port anytime that we need it */
351
352     if( HackPort == NULL )
353     {
354         HackPort = CreateMsgPort();
355         if( !HackPort )
356             panic( "no memory for msg port" );
357     }
358
359     nw = &new_wins[ type ].newwin;
360     nw->Width = amiIDisplay->xpix;
361     nw->Screen = HackScreen;
362
363     if( WINVERS_AMIV )
364     {
365         nw->DetailPen = C_WHITE;
366         nw->BlockPen = C_GREYBLUE;
367     }
368     else
369     {
370         nw->DetailPen = C_WHITE;
371         nw->BlockPen = C_BLACK;
372     }
373
374     if ( type == NHW_BASE ) {
375         nw->LeftEdge = 0;
376         nw->TopEdge = HackScreen->BarHeight+1;
377         nw->Width = HackScreen->Width;
378         nw->Height = HackScreen->Height - nw->TopEdge;
379     } else if( !WINVERS_AMIV && type == NHW_MAP ) {
380         nw->LeftEdge = 0;
381         nw->Height = maph;
382
383         if( msgwin && stwin ) {
384             nw->TopEdge = stwin->TopEdge - maph;
385         } else {
386             panic( "msgwin and stwin must open before map" );
387         }
388         if (nw->TopEdge < 0)
389             panic( "Too small screen to fit map" );
390     }
391     else if( type == NHW_MAP && WINVERS_AMIV )
392     {
393         struct Window *w;
394
395         w = amii_wins[ WIN_MESSAGE ]->win;
396         nw->LeftEdge = 0;
397         nw->TopEdge = w->TopEdge + w->Height;
398         nw->Width = amiIDisplay->xpix - nw->LeftEdge;
399
400         w = amii_wins[ WIN_STATUS ]->win;
401         nw->Height = w->TopEdge - nw->TopEdge;
402         nw->MaxHeight = 0xffff;
403         nw->MaxWidth = 0xffff;
404
405         if( nw->TopEdge + nw->Height > amiIDisplay->ypix - 1 )
406             nw->Height = amiIDisplay->ypix - nw->TopEdge - 1;
407     }
408     else if( type == NHW_STATUS )
409     {
410         if( !WINVERS_AMIV && ( WIN_MAP != WIN_ERR && amii_wins[ WIN_MAP ] ) )
411             w = amii_wins[ WIN_MAP ]->win;
412         else if( WIN_BASE != WIN_ERR && amii_wins[ WIN_BASE ] )
413             w = amii_wins[ WIN_BASE ]->win;
414         else
415             panic( "No window to base STATUS location from" );
416
417         nw->Height = stath;
418         nw->TopEdge = amiIDisplay->ypix - nw->Height;
419         nw->LeftEdge = w->LeftEdge;
420
421         if( nw->LeftEdge + nw->Width >= amiIDisplay->xpix )
422             nw->LeftEdge = 0;
423
424         if( nw->Width >= amiIDisplay->xpix - nw->LeftEdge )
425             nw->Width = amiIDisplay->xpix - nw->LeftEdge;
426     }
427     else if( WINVERS_AMIV && type == NHW_OVER )
428     {
429         nw->Flags |= WINDOWSIZING|WINDOWDRAG|WINDOWCLOSE;
430         nw->IDCMPFlags |= CLOSEWINDOW;
431         /* Bring up window as half the width of the message window, and make
432          * the message window change to one half the width...
433          */
434         if( amii_oldover.MaxX != 0 )
435         {
436             nw->LeftEdge = amii_oldover.MinX;
437             nw->TopEdge = amii_oldover.MinY;
438             nw->Width = amii_oldover.MaxX;
439             nw->Height = amii_oldover.MaxY;
440             ChangeWindowBox( amii_wins[ WIN_MESSAGE ]->win,
441                         amii_oldmsg.MinX, amii_oldmsg.MinY,
442                         amii_oldmsg.MaxX, amii_oldmsg.MaxY );
443         }
444         else
445         {
446             nw->LeftEdge = (amii_wins[ WIN_MESSAGE ]->win->Width*4)/9;
447             nw->TopEdge = amii_wins[ WIN_MESSAGE ]->win->TopEdge;
448             nw->Width = amiIDisplay->xpix - nw->LeftEdge;
449             nw->Height = amii_wins[ WIN_MESSAGE ]->win->Height;
450             SizeWindow( amii_wins[ WIN_MESSAGE ]->win,
451                     nw->LeftEdge - amii_wins[ WIN_MESSAGE ]->win->Width, 0 );
452         }
453     }
454     else if( type == NHW_MESSAGE )
455     {
456         if( !WINVERS_AMIV && ( WIN_MAP != WIN_ERR && amii_wins[ WIN_MAP ] ) )
457             w = amii_wins[ WIN_MAP ]->win;
458         else if( WIN_BASE != WIN_ERR && amii_wins[ WIN_BASE ] )
459             w = amii_wins[ WIN_BASE ]->win;
460         else
461             panic( "No window to base STATUS location from" );
462
463         nw->TopEdge = bigscreen ? HackScreen->BarHeight+1 : 0;
464
465         /* Assume highest possible message window */
466         nw->Height = HackScreen->Height - nw->TopEdge - maph - stath;
467
468         /* In tilemode we can cope with this */
469         if (WINVERS_AMIV && nw->Height < 0)
470             nw->Height = 0;
471
472         /* If in fontmode messagewindow is too small, open it with 3 lines
473            and overlap it with map */
474         if (nw->Height < txheight+2) {
475             nw->Height = txheight*4 + 3 + HackScreen->WBorTop + HackScreen->WBorBottom;
476         }
477
478         if ((nw->Height-2)/txheight < 3) {
479             scrollmsg = 0;
480             nw->Title = 0;
481         } else {
482             nw->FirstGadget = &MsgScroll;
483             nw->Flags |= WINDOWSIZING|WINDOWDRAG;
484             nw->Flags &= ~BORDERLESS;
485
486             if( WINVERS_AMIV || nw->Height == 0) {
487                 if( WINVERS_AMIV ) {
488                     nw->Height = TextsFont->tf_YSize + HackScreen->WBorTop + 3 +
489                                 HackScreen->WBorBottom;
490                     if( bigscreen )
491                         nw->Height += ( txheight * 6 );
492                     else
493                         nw->Height += ( txheight * 3 );
494                 }
495                 else
496                 {
497                     nw->Height = HackScreen->Height - nw->TopEdge - stath - maph;
498                 }
499             }
500         }
501
502         /* Do we have room for larger message window ?
503          * This is possible if we can show full height map in tile
504          * mode with default scaling.
505          */
506         if (nw->Height + stath + maph < HackScreen->Height - nw->TopEdge )
507             nw->Height = HackScreen->Height - nw->TopEdge - 1 - maph - stath;
508
509 #ifdef  INTUI_NEW_LOOK
510         if( IntuitionBase->LibNode.lib_Version >= 37 )
511         {
512             MsgPropScroll.Flags |= PROPNEWLOOK;
513             PropScroll.Flags |= PROPNEWLOOK;
514         }
515 #endif
516     }
517
518     nw->IDCMPFlags |= MENUPICK;
519
520     /* Check if there is "Room" for all this stuff... */
521     if( ( WINVERS_AMIV || bigscreen ) &&
522         type != NHW_BASE )
523     {
524         nw->Flags &= ~( BORDERLESS | BACKDROP );
525
526         if( WINVERS_AMIV )
527         {
528             if( type == NHW_STATUS )
529             {
530                 nw->Flags &= ~( WINDOWDRAG | WINDOWDEPTH | SIZEBRIGHT | WINDOWSIZING );
531                 nw->IDCMPFlags &= ~NEWSIZE;
532             }
533             else
534             {
535                 nw->Flags |= ( WINDOWDRAG | WINDOWDEPTH | SIZEBRIGHT | WINDOWSIZING );
536                 nw->IDCMPFlags |= NEWSIZE;
537             }
538         }
539         else
540         {
541             if( HackScreen->Width < 657 )
542             {
543                 nw->Flags |= ( WINDOWDRAG | WINDOWDEPTH );
544             }
545             else
546             {
547                 nw->Flags |= ( WINDOWDRAG | WINDOWDEPTH | SIZEBRIGHT );
548             }
549         }
550     }
551
552     if ( WINVERS_AMII && type == NHW_MAP )
553         nw->Flags &= ~WINDOWSIZING;
554
555     if ( type == NHW_MESSAGE && scrollmsg ) {
556         nw->Flags |= WINDOWDRAG|WINDOWDEPTH|SIZEBRIGHT|WINDOWSIZING;
557         nw->Flags &= ~BORDERLESS;
558     }
559
560     /* No titles on a hires only screen except for messagewindow */
561     if( !(WINVERS_AMIV && type == NHW_MAP) && !bigscreen && type != NHW_MESSAGE )
562         nw->Title = 0;
563
564     wd = (struct amii_WinDesc *)alloc(sizeof(struct amii_WinDesc));
565     memset( wd, 0, sizeof( struct amii_WinDesc ) );
566
567     /* Both, since user may have changed the pen settings so respect those */
568     if( WINVERS_AMII || WINVERS_AMIV )
569     {
570         /* Special backfill for these types of layers */
571         switch( type )
572         {
573         case NHW_MESSAGE:
574         case NHW_STATUS:
575         case NHW_TEXT:
576         case NHW_MENU:
577         case NHW_BASE:
578         case NHW_OVER:
579         case NHW_MAP:
580             if( wd )
581             {
582 #ifdef __GNUC__
583                 fillhook.h_Entry = (void *)&LayerFillHook;
584 #else
585                 fillhook.h_Entry = (ULONG(*)())LayerFillHook;
586 #endif
587                 fillhook.h_Data = (void *)type;
588                 fillhook.h_SubEntry = 0;
589                 wd->hook = alloc( sizeof( fillhook ) );
590                 memcpy( wd->hook, &fillhook, sizeof( fillhook ) );
591                 memcpy( wd->wintags, wintags, sizeof( wd->wintags) );
592                 wd->wintags[0].ti_Data = (long)wd->hook;
593                 nw->Extension = (void *)wd->wintags;
594             }
595             break;
596         }
597     }
598
599     /* Don't open MENU or TEXT windows yet */
600
601     if( type == NHW_MENU || type == NHW_TEXT )
602         w = NULL;
603     else
604         w=OpenShWindow( (void *)nw );
605
606     if( w == NULL && type != NHW_MENU && type != NHW_TEXT )
607     {
608         char buf[ 100 ];
609
610         sprintf( buf, "nw type (%d) dims l: %d, t: %d, w: %d, h: %d",
611                 type,
612                 nw->LeftEdge, nw->TopEdge,
613                 nw->Width, nw->Height );
614         raw_print( buf );
615         panic("bad openwin %d",type);
616     }
617
618     /* Check for an empty slot */
619
620     for(newid = 0; newid<MAXWIN + 1; newid++)
621     {
622         if(amii_wins[newid] == 0)
623             break;
624     }
625
626     if(newid==MAXWIN+1)
627         panic("time to write re-alloc code\n");
628
629     /* Set wincnt accordingly */
630
631     if( newid > wincnt )
632         wincnt = newid;
633
634     /* Do common initialization */
635
636     amii_wins[newid] = wd;
637
638     wd->newwin = NULL;
639     wd->win = w;
640     wd->type = type;
641     wd->wflags = 0;
642     wd->active = FALSE;
643     wd->curx=wd->cury = 0;
644     wd->resp = wd->canresp = wd->morestr = 0;   /* CHECK THESE */
645     wd->maxrow = new_wins[type].maxrow;
646     wd->maxcol = new_wins[type].maxcol;
647
648     if( type != NHW_TEXT && type != NHW_MENU )
649     {
650         if( TextsFont && ( type == NHW_MESSAGE || type == NHW_STATUS ) )
651         {
652             SetFont(w->RPort, TextsFont);
653             txheight = w->RPort->TxHeight;
654             txwidth = w->RPort->TxWidth;
655             txbaseline = w->RPort->TxBaseline;
656             if( type == NHW_MESSAGE )
657             {
658                 if (scrollmsg )
659                 {
660                     if( WINVERS_AMIV )
661                     {
662                         WindowLimits( w, 100, w->BorderTop +
663                                 w->BorderBottom +
664                                 ((txheight+1)*2) + 1, 0, 0 );
665                     }
666                     else
667                     {
668                         WindowLimits( w, w->Width, w->BorderTop +
669                                 w->BorderBottom +
670                                 ((txheight+1)*2) + 1, 0, 0 );
671                     }
672                 }
673                 else
674                 {
675                     WindowLimits( w, w->Width, w->BorderTop +
676                                 w->BorderBottom +
677                                 txheight + 2, 0, 0 );
678                 }
679             }
680         }
681         if ( type != NHW_MAP) {
682             SetFont(w->RPort, TextsFont);
683         }
684 #ifdef HACKFONT
685         else if( HackFont )
686             SetFont(w->RPort, HackFont);
687 #endif
688     }
689
690     /* Text and menu windows are not opened yet */
691     if( w )
692     {
693         wd->rows = ( w->Height - w->BorderTop -
694             w->BorderBottom - 2 ) / w->RPort->TxHeight;
695         wd->cols = ( w->Width - w->BorderLeft -
696             w->BorderRight - 2 ) / w->RPort->TxWidth;
697     }
698
699     /* Okay, now do the individual type initialization */
700
701     switch(type)
702     {
703         /* History lines for MESSAGE windows are stored in cw->data[?].
704          * maxcol and maxrow are used as cursors.  maxrow is the count
705          * of the number of history lines stored.  maxcol is the cursor
706          * to the last line that was displayed by ^P.
707          */
708         case NHW_MESSAGE:
709             SetMenuStrip(w, MenuStrip);
710             MsgScroll.TopEdge = HackScreen->WBorTop + scrfontysize + 1;
711             iflags.msg_history = wd->rows*10;
712             if (iflags.msg_history < 40)
713                 iflags.msg_history = 40;
714             if (iflags.msg_history > 400)
715                 iflags.msg_history = 400;
716             iflags.window_inited=TRUE;
717             wd->data = (char **)alloc( iflags.msg_history*sizeof( char * ) );
718             memset( wd->data, 0, iflags.msg_history * sizeof( char * ) );
719             wd->maxrow = wd->maxcol = 0;
720             /* Indicate that we have not positioned the cursor yet */
721             wd->curx = -1;
722             break;
723
724             /* A MENU contains a list of lines in wd->data[?].  These
725              * lines are created in amii_putstr() by reallocating the size
726              * of wd->data to hold enough (char *)'s.  wd->rows is the
727              * number of (char *)'s allocated.  wd->maxrow is the number
728              * used.  wd->maxcol is used to track how wide the menu needs
729              * to be.  wd->resp[x] contains the characters that correspond
730              * to selecting wd->data[x].  wd->resp[x] corresponds to
731              * wd->data[x] for any x. Elements of wd->data[?] that are not
732              * valid selections have the corresponding element of
733              * wd->resp[] set to a value of '\01';  i.e. a ^A which is
734              * not currently a valid keystroke for responding to any
735              * MENU or TEXT window.
736              */
737         case NHW_MENU:
738             MenuScroll.TopEdge = HackScreen->WBorTop + scrfontysize + 1;
739             wd->resp=(char*)alloc(256);
740             wd->resp[0]=0;
741             wd->rows = wd->maxrow = 0;
742             wd->cols = wd->maxcol = 0;
743             wd->data = NULL;
744             break;
745
746             /* See the explanation of MENU above.  Except, wd->resp[] is not
747              * used for TEXT windows since there is no selection of a
748              * a line performed/allowed.  The window is always full
749              * screen width.
750              */
751         case NHW_TEXT:
752             MenuScroll.TopEdge = HackScreen->WBorTop + scrfontysize + 1;
753             wd->rows = wd->maxrow = 0;
754             wd->cols = wd->maxcol = amiIDisplay->cols;
755             wd->data = NULL;
756             wd->morestr = NULL;
757             break;
758
759             /* The status window has only two lines.  These are stored in
760              * wd->data[], and here we allocate the space for them.
761              */
762         case NHW_STATUS:
763             SetMenuStrip(w, MenuStrip);
764             /* wd->cols is the number of characters which fit across the
765              * screen.
766              */
767             wd->data=(char **)alloc(3*sizeof(char *));
768             wd->data[0] = (char *)alloc(wd->cols + 10);
769             wd->data[1] = (char *)alloc(wd->cols + 10);
770             wd->data[2] = NULL;
771             break;
772
773             /* NHW_OVER does not use wd->data[] or the other text
774              * manipulating members of the amii_WinDesc structure.
775              */
776         case NHW_OVER:
777             SetMenuStrip(w, MenuStrip);
778             break;
779
780             /* NHW_MAP does not use wd->data[] or the other text
781              * manipulating members of the amii_WinDesc structure.
782              */
783         case NHW_MAP:
784             SetMenuStrip(w, MenuStrip);
785             if( WINVERS_AMIV )
786             {
787                 CO = (w->Width-w->BorderLeft-w->BorderRight)/mxsize;
788                 LI = (w->Height-w->BorderTop-w->BorderBottom)/mysize;
789                 amii_setclipped();
790                 SetFont( w->RPort, RogueFont);
791                 SetAPen( w->RPort, C_WHITE);    /* XXX not sufficient */
792                 SetBPen( w->RPort, C_BLACK);
793                 SetDrMd( w->RPort, JAM2);
794             }
795             else
796             {
797                 if( HackFont )
798                     SetFont( w->RPort, HackFont );
799             }
800             break;
801
802             /* The base window must exist until CleanUp() deletes it. */
803         case NHW_BASE:
804             SetMenuStrip(w, MenuStrip);
805             /* Make our requesters come to our screen */
806             {
807                 register struct Process *myProcess =
808                                         (struct Process *) FindTask(NULL);
809                 pr_WindowPtr = (struct Window *)(myProcess->pr_WindowPtr);
810                 myProcess->pr_WindowPtr = (APTR) w;
811             }
812
813             /* Need this for RawKeyConvert() */
814
815             ConsoleIO.io_Data = (APTR) w;
816             ConsoleIO.io_Length = sizeof( struct Window );
817             ConsoleIO.io_Message.mn_ReplyPort = CreateMsgPort();
818             if( OpenDevice("console.device", -1L,
819                                 (struct IORequest *) &ConsoleIO, 0L) != 0)
820             {
821                 Abort(AG_OpenDev | AO_ConsoleDev);
822             }
823
824             ConsoleDevice = (struct Library *) ConsoleIO.io_Device;
825
826             KbdBuffered = 0;
827
828 #ifdef HACKFONT
829             if( TextsFont )
830                 SetFont( w->RPort, TextsFont );
831             else if( HackFont )
832                 SetFont( w->RPort, HackFont );
833 #endif
834             txwidth = w->RPort->TxWidth;
835             txheight = w->RPort->TxHeight;
836             txbaseline = w->RPort->TxBaseline;
837             break;
838
839         default:
840             panic("bad create_nhwindow( %d )\n",type);
841             return WIN_ERR;
842     }
843
844     return( newid );
845 }
846
847 #ifdef __GNUC__
848 #ifdef __PPC__
849 int PPC_SM_Filter(void);
850 struct EmulLibEntry SM_Filter = {TRAP_LIB, 0, (int (*)(void)) PPC_SM_Filter};
851 int PPC_SM_Filter(void) {
852    struct Hook *hk = (struct Hook*)REG_A0;
853    ULONG modeID  = (ULONG)REG_A1;
854    struct ScreenModeRequester *smr = (struct ScreenModeRequester *)REG_A2;
855 #else
856 int SM_Filter(void) {
857     register struct Hook *hk asm("a0");
858     register ULONG modeID asm("a1");
859     register struct ScreenModeRequester *smr asm("a2");
860 #endif
861 #else
862 int
863 #ifndef _DCC
864 __interrupt
865 #endif
866 __saveds __asm SM_Filter(
867     register __a0 struct Hook *hk,
868     register __a1 ULONG modeID,
869     register __a2 struct ScreenModeRequester *smr)
870 {
871 #endif
872     struct DimensionInfo dims;
873     struct DisplayInfo disp;
874     DisplayInfoHandle handle;
875     handle = FindDisplayInfo(modeID);
876     if (handle) {
877         GetDisplayInfoData(handle, (char *)&dims, sizeof(dims), DTAG_DIMS, modeID);
878         GetDisplayInfoData(handle, (char *)&disp, sizeof(disp), DTAG_DISP, modeID);
879         if (!disp.NotAvailable &&
880              dims.MaxDepth <= 8 &&
881              dims.StdOScan.MaxX >= WIDTH-1 &&
882              dims.StdOScan.MaxY >= SCREENHEIGHT-1) {
883             return 1;
884         }
885     }
886     return 0;
887 }
888
889 /* Initialize the windowing environment */
890
891 void
892 amii_init_nhwindows(argcp,argv)
893     int *argcp;
894     char **argv;
895 {
896     int i;
897     struct Screen *wbscr;
898     int forcenobig = 0;
899
900     if( HackScreen )
901         panic( "init_nhwindows() called twice", 0 );
902
903         /* run args & set bigscreen from -L(1)/-l(-1) */
904     {
905         int lclargc = *argcp;
906         int t;
907         char **argv_in = argv;
908         char **argv_out = argv;
909
910         for(t=1;t<=lclargc;t++){
911             if(!strcmp("-L",*argv_in) || !strcmp("-l",*argv_in)){
912                 bigscreen = (*argv_in[1]=='l') ? -1 : 1;
913                 /* and eat the flag */
914                 (*argcp)--;
915             } else {
916                 *argv_out = *argv_in;   /* keep the flag */
917                 argv_out++;
918             }
919             argv_in++;
920         }
921         *argv_out = 0;
922     }
923
924     WIN_MESSAGE = WIN_ERR;
925     WIN_MAP = WIN_ERR;
926     WIN_STATUS = WIN_ERR;
927     WIN_INVEN = WIN_ERR;
928     WIN_BASE = WIN_ERR;
929     WIN_OVER = WIN_ERR;
930
931     if ( (IntuitionBase = (struct IntuitionBase *)
932           OpenLibrary("intuition.library", amii_libvers )) == NULL)
933     {
934         Abort(AG_OpenLib | AO_Intuition);
935     }
936
937     if ( (GfxBase = (struct GfxBase *)
938               OpenLibrary("graphics.library", amii_libvers )) == NULL)
939     {
940         Abort(AG_OpenLib | AO_GraphicsLib);
941     }
942
943     if( (LayersBase = (struct Library *)
944                 OpenLibrary("layers.library", amii_libvers )) == NULL)
945     {
946         Abort(AG_OpenLib | AO_LayersLib);
947     }
948
949     if ((GadToolsBase = OpenLibrary("gadtools.library", amii_libvers)) == NULL) {
950         Abort(AG_OpenLib | AO_GadTools);
951     }
952
953     if ((AslBase = OpenLibrary("asl.library", amii_libvers)) == NULL) {
954         Abort(AG_OpenLib);
955     }
956
957     amiIDisplay=(struct amii_DisplayDesc *)alloc(sizeof(struct amii_DisplayDesc));
958     memset( amiIDisplay, 0, sizeof( struct amii_DisplayDesc ) );
959
960     /* Use Intuition sizes for overscan screens... */
961
962     amiIDisplay->xpix = 0;
963 #ifdef  INTUI_NEW_LOOK
964     if( IntuitionBase->LibNode.lib_Version >= 37 )
965     {
966         if( wbscr = LockPubScreen( "Workbench" ) )
967         {
968             amiIDisplay->xpix = wbscr->Width;
969             amiIDisplay->ypix = wbscr->Height;
970             UnlockPubScreen( NULL, wbscr );
971         }
972     }
973 #endif
974     if( amiIDisplay->xpix == 0 )
975     {
976         amiIDisplay->ypix = GfxBase->NormalDisplayRows;
977         amiIDisplay->xpix = GfxBase->NormalDisplayColumns;
978     }
979
980     amiIDisplay->cols = amiIDisplay->xpix / FONTWIDTH;
981
982     amiIDisplay->toplin=0;
983     amiIDisplay->rawprint=0;
984     amiIDisplay->lastwin=0;
985
986     if( bigscreen == 0 )
987     {
988         if( ( GfxBase->ActiView->ViewPort->Modes & LACE ) == LACE )
989         {
990             amiIDisplay->ypix *= 2;
991             NewHackScreen.ViewModes |= LACE;
992             bigscreen = 1;
993         }
994         else if( GfxBase->NormalDisplayRows >= 300 ||
995                  amiIDisplay->ypix >= 300 )
996         {
997             bigscreen = 1;
998         }
999     }
1000     else if( bigscreen == -1 )
1001     {
1002         bigscreen = 0;
1003         forcenobig = 1;
1004     }
1005     else if( bigscreen )
1006     {
1007         /* If bigscreen requested and we don't have enough rows in
1008          * noninterlaced mode, switch to interlaced...
1009          */
1010         if( GfxBase->NormalDisplayRows < 300 )
1011         {
1012             amiIDisplay->ypix *= 2;
1013             NewHackScreen.ViewModes |= LACE;
1014         }
1015     }
1016
1017     if( !bigscreen )
1018     {
1019         alwaysinvent = 0;
1020     }
1021     amiIDisplay->rows = amiIDisplay->ypix / FONTHEIGHT;
1022
1023 #ifdef HACKFONT
1024     /*
1025      *  Load the fonts that we need.
1026      */
1027
1028     if( DiskfontBase =
1029                 OpenLibrary( "diskfont.library", amii_libvers  ) )
1030     {
1031         Hack80.ta_Name -= SIZEOF_DISKNAME;
1032         HackFont = OpenDiskFont( &Hack80 );
1033         Hack80.ta_Name += SIZEOF_DISKNAME;
1034
1035         /* Textsfont13 is filled in with "FONT=" settings. The default is
1036          * courier/13.
1037          */
1038         TextsFont = NULL;
1039         if( bigscreen )
1040             TextsFont = OpenDiskFont( &TextsFont13 );
1041
1042         /* Try hack/8 for texts if no user specified font */
1043         if( TextsFont == NULL )
1044         {
1045             Hack80.ta_Name -= SIZEOF_DISKNAME;
1046             TextsFont = OpenDiskFont( &Hack80 );
1047             Hack80.ta_Name += SIZEOF_DISKNAME;
1048         }
1049
1050         /* If no fonts, make everything topaz 8 for non-view windows.
1051          */
1052         Hack80.ta_Name = "topaz.font";
1053         RogueFont = OpenFont( &Hack80 );
1054         if(!RogueFont) panic("Can't get topaz:8");
1055         if( !HackFont || !TextsFont )
1056         {
1057             if( !HackFont )
1058             {
1059                 HackFont = OpenFont( &Hack80 );
1060                 if( !HackFont )
1061                     panic( "Can't get a map font, topaz:8" );
1062             }
1063
1064             if( !TextsFont )
1065             {
1066                 TextsFont = OpenFont( &Hack80 );
1067                 if( !TextsFont )
1068                     panic( "Can't open text font" );
1069             }
1070         }
1071         CloseLibrary(DiskfontBase);
1072         DiskfontBase = NULL;
1073     }
1074 #endif
1075
1076     /* Adjust getlin window size to font */
1077
1078     if (TextsFont) {
1079         extern SHORT BorderVectors1[];
1080         extern SHORT BorderVectors2[];
1081         extern struct Gadget Gadget2;
1082         extern struct Gadget String;
1083         extern struct NewWindow StrWindow;
1084         BorderVectors1[2] += (TextsFont->tf_XSize-8)*6; /* strlen("Cancel") == 6 */
1085         BorderVectors1[4] += (TextsFont->tf_XSize-8)*6;
1086         BorderVectors1[5] += TextsFont->tf_YSize-8;
1087         BorderVectors1[7] += TextsFont->tf_YSize-8;
1088         BorderVectors2[2] += (TextsFont->tf_XSize-8)*6;
1089         BorderVectors2[4] += (TextsFont->tf_XSize-8)*6;
1090         BorderVectors2[5] += TextsFont->tf_YSize-8;
1091         BorderVectors2[7] += TextsFont->tf_YSize-8;
1092         Gadget2.TopEdge += TextsFont->tf_YSize-8;
1093         Gadget2.Width += (TextsFont->tf_XSize-8)*6;
1094         Gadget2.Height += TextsFont->tf_YSize-8;
1095         String.LeftEdge += (TextsFont->tf_XSize-8)*6;
1096         String.TopEdge += TextsFont->tf_YSize-8;
1097         String.Width += TextsFont->tf_XSize-8;
1098         String.Height += TextsFont->tf_YSize-8;
1099         StrWindow.Width += (TextsFont->tf_XSize-8)*7;
1100         StrWindow.Height += (TextsFont->tf_YSize-8)*2; /* Titlebar + 1 row of gadgets */
1101     }
1102
1103     /* This is the size screen we want to open, within reason... */
1104
1105     NewHackScreen.Width = max( WIDTH, amiIDisplay->xpix );
1106     NewHackScreen.Height = max( SCREENHEIGHT, amiIDisplay->ypix );
1107     {
1108         static char fname[18];
1109         sprintf(fname,"NetHack %d.%d.%d", VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL);
1110         NewHackScreen.DefaultTitle=fname;
1111     }
1112 #if 0
1113     NewHackScreen.BlockPen = C_BLACK;
1114     NewHackScreen.DetailPen = C_WHITE;
1115 #endif
1116 #ifdef  INTUI_NEW_LOOK
1117     if( IntuitionBase->LibNode.lib_Version >= 37 )
1118     {
1119         int i;
1120         struct DimensionInfo dims;
1121         DisplayInfoHandle handle;
1122         struct DisplayInfo disp;
1123         ULONG modeid = DEFAULT_MONITOR_ID|HIRES_KEY;
1124
1125         NewHackScreen.Width = STDSCREENWIDTH;
1126         NewHackScreen.Height = STDSCREENHEIGHT;
1127
1128 #ifdef HACKFONT
1129         if (TextsFont) {
1130             NewHackScreen.Font = &TextsFont13;
1131         }
1132 #endif
1133
1134         if ( amii_scrnmode == 0xffffffff ) {
1135             struct ScreenModeRequester *SMR;
1136 #ifdef __GNUC__
1137             SM_FilterHook.h_Entry = (void *)&SM_Filter;
1138 #else
1139             SM_FilterHook.h_Entry = (ULONG(*)())SM_Filter;
1140 #endif
1141             SM_FilterHook.h_Data = 0;
1142             SM_FilterHook.h_SubEntry = 0;
1143             SMR = AllocAslRequest(ASL_ScreenModeRequest,NULL);
1144             if (AslRequestTags(SMR,
1145                                 ASLSM_FilterFunc, (ULONG)&SM_FilterHook,
1146                                 TAG_END))
1147                 amii_scrnmode = SMR->sm_DisplayID;
1148             else
1149                 amii_scrnmode = 0;
1150             FreeAslRequest(SMR);
1151         }
1152
1153         if( forcenobig == 0 )
1154         {
1155             if( ( wbscr = LockPubScreen( "Workbench" ) ) != NULL ||
1156                 ( wbscr = LockPubScreen( NULL ) ) != NULL )
1157             {
1158                 /* Get the default pub screen's size */
1159                 modeid = GetVPModeID( &wbscr->ViewPort );
1160                 if( modeid == INVALID_ID ||
1161                     ModeNotAvailable( modeid ) ||
1162                     ( handle = FindDisplayInfo( modeid ) ) == NULL ||
1163                     GetDisplayInfoData( handle, (char *)&dims, sizeof( dims ),
1164                         DTAG_DIMS, modeid ) <= 0 ||
1165                     GetDisplayInfoData( handle, (char *)&disp, sizeof( disp ),
1166                         DTAG_DISP, modeid ) <= 0 )
1167                 {
1168                     modeid = DEFAULT_MONITOR_ID|HIRES_KEY;
1169                     /* If the display database seems to not work, use the screen
1170                      * dimensions
1171                      */
1172                     NewHackScreen.Height = wbscr->Height;
1173                     NewHackScreen.Width = wbscr->Width;
1174                 
1175                     /*
1176                      * Request LACE if it looks laced.  For 2.1/3.0, we will get
1177                      * promoted to the users choice of modes (if promotion is allowed)
1178                      * If the user is using a dragable screen, things will get hosed
1179                      * but that is life...
1180                      */
1181                     if( wbscr->ViewPort.Modes & LACE )
1182                         NewHackScreen.ViewModes |= LACE;
1183                     modeid = -1;
1184                 }
1185                 else
1186                 {
1187                     /* Use the display database to get the correct information */
1188                     if( disp.PropertyFlags & DIPF_IS_LACE )
1189                         NewHackScreen.ViewModes |= LACE;
1190                     NewHackScreen.Height = dims.StdOScan.MaxY+1;
1191                     NewHackScreen.Width = dims.StdOScan.MaxX+1;
1192                 }
1193                 NewHackScreen.TopEdge = 0;
1194                 NewHackScreen.LeftEdge = 0;
1195
1196                 UnlockPubScreen( NULL, wbscr );
1197             }
1198         }
1199
1200         for( i = 0; scrntags[i].ti_Tag != TAG_DONE; ++i )
1201         {
1202             switch( scrntags[i].ti_Tag )
1203             {
1204                 case SA_DisplayID:
1205                     if( !amii_scrnmode || ModeNotAvailable( amii_scrnmode ) )
1206                     {
1207                         if( ModeNotAvailable( modeid ) )
1208                         {
1209                             scrntags[i].ti_Tag = TAG_IGNORE;
1210                             break;
1211                         }
1212                         else
1213                             scrntags[i].ti_Data = (long)modeid;
1214                     }
1215                     else
1216                         modeid = scrntags[i].ti_Data = (long)amii_scrnmode;
1217                     if( ( handle = FindDisplayInfo( modeid ) ) != NULL &&
1218                         GetDisplayInfoData( handle, (char *)&dims, sizeof( dims ),
1219                             DTAG_DIMS, modeid ) > 0 &&
1220                         GetDisplayInfoData( handle, (char *)&disp, sizeof( disp ),
1221                             DTAG_DISP, modeid ) > 0 )
1222                     {
1223                         if( disp.PropertyFlags & DIPF_IS_LACE )
1224                             NewHackScreen.ViewModes |= LACE;
1225                         NewHackScreen.Height = dims.StdOScan.MaxY+1;
1226                         NewHackScreen.Width = dims.StdOScan.MaxX+1;
1227                     }
1228                     break;
1229
1230                 case SA_Pens:
1231                     scrntags[i].ti_Data = (long)flags.amii_dripens;
1232                     break;
1233             }
1234         }
1235     }
1236 #endif
1237
1238     if( WINVERS_AMIV )
1239         amii_bmhd = ReadTileImageFiles( );
1240     else
1241         memcpy( amii_initmap, amii_init_map, sizeof( amii_initmap ) );
1242     memcpy(flags.amii_curmap,amii_initmap,sizeof(flags.amii_curmap));
1243
1244     /* Find out how deep the screen needs to be, 32 planes is enough! */
1245     for( i = 0; i < 32; ++i )
1246     {
1247         if( ( 1L << i ) >= amii_numcolors )
1248             break;
1249     }
1250
1251     NewHackScreen.Depth = i;
1252
1253     /* If for some reason Height/Width became smaller than the required,
1254         have the required one */
1255     if (NewHackScreen.Height < SCREENHEIGHT)
1256         NewHackScreen.Height = SCREENHEIGHT;
1257     if (NewHackScreen.Width < WIDTH)
1258         NewHackScreen.Width = WIDTH;
1259 #ifdef HACKFONT
1260     i = max(TextsFont->tf_XSize, HackFont->tf_XSize);
1261     if (NewHackScreen.Width < 80*i+4)
1262         NewHackScreen.Width = 80*i+4;
1263 #endif
1264
1265     /* While openscreen fails try fewer colors to see if that is the problem. */
1266     while( ( HackScreen = OpenScreen( (void *)&NewHackScreen ) ) == NULL )
1267     {
1268 #ifdef  TEXTCOLOR
1269         if( --NewHackScreen.Depth < 3 )
1270 #else
1271         if( --NewHackScreen.Depth < 2 )
1272 #endif
1273             Abort( AN_OpenScreen & ~AT_DeadEnd );
1274     }
1275     amii_numcolors = 1L << NewHackScreen.Depth;
1276     if( HackScreen->Height > 300 && forcenobig == 0 )
1277         bigscreen = 1;
1278     else
1279         bigscreen = 0;
1280
1281 #ifdef  INTUI_NEW_LOOK
1282     if( IntuitionBase->LibNode.lib_Version >= 37 )
1283         PubScreenStatus( HackScreen, 0 );
1284 #endif
1285
1286     amiIDisplay->ypix = HackScreen->Height;
1287     amiIDisplay->xpix = HackScreen->Width;
1288
1289     LoadRGB4(&HackScreen->ViewPort, flags.amii_curmap, amii_numcolors );
1290
1291     VisualInfo = GetVisualInfo(HackScreen, TAG_END);
1292     MenuStrip = CreateMenus(GTHackMenu, TAG_END);
1293     LayoutMenus(MenuStrip, VisualInfo, GTMN_NewLookMenus, TRUE, TAG_END);
1294
1295     /* Display the copyright etc... */
1296
1297     if( WIN_BASE == WIN_ERR )
1298         WIN_BASE = amii_create_nhwindow( NHW_BASE );
1299     amii_clear_nhwindow( WIN_BASE );
1300     amii_putstr( WIN_BASE, 0, "" );
1301     amii_putstr( WIN_BASE, 0, "" );
1302     amii_putstr( WIN_BASE, 0, "" );
1303     amii_putstr( WIN_BASE, 0, COPYRIGHT_BANNER_A);
1304     amii_putstr( WIN_BASE, 0, COPYRIGHT_BANNER_B);
1305     amii_putstr( WIN_BASE, 0, COPYRIGHT_BANNER_C);
1306     amii_putstr( WIN_BASE, 0, "");
1307
1308     Initialized = 1;
1309 }
1310
1311 void
1312 amii_sethipens( struct Window *w, int type, int attr )
1313 {
1314     switch( type )
1315     {
1316         default:
1317             SetAPen( w->RPort, attr ? C_RED : amii_otherAPen );
1318             SetBPen( w->RPort, C_BLACK );
1319             break;
1320         case NHW_STATUS:
1321             SetAPen( w->RPort, attr ? C_WHITE : amii_statAPen );
1322             SetBPen( w->RPort, amii_statBPen );
1323             break;
1324         case NHW_MESSAGE:
1325             SetAPen( w->RPort, attr ? C_WHITE : amii_msgAPen );
1326             SetBPen( w->RPort, amii_msgBPen );
1327             break;
1328         case NHW_MENU:
1329             SetAPen( w->RPort, attr ? C_BLACK : amii_menuAPen );
1330             SetBPen( w->RPort, amii_menuBPen );
1331             break;
1332         case NHW_TEXT:
1333             SetAPen( w->RPort, attr ? C_BLACK : amii_textAPen );
1334             SetBPen( w->RPort, amii_textBPen );
1335         case -2:
1336             SetBPen( w->RPort, amii_otherBPen );
1337             SetAPen( w->RPort, attr ? C_RED : amii_otherAPen );
1338             break;
1339     }
1340 }
1341
1342 void
1343 amii_setfillpens( struct Window *w, int type )
1344 {
1345     switch( type )
1346     {
1347     case NHW_MESSAGE:
1348         SetAPen( w->RPort, amii_msgBPen );
1349         SetBPen( w->RPort, amii_msgBPen );
1350         break;
1351     case NHW_STATUS:
1352         SetAPen( w->RPort, amii_statBPen );
1353         SetBPen( w->RPort, amii_statBPen );
1354         break;
1355     case NHW_MENU:
1356         SetAPen( w->RPort, amii_menuBPen );
1357         SetBPen( w->RPort, amii_menuBPen );
1358         break;
1359     case NHW_TEXT:
1360         SetAPen( w->RPort, amii_textBPen );
1361         SetBPen( w->RPort, amii_textBPen );
1362         break;
1363     case NHW_MAP:
1364     case NHW_BASE:
1365     case NHW_OVER:
1366     default:
1367         SetAPen( w->RPort, C_BLACK );
1368         SetBPen( w->RPort, C_BLACK );
1369         break;
1370     case -2:
1371         SetAPen( w->RPort, amii_otherBPen );
1372         SetBPen( w->RPort, amii_otherBPen );
1373         break;
1374     }
1375 }
1376
1377 void
1378 amii_setdrawpens( struct Window *w, int type )
1379 {
1380     switch( type )
1381     {
1382     case NHW_MESSAGE:
1383         SetAPen( w->RPort, amii_msgAPen );
1384         SetBPen( w->RPort, amii_msgBPen );
1385         break;
1386     case NHW_STATUS:
1387         SetAPen( w->RPort, amii_statAPen );
1388         SetBPen( w->RPort, amii_statBPen );
1389         break;
1390     case NHW_MENU:
1391         SetAPen( w->RPort, amii_menuAPen );
1392         SetBPen( w->RPort, amii_menuBPen );
1393         break;
1394     case NHW_TEXT:
1395         SetAPen( w->RPort, amii_textAPen );
1396         SetBPen( w->RPort, amii_textBPen );
1397         break;
1398     case NHW_MAP:
1399     case NHW_BASE:
1400     case NHW_OVER:
1401         SetAPen( w->RPort, C_WHITE );
1402         SetBPen( w->RPort, C_BLACK );
1403         break;
1404     default:
1405         SetAPen( w->RPort, amii_otherAPen );
1406         SetBPen( w->RPort, amii_otherBPen );
1407         break;
1408     }
1409 }
1410
1411 /* Clear the indicated window */
1412
1413 void
1414 amii_clear_nhwindow(win)
1415     register winid win;
1416 {
1417     register struct amii_WinDesc *cw;
1418     register struct Window *w;
1419
1420     if( reclip == 2 ) return;
1421
1422     if( win == WIN_ERR || ( cw = amii_wins[win] ) == NULL )
1423         panic( winpanicstr, win, "clear_nhwindow" );
1424
1425     /* Clear the overview window too if it is displayed */
1426     if( WINVERS_AMIV && ( cw->type == WIN_MAP && WIN_OVER != WIN_ERR && reclip == 0 ) )
1427     {
1428         amii_clear_nhwindow( WIN_OVER );
1429     }
1430
1431     if( w = cw->win )
1432         SetDrMd( w->RPort, JAM2);
1433     else
1434         return;
1435
1436     if( (cw->wflags & FLMAP_CURSUP ) )
1437     {
1438         if( cw->type != NHW_MAP )
1439             cursor_off( win );
1440         else
1441             cw->wflags &= ~FLMAP_CURSUP;
1442     }
1443
1444     amii_setfillpens( w, cw->type );
1445     SetDrMd( w->RPort, JAM2 );
1446
1447     if( cw->type == NHW_MENU || cw->type == NHW_TEXT )
1448     {
1449         RectFill( w->RPort, w->BorderLeft, w->BorderTop,
1450           w->Width - w->BorderRight-1,
1451           w->Height - w->BorderBottom-1 );
1452     }
1453     else
1454     {
1455         if( cw->type == NHW_MESSAGE )
1456         {
1457             amii_curs( win, 1, 0 );
1458             if( !scrollmsg )
1459                 TextSpaces( w->RPort, cw->cols );
1460         }
1461         else
1462         {
1463             RectFill( w->RPort, w->BorderLeft, w->BorderTop,
1464               w->Width - w->BorderRight-1,
1465               w->Height - w->BorderBottom-1 );
1466         }
1467     }
1468
1469     cw->cury = 0;
1470     cw->curx = 0;
1471     amii_curs( win, 1, 0 );
1472 }
1473
1474 /* Dismiss the window from the screen */
1475
1476 void
1477 dismiss_nhwindow(win)
1478     register winid win;
1479 {
1480     register struct Window *w;
1481     register struct amii_WinDesc *cw;
1482
1483     if( win == WIN_ERR || ( cw = amii_wins[win] ) == NULL )
1484     {
1485         panic(winpanicstr,win, "dismiss_nhwindow");
1486     }
1487
1488     w = cw->win;
1489
1490     if( w )
1491     {
1492         /* All windows have this stuff attached to them. */
1493         if(     cw->type == NHW_MAP ||
1494                 cw->type == NHW_OVER ||
1495                 cw->type == NHW_BASE ||
1496                 cw->type == NHW_MESSAGE ||
1497                 cw->type == NHW_STATUS )
1498         {
1499             ClearMenuStrip( w );
1500         }
1501
1502         /* Save where user like inventory to appear */
1503         if( win == WIN_INVEN )
1504         {
1505             lastinvent.MinX = w->LeftEdge;
1506             lastinvent.MinY = w->TopEdge;
1507             lastinvent.MaxX = w->Width;
1508             lastinvent.MaxY = w->Height;
1509         }
1510
1511         /* Close the window */
1512         CloseShWindow( w );
1513         cw->win = NULL;
1514
1515         /* Free copy of NewWindow structure for TEXT/MENU windows. */
1516         if( cw->newwin )
1517             FreeNewWindow( (void *)cw->newwin );
1518         cw->newwin = NULL;
1519     }
1520 }
1521
1522 void
1523 amii_exit_nhwindows(str)
1524     const char *str;
1525 {
1526     /* Seems strange to have to do this... but we need the BASE window
1527      * left behind...
1528      */
1529     kill_nhwindows( 0 );
1530     if( WINVERS_AMIV )
1531         FreeTileImageFiles( );
1532
1533     if( str )
1534     {
1535         raw_print( "" );        /* be sure we're not under the top margin */
1536         raw_print( str );
1537     }
1538 }
1539
1540 void
1541 amii_display_nhwindow(win,blocking)
1542     winid win;
1543     boolean blocking;
1544 {
1545     menu_item *mip;
1546     int cnt;
1547     static int lastwin = -1;
1548     struct amii_WinDesc *cw;
1549
1550     if( !Initialized )
1551         return;
1552     lastwin = win;
1553
1554     if( win == WIN_ERR || ( cw = amii_wins[win] ) == NULL )
1555         panic(winpanicstr,win,"display_nhwindow");
1556
1557     if( cw->type == NHW_MESSAGE )
1558         cw->wflags &= ~FLMAP_SKIP;
1559
1560     if( cw->type == NHW_MESSAGE || cw->type == NHW_STATUS )
1561         return;
1562
1563     if( WIN_MAP != WIN_ERR && amii_wins[ WIN_MAP ] )
1564     {
1565         flush_glyph_buffer( amii_wins[ WIN_MAP ]->win );
1566     }
1567
1568     if( cw->type == NHW_MENU || cw->type == NHW_TEXT )
1569     {
1570         cnt = DoMenuScroll( win, blocking, PICK_ONE, &mip );
1571     }
1572     else if( cw->type==NHW_MAP )
1573     {
1574         amii_end_glyphout( win );
1575         /* Do more if it is time... */
1576         if( blocking == TRUE && amii_wins[ WIN_MESSAGE ]->curx )
1577         {
1578             outmore( amii_wins[ WIN_MESSAGE ] );
1579         }
1580     }
1581 }
1582
1583 void
1584 amii_curs(window, x, y)
1585 winid window;
1586 register int x, y;  /* not xchar: perhaps xchar is unsigned and
1587                curx-x would be unsigned as well */
1588 {
1589     register struct amii_WinDesc *cw;
1590     register struct Window *w;
1591     register struct RastPort *rp;
1592
1593     if( window == WIN_ERR || ( cw = amii_wins[window] ) == NULL )
1594         panic(winpanicstr,  window, "curs");
1595     if( (w = cw->win) == NULL )
1596     {
1597         if( cw->type == NHW_MENU || cw->type == NHW_TEXT )
1598             return;
1599         else
1600             panic( "No window open yet in curs() for winid %d\n", window );
1601     }
1602     amiIDisplay->lastwin = window;
1603
1604     /* Make sure x is within bounds */
1605     if( x > 0 )
1606         --x;    /* column 0 is never used */
1607     else
1608         x = 0;
1609
1610     cw->curx = x;
1611     cw->cury = y;
1612
1613 #ifdef DEBUG
1614     if( x<0 || y<0 || y >= cw->rows || x >= cw->cols )
1615     {
1616         char *s = "[unknown type]";
1617         switch(cw->type)
1618         {
1619             case NHW_MESSAGE: s = "[topl window]"; break;
1620             case NHW_STATUS: s = "[status window]"; break;
1621             case NHW_MAP: s = "[map window]"; break;
1622             case NHW_MENU: s = "[menu window]"; break;
1623             case NHW_TEXT: s = "[text window]"; break;
1624             case NHW_BASE: s = "[base window]"; break;
1625             case NHW_OVER: s = "[overview window]"; break;
1626         }
1627         impossible("bad curs positioning win %d %s (%d,%d)", window, s, x, y);
1628         return;
1629     }
1630 #endif
1631
1632 #ifdef CLIPPING
1633     if(clipping && cw->type == NHW_MAP)
1634     {
1635         x -= clipx;
1636         y -= clipy;
1637     }
1638 #endif
1639
1640     /* Output all saved output before doing cursor movements for MAP */
1641
1642     if( cw->type == NHW_MAP )
1643     {
1644         flush_glyph_buffer( w );
1645     }
1646
1647     /* Actually do it */
1648
1649     rp = w->RPort;
1650     if( cw->type == NHW_MENU )
1651     {
1652         if( WINVERS_AMIV )
1653         {
1654             if( window == WIN_INVEN )
1655             {
1656                 Move( rp, (x * rp->TxWidth) + w->BorderLeft + 1 + pictdata.xsize + 4,
1657                     (y * max(rp->TxHeight,pictdata.ysize + 3) ) +
1658                      rp->TxBaseline + pictdata.ysize - rp->TxHeight + w->BorderTop + 4 );
1659             }
1660             else
1661             {
1662                 Move( rp, (x * rp->TxWidth) + w->BorderLeft + 1,
1663                     (y * rp->TxHeight) + rp->TxBaseline + w->BorderTop + 1 );
1664             }
1665         }
1666         else
1667         {
1668             Move( rp, (x * rp->TxWidth) + w->BorderLeft + 1,
1669                 (y*rp->TxHeight ) + rp->TxBaseline + w->BorderTop + 1 );
1670         }
1671     }
1672     else if( cw->type == NHW_TEXT )
1673     {
1674         Move( rp, (x * rp->TxWidth) + w->BorderLeft + 1,
1675             (y*rp->TxHeight ) + rp->TxBaseline + w->BorderTop + 1 );
1676     }
1677     else if( cw->type == NHW_MAP || cw->type == NHW_BASE )
1678     {
1679         /* These coordinate calculations must be synced with those
1680          * in flush_glyph_buffer() in winchar.c.  curs_on_u() will
1681          * use this code, all other drawing occurs through the glyph
1682          * code.  In order for the cursor to appear on top of the hero,
1683          * the code must compute X,Y in the same manner relative to
1684          * the RastPort coordinates.
1685          *
1686          * y = w->BorderTop + (g_nodes[i].y-2) * rp->TxHeight +
1687          *   rp->TxBaseline + 1;
1688          * x = g_nodes[i].x * rp->TxWidth + w->BorderLeft;
1689          */
1690
1691         if( WINVERS_AMIV )
1692         {
1693             if( cw->type == NHW_MAP )
1694             {
1695               if(Is_rogue_level(&u.uz)){
1696 #if 0
1697 int qqx= (x * w->RPort->TxWidth) + w->BorderLeft;
1698 int qqy= w->BorderTop + ( (y+1) * w->RPort->TxHeight ) + 1;
1699 printf("pos: (%d,%d)->(%d,%d)\n",x,y,qqx,qqy);
1700 #endif
1701                 SetAPen(w->RPort,C_WHITE); /* XXX should be elsewhere (was 4)*/
1702                 Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft,
1703                         w->BorderTop + ( (y+1) * w->RPort->TxHeight ) + 1 );
1704               } else {
1705                 Move( rp, (x * mxsize) + w->BorderLeft,
1706                                 w->BorderTop + ( (y+1) * mysize ) + 1 );
1707               }
1708             }
1709             else
1710             {
1711                 Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft,
1712                             w->BorderTop + ( (y + 1) * w->RPort->TxHeight ) +
1713                             w->RPort->TxBaseline + 1 );
1714             }
1715         }
1716         else
1717         {
1718             Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft,
1719                         w->BorderTop + ( y * w->RPort->TxHeight ) +
1720                         w->RPort->TxBaseline + 1 );
1721         }
1722     }
1723     else if( WINVERS_AMIV && cw->type == NHW_OVER )
1724     {
1725         Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft + 2,
1726                         w->BorderTop + w->RPort->TxBaseline + 3 );
1727     }
1728     else if( cw->type == NHW_MESSAGE && !scrollmsg )
1729     {
1730         Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft + 2,
1731                         w->BorderTop + w->RPort->TxBaseline + 3 );
1732     }
1733     else if( cw->type == NHW_STATUS )
1734     {
1735         Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft + 2,
1736                         (y*(w->RPort->TxHeight+1)) + w->BorderTop +
1737                         w->RPort->TxBaseline + 1 );
1738     }
1739     else
1740     {
1741         Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft + 2,
1742                         (y*w->RPort->TxHeight) + w->BorderTop +
1743                         w->RPort->TxBaseline + 1 );
1744     }
1745 }
1746
1747 void
1748 amii_set_text_font( name, size )
1749     char *name;
1750     int size;
1751 {
1752     register int i;
1753     register struct amii_WinDesc *cw;
1754     int osize = TextsFont13.ta_YSize;
1755     static char nname[ 100 ];
1756
1757     strncpy( nname, name, sizeof( nname ) - 1 );
1758     nname[ sizeof( nname ) - 1 ] = 0;
1759
1760     TextsFont13.ta_Name = nname;
1761     TextsFont13.ta_YSize = size;
1762
1763     /* No alternate text font allowed for 640x269 or smaller */
1764     if( !HackScreen || !bigscreen )
1765         return;
1766
1767     /* Look for windows to set, and change them */
1768
1769     if( DiskfontBase =
1770                 OpenLibrary( "diskfont.library", amii_libvers  ) )
1771     {
1772         TextsFont = OpenDiskFont( &TextsFont13 );
1773         for( i = 0; TextsFont && i < MAXWIN; ++i )
1774         {
1775             if( (cw = amii_wins[ i ]) && cw->win != NULL )
1776             {
1777                 switch( cw->type )
1778                 {
1779                 case NHW_STATUS:
1780                     MoveWindow( cw->win, 0, -( size - osize ) * 2 );
1781                     SizeWindow( cw->win, 0, ( size - osize ) * 2 );
1782                     SetFont( cw->win->RPort, TextsFont );
1783                     break;
1784                 case NHW_MESSAGE:
1785                 case NHW_MAP:
1786                 case NHW_BASE:
1787                 case NHW_OVER:
1788                     SetFont( cw->win->RPort, TextsFont );
1789                     break;
1790                 }
1791             }
1792         }
1793     }
1794     CloseLibrary(DiskfontBase);
1795     DiskfontBase = NULL;
1796 }
1797
1798 void
1799 kill_nhwindows( all )
1800     register int all;
1801 {
1802     register int i;
1803     register struct amii_WinDesc *cw;
1804
1805     /* Foreach open window in all of amii_wins[], CloseShWindow, free memory */
1806
1807     for( i = 0; i < MAXWIN; ++i )
1808     {
1809         if( (cw = amii_wins[ i ]) && (cw->type != NHW_BASE || all) )
1810         {
1811             amii_destroy_nhwindow( i );
1812         }
1813     }
1814 }
1815
1816 void
1817 amii_cl_end( cw, curs_pos )
1818     register struct amii_WinDesc *cw;
1819     register int curs_pos;
1820 {
1821     register struct Window *w = cw->win;
1822     register int oy, ox;
1823
1824     if( !w )
1825         panic("NULL window pointer in amii_cl_end()");
1826
1827     oy = w->RPort->cp_y;
1828     ox = w->RPort->cp_x;
1829
1830     TextSpaces( w->RPort, cw->cols - curs_pos );
1831
1832     Move( w->RPort, ox, oy );
1833 }
1834
1835 void
1836 cursor_off( window )
1837     winid window;
1838 {
1839     register struct amii_WinDesc *cw;
1840     register struct Window *w;
1841     register struct RastPort *rp;
1842     int curx, cury;
1843     int x, y;
1844     long dmode;
1845     short apen, bpen;
1846     unsigned char ch;
1847
1848     if( window == WIN_ERR || ( cw = amii_wins[window] ) == NULL )
1849     {
1850         iflags.window_inited=0;
1851         panic(winpanicstr,window, "cursor_off");
1852     }
1853
1854     if( !(cw->wflags & FLMAP_CURSUP ) )
1855         return;
1856
1857     w = cw->win;
1858
1859     if( !w )
1860         return;
1861
1862     cw->wflags &= ~FLMAP_CURSUP;
1863     rp = w->RPort;
1864
1865     /* Save the current information */
1866     curx = rp->cp_x;
1867     cury = rp->cp_y;
1868     x = cw->cursx;
1869     y = cw->cursy;
1870     dmode = rp->DrawMode;
1871     apen = rp->FgPen;
1872     bpen = rp->BgPen;
1873     SetAPen( rp, cw->curs_apen );
1874     SetBPen( rp, cw->curs_bpen );
1875     SetDrMd( rp, COMPLEMENT );
1876 /*printf("CURSOR OFF: %d %d\n",x,y);*/
1877
1878     if( WINVERS_AMIV && cw->type == NHW_MAP)
1879     {
1880         cursor_common(rp, x, y);
1881         if(Is_rogue_level(&u.uz))
1882             Move(rp,curx,cury);
1883     }
1884     else
1885     {
1886         ch = CURSOR_CHAR;
1887         Move( rp, x, y );
1888         Text( rp, &ch, 1 );
1889
1890         /* Put back the other stuff */
1891
1892         Move( rp, curx, cury );
1893     }
1894     SetDrMd( rp, dmode );
1895     SetAPen( rp, apen );
1896     SetBPen( rp, bpen );
1897 }
1898
1899 void
1900 cursor_on( window )
1901     winid window;
1902 {
1903     int x, y;
1904     register struct amii_WinDesc *cw;
1905     register struct Window *w;
1906     register struct RastPort *rp;
1907     unsigned char ch;
1908     long dmode;
1909     short apen, bpen;
1910
1911     if( window == WIN_ERR || ( cw = amii_wins[window] ) == NULL )
1912     {
1913         /* tty does this differently - is this OK? */
1914         iflags.window_inited=0;
1915         panic(winpanicstr,window, "cursor_on");
1916     }
1917
1918 /*printf("CURSOR ON: %d %d\n",cw->win->RPort->cp_x, cw->win->RPort->cp_y);*/
1919     if( (cw->wflags & FLMAP_CURSUP ) )
1920         cursor_off( window );
1921
1922     w = cw->win;
1923
1924     if( !w )
1925         return;
1926
1927     cw->wflags |= FLMAP_CURSUP;
1928     rp = w->RPort;
1929
1930     /* Save the current information */
1931
1932 #ifdef  DISPMAP
1933     if( WINVERS_AMIV && cw->type == NHW_MAP && !Is_rogue_level(&u.uz))
1934         x = cw->cursx = (rp->cp_x & -8) + 8;
1935     else
1936 #endif
1937         x = cw->cursx = rp->cp_x;
1938     y = cw->cursy = rp->cp_y;
1939     apen = rp->FgPen;
1940     bpen = rp->BgPen;
1941     dmode = rp->DrawMode;
1942
1943     /* Draw in complement mode. The cursor body will be C_WHITE */
1944
1945     cw->curs_apen = 0xff; /* Last color/all planes, regardless of depth */
1946     cw->curs_bpen = 0xff;
1947     SetAPen( rp, cw->curs_apen );
1948     SetBPen( rp, cw->curs_bpen );
1949     SetDrMd( rp, COMPLEMENT );
1950     if( WINVERS_AMIV && cw->type == NHW_MAP)
1951     {
1952         cursor_common(rp, x, y);
1953     }
1954     else
1955     {
1956         Move( rp, x, y );
1957         ch = CURSOR_CHAR;
1958         Text( rp, &ch, 1 );
1959         Move( rp, x, y );
1960     }
1961
1962     SetDrMd( rp, dmode );
1963     SetAPen( rp, apen );
1964     SetBPen( rp, bpen );
1965 }
1966
1967 static void
1968 cursor_common(rp, x, y)
1969         struct RastPort *rp;
1970         int x,y;
1971 {
1972     int x1,x2,y1,y2;
1973
1974     if(Is_rogue_level(&u.uz)){
1975         x1 = x-2;               y1 = y-rp->TxHeight;
1976         x2 = x+rp->TxWidth+1;   y2 = y+3;
1977 /*printf("COMM: (%d %d) (%d %d)  (%d %d) (%d %d)\n",x1,y1,x2,y2,x1+2,y1+2,x2-2,y2-2);*/
1978     } else {
1979         x1 = x;                 y1 = y-mysize-1;
1980         x2 = x+mxsize-1;        y2 = y-2;
1981         RectFill(rp, x1, y1, x2, y2);
1982     }
1983
1984     RectFill(rp, x1+2, y1+2, x2-2, y2-2);
1985 }
1986
1987 void amii_suspend_nhwindows( str )
1988     const char *str;
1989 {
1990     if( HackScreen )
1991         ScreenToBack( HackScreen );
1992 }
1993
1994 void amii_resume_nhwindows()
1995 {
1996     if( HackScreen )
1997         ScreenToFront( HackScreen );
1998 }
1999
2000 void amii_bell()
2001 {
2002     DisplayBeep( NULL );
2003 }
2004
2005 void
2006 removetopl(cnt)
2007         int cnt;
2008 {
2009     struct amii_WinDesc *cw=amii_wins[WIN_MESSAGE];
2010                                         /* NB - this is sufficient for
2011                                          * yn_function, but that's it
2012                                          */
2013     if(cw->curx < cnt)cw->curx=0;
2014     else cw->curx -= cnt;
2015
2016     amii_curs(WIN_MESSAGE, cw->curx+1, cw->cury);
2017     amii_cl_end(cw, cw->curx);
2018 }
2019 /*#endif /* AMIGA_INTUITION */
2020
2021 #ifdef  PORT_HELP
2022 void
2023 port_help()
2024 {
2025     display_file( PORT_HELP, 1 );
2026 }
2027 #endif
2028
2029 /*
2030  *  print_glyph
2031  *
2032  *  Print the glyph to the output device.  Don't flush the output device.
2033  *
2034  *  Since this is only called from show_glyph(), it is assumed that the
2035  *  position and glyph are always correct (checked there)!
2036  */
2037
2038 void
2039 amii_print_glyph(win,x,y,glyph)
2040     winid win;
2041     xchar x,y;
2042     int glyph;
2043 {
2044     struct amii_WinDesc *cw;
2045     uchar   ch;
2046     int     color, och;
2047     extern const int zapcolors[];
2048     unsigned special;
2049
2050     /* In order for the overview window to work, we can not clip here */
2051     if( !WINVERS_AMIV )
2052     {
2053 #ifdef  CLIPPING
2054         /* If point not in visible part of window just skip it */
2055         if( clipping )
2056         {
2057             if( x <= clipx || y < clipy || x >= clipxmax || y >= clipymax )
2058                 return;
2059         }
2060 #endif
2061     }
2062
2063     if( win == WIN_ERR || (cw=amii_wins[win]) == NULL || cw->type != NHW_MAP)
2064     {
2065         panic(winpanicstr,win,"amii_print_glyph");
2066     }
2067
2068 #if 0
2069 {
2070 static int x=-1;
2071 if(u.uz.dlevel != x){
2072  fprintf(stderr,"lvlchg: %d (%d)\n",u.uz.dlevel,Is_rogue_level(&u.uz));
2073  x = u.uz.dlevel;
2074 }
2075 }
2076 #endif
2077     if(
2078         WINVERS_AMIV
2079 #ifdef REINCARNATION
2080         && !Is_rogue_level(&u.uz)
2081 #endif
2082     )
2083     {
2084         amii_curs(win,x,y);
2085         amiga_print_glyph(win,0,glyph);
2086     }
2087     else                /* AMII, or Rogue level in either version */
2088     {
2089         /* map glyph to character and color */
2090         mapglyph(glyph, &och, &color, &special, x, y);
2091                                 /* XXX next if should be ifdef REINCARNATION */
2092         ch = (uchar)och;
2093         if( WINVERS_AMIV ){                     /* implies Rogue level here */
2094             amii_curs(win,x,y);
2095             amiga_print_glyph(win,NO_COLOR,ch + 10000);
2096         } else {
2097                 /* Move the cursor. */
2098             amii_curs(win,x,y+2);
2099
2100 #ifdef TEXTCOLOR
2101                 /* Turn off color if rogue level. */
2102 # ifdef REINCARNATION
2103             if (Is_rogue_level(&u.uz))
2104                 color = NO_COLOR;
2105 #  endif
2106
2107             amiga_print_glyph(win,color,ch);
2108 #else
2109             g_putch(ch);    /* print the character */
2110 #endif
2111             cw->curx++;     /* one character over */
2112         }
2113     }
2114 }
2115
2116 /* Make sure the user sees a text string when no windowing is available */
2117
2118 void
2119 amii_raw_print(s)
2120     register const char *s;
2121 {
2122     int argc = 0;
2123
2124     if( !s )
2125         return;
2126     if(amiIDisplay)
2127         amiIDisplay->rawprint++;
2128
2129     if (!Initialized) { /* Not yet screen open ... */
2130         puts(s);
2131         fflush(stdout);
2132         return;
2133     }
2134
2135     if( Initialized == 0 && WIN_BASE == WIN_ERR )
2136             init_nhwindows(&argc, (char **)0);
2137
2138     if( amii_rawprwin != WIN_ERR )
2139         amii_putstr( amii_rawprwin, 0, s );
2140     else if( WIN_MAP != WIN_ERR && amii_wins[ WIN_MAP ] )
2141         amii_putstr( WIN_MAP, 0, s );
2142     else if( WIN_BASE != WIN_ERR && amii_wins[ WIN_BASE ] )
2143         amii_putstr( WIN_BASE, 0, s );
2144     else
2145     {
2146         puts( s);
2147         fflush(stdout);
2148     }
2149 }
2150
2151 /* Make sure the user sees a bold text string when no windowing
2152  * is available
2153  */
2154
2155 void
2156 amii_raw_print_bold(s)
2157     register const char *s;
2158 {
2159     int argc = 0;
2160
2161     if( !s )
2162         return;
2163
2164     if(amiIDisplay)
2165         amiIDisplay->rawprint++;
2166
2167     if (!Initialized) { /* Not yet screen open ... */
2168         puts(s);
2169         fflush(stdout);
2170         return;
2171     }
2172
2173     if( Initialized == 0 && WIN_BASE == WIN_ERR )
2174             init_nhwindows(&argc, (char **)0);
2175
2176     if( amii_rawprwin != WIN_ERR )
2177         amii_putstr( amii_rawprwin, 1, s );
2178     else if( WIN_MAP != WIN_ERR && amii_wins[ WIN_MAP ] )
2179         amii_putstr( WIN_MAP, 1, s );
2180     else if( WIN_BASE != WIN_ERR && amii_wins[ WIN_BASE ] )
2181         amii_putstr( WIN_BASE, 1, s );
2182     else
2183     {
2184         printf("\33[1m%s\33[0m\n",s);
2185         fflush(stdout);
2186     }
2187 }
2188
2189 /* Rebuild/update the inventory if the window is up.
2190  */
2191 void
2192 amii_update_inventory()
2193 {
2194     register struct amii_WinDesc *cw;
2195
2196     if( WIN_INVEN != WIN_ERR && ( cw = amii_wins[ WIN_INVEN ] ) &&
2197                                 cw->type == NHW_MENU && cw->win )
2198     {
2199         display_inventory( NULL, FALSE );
2200     }
2201 }
2202
2203 /* Humm, doesn't really do anything useful */
2204
2205 void
2206 amii_mark_synch()
2207 {
2208     if(!amiIDisplay)
2209         fflush(stderr);
2210 /* anything else?  do we need this much? */
2211 }
2212
2213 /* Wait for everything to sync.  Nothing is asynchronous, so we just
2214  * ask for a key to be pressed.
2215  */
2216 void
2217 amii_wait_synch()
2218 {
2219     if(!amiIDisplay || amiIDisplay->rawprint)
2220     {
2221         if(amiIDisplay) amiIDisplay->rawprint=0;
2222     }
2223     else
2224     {
2225         if( WIN_MAP != WIN_ERR )
2226         {
2227             display_nhwindow(WIN_MAP,TRUE);
2228             flush_glyph_buffer( amii_wins[ WIN_MAP ]->win );
2229         }
2230     }
2231 }
2232
2233 void
2234 amii_setclipped()
2235 {
2236 #ifdef  CLIPPING
2237     clipping = TRUE;
2238     clipx=clipy=0;
2239     clipxmax=CO;
2240     clipymax=LI;
2241 /* some of this is now redundant with top of amii_cliparound XXX */
2242 #endif
2243 }
2244
2245 /* XXX still to do: suppress scrolling if we violate the boundary but the
2246  * edge of the map is already displayed
2247  */
2248 void
2249 amii_cliparound(x,y)
2250     register int x,y;
2251 {
2252     extern boolean restoring;
2253 #ifdef  CLIPPING
2254     int oldx = clipx, oldy = clipy;
2255     int oldxmax = clipxmax, oldymax = clipymax;
2256     int COx, LIx;
2257 #define SCROLLCNT       1       /* Get there in 3 moves... */
2258     int scrollcnt = SCROLLCNT;  /* ...or 1 if we changed level */
2259     if (!clipping)              /* And 1 in anycase, cleaner, simpler, quicker */
2260         return;
2261
2262     if(Is_rogue_level(&u.uz)){
2263         struct Window *w = amii_wins[WIN_MAP]->win;
2264         struct RastPort *rp = w->RPort;
2265
2266         COx = (w->Width-w->BorderLeft-w->BorderRight)/rp->TxWidth;
2267         LIx = (w->Height-w->BorderTop-w->BorderBottom)/rp->TxHeight;
2268     }else{
2269         COx = CO;
2270         LIx = LI;
2271     }
2272                 /*
2273                  * On a level change, move the clipping region so that for a
2274                  * reasonablely large window extra motion is avoided; for
2275                  * the rogue level hopefully this means no motion at all.
2276                  */
2277     {
2278         static d_level saved_level = {127,127};         /* XXX */
2279
2280         if(!on_level(&u.uz, &saved_level)){
2281             scrollcnt = 1;      /* jump with blanking */
2282             clipx=clipy=0;
2283             clipxmax = COx; clipymax = LIx;
2284             saved_level = u.uz;         /* save as new current level */
2285         }
2286     }
2287
2288     if (x <= clipx + xclipbord ) {
2289         clipx = max(0, x - (clipxmax - clipx)/2 );
2290         clipxmax = clipx + COx;
2291     }
2292     else if (x > clipxmax - xclipbord ) {
2293         clipxmax = min(COLNO, x + (clipxmax - clipx)/2 );
2294         clipx = clipxmax - COx;
2295     }
2296
2297     if (y <= clipy + yclipbord ) {
2298         clipy = max(0, y - (clipymax - clipy) / 2);
2299         clipymax = clipy + LIx;
2300     }
2301     else if (y > clipymax - yclipbord ) {
2302         clipymax = min(ROWNO, y + (clipymax - clipy) / 2);
2303         clipy = clipymax - LIx;
2304     }
2305
2306     reclip = 1;
2307     if (clipx != oldx || clipy != oldy || clipxmax != oldxmax || clipymax != oldymax )
2308     {
2309 #ifndef NOSCROLLRASTER
2310         struct Window *w = amii_wins[ WIN_MAP ]->win;
2311         struct RastPort *rp = w->RPort;
2312         int xdelta, ydelta, xmod, ymod, i;
2313         int incx, incy, mincx, mincy;
2314         int savex, savey, savexmax, saveymax;
2315         int scrx, scry;
2316
2317         if(Is_rogue_level(&u.uz)){
2318             scrx = rp->TxWidth;
2319             scry = rp->TxHeight;
2320         } else {
2321             scrx = mxsize;
2322             scry = mysize;
2323         }
2324
2325         /* Ask that the glyph routines not draw the overview window */
2326         reclip = 2;
2327         cursor_off( WIN_MAP );
2328
2329         /* Compute how far we are moving in terms of tiles */
2330         mincx = clipx - oldx ;
2331         mincy = clipy - oldy ;
2332
2333         /* How many tiles to get there in SCROLLCNT moves */
2334         incx = ( clipx - oldx )/scrollcnt;
2335         incy = ( clipy - oldy )/scrollcnt;
2336
2337         /* If less than SCROLLCNT tiles, then move by 1 tile if moving at all */
2338         if( incx == 0 ) incx = (mincx != 0);
2339         if( incy == 0 ) incy = (mincy != 0);
2340
2341         /* Get count of pixels to move each iteration and final pixel count */
2342         xdelta = ((clipx-oldx )*scrx) / scrollcnt;
2343         xmod = ((clipx-oldx )*scrx) % scrollcnt;
2344         ydelta = ((clipy-oldy )*scry) / scrollcnt;
2345         ymod = ((clipy-oldy )*scry) % scrollcnt;
2346
2347         /* Preserve the final move location */
2348         savex = clipx;
2349         savey = clipy;
2350         saveymax = clipymax;
2351         savexmax = clipxmax;
2352
2353         /*
2354          * Set clipping rectangle to be just the region that will be exposed so
2355          * that drawing will be faster
2356          */
2357 #if 0   /* Doesn't seem to work quite the way it should */
2358         /* In some cases hero is 'centered' offscreen */
2359         if( xdelta < 0 )
2360         {
2361             clipx = oldx;
2362             clipxmax = clipx + incx;
2363         }
2364         else if( xdelta > 0 )
2365         {
2366             clipxmax = oldxmax;
2367             clipx = clipxmax - incx;
2368         }
2369         else
2370         {
2371             clipx = oldx;
2372             clipxmax = oldxmax;
2373         }
2374
2375         if( ydelta < 0 )
2376         {
2377             clipy = oldy;
2378             clipymax = clipy + incy;
2379         }
2380         else if( ydelta > 0 )
2381         {
2382             clipymax = oldymax;
2383             clipy = clipymax - incy;
2384         }
2385         else
2386         {
2387             clipy = oldy;
2388             clipymax = oldymax;
2389         }
2390 #endif
2391         /* Now, in scrollcnt moves, move the picture toward the final view */
2392         for( i = 0; i < scrollcnt; ++i )
2393         {
2394 #ifdef  DISPMAP
2395             if( i == scrollcnt - 1 && (xmod != 0 || ymod != 0) &&
2396                         (xdelta != 0 || ydelta != 0) )
2397             {
2398                 incx += (clipx - oldx)%scrollcnt;
2399                 incy += (clipy - oldy)%scrollcnt;
2400                 xdelta += xmod;
2401                 ydelta += ymod;
2402             }
2403 #endif
2404             /* Scroll the raster if we are scrolling */
2405             if( xdelta != 0 || ydelta != 0 )
2406             {
2407                 ScrollRaster( rp, xdelta, ydelta,
2408                             w->BorderLeft, w->BorderTop,
2409                             w->Width - w->BorderRight - 1,
2410                             w->Height - w->BorderBottom - 1 );
2411
2412                 if( mincx == 0 ) incx = 0;
2413                 else mincx -= incx;
2414
2415                 clipx += incx;
2416                 clipxmax += incx;
2417
2418                 if( mincy == 0 ) incy = 0;
2419                 else mincy -= incy;
2420
2421                 clipy += incy;
2422                 clipymax += incy;
2423
2424                 /* Draw the exposed portion */
2425                 if (on_level(&u.uz0, &u.uz) && !restoring)
2426                     (void) doredraw();
2427                 flush_glyph_buffer( amii_wins[ WIN_MAP ]->win );
2428             }
2429         }
2430
2431         clipx = savex;
2432         clipy = savey;
2433         clipymax = saveymax;
2434         clipxmax = savexmax;
2435 #endif
2436         if (on_level(&u.uz0, &u.uz) && !restoring && moves > 1)
2437             (void) doredraw();
2438         flush_glyph_buffer( amii_wins[ WIN_MAP ]->win );
2439     }
2440     reclip = 0;
2441 #endif
2442 }
2443
2444 void
2445 flushIDCMP( port )
2446         struct MsgPort *port;
2447 {
2448         struct Message *msg;
2449         while( msg = GetMsg( port ) )
2450                 ReplyMsg( msg );
2451 }