/************************************************************************
*  Version 3.00  MANDELBROT - Self-Squared Dragon Generator  29-May-86  *
*  Commodore Amiga           Color Window                      MAND5.C  *
*************************************************************************
*         Copyright (c) 1986, Robert S. French and R. J. Mical          *
* --------------------------------------------------------------------- *
*  This program has been placed in the public domain.  A limited        *
*  license is hereby granted for the unlimited use and distribution of  *
*  this program, provided it is not used for commercial or profit-      *
*  making purposes.  Thank you.                                         *
*************************************************************************
*  Author information:            | Name:   R. J. Mical                 *
*                                 | USnail: Commodore-Amiga, Inc.       *
*  Name:   Robert S. French       |         983 University Avenue       *
*  USnail: 2740 Frankfort Avenue  |         Los Gatos, CA  95030        *
*          Louisville, KY  40206  \-------------------------------------*
*  Phone:  (502) 897-5096              UUCP: ihnp4!ptsfa!well!french    *
*  ARPA:   French#Robert%d@LLL-MFE or RFrench@MIT-MULTICS               *
*************************************************************************
*  Please send any comments, suggestions, or bugs to one of the above   *
*  addresses.                                                           *
************************************************************************/

#include "mand.h"
#include "globals.h"


#define COPYCOLOR    1
#define RANGE_FIRST  2
#define RANGE_SECOND 3

#define COLOR_IDCMP_FLAGS (GADGETDOWN | GADGETUP | MOUSEBUTTONS | MENUPICK | MOUSEMOVE | ACTIVEWINDOW | INACTIVEWINDOW)

USHORT ColorMode;
USHORT SavePalette[32];
USHORT RangeFirst;      /* the first selection of the range-color pair */

/*****************************************************************************
*
* Color initialization and routines
*
****************************************************************************/


BOOL OpenColorWindow()
{
	SHORT i;

	if (ColorWindow)
		return(TRUE);

	disable_some(~0,~0,~0);
	ColorNewWindow.Screen = screen;
	ColorNewWindow.IDCMPFlags = NULL;
	ColorNewWindow.FirstGadget	= &ColorTemplateGadgets[COLOR_GADGETS_COUNT - 1];
	SetColorProps();
	InitSuperColors();
	ColorMode = NULL;

	if ((ColorWindow = (struct Window *)OpenWindow(&ColorNewWindow)) == 0) {
		printf("no memory!\n");
		return(FALSE);
	}
	ColorWindow->UserPort = w->UserPort;
	ModifyIDCMP(ColorWindow, COLOR_IDCMP_FLAGS);
	reset_menus();

	for (i = 0; i < 32; i++)
		SavePalette[i] = GetRGB4(vp->ColorMap, i);
	DrawColorWindow();
	return(TRUE);
}


VOID CloseColorWindow(accept)
BOOL accept;
{
	SHORT i;

	if (ColorWindow == NULL)
		return;

	ClearMenuStrip(ColorWindow);
	ColorWindow->UserPort = NULL;
	CloseWindow(ColorWindow);
	ColorWindow = NULL;

	if (NOT accept)
		LoadRGB4(vp, &SavePalette[0], 32);
	else {
		color_set = 2;
		UserPalette[0] = GetRGB4(vp->ColorMap, 0);
		UserPalette[1] = GetRGB4(vp->ColorMap, 1);
		UserPalette[2] = GetRGB4(vp->ColorMap, 2);
		for (i = 3; i <= 31; i++)
			*(color_table + color_offset + (i - 2) * color_inc)
			= GetRGB4(vp->ColorMap, i);
	}
}


