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

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

IMPORT BOOL Kick36;

struct Window *ControlWindow = NULL;

IMPORT struct MsgPort *Sharedport;
IMPORT WORD Sharedrefs;
IMPORT struct Window *SaveWin;

IMPORT LONG TopBar;
IMPORT LONG LeftBar;
IMPORT LONG RightBar;
IMPORT LONG BottomBar;
IMPORT LONG ScreenFontHeight;
IMPORT struct TextFont *ScreenFont;
IMPORT struct RastPort MyRP;

#define IDCMPFLAGS (MOUSEMOVE | NEWSIZE | CLOSEWINDOW | GADGETUP | \
                    ACTIVEWINDOW | INACTIVEWINDOW | MOUSEBUTTONS)

UBYTE *WindowTitle = (UBYTE *)"Snap 1.64 © Mikael Karlsson & Absolut Software\0";

/* Important!
 * The Inactive Image structs contains the values to be used with Kickstart >= 36.
 * The Active Image structs contains the values to be used with Kickstart < 36.
 * The Image structs are copied accordingly in OpenStuff().
 */

struct Image InactiveDiskImage = {
    0, 0,
    18, 12, 2,
    NULL,
    0x03, 0x00,
    NULL
};

struct Image ActiveDiskImage = {
    -1, -1,
    15, 13, 1,
    NULL,
    0x01, 0x00,
    NULL
};

struct Image SelDiskImage = {
    0, 0,
    18, 12, 2,
    NULL,
    0x03, 0x00,
    NULL
};

#if 0
struct Image DiskImage = {
    0, 0,
    18, 13, 1,
    NULL,
    0x01, 0x00,
    NULL
};
#endif

struct Image InactiveClipImage = {
    0, 0,
    18, 13, 2,
    NULL,
    0x03, 0x00,
    NULL
};

struct Image ActiveClipImage = {
    -1, 0,
    15, 14, 1,
    NULL,
    0x01, 0x00,
    NULL
};

struct Image SelClipImage = {
    0, 0,
    18, 13, 2,
    NULL,
    0x03, 0x00,
    NULL
};

struct Gadget DiskGad = {
    NULL,
    -12, 10,
    10, 12,
    GADGIMAGE | GRELRIGHT,
    RIGHTBORDER | RELVERIFY,
    BOOLGADGET,
    (APTR)&InactiveDiskImage,
    (APTR)&SelDiskImage,
    NULL,
    0L,
    NULL,
    DISKGAD,
    NULL,
};

struct Gadget ClipGad = {
    NULL,
    -12, 10,
    10, 13,
    GADGIMAGE | GRELRIGHT,
    RIGHTBORDER | RELVERIFY,
    BOOLGADGET,
    (APTR)&InactiveClipImage,
    (APTR)&SelClipImage,
    NULL,
    0L,
    NULL,
    CLIPGAD,
    NULL,
};

struct Gadget VProp = {
    NULL,
    -12, 10,
    10, -15,
    GADGHCOMP | GRELRIGHT | GRELHEIGHT,
    RIGHTBORDER | GADGIMMEDIATE | FOLLOWMOUSE | RELVERIFY,
    PROPGADGET,
    NULL,
    NULL,
    NULL,
    0L,
    NULL,
    VPROP,
    NULL
};

struct Gadget HProp = {
    NULL,
    4, -6,
    -23, 5,
    GADGHCOMP | GRELBOTTOM | GRELWIDTH,
    BOTTOMBORDER | GADGIMMEDIATE | FOLLOWMOUSE | RELVERIFY,
    PROPGADGET,
    NULL,
    NULL,
    NULL,
    0L,
    NULL,
    HPROP,
    NULL
};

struct PropInfo VInfo = {
    AUTOKNOB | FREEVERT | PROPBORDERLESS,
    0, 0,
    MAXBODY, MAXBODY,
    0, 0, 0, 0, 0, 0
};

