/******************************************************************************

	RdLine()

	This function reads a line from the current input file into the
edit buffer.
	This function places the input into the edit buffer by appending it
to the edit buffer and adjusting the EndEBf pointer.  IBfEnd points to the
last byte of allocated, unused memory at the end of the edit buffer.

*****************************************************************************/

#include "ZPort.h"		/* define portability identifiers */
#include "DefTeco.h"		/* define general identifiers */
#include "DefError.h"		/* define identifiers for error messages */
#include "DefChars.h"		/* define identifiers for characters */

char	*ZRaloc();		/* re-allocate memory */
DEFAULT	ZRdLin();		/* read a line */

EXTERN	DEFAULT	CurInp;		/* index of current input stream in IFiles */
EXTERN	char	*EBfBeg;	/* beginning of edit buffer */
EXTERN	char	*EBfEnd;	/* edit buffer end */
EXTERN	LONG	FFPage;		/* form feed flag (see ^E command) */
EXTERN	char	*GapBeg;	/* beginning of edit buffer gap */
EXTERN	char	*GapEnd;	/* end of edit buffer gap */
EXTERN	char	*IBfEnd;	/* end of input buffer */
EXTERN	BOOLEAN	IsEofI[];	/* input file at end-of-file indicators */
EXTERN	BOOLEAN	IsOpnI[];	/* input file open indicators */


DEFAULT RdLine()		/* read a line */
{
	DEFAULT	length;
	LONG	NewSiz;
	char	*NewBeg;

#if DEBUGGING
DbgInd+=2;if(DbgLvl>=2){DbgMsg();DbgDBf("RdLine: called.\015\012");DbgROf();}
#endif
	if (!IsOpnI[CurInp])		/* if current input stream not open */
		{
		ErrMsg(ERR_NFI);	/* NFI = "no file for input" */
#if DEBUGGING
if(DbgLvl>=2)
{DbgMsg();DbgDBf("RdLine: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
		return(FAILURE);
		}

	if (IsEofI[CurInp])		/* if already at end-of-file */
#if DEBUGGING
{if(DbgLvl>=2)
{DbgMsg();DbgDBf("RdLine: returning SUCCESS.\015\012");DbgROf();}DbgInd-=2;
#endif
		return(SUCCESS);
#if DEBUGGING
}
#endif

/*
  The next block of code insures that there is enough room to append a
  reasonable-size line to the end of the edit buffer.  New text is always
  appended to the end of the edit buffer.  This means that read operations
  will always increase EBfEnd,  but never decrease it.  Thus, the edit buffer
  tends to grow when text is read,  but when it is deleted, only the gap
  pointers are modified.  The next block of code checks if there is more room
  than there should be in the edit buffer gap.  If there is,  then the second
  half of the edit buffer is moved in the direction of the gap,  which shrinks
  the gap but increases the input buffer area.  If the edit buffer gap is not
  large,  then the next block of code just expands the input buffer by
  allocating more memory at the end of it.
*/
	if ((IBfEnd-EBfEnd) < IBFMIN)		/* if not enough room */
		if ((GapEnd-GapBeg) > IBFEXP)	/* if gap is big */
			{
			ZCpyBl(IBFEXP, GapEnd+1L, GapEnd+1L-IBFEXP);
			GapEnd -= IBFEXP;
			EBfEnd -= IBFEXP;
			}
		else
			{
			NewSiz = (EBfEnd - EBfBeg) + IBFEXP;
#if DEBUGGING
if(DbgLvl>=2){DbgMsg();DbgDBf("RdLine: ZRaloc-ing EBf");
DbgDBf(", NewSiz = ");MakDBf(NewSiz, 10);ZDspBf(DBfBeg, DBfPtr-DBfBeg);
DbgDBf("\015\012");DbgROf();}
#endif
			NewBeg = ZRaloc(EBfBeg, NewSiz);
			if (NewBeg == NULL)
				{
				ErrMsg(ERR_MEM);	/* memory overflow */
#if DEBUGGING
if(DbgLvl>=2)
{DbgMsg();DbgDBf("RdLine: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
				return(FAILURE);
				}
			if (NewBeg != EBfBeg)
				{
				GapBeg = NewBeg + (GapBeg - EBfBeg);
				GapEnd = NewBeg + (GapEnd - EBfBeg);
				EBfEnd = NewBeg + (EBfEnd - EBfBeg);
				EBfBeg = NewBeg;
				}
			IBfEnd = (NewBeg + NewSiz) - 1L;
			}

	if (ZRdLin(&length) == FAILURE)
#if DEBUGGING
{if(DbgLvl>=2)
{DbgMsg();DbgDBf("RdLine: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
		return(FAILURE);
#if DEBUGGING
}
#endif

	if (IsEofI[CurInp])			/* if end-of-file */
#if DEBUGGING
{if(DbgLvl>=2)
{DbgMsg();DbgDBf("RdLine: returning SUCCESS.\015\012");DbgROf();}DbgInd-=2;
#endif
		return(SUCCESS);
#if DEBUGGING
}
#endif

	EBfEnd += length;
	if (length > 0)				/* if not an empty line */
		if (*EBfEnd == FORMFD)		/* if last char = form feed */
			{
			--EBfEnd;		/* cut it from edit buffer */
			FFPage = -1L;		/* and remember */
#if DEBUGGING
if(DbgLvl>=2)
{DbgMsg();DbgDBf("RdLine: returning SUCCESS.\015\012");DbgROf();}DbgInd-=2;
#endif
			return(SUCCESS);
			}
		else if ((*EBfEnd == VRTTAB) ||
			 ((length > 2) &&
			   (*EBfEnd == LINEFD) &&
		           (*(EBfEnd-1L) == CRETRN) &&
		           (*(EBfEnd-2L) == ESCAPE)
		         )
			)
#if DEBUGGING
{if(DbgLvl>=2)
{DbgMsg();DbgDBf("RdLine: returning SUCCESS.\015\012");DbgROf();}DbgInd-=2;
#endif
			return(SUCCESS);
#if DEBUGGING
}
#endif
	++EBfEnd;
	*EBfEnd = CRETRN;	/* append a carriage return */
	++EBfEnd;
	*EBfEnd = LINEFD;	/* append a line feed */
#if DEBUGGING
if(DbgLvl>=2)
{DbgMsg();DbgDBf("RdLine: returning SUCCESS.\015\012");DbgROf();}DbgInd-=2;
#endif
	return(SUCCESS);
}
