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