struct PropInfo HInfo = {
    AUTOKNOB | FREEHORIZ | PROPBORDERLESS,
    0, 0,
    MAXBODY, MAXBODY,
    0, 0, 0, 0, 0, 0
};

struct Image VImage = {
    0, 0, 0, 0, 0, NULL, 0, 0, NULL
};
struct Image HImage = {
    0, 0, 0, 0, 0, NULL, 0, 0, NULL
};

/* Window structure for snapped gfx */
struct NewWindow Nw = {
    0, 1,                   /* LeftEdge, TopEdge  */
    0, 0,                   /* Width, Height */
    -1, -1,                 /* DetailPen, BlockPen */
    NULL,                   /* IDCMPFlags */
    WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE | WINDOWSIZING | RMBTRAP,
    NULL, NULL,             /* FirstGadget, CheckMark */
    NULL,
    NULL, NULL,             /* Screen, BitMap */
    0, 0,                   /* MinWidth, MinHeight */
    0, 0,                   /* MaxWidth, MaxHeight */
    WBENCHSCREEN            /* Type */
};

SHORT Coords3[5][2] = {
    {  0,  0},
    { 74,  0},
    { 74, 10},
    {  0, 10},
    {  0,  0}
};

SHORT Coords2[5][2] = {
    {  0,  0},
    { 74,  0},
    { 74, 10},
    {  0, 10},
    {  0,  0}
};

SHORT Coords1[5][2] = {
    {  0,  0},
    { 34,  0},
    { 34, 10},
    {  0, 10},
    {  0,  0}
};

struct Border Border3 = {
    -1, -2,
    1, 0,
    JAM1,
    5,
    (SHORT *)&Coords3,
    NULL
};

struct Border Border2 = {
    -1, -1,
    1, 0,
    JAM1,
    5,
    (SHORT *)&Coords2,
    NULL
};

struct Border Border1 = {
    -1, -1,
    1, 0,
    JAM1,
    5,
    (SHORT *)&Coords1,
    NULL
};

UBYTE TranspBuf[5];

struct StringInfo TranspSI = {
    TranspBuf,  /* Buf */
    NULL,       /* UndoBuf */
    0,          /* BufferPos */
    4,          /* MaxChars */
    0,          /* DispPos */
    0,          /* UndoPos */
    0,          /* NumChars */
    0,          /* DispCount */
    0, 0,       /* CLeft, CTop */
    NULL,       /* Layer */
    0L,         /* LongInt */
    NULL        /* AltKeyMap */
};

struct Gadget TranspGad = {
    NULL,
    5, 16,
    32, 8,
    LONGINT,
    RELVERIFY,
    STRGADGET,
    (APTR)&Border3,
    NULL,
    NULL,
    0L,
    (APTR)&TranspSI,
    0,
    NULL,
};

IMPORT char SaveName[DSIZE+FCHARS+2];

struct StringInfo NameSI = {
    (UBYTE *)SaveName,      /* Buf */
    NULL,                   /* UndoBuf */
    0,                      /* BufferPos */
    DSIZE+FCHARS,           /* MaxChars */
    0,                      /* DispPos */
    0,                      /* UndoPos */
    0,                      /* NumChars */
    0,                      /* DispCount */
    0, 0,                   /* CLeft, CTop */
    NULL,                   /* Layer */
    0L,                     /* LongInt */
    NULL                    /* AltKeyMap */
};

struct Gadget NameGad = {
    &TranspGad,
    5, 16,
    32, 8,
    NULL,
    NULL,
    NULL,
    (APTR)&Border2,
    NULL,
    NULL,
    0L,
    NULL,
    NAMEGAD,
    NULL,
};

struct Gadget SaveGad = {
    &NameGad,
    5, 16,
    32, 8,
    GADGHCOMP,
    RELVERIFY,
    BOOLGADGET,
    (APTR)&Border1,
    NULL,
    NULL,
    0L,
    NULL,
    SAVEGAD,
    NULL,
};

