From 32b60962a1b7b676abc7e4db78cbe91e52b3b13f Mon Sep 17 00:00:00 2001 From: jwalz Date: Sat, 5 Jan 2002 21:05:54 +0000 Subject: [PATCH] *** empty log message *** --- sys/amiga/amiwind.c | 953 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 953 insertions(+) create mode 100644 sys/amiga/amiwind.c diff --git a/sys/amiga/amiwind.c b/sys/amiga/amiwind.c new file mode 100644 index 000000000..fab7f722e --- /dev/null +++ b/sys/amiga/amiwind.c @@ -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