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