Update the Amiga Intuition window port (AMII/AMIV) for the 3.7 window_procs API. Key changes: - Update all window function signatures for 3.7 - Add assembly trampolines for AmigaOS register-based callbacks - Convert all K&R function definitions to C99 - Add cross-compilation build system (cross-pre1/pre2/post.370) using bebbo's m68k-amigaos-gcc with -noixemul -std=gnu17 -m68000 - Clipping fixes: viewport centering, simplified ScrollRaster, duplicate Ctrl-R suppression, glyph buffer invalidation - Add menucolor support in menu rendering - Move native txt2iff.c and xpm2iff.c to outdated/ - Add nethack.cnf and README.amiga
2374 lines
70 KiB
C
2374 lines
70 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. */
|
|
|
|
#ifndef CROSS_TO_AMIGA
|
|
#include "NH:sys/amiga/windefs.h"
|
|
#include "NH:sys/amiga/winext.h"
|
|
#include "NH:sys/amiga/winproto.h"
|
|
#else
|
|
#include "windefs.h"
|
|
#include "winext.h"
|
|
#include "winproto.h"
|
|
#endif
|
|
|
|
#include "patchlevel.h"
|
|
|
|
extern struct TagItem scrntags[];
|
|
#ifndef CROSS_TO_AMIGA
|
|
extern struct Library *ConsoleDevice;
|
|
#else
|
|
extern struct Device *
|
|
# ifdef __CONSTLIBBASEDECL__
|
|
__CONSTLIBBASEDECL__
|
|
# endif /* __CONSTLIBBASEDECL__ */
|
|
ConsoleDevice;
|
|
#endif
|
|
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;
|
|
|
|
/* Track the last level we centered the clipping viewport on, so that
|
|
both amii_clear_nhwindow (pre-docrt centering) and amii_cliparound
|
|
(scroll/pan during play) can detect level changes. */
|
|
static d_level clip_saved_level = { 127, 127 }; /* XXX */
|
|
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(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) {
|
|
amii_numcolors = 8;
|
|
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(winid win) /* just hide */
|
|
{
|
|
int i;
|
|
int type;
|
|
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
|
|
/* Assembly trampoline: Intuition calls LayerFillHook with arguments
|
|
in registers a0 (hook), a1 (fillparams), a2 (rastport).
|
|
Push them onto the stack and call the C implementation. */
|
|
__asm(
|
|
" .globl _LayerFillHook\n"
|
|
"_LayerFillHook:\n"
|
|
" move.l a1,-(sp)\n"
|
|
" move.l a2,-(sp)\n"
|
|
" move.l a0,-(sp)\n"
|
|
" jsr _LayerFillHook_impl\n"
|
|
" lea 12(sp),sp\n"
|
|
" rts\n"
|
|
);
|
|
void
|
|
LayerFillHook_impl(struct Hook *hk, struct RastPort *rp,
|
|
struct FillParams *fp)
|
|
{
|
|
#endif
|
|
#else
|
|
void
|
|
#ifndef _DCC
|
|
__interrupt
|
|
#endif
|
|
__saveds __asm LayerFillHook(__a0 struct Hook *hk,
|
|
__a2 struct RastPort *rp,
|
|
__a1 struct FillParams *fp)
|
|
{
|
|
#endif
|
|
|
|
long x, y, xmax, ymax;
|
|
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
|
|
|
|
winid
|
|
amii_create_nhwindow(int type)
|
|
{
|
|
struct Window *w = NULL;
|
|
struct NewWindow *nw = NULL;
|
|
struct amii_WinDesc *wd = NULL;
|
|
struct Window *mapwin = NULL, *stwin = NULL, *msgwin = NULL;
|
|
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) {
|
|
fillhook.h_Entry = (void *) &LayerFillHook;
|
|
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;
|
|
/* Map window uses y+2 offset in amii_print_glyph, so cury
|
|
values go up to ROWNO+2. Ensure rows accommodates this. */
|
|
if (type == NHW_MAP && wd->rows < ROWNO + 3)
|
|
wd->rows = ROWNO + 3;
|
|
}
|
|
|
|
/* 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[0][0] = '\0';
|
|
wd->data[1] = (char *) alloc(wd->cols + 10);
|
|
wd->data[1][0] = '\0';
|
|
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 */
|
|
{
|
|
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 Device *) 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
|
|
/* Assembly trampoline for SM_Filter hook callback.
|
|
SM_Filter is the asm entry point; SM_Filter_impl is the C body. */
|
|
extern void SM_Filter(void);
|
|
__asm(
|
|
" .globl _SM_Filter\n"
|
|
"_SM_Filter:\n"
|
|
" move.l a2,-(sp)\n"
|
|
" move.l a1,-(sp)\n"
|
|
" move.l a0,-(sp)\n"
|
|
" jsr _SM_Filter_impl\n"
|
|
" lea 12(sp),sp\n"
|
|
" rts\n"
|
|
);
|
|
int
|
|
SM_Filter_impl(struct Hook *hk, ULONG modeID,
|
|
struct ScreenModeRequester *smr)
|
|
{
|
|
#endif
|
|
#else
|
|
int
|
|
#ifndef _DCC
|
|
__interrupt
|
|
#endif
|
|
__saveds __asm SM_Filter(
|
|
__a0 struct Hook *hk, __a1 ULONG modeID,
|
|
__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(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) {
|
|
extern char *tilefile;
|
|
if (amii_numcolors >= 32) {
|
|
tilefile = "NetHack:tiles/tiles32.iff";
|
|
amii_numcolors = 32;
|
|
} else {
|
|
tilefile = "NetHack:tiles/tiles16.iff";
|
|
}
|
|
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) {
|
|
if (--NewHackScreen.Depth < 3)
|
|
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(winid win)
|
|
{
|
|
struct amii_WinDesc *cw;
|
|
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);
|
|
|
|
#ifdef CLIPPING
|
|
/* When clearing the map for a full redraw (docrt/cls), center the
|
|
clipping viewport on the player BEFORE the map is redrawn.
|
|
Without this, the first docrt() after a level change or new game
|
|
draws with stale clip coordinates (typically 0,0), leaving the
|
|
player off-screen until their first move triggers amii_cliparound. */
|
|
if (cw->type == NHW_MAP && clipping && u.ux
|
|
&& !on_level(&u.uz, &clip_saved_level)) {
|
|
int COx, LIx;
|
|
struct RastPort *rp = w->RPort;
|
|
|
|
if (Is_rogue_level(&u.uz)) {
|
|
COx = (w->Width - w->BorderLeft - w->BorderRight) / rp->TxWidth;
|
|
LIx = (w->Height - w->BorderTop - w->BorderBottom) / rp->TxHeight;
|
|
} else {
|
|
COx = CO;
|
|
LIx = LI;
|
|
}
|
|
clipx = max(0, (int) u.ux - COx / 2);
|
|
clipxmax = clipx + COx;
|
|
if (clipxmax > COLNO) {
|
|
clipxmax = COLNO;
|
|
clipx = clipxmax - COx;
|
|
}
|
|
clipy = max(0, (int) u.uy - LIx / 2);
|
|
clipymax = clipy + LIx;
|
|
if (clipymax > ROWNO) {
|
|
clipymax = ROWNO;
|
|
clipy = clipymax - LIx;
|
|
}
|
|
clip_saved_level = u.uz;
|
|
}
|
|
#endif
|
|
|
|
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(winid win)
|
|
{
|
|
struct Window *w;
|
|
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(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(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(winid window, int x, int y)
|
|
{
|
|
struct amii_WinDesc *cw;
|
|
struct Window *w;
|
|
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;
|
|
|
|
/* Silently skip rendering for out-of-bounds coordinates */
|
|
if (cw->rows > 0 && y >= cw->rows)
|
|
return;
|
|
if (cw->cols > 0 && x >= cw->cols)
|
|
return;
|
|
|
|
#ifdef DEBUG
|
|
if (0 && (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(char *name, int size)
|
|
{
|
|
int i;
|
|
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(int all)
|
|
{
|
|
int i;
|
|
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(struct amii_WinDesc *cw, int curs_pos)
|
|
{
|
|
struct Window *w = cw->win;
|
|
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(winid window)
|
|
{
|
|
struct amii_WinDesc *cw;
|
|
struct Window *w;
|
|
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(winid window)
|
|
{
|
|
int x, y;
|
|
struct amii_WinDesc *cw;
|
|
struct Window *w;
|
|
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 {
|
|
if (w && x >= 0 && y >= 0
|
|
&& x < w->Width && y < w->Height) {
|
|
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(struct RastPort *rp, int x, int 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(const char *str)
|
|
{
|
|
if (HackScreen)
|
|
ScreenToBack(HackScreen);
|
|
}
|
|
|
|
void
|
|
amii_resume_nhwindows(void)
|
|
{
|
|
if (HackScreen)
|
|
ScreenToFront(HackScreen);
|
|
}
|
|
|
|
void
|
|
amii_bell(void)
|
|
{
|
|
DisplayBeep(NULL);
|
|
}
|
|
|
|
void
|
|
removetopl(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(void)
|
|
{
|
|
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(winid win, coordxy x, coordxy y,
|
|
const glyph_info *glyphinfo,
|
|
const glyph_info *bkglyphinfo UNUSED)
|
|
{
|
|
struct amii_WinDesc *cw;
|
|
uchar ch;
|
|
int glyph;
|
|
int color, och;
|
|
extern const int zapcolors[];
|
|
unsigned special;
|
|
|
|
|
|
glyph = glyphinfo->glyph;
|
|
|
|
/* 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 */
|
|
ch = glyphinfo->ttychar;
|
|
color = glyphinfo->gm.sym.color;
|
|
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);
|
|
|
|
/* Turn off color if rogue level. */
|
|
if (Is_rogue_level(&u.uz))
|
|
color = NO_COLOR;
|
|
|
|
amiga_print_glyph(win, color, ch);
|
|
cw->curx++; /* one character over */
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Make sure the user sees a text string when no windowing is available */
|
|
|
|
void
|
|
amii_raw_print(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(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(int arg UNUSED)
|
|
{
|
|
struct amii_WinDesc *cw;
|
|
|
|
|
|
if (WIN_INVEN != WIN_ERR && (cw = amii_wins[WIN_INVEN])
|
|
&& cw->type == NHW_MENU && cw->win) {
|
|
repopulate_perminvent();
|
|
}
|
|
}
|
|
|
|
/* Stub for ctrl_nhwindow - no special handling needed for Amiga */
|
|
win_request_info *
|
|
amii_ctrl_nhwindow(winid window UNUSED, int request UNUSED, win_request_info *wri UNUSED)
|
|
{
|
|
return (win_request_info *) 0;
|
|
}
|
|
|
|
/* Humm, doesn't really do anything useful */
|
|
|
|
void
|
|
amii_mark_synch(void)
|
|
{
|
|
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(void)
|
|
{
|
|
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(void)
|
|
{
|
|
#ifdef CLIPPING
|
|
clipping = TRUE;
|
|
clipx = clipy = 0;
|
|
clipxmax = CO;
|
|
clipymax = LI;
|
|
/* some of this is now redundant with top of amii_cliparound XXX */
|
|
#endif
|
|
}
|
|
|
|
/* Redraw a rectangular region of the map via newsym(). Used after
|
|
ScrollRaster() shifts existing pixels — only the exposed strip needs
|
|
redrawing. Does NOT flush; the caller flushes after all regions. */
|
|
static void
|
|
redraw_map_region(int x1, int y1, int x2, int y2)
|
|
{
|
|
int x, y;
|
|
|
|
if (!u.ux)
|
|
return;
|
|
if (x1 < 1) x1 = 1;
|
|
if (y1 < 0) y1 = 0;
|
|
if (x2 >= COLNO) x2 = COLNO - 1;
|
|
if (y2 >= ROWNO) y2 = ROWNO - 1;
|
|
for (y = y1; y <= y2; y++)
|
|
for (x = x1; x <= x2; x++) {
|
|
/* Invalidate the glyph buffer so newsym() redraws even if
|
|
* the glyph hasn't changed — the pixels were shifted by
|
|
* ScrollRaster and no longer match the buffer. */
|
|
gg.gbuf[y][x].glyphinfo.glyph = NO_GLYPH;
|
|
newsym(x, y);
|
|
}
|
|
}
|
|
|
|
/* XXX still to do: suppress scrolling if we violate the boundary but the
|
|
* edge of the map is already displayed
|
|
*/
|
|
void
|
|
amii_cliparound(int x, int 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.
|
|
*/
|
|
if (!on_level(&u.uz, &clip_saved_level)) {
|
|
scrollcnt = 1; /* jump with blanking */
|
|
/* Center viewport on the player for the new level. */
|
|
clipx = max(0, x - COx / 2);
|
|
clipxmax = clipx + COx;
|
|
if (clipxmax > COLNO) {
|
|
clipxmax = COLNO;
|
|
clipx = clipxmax - COx;
|
|
}
|
|
clipy = max(0, y - LIx / 2);
|
|
clipymax = clipy + LIx;
|
|
if (clipymax > ROWNO) {
|
|
clipymax = ROWNO;
|
|
clipy = clipymax - LIx;
|
|
}
|
|
clip_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) {
|
|
struct Window *w = amii_wins[WIN_MAP]->win;
|
|
struct RastPort *rp = w->RPort;
|
|
int dx = clipx - oldx;
|
|
int dy = clipy - oldy;
|
|
int scrx, scry; /* tile pixel dimensions */
|
|
int halfW, halfH; /* half viewport in tiles */
|
|
|
|
if (Is_rogue_level(&u.uz)) {
|
|
scrx = rp->TxWidth;
|
|
scry = rp->TxHeight;
|
|
} else {
|
|
scrx = mxsize;
|
|
scry = mysize;
|
|
}
|
|
|
|
halfW = COx / 2;
|
|
halfH = LIx / 2;
|
|
|
|
/* Erase the map cursor before shifting pixels, otherwise the
|
|
old cursor position leaves a COMPLEMENT artifact on screen. */
|
|
if (WIN_MAP != WIN_ERR)
|
|
cursor_off(WIN_MAP);
|
|
|
|
/* Large jumps (teleport, level change): just redraw everything. */
|
|
if (abs(dx) > halfW || abs(dy) > halfH
|
|
|| scrollcnt != SCROLLCNT) {
|
|
{
|
|
int savedAPen = rp->FgPen;
|
|
int savedDrMd = rp->DrawMode;
|
|
SetAPen(rp, amii_otherBPen);
|
|
SetDrMd(rp, JAM1);
|
|
RectFill(rp, w->BorderLeft, w->BorderTop,
|
|
w->Width - w->BorderRight - 1,
|
|
w->Height - w->BorderBottom - 1);
|
|
SetAPen(rp, savedAPen);
|
|
SetDrMd(rp, savedDrMd);
|
|
}
|
|
redraw_map(FALSE);
|
|
} else {
|
|
/* Flush pending glyphs — they reference old clip coords */
|
|
flush_glyph_buffer(w);
|
|
|
|
/* Hardware-blit the viewport by the scroll delta */
|
|
ScrollRaster(rp, dx * scrx, dy * scry,
|
|
w->BorderLeft, w->BorderTop,
|
|
w->Width - w->BorderRight - 1,
|
|
w->Height - w->BorderBottom - 1);
|
|
|
|
/* Redraw only the exposed strip(s) */
|
|
if (dx > 0)
|
|
redraw_map_region(clipxmax - dx, clipy,
|
|
clipxmax, clipymax - 1);
|
|
else if (dx < 0)
|
|
redraw_map_region(clipx, clipy,
|
|
clipx - dx, clipymax - 1);
|
|
|
|
if (dy > 0)
|
|
redraw_map_region(clipx, clipymax - dy,
|
|
clipxmax, clipymax - 1);
|
|
else if (dy < 0)
|
|
redraw_map_region(clipx, clipy,
|
|
clipxmax, clipy - dy - 1);
|
|
|
|
flush_glyph_buffer(w);
|
|
}
|
|
}
|
|
reclip = 0;
|
|
#endif
|
|
}
|
|
|
|
void
|
|
flushIDCMP(struct MsgPort *port)
|
|
{
|
|
struct Message *msg;
|
|
while (msg = GetMsg(port))
|
|
ReplyMsg(msg);
|
|
}
|