/****************************************
 *													 *
 *	Module: Edit									 *
 *													 *
 *	Functions to edit the text
 *													 *
 ****************************************/

/*#FOLD:	Includes	*/
/************
 *
 * Includes:
 *
 ************/

#include <exec/types.h>
#include <intuition/intuition.h>
#include "src/Editor.h"
/*#ENDFD*/
/*#FOLD:	Defines */
/***********
 *
 * Defines:
 *
 ***********/

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

/* Lenght of fold start and end: */
#define FSE_LEN 10
/* Number of characters, significant for fold marking: */
#define FSE_SIG 8
/*#ENDFD*/
/*#FOLD:	External Functions */
/**********************
 *
 * External Functions:
 *
 **********************/

UWORD convertLineForPrint(),strncmp(),recalcTopOfWindow();
void deleteZline(),Insert(),printAll(),restoreZlinenptr();
void DisplayBeep(),printLine(),AddHead(),scrollRight(),scrollUp();
void ScrollRaster(),printXpos(),printYpos(),printFold();
void printNumLines(),printFlags();
struct Zline *newZline(),*nextLine(),*prevLine();
BOOL cursorLeft(),cursorRight(),cursorDown(),cursorHome(),cursorEnd();
/*#ENDFD*/
/*#FOLD:	External Variables	*/
/*********************
 *
 * External Variables:
 *
 *********************/ 

extern struct Editor *actualEditor;
/*#ENDFD*/
/*#FOLD:	Global Variables	*/
/*********************
 *
 * Global Variables:
 *
 *********************/ 

UBYTE	foldStart[] =	"/*#FOLD:*/";
UBYTE foldEnde[] 	 = "/*#ENDFD*/";
/*#ENDFD*/

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

/*#FOLD:	getLineForEdit	*/
/********************************
 *
 * getLineForEdit(line,znr)
 *
 * Copy line to edit into
 * the buffer.
 *
 * line ^ Zline.
 * znr = line number of the line.
 *
 ********************************/

void getLineForEdit	 (line,znr)
register struct Zline *line;
register UWORD					  znr;
{
	register UWORD leftpos;

	/* get leftpos: */
	leftpos = actualEditor->leftpos;
	actualEditor->leftpos = 0;

	/* convert line: */
	actualEditor->buflen =
		convertLineForPrint(line+1,line->len,MAXWIDTH + 1,
			actualEditor->buffer,&actualEditor->buflastchar);

	/* mark line as  "used"  : */
	line->flags |= ZLF_USED;
	actualEditor->actual = line;
	actualEditor->bufypos = znr;

	/* establish Leftpos: */
	actualEditor->leftpos = leftpos;
}
/*#ENDFD*/
/*#FOLD:	cursorOnText */
/*******************************
 *
 * cursorOnText:
 *
 * make sure that the cursor
 * is found on text.
 *
 *******************************/

void cursorOnText()
{
	register struct Zline **zptr;
	register UWORD l;

	/* makes sure that the cursor is really on text: */
	zptr = &(ZLINESPTR(l = actualEditor->wdy));
	while ((*zptr == NULL) && l)
	{
		zptr--;
		l--;
	}
	actualEditor->wdy  = l;
	actualEditor->ypos = ZLINESNR(l);
}
/*#ENDFD*/
/*#FOLD:	deconvertLine */
/*************************
 *
 * deconvertLine():
 *
 * Deconverts line.
 *
 * buf	^ target buffer.
 * buffer^ source pointer.
 * buflen= buffer length.
 *
 *************************/