VOID ColorRange(first, last)
SHORT first, last;
{
	SHORT i;
	LONG whole, redfraction, greenfraction, bluefraction;
	USHORT rgb;
	SHORT firstred, firstgreen, firstblue;
	SHORT lastred, lastgreen, lastblue;
	SHORT workred, workgreen, workblue;

	if (first > last) {
		i = first;
		first = last;
		last = i;
	}

	/* I need to see a spread of at least two, where there's at least one
	* spot between the endpoints, else there's no work to do so I
	* might as well just return now.
	*/
	if (first >= last - 1)
		return;

	rgb = GetRGB4(vp->ColorMap, first);
	firstred = (rgb >> 8) & 0xF;
	firstgreen = (rgb >> 4) & 0xF;
	firstblue = (rgb >> 0) & 0xF;

	rgb = GetRGB4(vp->ColorMap, last);
	lastred = (rgb >> 8) & 0xF;
	lastgreen = (rgb >> 4) & 0xF;
	lastblue = (rgb >> 0) & 0xF;

	whole = (lastred - firstred) << 16;
	redfraction = whole / (last - first);
	whole = (lastgreen - firstgreen) << 16;
	greenfraction = whole / (last - first);
	whole = (lastblue - firstblue) << 16;
	bluefraction = whole / (last - first);

	for (i = first + 1; i < last; i++) {
		lastred = (redfraction * (i - first) + 0x8000) >> 16;
		workred = firstred + lastred;
		lastgreen = (greenfraction * (i - first) + 0x8000) >> 16;
		workgreen = firstgreen + lastgreen;
		lastblue = (bluefraction * (i - first) + 0x8000) >> 16;
		workblue = firstblue + lastblue;
		SetRGB4(vp, i, workred, workgreen, workblue);
	}
}


BOOL ColorGadgetGotten(gadget)
struct Gadget *gadget;
{
	USHORT rgb, pen;
	struct RastPort *RPort;
	SHORT greenpos, redpos, bluepos;

	RPort = ColorWindow->RPort;

	/* Have we got a color specifier? */
	if (gadget->GadgetID < 32) {
		/* Yes, it's a color gadget.  Set this pen number */
		pen = gadget->GadgetID;
		/* first, were we in COPY COLOR mode? */
		if (ColorMode == COPYCOLOR) {
			/* ok, copy old color here first! */
			rgb = GetRGB4(vp->ColorMap, rp->FgPen);
			SetRGB4(vp, pen, rgb >> 8, rgb >> 4, rgb);
			ColorMode = NULL;
		}
		if (ColorMode == RANGE_FIRST) {
			ColorMode = RANGE_SECOND;
			RangeFirst = pen;
		}
		else
			if (ColorMode == RANGE_SECOND) {
				ColorMode = NULL;
				ColorRange(RangeFirst, pen);
			}
			SetAPen(rp, pen);
		rgb = GetRGB4(vp->ColorMap, pen);
		ColorRectFill(RPort, pen);

		redpos = RemoveGadget(ColorWindow,
		&ColorTemplateGadgets[COLOR_RED]);
		greenpos = RemoveGadget(ColorWindow,
		&ColorTemplateGadgets[COLOR_GREEN]);
		bluepos = RemoveGadget(ColorWindow,
		&ColorTemplateGadgets[COLOR_BLUE]);
		SetColorProps();
		AddGadget(ColorWindow, &ColorTemplateGadgets[COLOR_BLUE], bluepos);
		AddGadget(ColorWindow, &ColorTemplateGadgets[COLOR_GREEN], greenpos);
		AddGadget(ColorWindow, &ColorTemplateGadgets[COLOR_RED], redpos);
		RefreshGadgets(&ColorTemplateGadgets[COLOR_GADGETS_COUNT - 1],
		ColorWindow);
	}

	else
		switch (gadget->GadgetID) {
			case COLOR_OK:
				CloseColorWindow(TRUE);
				return(FALSE);
				break;
			case COLOR_CANCEL:
				CloseColorWindow(FALSE);
				return(FALSE);
				break;
			case COLOR_COPY:
				ColorMode = COPYCOLOR;
				break;
			case COLOR_RANGE:
				ColorMode = RANGE_FIRST;
				break;
		}
		return(TRUE);
}


