/*************************************************
* Function to do tek 4010 graphics and mode
* switching, the function returns TRUE if it
* uses the character else the
* character can be used for something else
*************************************************/

#include "ownincs/VT340console.h"


/* allowed globals.. */
struct	ExecBase			*SysBase;
struct	DosLibrary		*DOSBase;
struct	GfxBase			*GfxBase;
struct	IntuitionBase	*IntuitionBase;

                /* TEK Funktionen zu VT340 Emulator.. */

/* macros.. */

#define COLOR(i, j, k, l) SetRGB4(&con->TEKscreen->ViewPort, i, j, k, l)
#ifndef max
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<=(b)?(a):(b))
#endif

/* this macro puts the tek screen at the back
 * and sets things so that the user gets the
 * non-tek mode of operation, there are some problems here
 * as we do not use intuition to control window positions */

/* the screen size */
#define xmin 0
#define ymin 0 
#define xmax 640		/* changed from old tek version		*/
#define ymax 400
#define COLORSET 1024

STATIC VOID TEK_off(struct VT340Console *);
STATIC VOID TEK_reset(struct VT340Console *);


BOOL TEK_parse(struct VT340Console *con, UBYTE c)
{
#define dx 8
#define dy 10

/*
	if(!con->inTEK)
	{
		if(c == GS)
		{
			con->inTEK = TRUE;
			if(con->TEKscreen)
			{
				ScreenToFront(con->TEKscreen);
				con->TEKmainmode = MOVE;
			}
		}
		return((BOOL)con->inTEK); /* i.e. if c == GS we used it and can leave */
	}
*/

/* first handle case if graph is sent without having the tek screen
 * turned on; just eat the graphics commands until the graph is
 * finished - then turn back to text mode
 * also make this selanar compatible
 */
	if(con->TEKscreen == NULL)
	{  
		if(c == CAN  ||  (con->TEKlastc == ESC  &&  c == '2'))
			con->inTEK = FALSE;	 /* turn tek mode off	*/
		con->TEKlastc = c;
		return(TRUE);
	}