/* Window structure for control window */
struct NewWindow NewCW = {
    10, 10,           /* LeftEdge, TopEdge  */
    326, 40,          /* Width, Height */
    -1, -1,           /* DetailPen, BlockPen */
    NULL,             /* IDCMPFlags */
    WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE | ACTIVATE |
      SMART_REFRESH | NOCAREREFRESH | RMBTRAP,
    NULL, NULL,       /* FirstGadget, CheckMark */
    (UBYTE *)"Snap Control Window",
    NULL, NULL,       /* Screen, BitMap */
    32, 32,           /* MinWidth, MinHeight */
    -1, -1,           /* MaxWidth, MaxHeight */
    WBENCHSCREEN      /* Type */
};

#ifdef REQLIB
IMPORT struct ReqFileRequester *NameFR;
#endif REQLIB
#ifdef ASLLIB
IMPORT struct FileRequester *AslNameFR;
#endif ASLLIB

struct Window *opensharedwindow(nw)
struct NewWindow *nw;
{
    struct Window *win;
    struct Screen scr;

    if (!GetScreenData((char *)&scr, (LONG)sizeof(struct Screen),
      WBENCHSCREEN, NULL)) {
        return NULL;     /* No WB */
    }
    if (nw->TopEdge+nw->Height > scr.Height) {
        nw->TopEdge = scr.Height-nw->Height;
    }
    if (nw->LeftEdge+nw->Width > scr.Width) {
        nw->LeftEdge = scr.Width-nw->Width;
    }
    if (nw->TopEdge < 0) {
        nw->TopEdge = 0;
    }
    if (nw->LeftEdge < 0) {
        nw->LeftEdge = 0;
    }
    if (nw->TopEdge+nw->Height > scr.Height) {
        nw->Height = scr.Height-nw->TopEdge;
    }
    if (nw->LeftEdge+nw->Width > scr.Width) {
        nw->Width = scr.Width-nw->LeftEdge;
    }

    nw->IDCMPFlags = NULL;

    if (win = OpenWindow(nw)) {
        if (!Sharedport && !(Sharedport = CreatePort(0L, 0L))) {
            return NULL;
        }
        win->UserPort = Sharedport;
        ModifyIDCMP(win, IDCMPFLAGS);
        ++Sharedrefs;
    }
    return(win);
}


VOID closesharedwindow(win)
struct Window *win;
{
    REGISTER struct IntuiMessage *im, *safe;
    Forbid();
    Sharedrefs--;
    SAFEMAPLIST(&win->UserPort->mp_MsgList,
      struct IntuiMessage *, im, safe) {
        if (im->IDCMPWindow == win) {
            Remove((struct Node *)im);
            ReplyMsg((struct Message *)im);
        }
    }
    win->UserPort = NULL;
    ModifyIDCMP(win, NULL);
    Permit();
    CloseWindow(win);
    if (!Sharedrefs) {
        DeletePort(Sharedport);
        Sharedport = NULL;
    }
}

VOID SetUpBorder(Border, Gad)
struct Border *Border;
struct Gadget *Gad;
{
    Border->XY[2] = Border->XY[4] = Gad->Width + 1;
    Border->XY[5] = Border->XY[7] = Gad->Height + 1;
}

VOID DrawOldBorders(GS)
struct GfxSnap *GS;
{
    REGISTER LONG right;
    REGISTER LONG bottom;

    if (!Kick36) {
        right = GS->window->Width - GS->rightbar;
        bottom = GS->window->Height - GS->bottombar;
        SetDrMd(GS->window->RPort, JAM1);
        SetAPen(GS->window->RPort, 0L);
        Move(GS->window->RPort, 2L,        bottom);
        Draw(GS->window->RPort, right,     bottom);
        Move(GS->window->RPort, 2L,        bottom + 2);
        Draw(GS->window->RPort, right,     bottom + 2);
        Move(GS->window->RPort, right,     (LONG)GS->topbar);
        Draw(GS->window->RPort, right,     bottom);
        Draw(GS->window->RPort, right + 1, bottom);
        Draw(GS->window->RPort, right + 1, (LONG)GS->topbar);
        SetAPen(GS->window->RPort, 1L);
        Move(GS->window->RPort, right + 2, (LONG)GS->topbar);
        Draw(GS->window->RPort, right + 2, bottom);
        Draw(GS->window->RPort, right + 3, bottom);
        Draw(GS->window->RPort, right + 3, (LONG)GS->topbar);
        Move(GS->window->RPort, 2L,        bottom + 1);
        Draw(GS->window->RPort, right + 1, bottom + 1);
    }
}

