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

#include "Snap.h"

IMPORT BOOL Kick36;

struct Window *ControlWindow = NULL;

extern char Version[];
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 *) Version[ 5];

/* 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 */
	(UBYTE)-1, (UBYTE)-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 */
	(UBYTE)-1, (UBYTE)-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 */
	(UWORD)-1, (UWORD)-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( 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->BitMap;
	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->BitMap;
	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;
}