/*
	if(con->TEKmode == ALPHA)
	{
		emit(c);
		emit(CR);
		emit(LF);
	}
*/

	if(con->TEKescmode)
	{
		if(con->TEKcolormode)
		{
			c = c - '0';
			con->TEKcolormode++;

			switch(con->TEKcolormode)
			{
				case 2:
					con->TEKcolorindex = c;
				break;

				case 3:
					con->TEKred = c;
				break;

				case 4:
					con->TEKgreen = c;
				break;

				case 5:
					COLOR(con->TEKcolorindex, con->TEKred, con->TEKgreen, (ULONG)c);
					con->TEKcolormode = FALSE;
					con->TEKescmode = FALSE;
				break;

			}
			return((BOOL)con->inTEK);
		}

		switch(c)
		{
	    /* Selanar Compatable graphics terminator */
			case '2':
 				TEK_off(con);
				con->TEKboxmode = FALSE;
			break;

		/* I do not know what the tek 4100 area fill commands are so I made-up
 			my own, this will not harm the line drawing mode. */
			case 'A':
				con->TEKboxmode = TRUE;
			break;

			case 'B':
				con->TEKboxmode = FALSE;
			break;

			case 'Q':
				con->TEKcolormode = 1;
			return((BOOL)con->inTEK);

		/* another one of my own commands */
			case 'R':
			/* reset to default then clear screen */
				TEK_reset(con);
				con->TEKapen = 1;

			case FF:
				/* clear page */
 				con->TEKx = xmin;
				con->TEKy = ymin + dy;
				con->TEKmainmode = ALPHA;
				con->TEK4100 = NUL;
				SetRast(con->TEKrp, 0);
			break;

		/* looks like a 4100 command */
			case 'M':
				con->TEK4100 = 'M';
			break;
		}
		con->TEKescmode = FALSE;
	}
	else
	{
		if(con->TEK4100 != NUL)
		{
			if(con->TEK4100 == COLORSET)
				con->TEKapen = c - '0';
			SetAPen(con->TEKrp, con->TEKapen);
	  
			if(con->TEK4100 == 'M'  &&  c == 'L')  
				con->TEK4100 = COLORSET;
			else
				con->TEK4100 = NUL;
		}
		else
		{
			if(c >= ' ')
			{
				if(con->TEKmainmode == ALPHA)
				{
					if(con->TEKlastx > xmax-dx)
						con->TEKlastx = xmax-dx;

					if(con->TEKlastx < xmin)
						con->TEKlastx = xmin;

					if(con->TEKlasty < ymin+dy)
						con->TEKlasty = ymin+dy;

					if(con->TEKlasty > ymax)
						con->TEKlasty = ymax;

					SetAPen(con->TEKrp, 1);
					Move(con->TEKrp, con->TEKlastx, con->TEKlasty);
					Text(con->TEKrp, &c, 1);
					SetAPen(con->TEKrp, con->TEKapen);
					con->TEKlastx += dx;
					if(con->TEKlastx > xmax)
						con->TEKlastx = xmax;		
				}
				else
				{
				/* a note here about 4014 graphics, If your graphics software
					drives a Tek 4014 then this will work perfecly well, you
					just will not be able to use the 4096 pixel resolution
					that that big storage tube device offers */

					ULONG tag, data, x, y;

					tag = c >> 5;
					data = c - (tag << 5);

					switch(tag)
					{
						case 1:
							if(con->TEKlastval == 3)
								con->TEKhix = data << 5;
							else
								con->TEKhiy = data << 5;
						break;

						case 2:
						{
						/* low x always sent so don't save it */
							x = con->TEKhix + data;
							y = con->TEKhiy + con->TEKloy;

							if(!con->TEKscale)
							{
							/*
								x = (((float)x)*xmax)/1024;
								y = (((float)y)*ymax)/780;
							*/
								x = (x * xmax) / 1024;
								y = (y * ymax) / 780;
	       				}
	       				x = con->TEKx / (2 - con->TEKlace);
							y = (ymax - 1) - (con->TEKy / (2 - con->TEKlace));

							if(x > xmax)
								x = xmax;
							if(x < xmin)
								x = xmin;

							if(y > ymax)
								y = ymax;
							if(y < ymin)
								y = ymin;

							switch(con->TEKmainmode)
	     					{
								case MOVE:
									con->TEKmainmode = LINE;
									Move(con->TEKrp, x, y);
								break;

								case LINE:
									if(con->TEKboxmode)
										RectFill(con->TEKrp,
														min(con->TEKlastx, x), 
														min(con->TEKlasty, y),
														max(con->TEKlastx, x),
														max(con->TEKlasty, y));
	        						else
										Draw(con->TEKrp, x, y);
	     							break;

								case POINT:
									WritePixel(con->TEKrp, x, y);
	      					break;

							}
							con->TEKlastx = x;
							con->TEKlasty = y;
	  					}
	  					break;

						case 3:
							con->TEKloy = data;
						break;
					}
					con->TEKlastval = tag; 
				}
			}
			else
			{
				switch(c)
				{
					case BEL:
						con->io->xem_tbeep(1, 0);
					break;

					case BS:
 						con->TEKx -= dx;
						if(con->TEKx < xmin)
							con->TEKx = xmin;
 					break;

					case HT:
						con->TEKx += dx;
						if(con->TEKx > xmax)
							con->TEKx = xmax;
					break;

					case LF:
						con->TEKy += dy;
						if(con->TEKy > ymax)
							con->TEKy = ymax;
					break;

					case VT:
						con->TEKy -= dy;
						if(con->TEKy < (ymin + dy))
							con->TEKy = ymin + dy;
					break;

					case CR:
						con->TEKx = xmin;
					break;

					case CAN:
						TEK_off(con);
						con->TEKboxmode = FALSE;
					break;

					case ESC:
						con->TEKescmode = TRUE;
					break;

					case FS: /* (point-plot) */
						con->TEKmainmode = POINT;
					break;

					case GS: /* vector */
						con->TEKmainmode = MOVE;
					break;

					case US: /* alpha mode */
						con->TEKmainmode = ALPHA;
					break;

					default:
						;
					break;

				}
			}
		}
	}
	return(TRUE);
}


