/* Auto: make "CCEXTRA=-wq -qf"
*/

#if __SASC
#include "snap.h"
#endif

IMPORT BOOL Kick36;

IMPORT LONGBITS startsignal, insertsignal, cancelsignal;
IMPORT LONGBITS donesignal, movesignal, clicksignal;
IMPORT LONGBITS timersignal, initsignal, cwsignal, ticksignal;
IMPORT ULONG startsignum, insertsignum, cancelsignum;
IMPORT ULONG donesignum, movesignum, clicksignum;
IMPORT ULONG initsignum, cwsignum, ticksignum;

/* program */
IMPORT struct SnapRsrc *SnapRsrc;
IMPORT struct Task *MyTask;

/* Snap state machine */
IMPORT WORD action;
IMPORT WORD state;

/* clipboard */
IMPORT struct IOClipReq *ClipReq;
IMPORT struct MsgPort *ClipPort;

/* timer device */
IMPORT struct MsgPort *TimerPort;
IMPORT struct timerequest MyTR;

/* input device */
IMPORT struct MsgPort *inputDevPort;
IMPORT struct Interrupt handlerStuff;
IMPORT struct IOStdReq *inputRequestBlock;

IMPORT UBYTE *CharData;

/* console */
IMPORT struct MsgPort *ConPort;
IMPORT struct IOStdReq *ConIOR;
IMPORT struct KeyMap keymap;

/* windows */
#ifdef SNAPGFX
IMPORT struct MsgPort *Sharedport;
IMPORT SHORT Sharedrefs;
#endif SNAPGFX

/* libraries */
IMPORT struct IntuitionBase *IntuitionBase;
IMPORT struct GfxBase       *GfxBase;
#if 0
IMPORT struct LayersBase    *LayersBase;
IMPORT struct DiskFontBase  *DiskfontBase;
#endif
IMPORT struct Library *	LayersBase;
IMPORT struct Library *	DiskfontBase;

IMPORT struct Library       *IconBase;
#ifdef SNAPGFX
#ifdef REQLIB
IMPORT struct ReqBase       *ReqBase;
#endif REQLIB
#ifdef ASLLIB
IMPORT struct Library *AslBase;
#endif ASLLIB
#endif SNAPGFX

/* graphics */
IMPORT struct RastPort TempRp;
IMPORT struct BitMap TempBM;
IMPORT UBYTE *TempRaster;

#ifdef SNAPGFX
#ifdef REQLIB
IMPORT struct ReqFileRequester *NameFR;
#endif REQLIB
#ifdef ASLLIB
#define SetTag(t,i,v) { (t).ti_Tag = i; (t).ti_Data = (ULONG)(v); }
IMPORT struct FileRequester *AslNameFR;
#endif ASLLIB

IMPORT struct Image ActiveDiskImage;
IMPORT struct Image InactiveDiskImage;
IMPORT struct Image SelDiskImage;
IMPORT struct Image ActiveClipImage;
IMPORT struct Image InactiveClipImage;
IMPORT struct Image SelClipImage;
IMPORT struct Gadget DiskGad;
IMPORT struct Gadget ClipGad;

