/*
 * MandelVroom 2.0
 *
 * (c) Copyright 1987,1989  Kevin L. Clague, San Jose, CA
 *
 * All rights reserved.
 *
 * Permission is hereby granted to distribute this program's source
 * executable, and documentation for non-comercial purposes, so long as the
 * copyright notices are not removed from the sources, executable or
 * documentation.  This program may not be distributed for a profit without
 * the express written consent of the author Kevin L. Clague.
 *
 * This program is not in the public domain.
 *
 * Fred Fish is expressly granted permission to distribute this program's
 * source and executable as part of the "Fred Fish freely redistributable
 * Amiga software library."
 *
 * Permission is expressly granted for this program and it's source to be
 * distributed as part of the Amicus Amiga software disks, and the
 * First Amiga User Group's Hot Mix disks.
 *
 * contents:  this file contains the routines that open and close
 * MandelVrooms custom screen as well as the required Amiga libraries.
 *
 */

#include "mandp.h"

char *ExecLib   = "exec.library";
char *IntuiLib  = "intuition.library";
char *GfxLib    = "graphics.library";
char *LayersLib = "layers.library";
char *FFPLib    = "mathffp.library";
char *TransLib  = "mathtrans.library";
char *IEEELib   = "mathieeedoubbas.library";
char *IconLib   = "icon.library";

struct IntuitionBase       *IntuitionBase;
struct GfxBase             *GfxBase;
struct MathBase            *MathBase;
struct MathTransBase       *MathTransBase;
struct LayersBase          *LayersBase;
struct ExecBase            *ExecBase;
struct MathIeeeDoubBasBase *MathIeeeDoubBasBase;
extern struct IconBase     *IconBase;

struct Screen   *screen;
struct ViewPort *vp;

int Num_vp_Colors;

UBYTE StandardSize;

extern BYTE FromWB;

/*
 * The following window's message port is used to communicate with
 * all the other windows in the system.  It is a small backdrop,
 * borderless window that is always open and in custom screen used
 * by MandelVroom.
 */

struct Window *BackWind;

struct NewWindow NewBack = {
   0,10,                     /* start position           */
   0,0,                      /* width, height            */
   (UBYTE) 0, (UBYTE) 1,     /* detail pen, block pen    */
                             /* IDCMP flags */
   MENUPICK | GADGETDOWN | GADGETUP | REQCLEAR | CLOSEWINDOW |
   MOUSEBUTTONS | ACTIVEWINDOW | NEWSIZE,
   /* backWind flags */
   ACTIVATE|BACKDROP|BORDERLESS|REPORTMOUSE|NOCAREREFRESH|SIMPLE_REFRESH,
   (struct Gadget *) NULL,   /* first gadget             */
   (struct Image *) NULL,    /* user checkmark           */
   (UBYTE *) NULL,           /* Title                    */
   (struct Screen *) NULL,   /* pointer to screen        */
   (struct BitMap *) NULL,   /* pointer to superbitmap   */
   8,8,-1,-1,                /* sizing                   */
   CUSTOMSCREEN              /* type of screen           */
};

extern struct Window *CurWind;

SHORT YScale, XScale;

static
struct TextAttr myfont = {
   (STRPTR) "topaz.font",
   TOPAZ_EIGHTY,
   0,
   0
};


struct NewScreen NewScreen = {
   0,0,                      /* start position           */
   320, 200, 5,              /* width, height, depth     */
   (UBYTE)  0, (UBYTE)  1,   /* detail pen, block pen    */
   (USHORT) NULL,            /* HIRES, INTERLACE, SPRITES, DUAL, HAM */
   CUSTOMSCREEN,             /* screen type              */
   &myfont,                  /* font to use              */
   (UBYTE *) NULL,
   (struct Gadget *) NULL    /* pointer to extra gadgets */
};

/***************************************************************************
 *
 * Open the Libraries and custom screen
 *
 **************************************************************************/

/*
 * Open the libraries
 */
