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

	SrcLop()

	This function is called by the Search function only,  after the
Search function has set up the search string buffer (SBfBeg, SBfEnd, SBfPtr)
and the iteration count (NArgmt).  It sets up the edit buffer bounds for the
search (EBPtr1, EndSAr) and direction indicator (SIncrm) and then calls
the SSerch function.  One way to describe this function is that it handles
the numeric arguments of all search commands by handling m,n arguments or
actually doing the loop for n arguments.

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

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

extern	DEFAULT	DoFBFC();	/* execute FB or FC path */
extern	VOID	ErrMsg();	/* display an error message */
extern	DEFAULT	ExeNYI();	/* "not yet implemented" function */
extern	DEFAULT	SSerch();	/* single search */
extern	VOID	ZCpyBl();	/* copy a block of memory */
extern	DEFAULT	RdPage();	/* read a page */
extern	DEFAULT	WrPage();	/* write to output file */

EXTERN	DEFAULT	CurInp;		/* index of current input stream in IFiles */
EXTERN	DEFAULT	CurOut;		/* index of current output stream in OFiles */
EXTERN	char	*EBfBeg;	/* beginning of edit buffer */
EXTERN	char	*EBfEnd;	/* end of edit buffer */
EXTERN	char	*EBPtr1;
EXTERN	char	*EBPtr2;	/* pointer to end of found string */
EXTERN	WORD	EdFlag;		/* ED mode control flag */
EXTERN	char	*EndSAr;	/* end of search area */
EXTERN	LONG	FFPage;		/* form feed flag (returned by ^E command) */
EXTERN	char	*GapBeg;	/* beginning of edit buffer gap */
EXTERN	char	*GapEnd;	/* end of edit buffer gap */
EXTERN	BOOLEAN	IsEofI[];
EXTERN	BOOLEAN	IsOpnO[];
EXTERN	BOOLEAN	Matchd;		/* used by search code */
EXTERN	LONG	NArgmt;		/* numeric argument */
EXTERN	LONG	RefLen;		/* value returned by ^S command */
EXTERN	char	*RhtSid;	/* right-hand end of area to be searched */
EXTERN	LONG	SIncrm;		/* search increment, 1L or -1L */
EXTERN	WORD	SrcTyp;		/* type of search (S, N, _ or E_) */


