/* These are for SAS/C */
#define __USE_SYSBASE
long    __oslibversion = 37L;

/* The includes */
#include <exec/types.h>
#include <exec/exec.h>
#include <exec/interrupts.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <devices/input.h>
#include <workbench/workbench.h>
#include <dos/dos.h>
#include <dos/dostags.h>

/* With SAS/C, if we include these, the libs are Auto Open/Close */
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/dos.h>
#include <proto/icon.h>
//#include <proto/graphics.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* This has all the stuff for StartMenu */
#include "/_StartMenu/messages.h"

UBYTE ver[] = {"$VER: WinMaster v1.0 "__AMIGADATE__};

struct MsgPort *my_port;
extern struct MsgPort *other_port;
IMAGE_SCALED ims;
START_MENU_GADGET smg;
WIN_INFO smwin;
struct Screen *scn;

VOID ShutDown(STRPTR s, int rc);
VOID FindStartMenu(VOID);
VOID SendStartMsg(APTR data, UBYTE command);
extern VOID __saveds PopWin(VOID);

int main(int argc, char **argv)
{
    START_MSG *rep_smsg;
    ULONG sig, my_sig;
    BOOL done = FALSE;
    BPTR lock;
    UBYTE icon_name[128];
    struct DiskObject *d_obj;

    FindStartMenu();

    lock = GetProgramDir();
    NameFromLock(lock, icon_name, 128);
    AddPart(icon_name, "WinMaster", 128);
    /* Scale the image */
    if (d_obj = GetDiskObject(icon_name)) {
        if (d_obj->do_Gadget.GadgetRender) {
            ims.ims_Image = d_obj->do_Gadget.GadgetRender;
            SendStartMsg((APTR)(&ims), SCALE_IMAGE);
            if (NULL == ims.ims_ScaledBM)
                ShutDown("Could not create icon", 5);
            memset(ims.ims_Mask->Planes[0], 0xFF, (ims.ims_Mask->BytesPerRow * ims.ims_Mask->Rows));
         }
         FreeDiskObject(d_obj);
     }

    smg.smg_BitMap    = ims.ims_ScaledBM;
    smg.smg_Mask      = ims.ims_Mask;
    smg.smg_Port      = my_port;
    smg.smg_PrivateBM = FALSE;
    SendStartMsg((APTR)(&smg), ADD_CLOCK_GADGET);
    if (NULL == smg.smg_Gadget)
        ShutDown("Could not create gadget.", 5);

    /* The event loop */
    my_sig = 1L << my_port->mp_SigBit;
    while (!done) {
        sig = Wait(my_sig | SIGBREAKF_CTRL_C);
        if (sig & my_sig) {
            while (rep_smsg = (START_MSG *)GetMsg(my_port)) {
                /* If it's GADGET_STATS, the user pressed a button */
                if (rep_smsg->sm_Command == GADGET_STATUS) {
                    ReplyMsg((struct Message *)rep_smsg);
                    if (NULL == other_port)
                        CreateNewProcTags(NP_Entry,       PopWin,
                                           NP_Input,       NULL,
                                           NP_Output,      NULL,
                                           NP_Name,        "WinMasterWin",
                                           TAG_END);
                }
                /* Start menu booted us! It must be shutting down */
                else if (rep_smsg->sm_Command == REM_CLOCK_GADGET) {
                    ReplyMsg((struct Message *)rep_smsg);
                    smg.smg_Gadget = NULL;
                    done = TRUE;
                }
            }
        }
        else if (sig & SIGBREAKF_CTRL_C) {
            done = TRUE;
        }
    }

    ShutDown(NULL, 0);
}

VOID ShutDown(STRPTR s, int rc)
{
    RE_GADGET reg;
    struct Message msg;

    if (NULL != other_port) {
        msg.mn_Node.ln_Type = NT_MESSAGE;
        msg.mn_Length = sizeof(struct Message);
        msg.mn_ReplyPort = my_port;
        PutMsg(other_port, &msg);
        WaitPort(my_port);
        GetMsg(my_port);
    }

    if (smg.smg_Gadget) {
        reg.re_Gadget = smg.smg_Gadget;
        SendStartMsg((APTR)(&reg), REM_CLOCK_GADGET);
    }

    if (my_port) DeletePort(my_port);

    if (s) printf("WinMaster: %s\n", s);
    exit(rc);
}

VOID FindStartMenu(VOID)
{
    WORD x = 0;
    struct MsgPort *tport;
    
    /* Make a couple of tries to find StartMenu */
    while (NULL == (tport = FindPort(STARTMENU_PORT_NAME))) {
        if (++x == 10) break;
        Delay(250);
    }
    if (NULL == tport)
        ShutDown("Could not find StartMenu.", 10);

    /* This port is for StartMenu to send us messages and for us to
       send StartMenu mesages */
    if (NULL == (my_port = CreatePort(0,0)))
        ShutDown("Could not create port.", 10);

    /* Want to know what screen StartMenu is running on */
    SendStartMsg((APTR)(&smwin), GET_WINDOW_INFO);
    if (NULL == (scn = smwin.wi_Window->WScreen))
        ShutDown("Could not get screen.", 5);
}

VOID SendStartMsg(APTR data, UBYTE command)
{
    struct MsgPort *sm_port;
    START_MSG msg;
    
    /* Make sure StartMenu hasn't gone anywhere */
    if (sm_port = FindPort(STARTMENU_PORT_NAME)) {
        msg.sm_Msg.mn_Node.ln_Type = NT_MESSAGE;
        msg.sm_Msg.mn_Length = START_MSG_SIZE;
        msg.sm_Msg.mn_ReplyPort = my_port;
        msg.sm_Command = command;
        msg.sm_Data = data;
        PutMsg(sm_port, (struct Message *)(&msg));
        WaitPort(my_port);           /* StartMenu replies to ALL messages!! */
        GetMsg(my_port);
    }
}