int
OpenLibs() {

  ExecBase = (struct ExecBase *) OpenLibrary( ExecLib, (long) 0);

  if (ExecBase == NULL) {
     LibErr( ExecLib );
     return( 100);
     }

#define LIB_FOR_1_2 33L
  IntuitionBase = (struct IntuitionBase *) OpenLibrary( IntuiLib,
                  LIB_FOR_1_2);

  if (IntuitionBase == NULL) {
     LibErr( IntuiLib );
     return(100);
     }

  GfxBase = (struct GfxBase *) OpenLibrary( GfxLib, (long) 0);

  if (GfxBase == NULL) {
     LibErr( GfxLib );
     return(100);
     }

  LayersBase = (struct LayersBase *) OpenLibrary( LayersLib, (long) 0);

  if (LayersBase == NULL) {
     LibErr( LayersLib );
     return(100);
     }

  MathIeeeDoubBasBase = (struct MathIeeeDoubBasBase *)
     OpenLibrary( IEEELib, (long) 0);

  if (MathIeeeDoubBasBase == NULL) {
     LibErr( IEEELib );
     return(100);
     }

  /* if started from the workbench, then open the icon library */

  if (FromWB) {

    IconBase = (struct IconBase *) OpenLibrary( IconLib, (long) 0);

    if (IconBase == NULL) {
       LibErr( IconLib );
       return(100);
       }
  }

  return(0);
} /* OpenLibs */

OpenFFPLibs()
{
  if ( MathBase == NULL ) {

    MathBase = (struct MathBase *) OpenLibrary( FFPLib, (long) 0);

    if (MathBase == NULL) {
       DispErrMsg( "Can't open FFP library", 0);
       return(100);
    }
  }

  if ( MathTransBase == NULL ) {

    MathTransBase = (struct MathTransBase *)
                    OpenLibrary( TransLib, (long) 0);

    if (MathTransBase == NULL) {
       DispErrMsg( "Can't open FFP transcendental library", 0);
       return(100);
    }
  }
  return(0);
}

LibErr( Name )
  char *Name;
{
  printf("Can't open %s\nPlease check to see if it is present on your disk\n",Name);
}

/*
 * Close the libraries used
 */
CloseLibs() {

  if ( MathBase )
    CloseLibrary( MathBase );
  MathBase = NULL;

  if ( MathTransBase )
    CloseLibrary( MathTransBase );
  MathTransBase = NULL;

  if ( MathIeeeDoubBasBase )
    CloseLibrary( MathIeeeDoubBasBase );
  MathIeeeDoubBasBase = NULL;

  if ( IconBase )
    CloseLibrary( IconBase );
  IconBase = NULL;

  if ( IntuitionBase )
    CloseLibrary( IntuitionBase );
  IntuitionBase = NULL;

  if ( LayersBase )
    CloseLibrary( LayersBase );
  LayersBase = NULL;

  if ( GfxBase )
    CloseLibrary( GfxBase );
  GfxBase = NULL;

  if ( ExecBase )
    CloseLibrary( ExecBase );
  ExecBase = NULL;

} /* CloseLibs */

struct Window *Save_PR_Wind;

/*
 * Open the display
 */
