/***********************************************************************
 * Journey to the Center of the SMURF... the End_of_SMURF command file
 * Marc Wolfgram, 1Nov90
 ***********************************************************************/

#include "genesys.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <types.h>
#include <quickdraw.h>
#include <qdaux.h>
#include <control.h>
#include <lineedit.h>
#include <list.h>
#include <gsos.h>
#include <intmath.h>
#include <memory.h>
#include <resources.h>
#include <window.h>
#include <usrlib.h>
#include "smurf.h"

#define horz 1
#define vert 2

extern Smurf SMURF;
extern int ResFileID, MasterID;
extern long taskORmask, taskANDmask;

typedef struct rgnList {
    int         patNum;
    int         numRgns;
    RegionHndl  list[1];
} rgnList, *rgnListPtr, **rgnListHan;

word        rNest;
LongWord    lastTick;

extern int  AddItem(word, long);
extern int  DelItem(word, long);

/* Red 640 mode 32 bit patterns */

Byte       StartStopPat[44] = {     /* get things going/stop march patterns */
           0x44, 0xff, 0x44, 0xff,  /* pattern[3] entry */
           0x4f, 0xf4, 0x4f, 0xf4,  /* pattern[2] entry */
           0xff, 0x44, 0xff, 0x44,  /* pattern[1] entry */
           0xf4, 0x4f, 0xf4, 0x4f,  /* pattern[0] entry */
           0x44, 0xff, 0x44, 0xff,
           0x4f, 0xf4, 0x4f, 0xf4,
           0xff, 0x44, 0xff, 0x44,
           0xf4, 0x4f, 0xf4, 0x4f,
           0x44, 0xff, 0x44, 0xff,
           0x4f, 0xf4, 0x4f, 0xf4,
           0xff, 0x44, 0xff, 0x44,
           };

Byte       MarchPat [44] = {       /* sneaky pre-shifted notXOR patterns */
           0x4f, 0x4f, 0x4f, 0x4f, /* pattern[3] entry */
           0xf4, 0xf4, 0xf4, 0xf4, /* pattern[2] entry */
           0x4f, 0x4f, 0x4f, 0x4f, /* pattern[1] entry */
           0xf4, 0xf4, 0xf4, 0xf4, /* pattern[0] entry */
           0x4f, 0x4f, 0x4f, 0x4f,
           0xf4, 0xf4, 0xf4, 0xf4,
           0x4f, 0x4f, 0x4f, 0x4f,
           0xf4, 0xf4, 0xf4, 0xf4,
           0x4f, 0x4f, 0x4f, 0x4f,
           0xf4, 0xf4, 0xf4, 0xf4,
           0x4f, 0x4f, 0x4f, 0x4f,
           };

int toolerror(void);
int jsl_Editor(void);
void shError(int, int);
void ShellCoords(void);
void ClipEvent(void);

/*****************************************************************************
 * SaveSMURF(), LoadSMURF()
 *****************************************************************************/
Handle SaveSMURF(void)
{
    int i;
    char *t, *s;
    Handle Hndl;

    Hndl = NewHandle(64L, MasterID, 0x8018, 0L);
    if (toolerror() != 0)
        return (Handle) 0L;

    HLock(Hndl);
    s = (char *) &SMURF;
    t = (char *) *Hndl;
    for (i = 0; i < 64; i++)
        *t++ = *s++;
    HUnlock(Hndl);
    return Hndl;
}

int LoadSMURF(Handle sHndl)
{
    int i;
    char *t, *s;

    HLock(sHndl);
    if ((i = toolerror()) == 0) {
        s = (char *) *sHndl;
        t = (char *) &SMURF;
        for (i = 0; i < 64; i++)
            *t++ = *s++;
        HUnlock(sHndl);
        DisposeHandle(sHndl);
        i = toolerror();
    }
    return i;
}

/*****************************************************************************
 * SetResAccess(), EndResAccess()
 *****************************************************************************/
LongWord SetResAccess(int rFileID, int rDepth)
{
    LongWord ret;

    ret = (long) GetCurResourceFile();
    if (toolerror())
        return 0L;
    ret <<= 16;
    ret += (long) SetResourceFileDepth(rDepth);
    SetCurResourceFile(rFileID);
    return ret;
}