VOID TEK_reset(struct VT340Console *con)
{
	/* mess up the colors */
	COLOR( 0,  0,  0,  0);
	COLOR( 1, 15, 15, 15);
	COLOR( 2, 15,  0,  0);
	COLOR( 3,  0, 15,  0);
	COLOR( 4,  0,  0, 15);
	COLOR( 5,  0, 15, 15);
	COLOR( 6, 15,  0, 15);
	COLOR( 7, 15, 15,  0);
	COLOR( 8, 15,  8,  0);
	COLOR( 9,  8, 15,  0);
	COLOR(10,  0, 15,  8);
	COLOR(11,  0,  8, 15);
	COLOR(12,  8,  0, 15);
	COLOR(13, 15,  0,  8);
	COLOR(14,  5,  5,  5);
	COLOR(15, 10, 10, 10);

	SetRast(con->TEKrp, 0);
	SetAPen(con->TEKrp, 1); 
}


VOID TEK_off(struct VT340Console *con)
{
	con->inTEK = FALSE;
	ScreenToBack(con->TEKscreen);
}


BOOL TEK_open(struct VT340Console *con)
{
	STATIC struct NewScreen TekNewScreen = { 
		xmin, ymin,
		xmax, ymax, 1,
		0, 1,
		HIRES | LACE,
		CUSTOMSCREEN,
		NULL, NULL, NULL, NULL };

	STATIC struct NewWindow TekNewWindow = {
		xmin, ymin,
		xmax, ymax,
		1, 0,
		NULL,
		BORDERLESS | NOCAREREFRESH | SMART_REFRESH,
		NULL, NULL, NULL, NULL, NULL,
		0, 0, 0, 0,
		CUSTOMSCREEN };


	if(con->TEKscreen)
		return(TRUE);

	con->TEKscreen = (struct Screen *)OpenScreen(&TekNewScreen);
	if(con->TEKscreen == NULL)
		return(FALSE);

	TekNewWindow.Screen = con->TEKscreen;
	con->TEKwindow = (struct Window *)OpenWindow(&TekNewWindow);
	if(con->TEKwindow == NULL)
		return(FALSE);
	con->TEKrp = con->TEKwindow->RPort;

	con->TEKx = xmin;
	con->TEKy = ymin + dy;

	con->TEKwindow->UserPort = con->io->xem_window->UserPort;
	ModifyIDCMP(con->TEKwindow, con->io->xem_window->IDCMPFlags);

/* allow for area fill */
	InitArea(&con->TEKai, con->buffer, 100);
	con->TEKrp->AreaInfo = &con->TEKai;
	con->TEKfillras = AllocRaster(xmax, ymax);
	InitTmpRas(&con->TEKtr, con->TEKfillras, RASSIZE(xmax, ymax)); 

	TEK_reset(con);
	TEK_off(con);

	return(TRUE);
}


VOID TEK_close(struct VT340Console *con)
{
	if(con->TEKscreen == NULL)
		return;

	con->TEKmainmode = FALSE;
	FreeRaster(con->TEKfillras, xmax, ymax);
	con->TEKwindow->UserPort = NULL; /* I will not close his port */

	if(con->TEKwindow)
	{
		CloseWindow(con->TEKwindow);
		con->TEKwindow = NULL;
	}

	if(con->TEKscreen)
	{
		CloseScreen(con->TEKscreen);
		con->TEKscreen = NULL;
	}
}