UWORD deconvertLine(buf, buffer,buflen)
UBYTE					 *buf,*buffer;
UWORD									  buflen;
{
	register UBYTE *p1,*p2,*tab,*fb = NULL;
	register WORD l;

	/* deconvert line: */
	p1 = buffer;
	p2 = buf;
	tab= actualEditor->tabstring;
	l	= buflen;

	if (actualEditor->tabs)
		/* Spaces converted to tabs: */
		while (l)
		{
			if ((*p2 = *p1++) == ' ')
			{
				if (fb == NULL)
					fb = p2;
			}
			else
			{
				if (fb)
					fb = NULL;
			}

			/* fb points to first space */
			/* other characters are copied. (first blank)	*/
			if ((! *++tab) && (fb))
			{
				*fb = TAB;
				fb++;
				p2 = fb;
			}
			else
				p2++;

			l--;
		}
	else
		while (l)
		{
			*p2 = *p1;
			p1++;
			p2++;
			l--;
		}

	/* Spaces at end deleted: */
	if (actualEditor->skipblanks)
		while ((p2 > buf) && ((*(p2-1) == ' ') || (*(p2-1) == TAB)))
			p2--;

	return ((UWORD)(p2 - buf));
}
/*#ENDFD*/
/*#FOLD:	getFoldInc */
/****************************************
 *
 * getFoldInc(line)
 *
 * Tests if line is a fold start
 * or end mark and gives 1 or -1
 * back.
 * Else a 0 is returned.
 *
 * line ^ corresponding line.
 *
 ****************************************/

UWORD getFoldInc(line)
struct Zline	 *line;
{
	register UBYTE *p1;
	register UWORD l;

	/* Fold marker at beginning of line! */
	p1 = (UBYTE *)(line + 1);
	l	= line->len;
	while (l && ((*p1 == ' ') || (*p1 == TAB)))
	{
		p1++;
		l--;
	}

	/* Type of fold markers (-> l): */
	/*	1	= Start,										*/
	/*	-1	 End and										*/
	/*	0	no fold marker. 					*/
	if (l >= FSE_SIG)
		if (strncmp(p1,foldStart,FSE_SIG) == 0)
			l = 1;
		else if (strncmp(p1,foldEnde,FSE_SIG) == 0)
			l = -1;
		else
			l = 0;
	else
		l = 0;	/* has no fold markers */

	return (l);
}
/*#ENDFD*/
/*#FOLD:	saveLine	*/
/*******************************
 *
 * saveLine(line)
 *
 * Saves line again.
 *
 * line ^ old line structure.
 *
 *******************************/

BOOL saveLine(line)
struct Zline *line;
{
	static UBYTE buf[MAXWIDTH + 2];		/* +2 fuer CR und LF */
	register UBYTE *p1,*p2,*tab,*fb = NULL;
	register WORD l,len;
	struct Zline *pred,*old,**zptr;

	/* Only for security: */
	if (actualEditor->actual == NULL)
		return (FALSE);

	/* deconvert line: */
	p2 = buf + (len = deconvertLine(buf,actualEditor->buffer,
											  actualEditor->buflen));

	/* determine if line ended with CR or LF, */
	/*  and increases len correspondingly. */
	p2 = buf + len;
	if (l = line->len)
	{
		p1 = ((UBYTE *)(line + 1)) + line->len - 1;
		if (*p1 == CR)
		{
			len++;
			*p2 = CR;
		}
		else if (*p1 == LF)
		{
			len++;
			if ((l > 1) && (*--p1 == CR))
			{
				len++;
				*p2++ = CR;
			}
			*p2 = LF;
		}
	}

	/* use new line: */
	if (EVENLEN(len) != EVENLEN(line->len))
	{
		actualEditor->lineptr =	line;	/* Garbage-Collection	*/
		if (line = newZline(len))
		{
			old =	actualEditor->lineptr;
			Insert(&actualEditor->zlines,line,old);
			line->flags = old->flags & ~ZLF_USED;
			deleteZline(old);

			/* now possible to convert pointer: */
			for (l = 0, zptr = actualEditor->zlinesptr;
					l <= actualEditor->wch; l++, zptr++)
				if (*zptr == old)
				{
					*zptr = line;
					break;
				}

			actualEditor->lineptr =	NULL;
		}
		else
		{
			actualEditor->lineptr =	NULL;
			return (FALSE);
		}
	}
	else
	{
		line->len	  = len;
		line->flags &= ~ZLF_USED;
	}

