#include "ownincs/VT340console.h"


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





VOID DeleteRaster(struct VT340Console *con)
{
	if(con->text_raster)
	{
		FreeMem(con->text_raster, (con->raster_width * con->raster_height) << 1);
		con->text_raster = NULL;
	}

	if(con->erase_raster)
	{
		FreeMem(con->erase_raster, (con->raster_width * con->raster_height) << 1);
		con->erase_raster = NULL;
	}
}


BOOL CreateRaster(struct VT340Console *con)
{
	con->raster_width	 = con->io->xem_window->Width >> 3;
	con->raster_height = con->io->xem_window->Height >> 3;

	con->text_raster = (UBYTE *)AllocMem((con->raster_width * con->raster_height) << 1, MEMF_PUBLIC|MEMF_CLEAR);
	if(con->text_raster == NULL)
		return(FALSE);

	con->erase_raster = (UBYTE *)AllocMem((con->raster_width * con->raster_height) << 1, MEMF_PUBLIC|MEMF_CLEAR);
	if(con->erase_raster == NULL)
		return(FALSE);

	return(TRUE);
}


VOID RasterEraseScreen(struct VT340Console *con, UWORD mode)
{
	UWORD first, last;

	switch(mode)
	{
		default:
		case 0:		/* cursor to end of screen, inclusive */
			first	= (con->row - 1) * con->raster_width + (con->col-1);
			last	= (con->lastline - 1) * con->raster_width - 1;
		break;

		case 1:		/* start of screen to cursor, inclusive */
			first = (con->firstline - 1) * con->raster_width;
			last	= (con->row - 1) * con->raster_width + (con->col - 1); 
		break;

		case 2:		/* entire screen */
			first	= (con->firstline - 1) * con->raster_width;
			last	= (con->lastline - 1) * con->raster_width - 1;
		break;

	}

	memset(&con->text_raster[first], ' ', last - first);
	memset(&con->erase_raster[first], ERASEABLE, last - first);
}


VOID RasterEraseLine(struct VT340Console *con, UWORD mode)
{
	UWORD first, last;

	switch(mode)
	{
		default:
		case 0:		/* cursor to end of line, inclusive */
			first	= (con->row-1) * con->raster_width + (con->col-1);
			last	= con->row * con->raster_width;
		break;

		case 1:		/* start of line to cursor, inclusive */
			first	= (con->row-1) * con->raster_width;
			last	= first + con->col;
		break;

		case 2:		/* entire line */
			first	= (con->row-1) * con->raster_width;
			last	= first + con->raster_width;
		break;

	}

	memset(&con->text_raster[first], ' ', last - first);
	memset(&con->erase_raster[first], ERASEABLE, last - first);
}


VOID RasterSelectiveEraseScreen(struct VT340Console *con, UWORD mode)
{
	UWORD first, last, s_row, i;

	switch(mode)
	{
		default:
		case 0:		/* cursor to end of screen, inclusive */
			RasterSelectiveEraseLine(con, 0);
			if(con->row == con->lastline)
				return;
			first	= con->row + 1;
			last	= con->lastline + 1;
		break;

		case 1:		/* start of screen to cursor, inclusive */
			RasterSelectiveEraseLine(con, 1);
			if(con->row == 1)
				return;
			first = con->firstline;
			last	= con->row;
		break;

		case 2:		/* entire screen */
			first = con->firstline;
			last	= con->lastline + 1;
		break;

	}

	s_row = con->row;
	for(i=first; i<last; i++)
	{
		con->row = i;
		RasterSelectiveEraseLine(con, 2);
	}
	con->row = s_row;
}


VOID RasterSelectiveEraseLine(struct VT340Console *con, UWORD mode)
{
	UWORD first, cnt, prevpos, chars, i, s_col;
	BOOL erase;
	UBYTE *rasterptr;

	switch(mode)
	{
		default:
		case 0:		/* cursor to end of line, inclusive */
			first	= con->col - 1;
			cnt	= con->raster_width;
		break;

		case 1:		/* start of line to cursor, inclusive */
			first	= 0;
			cnt	= con->col;
		break;

		case 2:		/* entire line */
			first	= 0;
			cnt	= con->raster_width;
		break;

	}

	chars = 0; 
	prevpos = first + 1;
	erase = FALSE;
	rasterptr = &con->erase_raster[(con->row-1) * con->raster_width];

	for(i=first; i<cnt; i++)
	{
		if(rasterptr[i] == ERASEABLE)
		{
			chars++;
			if(erase == FALSE)
			{
				erase = TRUE;
				prevpos = i + 1;
			}
		}
		else
		{
			erase = FALSE;
			if(chars)
			{
				s_col = con->col;
				con->col = prevpos;
				RasterEraseCharacters(con, chars);
				con->col = s_col;
				chars = 0;
			}
		}
	}

	if(chars)
	{
		s_col = con->col;
		con->col = prevpos;
		RasterEraseCharacters(con, chars);
		con->col = s_col;
	}

	s_col = con->col;
	con->col = first + 1;
	RasterGetLine(con);
	con->col = s_col;
}


VOID RasterEraseCharacters(struct VT340Console *con, UWORD chars)
{
	UWORD first;

/* Error-Checking MUSS im Caller geschehen, da diese Routine nicht weiss,
   wie breit der Screen ist!  Bsp: siehe VT340_erasechars() */

	first	= (con->row-1) * con->raster_width + (con->col-1);
	memset(&con->text_raster[first], ' ', chars);
	memset(&con->erase_raster[first], ERASEABLE, chars);
}


