 /**************************************************************************
 *
 *                 MandelVroom Display Setup/Cleanup
 *
 *                         Kevin L. Clague
 *
 *                        Copyright (C) 1987
 *
 **************************************************************************/

#include "mand.h"

extern struct Window *MandWind, *ContWind, *PalWind;
extern struct NewWindow NewMand, NewCont, NewPal;
extern struct Menu Menu;

extern struct Windows {
  struct Windows *NextWindow;
  struct Window  *Window;
} *WindowList;

extern struct MenuItem ViewModeSubs[];

extern SHORT  *ContourBase,Ceiling;

extern SHORT CountX, CountY;

struct IntuitionBase *IntuitionBase;
struct GfxBase       *GfxBase;
struct MathBase      *MathBase;

struct Screen   *screen = (struct Screen *) NULL;
struct RastPort *rp;
struct ViewPort *vp;

USHORT YScale, XScale;

USHORT *BabyBrotPointer = (USHORT *) NULL;
USHORT *BabyToPointer   = (USHORT *) NULL;
USHORT *SleepyPointer   = (USHORT *) NULL;

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

UBYTE   PointerType = UNINITIALIZED;

SHORT  SavePalette[32];
SHORT  Inited;

extern USHORT CmdMode;

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              */
   (struct TextAttr *) NULL, /* font to use              */
   (UBYTE *) "                MandelVroom v1.50       by Kevin L. Clague",
   (struct Gadget *) NULL    /* pointer to extra gadgets */
};

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

/*
 * Open the libraries
 */
OpenLibs() {
  IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",0);
  if (IntuitionBase == (struct IntuitionBase *) NULL) {
     printf("Couldn't get Intuition\n");
     return(100);
     }

  GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",0);
  if (GfxBase == (struct GfxBase *) NULL) {
     printf("Couldn't get Graphics\n");
     return(100);
     }

  MathBase = (struct MathBase *) OpenLibrary("mathffp.library",0);
  if (MathBase == (struct MathBase *) NULL) {
     printf("Couldn't get MathFFP\n");
     return(100);
     }

  return(0);
} /* OpenLibs */

/*
 * Close the libraries used
 */
CloseLibs() {
  if (IntuitionBase != (struct IntuitionBase *) NULL) CloseLibrary(IntuitionBase);
  if (GfxBase       != (struct GfxBase *) NULL) CloseLibrary(GfxBase);
  if (MathBase      != (struct MathBase *) NULL) CloseLibrary(MathBase);
} /* CloseLibs */

/*
 * Open the display
 */
OpenDisp()
{
  SHORT i;

  struct Window *OpenMyWind();
  struct Screen *OpenScreen();

  if (NewScreen.ViewModes & HIRES) {
    NewScreen.Width = 640;
    if ( NewScreen.Depth > 4 ) NewScreen.Depth = 4;
    XScale = 1;

  } else {
    NewScreen.Width = 320;
    XScale = 0;
  }

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

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

  if (screen == (struct Screen *) NULL) {
     AndDie("Can't open new screen!\n");
  }
  InitViewModesSubs();
  InitDepthSubs();
  InitGenSubs();
  InitMaxISubs();

  AllocateMice();

  OpenMandWind();

  if ( MandWind == (struct Window *) NULL ) {
    AndDie("Can't open Picture window\n");
  }

  rp = MandWind->RPort;
  vp = &screen->ViewPort;

  if ( Inited )
    LoadRGB4(vp, &SavePalette[0], 32);
  Inited = 1;

  return(0);
} /* opendisp */

/*
 *  Close the screen
 */
CloseDisp() {
  LONG i;

  ClosePalWind();
  CloseContWind();
  CloseMandWind();

  if (Inited)
    for (i = 0; i < 32; i++) SavePalette[i] = GetRGB4(vp->ColorMap, i);

  if ( screen )   CloseScreen(screen);

  FreeMice();

} /* CloseDisp */

AndDie( ErrMsg )
  char *ErrMsg;
{
  extern SHORT *CountBase;

  printf("%s\n", ErrMsg);

  CloseLibs();

  CloseDisp();

  if (CountBase)
    FreeMem( CountBase, CountX * CountY * sizeof( USHORT ) );

  printf("Something unrecoverable happened!!!\n");
  exit(0);
}

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

/*
 *  Open a window and put it in the window list
 */
