/*******************************************************************************
 *   BlitDemons by Walter Strickler
 *   This program and all its source code are in the public domain and are
 * freely distributable and usable for any purpose, private or commercial.
 ******************************************************************************/

#include "BDemon.h"


/*******************************************************************************
 *     Intuition stuff is global:
 ******************************************************************************/
struct Window *BDWindow;
struct Screen *BDScreen;

/*******************************************************************************
 *    Defines to make life with Power Windows easier...
 *****************************************************************************/
#define BDNewWindow BDWindowNewWindowStructure3
#define ABD1NewWindow ABDWin1NewWindowStructure4
#define ABD2NewWindow ABDWin2NewWindowStructure1
#define ABD3NewWindow ABDWin3NewWindowStructure2
#define ABD1IText     ABDWin1IText28
#define ABD2IText     ABDWin2IText1
#define ABD3IText     ABDWin3IText16

/*******************************************************************************
 *    This stuff came from PowerWindows, but we gotta know what it is here.
 *****************************************************************************/
extern struct NewScreen NewScreenStructure;
extern struct NewWindow BDNewWindow;
extern struct Menu BDWindowMenu1;
extern struct NewWindow ABD1NewWindow;
extern struct NewWindow ABD2NewWindow;
extern struct NewWindow ABD3NewWindow;
extern struct IntuiText ABD1IText;
extern struct IntuiText ABD2IText;
extern struct IntuiText ABD3IText;


/*******************************************************************************
 *    Here is a useful #define for turning on/off Menu items.
 *****************************************************************************/
#define GET_MENU_NUMBER(Menu, Item) (SHIFTMENU((Menu)) + SHIFTITEM((Item)))


/*******************************************************************************
   InitIntui() opens various system things.
*******************************************************************************/
int InitIntui()
    { 
    int RetVal;

    IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",0);
    if (IntuitionBase == 0) 
        {
        RetVal = NO_INTUI;
        }
    else
        {
        GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",0);
        if (GfxBase == 0) 
            {
            RetVal = NO_GFX;
            }
        else
            {
            BDScreen = OpenScreen(&NewScreenStructure);
            if (BDScreen == NULL)
                {
                RetVal = NO_SCREEN;
                }
             else
                {
                /* Set the Palette */
                SetPalette();
                /* Power Windows doesn't init this schtick 'cause it can't */
                BDNewWindow.Screen = BDScreen;
                ABD1NewWindow.Screen = BDScreen;
                ABD2NewWindow.Screen = BDScreen;
                ABD3NewWindow.Screen = BDScreen;
                BDWindow = OpenWindow(&BDNewWindow);
                if (BDWindow == NULL)
                    {
                    RetVal = NO_WIN;
                    }
                else
                    {
                    SetMenuStrip(BDWindow, &BDWindowMenu1);
                    RetVal = INTUI_OK;
                    }   /* END window open */
                }   /* END screen open */
            }   /* END Gfx open */
        }  /* END intuition open */
    return RetVal;
    }  /* END IntuiInit() */

void SetPalette()
    {
/*
    struct ViewPort *ThisVP;
    USHORT           RVal,
                     GVal,
                     BVal;
    int              i;

    static int Red[32] =   {1,1, 0, 0, 0,0,0, 3, 9,11,13,15,15,14,15,0};
    static int Green[32] = {0,0, 0, 0, 7,9,9,10,11,12,10, 6, 5, 1, 0,0};
    static int Blue[32] =  {4,9,12,14,11,5,0, 0, 0, 0, 0, 0, 0, 0, 0,0};
*/

/*   Neither of these algorithms produced satisfying results.  There was
 * Video beam hash with both that didn't exist with the default colors.
 */

    /* Set Palette as in MFPU */
/*    ThisVP = &(BDScreen -> ViewPort);
    for (i = 2; i <= 15; i++)
        {
        SetRGB4(ThisVP, i, Red[i], Green[i], Blue[i]);        
        }
*/

    /* Set Palette according to algorithm by Loren Blaney: */
/*  
    RVal = 14;
    GVal = 2;
    BVal = 0; 
    for (i = 2; i <= 8; i++)
        {
        SetRGB4(ThisVP, i, RVal, GVal, BVal);
        RVal = RVal - 2;
        GVal = GVal + 2;
        }
    RVal = 0;
    GVal = 14;
    BVal = 2;
    for (i = 9; i <= 15; i++)
        {
        SetRGB4(ThisVP, i, RVal, GVal, BVal);
        GVal = GVal - 2;
        BVal = BVal + 2;
        }
*/
    }  /* End SetPalette() */
    