	/* write line back: */
	p1 = (UBYTE *)(line + 1);
	p2 = buf;
	l	= len;

	while (l)
	{
		*p1 = *p2;
		p1++;
		p2++;
		l--;
	}

	/* reconstruct folding: */
	/* was old or is new line a fold marker? */
	l = getFoldInc(line);
	if ((line->flags & ZLF_FSE) || l)
	{
		/* next the ZLF_FSE  flag set to 1: */
		if (l)
			line->flags |= ZLF_FSE;
		else
			line->flags &= ~ZLF_FSE;

		/* calculate how the fold level of the following lines */
		/* must be changed: level += l.				 */
		if ((old = line->succ)->succ)
		{
			if (((line->flags+1) & ZLF_FOLD) == (old->flags & ZLF_FOLD))
				/* Old line was fold start: */
				l -= 1;
			else if ((line->flags & ZLF_FOLD) == ((old->flags+1) & ZLF_FOLD))
				/* Old line was fold end: */
				l += 1;

			if (l)
			{
				/* change fold level of following lines: */
				while (old->succ)
				{
					old->flags = (old->flags & ~ZLF_FOLD)
									| ((old->flags + l) & ZLF_FOLD);
					old = old->succ;
				}

				restoreZlinenptr();
				printAll();
				cursorOnText();
				printYpos();
			}
		}
	}

	/* Display lines for security: */
	/* First calculate Ypos:			 */
	for (l = 0, zptr = actualEditor->zlinesptr;
		  l <= actualEditor->wch; l++, zptr++)
		if (*zptr == line)
		{
			printLine(line,actualEditor->yoff + actualEditor->ch*l);
			break;
		}

	/* Delete reference: */
	actualEditor->actual = NULL;
	actualEditor->buflen	 = 0;
	actualEditor->bufypos = 0;

	/* Text was changed! */
	actualEditor->changed = 1;
	printFlags();

	return (TRUE);
}
/*#ENDFD*/
/*#FOLD:	saveIfCursorMoved	*/
/***************************************
 *
 * saveIfCursorMoved:
 *
 * Saves line in buffer,
 * if the cursor is moved.
 *
 ***************************************/

void saveIfCursorMoved()
{
	register UWORD bufypos;

	if (bufypos = actualEditor->bufypos)
		if (actualEditor->ypos != bufypos)
			if (! saveLine(actualEditor->actual))
				DisplayBeep(NULL);
}
/*#ENDFD*/
/*#FOLD:	undoLine	*/
/******************************************
 *
 * undoLine:
 *
 * Makes changes in actual line
 * before cursor leaves line
 *  
 *  
 *
 ******************************************/

void undoLine()
{
	register struct Zline *z;

	if (z = actualEditor->actual)
	{
		actualEditor->actual = NULL;
		actualEditor->bufypos = 0;
		actualEditor->buflen  = 0;

		z->flags &= ~ZLF_USED;

		/* Line output: */
		printLine(z,actualEditor->yoff
						+ actualEditor->ch*actualEditor->wdy);
	}
}
/*#ENDFD*/
/*#FOLD:	getBufferPointer */
/***************************************************
 *
 * getBufferPointer(pptr,pinc,prest):
 *
 * Initialize pointer to actualEditor->buffer.
 * The biffer is initialized.
 * FALSE is returned if the buffer
 * cannot be initialized.
 *
 * pptr ^ Pointer in buffer at cursor position.
 * pinc ^ Offset to buffer start.
 * prest^ buflen - inc.
 *
 ***************************************************/

