/************
 *
 * Includes:
 *
 ************/

#include <exec/types.h>
#include <intuition/intuition.h>
#include "src/Editor.h"

/***********
 *
 * Defines:
 *
 ***********/

#define CR 13
#define LF 10
#define TAB 9

/**********************
 *
 * External Functions:
 *
 **********************/

void SetAPen(),RectFill(),Text(),Move();
struct Zline *nextLine();

/*********************
 *
 * External Variables:
 *
 *********************/ 

extern struct Editor *actualEditor;

/***************
 *					*
 * Functions: *
 *					*
 ***************/

/**********************************
 *
 * initWindowSize(ed)
 *
 * Initializes the width/height
 * statement of the actual windows.
 * Restores the zlineptr field
 *   .
 *
 * ed ^ Editor structure.
 *
 **********************************/

void initWindowSize	  (ed)
register struct Editor *ed;
{
	register struct Window *w;
	register struct RastPort *rp;
	register struct Zline *z,**zptr;
	register UWORD n,newh;

	w	= ed->window;
	rp = ed->rp;

	ed->xoff = (UWORD)w->BorderLeft;
	ed->yoff = (UWORD)w->BorderTop;

	ed->cw	= (rp->TxWidth)? rp->TxWidth : 8;
	ed->ch	= (rp->TxHeight)? rp->TxHeight : 8;

	ed->wcw	= (w->Width - ed->xoff - w->BorderRight) / ed->cw;
	newh		= (w->Height- ed->yoff - w->BorderBottom)/ ed->ch;

	ed->xrl	= ed->xoff + ed->wcw*ed->cw;
	ed->xrr	= w->Width - w->BorderRight - 1;
	ed->yru	= w->Height - w->BorderBottom - 1;
	ed->bl	= rp->TxBaseline;

	/* Now restore the zlineptr field: */
	if (newh != ed->wch)
	{
		if (newh < ed->wch)
		{
			/* Pointer to Null set: */
			zptr = ed->zlinesptr + newh + 1;
			for (n = newh; n < ed->wch; n++)
				*zptr++ = NULL;
		}
		else
		{
			zptr	= ed->zlinesptr + ed->wch;
			z		= *zptr++;
			for (n = ed->wch; n < newh; n++)
				*zptr++ = (z = nextLine(z));
		}

		ed->wch = newh;
	}
}

/****************************************
 *
 * convertLineForPrint(line,len,buf)
 *
 * Convert line so that this can be
 * displayed simply.
 * Tabs converted into spaces
 *   
 *
 * line ^ Zline.
 * len = the length.
 * w = maximum wiidth.
 * buf ^buffer, in which the converted line
 *			 is stored.
 *
 ****************************************/

void convertLineForPrint(line,len,w,buf)
UBYTE							*line;
register WORD						 len;
register UWORD						  w;
register UBYTE						*buf;
{
	register UBYTE *tab;
	register UWORD l = 1;
	register UBYTE lastchar;

	/* determine if ends with CR or LF: */
	if (len)
	{
		tab = line + len - 1;
		if (*tab == CR)
		{
			len--;
			lastchar = ' ';
		}
		else if (*tab == LF)
		{
			len--;
			lastchar = ' ';
			if ((len) && (*--tab == CR))
				len--;
		}
		else
			lastchar = 183;
	}
	else
		lastchar = 183;

	/* Zline convert: */
	tab = actualEditor->tabstring;
	while ((len--) && (l < w))
		if ((*buf = *line++) == TAB)
			do
			{
				*buf++ = ' ';
				l++;
				tab++;
			} while ((*tab) && (l < w));
		else
		{
			buf++;
			tab++;
			l++;
		}

	/* determine if the line is not completely converted: */
	if (len >= 0)
		lastchar = 183;

	/* line filled from last character to end: */
	while (l++ <= w)
		*buf++ = lastchar;
}

/************************************
 *
 * printAt(buf,len,x,y)
 *
 *Prive character string buf a position
 * (x,y) in a window. The character-
 * string is changed!
 *
 * buf ^ character sring.
 * len = the length.
 * x = Pixel-X-Position.
 * y = Pixel-Y-Position.
 *
 ************************************/

void printAt	(buf,len,x,y)
register UBYTE	*buf;
WORD					  len;
register UWORD				x,y;
{
	struct RastPort *rp = actualEditor->rp;
	register UWORD cw = actualEditor->cw;
	register UWORD x2;
	UWORD y2 = y + actualEditor->ch - 1;
	UBYTE *ptr;
	ULONG l;

	while (len > 0)
		if (*buf == ' ')
		{
			/* output spaces: */
			x2 = x - 1;

			while ((*buf == ' ') && len--)
			{
				buf++;
				x2 += cw;
			}

			SetAPen(rp,BGPEN);
			RectFill(rp,(ULONG)x,(ULONG)y,(ULONG)x2,(ULONG)y2);
			SetAPen(rp,FGPEN);

			x = ++x2;
		}
		else
		{
			/* Also output text: */
			Move(rp,(ULONG)x,(ULONG)y + actualEditor->bl);
			ptr = buf;

			if (CONTROLCODE(*buf))
			{
				SetAPen(rp,CTRLPEN);

				while (CONTROLCODE(*buf) && len--)
					*buf++ |= 64;
				l = buf - ptr;
				Text(rp,ptr,l);

				SetAPen(rp,FGPEN);
			}
			else
			{
				while (!CONTROLCODE(*buf) && (*buf != ' ') && len--)
					buf++;
				l = buf - ptr;
				Text(rp,ptr,l);
			}
			x += cw*l;
		}
}

/************************************
 *
 * printLine(line,y)
 *
 * Displays Zline at pixel position
 *y on the screen.
 *
 * line ^ Zline structure.
 * y = pixel positon.
 *
 ************************************/

void printLine			 (line,y)
register struct Zline *line;
register UWORD					  y;
{
	static UBYTE buf[MAXWIDTH];
	register UWORD w;

	convertLineForPrint(line+1,line->len,w = actualEditor->wcw,buf);
	printAt(buf,w,actualEditor->xoff,y);
}

/**********************************
 *
 * printAll
 *
 * redisplays the entire screen.
 *
 **********************************/

void printAll()
{
	register UWORD y,ch,count;
	register struct Zline **z;
	register struct RastPort *rp;

	y		= actualEditor->yoff;
	ch		= actualEditor->ch;
	count	= actualEditor->wch;
	rp		= actualEditor->rp;

	/* Output the line: */
	for (z = actualEditor->zlinesptr; count-- && (*z != NULL);
			z++, y += ch)
		printLine(*z,y);

	/* erase right and bottom border: */
	SetAPen(rp,BGPEN);
	if (actualEditor->yru >= y)
		RectFill(rp,(ULONG)actualEditor->xoff,(ULONG)y,
						(ULONG)actualEditor->xrr,(ULONG)actualEditor->yru);
	if ((actualEditor->xrr >= actualEditor->xrl)
		&& (y > actualEditor->yoff))
		RectFill(rp,(ULONG)actualEditor->xrl,(ULONG)actualEditor->yoff,
						(ULONG)actualEditor->xrr,(ULONG)y-1);
	SetAPen(rp,FGPEN);
}