int
OpenDisp()
{
  extern UBYTE ContOpen, PaletteOpen, CycleOpen, HistOpen;

  extern struct MenuItem GenerateSubs[];

  NewScreenSize( &NewScreen );

  if (NewScreen.ViewModes & HIRES) {
    XScale = 1;
  } else {
    XScale = 0;
  }

  if (NewScreen.ViewModes & INTERLACE) {
    YScale = 1;
  } else {
    YScale = 0;
  }

  RightMarg = 16;

  screen = OpenScreen( (struct NewScreen *) &NewScreen);

  if (screen == NULL) {
     AndDie("Can't open new screen!\n");
  }
  vp = &screen->ViewPort;

  Num_vp_Colors = 1 << NewScreen.Depth;

  if (Num_vp_Colors > 32)
    Num_vp_Colors = 32;

  if (CurPict)
    LoadRGB4(vp, CurPict->RGBs, Num_vp_Colors );
  else
    DefaultColors();

  if ( ExecBase->AttnFlags & AFF_68020 ) {
    GenerateSubs[ INTIIGENERATOR ].Flags |= ITEMENABLED;
  }

  if ( ExecBase->AttnFlags & AFF_68881 ) {
    GenerateSubs[ _81GENERATOR ].Flags |= ITEMENABLED;
  }

  InitViewModesSubs();
  InitDepthSubs();
  InitGenSubs();

  AllocateMice();

  OpenBackWind();      /* Open this before any other window */

  Save_PR_Wind = (struct Window *)
                 ((struct Process *) FindTask(0L))->pr_WindowPtr;

  ((struct Process *) FindTask(0L))->pr_WindowPtr = (APTR) BackWind;

  ReOpenPicts();

  if (ContOpen)    OpenContWind();
  if (HistOpen)    OpenHistWind();
  if (PaletteOpen) OpenPalWind();
  if (CycleOpen)   OpenCycWind();

  return(0);
} /* opendisp */

/*
 *  Close the screen
 */
CloseDisp() {

  if ( screen ) {

    CloseCycWind();
    ClosePalWind();
    CloseContWind();
    CloseHistWind();
    CloseStatsWind();
    CloseOrbitWind();

    CloseHelpWind(0,NULL);

    ClosePicts();

    CloseBackWind();   /* Close this window last */

    ((struct Process *) FindTask(0L))->pr_WindowPtr = (APTR) Save_PR_Wind;

    NewScreen.TopEdge = screen->TopEdge >> YScale;

    CloseScreen( screen );

    screen = NULL;

    FreeMice();
  }
} /* CloseDisp */

/*
 * Check New Screen Size
 */
int
NewScreenSize( NewScreen )
  struct NewScreen *NewScreen;
{
  extern struct MenuItem ScreenSizeSubs[];

  struct Screen WBenchScreen;

  (void) GetScreenData( &WBenchScreen, sizeof(struct Screen),
                         WBENCHSCREEN, NULL);

  if (!(WBenchScreen.ViewPort.Modes & LACE)) {
    WBenchScreen.Height <<= 1;
  }

  if ( StandardSize ) {

    WBenchScreen.Width  = 640;

    if (GfxBase->DisplayFlags & PAL)
      WBenchScreen.Height = 512;
    else
      WBenchScreen.Height = 400;
  }

  if (NewScreen->ViewModes & HIRES) {

    if ( NewScreen->Depth > 4 )
      NewScreen->Depth = 4;

    if ( NewScreen->ViewModes & EXTRA_HALFBRITE )
      NewScreen->ViewModes &= ~EXTRA_HALFBRITE;

    NewScreen->Width = WBenchScreen.Width;

  } else {

    NewScreen->Width = WBenchScreen.Width >> 1;
  }

  if (NewScreen->ViewModes & INTERLACE) {

    NewScreen->Height = WBenchScreen.Height;
  } else {

    NewScreen->Height = WBenchScreen.Height >> 1;
  }

  if (NewScreen->ViewModes & EXTRA_HALFBRITE) {

    NewScreen->Depth = 6;
  } else {

    if (NewScreen->Depth == 6)
      NewScreen->Depth = 5;
  }

  NewScreen->TopEdge <<= YScale;
} /* NewScreenSize */

SaveRGBs( Pict )
  struct Picture *Pict;
{
  register int i;
  register SHORT *RGBs;

  if (Pict) {

    RGBs = Pict->RGBs;

    for (i = 0; i < Num_vp_Colors; i++)
      *RGBs++ = GetRGB4(vp->ColorMap, i);
  }
}

AndDie( ErrMsg )
  char *ErrMsg;
{
  printf("%s\n", ErrMsg);

  ThrowPicts();

  CloseTasks();
  CloseDisp();
  CloseLibs();

  exit(0);
}