BOOL getBufferPointer(pptr,pinc, prest)
UBYTE					  **pptr;
UWORD							  *pinc,*prest;
{
	register UBYTE *ptr;
	register WORD inc,rest;

	/* Buffer initialized: */
	if (actualEditor->actual == NULL)
	{
		register UWORD wdy;

		if (ZLINESPTR(wdy = actualEditor->wdy))
			getLineForEdit(ZLINESPTR(wdy),ZLINESNR(wdy));
		else
			if (actualEditor->num_lines == 0)
			{
				/* create first line: */
				register struct Zline *z;

				if (z = newZline((UWORD) 1))
				{
					*((UBYTE *)(z + 1)) = LF;
					AddHead(&actualEditor->zlines,z);
					ZLINESPTR(0) = z;
					ZLINESNR(0)  = (actualEditor->num_lines = 1);
					getLineForEdit(ZLINESPTR(0),ZLINESNR(0));
					printNumLines();
				}
				else
					return (FALSE);
			}
			else
				/* Cursor is not in line! */
				return (FALSE);
	}

	/* Calculate pointer to cursor position: */
	inc = actualEditor->xpos - 1;
	ptr = actualEditor->buffer + inc;
	rest= actualEditor->buflen - inc;

	/* What if inc > buflen? */
	if (inc < MAXWIDTH)
	{
		if (rest < 0)
		{
			register UBYTE *p;

			p = actualEditor->buffer + actualEditor->buflen;
			actualEditor->buflen -= rest;
			while (rest)
			{
				*p = ' ';
				p++;
				rest++;
			}
		}
	}
	else
		return (FALSE);

	*pptr = ptr;
	*pinc = inc;
	*prest= rest;
	return (TRUE);
}
/*#ENDFD*/
/*#FOLD:	deleteChar */
/************************************
 *
 * deleteChar:
  *
 * Delet echaracter under the cursor.
 * False is returned if no more
 * characters.
 *
 ************************************/

BOOL deleteChar()
{
	UBYTE *ptr;
	UWORD inc,rest;
	register UBYTE *p1,*p2;
	register UWORD l;

	if (! getBufferPointer(&ptr,&inc,&rest))
		return (FALSE);

	if (rest)
	{
		p1 = ptr + 1;
		p2 = ptr;
		l	= --rest;
		while (l)
		{
			*p2 = *p1;
			p1++;
			p2++;
			l--;
		}
		*p2 = actualEditor->buflastchar;

		/* Lenght - 1 */
		actualEditor->buflen--;

		printLine(actualEditor->actual,actualEditor->yoff
							+ actualEditor->ch*actualEditor->wdy);
	}

	return (TRUE);
}
/*#ENDFD*/
/*#FOLD:	backspaceChar */
/******************************
 *
 * backspaceChar:
 *
 * Delete character before cursor.
 * False is returned when
 * cursor is at start of line.
 *
 ******************************/

BOOL backspaceChar()
{
	UBYTE *ptr;
	UWORD inc,rest;
	register UBYTE *p1,*p2;
	register UWORD l;

	if (! getBufferPointer(&ptr,&inc,&rest))
		return (FALSE);

	if (inc)
	{
		if (actualEditor->insert)
		{
			p1 = ptr;
			p2 = --ptr;
			l	= rest;
			while (l)
			{
				*p2 = *p1;
				p1++;
				p2++;
				l--;
			}
			*p2 = actualEditor->buflastchar;

			/* Lenght - 1 */
			actualEditor->buflen--;
			inc--;
		}
		else
		{
			*--ptr = ' ';
			inc--;
			rest++;
		}

		cursorLeft();
		printLine(actualEditor->actual,actualEditor->yoff
							+ actualEditor->ch*actualEditor->wdy);
	}

	return (TRUE);
}
/*#ENDFD*/
/*#FOLD:	insertLine */
/**************************
 *
 * insertLine(c):
 *
 * Inserts new line behind
 * actual line.
 * FALSE returned if
 * error encountered.
 *
 * c = line end (CR/LF).
 *
 **************************/