UWORD DiskImData36[144] = {
    /* Inactive */
    0x0000, 0x0000,
    0x0000, 0x4000,
    0x07f8, 0x4000,
    0x0408, 0x4000,
    0x05E8, 0x4000,
    0x0408, 0x4000,
    0x07F8, 0x4000,
    0x0618, 0x4000,
    0x0698, 0x4000,
    0x0698, 0x4000,
    0x0000, 0x4000,
    0x7FFF, 0xC000,

    0xFFFF, 0xC000,
    0x8000, 0x0000,
    0x8000, 0x0000,
    0x8000, 0x0000,
    0x8000, 0x0000,
    0x8000, 0x0000,
    0x8000, 0x0000,
    0x8000, 0x0000,
    0x8000, 0x0000,
    0x8000, 0x0000,
    0x8000, 0x0000,
    0x8000, 0x0000,

    /* Active */
    0x0000, 0x0000,
    0x7FFF, 0xC000,
    0x7FFF, 0xC000,
    0x7C0F, 0xC000,
    0x7DEF, 0xC000,
    0x7C0F, 0xC000,
    0x7FFF, 0xC000,
    0x7E1F, 0xC000,
    0x7E9F, 0xC000,
    0x7E9F, 0xC000,
    0x7FFF, 0xC000,
    0x7FFF, 0xC000,

    0xFFFF, 0xC000,
    0xFFFF, 0x8000,
    0xF807, 0x8000,
    0xFBF7, 0x8000,
    0xFA17, 0x8000,
    0xFBF7, 0x8000,
    0xF807, 0x8000,
    0xF9E7, 0x8000,
    0xF967, 0x8000,
    0xF967, 0x8000,
    0xFFFF, 0x8000,
    0x8000, 0x0000,

    /* Selected */
    0xFFFF, 0xC000,
    0xFFFF, 0x8000,
    0xFFFF, 0x8000,
    0xFC0F, 0x8000,
    0xFDEF, 0x8000,
    0xFC0F, 0x8000,
    0xFFFF, 0x8000,
    0xFE1F, 0x8000,
    0xFE9F, 0x8000,
    0xFE9F, 0x8000,
    0xFFFF, 0x8000,
    0x8000, 0x0000,

    0x0000, 0x0000,
    0x7FFF, 0xC000,
    0x7807, 0xC000,
    0x7BF7, 0xC000,
    0x7A17, 0xC000,
    0x7BF7, 0xC000,
    0x7807, 0xC000,
    0x79E7, 0xC000,
    0x7967, 0xC000,
    0x7967, 0xC000,
    0x7FFF, 0xC000,
    0x7FFF, 0xC000
};

UWORD DiskImData[13] = {
    /* BitPlane 0 */
    0xFFFF,
    0xFFFF,
    0xFFFF,
    0xF00F,
    0xF7EF,
    0xF42F,
    0xF7EF,
    0xF00F,
    0xF3CF,
    0xF2CF,
    0xF2CF,
    0xFFFF,
    0xFFFF
};

UWORD ClipImData36[156] = {
    /* Inactive */
    0x0000, 0x0000,
    0x0000, 0x4000,
    0x0C00, 0x4000,
    0x120E, 0x4000,
    0x1A38, 0x4000,
    0x0EE0, 0x4000,
    0x0380, 0x4000,
    0x0EE0, 0x4000,
    0x1A38, 0x4000,
    0x120E, 0x4000,
    0x0C00, 0x4000,
    0x0000, 0x4000,
    0x7FFF, 0xC000,

    0xFFFF, 0xC000,
    0x8000, 0x0000,
    0x8000, 0x0000,
    0x8000, 0x0000,
    0x8000, 0x0000,
    0x8000, 0x0000,
    0x8000, 0x0000,
    0x8000, 0x0000,
    0x8000, 0x0000,
    0x8000, 0x0000,
    0x8000, 0x0000,
    0x8000, 0x0000,
    0x8000, 0x0000,

    /* Active */
    0x0000, 0x0000,
    0x7FFF, 0xC000,
    0x7FFF, 0xC000,
    0x7FFF, 0xC000,
    0x7FFF, 0xC000,
    0x7FFF, 0xC000,
    0x7FFF, 0xC000,
    0x7FFF, 0xC000,
    0x7FFF, 0xC000,
    0x7FFF, 0xC000,
    0x7FFF, 0xC000,
    0x7FFF, 0xC000,
    0x7FFF, 0xC000,

    0xFFFF, 0xC000,
    0xFFFF, 0x8000,
    0xF3FF, 0x8000,
    0xEDF1, 0x8000,
    0xE5C7, 0x8000,
    0xF11F, 0x8000,
    0xFC7F, 0x8000,
    0xF11F, 0x8000,
    0xE5C7, 0x8000,
    0xEDF1, 0x8000,
    0xF3FF, 0x8000,
    0xFFFF, 0x8000,
    0x8000, 0x0000,

    /* Selected */
    0xFFFF, 0xC000,
    0xFFFF, 0x8000,
    0xFFFF, 0x8000,
    0xFFFF, 0x8000,
    0xFFFF, 0x8000,
    0xFFFF, 0x8000,
    0xFFFF, 0x8000,
    0xFFFF, 0x8000,
    0xFFFF, 0x8000,
    0xFFFF, 0x8000,
    0xFFFF, 0x8000,
    0xFFFF, 0x8000,
    0x8000, 0x0000,

    0x0000, 0x0000,
    0x7FFF, 0xC000,
    0x73FF, 0xC000,
    0x6DF1, 0xC000,
    0x65C7, 0xC000,
    0x711F, 0xC000,
    0x7C7F, 0xC000,
    0x711F, 0xC000,
    0x65C7, 0xC000,
    0x6DF1, 0xC000,
    0x73FF, 0xC000,
    0x7FFF, 0xC000,
    0x7FFF, 0xC000
};