VOID RasterScroll_V(struct VT340Console *con, WORD direction, UWORD top, UWORD bot)
{
	UWORD lines, diff, max;

/* top & bot zählen von null an */

	diff	= abs(direction);

	if(top + diff > bot)
		diff = bot - top;


	lines = bot - top - diff;
	max	= lines * con->raster_width;

	if(direction < 0)	/* scroll up */
	{
		UWORD first, last, i;
		UBYTE *e_firstptr, *e_lastptr;
		UBYTE *t_firstptr, *t_lastptr;

		first	= (top + lines) * con->raster_width - 1;
		last	= (top + lines + diff) * con->raster_width - 1;

		e_firstptr	= &con->erase_raster[first];
		e_lastptr	= &con->erase_raster[last];
		t_firstptr	= &con->text_raster[first];
		t_lastptr	= &con->text_raster[last];
		i = 0;
		while(i++ < max)
		{
			*e_lastptr-- = *e_firstptr--;
			*t_lastptr-- = *t_firstptr--;
		}
		memset(&con->text_raster[top * con->raster_width], ' ', diff * con->raster_width);
		memset(&con->erase_raster[top * con->raster_width], ERASEABLE, diff * con->raster_width);
	}
	else	/* scroll down */
	{
		UWORD first, last, i;
		UBYTE *e_firstptr, *e_lastptr;
		UBYTE *t_firstptr, *t_lastptr;

		first	= top * con->raster_width + (con->raster_width * diff);
		last	= top * con->raster_width;

		e_firstptr	= &con->erase_raster[first];
		e_lastptr	= &con->erase_raster[last];
		t_firstptr	= &con->text_raster[first];
		t_lastptr	= &con->text_raster[last];
		i = 0;
		while(i++ < max)
		{
			*e_lastptr++ = *e_firstptr++;
			*t_lastptr++ = *t_firstptr++;
		}
		memset(&con->text_raster[(bot - diff) * con->raster_width], ' ', diff * con->raster_width);
		memset(&con->erase_raster[(bot - diff) * con->raster_width], ERASEABLE, diff * con->raster_width);
	}
}


VOID RasterScroll_H(struct VT340Console *con, WORD direction, UWORD row, UWORD col)
{
	UWORD diff, max, top;

	diff = abs(direction);
	if(col + diff > con->raster_width)
		diff = con->raster_width - col;

	top	= row * con->raster_width; 
	max	= con->raster_width - col - diff;

	if(direction < 0)	/* scroll right */
	{
		UWORD first, last, i;
		UBYTE *e_firstptr, *e_lastptr;
		UBYTE *t_firstptr, *t_lastptr;

		first	= con->raster_width - diff - 1;
		last	= con->raster_width - 1;

		e_firstptr	= &con->erase_raster[top + first];
		e_lastptr	= &con->erase_raster[top + last];
		t_firstptr	= &con->text_raster[top + first];
		t_lastptr	= &con->text_raster[top + last];
		i = 0;
		while(i++ < max)
		{
			*e_lastptr-- = *e_firstptr--;
			*t_lastptr-- = *t_firstptr--;
		}
		memset(&con->text_raster[top + col], ' ', diff);
		memset(&con->erase_raster[top + col], ERASEABLE, diff);
	}
	else	/* scroll left */
	{
		UWORD first, last, i;
		UBYTE *e_firstptr, *e_lastptr;
		UBYTE *t_firstptr, *t_lastptr;

		first	= col + diff;
		last	= col;

		e_firstptr	= &con->erase_raster[top + first];
		e_lastptr	= &con->erase_raster[top + last];
		t_firstptr	= &con->text_raster[top + first];
		t_lastptr	= &con->text_raster[top + last];
		i = 0;
		while(i++ < max)
		{
			*e_lastptr++ = *e_firstptr++;
			*t_lastptr++ = *t_firstptr++;
		}
		memset(&con->text_raster[top + con->raster_width - diff], ' ', diff);
		memset(&con->erase_raster[top + con->raster_width - diff], ERASEABLE, diff);
	}
}


VOID RasterPutString(struct VT340Console *con, UBYTE *string, UWORD length, UWORD x)
{
	ULONG line_pos;

	line_pos = (con->row-1) * con->raster_width + x;

	if(length == -1)
		length = strlen(string);

	if(length == 1)
	{
		if(x <= con->raster_width - 1)
		{
			con->text_raster[line_pos] = string[0];
			con->erase_raster[line_pos] = con->DECSCA;
		}
	}
	else
	{
		if(x + length >= con->raster_width - 1)
			length = con->raster_width - 1 - x;

		CopyMem(string, &con->text_raster[line_pos], length);
		memset(&con->erase_raster[line_pos], con->DECSCA, length);
	}
}


VOID RasterGetLine(struct VT340Console *con)
{
	UWORD chars;
	UBYTE width;

	chars = con->raster_width;
	width	= *(con->rows + con->row);
	if(width)
		chars >>= 1;

	Move(con->rp, 0, con->row * con->ysize - (FONT_YSIZE - BOTLINE));
	Text(con->rp, &con->text_raster[(con->row-1) * con->raster_width], chars);

	if(width)
		VT220_stretch(con->rp, 0, (con->row - 1) * con->ysize, con->width>>1, con->ysize, width);
}



/* end of source-code */