BOOL insertLine(c)
UBYTE				 c;
{
	static UBYTE buf[MAXWIDTH + 1];
	UBYTE *ptr;
	register UBYTE *p1,*p2;
	WORD inc,rest,len;
	UWORD autoindent;
	register UWORD l;
	register struct Zline *z;

	/* Insert new line only if actual line
		has no fold markers!!! */
	if ((z = actualEditor->actual) == NULL)
		z = ZLINESPTR(actualEditor->wdy);

	if (!z || !(z->flags & ZLF_FSE))
	{
		/* get line in buffer: */
		if (! getBufferPointer(&ptr,&inc,&rest))
			return (FALSE);

		/* calculate auto indent: */
		if (actualEditor->autoindent)
		{
			p1 = actualEditor->buffer;
			l	= inc;
			while (l && ((*p1 == ' ') || (*p1 == TAB)))
			{
				p1++;
				l--;
			}

			if (l)
				autoindent = p1 - actualEditor->buffer + 1;
			else
				/* line consisits only of spaces: */
				autoindent = 1;
		}
		else
			autoindent = 1;

		/* deconvert line: */
		p2 = buf + (len = deconvertLine(buf,actualEditor->buffer,inc));
		if (*p2 = c)
			len++;

		if (z = newZline(len))
		{
			z->flags = (actualEditor->actual->flags & ~ZLF_USED);

			/* save line that the cursor is in: */
			p1 = (UBYTE *)(z + 1);
			p2 = buf;
			l	= len;

			while (l)
			{
				*p1 = *p2;
				p1++;
				p2++;
				l--;
			}

			/* bind line: */
			Insert(&actualEditor->zlines,z,actualEditor->actual->pred);
			actualEditor->num_lines++;
			actualEditor->changed = 1;

			/* move rest of buffer line in front: */
			/* remember auto indent! */
			p1 = actualEditor->buffer;
			l	= autoindent;
			while (--l)
				p1++;				/* Old contents remain! */

			p2 = ptr;
			l	= rest;

			if	(actualEditor->autoindent)
				/*	Spaces at start cot off:	*/
				while	(l	&&	(*p2 == ' '))
				{
					p2++;
					l--;
				}

			/*	The write rest of the buffer start:	*/
			while	(l)
			{
				*p1 = *p2;
				p1++;
				p2++;
				l--;
			}
			actualEditor->buflen = p1 - actualEditor->buffer;

			/* rest filled with lastchar: */
			l = inc + 1 - autoindent;
			while (l)
			{
				*p1 = actualEditor->buflastchar;
				p1++;
				l--;
			}

			/* determine if new line is a fold marker: */
			if (l = getFoldInc(z))
			{
				register struct Zline *old;
				register UWORD fold;

				z->flags |= ZLF_FSE;

				/* change fold level of following lines: */
				if ((old = z->succ)->succ)
					while (old->succ)
					{
						old->flags = (old->flags & ~ZLF_FOLD)
										| ((old->flags + l) & ZLF_FOLD);
						old = old->succ;
					}

				/* fit minfold and maxfold: */
				if ((l > 0) || ((z->flags & ZLF_FOLD) > 0))
				{
					fold = (z->flags & ZLF_FOLD) + l;
					if (actualEditor->minfold > fold)
					{
						actualEditor->minfold = fold;
						printFold();
					}
					if (actualEditor->maxfold < fold)
					{
						actualEditor->maxfold = fold;
						printFold();
					}

					ZLINESPTR(actualEditor->wdy) = z;
					actualEditor->wdy =
								recalcTopOfWindow(actualEditor->wdy);
				}
			}

			/*	If cursor ontop line => zlinesptr[0]:	*/
			if (actualEditor->wdy == 0)
				ZLINESPTR(0) = z;

			restoreZlinenptr();

			/* redisplay window: */
			actualEditor->xpos = autoindent;
			if (actualEditor->xpos <= actualEditor->leftpos)
			{
				/* If scrolling necessary: printAll */
				actualEditor->leftpos = actualEditor->xpos - 1;
				if (++actualEditor->wdy >= actualEditor->wch)
				{
					ZLINESPTR(0) = ZLINESPTR(1);
					ZLINESNR(0)  = ZLINESNR(1);
					restoreZlinenptr();
					actualEditor->wdy--;
				}
				actualEditor->ypos = ZLINESNR(actualEditor->wdy);

				printAll();
			}
			else
				if (l)
				{
					/* If fold marker: then redisplay window: */
					if (++actualEditor->wdy >= actualEditor->wch)
					{
						ZLINESPTR(0) = ZLINESPTR(1);
						ZLINESNR(0)  = ZLINESNR(1);
						restoreZlinenptr();
						actualEditor->wdy--;
					}
					actualEditor->ypos = ZLINESNR(actualEditor->wdy);

					printAll();
				}
				else
				{
					/* it was scrolled: */
					if (++actualEditor->wdy >= actualEditor->wch)
					{
						/* Cursor was on last line: */
						register UWORD nr;

						scrollUp((UWORD) 1);
						nr = (--actualEditor->wdy) - 1;
						actualEditor->ypos = ZLINESNR(actualEditor->wdy);
						printLine(ZLINESPTR(nr),actualEditor->yoff
														+ actualEditor->ch*nr);
					}
					else
					{
						/* Cursor near middle of window: */
						register UWORD nr;

						if (ZLINESPTR((nr = actualEditor->wdy) + 1))
						{
							/* move rest of window down: */
							ScrollRaster(actualEditor->rp,
										 	0L,(LONG)-actualEditor->ch,
										 	(LONG)actualEditor->xoff,
										 	(LONG)actualEditor->yoff
										 	+ actualEditor->wdy*actualEditor->ch,
										 	(LONG)actualEditor->xscr,
										 	(LONG)actualEditor->yscr);
						}
						actualEditor->ypos = ZLINESNR(actualEditor->wdy);

						printLine(ZLINESPTR(nr),actualEditor->yoff
														+ actualEditor->ch*nr);
						nr--;
						printLine(ZLINESPTR(nr),actualEditor->yoff
														+ actualEditor->ch*nr);
					}
				}

			printXpos();
			printYpos();
			printNumLines();
			printFlags();

			return (TRUE);
		}
		else
			return (FALSE);
	}
	else
	{
		cursorHome();
		cursorDown();

		return (FALSE);
	}
}
/*#ENDFD*/
/*#FOLD:	getLastWord	*/
/**************************************
 *
 * getLastWord(str,len)
 *
 * Returns pointer to last 
 * word in a string.
 *
 * str ^ String.
 * len = buffer length.
 *
 **************************************/

