If an old port is resurrected to work with current version code, its files can be relocated to the appropriate sys or win folder as required. In the meantime, the burden of upkeep can be avoided for the stuff in the outdated folder for now.
2334 lines
67 KiB
C
2334 lines
67 KiB
C
/* 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 $ */
|
|
/* Copyright (c) Gregg Wonderly, Naperville, Illinois, 1991,1992,1993,1996.
|
|
*/
|
|
/* NetHack may be freely redistributed. See license for details. */
|
|
|
|
#include "NH:sys/amiga/windefs.h"
|
|
#include "NH:sys/amiga/winext.h"
|
|
#include "NH:sys/amiga/winproto.h"
|
|
#include "patchlevel.h"
|
|
#include "date.h"
|
|
|
|
extern struct TagItem scrntags[];
|
|
|
|
static BitMapHeader amii_bmhd;
|
|
static void cursor_common(struct RastPort *, int, int);
|
|
|
|
#ifdef CLIPPING
|
|
int CO, LI;
|
|
|
|
/* Changing clipping region, skip clear of screen in overview window. */
|
|
int reclip;
|
|
|
|
/* Must be set to at least two or you will get stuck! */
|
|
int xclipbord = 4, yclipbord = 2;
|
|
#endif
|
|
|
|
int mxsize, mysize;
|
|
struct Rectangle amii_oldover;
|
|
struct Rectangle amii_oldmsg;
|
|
|
|
extern struct TextFont *RogueFont;
|
|
|
|
int amii_msgAPen;
|
|
int amii_msgBPen;
|
|
int amii_statAPen;
|
|
int amii_statBPen;
|
|
int amii_menuAPen;
|
|
int amii_menuBPen;
|
|
int amii_textAPen;
|
|
int amii_textBPen;
|
|
int amii_otherAPen;
|
|
int amii_otherBPen;
|
|
long amii_libvers = LIBRARY_FONT_VERSION;
|
|
|
|
void
|
|
ami_wininit_data(dir)
|
|
int dir;
|
|
{
|
|
extern unsigned short amii_init_map[AMII_MAXCOLORS];
|
|
extern unsigned short amiv_init_map[AMII_MAXCOLORS];
|
|
|
|
if (dir != WININIT)
|
|
return;
|
|
|
|
if (!WINVERS_AMIV) {
|
|
#ifdef TEXTCOLOR
|
|
amii_numcolors = 8;
|
|
#else
|
|
amii_numcolors = 4;
|
|
#endif
|
|
amii_defpens[0] = C_BLACK; /* DETAILPEN */
|
|
amii_defpens[1] = C_BLUE; /* BLOCKPEN */
|
|
amii_defpens[2] = C_BROWN; /* TEXTPEN */
|
|
amii_defpens[3] = C_WHITE; /* SHINEPEN */
|
|
amii_defpens[4] = C_BLUE; /* SHADOWPEN */
|
|
amii_defpens[5] = C_CYAN; /* FILLPEN */
|
|
amii_defpens[6] = C_WHITE; /* FILLTEXTPEN */
|
|
amii_defpens[7] = C_CYAN; /* BACKGROUNDPEN */
|
|
amii_defpens[8] = C_RED; /* HIGHLIGHTTEXTPEN */
|
|
amii_defpens[9] = C_WHITE; /* BARDETAILPEN */
|
|
amii_defpens[10] = C_CYAN; /* BARBLOCKPEN */
|
|
amii_defpens[11] = C_BLUE; /* BARTRIMPEN */
|
|
amii_defpens[12] = (unsigned short) ~0;
|
|
|
|
amii_msgAPen = C_WHITE;
|
|
amii_msgBPen = C_BLACK;
|
|
amii_statAPen = C_WHITE;
|
|
amii_statBPen = C_BLACK;
|
|
amii_menuAPen = C_WHITE;
|
|
amii_menuBPen = C_BLACK;
|
|
amii_textAPen = C_WHITE;
|
|
amii_textBPen = C_BLACK;
|
|
amii_otherAPen = C_RED;
|
|
amii_otherBPen = C_BLACK;
|
|
|
|
mxsize = 8;
|
|
mysize = 8;
|
|
|
|
amii_libvers = LIBRARY_FONT_VERSION;
|
|
memcpy(amii_initmap, amii_init_map, sizeof(amii_initmap));
|
|
} else {
|
|
mxsize = 16;
|
|
mysize = 16;
|
|
|
|
amii_numcolors = 16;
|
|
|
|
amii_defpens[0] = C_BLACK; /* DETAILPEN */
|
|
amii_defpens[1] = C_WHITE; /* BLOCKPEN */
|
|
amii_defpens[2] = C_BLACK; /* TEXTPEN */
|
|
amii_defpens[3] = C_CYAN; /* SHINEPEN */
|
|
amii_defpens[4] = C_BLUE; /* SHADOWPEN */
|
|
amii_defpens[5] = C_GREYBLUE; /* FILLPEN */
|
|
amii_defpens[6] = C_LTGREY; /* FILLTEXTPEN */
|
|
amii_defpens[7] = C_GREYBLUE; /* BACKGROUNDPEN */
|
|
amii_defpens[8] = C_RED; /* HIGHLIGHTTEXTPEN */
|
|
amii_defpens[9] = C_WHITE; /* BARDETAILPEN */
|
|
amii_defpens[10] = C_GREYBLUE; /* BARBLOCKPEN */
|
|
amii_defpens[11] = C_BLUE; /* BARTRIMPEN */
|
|
amii_defpens[12] = (unsigned short) ~0;
|
|
|
|
amii_msgAPen = C_WHITE;
|
|
amii_msgBPen = C_GREYBLUE;
|
|
amii_statAPen = C_WHITE;
|
|
amii_statBPen = C_GREYBLUE;
|
|
amii_menuAPen = C_BLACK;
|
|
amii_menuBPen = C_LTGREY;
|
|
amii_textAPen = C_BLACK;
|
|
amii_textBPen = C_LTGREY;
|
|
amii_otherAPen = C_RED;
|
|
amii_otherBPen = C_BLACK;
|
|
amii_libvers = LIBRARY_TILE_VERSION;
|
|
|
|
memcpy(amii_initmap, amiv_init_map, sizeof(amii_initmap));
|
|
}
|
|
#ifdef OPT_DISPMAP
|
|
dispmap_sanity();
|
|
#endif
|
|
memcpy(sysflags.amii_dripens, amii_defpens,
|
|
sizeof(sysflags.amii_dripens));
|
|
}
|
|
|
|
#ifdef INTUI_NEW_LOOK
|
|
struct Hook SM_FilterHook;
|
|
struct Hook fillhook;
|
|
struct TagItem wintags[] = {
|
|
{ WA_BackFill, (ULONG) &fillhook },
|
|
{ WA_PubScreenName, (ULONG) "NetHack" },
|
|
{ TAG_END, 0 },
|
|
};
|
|
#endif
|
|
|
|
void amii_destroy_nhwindow(win) /* just hide */
|
|
register winid win;
|
|
{
|
|
int i;
|
|
int type;
|
|
register struct amii_WinDesc *cw;
|
|
|
|
if (win == WIN_ERR || (cw = amii_wins[win]) == NULL) {
|
|
panic(winpanicstr, win, "destroy_nhwindow");
|
|
}
|
|
|
|
if (WINVERS_AMIV) {
|
|
if (cw->type == NHW_MAP) {
|
|
/* If inventory is up, close it now, it will be freed later */
|
|
if (alwaysinvent && WIN_INVEN != WIN_ERR && amii_wins[WIN_INVEN]
|
|
&& amii_wins[WIN_INVEN]->win) {
|
|
dismiss_nhwindow(WIN_INVEN);
|
|
}
|
|
|
|
/* Tear down overview window if it is up */
|
|
if (WIN_OVER != WIN_ERR) {
|
|
amii_destroy_nhwindow(WIN_OVER);
|
|
WIN_OVER = WIN_ERR;
|
|
}
|
|
} else if (cw->type == NHW_OVER) {
|
|
struct Window *w = amii_wins[WIN_OVER]->win;
|
|
amii_oldover.MinX = w->LeftEdge;
|
|
amii_oldover.MinY = w->TopEdge;
|
|
amii_oldover.MaxX = w->Width;
|
|
amii_oldover.MaxY = w->Height;
|
|
|
|
if (WIN_MESSAGE != WIN_ERR && amii_wins[WIN_MESSAGE]) {
|
|
w = amii_wins[WIN_MESSAGE]->win;
|
|
amii_oldmsg.MinX = w->LeftEdge;
|
|
amii_oldmsg.MinY = w->TopEdge;
|
|
amii_oldmsg.MaxX = w->Width;
|
|
amii_oldmsg.MaxY = w->Height;
|
|
SizeWindow(amii_wins[WIN_MESSAGE]->win,
|
|
(amiIDisplay->xpix
|
|
- amii_wins[WIN_MESSAGE]->win->LeftEdge)
|
|
- amii_wins[WIN_MESSAGE]->win->Width,
|
|
0);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Tear down the Intuition stuff */
|
|
dismiss_nhwindow(win);
|
|
type = cw->type;
|
|
|
|
if (cw->resp) {
|
|
free(cw->resp);
|
|
cw->resp = NULL;
|
|
}
|
|
if (cw->canresp) {
|
|
free(cw->canresp);
|
|
cw->canresp = NULL;
|
|
}
|
|
if (cw->morestr) {
|
|
free(cw->morestr);
|
|
cw->morestr = NULL;
|
|
}
|
|
if (cw->hook) {
|
|
free(cw->hook);
|
|
cw->hook = NULL;
|
|
}
|
|
|
|
if (cw->data && (cw->type == NHW_MESSAGE || cw->type == NHW_MENU
|
|
|| cw->type == NHW_TEXT)) {
|
|
for (i = 0; i < cw->maxrow; ++i) {
|
|
if (cw->data[i])
|
|
free(cw->data[i]);
|
|
}
|
|
free(cw->data);
|
|
}
|
|
|
|
free(cw);
|
|
amii_wins[win] = NULL;
|
|
|
|
/* Set globals to WIN_ERR for known one-of-a-kind windows. */
|
|
if (win == WIN_MAP)
|
|
WIN_MAP = WIN_ERR;
|
|
else if (win == WIN_STATUS)
|
|
WIN_STATUS = WIN_ERR;
|
|
else if (win == WIN_MESSAGE)
|
|
WIN_MESSAGE = WIN_ERR;
|
|
else if (win == WIN_INVEN)
|
|
WIN_INVEN = WIN_ERR;
|
|
}
|
|
|
|
#ifdef INTUI_NEW_LOOK
|
|
struct FillParams {
|
|
struct Layer *layer;
|
|
struct Rectangle bounds;
|
|
WORD offsetx;
|
|
WORD offsety;
|
|
};
|
|
|
|
#ifdef __GNUC__
|
|
#ifdef __PPC__
|
|
void PPC_LayerFillHook(void);
|
|
struct EmulLibEntry LayerFillHook = { TRAP_LIB, 0,
|
|
(void (*)(void)) PPC_LayerFillHook };
|
|
void
|
|
PPC_LayerFillHook(void)
|
|
{
|
|
struct Hook *hk = (struct Hook *) REG_A0;
|
|
struct RastPort *rp = (struct RastPort *) REG_A2;
|
|
struct FillParams *fp = (struct FillParams *) REG_A1;
|
|
#else
|
|
void
|
|
LayerFillHook(void)
|
|
{
|
|
register struct Hook *hk asm("a0");
|
|
register struct RastPort *rp asm("a2");
|
|
register struct FillParams *fp asm("a1");
|
|
#endif
|
|
#else
|
|
void
|
|
#ifndef _DCC
|
|
__interrupt
|
|
#endif
|
|
__saveds __asm LayerFillHook(register __a0 struct Hook *hk,
|
|
register __a2 struct RastPort *rp,
|
|
register __a1 struct FillParams *fp)
|
|
{
|
|
#endif
|
|
|
|
register long x, y, xmax, ymax;
|
|
register int apen;
|
|
struct RastPort rptmp;
|
|
|
|
memcpy(&rptmp, rp, sizeof(struct RastPort));
|
|
rptmp.Layer = NULL;
|
|
|
|
switch ((int) hk->h_Data) {
|
|
case NHW_STATUS:
|
|
apen = amii_statBPen;
|
|
break;
|
|
case NHW_MESSAGE:
|
|
apen = amii_msgBPen;
|
|
break;
|
|
case NHW_TEXT:
|
|
apen = amii_textBPen;
|
|
break;
|
|
case NHW_MENU:
|
|
apen = amii_menuBPen;
|
|
break;
|
|
case -2:
|
|
apen = amii_otherBPen;
|
|
break;
|
|
case NHW_BASE:
|
|
case NHW_MAP:
|
|
case NHW_OVER:
|
|
default:
|
|
apen = C_BLACK;
|
|
break;
|
|
}
|
|
|
|
x = fp->bounds.MinX;
|
|
y = fp->bounds.MinY;
|
|
xmax = fp->bounds.MaxX;
|
|
ymax = fp->bounds.MaxY;
|
|
|
|
SetAPen(&rptmp, apen);
|
|
SetBPen(&rptmp, apen);
|
|
SetDrMd(&rptmp, JAM2);
|
|
RectFill(&rptmp, x, y, xmax, ymax);
|
|
}
|
|
#endif
|
|
|
|
amii_create_nhwindow(type) register int type;
|
|
{
|
|
register struct Window *w = NULL;
|
|
register struct NewWindow *nw = NULL;
|
|
register struct amii_WinDesc *wd = NULL;
|
|
struct Window *mapwin = NULL, *stwin = NULL, *msgwin = NULL;
|
|
register int newid;
|
|
int maph, stath, scrfontysize;
|
|
|
|
scrfontysize = HackScreen->Font->ta_YSize;
|
|
|
|
/*
|
|
* Initial mapwindow height, this might change later in tilemode
|
|
* and low screen
|
|
*/
|
|
maph = (21 * mxsize) + 2
|
|
+ (bigscreen
|
|
? HackScreen->WBorTop + HackScreen->WBorBottom
|
|
+ scrfontysize + 1
|
|
: 0);
|
|
|
|
/* Status window height, avoids having to calculate many times */
|
|
stath =
|
|
txheight * 2 + 2 + (WINVERS_AMIV || bigscreen
|
|
? HackScreen->WBorTop + HackScreen->WBorBottom
|
|
+ (bigscreen ? scrfontysize + 1 : 0)
|
|
: 0);
|
|
|
|
if (WIN_STATUS != WIN_ERR && amii_wins[WIN_STATUS])
|
|
stwin = amii_wins[WIN_STATUS]->win;
|
|
|
|
if (WIN_MESSAGE != WIN_ERR && amii_wins[WIN_MESSAGE])
|
|
msgwin = amii_wins[WIN_MESSAGE]->win;
|
|
|
|
if (WIN_MAP != WIN_ERR && amii_wins[WIN_MAP])
|
|
mapwin = amii_wins[WIN_MAP]->win;
|
|
|
|
/* Create Port anytime that we need it */
|
|
|
|
if (HackPort == NULL) {
|
|
HackPort = CreateMsgPort();
|
|
if (!HackPort)
|
|
panic("no memory for msg port");
|
|
}
|
|
|
|
nw = &new_wins[type].newwin;
|
|
nw->Width = amiIDisplay->xpix;
|
|
nw->Screen = HackScreen;
|
|
|
|
if (WINVERS_AMIV) {
|
|
nw->DetailPen = C_WHITE;
|
|
nw->BlockPen = C_GREYBLUE;
|
|
} else {
|
|
nw->DetailPen = C_WHITE;
|
|
nw->BlockPen = C_BLACK;
|
|
}
|
|
|
|
if (type == NHW_BASE) {
|
|
nw->LeftEdge = 0;
|
|
nw->TopEdge = HackScreen->BarHeight + 1;
|
|
nw->Width = HackScreen->Width;
|
|
nw->Height = HackScreen->Height - nw->TopEdge;
|
|
} else if (!WINVERS_AMIV && type == NHW_MAP) {
|
|
nw->LeftEdge = 0;
|
|
nw->Height = maph;
|
|
|
|
if (msgwin && stwin) {
|
|
nw->TopEdge = stwin->TopEdge - maph;
|
|
} else {
|
|
panic("msgwin and stwin must open before map");
|
|
}
|
|
if (nw->TopEdge < 0)
|
|
panic("Too small screen to fit map");
|
|
} else if (type == NHW_MAP && WINVERS_AMIV) {
|
|
struct Window *w;
|
|
|
|
w = amii_wins[WIN_MESSAGE]->win;
|
|
nw->LeftEdge = 0;
|
|
nw->TopEdge = w->TopEdge + w->Height;
|
|
nw->Width = amiIDisplay->xpix - nw->LeftEdge;
|
|
|
|
w = amii_wins[WIN_STATUS]->win;
|
|
nw->Height = w->TopEdge - nw->TopEdge;
|
|
nw->MaxHeight = 0xffff;
|
|
nw->MaxWidth = 0xffff;
|
|
|
|
if (nw->TopEdge + nw->Height > amiIDisplay->ypix - 1)
|
|
nw->Height = amiIDisplay->ypix - nw->TopEdge - 1;
|
|
} else if (type == NHW_STATUS) {
|
|
if (!WINVERS_AMIV && (WIN_MAP != WIN_ERR && amii_wins[WIN_MAP]))
|
|
w = amii_wins[WIN_MAP]->win;
|
|
else if (WIN_BASE != WIN_ERR && amii_wins[WIN_BASE])
|
|
w = amii_wins[WIN_BASE]->win;
|
|
else
|
|
panic("No window to base STATUS location from");
|
|
|
|
nw->Height = stath;
|
|
nw->TopEdge = amiIDisplay->ypix - nw->Height;
|
|
nw->LeftEdge = w->LeftEdge;
|
|
|
|
if (nw->LeftEdge + nw->Width >= amiIDisplay->xpix)
|
|
nw->LeftEdge = 0;
|
|
|
|
if (nw->Width >= amiIDisplay->xpix - nw->LeftEdge)
|
|
nw->Width = amiIDisplay->xpix - nw->LeftEdge;
|
|
} else if (WINVERS_AMIV && type == NHW_OVER) {
|
|
nw->Flags |= WINDOWSIZING | WINDOWDRAG | WINDOWCLOSE;
|
|
nw->IDCMPFlags |= CLOSEWINDOW;
|
|
/* Bring up window as half the width of the message window, and make
|
|
* the message window change to one half the width...
|
|
*/
|
|
if (amii_oldover.MaxX != 0) {
|
|
nw->LeftEdge = amii_oldover.MinX;
|
|
nw->TopEdge = amii_oldover.MinY;
|
|
nw->Width = amii_oldover.MaxX;
|
|
nw->Height = amii_oldover.MaxY;
|
|
ChangeWindowBox(amii_wins[WIN_MESSAGE]->win, amii_oldmsg.MinX,
|
|
amii_oldmsg.MinY, amii_oldmsg.MaxX,
|
|
amii_oldmsg.MaxY);
|
|
} else {
|
|
nw->LeftEdge = (amii_wins[WIN_MESSAGE]->win->Width * 4) / 9;
|
|
nw->TopEdge = amii_wins[WIN_MESSAGE]->win->TopEdge;
|
|
nw->Width = amiIDisplay->xpix - nw->LeftEdge;
|
|
nw->Height = amii_wins[WIN_MESSAGE]->win->Height;
|
|
SizeWindow(amii_wins[WIN_MESSAGE]->win,
|
|
nw->LeftEdge - amii_wins[WIN_MESSAGE]->win->Width, 0);
|
|
}
|
|
} else if (type == NHW_MESSAGE) {
|
|
if (!WINVERS_AMIV && (WIN_MAP != WIN_ERR && amii_wins[WIN_MAP]))
|
|
w = amii_wins[WIN_MAP]->win;
|
|
else if (WIN_BASE != WIN_ERR && amii_wins[WIN_BASE])
|
|
w = amii_wins[WIN_BASE]->win;
|
|
else
|
|
panic("No window to base STATUS location from");
|
|
|
|
nw->TopEdge = bigscreen ? HackScreen->BarHeight + 1 : 0;
|
|
|
|
/* Assume highest possible message window */
|
|
nw->Height = HackScreen->Height - nw->TopEdge - maph - stath;
|
|
|
|
/* In tilemode we can cope with this */
|
|
if (WINVERS_AMIV && nw->Height < 0)
|
|
nw->Height = 0;
|
|
|
|
/* If in fontmode messagewindow is too small, open it with 3 lines
|
|
and overlap it with map */
|
|
if (nw->Height < txheight + 2) {
|
|
nw->Height = txheight * 4 + 3 + HackScreen->WBorTop
|
|
+ HackScreen->WBorBottom;
|
|
}
|
|
|
|
if ((nw->Height - 2) / txheight < 3) {
|
|
scrollmsg = 0;
|
|
nw->Title = 0;
|
|
} else {
|
|
nw->FirstGadget = &MsgScroll;
|
|
nw->Flags |= WINDOWSIZING | WINDOWDRAG;
|
|
nw->Flags &= ~BORDERLESS;
|
|
|
|
if (WINVERS_AMIV || nw->Height == 0) {
|
|
if (WINVERS_AMIV) {
|
|
nw->Height = TextsFont->tf_YSize + HackScreen->WBorTop + 3
|
|
+ HackScreen->WBorBottom;
|
|
if (bigscreen)
|
|
nw->Height += (txheight * 6);
|
|
else
|
|
nw->Height += (txheight * 3);
|
|
} else {
|
|
nw->Height =
|
|
HackScreen->Height - nw->TopEdge - stath - maph;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Do we have room for larger message window ?
|
|
* This is possible if we can show full height map in tile
|
|
* mode with default scaling.
|
|
*/
|
|
if (nw->Height + stath + maph < HackScreen->Height - nw->TopEdge)
|
|
nw->Height = HackScreen->Height - nw->TopEdge - 1 - maph - stath;
|
|
|
|
#ifdef INTUI_NEW_LOOK
|
|
if (IntuitionBase->LibNode.lib_Version >= 37) {
|
|
MsgPropScroll.Flags |= PROPNEWLOOK;
|
|
PropScroll.Flags |= PROPNEWLOOK;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
nw->IDCMPFlags |= MENUPICK;
|
|
|
|
/* Check if there is "Room" for all this stuff... */
|
|
if ((WINVERS_AMIV || bigscreen) && type != NHW_BASE) {
|
|
nw->Flags &= ~(BORDERLESS | BACKDROP);
|
|
|
|
if (WINVERS_AMIV) {
|
|
if (type == NHW_STATUS) {
|
|
nw->Flags &=
|
|
~(WINDOWDRAG | WINDOWDEPTH | SIZEBRIGHT | WINDOWSIZING);
|
|
nw->IDCMPFlags &= ~NEWSIZE;
|
|
} else {
|
|
nw->Flags |=
|
|
(WINDOWDRAG | WINDOWDEPTH | SIZEBRIGHT | WINDOWSIZING);
|
|
nw->IDCMPFlags |= NEWSIZE;
|
|
}
|
|
} else {
|
|
if (HackScreen->Width < 657) {
|
|
nw->Flags |= (WINDOWDRAG | WINDOWDEPTH);
|
|
} else {
|
|
nw->Flags |= (WINDOWDRAG | WINDOWDEPTH | SIZEBRIGHT);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (WINVERS_AMII && type == NHW_MAP)
|
|
nw->Flags &= ~WINDOWSIZING;
|
|
|
|
if (type == NHW_MESSAGE && scrollmsg) {
|
|
nw->Flags |= WINDOWDRAG | WINDOWDEPTH | SIZEBRIGHT | WINDOWSIZING;
|
|
nw->Flags &= ~BORDERLESS;
|
|
}
|
|
|
|
/* No titles on a hires only screen except for messagewindow */
|
|
if (!(WINVERS_AMIV && type == NHW_MAP) && !bigscreen
|
|
&& type != NHW_MESSAGE)
|
|
nw->Title = 0;
|
|
|
|
wd = (struct amii_WinDesc *) alloc(sizeof(struct amii_WinDesc));
|
|
memset(wd, 0, sizeof(struct amii_WinDesc));
|
|
|
|
/* Both, since user may have changed the pen settings so respect those */
|
|
if (WINVERS_AMII || WINVERS_AMIV) {
|
|
/* Special backfill for these types of layers */
|
|
switch (type) {
|
|
case NHW_MESSAGE:
|
|
case NHW_STATUS:
|
|
case NHW_TEXT:
|
|
case NHW_MENU:
|
|
case NHW_BASE:
|
|
case NHW_OVER:
|
|
case NHW_MAP:
|
|
if (wd) {
|
|
#ifdef __GNUC__
|
|
fillhook.h_Entry = (void *) &LayerFillHook;
|
|
#else
|
|
fillhook.h_Entry = (ULONG (*) ()) LayerFillHook;
|
|
#endif
|
|
fillhook.h_Data = (void *) type;
|
|
fillhook.h_SubEntry = 0;
|
|
wd->hook = alloc(sizeof(fillhook));
|
|
memcpy(wd->hook, &fillhook, sizeof(fillhook));
|
|
memcpy(wd->wintags, wintags, sizeof(wd->wintags));
|
|
wd->wintags[0].ti_Data = (long) wd->hook;
|
|
nw->Extension = (void *) wd->wintags;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Don't open MENU or TEXT windows yet */
|
|
|
|
if (type == NHW_MENU || type == NHW_TEXT)
|
|
w = NULL;
|
|
else
|
|
w = OpenShWindow((void *) nw);
|
|
|
|
if (w == NULL && type != NHW_MENU && type != NHW_TEXT) {
|
|
char buf[100];
|
|
|
|
sprintf(buf, "nw type (%d) dims l: %d, t: %d, w: %d, h: %d", type,
|
|
nw->LeftEdge, nw->TopEdge, nw->Width, nw->Height);
|
|
raw_print(buf);
|
|
panic("bad openwin %d", type);
|
|
}
|
|
|
|
/* Check for an empty slot */
|
|
|
|
for (newid = 0; newid < MAXWIN + 1; newid++) {
|
|
if (amii_wins[newid] == 0)
|
|
break;
|
|
}
|
|
|
|
if (newid == MAXWIN + 1)
|
|
panic("time to write re-alloc code\n");
|
|
|
|
/* Set wincnt accordingly */
|
|
|
|
if (newid > wincnt)
|
|
wincnt = newid;
|
|
|
|
/* Do common initialization */
|
|
|
|
amii_wins[newid] = wd;
|
|
|
|
wd->newwin = NULL;
|
|
wd->win = w;
|
|
wd->type = type;
|
|
wd->wflags = 0;
|
|
wd->active = FALSE;
|
|
wd->curx = wd->cury = 0;
|
|
wd->resp = wd->canresp = wd->morestr = 0; /* CHECK THESE */
|
|
wd->maxrow = new_wins[type].maxrow;
|
|
wd->maxcol = new_wins[type].maxcol;
|
|
|
|
if (type != NHW_TEXT && type != NHW_MENU) {
|
|
if (TextsFont && (type == NHW_MESSAGE || type == NHW_STATUS)) {
|
|
SetFont(w->RPort, TextsFont);
|
|
txheight = w->RPort->TxHeight;
|
|
txwidth = w->RPort->TxWidth;
|
|
txbaseline = w->RPort->TxBaseline;
|
|
if (type == NHW_MESSAGE) {
|
|
if (scrollmsg) {
|
|
if (WINVERS_AMIV) {
|
|
WindowLimits(w, 100, w->BorderTop + w->BorderBottom
|
|
+ ((txheight + 1) * 2) + 1,
|
|
0, 0);
|
|
} else {
|
|
WindowLimits(w, w->Width,
|
|
w->BorderTop + w->BorderBottom
|
|
+ ((txheight + 1) * 2) + 1,
|
|
0, 0);
|
|
}
|
|
} else {
|
|
WindowLimits(w, w->Width, w->BorderTop + w->BorderBottom
|
|
+ txheight + 2,
|
|
0, 0);
|
|
}
|
|
}
|
|
}
|
|
if (type != NHW_MAP) {
|
|
SetFont(w->RPort, TextsFont);
|
|
}
|
|
#ifdef HACKFONT
|
|
else if (HackFont)
|
|
SetFont(w->RPort, HackFont);
|
|
#endif
|
|
}
|
|
|
|
/* Text and menu windows are not opened yet */
|
|
if (w) {
|
|
wd->rows = (w->Height - w->BorderTop - w->BorderBottom - 2)
|
|
/ w->RPort->TxHeight;
|
|
wd->cols = (w->Width - w->BorderLeft - w->BorderRight - 2)
|
|
/ w->RPort->TxWidth;
|
|
}
|
|
|
|
/* Okay, now do the individual type initialization */
|
|
|
|
switch (type) {
|
|
/* History lines for MESSAGE windows are stored in cw->data[?].
|
|
* maxcol and maxrow are used as cursors. maxrow is the count
|
|
* of the number of history lines stored. maxcol is the cursor
|
|
* to the last line that was displayed by ^P.
|
|
*/
|
|
case NHW_MESSAGE:
|
|
SetMenuStrip(w, MenuStrip);
|
|
MsgScroll.TopEdge = HackScreen->WBorTop + scrfontysize + 1;
|
|
iflags.msg_history = wd->rows * 10;
|
|
if (iflags.msg_history < 40)
|
|
iflags.msg_history = 40;
|
|
if (iflags.msg_history > 400)
|
|
iflags.msg_history = 400;
|
|
iflags.window_inited = TRUE;
|
|
wd->data = (char **) alloc(iflags.msg_history * sizeof(char *));
|
|
memset(wd->data, 0, iflags.msg_history * sizeof(char *));
|
|
wd->maxrow = wd->maxcol = 0;
|
|
/* Indicate that we have not positioned the cursor yet */
|
|
wd->curx = -1;
|
|
break;
|
|
|
|
/* A MENU contains a list of lines in wd->data[?]. These
|
|
* lines are created in amii_putstr() by reallocating the size
|
|
* of wd->data to hold enough (char *)'s. wd->rows is the
|
|
* number of (char *)'s allocated. wd->maxrow is the number
|
|
* used. wd->maxcol is used to track how wide the menu needs
|
|
* to be. wd->resp[x] contains the characters that correspond
|
|
* to selecting wd->data[x]. wd->resp[x] corresponds to
|
|
* wd->data[x] for any x. Elements of wd->data[?] that are not
|
|
* valid selections have the corresponding element of
|
|
* wd->resp[] set to a value of '\01'; i.e. a ^A which is
|
|
* not currently a valid keystroke for responding to any
|
|
* MENU or TEXT window.
|
|
*/
|
|
case NHW_MENU:
|
|
MenuScroll.TopEdge = HackScreen->WBorTop + scrfontysize + 1;
|
|
wd->resp = (char *) alloc(256);
|
|
wd->resp[0] = 0;
|
|
wd->rows = wd->maxrow = 0;
|
|
wd->cols = wd->maxcol = 0;
|
|
wd->data = NULL;
|
|
break;
|
|
|
|
/* See the explanation of MENU above. Except, wd->resp[] is not
|
|
* used for TEXT windows since there is no selection of a
|
|
* a line performed/allowed. The window is always full
|
|
* screen width.
|
|
*/
|
|
case NHW_TEXT:
|
|
MenuScroll.TopEdge = HackScreen->WBorTop + scrfontysize + 1;
|
|
wd->rows = wd->maxrow = 0;
|
|
wd->cols = wd->maxcol = amiIDisplay->cols;
|
|
wd->data = NULL;
|
|
wd->morestr = NULL;
|
|
break;
|
|
|
|
/* The status window has only two lines. These are stored in
|
|
* wd->data[], and here we allocate the space for them.
|
|
*/
|
|
case NHW_STATUS:
|
|
SetMenuStrip(w, MenuStrip);
|
|
/* wd->cols is the number of characters which fit across the
|
|
* screen.
|
|
*/
|
|
wd->data = (char **) alloc(3 * sizeof(char *));
|
|
wd->data[0] = (char *) alloc(wd->cols + 10);
|
|
wd->data[1] = (char *) alloc(wd->cols + 10);
|
|
wd->data[2] = NULL;
|
|
break;
|
|
|
|
/* NHW_OVER does not use wd->data[] or the other text
|
|
* manipulating members of the amii_WinDesc structure.
|
|
*/
|
|
case NHW_OVER:
|
|
SetMenuStrip(w, MenuStrip);
|
|
break;
|
|
|
|
/* NHW_MAP does not use wd->data[] or the other text
|
|
* manipulating members of the amii_WinDesc structure.
|
|
*/
|
|
case NHW_MAP:
|
|
SetMenuStrip(w, MenuStrip);
|
|
if (WINVERS_AMIV) {
|
|
CO = (w->Width - w->BorderLeft - w->BorderRight) / mxsize;
|
|
LI = (w->Height - w->BorderTop - w->BorderBottom) / mysize;
|
|
amii_setclipped();
|
|
SetFont(w->RPort, RogueFont);
|
|
SetAPen(w->RPort, C_WHITE); /* XXX not sufficient */
|
|
SetBPen(w->RPort, C_BLACK);
|
|
SetDrMd(w->RPort, JAM2);
|
|
} else {
|
|
if (HackFont)
|
|
SetFont(w->RPort, HackFont);
|
|
}
|
|
break;
|
|
|
|
/* The base window must exist until CleanUp() deletes it. */
|
|
case NHW_BASE:
|
|
SetMenuStrip(w, MenuStrip);
|
|
/* Make our requesters come to our screen */
|
|
{
|
|
register struct Process *myProcess =
|
|
(struct Process *) FindTask(NULL);
|
|
pr_WindowPtr = (struct Window *) (myProcess->pr_WindowPtr);
|
|
myProcess->pr_WindowPtr = (APTR) w;
|
|
}
|
|
|
|
/* Need this for RawKeyConvert() */
|
|
|
|
ConsoleIO.io_Data = (APTR) w;
|
|
ConsoleIO.io_Length = sizeof(struct Window);
|
|
ConsoleIO.io_Message.mn_ReplyPort = CreateMsgPort();
|
|
if (OpenDevice("console.device", -1L, (struct IORequest *) &ConsoleIO,
|
|
0L) != 0) {
|
|
Abort(AG_OpenDev | AO_ConsoleDev);
|
|
}
|
|
|
|
ConsoleDevice = (struct Library *) ConsoleIO.io_Device;
|
|
|
|
KbdBuffered = 0;
|
|
|
|
#ifdef HACKFONT
|
|
if (TextsFont)
|
|
SetFont(w->RPort, TextsFont);
|
|
else if (HackFont)
|
|
SetFont(w->RPort, HackFont);
|
|
#endif
|
|
txwidth = w->RPort->TxWidth;
|
|
txheight = w->RPort->TxHeight;
|
|
txbaseline = w->RPort->TxBaseline;
|
|
break;
|
|
|
|
default:
|
|
panic("bad create_nhwindow( %d )\n", type);
|
|
return WIN_ERR;
|
|
}
|
|
|
|
return (newid);
|
|
}
|
|
|
|
#ifdef __GNUC__
|
|
#ifdef __PPC__
|
|
int PPC_SM_Filter(void);
|
|
struct EmulLibEntry SM_Filter = { TRAP_LIB, 0,
|
|
(int (*)(void)) PPC_SM_Filter };
|
|
int
|
|
PPC_SM_Filter(void)
|
|
{
|
|
struct Hook *hk = (struct Hook *) REG_A0;
|
|
ULONG modeID = (ULONG) REG_A1;
|
|
struct ScreenModeRequester *smr = (struct ScreenModeRequester *) REG_A2;
|
|
#else
|
|
int
|
|
SM_Filter(void)
|
|
{
|
|
register struct Hook *hk asm("a0");
|
|
register ULONG modeID asm("a1");
|
|
register struct ScreenModeRequester *smr asm("a2");
|
|
#endif
|
|
#else
|
|
int
|
|
#ifndef _DCC
|
|
__interrupt
|
|
#endif
|
|
__saveds __asm SM_Filter(
|
|
register __a0 struct Hook *hk, register __a1 ULONG modeID,
|
|
register __a2 struct ScreenModeRequester *smr)
|
|
{
|
|
#endif
|
|
struct DimensionInfo dims;
|
|
struct DisplayInfo disp;
|
|
DisplayInfoHandle handle;
|
|
handle = FindDisplayInfo(modeID);
|
|
if (handle) {
|
|
GetDisplayInfoData(handle, (char *) &dims, sizeof(dims), DTAG_DIMS,
|
|
modeID);
|
|
GetDisplayInfoData(handle, (char *) &disp, sizeof(disp), DTAG_DISP,
|
|
modeID);
|
|
if (!disp.NotAvailable && dims.MaxDepth <= 8
|
|
&& dims.StdOScan.MaxX >= WIDTH - 1
|
|
&& dims.StdOScan.MaxY >= SCREENHEIGHT - 1) {
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Initialize the windowing environment */
|
|
|
|
void
|
|
amii_init_nhwindows(argcp, argv)
|
|
int *argcp;
|
|
char **argv;
|
|
{
|
|
int i;
|
|
struct Screen *wbscr;
|
|
int forcenobig = 0;
|
|
|
|
if (HackScreen)
|
|
panic("init_nhwindows() called twice", 0);
|
|
|
|
/* run args & set bigscreen from -L(1)/-l(-1) */
|
|
{
|
|
int lclargc = *argcp;
|
|
int t;
|
|
char **argv_in = argv;
|
|
char **argv_out = argv;
|
|
|
|
for (t = 1; t <= lclargc; t++) {
|
|
if (!strcmp("-L", *argv_in) || !strcmp("-l", *argv_in)) {
|
|
bigscreen = (*argv_in[1] == 'l') ? -1 : 1;
|
|
/* and eat the flag */
|
|
(*argcp)--;
|
|
} else {
|
|
*argv_out = *argv_in; /* keep the flag */
|
|
argv_out++;
|
|
}
|
|
argv_in++;
|
|
}
|
|
*argv_out = 0;
|
|
}
|
|
|
|
WIN_MESSAGE = WIN_ERR;
|
|
WIN_MAP = WIN_ERR;
|
|
WIN_STATUS = WIN_ERR;
|
|
WIN_INVEN = WIN_ERR;
|
|
WIN_BASE = WIN_ERR;
|
|
WIN_OVER = WIN_ERR;
|
|
|
|
if ((IntuitionBase = (struct IntuitionBase *) OpenLibrary(
|
|
"intuition.library", amii_libvers)) == NULL) {
|
|
Abort(AG_OpenLib | AO_Intuition);
|
|
}
|
|
|
|
if ((GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",
|
|
amii_libvers)) == NULL) {
|
|
Abort(AG_OpenLib | AO_GraphicsLib);
|
|
}
|
|
|
|
if ((LayersBase = (struct Library *) OpenLibrary("layers.library",
|
|
amii_libvers)) == NULL) {
|
|
Abort(AG_OpenLib | AO_LayersLib);
|
|
}
|
|
|
|
if ((GadToolsBase = OpenLibrary("gadtools.library", amii_libvers))
|
|
== NULL) {
|
|
Abort(AG_OpenLib | AO_GadTools);
|
|
}
|
|
|
|
if ((AslBase = OpenLibrary("asl.library", amii_libvers)) == NULL) {
|
|
Abort(AG_OpenLib);
|
|
}
|
|
|
|
amiIDisplay =
|
|
(struct amii_DisplayDesc *) alloc(sizeof(struct amii_DisplayDesc));
|
|
memset(amiIDisplay, 0, sizeof(struct amii_DisplayDesc));
|
|
|
|
/* Use Intuition sizes for overscan screens... */
|
|
|
|
amiIDisplay->xpix = 0;
|
|
#ifdef INTUI_NEW_LOOK
|
|
if (IntuitionBase->LibNode.lib_Version >= 37) {
|
|
if (wbscr = LockPubScreen("Workbench")) {
|
|
amiIDisplay->xpix = wbscr->Width;
|
|
amiIDisplay->ypix = wbscr->Height;
|
|
UnlockPubScreen(NULL, wbscr);
|
|
}
|
|
}
|
|
#endif
|
|
if (amiIDisplay->xpix == 0) {
|
|
amiIDisplay->ypix = GfxBase->NormalDisplayRows;
|
|
amiIDisplay->xpix = GfxBase->NormalDisplayColumns;
|
|
}
|
|
|
|
amiIDisplay->cols = amiIDisplay->xpix / FONTWIDTH;
|
|
|
|
amiIDisplay->toplin = 0;
|
|
amiIDisplay->rawprint = 0;
|
|
amiIDisplay->lastwin = 0;
|
|
|
|
if (bigscreen == 0) {
|
|
if ((GfxBase->ActiView->ViewPort->Modes & LACE) == LACE) {
|
|
amiIDisplay->ypix *= 2;
|
|
NewHackScreen.ViewModes |= LACE;
|
|
bigscreen = 1;
|
|
} else if (GfxBase->NormalDisplayRows >= 300
|
|
|| amiIDisplay->ypix >= 300) {
|
|
bigscreen = 1;
|
|
}
|
|
} else if (bigscreen == -1) {
|
|
bigscreen = 0;
|
|
forcenobig = 1;
|
|
} else if (bigscreen) {
|
|
/* If bigscreen requested and we don't have enough rows in
|
|
* noninterlaced mode, switch to interlaced...
|
|
*/
|
|
if (GfxBase->NormalDisplayRows < 300) {
|
|
amiIDisplay->ypix *= 2;
|
|
NewHackScreen.ViewModes |= LACE;
|
|
}
|
|
}
|
|
|
|
if (!bigscreen) {
|
|
alwaysinvent = 0;
|
|
}
|
|
amiIDisplay->rows = amiIDisplay->ypix / FONTHEIGHT;
|
|
|
|
#ifdef HACKFONT
|
|
/*
|
|
* Load the fonts that we need.
|
|
*/
|
|
|
|
if (DiskfontBase = OpenLibrary("diskfont.library", amii_libvers)) {
|
|
Hack80.ta_Name -= SIZEOF_DISKNAME;
|
|
HackFont = OpenDiskFont(&Hack80);
|
|
Hack80.ta_Name += SIZEOF_DISKNAME;
|
|
|
|
/* Textsfont13 is filled in with "FONT=" settings. The default is
|
|
* courier/13.
|
|
*/
|
|
TextsFont = NULL;
|
|
if (bigscreen)
|
|
TextsFont = OpenDiskFont(&TextsFont13);
|
|
|
|
/* Try hack/8 for texts if no user specified font */
|
|
if (TextsFont == NULL) {
|
|
Hack80.ta_Name -= SIZEOF_DISKNAME;
|
|
TextsFont = OpenDiskFont(&Hack80);
|
|
Hack80.ta_Name += SIZEOF_DISKNAME;
|
|
}
|
|
|
|
/* If no fonts, make everything topaz 8 for non-view windows.
|
|
*/
|
|
Hack80.ta_Name = "topaz.font";
|
|
RogueFont = OpenFont(&Hack80);
|
|
if (!RogueFont)
|
|
panic("Can't get topaz:8");
|
|
if (!HackFont || !TextsFont) {
|
|
if (!HackFont) {
|
|
HackFont = OpenFont(&Hack80);
|
|
if (!HackFont)
|
|
panic("Can't get a map font, topaz:8");
|
|
}
|
|
|
|
if (!TextsFont) {
|
|
TextsFont = OpenFont(&Hack80);
|
|
if (!TextsFont)
|
|
panic("Can't open text font");
|
|
}
|
|
}
|
|
CloseLibrary(DiskfontBase);
|
|
DiskfontBase = NULL;
|
|
}
|
|
#endif
|
|
|
|
/* Adjust getlin window size to font */
|
|
|
|
if (TextsFont) {
|
|
extern SHORT BorderVectors1[];
|
|
extern SHORT BorderVectors2[];
|
|
extern struct Gadget Gadget2;
|
|
extern struct Gadget String;
|
|
extern struct NewWindow StrWindow;
|
|
BorderVectors1[2] +=
|
|
(TextsFont->tf_XSize - 8) * 6; /* strlen("Cancel") == 6 */
|
|
BorderVectors1[4] += (TextsFont->tf_XSize - 8) * 6;
|
|
BorderVectors1[5] += TextsFont->tf_YSize - 8;
|
|
BorderVectors1[7] += TextsFont->tf_YSize - 8;
|
|
BorderVectors2[2] += (TextsFont->tf_XSize - 8) * 6;
|
|
BorderVectors2[4] += (TextsFont->tf_XSize - 8) * 6;
|
|
BorderVectors2[5] += TextsFont->tf_YSize - 8;
|
|
BorderVectors2[7] += TextsFont->tf_YSize - 8;
|
|
Gadget2.TopEdge += TextsFont->tf_YSize - 8;
|
|
Gadget2.Width += (TextsFont->tf_XSize - 8) * 6;
|
|
Gadget2.Height += TextsFont->tf_YSize - 8;
|
|
String.LeftEdge += (TextsFont->tf_XSize - 8) * 6;
|
|
String.TopEdge += TextsFont->tf_YSize - 8;
|
|
String.Width += TextsFont->tf_XSize - 8;
|
|
String.Height += TextsFont->tf_YSize - 8;
|
|
StrWindow.Width += (TextsFont->tf_XSize - 8) * 7;
|
|
StrWindow.Height +=
|
|
(TextsFont->tf_YSize - 8) * 2; /* Titlebar + 1 row of gadgets */
|
|
}
|
|
|
|
/* This is the size screen we want to open, within reason... */
|
|
|
|
NewHackScreen.Width = max(WIDTH, amiIDisplay->xpix);
|
|
NewHackScreen.Height = max(SCREENHEIGHT, amiIDisplay->ypix);
|
|
{
|
|
static char fname[18];
|
|
sprintf(fname, "NetHack %d.%d.%d", VERSION_MAJOR, VERSION_MINOR,
|
|
PATCHLEVEL);
|
|
NewHackScreen.DefaultTitle = fname;
|
|
}
|
|
#if 0
|
|
NewHackScreen.BlockPen = C_BLACK;
|
|
NewHackScreen.DetailPen = C_WHITE;
|
|
#endif
|
|
#ifdef INTUI_NEW_LOOK
|
|
if (IntuitionBase->LibNode.lib_Version >= 37) {
|
|
int i;
|
|
struct DimensionInfo dims;
|
|
DisplayInfoHandle handle;
|
|
struct DisplayInfo disp;
|
|
ULONG modeid = DEFAULT_MONITOR_ID | HIRES_KEY;
|
|
|
|
NewHackScreen.Width = STDSCREENWIDTH;
|
|
NewHackScreen.Height = STDSCREENHEIGHT;
|
|
|
|
#ifdef HACKFONT
|
|
if (TextsFont) {
|
|
NewHackScreen.Font = &TextsFont13;
|
|
}
|
|
#endif
|
|
|
|
if (amii_scrnmode == 0xffffffff) {
|
|
struct ScreenModeRequester *SMR;
|
|
#ifdef __GNUC__
|
|
SM_FilterHook.h_Entry = (void *) &SM_Filter;
|
|
#else
|
|
SM_FilterHook.h_Entry = (ULONG (*) ()) SM_Filter;
|
|
#endif
|
|
SM_FilterHook.h_Data = 0;
|
|
SM_FilterHook.h_SubEntry = 0;
|
|
SMR = AllocAslRequest(ASL_ScreenModeRequest, NULL);
|
|
if (AslRequestTags(SMR, ASLSM_FilterFunc, (ULONG) &SM_FilterHook,
|
|
TAG_END))
|
|
amii_scrnmode = SMR->sm_DisplayID;
|
|
else
|
|
amii_scrnmode = 0;
|
|
FreeAslRequest(SMR);
|
|
}
|
|
|
|
if (forcenobig == 0) {
|
|
if ((wbscr = LockPubScreen("Workbench")) != NULL
|
|
|| (wbscr = LockPubScreen(NULL)) != NULL) {
|
|
/* Get the default pub screen's size */
|
|
modeid = GetVPModeID(&wbscr->ViewPort);
|
|
if (modeid == INVALID_ID || ModeNotAvailable(modeid)
|
|
|| (handle = FindDisplayInfo(modeid)) == NULL
|
|
|| GetDisplayInfoData(handle, (char *) &dims,
|
|
sizeof(dims), DTAG_DIMS,
|
|
modeid) <= 0
|
|
|| GetDisplayInfoData(handle, (char *) &disp,
|
|
sizeof(disp), DTAG_DISP,
|
|
modeid) <= 0) {
|
|
modeid = DEFAULT_MONITOR_ID | HIRES_KEY;
|
|
/* If the display database seems to not work, use the
|
|
* screen
|
|
* dimensions
|
|
*/
|
|
NewHackScreen.Height = wbscr->Height;
|
|
NewHackScreen.Width = wbscr->Width;
|
|
|
|
/*
|
|
* Request LACE if it looks laced. For 2.1/3.0, we will
|
|
* get
|
|
* promoted to the users choice of modes (if promotion is
|
|
* allowed)
|
|
* If the user is using a dragable screen, things will get
|
|
* hosed
|
|
* but that is life...
|
|
*/
|
|
if (wbscr->ViewPort.Modes & LACE)
|
|
NewHackScreen.ViewModes |= LACE;
|
|
modeid = -1;
|
|
} else {
|
|
/* Use the display database to get the correct information
|
|
*/
|
|
if (disp.PropertyFlags & DIPF_IS_LACE)
|
|
NewHackScreen.ViewModes |= LACE;
|
|
NewHackScreen.Height = dims.StdOScan.MaxY + 1;
|
|
NewHackScreen.Width = dims.StdOScan.MaxX + 1;
|
|
}
|
|
NewHackScreen.TopEdge = 0;
|
|
NewHackScreen.LeftEdge = 0;
|
|
|
|
UnlockPubScreen(NULL, wbscr);
|
|
}
|
|
}
|
|
|
|
for (i = 0; scrntags[i].ti_Tag != TAG_DONE; ++i) {
|
|
switch (scrntags[i].ti_Tag) {
|
|
case SA_DisplayID:
|
|
if (!amii_scrnmode || ModeNotAvailable(amii_scrnmode)) {
|
|
if (ModeNotAvailable(modeid)) {
|
|
scrntags[i].ti_Tag = TAG_IGNORE;
|
|
break;
|
|
} else
|
|
scrntags[i].ti_Data = (long) modeid;
|
|
} else
|
|
modeid = scrntags[i].ti_Data = (long) amii_scrnmode;
|
|
if ((handle = FindDisplayInfo(modeid)) != NULL
|
|
&& GetDisplayInfoData(handle, (char *) &dims,
|
|
sizeof(dims), DTAG_DIMS, modeid) > 0
|
|
&& GetDisplayInfoData(handle, (char *) &disp,
|
|
sizeof(disp), DTAG_DISP,
|
|
modeid) > 0) {
|
|
if (disp.PropertyFlags & DIPF_IS_LACE)
|
|
NewHackScreen.ViewModes |= LACE;
|
|
NewHackScreen.Height = dims.StdOScan.MaxY + 1;
|
|
NewHackScreen.Width = dims.StdOScan.MaxX + 1;
|
|
}
|
|
break;
|
|
|
|
case SA_Pens:
|
|
scrntags[i].ti_Data = (long) sysflags.amii_dripens;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (WINVERS_AMIV)
|
|
amii_bmhd = ReadTileImageFiles();
|
|
else
|
|
memcpy(amii_initmap, amii_init_map, sizeof(amii_initmap));
|
|
memcpy(sysflags.amii_curmap, amii_initmap, sizeof(sysflags.amii_curmap));
|
|
|
|
/* Find out how deep the screen needs to be, 32 planes is enough! */
|
|
for (i = 0; i < 32; ++i) {
|
|
if ((1L << i) >= amii_numcolors)
|
|
break;
|
|
}
|
|
|
|
NewHackScreen.Depth = i;
|
|
|
|
/* If for some reason Height/Width became smaller than the required,
|
|
have the required one */
|
|
if (NewHackScreen.Height < SCREENHEIGHT)
|
|
NewHackScreen.Height = SCREENHEIGHT;
|
|
if (NewHackScreen.Width < WIDTH)
|
|
NewHackScreen.Width = WIDTH;
|
|
#ifdef HACKFONT
|
|
i = max(TextsFont->tf_XSize, HackFont->tf_XSize);
|
|
if (NewHackScreen.Width < 80 * i + 4)
|
|
NewHackScreen.Width = 80 * i + 4;
|
|
#endif
|
|
|
|
/* While openscreen fails try fewer colors to see if that is the problem.
|
|
*/
|
|
while ((HackScreen = OpenScreen((void *) &NewHackScreen)) == NULL) {
|
|
#ifdef TEXTCOLOR
|
|
if (--NewHackScreen.Depth < 3)
|
|
#else
|
|
if (--NewHackScreen.Depth < 2)
|
|
#endif
|
|
Abort(AN_OpenScreen & ~AT_DeadEnd);
|
|
}
|
|
amii_numcolors = 1L << NewHackScreen.Depth;
|
|
if (HackScreen->Height > 300 && forcenobig == 0)
|
|
bigscreen = 1;
|
|
else
|
|
bigscreen = 0;
|
|
|
|
#ifdef INTUI_NEW_LOOK
|
|
if (IntuitionBase->LibNode.lib_Version >= 37)
|
|
PubScreenStatus(HackScreen, 0);
|
|
#endif
|
|
|
|
amiIDisplay->ypix = HackScreen->Height;
|
|
amiIDisplay->xpix = HackScreen->Width;
|
|
|
|
LoadRGB4(&HackScreen->ViewPort, sysflags.amii_curmap, amii_numcolors);
|
|
|
|
VisualInfo = GetVisualInfo(HackScreen, TAG_END);
|
|
MenuStrip = CreateMenus(GTHackMenu, TAG_END);
|
|
LayoutMenus(MenuStrip, VisualInfo, GTMN_NewLookMenus, TRUE, TAG_END);
|
|
|
|
/* Display the copyright etc... */
|
|
|
|
if (WIN_BASE == WIN_ERR)
|
|
WIN_BASE = amii_create_nhwindow(NHW_BASE);
|
|
amii_clear_nhwindow(WIN_BASE);
|
|
amii_putstr(WIN_BASE, 0, "");
|
|
amii_putstr(WIN_BASE, 0, "");
|
|
amii_putstr(WIN_BASE, 0, "");
|
|
amii_putstr(WIN_BASE, 0, COPYRIGHT_BANNER_A);
|
|
amii_putstr(WIN_BASE, 0, COPYRIGHT_BANNER_B);
|
|
amii_putstr(WIN_BASE, 0, COPYRIGHT_BANNER_C);
|
|
amii_putstr(WIN_BASE, 0, COPYRIGHT_BANNER_D);
|
|
amii_putstr(WIN_BASE, 0, "");
|
|
|
|
Initialized = 1;
|
|
}
|
|
|
|
void
|
|
amii_sethipens(struct Window *w, int type, int attr)
|
|
{
|
|
switch (type) {
|
|
default:
|
|
SetAPen(w->RPort, attr ? C_RED : amii_otherAPen);
|
|
SetBPen(w->RPort, C_BLACK);
|
|
break;
|
|
case NHW_STATUS:
|
|
SetAPen(w->RPort, attr ? C_WHITE : amii_statAPen);
|
|
SetBPen(w->RPort, amii_statBPen);
|
|
break;
|
|
case NHW_MESSAGE:
|
|
SetAPen(w->RPort, attr ? C_WHITE : amii_msgAPen);
|
|
SetBPen(w->RPort, amii_msgBPen);
|
|
break;
|
|
case NHW_MENU:
|
|
SetAPen(w->RPort, attr ? C_BLACK : amii_menuAPen);
|
|
SetBPen(w->RPort, amii_menuBPen);
|
|
break;
|
|
case NHW_TEXT:
|
|
SetAPen(w->RPort, attr ? C_BLACK : amii_textAPen);
|
|
SetBPen(w->RPort, amii_textBPen);
|
|
case -2:
|
|
SetBPen(w->RPort, amii_otherBPen);
|
|
SetAPen(w->RPort, attr ? C_RED : amii_otherAPen);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
amii_setfillpens(struct Window *w, int type)
|
|
{
|
|
switch (type) {
|
|
case NHW_MESSAGE:
|
|
SetAPen(w->RPort, amii_msgBPen);
|
|
SetBPen(w->RPort, amii_msgBPen);
|
|
break;
|
|
case NHW_STATUS:
|
|
SetAPen(w->RPort, amii_statBPen);
|
|
SetBPen(w->RPort, amii_statBPen);
|
|
break;
|
|
case NHW_MENU:
|
|
SetAPen(w->RPort, amii_menuBPen);
|
|
SetBPen(w->RPort, amii_menuBPen);
|
|
break;
|
|
case NHW_TEXT:
|
|
SetAPen(w->RPort, amii_textBPen);
|
|
SetBPen(w->RPort, amii_textBPen);
|
|
break;
|
|
case NHW_MAP:
|
|
case NHW_BASE:
|
|
case NHW_OVER:
|
|
default:
|
|
SetAPen(w->RPort, C_BLACK);
|
|
SetBPen(w->RPort, C_BLACK);
|
|
break;
|
|
case -2:
|
|
SetAPen(w->RPort, amii_otherBPen);
|
|
SetBPen(w->RPort, amii_otherBPen);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
amii_setdrawpens(struct Window *w, int type)
|
|
{
|
|
switch (type) {
|
|
case NHW_MESSAGE:
|
|
SetAPen(w->RPort, amii_msgAPen);
|
|
SetBPen(w->RPort, amii_msgBPen);
|
|
break;
|
|
case NHW_STATUS:
|
|
SetAPen(w->RPort, amii_statAPen);
|
|
SetBPen(w->RPort, amii_statBPen);
|
|
break;
|
|
case NHW_MENU:
|
|
SetAPen(w->RPort, amii_menuAPen);
|
|
SetBPen(w->RPort, amii_menuBPen);
|
|
break;
|
|
case NHW_TEXT:
|
|
SetAPen(w->RPort, amii_textAPen);
|
|
SetBPen(w->RPort, amii_textBPen);
|
|
break;
|
|
case NHW_MAP:
|
|
case NHW_BASE:
|
|
case NHW_OVER:
|
|
SetAPen(w->RPort, C_WHITE);
|
|
SetBPen(w->RPort, C_BLACK);
|
|
break;
|
|
default:
|
|
SetAPen(w->RPort, amii_otherAPen);
|
|
SetBPen(w->RPort, amii_otherBPen);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Clear the indicated window */
|
|
|
|
void
|
|
amii_clear_nhwindow(win)
|
|
register winid win;
|
|
{
|
|
register struct amii_WinDesc *cw;
|
|
register struct Window *w;
|
|
|
|
if (reclip == 2)
|
|
return;
|
|
|
|
if (win == WIN_ERR || (cw = amii_wins[win]) == NULL)
|
|
panic(winpanicstr, win, "clear_nhwindow");
|
|
|
|
/* Clear the overview window too if it is displayed */
|
|
if (WINVERS_AMIV
|
|
&& (cw->type == WIN_MAP && WIN_OVER != WIN_ERR && reclip == 0)) {
|
|
amii_clear_nhwindow(WIN_OVER);
|
|
}
|
|
|
|
if (w = cw->win)
|
|
SetDrMd(w->RPort, JAM2);
|
|
else
|
|
return;
|
|
|
|
if ((cw->wflags & FLMAP_CURSUP)) {
|
|
if (cw->type != NHW_MAP)
|
|
cursor_off(win);
|
|
else
|
|
cw->wflags &= ~FLMAP_CURSUP;
|
|
}
|
|
|
|
amii_setfillpens(w, cw->type);
|
|
SetDrMd(w->RPort, JAM2);
|
|
|
|
if (cw->type == NHW_MENU || cw->type == NHW_TEXT) {
|
|
RectFill(w->RPort, w->BorderLeft, w->BorderTop,
|
|
w->Width - w->BorderRight - 1,
|
|
w->Height - w->BorderBottom - 1);
|
|
} else {
|
|
if (cw->type == NHW_MESSAGE) {
|
|
amii_curs(win, 1, 0);
|
|
if (!scrollmsg)
|
|
TextSpaces(w->RPort, cw->cols);
|
|
} else {
|
|
RectFill(w->RPort, w->BorderLeft, w->BorderTop,
|
|
w->Width - w->BorderRight - 1,
|
|
w->Height - w->BorderBottom - 1);
|
|
}
|
|
}
|
|
|
|
cw->cury = 0;
|
|
cw->curx = 0;
|
|
amii_curs(win, 1, 0);
|
|
}
|
|
|
|
/* Dismiss the window from the screen */
|
|
|
|
void
|
|
dismiss_nhwindow(win)
|
|
register winid win;
|
|
{
|
|
register struct Window *w;
|
|
register struct amii_WinDesc *cw;
|
|
|
|
if (win == WIN_ERR || (cw = amii_wins[win]) == NULL) {
|
|
panic(winpanicstr, win, "dismiss_nhwindow");
|
|
}
|
|
|
|
w = cw->win;
|
|
|
|
if (w) {
|
|
/* All windows have this stuff attached to them. */
|
|
if (cw->type == NHW_MAP || cw->type == NHW_OVER
|
|
|| cw->type == NHW_BASE || cw->type == NHW_MESSAGE
|
|
|| cw->type == NHW_STATUS) {
|
|
ClearMenuStrip(w);
|
|
}
|
|
|
|
/* Save where user like inventory to appear */
|
|
if (win == WIN_INVEN) {
|
|
lastinvent.MinX = w->LeftEdge;
|
|
lastinvent.MinY = w->TopEdge;
|
|
lastinvent.MaxX = w->Width;
|
|
lastinvent.MaxY = w->Height;
|
|
}
|
|
|
|
/* Close the window */
|
|
CloseShWindow(w);
|
|
cw->win = NULL;
|
|
|
|
/* Free copy of NewWindow structure for TEXT/MENU windows. */
|
|
if (cw->newwin)
|
|
FreeNewWindow((void *) cw->newwin);
|
|
cw->newwin = NULL;
|
|
}
|
|
}
|
|
|
|
void
|
|
amii_exit_nhwindows(str)
|
|
const char *str;
|
|
{
|
|
/* Seems strange to have to do this... but we need the BASE window
|
|
* left behind...
|
|
*/
|
|
kill_nhwindows(0);
|
|
if (WINVERS_AMIV)
|
|
FreeTileImageFiles();
|
|
|
|
if (str) {
|
|
raw_print(""); /* be sure we're not under the top margin */
|
|
raw_print(str);
|
|
}
|
|
}
|
|
|
|
void
|
|
amii_display_nhwindow(win, blocking)
|
|
winid win;
|
|
boolean blocking;
|
|
{
|
|
menu_item *mip;
|
|
int cnt;
|
|
static int lastwin = -1;
|
|
struct amii_WinDesc *cw;
|
|
|
|
if (!Initialized)
|
|
return;
|
|
lastwin = win;
|
|
|
|
if (win == WIN_ERR || (cw = amii_wins[win]) == NULL)
|
|
panic(winpanicstr, win, "display_nhwindow");
|
|
|
|
if (cw->type == NHW_MESSAGE)
|
|
cw->wflags &= ~FLMAP_SKIP;
|
|
|
|
if (cw->type == NHW_MESSAGE || cw->type == NHW_STATUS)
|
|
return;
|
|
|
|
if (WIN_MAP != WIN_ERR && amii_wins[WIN_MAP]) {
|
|
flush_glyph_buffer(amii_wins[WIN_MAP]->win);
|
|
}
|
|
|
|
if (cw->type == NHW_MENU || cw->type == NHW_TEXT) {
|
|
cnt = DoMenuScroll(win, blocking, PICK_ONE, &mip);
|
|
} else if (cw->type == NHW_MAP) {
|
|
amii_end_glyphout(win);
|
|
/* Do more if it is time... */
|
|
if (blocking == TRUE && amii_wins[WIN_MESSAGE]->curx) {
|
|
outmore(amii_wins[WIN_MESSAGE]);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
amii_curs(window, x, y)
|
|
winid window;
|
|
register int x, y; /* not xchar: perhaps xchar is unsigned and
|
|
curx-x would be unsigned as well */
|
|
{
|
|
register struct amii_WinDesc *cw;
|
|
register struct Window *w;
|
|
register struct RastPort *rp;
|
|
|
|
if (window == WIN_ERR || (cw = amii_wins[window]) == NULL)
|
|
panic(winpanicstr, window, "curs");
|
|
if ((w = cw->win) == NULL) {
|
|
if (cw->type == NHW_MENU || cw->type == NHW_TEXT)
|
|
return;
|
|
else
|
|
panic("No window open yet in curs() for winid %d\n", window);
|
|
}
|
|
amiIDisplay->lastwin = window;
|
|
|
|
/* Make sure x is within bounds */
|
|
if (x > 0)
|
|
--x; /* column 0 is never used */
|
|
else
|
|
x = 0;
|
|
|
|
cw->curx = x;
|
|
cw->cury = y;
|
|
|
|
#ifdef DEBUG
|
|
if (x < 0 || y < 0 || y >= cw->rows || x >= cw->cols) {
|
|
char *s = "[unknown type]";
|
|
switch (cw->type) {
|
|
case NHW_MESSAGE:
|
|
s = "[topl window]";
|
|
break;
|
|
case NHW_STATUS:
|
|
s = "[status window]";
|
|
break;
|
|
case NHW_MAP:
|
|
s = "[map window]";
|
|
break;
|
|
case NHW_MENU:
|
|
s = "[menu window]";
|
|
break;
|
|
case NHW_TEXT:
|
|
s = "[text window]";
|
|
break;
|
|
case NHW_BASE:
|
|
s = "[base window]";
|
|
break;
|
|
case NHW_OVER:
|
|
s = "[overview window]";
|
|
break;
|
|
}
|
|
impossible("bad curs positioning win %d %s (%d,%d)", window, s, x, y);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CLIPPING
|
|
if (clipping && cw->type == NHW_MAP) {
|
|
x -= clipx;
|
|
y -= clipy;
|
|
}
|
|
#endif
|
|
|
|
/* Output all saved output before doing cursor movements for MAP */
|
|
|
|
if (cw->type == NHW_MAP) {
|
|
flush_glyph_buffer(w);
|
|
}
|
|
|
|
/* Actually do it */
|
|
|
|
rp = w->RPort;
|
|
if (cw->type == NHW_MENU) {
|
|
if (WINVERS_AMIV) {
|
|
if (window == WIN_INVEN) {
|
|
Move(rp, (x * rp->TxWidth) + w->BorderLeft + 1
|
|
+ pictdata.xsize + 4,
|
|
(y * max(rp->TxHeight, pictdata.ysize + 3))
|
|
+ rp->TxBaseline + pictdata.ysize - rp->TxHeight
|
|
+ w->BorderTop + 4);
|
|
} else {
|
|
Move(rp, (x * rp->TxWidth) + w->BorderLeft + 1,
|
|
(y * rp->TxHeight) + rp->TxBaseline + w->BorderTop + 1);
|
|
}
|
|
} else {
|
|
Move(rp, (x * rp->TxWidth) + w->BorderLeft + 1,
|
|
(y * rp->TxHeight) + rp->TxBaseline + w->BorderTop + 1);
|
|
}
|
|
} else if (cw->type == NHW_TEXT) {
|
|
Move(rp, (x * rp->TxWidth) + w->BorderLeft + 1,
|
|
(y * rp->TxHeight) + rp->TxBaseline + w->BorderTop + 1);
|
|
} else if (cw->type == NHW_MAP || cw->type == NHW_BASE) {
|
|
/* These coordinate calculations must be synced with those
|
|
* in flush_glyph_buffer() in winchar.c. curs_on_u() will
|
|
* use this code, all other drawing occurs through the glyph
|
|
* code. In order for the cursor to appear on top of the hero,
|
|
* the code must compute X,Y in the same manner relative to
|
|
* the RastPort coordinates.
|
|
*
|
|
* y = w->BorderTop + (g_nodes[i].y-2) * rp->TxHeight +
|
|
* rp->TxBaseline + 1;
|
|
* x = g_nodes[i].x * rp->TxWidth + w->BorderLeft;
|
|
*/
|
|
|
|
if (WINVERS_AMIV) {
|
|
if (cw->type == NHW_MAP) {
|
|
if (Is_rogue_level(&u.uz)) {
|
|
#if 0
|
|
int qqx= (x * w->RPort->TxWidth) + w->BorderLeft;
|
|
int qqy= w->BorderTop + ( (y+1) * w->RPort->TxHeight ) + 1;
|
|
printf("pos: (%d,%d)->(%d,%d)\n",x,y,qqx,qqy);
|
|
#endif
|
|
SetAPen(w->RPort,
|
|
C_WHITE); /* XXX should be elsewhere (was 4)*/
|
|
Move(rp, (x * w->RPort->TxWidth) + w->BorderLeft,
|
|
w->BorderTop + ((y + 1) * w->RPort->TxHeight) + 1);
|
|
} else {
|
|
Move(rp, (x * mxsize) + w->BorderLeft,
|
|
w->BorderTop + ((y + 1) * mysize) + 1);
|
|
}
|
|
} else {
|
|
Move(rp, (x * w->RPort->TxWidth) + w->BorderLeft,
|
|
w->BorderTop + ((y + 1) * w->RPort->TxHeight)
|
|
+ w->RPort->TxBaseline + 1);
|
|
}
|
|
} else {
|
|
Move(rp, (x * w->RPort->TxWidth) + w->BorderLeft,
|
|
w->BorderTop + (y * w->RPort->TxHeight)
|
|
+ w->RPort->TxBaseline + 1);
|
|
}
|
|
} else if (WINVERS_AMIV && cw->type == NHW_OVER) {
|
|
Move(rp, (x * w->RPort->TxWidth) + w->BorderLeft + 2,
|
|
w->BorderTop + w->RPort->TxBaseline + 3);
|
|
} else if (cw->type == NHW_MESSAGE && !scrollmsg) {
|
|
Move(rp, (x * w->RPort->TxWidth) + w->BorderLeft + 2,
|
|
w->BorderTop + w->RPort->TxBaseline + 3);
|
|
} else if (cw->type == NHW_STATUS) {
|
|
Move(rp, (x * w->RPort->TxWidth) + w->BorderLeft + 2,
|
|
(y * (w->RPort->TxHeight + 1)) + w->BorderTop
|
|
+ w->RPort->TxBaseline + 1);
|
|
} else {
|
|
Move(rp, (x * w->RPort->TxWidth) + w->BorderLeft + 2,
|
|
(y * w->RPort->TxHeight) + w->BorderTop + w->RPort->TxBaseline
|
|
+ 1);
|
|
}
|
|
}
|
|
|
|
void
|
|
amii_set_text_font(name, size)
|
|
char *name;
|
|
int size;
|
|
{
|
|
register int i;
|
|
register struct amii_WinDesc *cw;
|
|
int osize = TextsFont13.ta_YSize;
|
|
static char nname[100];
|
|
|
|
strncpy(nname, name, sizeof(nname) - 1);
|
|
nname[sizeof(nname) - 1] = 0;
|
|
|
|
TextsFont13.ta_Name = nname;
|
|
TextsFont13.ta_YSize = size;
|
|
|
|
/* No alternate text font allowed for 640x269 or smaller */
|
|
if (!HackScreen || !bigscreen)
|
|
return;
|
|
|
|
/* Look for windows to set, and change them */
|
|
|
|
if (DiskfontBase = OpenLibrary("diskfont.library", amii_libvers)) {
|
|
TextsFont = OpenDiskFont(&TextsFont13);
|
|
for (i = 0; TextsFont && i < MAXWIN; ++i) {
|
|
if ((cw = amii_wins[i]) && cw->win != NULL) {
|
|
switch (cw->type) {
|
|
case NHW_STATUS:
|
|
MoveWindow(cw->win, 0, -(size - osize) * 2);
|
|
SizeWindow(cw->win, 0, (size - osize) * 2);
|
|
SetFont(cw->win->RPort, TextsFont);
|
|
break;
|
|
case NHW_MESSAGE:
|
|
case NHW_MAP:
|
|
case NHW_BASE:
|
|
case NHW_OVER:
|
|
SetFont(cw->win->RPort, TextsFont);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
CloseLibrary(DiskfontBase);
|
|
DiskfontBase = NULL;
|
|
}
|
|
|
|
void
|
|
kill_nhwindows(all)
|
|
register int all;
|
|
{
|
|
register int i;
|
|
register struct amii_WinDesc *cw;
|
|
|
|
/* Foreach open window in all of amii_wins[], CloseShWindow, free memory
|
|
*/
|
|
|
|
for (i = 0; i < MAXWIN; ++i) {
|
|
if ((cw = amii_wins[i]) && (cw->type != NHW_BASE || all)) {
|
|
amii_destroy_nhwindow(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
amii_cl_end(cw, curs_pos)
|
|
register struct amii_WinDesc *cw;
|
|
register int curs_pos;
|
|
{
|
|
register struct Window *w = cw->win;
|
|
register int oy, ox;
|
|
|
|
if (!w)
|
|
panic("NULL window pointer in amii_cl_end()");
|
|
|
|
oy = w->RPort->cp_y;
|
|
ox = w->RPort->cp_x;
|
|
|
|
TextSpaces(w->RPort, cw->cols - curs_pos);
|
|
|
|
Move(w->RPort, ox, oy);
|
|
}
|
|
|
|
void
|
|
cursor_off(window)
|
|
winid window;
|
|
{
|
|
register struct amii_WinDesc *cw;
|
|
register struct Window *w;
|
|
register struct RastPort *rp;
|
|
int curx, cury;
|
|
int x, y;
|
|
long dmode;
|
|
short apen, bpen;
|
|
unsigned char ch;
|
|
|
|
if (window == WIN_ERR || (cw = amii_wins[window]) == NULL) {
|
|
iflags.window_inited = 0;
|
|
panic(winpanicstr, window, "cursor_off");
|
|
}
|
|
|
|
if (!(cw->wflags & FLMAP_CURSUP))
|
|
return;
|
|
|
|
w = cw->win;
|
|
|
|
if (!w)
|
|
return;
|
|
|
|
cw->wflags &= ~FLMAP_CURSUP;
|
|
rp = w->RPort;
|
|
|
|
/* Save the current information */
|
|
curx = rp->cp_x;
|
|
cury = rp->cp_y;
|
|
x = cw->cursx;
|
|
y = cw->cursy;
|
|
dmode = rp->DrawMode;
|
|
apen = rp->FgPen;
|
|
bpen = rp->BgPen;
|
|
SetAPen(rp, cw->curs_apen);
|
|
SetBPen(rp, cw->curs_bpen);
|
|
SetDrMd(rp, COMPLEMENT);
|
|
/*printf("CURSOR OFF: %d %d\n",x,y);*/
|
|
|
|
if (WINVERS_AMIV && cw->type == NHW_MAP) {
|
|
cursor_common(rp, x, y);
|
|
if (Is_rogue_level(&u.uz))
|
|
Move(rp, curx, cury);
|
|
} else {
|
|
ch = CURSOR_CHAR;
|
|
Move(rp, x, y);
|
|
Text(rp, &ch, 1);
|
|
|
|
/* Put back the other stuff */
|
|
|
|
Move(rp, curx, cury);
|
|
}
|
|
SetDrMd(rp, dmode);
|
|
SetAPen(rp, apen);
|
|
SetBPen(rp, bpen);
|
|
}
|
|
|
|
void
|
|
cursor_on(window)
|
|
winid window;
|
|
{
|
|
int x, y;
|
|
register struct amii_WinDesc *cw;
|
|
register struct Window *w;
|
|
register struct RastPort *rp;
|
|
unsigned char ch;
|
|
long dmode;
|
|
short apen, bpen;
|
|
|
|
if (window == WIN_ERR || (cw = amii_wins[window]) == NULL) {
|
|
/* tty does this differently - is this OK? */
|
|
iflags.window_inited = 0;
|
|
panic(winpanicstr, window, "cursor_on");
|
|
}
|
|
|
|
/*printf("CURSOR ON: %d %d\n",cw->win->RPort->cp_x,
|
|
* cw->win->RPort->cp_y);*/
|
|
if ((cw->wflags & FLMAP_CURSUP))
|
|
cursor_off(window);
|
|
|
|
w = cw->win;
|
|
|
|
if (!w)
|
|
return;
|
|
|
|
cw->wflags |= FLMAP_CURSUP;
|
|
rp = w->RPort;
|
|
|
|
/* Save the current information */
|
|
|
|
#ifdef DISPMAP
|
|
if (WINVERS_AMIV && cw->type == NHW_MAP && !Is_rogue_level(&u.uz))
|
|
x = cw->cursx = (rp->cp_x & -8) + 8;
|
|
else
|
|
#endif
|
|
x = cw->cursx = rp->cp_x;
|
|
y = cw->cursy = rp->cp_y;
|
|
apen = rp->FgPen;
|
|
bpen = rp->BgPen;
|
|
dmode = rp->DrawMode;
|
|
|
|
/* Draw in complement mode. The cursor body will be C_WHITE */
|
|
|
|
cw->curs_apen = 0xff; /* Last color/all planes, regardless of depth */
|
|
cw->curs_bpen = 0xff;
|
|
SetAPen(rp, cw->curs_apen);
|
|
SetBPen(rp, cw->curs_bpen);
|
|
SetDrMd(rp, COMPLEMENT);
|
|
if (WINVERS_AMIV && cw->type == NHW_MAP) {
|
|
cursor_common(rp, x, y);
|
|
} else {
|
|
Move(rp, x, y);
|
|
ch = CURSOR_CHAR;
|
|
Text(rp, &ch, 1);
|
|
Move(rp, x, y);
|
|
}
|
|
|
|
SetDrMd(rp, dmode);
|
|
SetAPen(rp, apen);
|
|
SetBPen(rp, bpen);
|
|
}
|
|
|
|
static void
|
|
cursor_common(rp, x, y)
|
|
struct RastPort *rp;
|
|
int x, y;
|
|
{
|
|
int x1, x2, y1, y2;
|
|
|
|
if (Is_rogue_level(&u.uz)) {
|
|
x1 = x - 2;
|
|
y1 = y - rp->TxHeight;
|
|
x2 = x + rp->TxWidth + 1;
|
|
y2 = y + 3;
|
|
/*printf("COMM: (%d %d) (%d %d) (%d %d) (%d
|
|
* %d)\n",x1,y1,x2,y2,x1+2,y1+2,x2-2,y2-2);*/
|
|
} else {
|
|
x1 = x;
|
|
y1 = y - mysize - 1;
|
|
x2 = x + mxsize - 1;
|
|
y2 = y - 2;
|
|
RectFill(rp, x1, y1, x2, y2);
|
|
}
|
|
|
|
RectFill(rp, x1 + 2, y1 + 2, x2 - 2, y2 - 2);
|
|
}
|
|
|
|
void
|
|
amii_suspend_nhwindows(str)
|
|
const char *str;
|
|
{
|
|
if (HackScreen)
|
|
ScreenToBack(HackScreen);
|
|
}
|
|
|
|
void
|
|
amii_resume_nhwindows()
|
|
{
|
|
if (HackScreen)
|
|
ScreenToFront(HackScreen);
|
|
}
|
|
|
|
void
|
|
amii_bell()
|
|
{
|
|
DisplayBeep(NULL);
|
|
}
|
|
|
|
void
|
|
removetopl(cnt)
|
|
int cnt;
|
|
{
|
|
struct amii_WinDesc *cw = amii_wins[WIN_MESSAGE];
|
|
/* NB - this is sufficient for
|
|
* yn_function, but that's it
|
|
*/
|
|
if (cw->curx < cnt)
|
|
cw->curx = 0;
|
|
else
|
|
cw->curx -= cnt;
|
|
|
|
amii_curs(WIN_MESSAGE, cw->curx + 1, cw->cury);
|
|
amii_cl_end(cw, cw->curx);
|
|
}
|
|
/*#endif /* AMIGA_INTUITION */
|
|
|
|
#ifdef PORT_HELP
|
|
void
|
|
port_help()
|
|
{
|
|
display_file(PORT_HELP, 1);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* print_glyph
|
|
*
|
|
* Print the glyph to the output device. Don't flush the output device.
|
|
*
|
|
* Since this is only called from show_glyph(), it is assumed that the
|
|
* position and glyph are always correct (checked there)!
|
|
*/
|
|
|
|
void
|
|
amii_print_glyph(win, x, y, glyph, bkglyph)
|
|
winid win;
|
|
xchar x, y;
|
|
int glyph, bkglyph;
|
|
{
|
|
struct amii_WinDesc *cw;
|
|
uchar ch;
|
|
int color, och;
|
|
extern const int zapcolors[];
|
|
unsigned special;
|
|
|
|
/* In order for the overview window to work, we can not clip here */
|
|
if (!WINVERS_AMIV) {
|
|
#ifdef CLIPPING
|
|
/* If point not in visible part of window just skip it */
|
|
if (clipping) {
|
|
if (x <= clipx || y < clipy || x >= clipxmax || y >= clipymax)
|
|
return;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (win == WIN_ERR || (cw = amii_wins[win]) == NULL
|
|
|| cw->type != NHW_MAP) {
|
|
panic(winpanicstr, win, "amii_print_glyph");
|
|
}
|
|
|
|
#if 0
|
|
{
|
|
static int x=-1;
|
|
if(u.uz.dlevel != x){
|
|
fprintf(stderr,"lvlchg: %d (%d)\n",u.uz.dlevel,Is_rogue_level(&u.uz));
|
|
x = u.uz.dlevel;
|
|
}
|
|
}
|
|
#endif
|
|
if (WINVERS_AMIV && !Is_rogue_level(&u.uz)) {
|
|
amii_curs(win, x, y);
|
|
amiga_print_glyph(win, 0, glyph);
|
|
} else /* AMII, or Rogue level in either version */
|
|
{
|
|
/* map glyph to character and color */
|
|
(void) mapglyph(glyph, &och, &color, &special, x, y, 0);
|
|
ch = (uchar) och;
|
|
if (WINVERS_AMIV) { /* implies Rogue level here */
|
|
amii_curs(win, x, y);
|
|
amiga_print_glyph(win, NO_COLOR, ch + 10000);
|
|
} else {
|
|
/* Move the cursor. */
|
|
amii_curs(win, x, y + 2);
|
|
|
|
#ifdef TEXTCOLOR
|
|
/* Turn off color if rogue level. */
|
|
if (Is_rogue_level(&u.uz))
|
|
color = NO_COLOR;
|
|
|
|
amiga_print_glyph(win, color, ch);
|
|
#else
|
|
g_putch(ch); /* print the character */
|
|
#endif
|
|
cw->curx++; /* one character over */
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Make sure the user sees a text string when no windowing is available */
|
|
|
|
void
|
|
amii_raw_print(s)
|
|
register const char *s;
|
|
{
|
|
int argc = 0;
|
|
|
|
if (!s)
|
|
return;
|
|
if (amiIDisplay)
|
|
amiIDisplay->rawprint++;
|
|
|
|
if (!Initialized) { /* Not yet screen open ... */
|
|
puts(s);
|
|
fflush(stdout);
|
|
return;
|
|
}
|
|
|
|
if (Initialized == 0 && WIN_BASE == WIN_ERR)
|
|
init_nhwindows(&argc, (char **) 0);
|
|
|
|
if (amii_rawprwin != WIN_ERR)
|
|
amii_putstr(amii_rawprwin, 0, s);
|
|
else if (WIN_MAP != WIN_ERR && amii_wins[WIN_MAP])
|
|
amii_putstr(WIN_MAP, 0, s);
|
|
else if (WIN_BASE != WIN_ERR && amii_wins[WIN_BASE])
|
|
amii_putstr(WIN_BASE, 0, s);
|
|
else {
|
|
puts(s);
|
|
fflush(stdout);
|
|
}
|
|
}
|
|
|
|
/* Make sure the user sees a bold text string when no windowing
|
|
* is available
|
|
*/
|
|
|
|
void
|
|
amii_raw_print_bold(s)
|
|
register const char *s;
|
|
{
|
|
int argc = 0;
|
|
|
|
if (!s)
|
|
return;
|
|
|
|
if (amiIDisplay)
|
|
amiIDisplay->rawprint++;
|
|
|
|
if (!Initialized) { /* Not yet screen open ... */
|
|
puts(s);
|
|
fflush(stdout);
|
|
return;
|
|
}
|
|
|
|
if (Initialized == 0 && WIN_BASE == WIN_ERR)
|
|
init_nhwindows(&argc, (char **) 0);
|
|
|
|
if (amii_rawprwin != WIN_ERR)
|
|
amii_putstr(amii_rawprwin, 1, s);
|
|
else if (WIN_MAP != WIN_ERR && amii_wins[WIN_MAP])
|
|
amii_putstr(WIN_MAP, 1, s);
|
|
else if (WIN_BASE != WIN_ERR && amii_wins[WIN_BASE])
|
|
amii_putstr(WIN_BASE, 1, s);
|
|
else {
|
|
printf("\33[1m%s\33[0m\n", s);
|
|
fflush(stdout);
|
|
}
|
|
}
|
|
|
|
/* Rebuild/update the inventory if the window is up.
|
|
*/
|
|
void
|
|
amii_update_inventory()
|
|
{
|
|
register struct amii_WinDesc *cw;
|
|
|
|
if (WIN_INVEN != WIN_ERR && (cw = amii_wins[WIN_INVEN])
|
|
&& cw->type == NHW_MENU && cw->win) {
|
|
display_inventory(NULL, FALSE);
|
|
}
|
|
}
|
|
|
|
/* Humm, doesn't really do anything useful */
|
|
|
|
void
|
|
amii_mark_synch()
|
|
{
|
|
if (!amiIDisplay)
|
|
fflush(stderr);
|
|
/* anything else? do we need this much? */
|
|
}
|
|
|
|
/* Wait for everything to sync. Nothing is asynchronous, so we just
|
|
* ask for a key to be pressed.
|
|
*/
|
|
void
|
|
amii_wait_synch()
|
|
{
|
|
if (!amiIDisplay || amiIDisplay->rawprint) {
|
|
if (amiIDisplay)
|
|
amiIDisplay->rawprint = 0;
|
|
} else {
|
|
if (WIN_MAP != WIN_ERR) {
|
|
display_nhwindow(WIN_MAP, TRUE);
|
|
flush_glyph_buffer(amii_wins[WIN_MAP]->win);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
amii_setclipped()
|
|
{
|
|
#ifdef CLIPPING
|
|
clipping = TRUE;
|
|
clipx = clipy = 0;
|
|
clipxmax = CO;
|
|
clipymax = LI;
|
|
/* some of this is now redundant with top of amii_cliparound XXX */
|
|
#endif
|
|
}
|
|
|
|
/* XXX still to do: suppress scrolling if we violate the boundary but the
|
|
* edge of the map is already displayed
|
|
*/
|
|
void
|
|
amii_cliparound(x, y)
|
|
register int x, y;
|
|
{
|
|
#ifdef CLIPPING
|
|
int oldx = clipx, oldy = clipy;
|
|
int oldxmax = clipxmax, oldymax = clipymax;
|
|
int COx, LIx;
|
|
#define SCROLLCNT 1 /* Get there in 3 moves... */
|
|
int scrollcnt = SCROLLCNT; /* ...or 1 if we changed level */
|
|
|
|
if (!clipping) /* And 1 in anycase, cleaner, simpler, quicker */
|
|
return;
|
|
|
|
if (Is_rogue_level(&u.uz)) {
|
|
struct Window *w = amii_wins[WIN_MAP]->win;
|
|
struct RastPort *rp = w->RPort;
|
|
|
|
COx = (w->Width - w->BorderLeft - w->BorderRight) / rp->TxWidth;
|
|
LIx = (w->Height - w->BorderTop - w->BorderBottom) / rp->TxHeight;
|
|
} else {
|
|
COx = CO;
|
|
LIx = LI;
|
|
}
|
|
/*
|
|
* On a level change, move the clipping region so that for a
|
|
* reasonablely large window extra motion is avoided; for
|
|
* the rogue level hopefully this means no motion at all.
|
|
*/
|
|
{
|
|
static d_level saved_level = { 127, 127 }; /* XXX */
|
|
|
|
if (!on_level(&u.uz, &saved_level)) {
|
|
scrollcnt = 1; /* jump with blanking */
|
|
clipx = clipy = 0;
|
|
clipxmax = COx;
|
|
clipymax = LIx;
|
|
saved_level = u.uz; /* save as new current level */
|
|
}
|
|
}
|
|
|
|
if (x <= clipx + xclipbord) {
|
|
clipx = max(0, x - (clipxmax - clipx) / 2);
|
|
clipxmax = clipx + COx;
|
|
} else if (x > clipxmax - xclipbord) {
|
|
clipxmax = min(COLNO, x + (clipxmax - clipx) / 2);
|
|
clipx = clipxmax - COx;
|
|
}
|
|
|
|
if (y <= clipy + yclipbord) {
|
|
clipy = max(0, y - (clipymax - clipy) / 2);
|
|
clipymax = clipy + LIx;
|
|
} else if (y > clipymax - yclipbord) {
|
|
clipymax = min(ROWNO, y + (clipymax - clipy) / 2);
|
|
clipy = clipymax - LIx;
|
|
}
|
|
|
|
reclip = 1;
|
|
if (clipx != oldx || clipy != oldy || clipxmax != oldxmax
|
|
|| clipymax != oldymax) {
|
|
#ifndef NOSCROLLRASTER
|
|
struct Window *w = amii_wins[WIN_MAP]->win;
|
|
struct RastPort *rp = w->RPort;
|
|
int xdelta, ydelta, xmod, ymod, i;
|
|
int incx, incy, mincx, mincy;
|
|
int savex, savey, savexmax, saveymax;
|
|
int scrx, scry;
|
|
|
|
if (Is_rogue_level(&u.uz)) {
|
|
scrx = rp->TxWidth;
|
|
scry = rp->TxHeight;
|
|
} else {
|
|
scrx = mxsize;
|
|
scry = mysize;
|
|
}
|
|
|
|
/* Ask that the glyph routines not draw the overview window */
|
|
reclip = 2;
|
|
cursor_off(WIN_MAP);
|
|
|
|
/* Compute how far we are moving in terms of tiles */
|
|
mincx = clipx - oldx;
|
|
mincy = clipy - oldy;
|
|
|
|
/* How many tiles to get there in SCROLLCNT moves */
|
|
incx = (clipx - oldx) / scrollcnt;
|
|
incy = (clipy - oldy) / scrollcnt;
|
|
|
|
/* If less than SCROLLCNT tiles, then move by 1 tile if moving at all
|
|
*/
|
|
if (incx == 0)
|
|
incx = (mincx != 0);
|
|
if (incy == 0)
|
|
incy = (mincy != 0);
|
|
|
|
/* Get count of pixels to move each iteration and final pixel count */
|
|
xdelta = ((clipx - oldx) * scrx) / scrollcnt;
|
|
xmod = ((clipx - oldx) * scrx) % scrollcnt;
|
|
ydelta = ((clipy - oldy) * scry) / scrollcnt;
|
|
ymod = ((clipy - oldy) * scry) % scrollcnt;
|
|
|
|
/* Preserve the final move location */
|
|
savex = clipx;
|
|
savey = clipy;
|
|
saveymax = clipymax;
|
|
savexmax = clipxmax;
|
|
|
|
/*
|
|
* Set clipping rectangle to be just the region that will be exposed so
|
|
* that drawing will be faster
|
|
*/
|
|
#if 0 /* Doesn't seem to work quite the way it should */
|
|
/* In some cases hero is 'centered' offscreen */
|
|
if( xdelta < 0 )
|
|
{
|
|
clipx = oldx;
|
|
clipxmax = clipx + incx;
|
|
}
|
|
else if( xdelta > 0 )
|
|
{
|
|
clipxmax = oldxmax;
|
|
clipx = clipxmax - incx;
|
|
}
|
|
else
|
|
{
|
|
clipx = oldx;
|
|
clipxmax = oldxmax;
|
|
}
|
|
|
|
if( ydelta < 0 )
|
|
{
|
|
clipy = oldy;
|
|
clipymax = clipy + incy;
|
|
}
|
|
else if( ydelta > 0 )
|
|
{
|
|
clipymax = oldymax;
|
|
clipy = clipymax - incy;
|
|
}
|
|
else
|
|
{
|
|
clipy = oldy;
|
|
clipymax = oldymax;
|
|
}
|
|
#endif
|
|
/* Now, in scrollcnt moves, move the picture toward the final view */
|
|
for (i = 0; i < scrollcnt; ++i) {
|
|
#ifdef DISPMAP
|
|
if (i == scrollcnt - 1 && (xmod != 0 || ymod != 0)
|
|
&& (xdelta != 0 || ydelta != 0)) {
|
|
incx += (clipx - oldx) % scrollcnt;
|
|
incy += (clipy - oldy) % scrollcnt;
|
|
xdelta += xmod;
|
|
ydelta += ymod;
|
|
}
|
|
#endif
|
|
/* Scroll the raster if we are scrolling */
|
|
if (xdelta != 0 || ydelta != 0) {
|
|
ScrollRaster(rp, xdelta, ydelta, w->BorderLeft, w->BorderTop,
|
|
w->Width - w->BorderRight - 1,
|
|
w->Height - w->BorderBottom - 1);
|
|
|
|
if (mincx == 0)
|
|
incx = 0;
|
|
else
|
|
mincx -= incx;
|
|
|
|
clipx += incx;
|
|
clipxmax += incx;
|
|
|
|
if (mincy == 0)
|
|
incy = 0;
|
|
else
|
|
mincy -= incy;
|
|
|
|
clipy += incy;
|
|
clipymax += incy;
|
|
|
|
/* Draw the exposed portion */
|
|
redraw_map();
|
|
flush_glyph_buffer(amii_wins[WIN_MAP]->win);
|
|
}
|
|
}
|
|
|
|
clipx = savex;
|
|
clipy = savey;
|
|
clipymax = saveymax;
|
|
clipxmax = savexmax;
|
|
#endif
|
|
redraw_map();
|
|
flush_glyph_buffer(amii_wins[WIN_MAP]->win);
|
|
}
|
|
reclip = 0;
|
|
#endif
|
|
}
|
|
|
|
void
|
|
flushIDCMP(port)
|
|
struct MsgPort *port;
|
|
{
|
|
struct Message *msg;
|
|
while (msg = GetMsg(port))
|
|
ReplyMsg(msg);
|
|
}
|