int EndResAccess(LongWord rav)
{
    int tmp;

    tmp = SetResourceFileDepth((int)(rav & 0xFFFF));
    rav >>= 16;
    SetCurResourceFile((int) rav);
    return toolerror();
}
/*****************************************************************************
 * EOS COMMAND 1 is the DrawCoords routine in Layout.asm
 *****************************************************************************/

/*****************************************************************************
 * EOS COMMAND 2
 * EOS_AntMarch()   Marching Ant proc for Genesys(tm) red ants
 *
 * Inputs : wP, theRgns, theTask, theTick
 *          task: 0 march ants in theRgns list
 *                1 start the regions passed in theRgns list
 *                2 remove the regions passed in theRgns list
 * NOTES  : Must set the high bit of the GrafPort ArcRot field for
 *          the window to use 32 bit patterns.
 *****************************************************************************/
void EOS_AntMarch(GrafPortPtr wP, rgnList **theRgns, Word theTask)

{
    int i;
    LongWord theTick;
    PenState   oldPenState;
    RegionHndl  updateRgn;
    GrafPortPtr oldWPtr;

    theTick = GetTick();

    oldWPtr = GetPort();             /* save the current port        */
    SetPort(wP);                     /* set port to passed ptr       */

    GetPenState(&oldPenState);       /* save current pen state       */
    SetPenSize(2, 1);                /* set up pen for ant drawing   */

    SetPenMode(notXOR);              /* non-destructive drawing mode */

    if (theTask) {  /* 1 or 2 */
        SetPenPat(&StartStopPat[((**theRgns).patNum)*4]);
        for (i = 0; i < (**theRgns).numRgns; i++)
            FrameRgn((**theRgns).list[i]);
        if (theTask == 1)
            lastTick = theTick;
    }
    else if ((theTick - lastTick) >= 10 && EmptyRgn(GetUpdateRgn(wP))) {
            SetPenPat(&MarchPat[((**theRgns).patNum)*4]);
            for (i = 0; i < (**theRgns).numRgns; i++)
                FrameRgn((**theRgns).list[i]);
            i = (**theRgns).patNum - 1;
            (**theRgns).patNum = (i >= 0) ? i : 3;
            lastTick = theTick;
    }

    SetPenState(&oldPenState);
    SetPort(oldWPtr);
}

void OldAntMarch(GrafPortPtr wP, rgnList **theRgns, Word theTask, long DUMMY)
{
    EOS_AntMarch(wP, theRgns, theTask);
}

/*****************************************************************************
 * EOS COMMAND 3
 * EOS_AddChild()
 *****************************************************************************/
void EOS_AddChild(word rType, long rID)
{
    int i;
    ResDepRecPntr p;
    ResDepRecHndl h;

    h = (ResDepRecHndl) SMURF.EditResult;
    SetHandleSize(GetHandleSize(h)+CHILDSIZE, h);
    if ((i = toolerror()) != 0) {
        shError(i, 0xf401);
    }
    else {
        HLock(h);
        p = *h;
        i = p->Count++;
        p->Child[i].rType = rType;
        p->Child[i].rID = rID;
        p->Child[i].rNest = rNest;
        HUnlock(h);
    }
}

/*****************************************************************************
 * EOS COMMAND 4
 * EOS_Create2()
 *****************************************************************************/
long EOS_Create2(int rType, long rID, Handle rHndl)
{
    Handle  sHndl;
    long    ret = 0L;

    sHndl = SaveSMURF();

    SMURF.ResourceType = rType;
    SMURF.ResourceID = rID;
    SMURF.EditResult = (long) rHndl;
    SMURF.EditCommand = 9;          /* Create2 */
    if (jsl_Editor() == 0)
        ret = SMURF.ResourceID;

    LoadSMURF(sHndl);
    return ret;
 }

/*****************************************************************************
 * EOS COMMAND 5  RESERVED
 *****************************************************************************/

/*****************************************************************************
 * EOS COMMAND 6
 * EOS_Special
 *****************************************************************************/
long EOS_Special(int subcmd, long misc)
{
long retval;

    switch (subcmd) {

    case 1: /* this handles the inactive controls for the window editor */
        taskORmask = 0L;
        taskANDmask = (misc) ? 0x1CFFFFL : 0x1FFFFFL;
        retval = 0L;
        break;

    default: /* this handles fuckups */
        SysBeep();
        break;
    }

    return retval;
}

