1 /*    SCCS Id: @(#)amiwind.c     3.2    2000/01/12
2 /*    Copyright (c) Olaf Seibert (KosmoSoft), 1989, 1992	  */
3 /*    Copyright (c) Kenneth Lorber, Bethesda, Maryland 1993,1996  */
4 /* NetHack may be freely redistributed.  See license for details. */
5 
6 #include "NH:sys/amiga/windefs.h"
7 #include "NH:sys/amiga/winext.h"
8 #include "NH:sys/amiga/winproto.h"
9 
10 /* Have to undef CLOSE as display.h and intuition.h both use it */
11 #undef CLOSE
12 
13 #ifdef AMII_GRAPHICS	/* too early in the file? too late? */
14 
15 #ifdef AMIFLUSH
16 static struct Message *FDECL(GetFMsg,(struct MsgPort *));
17 #endif
18 
19 static int BufferGetchar(void);
20 static void ProcessMessage( register struct IntuiMessage *message );
21 
22 #define BufferQueueChar(ch) (KbdBuffer[KbdBuffered++] = (ch))
23 
24 struct Library *ConsoleDevice;
25 
26 #include "NH:sys/amiga/amimenu.c"
27 
28 /* Now our own variables */
29 
30 struct IntuitionBase *IntuitionBase;
31 struct Screen *HackScreen;
32 struct Window *pr_WindowPtr;
33 struct MsgPort *HackPort;
34 struct IOStdReq ConsoleIO;
35 struct Menu *MenuStrip;
36 APTR *VisualInfo;
37 char Initialized = 0;
38 WEVENT lastevent;
39 
40 #ifdef HACKFONT
41 struct GfxBase *GfxBase;
42 struct Library *DiskfontBase;
43 #endif
44 
45 extern struct Library *ConsoleDevice;
46 
47 #define KBDBUFFER   10
48 static unsigned char KbdBuffer[KBDBUFFER];
49 unsigned char KbdBuffered;
50 
51 #ifdef HACKFONT
52 
53 struct TextFont *TextsFont = NULL;
54 struct TextFont *HackFont = NULL;
55 struct TextFont *RogueFont = NULL;
56 
57 UBYTE FontName[] = "NetHack:hack.font";
58     /* # chars in "NetHack:": */
59 #define         SIZEOF_DISKNAME 8
60 
61 #endif
62 
63 struct TextAttr Hack80 = {
64 #ifdef HACKFONT
65     &FontName[SIZEOF_DISKNAME],
66 #else
67     (UBYTE *) "topaz.font",
68 #endif
69     8, FS_NORMAL, FPF_DISKFONT | FPF_DESIGNED
70 	| FPF_ROMFONT
71 };
72 
73 struct TextAttr TextsFont13 = {
74     (UBYTE *) "courier.font",
75     13, FS_NORMAL, FPF_DISKFONT | FPF_DESIGNED
76 #ifndef	HACKFONT
77 	| FPF_ROMFONT
78 #endif
79 };
80 
81 /* Avoid doing a ReplyMsg through a window that no longer exists. */
82 static enum {NoAction, CloseOver} delayed_key_action = NoAction;
83 
84 /*
85  * Open a window that shares the HackPort IDCMP. Use CloseShWindow()
86  * to close.
87  */
88 
OpenShWindow(nw)89 struct Window *OpenShWindow(nw)
90 struct NewWindow *nw;
91 {
92     register struct Window *win;
93     register ULONG idcmpflags;
94 
95     if (!HackPort)  /* Sanity check */
96 	return (struct Window *) 0;
97 
98     idcmpflags = nw->IDCMPFlags;
99     nw->IDCMPFlags = 0;
100     if (!(win = OpenWindow((void *)nw)))
101     {
102 	nw->IDCMPFlags = idcmpflags;
103 	return (struct Window *) 0;
104     }
105 
106     nw->IDCMPFlags = idcmpflags;
107     win->UserPort = HackPort;
108     ModifyIDCMP(win, idcmpflags);
109     return win;
110 }
111 
112 
113 /*
114  * Close a window that shared the HackPort IDCMP port.
115  */
116 
117 void FDECL(CloseShWindow, (struct Window *));
CloseShWindow(win)118 void CloseShWindow(win)
119 struct Window *win;
120 {
121     register struct IntuiMessage *msg;
122 
123     if( !HackPort )
124 	panic("HackPort NULL in CloseShWindow" );
125     if (!win)
126 	return;
127 
128     Forbid();
129     /* Flush all messages for all windows to avoid typeahead and other
130      * similar problems...
131      */
132     while( msg = (struct IntuiMessage *)GetMsg( win->UserPort ) )
133 	ReplyMsg( (struct Message *) msg );
134     KbdBuffered = 0;
135     win->UserPort = (struct MsgPort *) 0;
136     ModifyIDCMP(win, 0L);
137     Permit();
138     CloseWindow(win);
139 }
140 
BufferGetchar()141 static int BufferGetchar()
142 {
143     register int c;
144 
145     if (KbdBuffered > 0) {
146 	c = KbdBuffer[0];
147 	KbdBuffered--;
148 	/* Move the remaining characters */
149 	if( KbdBuffered < sizeof( KbdBuffer ) )
150 	    memcpy( KbdBuffer, KbdBuffer+1, KbdBuffered );
151 	return c;
152     }
153 
154     return NO_CHAR;
155 }
156 
157 /*
158  *  This should remind you remotely of DeadKeyConvert, but we are cheating
159  *  a bit. We want complete control over the numeric keypad, and no dead
160  *  keys... (they are assumed to be on Alted keys).
161  *
162  *  Also assumed is that the IntuiMessage is of type RAWKEY.  For some
163  *  reason, IECODE_UP_PREFIX events seem to be lost when they  occur while
164  *  our console window is inactive. This is particulary  troublesome with
165  *  qualifier keys... Is this because I never RawKeyConvert those events???
166  */
167 
ConvertKey(message)168 int ConvertKey(message)
169 register struct IntuiMessage *message;
170 {
171     static struct InputEvent theEvent;
172     static char       numpad[] = "bjnh.lyku";
173     static char  ctrl_numpad[] = "\x02\x0A\x0E\x08.\x0C\x19\x0B\x15";
174     static char shift_numpad[] = "BJNH.LYKU";
175 
176     unsigned char buffer[10];
177     struct Window *w = message->IDCMPWindow;
178     register int length;
179     register ULONG qualifier;
180     char numeric_pad, shift, control, alt;
181 
182     if( amii_wins[ WIN_MAP ] )
183 	w = amii_wins[ WIN_MAP ]->win;
184     qualifier = message->Qualifier;
185 
186     control = (qualifier &  IEQUALIFIER_CONTROL) != 0;
187     shift   = (qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) != 0;
188     alt     = (qualifier & (IEQUALIFIER_LALT   | IEQUALIFIER_RALT  )) != 0;
189 
190     /* Allow ALT to function as a META key ... */
191     /* But make it switchable - alt is needed for some non-US keymaps */
192     if(flags.altmeta)
193 	qualifier &= ~(IEQUALIFIER_LALT | IEQUALIFIER_RALT);
194     numeric_pad = (qualifier & IEQUALIFIER_NUMERICPAD) != 0;
195 
196     /*
197      *  Shortcut for HELP and arrow keys. I suppose this is allowed.
198      *  The defines are in intuition/intuition.h, and the keys don't
199      *  serve 'text' input, normally. Also, parsing their escape
200      *  sequences is such a mess...
201      */
202 
203     switch (message->Code) {
204 	case RAWHELP:
205 	    if( alt )
206 	    {
207 		EditColor();
208 		return( -1 );
209 	    }
210 #ifdef	CLIPPING
211 	    else if( control )
212 	    {
213 		EditClipping();
214 
215 		CO = ( w->Width - w->BorderLeft - w->BorderRight  ) / mxsize;
216 		LI = ( w->Height - w->BorderTop - w->BorderBottom ) / mysize;
217 		clipxmax = CO + clipx;
218 		clipymax = LI + clipy;
219 		if( CO < COLNO || LI < ROWNO )
220 		{
221 		    clipping = TRUE;
222 		    amii_cliparound( u.ux, u.uy );
223 		}
224 		else
225 		{
226 		    clipping = FALSE;
227 		    clipx = clipy = 0;
228 		}
229 		BufferQueueChar( 'R'-64 );
230 		return(-1);
231 	    }
232 #endif
233 	    else if( WINVERS_AMIV && shift )
234 	    {
235 		if( WIN_OVER == WIN_ERR )
236 		{
237 		    WIN_OVER = amii_create_nhwindow( NHW_OVER );
238 		    BufferQueueChar( 'R'-64 );
239 		}
240 		else
241 		{
242 		    delayed_key_action = CloseOver;
243 		}
244 	    	return( -1 );
245 	    }
246 	    return( '?' );
247 	    break;
248 	case CURSORLEFT:
249 	    length = '4';
250 	    numeric_pad = 1;
251 	    goto arrow;
252 	case CURSORDOWN:
253 	    length = '2';
254 	    numeric_pad = 1;
255 	    goto arrow;
256 	case CURSORUP:
257 	    length = '8';
258 	    numeric_pad = 1;
259 	    goto arrow;
260 	case CURSORRIGHT:
261 	    length = '6';
262 	    numeric_pad = 1;
263 	    goto arrow;
264     }
265 
266     theEvent.ie_Class = IECLASS_RAWKEY;
267     theEvent.ie_Code = message->Code;
268     theEvent.ie_Qualifier = numeric_pad ? IEQUALIFIER_NUMERICPAD : qualifier;
269     theEvent.ie_EventAddress = (APTR) (message->IAddress);
270 
271     length = RawKeyConvert(&theEvent, (char *)buffer,
272       (long) sizeof(buffer), NULL);
273 
274     if (length == 1) {   /* Plain ASCII character */
275 	length = buffer[0];
276 	/*
277 	 *  If iflags.num_pad is set, movement is by 4286.
278 	 *  If not set, translate 4286 into hjkl.
279 	 *  This way, the numeric pad can /always/ be used
280 	 *  for moving, though best results are when it is off.
281 	 */
282 arrow:
283 	if (!iflags.num_pad && numeric_pad && length >= '1' && length <= '9') {
284 	    length -= '1';
285 	    if (control) {
286 		length = ctrl_numpad[length];
287 	    } else if (shift) {
288 		length = shift_numpad[length];
289 	    } else {
290 		length = numpad[length];
291 	    }
292 	}
293 	if (alt && flags.altmeta)
294 	    length |= 0x80;
295 	return(length);
296     } /* else shift, ctrl, alt, amiga, F-key, shift-tab, etc */
297     else if( length > 1 )
298     {
299 	int i;
300 
301 	if( length == 3 && buffer[ 0 ] == 155 && buffer[ 2 ] == 126 )
302 	{
303 	    int got = 1;
304 	    switch( buffer[ 1 ] )
305 	    {
306 		case 53: mxsize = mysize = 8; break;
307 		case 54: mxsize = mysize = 16; break;
308 		case 55: mxsize = mysize = 24; break;
309 		case 56: mxsize = mysize = 32; break;
310 		case 57: mxsize = mysize = 48; break;
311 		default: got = 0; break;
312 	    }
313 #ifdef OPT_DISPMAP
314 	    dispmap_sanity();
315 #endif
316 
317 	    if( got )
318 	    {
319 		CO = (w->Width-w->BorderLeft-w->BorderRight)/mxsize;
320 		LI = (w->Height-w->BorderTop-w->BorderBottom)/mysize;
321 		clipxmax = CO + clipx;
322 		clipymax = LI + clipy;
323 		if( CO < COLNO || LI < ROWNO )
324 		{
325 		    amii_cliparound( u.ux, u.uy );
326 		}
327 		else
328 		{
329 			CO = COLNO;
330 			LI = ROWNO;
331 		}
332 		reclip = 1;
333 		doredraw();
334 		flush_screen( 1 );
335 		reclip = 0;
336 		/*BufferQueueChar( 'R'-64 );*/
337 		return( -1 );
338 	    }
339 	}
340 	printf( "Unrecognized key: %d ", (int)buffer[0]);
341 	for( i = 1; i < length; ++i )
342 	    printf( "%d ", (int)buffer[i]);
343 	printf( "\n" );
344     }
345     return( -1 );
346 }
347 
348 /*
349  *  Process an incoming IntuiMessage.
350  *  It would certainly look nicer if this could be done using a
351  *  PA_SOFTINT message port, but we cannot call RawKeyConvert()
352  *  during a software interrupt.
353  *  Anyway, amikbhit()/kbhit() is called often enough, and usually gets
354  *  ahead of input demands, when the user types ahead.
355  */
356 
ProcessMessage(message)357 static void ProcessMessage(message)
358 register struct IntuiMessage *message;
359 {
360     int c;
361     int cnt;
362     menu_item *mip;
363     static int skip_mouse=0;    /* need to ignore next mouse event on
364 				 * a window activation */
365     struct Window *w = message->IDCMPWindow;
366 
367     switch(message->Class) {
368     case ACTIVEWINDOW:
369 	if( alwaysinvent && WIN_INVEN != WIN_ERR &&
370 			    w == amii_wins[ WIN_INVEN ]->win )
371 	{
372 	    cnt = DoMenuScroll( WIN_INVEN, 0, PICK_NONE, &mip );
373 	}
374 	else if( scrollmsg && WIN_MESSAGE != WIN_ERR &&
375 			    w == amii_wins[ WIN_MESSAGE ]->win )
376 	{
377 	    cnt = DoMenuScroll( WIN_MESSAGE, 0, PICK_NONE, &mip );
378 	}
379 	else
380 	{
381 	    skip_mouse=1;
382 	}
383 	break;
384 
385     case MOUSEBUTTONS:
386 	{
387 	    if( skip_mouse )
388 	    {
389 		skip_mouse=0;
390 		break;
391 	    }
392 
393 	    if( !amii_wins[ WIN_MAP ] || w != amii_wins[ WIN_MAP ]->win )
394 		break;
395 
396 	    if( message->Code == SELECTDOWN )
397 	    {
398 		lastevent.type = WEMOUSE;
399 		lastevent.un.mouse.x = message->MouseX;
400 		lastevent.un.mouse.y = message->MouseY;
401 		    /* With shift equals RUN */
402 		lastevent.un.mouse.qual = (message->Qualifier &
403 		  (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) != 0;
404 	    }
405 	}
406 	break;
407 
408     case MENUPICK:
409 	{
410 	    USHORT thismenu;
411 	    struct MenuItem *item;
412 
413 	    thismenu = message->Code;
414 	    while (thismenu != MENUNULL)
415 	    {
416 		item = ItemAddress(MenuStrip, (ULONG) thismenu);
417 		if (KbdBuffered < KBDBUFFER)
418 		    BufferQueueChar((char)(GTMENUITEM_USERDATA(item)));
419 		thismenu = item->NextSelect;
420 	    }
421 	}
422 	break;
423 
424     case REFRESHWINDOW:
425 	{
426 	    if( scrollmsg
427 		&& amii_wins[ WIN_MESSAGE ]
428 		&& w == amii_wins[ WIN_MESSAGE ]->win
429 	    ){
430 		cnt = DoMenuScroll( WIN_MESSAGE, 0, PICK_NONE, &mip );
431 	    }
432 	}
433 	break;
434 
435     case CLOSEWINDOW:
436 	if( WIN_INVEN != WIN_ERR && w == amii_wins[ WIN_INVEN ]->win )
437 	{
438 	    dismiss_nhwindow( WIN_INVEN );
439 	}
440 	if( WINVERS_AMIV
441 	    && ( WIN_OVER != WIN_ERR && w == amii_wins[ WIN_OVER ]->win )
442 	){
443 	    destroy_nhwindow( WIN_OVER );
444 	    WIN_OVER = WIN_ERR;
445 	}
446 	break;
447 
448     case RAWKEY:
449 	if (!(message->Code & IECODE_UP_PREFIX)){
450 	    /* May queue multiple characters
451 	     * but doesn't do that yet...
452 	     */
453 	    if( ( c = ConvertKey(message) ) > 0 )
454 		BufferQueueChar( c );
455         }
456         break;
457 
458     case GADGETDOWN:
459 	if( WIN_MESSAGE != WIN_ERR && w == amii_wins[ WIN_MESSAGE ]->win )
460 	{
461 	    cnt = DoMenuScroll( WIN_MESSAGE, 0, PICK_NONE, &mip );
462 	}
463 	else if( WIN_INVEN != WIN_ERR && w == amii_wins[ WIN_INVEN ]->win )
464 	{
465 	    cnt = DoMenuScroll( WIN_INVEN, 0, PICK_NONE, &mip );
466 	}
467 	break;
468 
469     case NEWSIZE:
470 	if( WIN_MESSAGE != WIN_ERR && w == amii_wins[ WIN_MESSAGE ]->win )
471 	{
472 	    if( WINVERS_AMIV )
473 	    {
474 		/* Make sure that new size is honored for good. */
475 		SetAPen( w->RPort, amii_msgBPen );
476 		SetBPen( w->RPort, amii_msgBPen );
477 		SetDrMd( w->RPort, JAM2 );
478 		RectFill( w->RPort, w->BorderLeft, w->BorderTop,
479 		  w->Width - w->BorderRight-1,
480 		  w->Height - w->BorderBottom-1 );
481 	    }
482 	    ReDisplayData( WIN_MESSAGE );
483 	}
484 	else if( WIN_INVEN != WIN_ERR && w == amii_wins[ WIN_INVEN ]->win )
485 	{
486 	    ReDisplayData( WIN_INVEN );
487 	}
488 	else if( WINVERS_AMIV
489 		 && ( WIN_OVER != WIN_ERR && w == amii_wins[ WIN_OVER ]->win )
490 	){
491 	    BufferQueueChar( 'R'-64 );
492 	}
493 	else if( WIN_MAP != WIN_ERR && w == amii_wins[ WIN_MAP ]->win )
494 	{
495 #ifdef	CLIPPING
496 	    CO = (w->Width-w->BorderLeft-w->BorderRight)/mxsize;
497 	    LI = (w->Height-w->BorderTop-w->BorderBottom)/mysize;
498 	    clipxmax = CO + clipx;
499 	    clipymax = LI + clipy;
500 	    if( CO < COLNO || LI < ROWNO )
501 	    {
502 		amii_cliparound( u.ux, u.uy );
503 	    }
504 	    else
505 	    {
506 	    	clipping = FALSE;
507 	    	clipx = clipy = 0;
508 	    }
509 	    BufferQueueChar( 'R'-64 );
510 #endif
511 	}
512 	break;
513     }
514     ReplyMsg((struct Message *) message);
515 
516     switch(delayed_key_action){
517     case CloseOver:
518 	amii_destroy_nhwindow( WIN_OVER );
519 	WIN_OVER = WIN_ERR;
520 	delayed_key_action = NoAction;
521     case NoAction:
522 	;	/* null */
523     }
524 }
525 
526 #endif /* AMII_GRAPHICS */
527 /*
528  *  Get all incoming messages and fill up the keyboard buffer,
529  *  thus allowing Intuition to (maybe) free up the IntuiMessages.
530  *  Return when no more messages left, or keyboard buffer half full.
531  *  We need to do this since there is no one-to-one correspondence
532  *  between characters and incoming messages.
533  */
534 
535 #if defined(TTY_GRAPHICS) && !defined(AMII_GRAPHICS)
kbhit()536 int kbhit(){
537 	return 0;
538 }
539 #else
540 int
kbhit()541 kbhit()
542 {
543     int c;
544 # ifdef TTY_GRAPHICS
545 		/* a kludge to defuse the mess in allmain.c */
546 		/* I hope this is the right approach */
547     if(windowprocs.win_init_nhwindows==amii_procs.win_init_nhwindows)return 0;
548 # endif
549     c = amikbhit();
550     if( c <= 0 )
551     	return( 0 );
552     return( c );
553 }
554 #endif
555 
556 #ifdef AMII_GRAPHICS
557 
558 int
amikbhit()559 amikbhit()
560 {
561     register struct IntuiMessage *message;
562     while( KbdBuffered < KBDBUFFER / 2 )
563     {
564 #ifdef AMIFLUSH
565 	message = (struct IntuiMessage *) GetFMsg(HackPort);
566 #else
567 	message = (struct IntuiMessage *) GetMsg(HackPort);
568 #endif
569 	if(message)
570 	{
571 	    ProcessMessage(message);
572 	    if( lastevent.type != WEUNK && lastevent.type != WEKEY )
573 		break;
574 	}
575 	else
576 	    break;
577     }
578     return ( lastevent.type == WEUNK ) ? KbdBuffered : -1;
579 }
580 
581 /*
582  *  Get a character from the keyboard buffer, waiting if not available.
583  *  Ignore other kinds of events that happen in the mean time.
584  */
585 
WindowGetchar()586 int WindowGetchar( )
587 {
588     while ((lastevent.type = WEUNK), amikbhit() <= 0) {
589 	WaitPort(HackPort);
590     }
591     return BufferGetchar();
592 }
593 
WindowGetevent()594 WETYPE WindowGetevent()
595 {
596     lastevent.type = WEUNK;
597     while (amikbhit() == 0)
598     {
599 	WaitPort(HackPort);
600     }
601 
602     if( KbdBuffered )
603     {
604 	lastevent.type = WEKEY;
605 	lastevent.un.key = BufferGetchar();
606     }
607     return( lastevent.type );
608 }
609 
610 /*
611  *  Clean up everything. But before we do, ask the user to hit return
612  *  when there is something that s/he should read.
613  */
614 
amii_cleanup()615 void amii_cleanup()
616 {
617     register struct IntuiMessage *msg;
618 
619     /* Close things up */
620     if( HackPort )
621     {
622 	amii_raw_print("");
623 	amii_getret();
624     }
625 
626     if (ConsoleIO.io_Device)
627 	CloseDevice( (struct IORequest *)&ConsoleIO );
628     ConsoleIO.io_Device = 0;
629 
630     if( ConsoleIO.io_Message.mn_ReplyPort )
631 	DeletePort( ConsoleIO.io_Message.mn_ReplyPort );
632     ConsoleIO.io_Message.mn_ReplyPort = 0;
633 
634     /* Strip messages before deleting the port */
635     if( HackPort )
636     {
637 	Forbid();
638 	while (msg = (struct IntuiMessage *) GetMsg(HackPort))
639 	    ReplyMsg((struct Message *) msg);
640 	kill_nhwindows( 1 );
641 	DeletePort( HackPort );
642 	HackPort = NULL;
643 	Permit();
644     }
645 
646     /* Close the screen, under v37 or greater it is a pub screen and there may
647      * be visitors, so check close status and wait till everyone is gone.
648      */
649     if( HackScreen )
650     {
651 #ifdef  INTUI_NEW_LOOK
652 	if( IntuitionBase->LibNode.lib_Version >= 37 )
653 	{
654 	    if (MenuStrip) FreeMenus(MenuStrip);
655 	    if (VisualInfo) FreeVisualInfo(VisualInfo);
656 	    while( CloseScreen( HackScreen ) == FALSE )
657 	    {
658 		struct EasyStruct easy =
659 		{
660 		    sizeof( struct EasyStruct ),
661 		    0,
662 		    "Nethack Problem",
663 		    "Can't Close Screen, Close Visiting Windows",
664 		    "Okay"
665 		};
666 		EasyRequest( NULL, &easy, NULL, NULL );
667 	    }
668 	}
669 	else
670 #endif
671 	{
672 	    CloseScreen(HackScreen);
673 	}
674 	HackScreen = NULL;
675     }
676 
677 #ifdef HACKFONT
678     if (HackFont)
679     {
680 	CloseFont(HackFont);
681 	HackFont = NULL;
682     }
683 
684     if( TextsFont )
685     {
686 	CloseFont( TextsFont );
687 	TextsFont = NULL;
688     }
689 
690     if( RogueFont )
691     {
692 	CloseFont( RogueFont );
693 	RogueFont = NULL;
694     }
695 
696     if( DiskfontBase )
697     {
698 	CloseLibrary(DiskfontBase);
699 	DiskfontBase = NULL;
700     }
701 #endif
702 
703     if( WINVERS_AMIV && LayersBase)
704     {
705 	CloseLibrary((struct Library *)LayersBase);
706 	LayersBase = NULL;
707     }
708 
709     if (GfxBase) {
710 	CloseLibrary((struct Library *)GfxBase);
711 	GfxBase = NULL;
712     }
713 
714     if (IntuitionBase) {
715 	CloseLibrary((struct Library *)IntuitionBase);
716 	IntuitionBase = NULL;
717     }
718 
719 #ifdef	SHAREDLIB
720     if (DOSBase) {
721 	CloseLibrary((struct Library *)DOSBase);
722 	DOSBase = NULL;
723     }
724 #endif
725 
726     ((struct Process *) FindTask(NULL))->pr_WindowPtr = (APTR) pr_WindowPtr;
727 
728     Initialized = 0;
729 }
730 
731 #endif	/* AMII_GRAPHICS */
732 
733 #ifndef	SHAREDLIB
Abort(rc)734 void Abort(rc)
735 long rc;
736 {
737     int fault = 1;
738 #ifdef CHDIR
739     extern char orgdir[];
740     chdir(orgdir);
741 #endif
742 #ifdef AMII_GRAPHICS
743     if (Initialized
744       && ConsoleDevice
745       && windowprocs.win_init_nhwindows==amii_procs.win_init_nhwindows) {
746       printf("\n\nAbort with alert code %08lx...\n", rc);
747       amii_getret();
748     } else
749 #endif
750       printf("\n\nAbort with alert code %08lx...\n",rc);
751       /* Alert(rc);              this is too severe */
752 #ifdef __SASC
753 # ifdef	INTUI_NEW_LOOK
754     if( IntuitionBase->LibNode.lib_Version >= 37 )
755     {
756     	struct EasyStruct es =
757     	{
758     		sizeof( struct EasyStruct ),
759     		0,
760     		"NetHack Panic Request",
761     		"NetHack is Aborting with code == 0x%08lx",
762 		"Continue Abort|Return to Program|Clean up and exit",
763     	};
764     	fault = EasyRequest( NULL, &es, NULL, (long)rc );
765     	if( fault == 2 )
766     	    return;
767     }
768 # endif
769     if( fault == 1 )
770     {
771 /*  __emit(0x4afc); */    /* illegal instruction */
772     __emit(0x40fc);     /* divide by */
773     __emit(0x0000);     /*  #0  */
774       /* NOTE: don't move amii_cleanup() above here - */
775       /* it is too likely to kill the system     */
776       /* before it can get the SnapShot out, if  */
777       /* there is something really wrong.    */
778     }
779 #endif
780 #ifdef AMII_GRAPHICS
781     if(windowprocs.win_init_nhwindows==amii_procs.win_init_nhwindows)
782       amii_cleanup();
783 #endif
784 #undef exit
785 #ifdef AZTEC_C
786     _abort();
787 #endif
788     exit((int) rc);
789 }
790 
791 void
CleanUp()792 CleanUp()
793 {
794 	amii_cleanup();
795 }
796 #endif
797 
798 #ifdef AMII_GRAPHICS
799 
800 #ifdef AMIFLUSH
801 /* This routine adapted from AmigaMail IV-37 by Michael Sinz */
802 static struct Message *
GetFMsg(port)803 GetFMsg(port)
804     struct MsgPort *port;
805     {
806     struct IntuiMessage *msg,*succ,*succ1;
807 
808     if(msg=(struct IntuiMessage *)GetMsg(port)){
809 	if(!flags.amiflush)return((struct Message *)msg);
810 	if(msg->Class==RAWKEY){
811 	    Forbid();
812 	    succ=(struct IntuiMessage *)(port->mp_MsgList.lh_Head);
813 	    while(succ1=(struct IntuiMessage *)
814 	      (succ->ExecMessage.mn_Node.ln_Succ)){
815 		if(succ->Class==RAWKEY){
816 		    Remove((struct Node *)succ);
817 		    ReplyMsg((struct Message *)succ);
818 		}
819 		succ=succ1;
820 	    }
821 	    Permit();
822 	}
823     }
824     return((struct Message *)msg);
825 }
826 #endif
827 
828 struct NewWindow *
DupNewWindow(win)829 DupNewWindow( win )
830     struct NewWindow *win;
831 {
832     struct NewWindow *nwin;
833     struct Gadget *ngd, *gd, *pgd = NULL;
834     struct PropInfo *pip;
835     struct StringInfo *sip;
836 
837     /* Copy the (Ext)NewWindow structure */
838 
839     nwin = (struct NewWindow *)alloc( sizeof( struct NewWindow ) );
840     *nwin = *win;
841 
842     /* Now do the gadget list */
843 
844     nwin->FirstGadget = NULL;
845     for( gd = win->FirstGadget; gd; gd = gd->NextGadget )
846     {
847 	ngd = (struct Gadget *)alloc( sizeof( struct Gadget ) );
848 	*ngd = *gd;
849 	if( gd->GadgetType == STRGADGET )
850 	{
851 	    sip = (struct StringInfo *)alloc( sizeof( struct StringInfo ) );
852 	    *sip = *((struct StringInfo *)gd->SpecialInfo);
853 	    sip->Buffer = (UBYTE *) alloc( sip->MaxChars );
854 	    *sip->Buffer = 0;
855 	    ngd->SpecialInfo = (APTR)sip;
856 	}
857 	else if( gd->GadgetType == PROPGADGET )
858 	{
859 	    pip = (struct PropInfo *)alloc( sizeof( struct PropInfo ) );
860 	    *pip = *((struct PropInfo *)gd->SpecialInfo);
861 	    ngd->SpecialInfo = (APTR)pip;
862 	}
863 	if( pgd )
864 	    pgd->NextGadget = ngd;
865 	else
866 	    nwin->FirstGadget = ngd;
867 	pgd = ngd;
868 	ngd->NextGadget = NULL;
869     }
870     return( nwin );
871 }
872 
873 void
FreeNewWindow(win)874 FreeNewWindow( win )
875     struct NewWindow *win;
876 {
877     register struct Gadget *gd, *pgd;
878     register struct StringInfo *sip;
879 
880     for( gd = win->FirstGadget; gd; gd = pgd )
881     {
882 	pgd = gd->NextGadget;
883 	if( gd->GadgetType == STRGADGET )
884 	{
885 	    sip = (struct StringInfo *)gd->SpecialInfo;
886 	    free( sip->Buffer );
887 	    free( sip );
888 	}
889 	else if( gd->GadgetType == PROPGADGET )
890 
891 	{
892 	    free( (struct PropInfo *)gd->SpecialInfo );
893 	}
894 	free( gd );
895     }
896     free( win );
897 }
898 
899 void
bell()900 bell()
901 {
902     if (flags.silent) return;
903     DisplayBeep(NULL);
904 }
905 
906 void
amii_delay_output()907 amii_delay_output()
908 {
909     /* delay 50 ms */
910     Delay(2L);
911 }
912 
913 void
amii_number_pad(state)914 amii_number_pad(state)
915 int state;
916 {
917 }
918 #endif  /* AMII_GRAPHICS */
919 
920 #ifndef	SHAREDLIB
921 void
amiv_loadlib(void)922 amiv_loadlib( void )
923 {
924 }
925 
926 void
amii_loadlib(void)927 amii_loadlib( void )
928 {
929 }
930 
931 /* fatal error */
932 /*VARARGS1*/
933 void error VA_DECL(const char *, s)
934     VA_START(s);
935     VA_INIT(s, char *);
936 
937     putchar('\n');
938     vprintf(s, VA_ARGS);
939     putchar('\n');
940 
941     VA_END();
942     Abort(0L);
943 }
944 #endif
945