VOID AdjustSize(GS)
struct GfxSnap *GS;
{
    ULONG w = GS->window->Width - GS->leftbar - GS->rightbar;
    ULONG h = GS->window->Height - GS->topbar - GS->bottombar;
    ULONG vb, hb;

    vb = hb = MAXBODY;

    if (w < GS->width) {
        hb = w * (ULONG)MAXBODY / GS->width;
    }
    if (h < GS->height) {
        vb = h * (ULONG)MAXBODY / GS->height;
    }
    NewModifyProp(&GS->VProp, GS->window, NULL,
      (ULONG)AUTOKNOB | FREEVERT | PROPBORDERLESS,
      0L, 0L, (ULONG)MAXBODY, vb, 1L);
    NewModifyProp(&GS->HProp, GS->window, NULL,
      (ULONG)AUTOKNOB | FREEHORIZ | PROPBORDERLESS,
      0L, 0L, hb, (ULONG)MAXBODY, 1L);
    RefreshWindowFrame(GS->window);
    DrawOldBorders(GS);
    InitRastPort(&MyRP);
    MyRP.BitMap = &GS->BM;
    SetAPen(GS->window->RPort, 0);
    RectFill(GS->window->RPort,
      (LONG)GS->leftbar, (LONG)GS->topbar,
      (LONG)GS->leftbar + w - 1, (LONG)GS->topbar + h - 1);
    if (w > GS->width)  w = GS->width;
    if (h > GS->height) h = GS->height;
    ClipBlit(&MyRP, 0L, 0L, GS->window->RPort,
      (LONG)GS->leftbar, (LONG)GS->topbar, w, h, 0xC0L);
}

VOID SyncGS(GS)
struct GfxSnap *GS;
{
    ULONG w = GS->window->Width - GS->leftbar - GS->rightbar;
    ULONG h = GS->window->Height - GS->topbar - GS->bottombar;
    ULONG vpos, hpos;
    LONG temp;

    temp = GS->width - w;
    if (temp <= 0) {
        hpos = 0;
    } else {
        hpos = temp * (LONG)GS->HInfo.HorizPot / MAXBODY;
        if (hpos > temp) {
            hpos = temp;
        }
    }
    temp = GS->height - h;
    if (temp <= 0) {
        vpos = 0;
    } else {
        vpos = temp * (LONG)GS->VInfo.VertPot / MAXBODY;
        if (vpos > temp) {
            vpos = temp;
        }
    }
    DrawOldBorders(GS);
    InitRastPort(&MyRP);
    MyRP.BitMap = &GS->BM;
    if (w > GS->width) {
        w = GS->width;
    }
    if (h > GS->height) {
        h = GS->height;
    }
    ClipBlit(&MyRP, hpos, vpos, GS->window->RPort,
      (LONG)GS->leftbar, (LONG)GS->topbar, w, h, 0xC0L);
}

