/***************************************************************************
 *
 *                         MandelZoom Main
 *
 *                         Kevin L. Clague
 *
 *                        Copyright (C) 1986
 *
 **************************************************************************/

#include "mand.h"
#include <libraries/dosextens.h>

extern struct Menu Menu[], GenMenu[];

extern USHORT CmdMode;

extern SHORT CountX,CountY;

extern float StartX, StartY, EndX, EndY;
extern LONG  NavTop,NavBot,NavRight,NavLeft;
extern SHORT DragSize, BoxSizeX, BoxSizeY;

extern struct NewScreen NewScreen;
extern struct Screen *screen;

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

extern SHORT MaxCount;

extern SHORT *ContourBase;
extern UBYTE *ColorBase;

struct IntuiMessage *message;

SHORT *CountBase = (SHORT *) NULL;

UBYTE  QuitScreen = FALSE;

UBYTE  MandType;

ULONG  BorderType = 0;

SHORT MouseX,MouseY;

SHORT Zoom = 0;

ULONG SaveIDCMP;

SHORT HotSpotX, HotSpotY;

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

/*
 * Do it all
 */
main () {
  if (OpenLibs() == 0 && OpenDisp() == 0) {
    InitPreset(0);
    GenerateIt();
    DoBrot();
  }

  CloseDisp();

  if (CountBase) {
    FreeMem(CountBase,CountX*CountY*sizeof(SHORT));
  }

  CloseLibs();
}

/*
 * Decide what to do to satisfy this message
 */
DoBrot()
{
  ULONG   class;
  USHORT  code = 0;
  SHORT   ContNum;
  struct  MenuItem *Item;
  struct  Gadget *gadget;
  struct  Windows *Windows;
  struct  Window  *Window;
  ULONG   WaitMask;

#define INTUINULL ((struct IntuiMessage *) NULL)

  extern struct MenuItem *ItemAddress();
  extern struct IntuiMessage *GetMsg();

  if (WindowList == (struct Windows *) NULL) {
    printf("Fatal programming error\nNo windows\n");
    return(0);
  }

  while (QuitScreen == FALSE) {

    /* grab the first window in the list */
    Windows = WindowList;
    Window  = Windows->Window;

    /* while we still have windows and there are no messages,
       gather up the wait bit mask */

    WaitMask = 0;

    while (Windows && (message = GetMsg( Window->UserPort)) == INTUINULL ) {
      /* Add to the wait mask */
      WaitMask |= 1L << Window->UserPort->mp_SigBit;

      Windows = Windows->NextWindow;
      Window  = Windows->Window;
    }

    /* Wait here for a message */
    if (message == (struct IntuiMessage *) NULL) {
      Wait(WaitMask);
      continue;
    }

    /* got a message */
    class  = message->Class;
    code   = message->Code;
    gadget = (struct Gadget *) message->IAddress;
    MouseX = message->MouseX;
    MouseY = message->MouseY;
    ReplyMsg(message);

    if (class == MOUSEMOVE) {
      DoMouseMove(MouseX, MouseY);   /* Try this first */
    } else

    if (class == MENUPICK) {

      SetNormPointer();

      while (code != MENUNULL) {
        switch (MENUNUM(code)) {
          case PROJECTMENU:
               ScreenProject(code);
               break;
          case EDITMENU:
               EditScreen(code);
               break;
          case PRESETMENU:
               SetPreset(ITEMNUM(code));
               break;
        }
        Item = ItemAddress( (struct Menu *) &Menu[0], code);
        code = Item->NextSelect;
      }
    } else

    if (class == GADGETDOWN) {
      DoGadgetDown(gadget);
    } else

    if (class == GADGETUP) {
      DoGadgetUp(gadget);
    } else

    if (class == MOUSEBUTTONS) {
      DoMouseButtons(code);
    } else

    if (class == CLOSEWINDOW) {
      SetNormPointer();

      if (Windows->Window == ContWind) {
        CloseContWind();

      } else
      if (Windows->Window == PalWind) {
        ClosePalWind();
      }
    }
  }
} /* DoBrot */

/*
 * Perform functions for Gadget down messages
 */
DoGadgetDown(gadget)
  struct Gadget *gadget;

{
  switch (gadget->GadgetID >> WINDTYPEBITS & WINDMASK) {
  case PALTYPE:
       DoPalette(gadget);
       break;

  case CONTYPE:
       DoContourDown(gadget);
       break;
  }
} /* DoGadgetDown */

/*
 * Perform functions for Gadget up messages
 */
DoGadgetUp(gadget)
  struct Gadget *gadget;
{
  switch (gadget->GadgetID >> WINDTYPEBITS & WINDMASK) {
  case PALTYPE:
       SetNormPointer();
       break;

  case CONTYPE:
       DoContourUp(gadget);
       break;
  }
} /* DoGadgetUp */

/*
 * Perform functions for Mouse buttons
 */