OpenBackWind()
{
  NewBack.Screen = screen;
  NewBack.Width  = screen->Width;
  NewBack.Height = screen->Height - NewBack.TopEdge - 1;

  BackWind = OpenWindow( &NewBack );

  if ( BackWind == NULL ) {
    AndDie("Can't open common window\n");
  }

  (void) SetMenuStrip( BackWind, Menu );

  CurWind = BackWind;

  ForceNormPointer();
}

CloseBackWind()
{
  ClearPointer( BackWind );

  ClearMenuStrip( BackWind );

  CloseWindow( BackWind );
  BackWind = NULL;
}

/***************************************************************************
 *
 * Open and Close Window tools
 *
 **************************************************************************/

int NumWindows;

/*
 *  Open a window and put it in the window list
 */
struct Window *OpenMyWind(NewWind, Screen, Gadgets, Width, Height)
  struct NewWindow *NewWind;
  struct Screen *Screen;
  struct Gadget *Gadgets;
  SHORT  Width, Height;
{
  register struct Window *Window;
  register LONG t;

  NewWind->Screen = Screen;
  NewWind->FirstGadget = Gadgets;

  NewWind->Width = Width;
  NewWind->Height = Height;

  /* Window too wide ? */

  t = Width - Screen->Width;

  if (t > 0) {
    Width -= t;
  }

  /* Too far to the right ? */

  t = NewWind->LeftEdge + Width - Screen->Width;

  if ( t > 0 ) {
    NewWind->LeftEdge -= t;
  }

  /* Window too tall ? */

  t = Height - Screen->Height;

  if (t > 0) {
    Height -= t;
  }

  /* Too close to the bottom ? */

  t = NewWind->TopEdge + Height - Screen->Height;

  if ( t > 0 ) {
    NewWind->TopEdge -= t;
  }

  Window = OpenWindow( NewWind );

  if (Window == (struct Window *) NULL) {
    DispErrMsg("Can't open new window",0);
    return( (struct Window *) NULL);
  }

  Window->UserPort = BackWind->UserPort;
  ModifyIDCMP( Window, (long) BackWind->IDCMPFlags );

  Window->UserData = NULL;

  (void) SetMenuStrip(Window, Menu);

  CurWind = Window;

  ForceNormPointer();

  return(Window);
} /* OpenMyWind */

/*
 * Deallocate all the gadgets associated with this window
 * Close the window
 */
CloseMyWind(Window,Gadgets)
  struct Window *Window;
  struct Gadget *Gadgets;
{
  if (Window) {

     /* get rid of the menu */
     if (Window->MenuStrip)
       ClearMenuStrip(Window);

     /* get rid of the pointer */
     if (Window->Pointer)
       ClearPointer( Window );

     if ( Window == CurWind ) {
       CurWind = BackWind;
     }

     CloseWindowSafely( Window );

     if (Gadgets)
       FreeGadgets(Gadgets);
  }
} /* CloseMyWind */

/***************************************************************************
 *
 * This section handles the Mouse pointer for the custom screen
 *
 **************************************************************************/

USHORT *BabyBrotPointer;
USHORT *BabyToPointer;
USHORT *BabyWithPointer;
USHORT *SleepyPointer;

/***************************************************************/
/*  This is the image for baby Mandelbrot pointer              */
/***************************************************************/

USHORT BabyBrotSprite[]=  {
 0x0000, 0x0000,
 0x8000, 0x0000,
 0x5000, 0x5000,
 0x2202, 0x2202,
 0x4D82, 0x5F82,
 0x0013, 0x1913,
 0x006C, 0x11FE,
 0x2000, 0x300A,
 0x0C00, 0x1C06,
 0x1004, 0x1407,
 0x0004, 0x0404,
 0x0028, 0x042C,
 0x0800, 0x0C1C,
 0x0220, 0x0630,
 0x01C0, 0x05F0,
 0x3800, 0x3F80,
 0x0000, 0x0880,
 0x0000, 0x0000,
 };