struct Window *OpenMyWind(NewWind, Screen, Gadgets, Width, Height,
                          MaxWidth, MaxHeight)
  struct NewWindow *NewWind;
  struct Screen *Screen;
  struct Gadget *Gadgets;
  SHORT  Width, Height, MaxWidth, MaxHeight;
{
  struct Window *Window, *OpenWindow();
  struct Windows *Windows;

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

  NewWind->Width = Width << XScale;
  NewWind->Height = Height << YScale;

  NewWind->MaxWidth = MaxWidth << XScale;
  NewWind->MaxHeight = MaxHeight << YScale;

  Window = OpenWindow( (struct NewWindow *) NewWind);

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

  Windows = (struct Windows *) AllocMem(sizeof(struct Windows), MEMF_CLEAR);

  if (Windows == (struct Windows *) NULL) {
    DispErrMsg("Can't malloc Windows. Out of RAM!!",0);
    return( (struct Window *) NULL);
  }

  Windows->Window = Window;
  if (WindowList)
    Windows->NextWindow = WindowList;
  WindowList = Windows;

  SetMenuStrip(Window, &Menu);

  return(Window);
} /* OpenMyWind */

/*
 * Remove the window from the window list,
 *   deallocate all the gadgets associated with this window
 */
CloseMyWind(Window,Gadgets)
  struct Window *Window;
  struct Gadget *Gadgets;
{
  struct Windows *Windows = WindowList, *PrevWinds = WindowList;

  if (Window) {

     /* get rid of the menu */
     ClearMenuStrip(Window);

     /* get rid of the previous pointer */
     ClearPointer(Window);

     if (Window == Windows->Window) {
       WindowList = WindowList->NextWindow;
       FreeMem(Windows,sizeof(struct Windows));
     } else {
       while (Windows && Windows->Window != Window) {
         PrevWinds = Windows;
         Windows = Windows->NextWindow;
       }
       if (Windows) {
         PrevWinds->NextWindow = Windows->NextWindow;
         FreeMem(Windows,sizeof(struct Windows));
       }
     }
     CloseWindow(Window);
     if (Gadgets)
       FreeGadgets(Gadgets);
  }
} /* CloseMyWind */

/*************************************************************************
 *
 * Allocate and ititialize gadget tools
 *
 ************************************************************************/

/*
 * Make a generic boolean gadget
 */
struct Gadget *MakeBool(x,y,xd,yd,c,id)
  SHORT  x,y,xd,yd;
  UBYTE  c;
  USHORT id;
{
  struct Gadget *NewGadget;
  struct Image  *NewImage;

  NewGadget = (struct Gadget *)
    AllocMem( (LONG) sizeof(struct Gadget), (LONG) MEMF_CLEAR );
  if (NewGadget == (struct Gadget *) NULL)
    return((struct Gadget *) NULL);

  NewImage = (struct Image *)
    AllocMem( (LONG) sizeof(struct Image), (LONG) MEMF_CHIP | MEMF_CLEAR );
  if (NewImage == (struct Image *) NULL) {
    FreeMem( NewGadget, (LONG) sizeof(struct Gadget));
    return((struct Gadget *) NULL);
  }
  NewGadget->LeftEdge = x << XScale;
  NewGadget->TopEdge  = y << YScale;
  NewGadget->Width    = xd << XScale;
  NewGadget->Height   = yd << YScale;
  NewGadget->Flags    = GADGHCOMP | GADGIMAGE;
  NewGadget->Activation = GADGIMMEDIATE;
  NewGadget->GadgetRender = (APTR) NewImage;
  NewGadget->GadgetType = BOOLGADGET;
  NewGadget->GadgetID = id;

  NewImage->Width = xd << XScale;
  NewImage->Height = yd << YScale;
  NewImage->PlaneOnOff = c;

  return(NewGadget);
} /* MakeBool */

/*
 * Make a generic potentiometer gadget
 */
