/*
 * $RCSfile: gi.cpp $
 *
 * $Author: marcel $
 *
 * $Revision: 1.8 $
 *
 * $Date: 1995/05/15 10:51:12 $
 *
 * $Locker: marcel $
 *
 * $State: Exp $
 *
 * Amiga version
 *
 * Copyright © 1995 Marcel Offermans
 *
 * tabsize = 5
 */

/* includes */
#include <exec/types.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/diskfont.h>
#include <proto/asl.h>
#include <graphics/gfxmacros.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "gi.h"

/* prototypes */
int round(double);

/* macros */
#define RGB24(r,g,b) (r << 24),(g << 24),(b << 24)

/* size of the font in pixels: you can't change this without seriously messing up the display */
const int					CHR_HGT_PIX		= 10;
const int					CHR_WID_PIX		= 9;

/* globals */
BOOL						available			= FALSE;
double					SCALE;
double					CHR_HGT;
double					CHR_WID;
static int				maxx, maxy;
static int				tran_table[]		= {8,9,10,11,12,13,14,15,0,1,2,3,4,5,6,7};
struct Screen *			screen_ptr		= NULL;
struct Window *			window_ptr		= NULL;
struct RastPort *			rp_ptr			= NULL;
PLANEPTR					plane_ptr			= NULL;
USHORT					areapattern_ptr[]	= {0x0000};
struct TextAttr			textattr			= {"topaz.font", 8, FS_NORMAL, FPF_ROMFONT};
struct TmpRas				tmpras;
ULONG					colortable[]		= {16L<<16 + 0,
	RGB24(128, 128, 128),
	RGB24(000, 000, 255),
	RGB24(000, 255, 000),
	RGB24(000, 255, 255),
	RGB24(255, 000, 000),
	RGB24(255, 000, 255),
	RGB24(255, 255, 000),
	RGB24(255, 255, 255),
	RGB24(000, 000, 000),
	RGB24(000, 000, 180),
	RGB24(000, 180, 000),
	RGB24(000, 180, 180),
	RGB24(180, 000, 000),
	RGB24(180, 000, 180),
	RGB24(180, 180, 000),
	RGB24(180, 180, 180),
	0};
struct colors			car_clrs[] = {
	{oWHITE,		oWHITE},
	{oRED,		oWHITE},
	{oBLACK,		oYELLOW},
	{oGREEN,		oWHITE},
	{oWHITE,		oMAGENTA},
	{oBLUE,		oBLUE},
	{oBLUE,		oWHITE},
	{oYELLOW,		oYELLOW},
	{oRED,		oRED},
	{oBROWN,		oCYAN},
	{oCYAN,		oCYAN},
	{oBLACK,		oLIGHTMAGENTA},
	{oBLACK,		oBLACK},
	{oGREEN,		oGREEN},
	{oBROWN,		oYELLOW},
	{oMAGENTA,	oLIGHTGREEN},
};

/* closes the graphical display screen */
void resume_normal_display(void)
{
	/* reset the available flag to suppress graphics output */
	available = FALSE;

	if (plane_ptr)
	{
		FreeRaster(plane_ptr, window_ptr->Width, window_ptr->Height);
		plane_ptr = NULL;
	}
	if (window_ptr)
	{
		CloseWindow(window_ptr);
		window_ptr = NULL;
	}
	if (screen_ptr)
	{
		CloseScreen(screen_ptr);
		screen_ptr = NULL;
	}
}

long xcon(double x)
{
   return((long)(round(x / SCALE)));
}

long ycon(double y)
{
   return((long)(maxy - round(y / SCALE)));
}

void draw_line(double x0, double y0, double x1, double y1)
{
	if (!available)
	{
		return;
	}

	Move(rp_ptr, xcon(x0), ycon(y0));
	Draw(rp_ptr, xcon(x1), ycon(y1));
}

void rectangle(double ulx, double uly, double lrx, double lry)
{
	if (!available)
	{
		return;
	}

	RectFill(rp_ptr, xcon(ulx), ycon(uly), xcon(lrx), ycon(lry));
}

void set_color(int our_color)
{
	if (!available)
	{
		return;
	}

	SetAPen(rp_ptr, tran_table[our_color]);
}

void set_fill_color(int our_color)
{
	if (!available)
	{
		return;
	}

	SetBPen(rp_ptr, tran_table[our_color]);
}

void flood_fill(double X, double Y)
{
	if (!available)
	{
		return;
	}

	Flood(rp_ptr, 1, xcon(X), ycon(Y));
}

void text_output(double X, double Y, char *source)
{
	if (!available)
	{
		return;
	}

	SetDrMd(rp_ptr, JAM1);
	Move(rp_ptr, xcon(X), ycon(Y) + 6);
	Text(rp_ptr, source, strlen(source));
	SetDrMd(rp_ptr, JAM2);
}

void initialize_graphics(void)
{
	/* open a screen */
	if (screen_ptr = OpenScreenTags(NULL,
		SA_Depth,			scrdepth,
		SA_Width,			scrwidth,
		SA_Height,		scrheight,
		SA_DisplayID,		scrid,
		SA_Overscan,		scroscantype,
		SA_AutoScroll,		scrautoscroll,
		SA_Type,			CUSTOMSCREEN | SCREENQUIET,
		SA_ShowTitle,		FALSE,
		SA_Colors32,		colortable,
		SA_Font,			&textattr,
		TAG_DONE))
	{
		if (window_ptr = OpenWindowTags(NULL,
			WA_CustomScreen,	screen_ptr,
			WA_Backdrop,		TRUE,
			WA_Borderless,		TRUE,
			WA_Activate,		TRUE,
			WA_IDCMP,			IDCMP_VANILLAKEY,
			TAG_DONE))
		{
			/* set the rastport pointer */
			rp_ptr = window_ptr->RPort;

			/* try to allocate a bitplane for the flood filling operation */
			if (plane_ptr = AllocRaster(window_ptr->Width, window_ptr->Height))
			{
				InitTmpRas(&tmpras, plane_ptr, RASSIZE(window_ptr->Width, window_ptr->Height));
				rp_ptr->TmpRas = &tmpras;
				/* set up the patterns for the pens */

				/* jam 2 colors onto the screen when drawing */
				SetDrMd(rp_ptr, JAM2);

				/* set the area fill pattern */
				SetAfPt(rp_ptr, areapattern_ptr, 0);

				/* set the pen that is used for lines and arcs to initial color */
				SetAPen(rp_ptr, 1);

				/* set the pen that is used for filling areas to initial color */
				SetBPen(rp_ptr, 2);

				/* set up some variables that are needed for the feet to pixel conversions */
				maxx = window_ptr->Width - 1;
				maxy = window_ptr->Height - 1;

				/* determine the distance in feet that each pixel will represent */
				SCALE = X_MAX / (double)maxx;
				if (Y_MAX / (double)maxy > SCALE)
				{
					SCALE = Y_MAX / (double)maxy;
					X_MAX = maxx * SCALE;
				}
				else
				{
					Y_MAX = maxy * SCALE;
				}

				/* compute character width and height in feet */
				CHR_HGT = CHR_HGT_PIX * SCALE;
				CHR_WID = CHR_WID_PIX * SCALE;

				/* set the IDCMP bit mask */
				idcmpmask = 1L << window_ptr->UserPort->mp_SigBit;

				/* add an exit trap which cleans up this screen and window */
				atexit(resume_normal_display);

				/* set the available flag so the GI knows it can draw */
				available = TRUE;
			}
		}
	}
}