/***************************************************************/
/*  This is a baby brot pointer with 'TO' in it.               */
/***************************************************************/
USHORT BabyToSprite[]=  {
 0x0000, 0x0000,
 0x8000, 0x0000,
 0x5000, 0x5000,
 0x2202, 0x2202,
 0x4D82, 0x5F82,
 0x0013, 0x1913,
 0x006C, 0x11FE,
 0x2000, 0x300A,
 0x0C00, 0x1C06,
 0x1004, 0x1407,
 0x0004, 0x0404,
 0x0028, 0x042C,
 0x0800, 0x0C1C,
 0x0220, 0x0630,
 0x01C0, 0x05F0,
 0x3800, 0x3F80,
 0x0000, 0x0880,
 0x0000, 0x0000,
 0x3F00, 0x3F00,
 0x2D00, 0x3F80,
 0x0C78, 0x1EF8,
 0x0CCC, 0x0EFC,
 0x0CCC, 0x0EEE,
 0x0CCC, 0x0EEE,
 0x1E78, 0x1E7E,
 0x0000, 0x0F3C,
 0x0000, 0x0000,
 };

/***************************************************************/
/*  This is a baby brot pointer with 'WITH' in it.             */
/***************************************************************/
USHORT BabyWithSprite[]=  {
 0x0000, 0x0000,
 0x8000, 0x0000,
 0x5000, 0x5000,
 0x2202, 0x2202,
 0x4D82, 0x5F82,
 0x0013, 0x1913,
 0x006C, 0x11FE,
 0x2000, 0x300A,
 0x0C00, 0x1C06,
 0x1004, 0x1407,
 0x0004, 0x0404,
 0x0028, 0x042C,
 0x0800, 0x0C1C,
 0x0220, 0x0630,
 0x01C0, 0x05F0,
 0x3800, 0x3F80,
 0x0000, 0x0880,
 0x0000, 0x0000,
 0x0630, 0x0630,
 0x0630, 0x0738,
 0x0630, 0x0738,
 0x06B0, 0x07B8,
 0x07F0, 0x07F8,
 0x0770, 0x07F8,
 0x0630, 0x07B8,
 0x0000, 0x0318,
 0x00C0, 0x00C0,
 0x0000, 0x0060,
 0x01C0, 0x01C0,
 0x00C0, 0x00E0,
 0x00C0, 0x00E0,
 0x00C0, 0x00E0,
 0x01E0, 0x01E0,
 0x0000, 0x00F0,
 0x0000, 0x0000,
 0x0040, 0x0040,
 0x00C0, 0x00E0,
 0x01F0, 0x01F0,
 0x00C0, 0x00F8,
 0x00C0, 0x00E0,
 0x00D0, 0x00F0,
 0x0060, 0x0068,
 0x0700, 0x0730,
 0x0300, 0x0380,
 0x0360, 0x03E0,
 0x03B0, 0x03B0,
 0x0330, 0x03F8,
 0x0330, 0x03B8,
 0x0730, 0x07B8,
 0x0000, 0x0398,
 0x0000, 0x0000,
 };

/***************************************************************/
/*  This is a sleepy cloud pointer                             */
/***************************************************************/
USHORT SleepySprite[] = {
      0x0000,  0x0000,
      0x0fe0,  0x0000,
      0x1830,  0x07c0,
      0x7018,  0x0fe0,
      0xc008,  0x3ff0,
      0x9e0c,  0x7ff0,
      0x8406,  0x7ff8,
      0x8802,  0x7ffc,
      0x1e03,  0xfffc,
      0x80f1,  0x7ffe,
      0x8021,  0x7ffe,
      0x4040,  0x3fff,
      0x80f1,  0x7ffe,
      0xc001,  0x3ffe,
      0x6003,  0x1ffc,
      0x3006,  0x0ff8,
      0x180c,  0x07f0,
      0x0718,  0x00e0,
      0x0070,  0x0f80,
      0x1810,  0x07e0,
      0x0820,  0x0740,
      0x0ff0,  0x0000,
      0x0020,  0x03c0,
      0x0410,  0x03e0,
      0x0310,  0x00e0,
      0x00e0,  0x0000,
      0x0000,  0x0000,
     };