/*******************************************************************************
 *  CloseIntui closes everything opened by IntiIntui().
 ******************************************************************************/
void CloseIntui()
    {
    if (IntuitionBase != NULL)
        {
        CloseLibrary((struct Library *) IntuitionBase);
        }
    if (GfxBase != NULL)
        {
        CloseLibrary((struct Library *) GfxBase);
        }
    ClearMenuStrip(BDWindow);
    if (BDWindow != NULL)
        {
        CloseWindow(BDWindow);
        }
    if (BDScreen != NULL)
        {
        CloseScreen (BDScreen);
        }
    }


/*******************************************************************************
 *  BDClearScreen() clears the blitfield.
*******************************************************************************/
/*
BDClearScreen()
    {
    SetRast(BDWindow -> RPort, 0);
    }
*/

/*******************************************************************************
 *  This function checks the message port BDWindow -> UserPort, waiting if
 * the parameter Control has a value of WAIT, polling otherwise.  Returns
 * constants relative to the type of message it found.
*******************************************************************************/
int CheckMsg(Control)
    int Control;
    {
    struct IntuiMessage *ThisMessage,
                         MsgCopy;
    ULONG                ThisClass;
    int                  RetVal,
                         MenuVal,
                         RecurseReturn;

    if (Control == WAIT)
        {
        WaitPort(BDWindow -> UserPort);
        }
    ThisMessage = (struct IntuiMessage *) GetMsg(BDWindow->UserPort);
    if (ThisMessage != NULL)
        {
        MsgCopy = *ThisMessage;
        ReplyMsg((struct Message *) ThisMessage);   /* Away with thee! */
        ThisClass = MsgCopy.Class;
        switch (ThisClass)
            {
            case MENUVERIFY:
                /* Recursion time! */
                RecurseReturn = CheckMsg(WAIT);  /* Get the menu message */
                RetVal = RecurseReturn;  /* Return the menu message value */
                break;
            case MENUPICK:
                MenuVal = DoMenus(&MsgCopy);
                if (MenuVal != NO_MENU)
                    {
                    RetVal = MenuVal;
                    }
                else 
                    {
                    RetVal = NO_MSG;
                    }
                break;
            case CLOSEWINDOW:
                RetVal = CLOSE_WIN;
                break;
            default:   
                assert (FALSE);  /* Shouldn't be here */        
                break;
            }      /* End switch(Class) */
        }     /* End Have a message */
    else   /* Tell caller no message */
        {
        RetVal = NO_MSG;
        }     /* End have no message */
    return RetVal;
    }    /* End CheckMsg() */



/*******************************************************************************
 *   DoMenus returns a constant depending on what kind of menu item is specified
 * by the Message pointed at by Msg.
*******************************************************************************/
#define PROJECT_MENU 0
#define ABOUT_ITEM 0
#define NEW_ITEM   1
#define START_ITEM 2
#define STOP_ITEM  3
#define QUIT_ITEM  4


int DoMenus(Msg)
    struct IntuiMessage *Msg;

    {
    USHORT  MenuNumber;
    int  Item,
         RetVal;

    MenuNumber = Msg -> Code;
    if (MenuNumber != MENUNULL)  /* Note: assuming only one menu */
        {
        Item = ITEMNUM(MenuNumber);
        switch (Item)
            {
            /* This is so obvious it must be good code... */
            case ABOUT_ITEM:
                RetVal = ABOUT;
                break;
            case STOP_ITEM:
                RetVal = STOP;
                break;
            case START_ITEM:
                RetVal = START;
                break;
            case NEW_ITEM:
                RetVal = NEW;
                break;
            case QUIT_ITEM:
                RetVal = QUIT;
                break;
            default:
                RetVal = NO_MENU;
                break;
            }   /* End switch (Item) */
        }  /* End if not MENUNULL */
    else
        {
        RetVal = NO_MENU;
        }  /* End if MENUNULL */
    return RetVal;
    }      