/*****************************************************************************
 * EOS COMMAND 7
 * Dependents()
 *****************************************************************************/
ResDepRecHndl Dependents(word rFileID, word rType, long rID, ResDepRecHndl h)
{
    int i;
    ResDepRecPntr p;
    Handle sHndl;

    if (h == 0L) {
        h = (ResDepRecHndl) NewHandle(4L+CHILDSIZE, MasterID, 0x8018, 0L);
        if ((i = toolerror()) != 0) {
            shError(i, 0xf301);
            return (ResDepRecHndl) 0L;
        }
        HLock(h);
        p = *h;
        p->Version = 1;
        p->Count = 1;
        i = 0;
    }
    else {
        HUnlock(h);
        if ((i = toolerror()) != 0) {
            shError(i, 0xf302);
            return (ResDepRecHndl) 0L;
        }
        SetHandleSize(GetHandleSize(h)+CHILDSIZE, h);
        if ((i = toolerror()) != 0) {
            shError(i, 0xf303);
            return (ResDepRecHndl) 0L;
        }
        HLock(h);
        p = *h;
        i = p->Count++;
    }

    p->Child[i].rType = rType;
    p->Child[i].rID = rID;
    p->Child[i].rNest = 1;

    sHndl = SaveSMURF();

    SMURF.ResourceFileID = rFileID;

    for (i = 0; i < (**h).Count; i++) {
        HLock(h);
        p = *h;
        SMURF.ResourceType = p->Child[i].rType;
        SMURF.ResourceID = p->Child[i].rID;
        rNest = p->Child[i].rNest + 1;
        HUnlock(h);
        SMURF.EditResult = (long) h;
        SMURF.EditCommand = 8;          /* request dependencies */
        jsl_Editor();
    }
    LoadSMURF(sHndl);

    return h;
}

/*****************************************************************************
 * EOS COMMAND 8
 * EOS_Update()
 *****************************************************************************/
void EOS_Update(int rType, long rID, word flag)
{
    if (!flag)
        DelItem(rType, rID);
    else
        AddItem(rType, rID);
}

/*******************a**********************************************************
 * EOS COMMAND 9
 * EOS_EdRes2Hand()
 *****************************************************************************/
Handle EOS_Res2Hand(int rFileID, int rType, long rID)
{
    int rAttr;
    long rItem;
    Handle rHndl;

    rHndl = (Handle) 0L;

    rItem = SetResAccess(rFileID, 1);
    if (rItem) {
        rAttr = GetResourceAttr(rType, rID);
        if (!toolerror()) {
            SetResourceAttr(0, rType, rID);

            rHndl = LoadResource(rType, rID);
            if (toolerror())
                rHndl = (Handle) 0L;
            else
                DetachResource(rType, rID);

            SetResourceAttr(rAttr, rType, rID);
        }
    }
    EndResAccess(rItem);

    return (rHndl);
}

/*****************************************************************************
 * EOS COMMAND 10
 *****************************************************************************/

/*****************************************************************************
 * EOS COMMAND 11
 * EOS_LoadRes()
 *****************************************************************************/
Handle EOS_LoadRes(int rType, long rID)
{
    int rAttr;
    long rItem;
    Handle rHndl;

    rHndl = (Handle) 0L;

    rItem = SetResAccess(ResFileID, 1);
    if (rItem) {
        rAttr = GetResourceAttr(rType, rID);
        if (!toolerror()) {
            SetResourceAttr(0, rType, rID);

            rHndl = LoadResource(rType, rID);
            if (toolerror())
                rHndl = (Handle) 0L;

            SetResourceAttr(rAttr, rType, rID);
        }
    }
    EndResAccess(rItem);

    return (rHndl);
}

/*****************************************************************************
 * EOS COMMAND 12
 * EOS_SaveRes()
 *****************************************************************************/
long EOS_SaveRes(int rType, long rID, int rPurge)
{
    int rAttr;
    long rItem, lErr;
    Handle rHndl;

    rHndl = (Handle) 0L;

    rItem = SetResAccess(ResFileID, 1);
    if (rItem) {
        rAttr = GetResourceAttr(rType, rID);
        lErr = (long) toolerror();
        if (!lErr) {
            SetResourceAttr(0, rType, rID);

            MarkResourceChange(-1, rType, rID);
            WriteResource(rType, rID);
            lErr = (long) toolerror();
            if (!lErr)
                ReleaseResource(rPurge, rType, rID);

            SetResourceAttr(rAttr, rType, rID);
        }
    }
    EndResAccess(rItem);

    return (lErr);
}