DEFAULT SrcLop()		/* search loop */
{
	LOCAL	LONG	HowFar;

#if DEBUGGING
DbgInd+=2;if(DbgLvl>=2){DbgMsg();DbgDBf("SrcLop1: called.\015\012");DbgROf();}
#endif

	if (SrcTyp == FB_SEARCH)		/* if it's FB or FC */
#if DEBUGGING
{if(DbgLvl>=2)
{DbgMsg();DbgDBf("SrcLop2: returning DoFBFC().\015\012");DbgROf();}DbgInd-=2;
#endif
		return(DoFBFC());
#if DEBUGGING
}
#endif


/* It's not an FB or FC search.  The FB and FC commands are the only
   ones which can be preceeded by an m,n argument pair.  Other search
   commands can be preceeded only by an iteration count.
*/

	if (NArgmt > 0L)			/* if forwards search */
		{
		SIncrm = 1L;
		EBPtr1 = GapEnd;
		EndSAr = RhtSid = EBfEnd;
		FOREVER
			{
			EBPtr1++;
			if (SSerch() == FAILURE)
#if DEBUGGING
{if(DbgLvl>=2)
{DbgMsg();DbgDBf("SrcLop3: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
				return(FAILURE);
#if DEBUGGING
}
#endif
			if (Matchd)		/* if search succeeded */
				--NArgmt;
			else			/* else search failed */
				switch (SrcTyp) {
				case S_SEARCH:
				case FK_SEARCH:
					NArgmt = 0L;	/* exit loop */
					break;
				case N_SEARCH:
					if (IsEofI[CurInp])
						{
						if (WrPage(
							CurOut,
							EBfBeg,
							EBfEnd,
							FFPage) == FAILURE)
#if DEBUGGING
{if(DbgLvl>=2)
{DbgMsg();DbgDBf("SrcLop4: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
							return(FAILURE);
#if DEBUGGING
}
#endif
						GapBeg = EBfBeg; /* clear.. */
						GapEnd = EBfEnd; /* ..buffr */
						NArgmt = 0L;   /* exit loop */
						}
					else	/* else not end-of-file */
						{
						if (SinglP() == FAILURE)
#if DEBUGGING
{if(DbgLvl>=2)
{DbgMsg();DbgDBf("SrcLop5: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
							return(FAILURE);
#if DEBUGGING
}
#endif
						EBPtr1 = GapEnd + 1L;
						EndSAr = RhtSid = EBfEnd;
						}
					break;
				case U_SEARCH:
					if (((EdFlag & ED_YANK_OK) == 0) &&
					    (IsOpnO[CurOut]) &&
					    (	(GapBeg != EBfBeg) ||
						(GapEnd != EBfEnd)
					    )
					   )
						{
						ErrMsg(ERR_YCA);
#if DEBUGGING
if(DbgLvl>=2)
{DbgMsg();DbgDBf("SrcLop6: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
						return(FAILURE);
						}
				case E_SEARCH:
					GapBeg = EBfBeg;  /* clear the... */
					GapEnd = EBfEnd;  /* ...edit buffer */
					if (IsEofI[CurInp])
						NArgmt = 0L;	/* exit loop */
					else
						{
						if (RdPage() == FAILURE)
#if DEBUGGING
{if(DbgLvl>=2)
{DbgMsg();DbgDBf("SrcLop7: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
							return(FAILURE);
#if DEBUGGING
}
#endif
						EBPtr1 = GapEnd + 1L;
						EndSAr = RhtSid = EBfEnd;
						}
				}			/* end of switch */
			if (NArgmt == 0L)		/* if done */
				break;			/* exit the loop */
			if ((EdFlag & ED_DOT_BY_ONE) == 0)
				EBPtr1 = EBPtr2;      /* skip found string */
			}
		}
	else					/* else backwards search */
		{
		SIncrm = -1L;
		EBPtr1 = RhtSid = GapBeg;		/* start point */
		RhtSid--;
		EndSAr = EBfBeg;			/* end point */
		do
			{
			EBPtr1--;
			if (SSerch() == FAILURE)
#if DEBUGGING
{if(DbgLvl>=2)
{DbgMsg();DbgDBf("SrcLop8: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
				return(FAILURE);
#if DEBUGGING
}
#endif
			if (Matchd)
				++NArgmt;
			else
				if ((SrcTyp==S_SEARCH) || (SrcTyp==FK_SEARCH))
					break;
				else
#if DEBUGGING
{if(DbgLvl>=2)
{DbgMsg();DbgDBf("SrcLop9: returning ExeNYI().\015\012");DbgROf();}DbgInd-=2;
#endif
					return(ExeNYI());
#if DEBUGGING
}
#endif
			}
		while (NArgmt < 0L);
		}

/* The next block of code deals with what happens to the edit buffer after
   the search.  There are three possibilities:

	if the search was successful
		if it's an FK command
			delete spanned characters
		else
			move to after the found string
	else
		move to the start of the edit buffer

*/

	if (Matchd)				/* if search succeeded */
		if (SrcTyp == FK_SEARCH)		/* if FK command */
			if (SIncrm == 1L)		/* if forward search */
				GapEnd = EBPtr2;	/* delete */
			else				/* else backward */
				GapBeg = EBPtr1;	/* delete */
		else					/* else not FK */
			if (SIncrm == 1L)
				{
				HowFar = EBPtr2 - GapEnd;
				ZCpyBl(HowFar, GapEnd+1L, GapBeg);
				GapBeg += HowFar;
				GapEnd += HowFar;
				}
			else
				{
				HowFar = (GapBeg-1L) - EBPtr2;
				GapBeg -= HowFar;
				GapEnd -= HowFar;
				ZCpyBl(HowFar, GapBeg, GapEnd+1L);
				}
	else					/* else search failed */
		if ((EdFlag & ED_PRES_DOT) == 0)   /* if don't preserve dot */
			{
			HowFar = GapBeg - EBfBeg;
			GapBeg -= HowFar;
			GapEnd -= HowFar;
			ZCpyBl(HowFar, GapBeg, GapEnd+1L);
			}

#if DEBUGGING
if(DbgLvl>=2){DbgMsg();DbgDBf("SrcLop10: returning SUCCESS, Matchd = ");
if(Matchd)DbgDBf("YES\015\012");else DbgDBf("NO\015\012");DbgROf();}DbgInd-=2;
#endif
	return(SUCCESS);
}
