NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / sys / amiga / amiwind.c
blobcf8d46bcfc3e442e6110466bf9c5d7033498e9a1
1 /* aNetHack 0.0.1 amiwind.c $ANH-Date: 1432512794 2015/05/25 00:13:14 $ $ANH-Branch: master $:$ANH-Revision: 1.10 $ */
2 /* Copyright (c) Olaf Seibert (KosmoSoft), 1989, 1992 */
3 /* Copyright (c) Kenneth Lorber, Bethesda, Maryland 1993,1996 */
4 /* aNetHack may be freely redistributed. See license for details. */
6 #include "NH:sys/amiga/windefs.h"
7 #include "NH:sys/amiga/winext.h"
8 #include "NH:sys/amiga/winproto.h"
10 /* Have to undef CLOSE as display.h and intuition.h both use it */
11 #undef CLOSE
13 #ifdef AMII_GRAPHICS /* too early in the file? too late? */
15 #ifdef AMIFLUSH
16 static struct Message *FDECL(GetFMsg, (struct MsgPort *));
17 #endif
19 static int BufferGetchar(void);
20 static void ProcessMessage(register struct IntuiMessage *message);
22 #define BufferQueueChar(ch) (KbdBuffer[KbdBuffered++] = (ch))
24 struct Library *ConsoleDevice;
26 #include "NH:sys/amiga/amimenu.c"
28 /* Now our own variables */
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;
40 #ifdef HACKFONT
41 struct GfxBase *GfxBase;
42 struct Library *DiskfontBase;
43 #endif
45 #define KBDBUFFER 10
46 static unsigned char KbdBuffer[KBDBUFFER];
47 unsigned char KbdBuffered;
49 #ifdef HACKFONT
51 struct TextFont *TextsFont = NULL;
52 struct TextFont *HackFont = NULL;
53 struct TextFont *RogueFont = NULL;
55 UBYTE FontName[] = "aNetHack:hack.font";
56 /* # chars in "aNetHack:": */
57 #define SIZEOF_DISKNAME 8
59 #endif
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
70 struct TextAttr TextsFont13 = { (UBYTE *) "courier.font", 13, FS_NORMAL,
71 FPF_DISKFONT | FPF_DESIGNED
72 #ifndef HACKFONT
73 | FPF_ROMFONT
74 #endif
77 /* Avoid doing a ReplyMsg through a window that no longer exists. */
78 static enum { NoAction, CloseOver } delayed_key_action = NoAction;
81 * Open a window that shares the HackPort IDCMP. Use CloseShWindow()
82 * to close.
85 struct Window *
86 OpenShWindow(nw)
87 struct NewWindow *nw;
89 register struct Window *win;
90 register ULONG idcmpflags;
92 if (!HackPort) /* Sanity check */
93 return (struct Window *) 0;
95 idcmpflags = nw->IDCMPFlags;
96 nw->IDCMPFlags = 0;
97 if (!(win = OpenWindow((void *) nw))) {
98 nw->IDCMPFlags = idcmpflags;
99 return (struct Window *) 0;
102 nw->IDCMPFlags = idcmpflags;
103 win->UserPort = HackPort;
104 ModifyIDCMP(win, idcmpflags);
105 return win;
109 * Close a window that shared the HackPort IDCMP port.
112 void FDECL(CloseShWindow, (struct Window *));
113 void
114 CloseShWindow(win)
115 struct Window *win;
117 register struct IntuiMessage *msg;
119 if (!HackPort)
120 panic("HackPort NULL in CloseShWindow");
121 if (!win)
122 return;
124 Forbid();
125 /* Flush all messages for all windows to avoid typeahead and other
126 * similar problems...
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);
137 static int
138 BufferGetchar()
140 register int c;
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;
151 return NO_CHAR;
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).
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???
166 ConvertKey(message)
167 register struct IntuiMessage *message;
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";
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;
180 if (amii_wins[WIN_MAP])
181 w = amii_wins[WIN_MAP]->win;
182 qualifier = message->Qualifier;
184 control = (qualifier & IEQUALIFIER_CONTROL) != 0;
185 shift = (qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) != 0;
186 alt = (qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT)) != 0;
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;
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...
201 switch (message->Code) {
202 case RAWHELP:
203 if (alt) {
204 EditColor();
205 return (-1);
207 #ifdef CLIPPING
208 else if (WINVERS_AMIV && control) {
209 EditClipping();
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;
222 BufferQueueChar('R' - 64);
223 return (-1);
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;
233 return (-1);
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;
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);
260 length = RawKeyConvert(&theEvent, (char *) buffer, (long) sizeof(buffer),
261 NULL);
263 if (length == 1) { /* Plain ASCII character */
264 length = buffer[0];
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.
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];
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;
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;
318 #ifdef OPT_DISPMAP
319 dispmap_sanity();
320 #endif
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;
333 reclip = 1;
334 doredraw();
335 flush_screen(1);
336 reclip = 0;
337 /*BufferQueueChar( 'R'-64 );*/
338 return (-1);
341 printf("Unrecognized key: %d ", (int) buffer[0]);
342 for (i = 1; i < length; ++i)
343 printf("%d ", (int) buffer[i]);
344 printf("\n");
346 return (-1);
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.
358 static void
359 ProcessMessage(message)
360 register struct IntuiMessage *message;
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;
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;
380 break;
382 case MOUSEBUTTONS: {
383 if (skip_mouse) {
384 skip_mouse = 0;
385 break;
388 if (!amii_wins[WIN_MAP] || w != amii_wins[WIN_MAP]->win)
389 break;
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;
400 } break;
402 case MENUPICK: {
403 USHORT thismenu;
404 struct MenuItem *item;
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;
413 } break;
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);
420 } break;
422 case CLOSEWINDOW:
423 if (WIN_INVEN != WIN_ERR && w == amii_wins[WIN_INVEN]->win) {
424 dismiss_nhwindow(WIN_INVEN);
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;
431 break;
433 case RAWKEY:
434 if (!(message->Code & IECODE_UP_PREFIX)) {
435 /* May queue multiple characters
436 * but doesn't do that yet...
438 if ((c = ConvertKey(message)) > 0)
439 BufferQueueChar(c);
441 break;
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);
449 break;
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);
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;
480 BufferQueueChar('R' - 64);
481 #endif
483 break;
485 ReplyMsg((struct Message *) message);
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 */
497 #endif /* AMII_GRAPHICS */
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.
506 #if defined(TTY_GRAPHICS) && !defined(AMII_GRAPHICS)
508 kbhit()
510 return 0;
512 #else
514 kbhit()
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);
528 #endif
530 #ifdef AMII_GRAPHICS
533 amikbhit()
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;
549 return (lastevent.type == WEUNK) ? KbdBuffered : -1;
553 * Get a character from the keyboard buffer, waiting if not available.
554 * Ignore other kinds of events that happen in the mean time.
558 WindowGetchar()
560 while ((lastevent.type = WEUNK), amikbhit() <= 0) {
561 WaitPort(HackPort);
563 return BufferGetchar();
566 WETYPE
567 WindowGetevent()
569 lastevent.type = WEUNK;
570 while (amikbhit() == 0) {
571 WaitPort(HackPort);
574 if (KbdBuffered) {
575 lastevent.type = WEKEY;
576 lastevent.un.key = BufferGetchar();
578 return (lastevent.type);
582 * Clean up everything. But before we do, ask the user to hit return
583 * when there is something that s/he should read.
586 void
587 amii_cleanup()
589 register struct IntuiMessage *msg;
591 /* Close things up */
592 if (HackPort) {
593 amii_raw_print("");
594 amii_getret();
597 if (ConsoleIO.io_Device)
598 CloseDevice((struct IORequest *) &ConsoleIO);
599 ConsoleIO.io_Device = 0;
601 if (ConsoleIO.io_Message.mn_ReplyPort)
602 DeleteMsgPort(ConsoleIO.io_Message.mn_ReplyPort);
603 ConsoleIO.io_Message.mn_ReplyPort = 0;
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();
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.
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"
631 EasyRequest(NULL, &easy, NULL, NULL);
633 } else
634 #endif
636 CloseScreen(HackScreen);
638 HackScreen = NULL;
641 #ifdef HACKFONT
642 if (HackFont) {
643 CloseFont(HackFont);
644 HackFont = NULL;
647 if (TextsFont) {
648 CloseFont(TextsFont);
649 TextsFont = NULL;
652 if (RogueFont) {
653 CloseFont(RogueFont);
654 RogueFont = NULL;
657 if (DiskfontBase) {
658 CloseLibrary(DiskfontBase);
659 DiskfontBase = NULL;
661 #endif
663 if (GadToolsBase) {
664 CloseLibrary((struct Library *) GadToolsBase);
665 GadToolsBase = NULL;
668 if (LayersBase) {
669 CloseLibrary((struct Library *) LayersBase);
670 LayersBase = NULL;
673 if (GfxBase) {
674 CloseLibrary((struct Library *) GfxBase);
675 GfxBase = NULL;
678 if (IntuitionBase) {
679 CloseLibrary((struct Library *) IntuitionBase);
680 IntuitionBase = NULL;
683 #ifdef SHAREDLIB
684 if (DOSBase) {
685 CloseLibrary((struct Library *) DOSBase);
686 DOSBase = NULL;
688 #endif
690 ((struct Process *) FindTask(NULL))->pr_WindowPtr = (APTR) pr_WindowPtr;
692 Initialized = 0;
695 #endif /* AMII_GRAPHICS */
697 #ifndef SHAREDLIB
698 void
699 Abort(rc)
700 long rc;
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, "aNetHack Panic Request",
721 "aNetHack is Aborting with code == 0x%08lx",
722 "Continue Abort|Return to Program|Clean up and exit",
724 fault = EasyRequest(NULL, &es, NULL, (long) rc);
725 if (fault == 2)
726 return;
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. */
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);
750 void
751 CleanUp()
753 amii_cleanup();
755 #endif
757 #ifdef AMII_GRAPHICS
759 #ifdef AMIFLUSH
760 /* This routine adapted from AmigaMail IV-37 by Michael Sinz */
761 static struct Message *
762 GetFMsg(port)
763 struct MsgPort *port;
765 struct IntuiMessage *msg, *succ, *succ1;
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);
779 succ = succ1;
781 Permit();
784 return ((struct Message *) msg);
786 #endif
788 struct NewWindow *
789 DupNewWindow(win)
790 struct NewWindow *win;
792 struct NewWindow *nwin;
793 struct Gadget *ngd, *gd, *pgd = NULL;
794 struct PropInfo *pip;
795 struct StringInfo *sip;
797 /* Copy the (Ext)NewWindow structure */
799 nwin = (struct NewWindow *) alloc(sizeof(struct NewWindow));
800 *nwin = *win;
802 /* Now do the gadget list */
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;
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()
827 return (nwin);
830 void
831 FreeNewWindow(win)
832 struct NewWindow *win;
834 register struct Gadget *gd, *pgd;
835 register struct StringInfo *sip;
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);
847 free(gd);
850 free(win);
853 void
854 bell()
856 if (flags.silent)
857 return;
858 DisplayBeep(NULL);
861 void
862 amii_delay_output()
864 /* delay 50 ms */
865 Delay(2L);
868 void
869 amii_number_pad(state)
870 int state;
873 #endif /* AMII_GRAPHICS */
875 #ifndef SHAREDLIB
876 void
877 amiv_loadlib(void)
881 void
882 amii_loadlib(void)
886 /* fatal error */
887 /*VARARGS1*/
888 void error
889 VA_DECL(const char *, s)
891 VA_START(s);
892 VA_INIT(s, char *);
894 putchar('\n');
895 vprintf(s, VA_ARGS);
896 putchar('\n');
898 VA_END();
899 Abort(0L);
901 #endif