/************
 *
 * 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;

/*********************
 *
 * Global Variables:
 *
 *********************/ 

UWORD SplitDec = 0;

/***************
 *					*
 * 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;
	UWORD znr,*pnr;

	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++;
			pnr	= &(ed->zlinesnr[ed->wch]);
			znr	= *pnr++;
			for (n = ed->wch; n < newh; n++)
			{
				*zptr++	= (z = nextLine(z,&znr));
				*pnr++	= znr;
			}
		}

		ed->wch = newh;
	}

	/* Top/bottom border for scrolling: */
	ed->xscr = ed->xoff + ed->wcw*ed->cw - 1;
	ed->yscr = ed->yoff + ed->wch*ed->ch - 1;
}

/****************************************
 *
 * 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, skip = actualEditor->leftpos;
	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
			{
				tab++;
				if (skip)
					skip--;
				else
				{
					l++;
					*buf++ = ' ';
				}
			} while ((*tab) && (l < w));
		else
		{
			tab++;
			if (skip)
				skip--;
			else
			{
				l++;
				buf++;
			}
		}

	/* 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,fgpen)
 *
 * Print 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.
 * fgpen = Foreground color (Folding)
 *
 ************************************/

void printAt	(buf,len,x,y,fgpen)
register UBYTE	*buf;
WORD					  len;
register UWORD				x,y;
ULONG								 fgpen;
{
	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;
	register struct Zline *z;
	register ULONG pen;

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

	/* If start/end marker of fold => FOLDPEN */
	if (line->flags & ZLF_FSE)
	{
		if ((z = line->succ)->succ)
		{
			if ((z->flags & ZLF_FOLD) <= actualEditor->maxfold)
			{
				SetAPen(actualEditor->rp,FOLDPEN);
				pen = FOLDPEN;
			}
			else
				pen = FGPEN;
		}
		else
		{
			SetAPen(actualEditor->rp,FOLDPEN);
			pen = FOLDPEN;
		}

		printAt(buf,w - SplitDec,actualEditor->xoff,y,pen);

		/* Old write color first again: */
		if (pen != FGPEN)
			SetAPen(actualEditor->rp,FGPEN);
	}
	else
		printAt(buf,w - SplitDec,actualEditor->xoff,y,FGPEN);
}

/**********************************
 *
 * printAll
 *
 * Print new screen out.
 *
 **********************************/

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);
}