struct Gadget *MakePot(x, y, xd, yd, id, cnt)
  SHORT  x,y,xd,yd;
  USHORT id;
  USHORT cnt;
{
  struct Gadget   *NewGadget;
  struct PropInfo *NewInfo;
  struct Image    *NewImage;

  NewGadget = (struct Gadget *)
    AllocMem( (LONG) sizeof(struct Gadget), MEMF_CLEAR );
  if (NewGadget == (struct Gadget *) NULL)
    return((struct Gadget *) NULL);

  NewImage = (struct Image *)
    AllocMem( (LONG) sizeof(struct Image), (LONG) MEMF_CHIP | MEMF_CLEAR );
  if (NewImage == (struct Image *) NULL) {
    FreeMem( NewGadget, (LONG) sizeof(struct Gadget));
    return((struct Gadget *) NULL);
  }
  NewInfo = (struct PropInfo *)
    AllocMem( (LONG) sizeof(struct PropInfo), MEMF_CLEAR );
  if (NewInfo == (struct PropInfo *) NULL) {
    FreeMem( NewGadget, (LONG) sizeof(struct Gadget));
    FreeMem( NewImage,  (LONG) sizeof(struct Image));
    return((struct Gadget *) NULL);
  }
  NewGadget->LeftEdge = x << XScale;
  NewGadget->TopEdge  = y << YScale;
  NewGadget->Width    = xd << XScale;
  NewGadget->Height   = yd << YScale;
  NewGadget->Flags    = GADGHIMAGE | GADGIMAGE;
  NewGadget->Activation   = RELVERIFY;
  NewGadget->GadgetType   = PROPGADGET;
  NewGadget->GadgetRender = (APTR) NewImage;
  NewGadget->SelectRender = (APTR) NewImage;
  NewGadget->SpecialInfo  = (APTR) NewInfo;
  NewGadget->GadgetID     = id;

  NewImage->PlaneOnOff = 1;
  NewImage->Width  = 4 << XScale;
  NewImage->Height = 3 << YScale;

  NewInfo->Flags = PROPBORDERLESS | FREEVERT;

  return(NewGadget);
} /* MakePot */

/*
 * Make an IntuiText structure
 */
struct IntuiText *MakeIntui(str, x, y, frontpen, backpen, drawmode )
  UBYTE *str;
  SHORT  x, y;
  UBYTE  frontpen, backpen, drawmode;
{
  struct IntuiText *NewIntui;

  NewIntui = (struct IntuiText *)
    AllocMem( (LONG) sizeof(struct IntuiText), (LONG) MEMF_CLEAR );

  if (NewIntui == (struct IntuiText *) NULL)
    return((struct IntuiText *) NULL);

  NewIntui->FrontPen = frontpen;
  NewIntui->BackPen  = backpen;
  NewIntui->DrawMode = drawmode;
  NewIntui->LeftEdge = x << XScale;
  NewIntui->TopEdge  = y << YScale;

  NewIntui->IText    = str;

  return(NewIntui);
} /* MakeIntui */

/*
 * Free a string of gadgets
 */
FreeGadgets(FirstGadget)
  struct Gadget *FirstGadget;
{
  struct Gadget *NextGadget;

  while (FirstGadget) {
    if (FirstGadget->GadgetRender)
      FreeMem(FirstGadget->GadgetRender, (LONG) sizeof(struct Image));

    if (FirstGadget->SpecialInfo)
      FreeMem(FirstGadget->SpecialInfo, (LONG) sizeof(struct PropInfo));

    if (FirstGadget->GadgetText)
      FreeMem(FirstGadget->GadgetText, (LONG) sizeof(struct IntuiText));

    NextGadget = FirstGadget->NextGadget;
    FreeMem(FirstGadget, (LONG) sizeof(struct Gadget));
    FirstGadget = NextGadget;
  }
} /* FreeGadgets */



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

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

USHORT BabyBrotSprite[]=  {
     /*plane1  plane0 */
      0x0000,  0x0000,
      0x8000,  0x0000,
      0x0000,  0x5000,
      0x2000,  0x2202,
      0x1600,  0x5f82,
      0x0802,  0x1913,
      0x1152,  0x11fe,
      0x1008,  0x300a,
      0x0404,  0x1c06,
      0x0006,  0x1407,
      0x0404,  0x0404,
      0x000c,  0x042c,
      0x0400,  0x0c1c,
      0x0220,  0x0630,
      0x01e0,  0x05f0,
      0x0c80,  0x3f80,
      0x0000,  0x0880,
      0x0000,  0x0000,
     };

/***************************************************************/
/*  This is a baby brot pointer with 'TO' in it.               */
/***************************************************************/
USHORT BabyToSprite[]=  {
     /*plane1  plane0 */
      0x0000,  0x0000,
      0x8000,  0x0000,
      0x0100,  0x5100,
      0x2000,  0x2202,
      0x1600,  0x5f82,
      0xfe7a,  0x0103,
      0x93de,  0x0132,
      0x108c,  0x200a,
      0x5484,  0x4c02,
      0x1086,  0x0403,
      0x1484,  0x0400,
      0x10cc,  0x0420,
      0x3c78,  0x0404,
      0x0220,  0x0630,
      0x01e0,  0x05f0,
      0x0c80,  0x3f80,
      0x0000,  0x0880,
      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,
     };

