*** empty log message ***
This commit is contained in:
953
sys/amiga/amiwind.c
Normal file
953
sys/amiga/amiwind.c
Normal file
@@ -0,0 +1,953 @@
|
||||
/* SCCS Id: @(#)amiwind.c 3.2 2000/01/12
|
||||
/* Copyright (c) Olaf Seibert (KosmoSoft), 1989, 1992 */
|
||||
/* Copyright (c) Kenneth Lorber, Bethesda, Maryland 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"
|
||||
|
||||
/* 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 *FDECL(GetFMsg,(struct MsgPort *));
|
||||
#endif
|
||||
|
||||
static int BufferGetchar(void);
|
||||
static void ProcessMessage( register struct IntuiMessage *message );
|
||||
|
||||
#define BufferQueueChar(ch) (KbdBuffer[KbdBuffered++] = (ch))
|
||||
|
||||
#ifdef __GNUC__ /* Conflicting includefiles ... */
|
||||
struct Device *ConsoleDevice;
|
||||
#else
|
||||
struct Library *ConsoleDevice;
|
||||
#endif
|
||||
|
||||
#include "NH:sys/amiga/amimenu.c"
|
||||
|
||||
/* 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 FDECL(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(flags.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 && flags.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(!flags.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
|
||||
Reference in New Issue
Block a user