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