UWORD ClipImData[14] = {
    /* BitPlane 0 */
    0xFFFF,
    0xFFFF,
    0xE7FF,
    0xDBE3,
    0xCB8F,
    0xE23F,
    0xF8FF,
    0xE23F,
    0xCB8F,
    0xDBE3,
    0xE7FF,
    0xFFFF,
    0xFFFF,
    0xFFFF
};
#endif SNAPGFX

VOID CloseStuff()
{
    SafeRestore();
    if (SnapRsrc) {
        KILLLIST(&SnapRsrc->CachedWindows, struct CacheWindow);
        if (SnapRsrc->AlternateFont) {
            CloseFont(SnapRsrc->AlternateFont);
        }
    }
#ifdef SNAPGFX
    if (InactiveDiskImage.ImageData) {
        FreeMem(InactiveDiskImage.ImageData,
                Kick36 ? sizeof(DiskImData36) : sizeof(DiskImData));
    }
    if (InactiveClipImage.ImageData) {
        FreeMem(InactiveClipImage.ImageData,
                Kick36 ? sizeof(ClipImData36) : sizeof(ClipImData));
    }
#endif SNAPGFX
    if (TempRaster)             FreeRaster(TempRaster, 16L, CHEIGHT);
    if (CharData)               FreeRaster(CharData, 16L, 256L * CHEIGHT);
    if (inputRequestBlock) {
        if (inputRequestBlock->io_Device) {
            inputRequestBlock->io_Command = IND_REMHANDLER;  /* Remove handler */
            inputRequestBlock->io_Data    = (APTR)&handlerStuff;
            DoIO((struct IORequest *)inputRequestBlock);
            CloseDevice((struct IORequest *)inputRequestBlock);
        }
        DeleteExtIO((struct IORequest *)inputRequestBlock);
    }
    if (inputDevPort)           DeletePort(inputDevPort);
    if (TimerPort) {
        DeletePort(TimerPort);
        CloseDevice((struct IORequest *)&MyTR);
    }
    if (ConIOR) {
        CloseDevice((struct IORequest *)ConIOR);
        DeleteExtIO((struct IORequest *)ConIOR);
    }
    if (ConPort)                DeletePort(ConPort);
    if (ClipReq) {
        if (ClipReq->io_Device) {
            CloseDevice((struct IORequest *)ClipReq);
        }
        DeleteExtIO((struct IORequest *)ClipReq);
    }
    if (ClipPort)               DeletePort(ClipPort);
    if (startsignum != -1)      FreeSignal(startsignum);
    if (donesignum != -1)       FreeSignal(donesignum);
    if (cancelsignum != -1)     FreeSignal(cancelsignum);
    if (movesignum != -1)       FreeSignal(movesignum);
    if (insertsignum != -1)     FreeSignal(insertsignum);
    if (clicksignum != -1)      FreeSignal(clicksignum);
    if (initsignum != -1)       FreeSignal(initsignum);
    if (cwsignum != -1)         FreeSignal(cwsignum);
    if (ticksignum != -1)       FreeSignal(ticksignum);
    if (SnapRsrc) {
        RemResource((struct MiscResource *)SnapRsrc);
        Kill(SnapRsrc);
    }
#ifdef SNAPGFX
#ifdef ASLLIB
    if (AslBase && AslNameFR)   FreeFileRequest(AslNameFR);
#endif ASLLIB
#ifdef REQLIB
    if (ReqBase && NameFR)      Delete(NameFR);
#endif REQLIB
#endif SNAPGFX
}