/* pointer types  */
#define UNINITIALIZED 0
#define NORMPOINTER   1
#define TOPOINTER     2
#define WITHPOINTER   3
#define SLEEPYPOINTER 4

UBYTE   PointerType = UNINITIALIZED;

/* defines for the cute pointer sprite */
#define MYSPRITE_WIDTH    ((long) 16)
#define MYSPRITE_HEIGHT   ((long) 16)
#define TOSPRITE_WIDTH    ((long) 16)
#define TOSPRITE_HEIGHT   ((long) 25)
#define WITHSPRITE_WIDTH  ((long) 16)
#define WITHSPRITE_HEIGHT ((long) 50)
#define SLEEPY_WIDTH      ((long) 16)
#define SLEEPY_HEIGHT     ((long) 25)
#define MYSPRITE_HOTX     ((long) -1)
#define MYSPRITE_HOTY     ((long)  0)

#define BABYSIZE   ((int) ((MYSPRITE_HEIGHT   + 2) * 8))
#define TOSIZE     ((int) ((TOSPRITE_HEIGHT   + 2) * 8))
#define WITHSIZE   ((int) ((WITHSPRITE_HEIGHT + 2) * 8))
#define SLEEPYSIZE ((int) ((SLEEPY_HEIGHT     + 2) * 8))

/*
 * Copy an Image into a chip ram image
 */
USHORT *
MakeChipSprite( FastRamSprite, Size )
  register USHORT *FastRamSprite;
  register int    Size;
{
  register USHORT *ChipSprite, *SaveSprite;
  register int i;

  ChipSprite = (USHORT *)
               safeAllocMem( (ULONG) (Size * sizeof(SHORT)), MEMF_CHIP );

  if ( ChipSprite == NULL )
    return ( ChipSprite );

  SaveSprite = ChipSprite;

  for ( i = 0; i < Size; i++)
    *(ChipSprite++) = *(FastRamSprite++);

  return( SaveSprite );
}

/*
 * Allocate all the mouse pointer sprites used by this program
 */
AllocateMice()
{
  BabyBrotPointer = MakeChipSprite( BabyBrotSprite, BABYSIZE );
  BabyToPointer   = MakeChipSprite( BabyToSprite,   TOSIZE );
  BabyWithPointer = MakeChipSprite( BabyWithSprite, WITHSIZE );
  SleepyPointer   = MakeChipSprite( SleepySprite,   SLEEPYSIZE );
}

/*
 * Free all the mouse pointer sprites used by this program
 */
FreeMice()
{
  if ( BabyBrotPointer )
    FreeMem( (char *) BabyBrotPointer, (long) BABYSIZE * sizeof(SHORT) );
  BabyBrotPointer = NULL;

  if ( BabyToPointer )
    FreeMem( (char *) BabyToPointer, (long) TOSIZE * sizeof(SHORT) );
  BabyToPointer = NULL;

  if ( BabyWithPointer )
    FreeMem( (char *) BabyWithPointer, (long) WITHSIZE * sizeof(SHORT) );
  BabyWithPointer = NULL;

  if ( SleepyPointer )
    FreeMem( (char *) SleepyPointer, (long) SLEEPYSIZE * sizeof(SHORT) );
  SleepyPointer = NULL;
}


/*
 * Set all window pointers NewPointer
 */
SetPointers()
{
  SetMouse( CurWind );
}

/*
 * Force normal pointers
 */
ForceNormPointer()
{
  PointerType = UNINITIALIZED;

  SetNormPointer();
}

/*
 * Set Normal Mouse Pointer
 */