/*****************************************************************************
 * EOS COMMAND 13
 * EOS_AddRes()
 *****************************************************************************/
long EOS_AddRes(Handle rHandle, int rAttr, int rType, long rID)
{
    int rErr = -1;
    long rItem;

    rItem = SetResAccess(ResFileID, 1);
    if (rItem) {
        if (rID == 0L)
            rID = UniqueResourceID(-1, rType);

        AddResource(rHandle, rAttr, rType, rID);
        rErr = toolerror();

        if (rErr == 0x1e05) {
            rID = UniqueResourceID(-1, rType);
            AddResource(rHandle, rAttr, rType, rID);
            rErr = toolerror();
        }

    }
    EndResAccess(rItem);

    return rErr ? 0L : rID;
}

/*****************************************************************************
 * EOS COMMAND 14
 * EOS_KillRes()
 *****************************************************************************/
long EOS_KillRes(int rType, long rID)
{
    int rDepth, rFileID;
    long lErr = -1L;
    long rItem;

    rItem = SetResAccess(ResFileID, 1);
    if (rItem) {
        RemoveResource(rType, rID);
        lErr = (long) toolerror();
    }
    EndResAccess(rItem);

    return (lErr);
}

/*****************************************************************************
 * EOS COMMAND 15
 * EOS_CntrWin()
 *****************************************************************************/
int EOS_CntrWin(int whichWay)
{
    Rect winRect, infoRect;
    GrafPortPtr oldPort, whichWin;
    WRefConHndl refconH;
    Word frame;

    whichWin = FrontWindow();       /* get front window */
    shError(toolerror(), 0x9402);
    if (whichWin) {
        refconH = (WRefConHndl) GetWRefCon(whichWin);
        shError(toolerror(), 0x9403);
        if ((**refconH).winResType == 0x800e)
            SMURF.EditModifiers |= 0x8000;

        oldPort = GetPort();        /* save and set */
        SetPort(whichWin);          /* window ports */

        GetPortRect(&winRect);      /* get content rect */
        frame = GetWFrame(whichWin);

        LocalToGlobal(&winRect.v1);
        LocalToGlobal(&winRect.v2);

        if (whichWay & horz) {      /* calc horz/both */
            winRect.h1 = (640 - (winRect.h2 - winRect.h1)) / 2;

            if ((frame & fRScroll) != 0)  /* right scroll */
                winRect.h1 -= 12;
        }

        if (whichWay & vert) {      /* calc vert/both */
            winRect.v1 = ((187 - (winRect.v2 - winRect.v1)) / 2) + 13;

            if ((frame & fTitle) != 0)    /* title bar */
                winRect.v1 += 6;
            if ((frame & fBScroll) != 0)  /* bottom scroll */
                winRect.v1 -= 6;
            if ((frame & fInfo) != 0) {   /* info bar is not */
                GetRectInfo(&infoRect, whichWin);       /* part of rect so */
                winRect.v1 += infoRect.v2 / 2;          /* calc it in too! */
            }
        }

        MoveWindow(winRect.h1 & 0xfffe, winRect.v1, whichWin);
        shError(toolerror(), 0x9410);

        SetPort(oldPort);   /* restore orig port*/
    }

    return 0;
}

/*****************************************************************************
 * EOS COMMAND 16 Copy
 *****************************************************************************/

/*****************************************************************************
 * EOS COMMAND 17 SubEdit
 *****************************************************************************/

/*****************************************************************************
 * EOS COMMAND 18
 * EOS_IndexChild()
 *****************************************************************************/
typedef struct ResRec { word rType; long rID; } *ResRecPtr;

long EOS_IndexChild(ResDepRecHndl h, word item, ResRecPtr child)
{
ResDepRecPntr   p;

    p = *h;

    if (item < 0 || item >= p->Count)
        return 0L;

    child->rType = p->Child[item].rType;
    child->rID = p->Child[item].rID;
    return (long) p->Child[item].rNest;
}