SHORT OpenCW()
{
    WORD temp;
    struct RastPort TmpRP;

    FixHeights();

    InitRastPort(&TmpRP);
    SetFont(&TmpRP, ScreenFont);

    SaveGad.TopEdge = NameGad.TopEdge = TopBar + 2;
    SaveGad.Height = NameGad.Height = TranspGad.Height = ScreenFontHeight + 2;

    TranspGad.TopEdge = SaveGad.TopEdge + SaveGad.Height + 5;

    SaveGad.LeftEdge = LeftBar + 2;
    SaveGad.Width = TextLength(&TmpRP, "Save", 4L) + 1;
    SaveGad.Flags |= GADGDISABLED;

    NameGad.LeftEdge = SaveGad.LeftEdge +
      TextLength(&TmpRP, "Save as ", 8L);

    temp = 322 - NameGad.LeftEdge;
    NameGad.Width =
      temp - (temp % TextLength(&TmpRP, " ", 1L)) + 1;

    TranspGad.LeftEdge = SaveGad.LeftEdge +
      TextLength(&TmpRP, "Transparent color ", 18L);
    TranspGad.Width = TextLength(&TmpRP, "0000", 4L) + 2;

    NewCW.Height = TopBar + BottomBar + ScreenFontHeight * 2 + 12;

#define dmax(a,b) ((a>b)?a:b)
    NewCW.Width=dmax((TranspGad.LeftEdge + TranspGad.Width + 2 + RightBar), (NameGad.LeftEdge + NameGad.Width + 2 + RightBar));
#undef dmax

    ControlWindow = opensharedwindow(&NewCW);
    if (!ControlWindow) {
        return 0;
    }
    SetFont(ControlWindow->RPort, ScreenFont);
    ModifyIDCMP(ControlWindow, ControlWindow->IDCMPFlags&~NEWSIZE);

    SetUpBorder(&Border1, &SaveGad);
    SetUpBorder(&Border2, &NameGad);
    SetUpBorder(&Border3, &TranspGad);

#if defined(REQLIB) || defined(ASLLIB)
#ifdef REQLIB
#ifdef ASLLIB
    if ((NameFR) || (AslNameFR))
#else ASLLIB
    if (NameFR)
#endif ASLLIB
#else
    if (AslNameFR)
#endif REQLIB
    {
        NameGad.Flags = GADGHCOMP;
        NameGad.Activation = RELVERIFY;
        NameGad.GadgetType = BOOLGADGET;
        NameGad.SpecialInfo = NULL;
    } else
#endif REQLIB || ASLLIB
    {
        NameGad.Flags = SELECTED;
        NameGad.Activation = NULL;
        NameGad.GadgetType = STRGADGET;
        NameGad.SpecialInfo = (APTR)&NameSI;
        ++NameGad.LeftEdge;         /* Adjust string gadget position */
        ++NameGad.TopEdge;          /* Adjust string gadget position */
    }

    strcpy(SaveName, "Snap.pic");
    strcpy((char *)TranspBuf, "0");
    TranspSI.LongInt = 0L;

    SetAPen(ControlWindow->RPort, 1L);
    SetBPen(ControlWindow->RPort, 0L);
    SetDrMd(ControlWindow->RPort, JAM2);
    Move(ControlWindow->RPort,
      (LONG)SaveGad.LeftEdge + 1,
      (LONG)SaveGad.TopEdge + ControlWindow->RPort->Font->tf_Baseline + 1);
    Text(ControlWindow->RPort, "Save as", 7L);
    Move(ControlWindow->RPort,
      (LONG)SaveGad.LeftEdge + 1,
      (LONG)TranspGad.TopEdge + ControlWindow->RPort->Font->tf_Baseline);
    Text(ControlWindow->RPort, "Transparent color", 17L);
    AddGList(ControlWindow, &SaveGad, -1L, 3L, NULL);
    RefreshGList(&SaveGad, ControlWindow, NULL, 3L);

#if defined(REQLIB) || defined(ASLLIB)
#ifdef REQLIB
#ifdef ASLLIB
    if ((NameFR) || (AslNameFR))
#else  ASLLIB
    if (NameFR)
#endif ASLLIB
#else
    if (AslNameFR)
#endif REQLIB
    {
        GadText(&NameGad, SaveName, 8L);
    } else
#endif REQLIB || ASLLIB
    {
        ActivateGadget(&NameGad, ControlWindow, NULL);
    }
    return 1;
}