VOID CloseLibs()
{
#ifdef SNAPGFX
#ifdef ASLLIB
    if (AslBase)            CloseLibrary(AslBase);
#endif ASLLIB
#ifdef REQLIB
    if (ReqBase)            CloseLibrary((struct Library *)ReqBase);
#endif REQLIB
#endif SNAPGFX
    if (IconBase)           CloseLibrary(IconBase);
    if (DiskfontBase)       CloseLibrary(DiskfontBase);
    if (LayersBase)         CloseLibrary(LayersBase);
    if (IntuitionBase)      CloseLibrary((struct Library *)IntuitionBase);
    if (GfxBase)            CloseLibrary((struct Library *)GfxBase);
}

WORD OpenLibs()
{
    /* libraries */

    if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0L)))
        return 0;
    if (!(IntuitionBase =
	  (struct IntuitionBase *)OpenLibrary("intuition.library", 0L)))
        return 0;
    if (!(LayersBase = OpenLibrary("layers.library", 0L)))
        return 0;
    DiskfontBase = OpenLibrary("diskfont.library", 0L);
    IconBase = OpenLibrary(ICONNAME, 0L);
#ifdef SNAPGFX
#ifdef REQLIB
    ReqBase = (struct ReqBase *)OpenLibrary("req.library", 0L);
#endif REQLIB
#ifdef ASLLIB
    AslBase = OpenLibrary(AslName, 0L);
#endif ASLLIB
#endif
    return 1;
}

WORD OpenStuff()
{
    action = noaction;
    state  = waiting;
    inputRequestBlock = NULL;

#ifdef SNAPGFX
    Sharedrefs = 0;
    Sharedport = NULL;
#endif SNAPGFX

    /* Set up everything we need. */

#ifdef SNAPGFX
#ifdef REQLIB
    if (ReqBase) {
        NameFR = Create(ReqFileRequester);
    }
#endif REQLIB
#ifdef ASLLIB
    if (AslBase) {
        struct TagItem FRTags[4];

        SetTag(FRTags[0], ASL_Hail, "Save Picture As...");
        SetTag(FRTags[1], ASL_Dir,  "t:");
        SetTag(FRTags[2], ASL_File, "Snap.pic");
        SetTag(FRTags[3], TAG_END,  NULL);
        AslNameFR = AllocAslRequest(ASL_FileRequest, FRTags);
    }
#endif ASLLIB
#endif SNAPGFX

    /* signals */

    if ((startsignum = AllocSignal(-1L)) == -1L)
        return 0;
    if ((insertsignum = AllocSignal(-1L)) == -1L)
        return 0;
    if ((cancelsignum = AllocSignal(-1L)) == -1L)
        return 0;
    if ((donesignum = AllocSignal(-1L)) == -1L)
        return 0;
    if ((movesignum = AllocSignal(-1L)) == -1L)
        return 0;
    if ((clicksignum = AllocSignal(-1L)) == -1L)
        return 0;
    if ((initsignum = AllocSignal(-1L)) == -1L)
        return 0;
    if ((cwsignum = AllocSignal(-1L)) == -1L)
        return 0;
    if ((ticksignum = AllocSignal(-1L)) == -1L)
        return 0;
    MyTask = FindTask(NULL);                  /* Find myself to Signal me.  */
    startsignal  = 1L << startsignum;         /* No good to use bit numbers */
    insertsignal = 1L << insertsignum;
    cancelsignal = 1L << cancelsignum;
    donesignal   = 1L << donesignum;
    movesignal   = 1L << movesignum;
    clicksignal  = 1L << clicksignum;
    initsignal   = 1L << initsignum;
    cwsignal     = 1L << cwsignum;
    ticksignal   = 1L << ticksignum;

    /* clipboard device */

    if (!(ClipPort = CreatePort(0L, 0L)))
        return 0;
    if (!(ClipReq = (struct IOClipReq *)CreateExtIO(ClipPort, (LONG)sizeof(*ClipReq))))
        return 0;
    if (OpenDevice("clipboard.device", 0L, (struct IORequest *)ClipReq, 0L))
        return 0;
    ClipReq->io_ClipID = 0L;

    /* console device */

    if (!(ConPort = CreatePort(0L, 0L)))
        return 0;
    if (!(ConIOR = (struct IOStdReq *)CreateExtIO(ConPort, (LONG)sizeof(struct IOStdReq))))
        return 0;
    if (OpenDevice("console.device", -1L, (struct IORequest *)ConIOR, 0L))
        return 0;

    /* timer device */
    if (!(TimerPort = CreatePort(NULL, 0L)))
        return 0;
    timersignal = 1L << TimerPort->mp_SigBit;
    if (OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)&MyTR, 0))
        return 0;
    MyTR.tr_node.io_Message.mn_ReplyPort = TimerPort;
    MyTR.tr_node.io_Error = 0;

    /* input device */

    if (!(inputDevPort = CreatePort(0L, 0L)))
        return 0;
    if (!(inputRequestBlock = (struct IOStdReq *)CreateExtIO(inputDevPort, (LONG)sizeof(struct IOStdReq))))
        return 0;
    if (OpenDevice("input.device", 0L, (struct IORequest *)inputRequestBlock, 0L))
        return 0;

    /* input handler */

    handlerStuff.is_Data = (APTR)0x534E4150; /* Set up for installation of */
    handlerStuff.is_Code = myhandler;        /* myhandler.                 */
    handlerStuff.is_Node.ln_Pri = SnapRsrc->Priority;
                                             /* Ahead of intuition, please */
    handlerStuff.is_Node.ln_Name = "Snap Input Handler";

    inputRequestBlock->io_Command = IND_ADDHANDLER;
    inputRequestBlock->io_Data    = (APTR)&handlerStuff;

    DoIO((struct IORequest *)inputRequestBlock);  /* Add me. */


    /* Aligned font bitmap to use when matching */

    if (!(CharData = AllocRaster(16L, 256L * CHEIGHT))) {
        return 0;
    }

    /* temporary raster */

    if (!(TempRaster = AllocRaster(16L, CHEIGHT)))
        return 0;
    InitRastPort(&TempRp);                   /* Init RastPort used for */
    InitBitMap(&TempBM, 1L, 16L, CHEIGHT);   /* Locating position of   */
    TempBM.Planes[0] = TempRaster;           /* first character.       */
    TempRp.BitMap = &TempBM;