ModifyColors()
{
	USHORT pen, newred, newgreen, newblue;

	pen = w->RPort->FgPen;

	newred = ((struct PropInfo *)
	ColorTemplateGadgets[COLOR_RED].SpecialInfo)->HorizPot >> 12;
	newgreen = ((struct PropInfo *)
	ColorTemplateGadgets[COLOR_GREEN].SpecialInfo)->HorizPot >> 12;
	newblue = ((struct PropInfo *)
	ColorTemplateGadgets[COLOR_BLUE].SpecialInfo)->HorizPot >> 12;

	SetRGB4(vp, pen, newred, newgreen, newblue);
}



DrawColorWindow()
{
	struct RastPort *RPort;

	RPort = ColorWindow->RPort;

	ColorRectFill(RPort, rp->FgPen);
	SetAPen(RPort, 1);
	DrawBox(RPort, 1, 1, COLORWINDOW_WIDTH - 2, COLORWINDOW_HEIGHT - 2);
	DrawBox(RPort, COLOR_BOX_LEFT - 2, COLOR_BOX_TOP - 2,
	COLOR_BOX_RIGHT + 2, COLOR_BOX_BOTTOM + 2);
	DrawBox(RPort, COLOR_BOX_LEFT - 2, COLOR_COLOR_TOP - 2,
	COLOR_BOX_LEFT + (8 * 15) + 1, COLOR_COLOR_TOP + (4 * 10) + 1);
}



SetColorProps()
{
	USHORT rgb, red, green, blue;

	rgb = GetRGB4(vp->ColorMap, rp->FgPen);
	red = (rgb >> 8) & 0xF;
	green = (rgb >> 4) & 0xF;
	blue = (rgb >> 0) & 0xF;

	((struct PropInfo *)ColorTemplateGadgets[COLOR_RED]
	.SpecialInfo)->HorizPot = (red << 12) | (red << 8) | (red << 4) | red;
	((struct PropInfo *)ColorTemplateGadgets[COLOR_GREEN]
	.SpecialInfo)->HorizPot = (green << 12) | (green << 8) | (green << 4) | green;
	((struct PropInfo *)ColorTemplateGadgets[COLOR_BLUE]
	.SpecialInfo)->HorizPot = (blue << 12) | (blue << 8) | (blue << 4) | blue;
}


ColorRectFill(RPort, pen)
struct RastPort *RPort;
SHORT pen;
{
	SetAPen(RPort, pen);
	SetDrMd(RPort, JAM2);
	WaitBOVP(vp);
	RectFill(RPort, COLOR_BOX_LEFT, COLOR_BOX_TOP,
	COLOR_BOX_RIGHT, COLOR_BOX_BOTTOM);
}


VOID DoColorWindow()
{
	struct IntuiMessage *message;
	ULONG class;
	struct Gadget *gadget;

	if (NOT OpenColorWindow())
		return;

	for (EVER) {
		Wait((1 << ColorWindow->UserPort->mp_SigBit));
		while (message = (struct IntuiMessage *)GetMsg(ColorWindow->UserPort)) {
			class = message->Class;
			gadget = (struct Gadget *)(message->IAddress);
			ReplyMsg(message);

			switch (class) {
				case GADGETDOWN:
				case GADGETUP:
					if (ColorGadgetGotten(gadget) == FALSE)
						return;
					break;
				case MOUSEMOVE:
					ModifyColors();
					break;
			}
		}
	}
}


InitSuperColors()
{
	SHORT i;

	/* OK, initialize those Super Color Gadgets! */
	for (i = 0; i < 32; i++) {
		SuperColorImages[i].LeftEdge = 0;
		SuperColorImages[i].TopEdge = 0;
		SuperColorImages[i].Width = 15;
		SuperColorImages[i].Height = 10;
		SuperColorImages[i].Depth = 0;
		SuperColorImages[i].ImageData = NULL;
		SuperColorImages[i].PlanePick = 0;
		SuperColorImages[i].PlaneOnOff = i;
		SuperColorImages[i].NextImage = NULL;
	}
}