SetNormPointer()
{
  if (PointerType != NORMPOINTER ) {

    PointerType = NORMPOINTER;

    SetPointers();
  }
}

/*
 * Set 'To' Mouse Pointer
 */
SetToPointer()
{
  if (PointerType != TOPOINTER ) {

    PointerType = TOPOINTER;

    SetPointers();
  }
}

/*
 * Set 'With' Mouse Pointer
 */
SetWithPointer()
{
  if (PointerType != TOPOINTER ) {

    PointerType = WITHPOINTER;

    SetPointers();
  }
}

/*
 * Set Sleepy Mouse Pointer
 */
SetSleepyPointer()
{
  if (PointerType != SLEEPYPOINTER ) {

    PointerType = SLEEPYPOINTER;

    SetPointers();
  }
}

SetMouse( window )
  struct Window *window;
{
  if (window == NULL)
    return;

  switch ( PointerType ) {

    case   NORMPOINTER:
           SetPointer( window,          BabyBrotPointer,
                       MYSPRITE_HEIGHT, MYSPRITE_WIDTH,
                       MYSPRITE_HOTX,   MYSPRITE_HOTY);
           break;

    case   TOPOINTER:
           SetPointer( window,          BabyToPointer,
                       TOSPRITE_HEIGHT, TOSPRITE_WIDTH,
                       MYSPRITE_HOTX,   MYSPRITE_HOTY);
           break;

    case   WITHPOINTER:
           SetPointer( window,            BabyWithPointer,
                       WITHSPRITE_HEIGHT, WITHSPRITE_WIDTH,
                       MYSPRITE_HOTX,     MYSPRITE_HOTY);
           break;

    case   SLEEPYPOINTER:
           SetPointer( window,          SleepyPointer,
                       SLEEPY_HEIGHT,   SLEEPY_WIDTH,
                       MYSPRITE_HOTX,   MYSPRITE_HOTY);
           break;
  }
}

/**************************************************************************
 *
 *  This code is used to display error messages on the cusom screen
 *
 **************************************************************************/
struct IntuiText msg_txt =
   {
     0,
     1,
     JAM2,
     5,
     20,
     NULL,
     NULL,
     NULL
   };

struct IntuiText OK_txt =
   {
     0,
     1,
     JAM2,
     5,
     3,
     NULL,
     (UBYTE *) "YES",
     NULL
   };

struct IntuiText NO_txt =
   {
     0,
     1,
     JAM2,
     5,
     3,
     NULL,
     (UBYTE *) "NO",
     NULL
   };

struct IntuiText Cont_txt =
   {
     0,
     1,
     JAM2,
     5,
     3,
     NULL,
     (UBYTE *) "Continue",
     NULL
   };


DispErrMsg(ErrMsg, Flag)
  char *ErrMsg;
  SHORT  Flag;
{
  msg_txt.IText = (UBYTE *) ErrMsg;

  SetNormPointer();

  if (BackWind) {

    if (Flag) {

      return( AutoRequest(BackWind, &msg_txt, &OK_txt, &NO_txt, 0L, 0L,
             (long) (IntuiTextLength(&msg_txt) + 50L), 70L));
    } else {

      (void) AutoRequest(BackWind, &msg_txt, 0L, &Cont_txt, 0L, 0L,
             (long) (IntuiTextLength(&msg_txt) + 50L), 70L);
    }

  } else {
    if (FromWB)
      printf("%s\n", ErrMsg);
  }
  return(0);
}

#define _K (1024L)
#define LOW_MEM_MARK (30*_K)

#ifdef MEM_DEBUG

APTR
SafeAllocMem( size, flags )

#else

APTR
safeAllocMem( size, flags )

#endif

  ULONG size;
  ULONG flags;
{
  register APTR p;

  if ( p = (APTR) AllocMem( (long) size, (long) flags) )
    if ( AvailMem( (long) flags ) < LOW_MEM_MARK ) {
      FreeMem((char *) p, (long) size);
      return( NULL );
    }
  return( p );
}