UBYTE *getLastWord(str,len)
register UBYTE		*str;
register UWORD			  len;
{
	register UBYTE c,*lwb,*lwn,*end;

	lwb = NULL;					/* Last Word is space  */
	lwn = NULL;					/* Last Word normal */
	end = str + len - 1;		/* pointer to string end */
	for (str += len; len; len--)
	{
		if ((c = *--str) == ' ')
		{
			lwb = str;
			break;
		}
		else if (! ((c >= 'A') && (c <= 'Z')
					|| (c >= 'a') && (c <= 'z')
					|| (c >= '0') && (c <= '9')
					|| (c >= 192) || (c == '_')))
			if (lwn == NULL)
				lwn = str;
	}

	if (lwb == NULL)
		if (lwn)
			lwb = lwn;
		else
			lwb = end;
	else
		if (lwn)
			if ((end - lwb) > MAXWIDTH / 5)
				if ((end - lwn + 5) < (end - lwb))
					lwb = lwn;

	return (lwb + 1);
}
/*#ENDFD*/
/*#FOLD:	insertChar */
/******************************************
 *
 * insertChar(c)
 *
 * Inserts character in buffer.
 * FALSE returned if character
 * cannot be inserted.
 *
 * c= character.
 *
 ******************************************/

BOOL insertChar(c)
register UBYTE  c;
{
	UBYTE *ptr;
	WORD inc,rest;
	WORD xadd = 1;

	if (! getBufferPointer(&ptr,&inc,&rest))
		return (FALSE);

	if ((c == TAB) && (actualEditor->tabs))
	{
		if (actualEditor->insert)
		{
			/* Insert spaces: */
			register UBYTE *p1,*p2;
			register UWORD num,l;

			p1  = actualEditor->tabstring + actualEditor->xpos - 1;
			l	 = MAXWIDTH - actualEditor->xpos;
			num = 1;
			while (l && (*++p1))
			{
				xadd++;
				l--;
				num++;
			}

			/* num = Number of spaces to insert: */
			if (actualEditor->buflen + num > MAXWIDTH)
			{
				xadd -= num + actualEditor->buflen - MAXWIDTH;
				num	= MAXWIDTH - actualEditor->buflen;
			}

			/* move rest of line: */
			p1 = ptr + rest;
			p2 = p1 + num;
			l	= rest;
			while (l)
			{
				*--p2 = *--p1;
				l--;
			}

			/* Insert spaces: */
			p1 = ptr;
			l	= num;
			while (l)
			{
				*p1 = ' ';
				p1++;
				l--;
			}

			actualEditor->buflen += num;
			rest += num;
		}
		else
		{
			/* move cursor only: */
			register UBYTE *tab;
			register UWORD max;

			tab = actualEditor->tabstring + actualEditor->xpos - 1;
			max = MAXWIDTH - actualEditor->xpos;
			while (max && (*++tab))
			{
				xadd++;
				max--;
			}
		}
	}
	else
	{
		/* besides a normal character: */
		if ((! actualEditor->skipblanks)
			&&	(actualEditor->xpos >= actualEditor->rm))
		{
			/* Word-Wrap when SkipBlanks == 0 */
			actualEditor->xpos = getLastWord(actualEditor->buffer,
															actualEditor->buflen)
										 - actualEditor->buffer + 1;
			if (! insertLine((UBYTE) 0))
				return (FALSE);

			if (! saveLine(actualEditor->actual))
				DisplayBeep(NULL);

			cursorEnd();

			if (! getBufferPointer(&ptr,&inc,&rest))
				return (FALSE);
		}

		if (actualEditor->insert)
			if (actualEditor->buflen < MAXWIDTH)
			{
				register UBYTE *p1,*p2;
				register UWORD l;

				p1 = ptr + rest;
				p2 = p1;
				l	= rest;
				while (l)
				{
					*p2 = *--p1;
					p2--;
					l--;
				}
				*ptr = c;

				/* Lenght + 1 */
				actualEditor->buflen++;
				rest++;
			}
			else
				return (FALSE);
		else
		{
			*ptr = c;
			if (rest == 0)
			{
				actualEditor->buflen++;
				rest = 1;
			}
		}
	}

	/* move cursor: */
	while (xadd)
	{
		if (! cursorRight()) break;
		xadd--;
	}

	/* Line output: */
	printLine(actualEditor->actual,
		actualEditor->yoff + actualEditor->ch*actualEditor->wdy);

	return (TRUE);
}
/*#ENDFD*/
/*#FOLD:	deleteLine */
/****************************
 *
 * deleteLine:
 *
 * delete the line,
 * that the cusor is on.
 * FALSE returned if
 * cannot be deleted
 *   
 *
 ****************************/