DoMouseButtons(code)
  USHORT code;
{
  extern SHORT XScale, YScale;

#define MINXBOX (8 << XScale)
#define MINYBOX (8 << YScale)

  switch (code) {
  case SELECTDOWN:

       switch(CmdMode) {

       case IMPLIEDSET:
            DoWindowPick(MouseX, MouseY);
            CmdMode = NULL;
            break;

       case STARTBOX:
            StartZoomBox();
            break;

       case NULL:            /* must be trying to move or resize with mouse */
            DoZoomBoxGadgets();
            break;
       }
       break;

  case SELECTUP:

       ModifyIDCMP(MandWind, MandWind->IDCMPFlags & ~MOUSEMOVE);

       switch(CmdMode) {

       case ZOOMDRAG:
            CmdMode = NULL;

            /* redraw the extras */
            DrawExtras(NavLeft, NavTop, NavRight, NavBot );
            break;

       case STRETCHBOX:
            DrawBox(NavLeft, NavTop, NavRight, NavBot );

            if ( NavRight - NavLeft < MINXBOX )
              NavRight = NavLeft + MINXBOX;

            if ( NavBot - NavTop < MINYBOX )
              NavBot = NavTop + MINYBOX;

            /* draw the extras */
            DrawExtras(NavLeft, NavTop, NavRight, NavBot );

            DrawBox(NavLeft, NavTop, NavRight, NavBot );
            CmdMode = NULL;
            break;

       }

       SetNormPointer();

       break;
  }
} /* DoMouseButtons */

/*
 * Start Zoom box
 */
StartZoomBox()
{
  if (Zoom == 0) {
    if (MouseX > LEFTMARG && MouseX < MandWind->Width - RIGHTMARG &&
        MouseY > TOPMARG  && MouseY < MandWind->Height - BOTMARG) {

      Zoom = 1;

      /* Draw first box */
      NavTop   = MouseY;
      NavLeft  = MouseX;
      NavBot   = NavTop;
      NavRight = NavLeft;
      HotSpotX = HotSpotY = 0;
      CmdMode = STRETCHBOX;

      DrawBox(NavLeft, NavTop, NavRight, NavBot );
      ModifyIDCMP(MandWind, MandWind->IDCMPFlags | MOUSEMOVE);
    }
  }
}

/*
 * Simulate Zoom box gadgets
 */
DoZoomBoxGadgets()
{
  extern SHORT XScale, YScale;

  SetNormPointer();

  if ( Zoom == 1 ) {

    /* is it in the window box? */
    if (MouseX >= NavLeft && MouseX <= NavRight &&
        MouseY >= NavTop  && MouseY <= NavBot) {

      /* is it in the top part? */
      if (MouseY <= NavTop + (3 << YScale)) {

        /* is it the drag bar? */
        if (MouseX > NavLeft + (3 << XScale)) {

          HotSpotX = MouseX - NavLeft;
          HotSpotY = MouseY - NavTop;

          /* undraw the extras */
          DrawExtras(NavLeft, NavTop, NavRight, NavBot );
          CmdMode = ZOOMDRAG;

        } else {                     /* We got the close gadget */
          CmdMode = NULL;
          DrawBox(NavLeft, NavTop, NavRight, NavBot );

          /* undraw the extras */
          DrawExtras(NavLeft, NavTop, NavRight, NavBot );
          Zoom = 0;
        }
      } else {

        /* is it the Resize Gadget? */
        if (MouseY >= NavBot - (3 << YScale) &&
            MouseX >= NavRight - (3 << XScale)) {

          HotSpotX = NavRight - MouseX;
          HotSpotY = NavBot   - MouseY;

          CmdMode = STRETCHBOX;
          /* undraw the extras */
          DrawExtras(NavLeft, NavTop, NavRight, NavBot );
        }
      }
    }
  }
  if (CmdMode) {
    ModifyIDCMP(MandWind, MandWind->IDCMPFlags | MOUSEMOVE);
  }
}

/*
 * Perform functions for Mouse movements
 */
DoMouseMove( MouseX, MouseY)
  SHORT MouseX, MouseY;
{
  SHORT Width, Height;

  switch(CmdMode) {

  case COLORSLIDE:
       ModifyColors();
       break;

  case STRETCHBOX:

       DrawBox(NavLeft, NavTop, NavRight, NavBot );

       if ( MouseX < NavLeft )
         MouseX = NavLeft;

       if ( MouseY < NavTop )
         MouseY = NavTop;

       if ( MouseX + HotSpotX > CountX + LEFTMARG )
         MouseX = CountX + LEFTMARG - HotSpotX;

       if ( MouseY + HotSpotY > CountY + TOPMARG )
         MouseY = CountY + TOPMARG - HotSpotY;

       DrawBox(NavLeft, NavTop, MouseX, MouseY);

       NavBot   = MouseY;
       NavRight = MouseX;
       break;

  case ZOOMDRAG:
       DrawBox(NavLeft, NavTop, NavRight, NavBot );

       Width  = NavRight - NavLeft - HotSpotX;
       Height = NavBot - NavTop - HotSpotY;

       if ( MouseY < 1 )
         MouseY = 1;

       if ( MouseX - HotSpotX < LEFTMARG )
         MouseX = LEFTMARG + HotSpotX;

       if ( MouseY - HotSpotY < TOPMARG )
         MouseY = TOPMARG + HotSpotY;

       if ( MouseX + Width > CountX + LEFTMARG )
         MouseX = CountX + LEFTMARG - Width;

       if ( MouseY + Height > CountY + TOPMARG )
         MouseY = CountY + TOPMARG - Height;

       NavLeft  = MouseX - HotSpotX;
       NavTop   = MouseY - HotSpotY;

       NavRight = MouseX + Width;
       NavBot   = MouseY + Height;

       DrawBox(NavLeft, NavTop, NavRight, NavBot );
       break;
  }
} /* DoMouseMove */
