919 lines
24 KiB
C
919 lines
24 KiB
C
/* NetHack 3.6 amiwind.c $NHDT-Date: 1432512794 2015/05/25 00:13:14 $ $NHDT-Branch: master $:$NHDT-Revision: 1.10 $ */
|
|
/* Copyright (c) Olaf Seibert (KosmoSoft), 1989, 1992 */
|
|
/* Copyright (c) Kenneth Lorber, Bethesda, Maryland 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
|
|
|
|
/* Have to undef CLOSE as display.h and intuition.h both use it */
|
|
#undef CLOSE
|
|
|
|
#ifdef AMII_GRAPHICS /* too early in the file? too late? */
|
|
|
|
#ifdef AMIFLUSH
|
|
static struct Message *GetFMsg(struct MsgPort *);
|
|
#endif
|
|
|
|
static int BufferGetchar(void);
|
|
static void ProcessMessage(register struct IntuiMessage *message);
|
|
|
|
#define BufferQueueChar(ch) (KbdBuffer[KbdBuffered++] = (ch))
|
|
#ifndef CROSS_TO_AMIGA
|
|
struct Library *ConsoleDevice;
|
|
#else
|
|
struct Device *
|
|
# ifdef __CONSTLIBBASEDECL__
|
|
__CONSTLIBBASEDECL__
|
|
# endif /* __CONSTLIBBASEDECL__ */
|
|
ConsoleDevice;
|
|
#endif
|
|
|
|
#ifndef CROSS_TO_AMIGA
|
|
#include "NH:sys/amiga/amimenu.c"
|
|
#else
|
|
#include "amimenu.c"
|
|
#endif
|
|
|
|
/* Now our own variables */
|
|
|
|
struct IntuitionBase *IntuitionBase;
|
|
struct Screen *HackScreen;
|
|
struct Window *pr_WindowPtr;
|
|
struct MsgPort *HackPort;
|
|
struct IOStdReq ConsoleIO;
|
|
struct Menu *MenuStrip;
|
|
APTR *VisualInfo;
|
|
char Initialized = 0;
|
|
WEVENT lastevent;
|
|
|
|
#ifdef HACKFONT
|
|
struct GfxBase *GfxBase;
|
|
struct Library *DiskfontBase;
|
|
#endif
|
|
|
|
#define KBDBUFFER 10
|
|
static unsigned char KbdBuffer[KBDBUFFER];
|
|
unsigned char KbdBuffered;
|
|
|
|
#ifdef HACKFONT
|
|
|
|
struct TextFont *TextsFont = NULL;
|
|
struct TextFont *HackFont = NULL;
|
|
struct TextFont *RogueFont = NULL;
|
|
|
|
UBYTE FontName[] = "NetHack:hack.font";
|
|
/* # chars in "NetHack:": */
|
|
#define SIZEOF_DISKNAME 8
|
|
|
|
#endif
|
|
|
|
struct TextAttr Hack80 = {
|
|
#ifdef HACKFONT
|
|
&FontName[SIZEOF_DISKNAME],
|
|
#else
|
|
(UBYTE *) "topaz.font",
|
|
#endif
|
|
8, FS_NORMAL, FPF_DISKFONT | FPF_DESIGNED | FPF_ROMFONT
|
|
};
|
|
|
|
struct TextAttr TextsFont13 = { (UBYTE *) "courier.font", 13, FS_NORMAL,
|
|
FPF_DISKFONT | FPF_DESIGNED
|
|
#ifndef HACKFONT
|
|
| FPF_ROMFONT
|
|
#endif
|
|
};
|
|
|
|
/* Avoid doing a ReplyMsg through a window that no longer exists. */
|
|
static enum { NoAction, CloseOver } delayed_key_action = NoAction;
|
|
|
|
/*
|
|
* Open a window that shares the HackPort IDCMP. Use CloseShWindow()
|
|
* to close.
|
|
*/
|
|
|
|
struct Window *
|
|
OpenShWindow(nw)
|
|
struct NewWindow *nw;
|
|
{
|
|
register struct Window *win;
|
|
register ULONG idcmpflags;
|
|
|
|
if (!HackPort) /* Sanity check */
|
|
return (struct Window *) 0;
|
|
|
|
idcmpflags = nw->IDCMPFlags;
|
|
nw->IDCMPFlags = 0;
|
|
if (!(win = OpenWindow((void *) nw))) {
|
|
nw->IDCMPFlags = idcmpflags;
|
|
return (struct Window *) 0;
|
|
}
|
|
|
|
nw->IDCMPFlags = idcmpflags;
|
|
win->UserPort = HackPort;
|
|
ModifyIDCMP(win, idcmpflags);
|
|
return win;
|
|
}
|
|
|
|
/*
|
|
* Close a window that shared the HackPort IDCMP port.
|
|
*/
|
|
|
|
void CloseShWindow(struct Window *);
|
|
void
|
|
CloseShWindow(win)
|
|
struct Window *win;
|
|
{
|
|
register struct IntuiMessage *msg;
|
|
|
|
if (!HackPort)
|
|
panic("HackPort NULL in CloseShWindow");
|
|
if (!win)
|
|
return;
|
|
|
|
Forbid();
|
|
/* Flush all messages for all windows to avoid typeahead and other
|
|
* similar problems...
|
|
*/
|
|
while (msg = (struct IntuiMessage *) GetMsg(win->UserPort))
|
|
ReplyMsg((struct Message *) msg);
|
|
KbdBuffered = 0;
|
|
win->UserPort = (struct MsgPort *) 0;
|
|
ModifyIDCMP(win, 0L);
|
|
Permit();
|
|
CloseWindow(win);
|
|
}
|
|
|
|
static int
|
|
BufferGetchar()
|
|
{
|
|
register int c;
|
|
|
|
if (KbdBuffered > 0) {
|
|
c = KbdBuffer[0];
|
|
KbdBuffered--;
|
|
/* Move the remaining characters */
|
|
if (KbdBuffered < sizeof(KbdBuffer))
|
|
memcpy(KbdBuffer, KbdBuffer + 1, KbdBuffered);
|
|
return c;
|
|
}
|
|
|
|
return NO_CHAR;
|
|
}
|
|
|
|
/*
|
|
* This should remind you remotely of DeadKeyConvert, but we are cheating
|
|
* a bit. We want complete control over the numeric keypad, and no dead
|
|
* keys... (they are assumed to be on Alted keys).
|
|
*
|
|
* Also assumed is that the IntuiMessage is of type RAWKEY. For some
|
|
* reason, IECODE_UP_PREFIX events seem to be lost when they occur while
|
|
* our console window is inactive. This is particulary troublesome with
|
|
* qualifier keys... Is this because I never RawKeyConvert those events???
|
|
*/
|
|
|
|
int
|
|
ConvertKey(message)
|
|
register struct IntuiMessage *message;
|
|
{
|
|
static struct InputEvent theEvent;
|
|
static char numpad[] = "bjnh.lyku";
|
|
static char ctrl_numpad[] = "\x02\x0A\x0E\x08.\x0C\x19\x0B\x15";
|
|
static char shift_numpad[] = "BJNH.LYKU";
|
|
|
|
unsigned char buffer[10];
|
|
struct Window *w = message->IDCMPWindow;
|
|
register int length;
|
|
register ULONG qualifier;
|
|
char numeric_pad, shift, control, alt;
|
|
|
|
if (amii_wins[WIN_MAP])
|
|
w = amii_wins[WIN_MAP]->win;
|
|
qualifier = message->Qualifier;
|
|
|
|
control = (qualifier & IEQUALIFIER_CONTROL) != 0;
|
|
shift = (qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) != 0;
|
|
alt = (qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT)) != 0;
|
|
|
|
/* Allow ALT to function as a META key ... */
|
|
/* But make it switchable - alt is needed for some non-US keymaps */
|
|
if (sysflags.altmeta)
|
|
qualifier &= ~(IEQUALIFIER_LALT | IEQUALIFIER_RALT);
|
|
numeric_pad = (qualifier & IEQUALIFIER_NUMERICPAD) != 0;
|
|
|
|
/*
|
|
* Shortcut for HELP and arrow keys. I suppose this is allowed.
|
|
* The defines are in intuition/intuition.h, and the keys don't
|
|
* serve 'text' input, normally. Also, parsing their escape
|
|
* sequences is such a mess...
|
|
*/
|
|
|
|
switch (message->Code) {
|
|
case RAWHELP:
|
|
if (alt) {
|
|
EditColor();
|
|
return (-1);
|
|
}
|
|
#ifdef CLIPPING
|
|
else if (WINVERS_AMIV && control) {
|
|
EditClipping();
|
|
|
|
CO = (w->Width - w->BorderLeft - w->BorderRight) / mxsize;
|
|
LI = (w->Height - w->BorderTop - w->BorderBottom) / mysize;
|
|
clipxmax = CO + clipx;
|
|
clipymax = LI + clipy;
|
|
if (CO < COLNO || LI < ROWNO) {
|
|
clipping = TRUE;
|
|
amii_cliparound(u.ux, u.uy);
|
|
} else {
|
|
clipping = FALSE;
|
|
clipx = clipy = 0;
|
|
}
|
|
BufferQueueChar('R' - 64);
|
|
return (-1);
|
|
}
|
|
#endif
|
|
else if (WINVERS_AMIV && shift) {
|
|
if (WIN_OVER == WIN_ERR) {
|
|
WIN_OVER = amii_create_nhwindow(NHW_OVER);
|
|
BufferQueueChar('R' - 64);
|
|
} else {
|
|
delayed_key_action = CloseOver;
|
|
}
|
|
return (-1);
|
|
}
|
|
return ('?');
|
|
break;
|
|
case CURSORLEFT:
|
|
length = '4';
|
|
numeric_pad = 1;
|
|
goto arrow;
|
|
case CURSORDOWN:
|
|
length = '2';
|
|
numeric_pad = 1;
|
|
goto arrow;
|
|
case CURSORUP:
|
|
length = '8';
|
|
numeric_pad = 1;
|
|
goto arrow;
|
|
case CURSORRIGHT:
|
|
length = '6';
|
|
numeric_pad = 1;
|
|
goto arrow;
|
|
}
|
|
|
|
theEvent.ie_Class = IECLASS_RAWKEY;
|
|
theEvent.ie_Code = message->Code;
|
|
theEvent.ie_Qualifier = numeric_pad ? IEQUALIFIER_NUMERICPAD : qualifier;
|
|
theEvent.ie_EventAddress = (APTR)(message->IAddress);
|
|
|
|
length = RawKeyConvert(&theEvent, (char *) buffer, (long) sizeof(buffer),
|
|
NULL);
|
|
|
|
if (length == 1) { /* Plain ASCII character */
|
|
length = buffer[0];
|
|
/*
|
|
* If iflags.num_pad is set, movement is by 4286.
|
|
* If not set, translate 4286 into hjkl.
|
|
* This way, the numeric pad can /always/ be used
|
|
* for moving, though best results are when it is off.
|
|
*/
|
|
arrow:
|
|
if (!iflags.num_pad && numeric_pad && length >= '1'
|
|
&& length <= '9') {
|
|
length -= '1';
|
|
if (control) {
|
|
length = ctrl_numpad[length];
|
|
} else if (shift) {
|
|
length = shift_numpad[length];
|
|
} else {
|
|
length = numpad[length];
|
|
}
|
|
}
|
|
|
|
/* Kludge to allow altmeta on eg. scandinavian keymap (# ==
|
|
shift+alt+3)
|
|
and prevent it from interfering with # command (M-#) */
|
|
if (length == ('#' | 0x80))
|
|
return '#';
|
|
if (alt && sysflags.altmeta)
|
|
length |= 0x80;
|
|
return (length);
|
|
} /* else shift, ctrl, alt, amiga, F-key, shift-tab, etc */
|
|
else if (length > 1) {
|
|
int i;
|
|
|
|
if (length == 3 && buffer[0] == 155 && buffer[2] == 126) {
|
|
int got = 1;
|
|
switch (buffer[1]) {
|
|
case 53:
|
|
mxsize = mysize = 8;
|
|
break;
|
|
case 54:
|
|
mxsize = mysize = 16;
|
|
break;
|
|
case 55:
|
|
mxsize = mysize = 24;
|
|
break;
|
|
case 56:
|
|
mxsize = mysize = 32;
|
|
break;
|
|
case 57:
|
|
mxsize = mysize = 48;
|
|
break;
|
|
default:
|
|
got = 0;
|
|
break;
|
|
}
|
|
#ifdef OPT_DISPMAP
|
|
dispmap_sanity();
|
|
#endif
|
|
|
|
if (got) {
|
|
CO = (w->Width - w->BorderLeft - w->BorderRight) / mxsize;
|
|
LI = (w->Height - w->BorderTop - w->BorderBottom) / mysize;
|
|
clipxmax = CO + clipx;
|
|
clipymax = LI + clipy;
|
|
if (CO < COLNO || LI < ROWNO) {
|
|
amii_cliparound(u.ux, u.uy);
|
|
} else {
|
|
CO = COLNO;
|
|
LI = ROWNO;
|
|
}
|
|
reclip = 1;
|
|
doredraw();
|
|
flush_screen(1);
|
|
reclip = 0;
|
|
/*BufferQueueChar( 'R'-64 );*/
|
|
return (-1);
|
|
}
|
|
}
|
|
printf("Unrecognized key: %d ", (int) buffer[0]);
|
|
for (i = 1; i < length; ++i)
|
|
printf("%d ", (int) buffer[i]);
|
|
printf("\n");
|
|
}
|
|
return (-1);
|
|
}
|
|
|
|
/*
|
|
* Process an incoming IntuiMessage.
|
|
* It would certainly look nicer if this could be done using a
|
|
* PA_SOFTINT message port, but we cannot call RawKeyConvert()
|
|
* during a software interrupt.
|
|
* Anyway, amikbhit()/kbhit() is called often enough, and usually gets
|
|
* ahead of input demands, when the user types ahead.
|
|
*/
|
|
|
|
static void
|
|
ProcessMessage(message)
|
|
register struct IntuiMessage *message;
|
|
{
|
|
int c;
|
|
int cnt;
|
|
menu_item *mip;
|
|
static int skip_mouse = 0; /* need to ignore next mouse event on
|
|
* a window activation */
|
|
struct Window *w = message->IDCMPWindow;
|
|
|
|
switch (message->Class) {
|
|
case ACTIVEWINDOW:
|
|
if (alwaysinvent && WIN_INVEN != WIN_ERR
|
|
&& w == amii_wins[WIN_INVEN]->win) {
|
|
cnt = DoMenuScroll(WIN_INVEN, 0, PICK_NONE, &mip);
|
|
} else if (scrollmsg && WIN_MESSAGE != WIN_ERR
|
|
&& w == amii_wins[WIN_MESSAGE]->win) {
|
|
cnt = DoMenuScroll(WIN_MESSAGE, 0, PICK_NONE, &mip);
|
|
} else {
|
|
skip_mouse = 1;
|
|
}
|
|
break;
|
|
|
|
case MOUSEBUTTONS: {
|
|
if (skip_mouse) {
|
|
skip_mouse = 0;
|
|
break;
|
|
}
|
|
|
|
if (!amii_wins[WIN_MAP] || w != amii_wins[WIN_MAP]->win)
|
|
break;
|
|
|
|
if (message->Code == SELECTDOWN) {
|
|
lastevent.type = WEMOUSE;
|
|
lastevent.un.mouse.x = message->MouseX;
|
|
lastevent.un.mouse.y = message->MouseY;
|
|
/* With shift equals RUN */
|
|
lastevent.un.mouse.qual =
|
|
(message->Qualifier
|
|
& (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) != 0;
|
|
}
|
|
} break;
|
|
|
|
case MENUPICK: {
|
|
USHORT thismenu;
|
|
struct MenuItem *item;
|
|
|
|
thismenu = message->Code;
|
|
while (thismenu != MENUNULL) {
|
|
item = ItemAddress(MenuStrip, (ULONG) thismenu);
|
|
if (KbdBuffered < KBDBUFFER)
|
|
BufferQueueChar((char) (GTMENUITEM_USERDATA(item)));
|
|
thismenu = item->NextSelect;
|
|
}
|
|
} break;
|
|
|
|
case REFRESHWINDOW: {
|
|
if (scrollmsg && amii_wins[WIN_MESSAGE]
|
|
&& w == amii_wins[WIN_MESSAGE]->win) {
|
|
cnt = DoMenuScroll(WIN_MESSAGE, 0, PICK_NONE, &mip);
|
|
}
|
|
} break;
|
|
|
|
case CLOSEWINDOW:
|
|
if (WIN_INVEN != WIN_ERR && w == amii_wins[WIN_INVEN]->win) {
|
|
dismiss_nhwindow(WIN_INVEN);
|
|
}
|
|
if (WINVERS_AMIV
|
|
&& (WIN_OVER != WIN_ERR && w == amii_wins[WIN_OVER]->win)) {
|
|
destroy_nhwindow(WIN_OVER);
|
|
WIN_OVER = WIN_ERR;
|
|
}
|
|
break;
|
|
|
|
case RAWKEY:
|
|
if (!(message->Code & IECODE_UP_PREFIX)) {
|
|
/* May queue multiple characters
|
|
* but doesn't do that yet...
|
|
*/
|
|
if ((c = ConvertKey(message)) > 0)
|
|
BufferQueueChar(c);
|
|
}
|
|
break;
|
|
|
|
case GADGETDOWN:
|
|
if (WIN_MESSAGE != WIN_ERR && w == amii_wins[WIN_MESSAGE]->win) {
|
|
cnt = DoMenuScroll(WIN_MESSAGE, 0, PICK_NONE, &mip);
|
|
} else if (WIN_INVEN != WIN_ERR && w == amii_wins[WIN_INVEN]->win) {
|
|
cnt = DoMenuScroll(WIN_INVEN, 0, PICK_NONE, &mip);
|
|
}
|
|
break;
|
|
|
|
case NEWSIZE:
|
|
if (WIN_MESSAGE != WIN_ERR && w == amii_wins[WIN_MESSAGE]->win) {
|
|
if (WINVERS_AMIV) {
|
|
/* Make sure that new size is honored for good. */
|
|
SetAPen(w->RPort, amii_msgBPen);
|
|
SetBPen(w->RPort, amii_msgBPen);
|
|
SetDrMd(w->RPort, JAM2);
|
|
RectFill(w->RPort, w->BorderLeft, w->BorderTop,
|
|
w->Width - w->BorderRight - 1,
|
|
w->Height - w->BorderBottom - 1);
|
|
}
|
|
ReDisplayData(WIN_MESSAGE);
|
|
} else if (WIN_INVEN != WIN_ERR && w == amii_wins[WIN_INVEN]->win) {
|
|
ReDisplayData(WIN_INVEN);
|
|
} else if (WINVERS_AMIV && (WIN_OVER != WIN_ERR
|
|
&& w == amii_wins[WIN_OVER]->win)) {
|
|
BufferQueueChar('R' - 64);
|
|
} else if (WIN_MAP != WIN_ERR && w == amii_wins[WIN_MAP]->win) {
|
|
#ifdef CLIPPING
|
|
CO = (w->Width - w->BorderLeft - w->BorderRight) / mxsize;
|
|
LI = (w->Height - w->BorderTop - w->BorderBottom) / mysize;
|
|
clipxmax = CO + clipx;
|
|
clipymax = LI + clipy;
|
|
if (CO < COLNO || LI < ROWNO) {
|
|
amii_cliparound(u.ux, u.uy);
|
|
} else {
|
|
clipping = FALSE;
|
|
clipx = clipy = 0;
|
|
}
|
|
BufferQueueChar('R' - 64);
|
|
#endif
|
|
}
|
|
break;
|
|
}
|
|
ReplyMsg((struct Message *) message);
|
|
|
|
switch (delayed_key_action) {
|
|
case CloseOver:
|
|
amii_destroy_nhwindow(WIN_OVER);
|
|
WIN_OVER = WIN_ERR;
|
|
delayed_key_action = NoAction;
|
|
case NoAction:
|
|
; /* null */
|
|
}
|
|
}
|
|
|
|
#endif /* AMII_GRAPHICS */
|
|
/*
|
|
* Get all incoming messages and fill up the keyboard buffer,
|
|
* thus allowing Intuition to (maybe) free up the IntuiMessages.
|
|
* Return when no more messages left, or keyboard buffer half full.
|
|
* We need to do this since there is no one-to-one correspondence
|
|
* between characters and incoming messages.
|
|
*/
|
|
|
|
#if defined(TTY_GRAPHICS) && !defined(AMII_GRAPHICS)
|
|
int
|
|
kbhit()
|
|
{
|
|
return 0;
|
|
}
|
|
#else
|
|
int
|
|
kbhit()
|
|
{
|
|
int c;
|
|
#ifdef TTY_GRAPHICS
|
|
/* a kludge to defuse the mess in allmain.c */
|
|
/* I hope this is the right approach */
|
|
if (windowprocs.win_init_nhwindows == amii_procs.win_init_nhwindows)
|
|
return 0;
|
|
#endif
|
|
c = amikbhit();
|
|
if (c <= 0)
|
|
return (0);
|
|
return (c);
|
|
}
|
|
#endif
|
|
|
|
#ifdef AMII_GRAPHICS
|
|
|
|
int
|
|
amikbhit()
|
|
{
|
|
register struct IntuiMessage *message;
|
|
while (KbdBuffered < KBDBUFFER / 2) {
|
|
#ifdef AMIFLUSH
|
|
message = (struct IntuiMessage *) GetFMsg(HackPort);
|
|
#else
|
|
message = (struct IntuiMessage *) GetMsg(HackPort);
|
|
#endif
|
|
if (message) {
|
|
ProcessMessage(message);
|
|
if (lastevent.type != WEUNK && lastevent.type != WEKEY)
|
|
break;
|
|
} else
|
|
break;
|
|
}
|
|
return (lastevent.type == WEUNK) ? KbdBuffered : -1;
|
|
}
|
|
|
|
/*
|
|
* Get a character from the keyboard buffer, waiting if not available.
|
|
* Ignore other kinds of events that happen in the mean time.
|
|
*/
|
|
|
|
int
|
|
WindowGetchar()
|
|
{
|
|
while ((lastevent.type = WEUNK), amikbhit() <= 0) {
|
|
WaitPort(HackPort);
|
|
}
|
|
return BufferGetchar();
|
|
}
|
|
|
|
WETYPE
|
|
WindowGetevent()
|
|
{
|
|
lastevent.type = WEUNK;
|
|
while (amikbhit() == 0) {
|
|
WaitPort(HackPort);
|
|
}
|
|
|
|
if (KbdBuffered) {
|
|
lastevent.type = WEKEY;
|
|
lastevent.un.key = BufferGetchar();
|
|
}
|
|
return (lastevent.type);
|
|
}
|
|
|
|
/*
|
|
* Clean up everything. But before we do, ask the user to hit return
|
|
* when there is something that s/he should read.
|
|
*/
|
|
|
|
void
|
|
amii_cleanup()
|
|
{
|
|
register struct IntuiMessage *msg;
|
|
|
|
/* Close things up */
|
|
if (HackPort) {
|
|
amii_raw_print("");
|
|
amii_getret();
|
|
}
|
|
|
|
if (ConsoleIO.io_Device)
|
|
CloseDevice((struct IORequest *) &ConsoleIO);
|
|
ConsoleIO.io_Device = 0;
|
|
|
|
if (ConsoleIO.io_Message.mn_ReplyPort)
|
|
DeleteMsgPort(ConsoleIO.io_Message.mn_ReplyPort);
|
|
ConsoleIO.io_Message.mn_ReplyPort = 0;
|
|
|
|
/* Strip messages before deleting the port */
|
|
if (HackPort) {
|
|
Forbid();
|
|
while (msg = (struct IntuiMessage *) GetMsg(HackPort))
|
|
ReplyMsg((struct Message *) msg);
|
|
kill_nhwindows(1);
|
|
DeleteMsgPort(HackPort);
|
|
HackPort = NULL;
|
|
Permit();
|
|
}
|
|
|
|
/* Close the screen, under v37 or greater it is a pub screen and there may
|
|
* be visitors, so check close status and wait till everyone is gone.
|
|
*/
|
|
if (HackScreen) {
|
|
#ifdef INTUI_NEW_LOOK
|
|
if (IntuitionBase->LibNode.lib_Version >= 37) {
|
|
if (MenuStrip)
|
|
FreeMenus(MenuStrip);
|
|
if (VisualInfo)
|
|
FreeVisualInfo(VisualInfo);
|
|
while (CloseScreen(HackScreen) == FALSE) {
|
|
struct EasyStruct easy = {
|
|
sizeof(struct EasyStruct), 0, "Nethack Problem",
|
|
"Can't Close Screen, Close Visiting Windows", "Okay"
|
|
};
|
|
EasyRequest(NULL, &easy, NULL, NULL);
|
|
}
|
|
} else
|
|
#endif
|
|
{
|
|
CloseScreen(HackScreen);
|
|
}
|
|
HackScreen = NULL;
|
|
}
|
|
|
|
#ifdef HACKFONT
|
|
if (HackFont) {
|
|
CloseFont(HackFont);
|
|
HackFont = NULL;
|
|
}
|
|
|
|
if (TextsFont) {
|
|
CloseFont(TextsFont);
|
|
TextsFont = NULL;
|
|
}
|
|
|
|
if (RogueFont) {
|
|
CloseFont(RogueFont);
|
|
RogueFont = NULL;
|
|
}
|
|
|
|
if (DiskfontBase) {
|
|
CloseLibrary(DiskfontBase);
|
|
DiskfontBase = NULL;
|
|
}
|
|
#endif
|
|
|
|
if (GadToolsBase) {
|
|
CloseLibrary((struct Library *) GadToolsBase);
|
|
GadToolsBase = NULL;
|
|
}
|
|
|
|
if (LayersBase) {
|
|
CloseLibrary((struct Library *) LayersBase);
|
|
LayersBase = NULL;
|
|
}
|
|
|
|
if (GfxBase) {
|
|
CloseLibrary((struct Library *) GfxBase);
|
|
GfxBase = NULL;
|
|
}
|
|
|
|
if (IntuitionBase) {
|
|
CloseLibrary((struct Library *) IntuitionBase);
|
|
IntuitionBase = NULL;
|
|
}
|
|
|
|
#ifdef SHAREDLIB
|
|
if (DOSBase) {
|
|
CloseLibrary((struct Library *) DOSBase);
|
|
DOSBase = NULL;
|
|
}
|
|
#endif
|
|
|
|
((struct Process *) FindTask(NULL))->pr_WindowPtr = (APTR) pr_WindowPtr;
|
|
|
|
Initialized = 0;
|
|
}
|
|
|
|
#endif /* AMII_GRAPHICS */
|
|
|
|
#ifndef SHAREDLIB
|
|
void
|
|
Abort(rc)
|
|
long rc;
|
|
{
|
|
int fault = 1;
|
|
#ifdef CHDIR
|
|
extern char orgdir[];
|
|
chdir(orgdir);
|
|
#endif
|
|
#ifdef AMII_GRAPHICS
|
|
if (Initialized && ConsoleDevice
|
|
&& windowprocs.win_init_nhwindows == amii_procs.win_init_nhwindows) {
|
|
printf("\n\nAbort with alert code %08lx...\n", rc);
|
|
amii_getret();
|
|
} else
|
|
#endif
|
|
printf("\n\nAbort with alert code %08lx...\n", rc);
|
|
/* Alert(rc); this is too severe */
|
|
#ifdef __SASC
|
|
#ifdef INTUI_NEW_LOOK
|
|
if (IntuitionBase->LibNode.lib_Version >= 37) {
|
|
struct EasyStruct es = {
|
|
sizeof(struct EasyStruct), 0, "NetHack Panic Request",
|
|
"NetHack is Aborting with code == 0x%08lx",
|
|
"Continue Abort|Return to Program|Clean up and exit",
|
|
};
|
|
fault = EasyRequest(NULL, &es, NULL, (long) rc);
|
|
if (fault == 2)
|
|
return;
|
|
}
|
|
#endif
|
|
if (fault == 1) {
|
|
/* __emit(0x4afc); */ /* illegal instruction */
|
|
__emit(0x40fc); /* divide by */
|
|
__emit(0x0000); /* #0 */
|
|
/* NOTE: don't move amii_cleanup() above here - */
|
|
/* it is too likely to kill the system */
|
|
/* before it can get the SnapShot out, if */
|
|
/* there is something really wrong. */
|
|
}
|
|
#endif
|
|
#ifdef AMII_GRAPHICS
|
|
if (windowprocs.win_init_nhwindows == amii_procs.win_init_nhwindows)
|
|
amii_cleanup();
|
|
#endif
|
|
#undef exit
|
|
#ifdef AZTEC_C
|
|
_abort();
|
|
#endif
|
|
exit((int) rc);
|
|
}
|
|
|
|
void
|
|
CleanUp()
|
|
{
|
|
amii_cleanup();
|
|
}
|
|
#endif
|
|
|
|
#ifdef AMII_GRAPHICS
|
|
|
|
#ifdef AMIFLUSH
|
|
/* This routine adapted from AmigaMail IV-37 by Michael Sinz */
|
|
static struct Message *
|
|
GetFMsg(port)
|
|
struct MsgPort *port;
|
|
{
|
|
struct IntuiMessage *msg, *succ, *succ1;
|
|
|
|
if (msg = (struct IntuiMessage *) GetMsg(port)) {
|
|
if (!sysflags.amiflush)
|
|
return ((struct Message *) msg);
|
|
if (msg->Class == RAWKEY) {
|
|
Forbid();
|
|
succ = (struct IntuiMessage *) (port->mp_MsgList.lh_Head);
|
|
while (succ1 = (struct IntuiMessage *) (succ->ExecMessage.mn_Node
|
|
.ln_Succ)) {
|
|
if (succ->Class == RAWKEY) {
|
|
Remove((struct Node *) succ);
|
|
ReplyMsg((struct Message *) succ);
|
|
}
|
|
succ = succ1;
|
|
}
|
|
Permit();
|
|
}
|
|
}
|
|
return ((struct Message *) msg);
|
|
}
|
|
#endif
|
|
|
|
struct NewWindow *
|
|
DupNewWindow(win)
|
|
struct NewWindow *win;
|
|
{
|
|
struct NewWindow *nwin;
|
|
struct Gadget *ngd, *gd, *pgd = NULL;
|
|
struct PropInfo *pip;
|
|
struct StringInfo *sip;
|
|
|
|
/* Copy the (Ext)NewWindow structure */
|
|
|
|
nwin = (struct NewWindow *) alloc(sizeof(struct NewWindow));
|
|
*nwin = *win;
|
|
|
|
/* Now do the gadget list */
|
|
|
|
nwin->FirstGadget = NULL;
|
|
for (gd = win->FirstGadget; gd; gd = gd->NextGadget) {
|
|
ngd = (struct Gadget *) alloc(sizeof(struct Gadget));
|
|
*ngd = *gd;
|
|
if (gd->GadgetType == STRGADGET) {
|
|
sip = (struct StringInfo *) alloc(sizeof(struct StringInfo));
|
|
*sip = *((struct StringInfo *) gd->SpecialInfo);
|
|
sip->Buffer = (UBYTE *) alloc(sip->MaxChars);
|
|
*sip->Buffer = 0;
|
|
ngd->SpecialInfo = (APTR) sip;
|
|
} else if (gd->GadgetType == PROPGADGET) {
|
|
pip = (struct PropInfo *) alloc(sizeof(struct PropInfo));
|
|
*pip = *((struct PropInfo *) gd->SpecialInfo);
|
|
ngd->SpecialInfo = (APTR) pip;
|
|
}
|
|
if (pgd)
|
|
pgd->NextGadget = ngd;
|
|
else
|
|
nwin->FirstGadget = ngd;
|
|
pgd = ngd;
|
|
ngd->NextGadget = NULL;
|
|
ngd->UserData = (APTR) 0x45f35c3d; // magic cookie for FreeNewWindow()
|
|
}
|
|
return (nwin);
|
|
}
|
|
|
|
void
|
|
FreeNewWindow(win)
|
|
struct NewWindow *win;
|
|
{
|
|
register struct Gadget *gd, *pgd;
|
|
register struct StringInfo *sip;
|
|
|
|
for (gd = win->FirstGadget; gd; gd = pgd) {
|
|
pgd = gd->NextGadget;
|
|
if ((ULONG) gd->UserData == 0x45f35c3d) {
|
|
if (gd->GadgetType == STRGADGET) {
|
|
sip = (struct StringInfo *) gd->SpecialInfo;
|
|
free(sip->Buffer);
|
|
free(sip);
|
|
} else if (gd->GadgetType == PROPGADGET) {
|
|
free((struct PropInfo *) gd->SpecialInfo);
|
|
}
|
|
free(gd);
|
|
}
|
|
}
|
|
free(win);
|
|
}
|
|
|
|
void
|
|
bell()
|
|
{
|
|
if (flags.silent)
|
|
return;
|
|
DisplayBeep(NULL);
|
|
}
|
|
|
|
void
|
|
amii_delay_output()
|
|
{
|
|
/* delay 50 ms */
|
|
Delay(2L);
|
|
}
|
|
|
|
void
|
|
amii_number_pad(state)
|
|
int state;
|
|
{
|
|
}
|
|
#endif /* AMII_GRAPHICS */
|
|
|
|
#ifndef SHAREDLIB
|
|
void
|
|
amiv_loadlib(void)
|
|
{
|
|
}
|
|
|
|
void
|
|
amii_loadlib(void)
|
|
{
|
|
}
|
|
|
|
/* fatal error */
|
|
/*VARARGS1*/
|
|
void error
|
|
VA_DECL(const char *, s)
|
|
{
|
|
VA_START(s);
|
|
VA_INIT(s, char *);
|
|
|
|
putchar('\n');
|
|
vprintf(s, VA_ARGS);
|
|
putchar('\n');
|
|
|
|
VA_END();
|
|
Abort(0L);
|
|
}
|
|
#endif
|