BOOL deleteLine()
{
	register struct Zline *line,*next,*prev;
	register UWORD l = 0;
	UWORD nextnr,prevnr;

	if (line = ZLINESPTR(actualEditor->wdy))
	{
		/* erase reference to lien: */
		if (line == actualEditor->actual)
		{
			actualEditor->actual = NULL;
			actualEditor->bufypos = 0;
			actualEditor->buflen  = 0;
		}

		actualEditor->changed = 1;
		actualEditor->num_lines--;

		/* Reconstruct folding: */
		if (line->flags & ZLF_FSE)
		{
			register struct Zline *z;

			/* change fold level of following lines: */
			if ((z = line->succ)->succ)
			{
				if (((line->flags+1) & ZLF_FOLD) == (z->flags & ZLF_FOLD))
					/* line was fold start: */
					l = -1;
				else if ((line->flags & ZLF_FOLD) == ((z->flags+1) & ZLF_FOLD))
					/* line was fold end: */
					l = 1;
				else
					l = 0;

				if (l)
					while (z->succ)
					{
						z->flags = (z->flags & ~ZLF_FOLD)
									| ((z->flags + l) & ZLF_FOLD);
						z = z->succ;
					}
			}
		}

		/* Note next and previous line: */
		prevnr= ZLINESNR(actualEditor->wdy);
		prev	= prevLine(line,&prevnr);
		next	= nextLine(line,&nextnr);
		nextnr= ZLINESNR(actualEditor->wdy);

		/* Security check: */
		while ((prev == NULL) && (next == NULL) && (actualEditor->minfold))
		{
			l = 1;				/* Window completely output */
			actualEditor->minfold--;
			printFold();

			prevnr= ZLINESNR(actualEditor->wdy);
			prev	= prevLine(line,&prevnr);
			next	= nextLine(line,&nextnr);
			nextnr= ZLINESNR(actualEditor->wdy);

			if (prev || next) break;
			if (actualEditor->minfold) continue;

			if ((next = actualEditor->zlines.head)->succ == NULL)
				next = NULL;
			else
				nextnr = 1;

			break;
		}

		/* delete line: */
		deleteZline(line);

		/* pointer to actual line reset for recalc: */
		if (next)
		{
			ZLINESPTR(actualEditor->wdy) = next;
			ZLINESNR(actualEditor->wdy)  = nextnr;
		}
		else
		{
			ZLINESPTR(actualEditor->wdy) = prev;
			ZLINESNR(actualEditor->wdy)  = prevnr;
		}

		/* Restore window contents: */
		if (l)
		{
			/* Redisplay window in each case: */
			actualEditor->wdy = recalcTopOfWindow(actualEditor->wdy);
			restoreZlinenptr();
			printAll();
			cursorOnText();
		}
		else
		{
			/* with scrolling: */
			register UWORD oldwdy;

			oldwdy = actualEditor->wdy;
			actualEditor->wdy = recalcTopOfWindow(actualEditor->wdy);
			restoreZlinenptr();

			if (next)
			{
				/* push up rest of window: */
				ScrollRaster(actualEditor->rp,
									0L,(LONG)actualEditor->ch,
									(LONG)actualEditor->xoff,
									(LONG)actualEditor->yoff
									+ actualEditor->wdy*actualEditor->ch,
									(LONG)actualEditor->xscr,
									(LONG)actualEditor->yscr);

				printLine(ZLINESPTR(actualEditor->wch - 1),
							 actualEditor->yoff
							 + actualEditor->ch*(actualEditor->wch - 1));
			}
			else
				if (oldwdy == actualEditor->wdy)
				{
					/* scroll top section of window down: */
					ScrollRaster(actualEditor->rp,
										0L,(LONG)-actualEditor->ch,
										(LONG)actualEditor->xoff,
										(LONG)actualEditor->yoff,
										(LONG)actualEditor->xscr,
										(LONG)actualEditor->yoff
										+ (actualEditor->wdy + 1)
										 *actualEditor->ch - 1);

					printLine(ZLINESPTR(0),actualEditor->yoff);
				}
				else
					printLine(ZLINESPTR(oldwdy),actualEditor->yoff
								 + actualEditor->ch*oldwdy);

			cursorOnText();
		}

		printXpos();
		printYpos();
		printNumLines();
		printFlags();

		return (TRUE);
	}
	else
		return (FALSE);
}
/*#ENDFD*/
/*#FOLD:	initFolding	*/
/**********************************
 *
 * initFolding:
 *
 * calculate the fold level of all
 * lines from text start.
 *
 **********************************/

void initFolding()
{
	register struct Zline *z;
	register UWORD level,l;

	z = actualEditor->zlines.head;
	level = 0;
	while (z->succ)
	{
		z->flags = (z->flags & ~ZLF_FOLD) | (level & ZLF_FOLD);
		if (l = getFoldInc(z))
		{
			z->flags |= ZLF_FSE;
			level += l;
		}

		z = z->succ;
	}
}
/*#ENDFD*/