/*******************************************************************************
 *   DisplayAbout() displays all three "About" windows.
 ******************************************************************************/
int DisplayAbout()
    {
    int RetVal;
    struct Window *Window1,
                  *Window2,
                  *Window3;

    ClearBDMenu();
    Window1 = Window2 = Window3 = NULL;
 
    Window1 = DisplayOne(&ABD1NewWindow, &ABD1IText);
    if (Window1 != NULL)
        {
        Window2 = DisplayOne(&ABD2NewWindow, &ABD2IText);
        CloseWindow(Window1);   /* Window2 is now covering blitfield */
        if (Window2 != NULL)
            {
            Window3 = DisplayOne(&ABD3NewWindow, &ABD3IText);
            CloseWindow(Window2);  /* Window3 is now covering blitfield */
            if (Window3 != NULL)
                {                
                /* Window3 opened and close gadget selected, it */
                CloseWindow(Window3);
                RetVal = DA_OK;
                }  /* End Window3 OK */
            else
                {
                RetVal = DA_CHOKE;
                }  /* End Window3 choked */
            }  /* End Window2 OK */
        else
            {
            RetVal = DA_CHOKE;
            }  /* End Window2 choked */
        }  /* End Window1 OK */
    else
        {
        RetVal = DA_CHOKE;
        }   /* End Window1 choked */
    SetBDMenu();
    return RetVal;
    }


/*******************************************************************************
 *   DisplayOne() displays one "About" window.
 ******************************************************************************/
struct Window *DisplayOne(AboutNewWindow, IText)
    struct NewWindow *AboutNewWindow;
    struct IntuiText *IText;

    {
    struct Window       *AboutWindow;
    struct IntuiMessage *ThisMessage; 
    int                  AllDone;

    AboutWindow = OpenWindow (AboutNewWindow);
    if (AboutWindow != 0)
        {
        PrintIText(AboutWindow -> RPort, IText, 0,0);
        AllDone = FALSE;
        while (!AllDone)
            {
            WaitPort(AboutWindow -> UserPort);
            ThisMessage = 
             (struct IntuiMessage *) GetMsg(AboutWindow -> UserPort);
            if (ThisMessage != NULL)
                {
                if (ThisMessage -> Class == CLOSEWINDOW)
                    {
                    AllDone = TRUE;
                    }
                ReplyMsg((struct Message *) ThisMessage);
                }    /* End if Message != NULL */
            }    /* End while !AllDone */
        }
    return AboutWindow;
    }
    

/*******************************************************************************
 *   These functions support information hiding by providing functions to 
 * operate on relatively hidden objects (in this case, menu items).
 ******************************************************************************/
void OnStart()
    {
    OnMenu(BDWindow, GET_MENU_NUMBER(PROJECT_MENU, START_ITEM));
    }   /* End OnStart */

void OffStart()
    {
    OffMenu(BDWindow, GET_MENU_NUMBER(PROJECT_MENU, START_ITEM));
    }   /* End OffStart */

void OnStop()
    {
    OnMenu(BDWindow, GET_MENU_NUMBER(PROJECT_MENU, STOP_ITEM));
    }   /* End OnStop */

void OffStop()
    {
    OffMenu(BDWindow, GET_MENU_NUMBER(PROJECT_MENU, STOP_ITEM));
    }   /* End OffStop */


void SetBDMenu()
    {
    ULONG Flags;

    Flags = (BDWindow -> IDCMPFlags) | MENUVERIFY; /* Set MENUVERIFY */
    ModifyIDCMP(BDWindow, Flags); 
    SetMenuStrip(BDWindow, &BDWindowMenu1);
    }

void ClearBDMenu()
    {
    ULONG Flags;

    Flags = (BDWindow -> IDCMPFlags) & ~MENUVERIFY; /* Clear that nasty */
                                                    /* MENUVERIFY bit */
    ModifyIDCMP(BDWindow, Flags);    
    ClearMenuStrip(BDWindow);
    }
	