#ifdef SNAPGFX
    {
        WORD i;
        UWORD *DiskImageData;
        UWORD *ClipImageData;
        LONG DiskImageSize;
        LONG ClipImageSize;

        if (Kick36) {
            ActiveDiskImage = SelDiskImage = InactiveDiskImage;
            ActiveClipImage = SelClipImage = InactiveClipImage;
            DiskImageData = DiskImData36;
            ClipImageData = ClipImData36;
            DiskImageSize = sizeof(DiskImData36);
            ClipImageSize = sizeof(ClipImData36);
            DiskGad.Flags |= GADGHIMAGE;
            ClipGad.Flags |= GADGHIMAGE;
        } else {
            InactiveDiskImage = SelDiskImage = ActiveDiskImage;
            InactiveClipImage = SelClipImage = ActiveClipImage;
            DiskImageData = DiskImData;
            ClipImageData = ClipImData;
            DiskImageSize = sizeof(DiskImData);
            ClipImageSize = sizeof(ClipImData);
            DiskGad.Flags |= GADGHCOMP;
            ClipGad.Flags |= GADGHCOMP;
        }
        if (!(InactiveDiskImage.ImageData = AllocMem(DiskImageSize, MEMF_CHIP))) {
            return 0;
        }
        ActiveDiskImage.ImageData = &InactiveDiskImage.ImageData[Kick36 ? 48 : 0];
        SelDiskImage.ImageData    = &InactiveDiskImage.ImageData[Kick36 ? 96 : 0];
        for (i = 0; i < (DiskImageSize / sizeof(UWORD)); i++) {
            InactiveDiskImage.ImageData[i] = DiskImageData[i];
        }
        if (!(InactiveClipImage.ImageData = AllocMem(ClipImageSize, MEMF_CHIP))) {
            return 0;
        }
        ActiveClipImage.ImageData = &InactiveClipImage.ImageData[Kick36 ? 52 : 0];
        SelClipImage.ImageData    = &InactiveClipImage.ImageData[Kick36 ? 104 : 0];
        for (i = 0; i < (ClipImageSize / sizeof(UWORD)); i++) {
            InactiveClipImage.ImageData[i] = ClipImageData[i];
        }
    }
#endif SNAPGFX

    return 1;
}
