/*
 * 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 functions that open, maintain and
 * close the orbit window.
 */

#define PARSEGOOD 0
#define PARSEBAD  1

#include "mandp.h"
#include "parms.h"

SHORT MaxOrbit = 32;
UBYTE OrbitMode = 1;

UBYTE OrbitOpen;

struct NewWindow NewOrbit = {
   100, 12,                  /* start position           */
   130,80,                   /* width, height            */

   (UBYTE) 0, (UBYTE) NORMALPEN,
   NULL,                     /* IDCMP flags */
   /* OrbitWind flags */
   WINDOWCLOSE | WINDOWDEPTH | WINDOWSIZING | WINDOWDRAG | ACTIVATE |
   NOCAREREFRESH | SMART_REFRESH,
   (struct Gadget *) NULL,   /* first gadget             */
   (struct Image *) NULL,    /* user checkmark           */
   (UBYTE *) "Orbit",        /* Title                    */
   (struct Screen *) NULL,   /* pointer to screen        */
   (struct BitMap *) NULL,   /* pointer to superbitmap   */
   20,20,-1,-1,              /* sizing                   */
   CUSTOMSCREEN              /* type of screen           */
};

struct Window *OrbitWind;

ConfOrbMode( subnum )
  int subnum;
{
  OrbitMode = subnum;
}

OrbitCmd( msg )
  register struct IntuiMessage *msg;
{
  static struct Picture *OrbitPict;
  register struct Window *Window;

  switch( msg->Class ) {
    case MENUPICK:
    case GADGETDOWN:
         OpenOrbitWind();
         break;

    case MOUSEBUTTONS:

         Window = (struct Window *) msg->IDCMPWindow;

         switch (msg->Code) {
           case SELECTDOWN:

                OrbitPict = (struct Picture *) Window->UserData;

                if (OrbitPict != NULL &&
                  !(OrbitPict->Flags & SCROLL_HAPPENED)) {

                  ModifyIDCMP( Window,
                               (long) Window->IDCMPFlags | MOUSEMOVE );
                  DrawOrbit(OrbitPict);
                }
                break;

           case SELECTUP:

                if (OrbitPict != NULL) {

                  ModifyIDCMP( Window,
                               (long) Window->IDCMPFlags & ~MOUSEMOVE );
                  OrbitPict = NULL;
                }
                break;
         }
         break;

    case MOUSEMOVE:

         if (OrbitPict != NULL) {
           DrawOrbit( OrbitPict );
         }
         break;
  }
}

DrawOrbit( Pict )
  struct Picture *Pict;
{
  switch( OrbitMode ) {
    case 1:   /* ffp       */
         {    /* 32 bit IEEE float variables */

           float CReal_float, CImag_float, ZReal_float, ZImag_float;

           if (OpenFFPLibs() != 0)
             return;

           /* convert 64 bit IEEE variables into 32 bit IEEE variables */

           CReal_float =
             Pict->RealLow + (MouseX-Pict->LeftMarg) * Pict->RealGap;
           CImag_float =
             Pict->ImagLow + (MouseY-Pict->TopMarg) * Pict->ImagGap;

           ZReal_float   = Pict->Real;
           ZImag_float   = Pict->Imag;

           /*
            * calculate pointers and convert them to pointers to ULONG
            * so that when we indirect off of these and pass the results
            * as parameters they are not promoted to doubles.
            */

           DrawOrbitFFP( Pict,
                         *((ULONG *) &CReal_float),
                         *((ULONG *) &CImag_float),
                         *((ULONG *) &ZReal_float),
                         *((ULONG *) &ZImag_float));
         }
         break;

    case 0:   /* int 16/32 */
         DrawOrbitInt( Pict );
         break;

    case 2:   /* ieee      */
         DrawOrbitIEEE( Pict );
         break;
  }
}

struct Gadget *
MakeOrbitGads()
{
  register struct Gadget *Firstgadget;
  register struct IntuiText  *Intui;

  struct IntuiText *ShadowIntui();
  struct Border *Border, *MakeShadow();

  Firstgadget = MakeBool(-15,TOPMARG, 12,12, 0,ORBTTYPE<<WINDTYPEBITS,NULL);

  if (Firstgadget == NULL) {
    return( Firstgadget );
  }

  Firstgadget->Flags      |= GRELRIGHT;
  Firstgadget->Activation |= RIGHTBORDER;

  Intui = ShadowIntui( "O", 3, 3);

  if (Intui == NULL) {
    FreeGadgets( Firstgadget );
    return( NULL );
  }

  Firstgadget->GadgetText = Intui;

#define NUMPATCHCORNERS 5

  Border = MakeShadow( NORMALPEN, NUMPATCHCORNERS );

  if ( Border ) {
    InitPatch( Border );

    Border->NextBorder = (struct Border *) Firstgadget->GadgetRender;
    Firstgadget->GadgetRender = (APTR) Border;
  }

  return( Firstgadget );
}

static struct Gadget *OrbitGadgets;
struct Gadget *OrbitResize;

/*
 * Open the Orbit window
 */
OpenOrbitWind()
{
  extern struct Window *OpenMyWind();

  register struct Window    *Window;
  register struct NewWindow *NewWind;

  struct Gadget *gadgets;

  if ( OrbitWind == NULL ) {

    OrbitGadgets = gadgets = MakeOrbitGads();

    if (gadgets == NULL) {
      return( -1 );
    }

    Window = OpenMyWind(&NewOrbit, screen, gadgets,
                         NewOrbit.Width, NewOrbit.Height );

    if (Window == NULL) {

      DispErrMsg("Can't open picture window",0);
      FreeGadgets( OrbitGadgets );
      return( -1 );

    } else {

      OrbitWind = Window;
      MoveResize( Window, &OrbitResize );
      BorderWindow( Window );
    }
  }

  OrbitOpen = 1;
  State = ORBITSTATE;
  SetToPointer();
  return( 0 );
} /* OpenOrbit */

/*
 * Close the Orbit Window
 */
CloseOrbitWind()
{
  register struct Window    *Window;
  register struct NewWindow *NewWindow;

  Window = OrbitWind;

  if ( Window != NULL) {

    NewOrbit.LeftEdge = Window->LeftEdge;
    NewOrbit.TopEdge  = Window->TopEdge;
    NewOrbit.Width    = Window->Width;
    NewOrbit.Height   = Window->Height;

    CloseMyWind(Window, OrbitGadgets );

    OrbitWind    = NULL;
    OrbitGadgets = NULL;
  }
}