/* defines for the cute pointer sprite */
#define MYSPRITE_WIDTH 16
#define MYSPRITE_HEIGHT 16
#define SLEEPY_WIDTH 16
#define SLEEPY_HEIGHT 25
#define MYSPRITE_HOTX -1
#define MYSPRITE_HOTY 0

#define BABYSIZE   ( (MYSPRITE_HEIGHT + 2) * 8)
#define TOSIZE     ( (MYSPRITE_HEIGHT + 2) * 8)
#define SLEEPYSIZE ( (SLEEPY_HEIGHT + 2) * 8)

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

  ChipSprite = AllocMem( (LONG) (Size * sizeof(SHORT)), MEMF_CHIP );

  if ( ChipSprite == (struct USHORT * ) 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 );
  SleepyPointer   = MakeChipSprite( SleepySprite,   SLEEPYSIZE );
}

/*
 * Free all the mouse pointer sprites used by this program
 */
FreeMice()
{

  if ( BabyBrotPointer )
    FreeMem( BabyBrotPointer, BABYSIZE * sizeof(SHORT) );
  BabyBrotPointer = NULL;

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

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

/*
 * Set all window pointers NewPointer
 */
SetPointers( NewPointer, Height, Width)
  USHORT *NewPointer;
  int     Height, Width;
{
  if (NewPointer == (struct USHORT *) NULL )
    return();

  if ( ContWind )
    SetPointer( ContWind, NewPointer, Height,   Width,
                                     MYSPRITE_HOTX, MYSPRITE_HOTY);
  if ( MandWind )
    SetPointer( MandWind, NewPointer, Height,  Width,
                                     MYSPRITE_HOTX, MYSPRITE_HOTY);
  if ( PalWind )
    SetPointer( PalWind,  NewPointer, Height,   Width,
                                     MYSPRITE_HOTX, MYSPRITE_HOTY);
}

/*
 * Clear the window pointers
 */
ClearPointers()
{
    if ( MandWind ) ClearPointer( MandWind );
    if ( ContWind ) ClearPointer( ContWind );
    if ( PalWind )  ClearPointer( PalWind );
}

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

  SetNormPointer();
}

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

    SetPointers( BabyBrotPointer, MYSPRITE_HEIGHT, MYSPRITE_WIDTH );

    PointerType = NORMPOINTER;
  }
  CmdMode = NULL;
}

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

    SetPointers( BabyToPointer, MYSPRITE_HEIGHT, MYSPRITE_WIDTH );

    PointerType = TOPOINTER;
  }
}

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

    SetPointers( SleepyPointer, SLEEPY_HEIGHT, SLEEPY_WIDTH );

    PointerType = SLEEPYPOINTER;
  }
}

SetSystemColors(flag)
  int flag;
{

  UWORD red, green, blue;

  static SHORT MenuColors[4] = { 0x0000, 0x0fff, 0x000a, 0x0b44 };
  static SHORT PointerColors[4] = { 0x0000, 0x00c0, 0x0dd0, 0x0f00 };
  static SHORT ColorSave[32];
  static SHORT SaveFull = 0;

  int i;

  if (flag) {
    if (SaveFull == 0) {
      for (i = 0; i < 32; i++) {
        ColorSave[i] = GetRGB4(vp->ColorMap, i);
      }
      /* Set the colors for the Menu */
      for (i = 0; i < 4; i++) {
        red = (MenuColors[i] & 0xf00) >> 8;
        green = (MenuColors[i] & 0x0f0) >> 4;
        blue  = (MenuColors[i] & 0x00f) ;
        SetRGB4(vp, i , red , green, blue);
      }

      /* Set the colors for the Mouse pointer */
      for (i = 0; i < 4; i++) {
        red = (PointerColors[i] & 0xf00) >> 8;
        green = (PointerColors[i] & 0x0f0) >> 4;
        blue  = (PointerColors[i] & 0x00f) ;
        SetRGB4(vp, i + 16, red , green, blue);
      }
    }
    SaveFull++;
  } else {
    if (SaveFull == 1)
      LoadRGB4(vp, &ColorSave[0], 32);

    if (--SaveFull < 0) SaveFull = 0;
  }
}

/**************************************************************************
 *
 *  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 *) "OK",
     NULL
   };

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


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

  SetNormPointer();

  if (MandWind) {
    SetSystemColors(1);
    if (Flag) {

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

      AutoRequest(MandWind, &msg_txt, 0L, &OK_txt, 0L, 0L,
         (long) (IntuiTextLength(&msg_txt) + 50L), 70L);
    }
    SetSystemColors(0);
  } else {
    printf("%s\n", ErrMsg);
  }
}



