OSDN Git Service

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