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

	DoFBFC()

	This function is called only by the SrcLop function,  after the
Search function has set up the SBfBeg, SBfEnd, SBfPtr and NArgmt variables.
It is called to handle the special processing needed by the FB and FC
search commands.  The FB and FC commands provide TECO's bounded search
capability.

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

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

extern	VOID	ErrMsg();	/* display an error message */
extern	LONG	Ln2Chr();	/* convert line offset to character offset */
extern	DEFAULT	SSerch();	/* single search */
extern	VOID	ZCpyBl();	/* copy a block of memory */

EXTERN	char	*AraBeg;	/* beginning of text m,n area */
EXTERN	char	*AraEnd;	/* end of m,n area */
EXTERN	BYTE	CmdMod;		/* command modifiers flags for @, :, etc. */
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	char	*EndSAr;	/* end of search area */
EXTERN	char	*GapBeg;	/* beginning of edit buffer gap */
EXTERN	char	*GapEnd;	/* end of edit buffer gap */
EXTERN	LONG	MArgmt;		/* m part of m,n numeric arguments */
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 DoFBFC()		/* search loop */
{
	LOCAL	LONG	HowFar;
	LOCAL	LONG	Shuffl;		/* how far buffer gap is shuffled */

#if DEBUGGING
DbgInd+=2;if(DbgLvl>=2){DbgMsg();DbgDBf("DoFBFC: called");
DbgDBf(", MArgmt = ");MakDBf(MArgmt, 10);ZDspBf(DBfBeg, DBfPtr-DBfBeg);
DbgDBf(", NArgmt = ");MakDBf(NArgmt, 10);ZDspBf(DBfBeg, DBfPtr-DBfBeg);
DbgDBf("\015\012");DbgROf();}
#endif

	Shuffl = 0L;
	if (CmdMod & MARGIS)			/* if it's m,nFB or m,nFC */
		{

/* Call GetAra to convert m and n into addresses.  A side effect of the call
   to GetAra is that MArgmt and NArgmt are sorted so that MArgmt is less than
   NArgmt.  We need to know the original order,  so set an indicator variable
   before calling GetAra.
*/

		SIncrm = (MArgmt < NArgmt) ? 1L : -1L;
		if (GetAra() == FAILURE)
#if DEBUGGING
{if(DbgLvl>=2)
{DbgMsg();DbgDBf("DoFBFC: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
			return(FAILURE);
#if DEBUGGING
}
#endif

/* If the edit buffer gap falls between m and n,  we need to shuffle part of
   the edit buffer to make the m,n area contiguous.  The gap is shuffled so
   that it is before the m,n area,  so that if part of the match string lies
   beyond the n boundary,  it can still be matched.
*/

		if ((AraBeg < GapBeg) && (AraEnd > GapEnd))
			{
			Shuffl = AraEnd - GapEnd;
			GapBeg -= Shuffl;
			GapEnd -= Shuffl;
			ZCpyBl(Shuffl, GapBeg, GapEnd+1L);
			}

/* set the variables for the call to SSerch */

		if (SIncrm == 1L)		/* forward search */
			{
			EBPtr1 = GapEnd;
			EBPtr1++;
			EndSAr = AraEnd;
			}
		else				/* else backward search */
			{
			EBPtr1 = AraEnd;
			EndSAr = GapEnd;
			EndSAr++;
			}
		RhtSid = EBfEnd;
		}
	else					/* else it's nFB or nFC */
		{
		if (NArgmt > 0L)		/* forward search */
			{
			SIncrm = 1L;
			EBPtr1 = GapEnd;
			EBPtr1++;
			EndSAr = GapEnd + Ln2Chr(NArgmt);
			RhtSid = EBfEnd;
			}
		else				/* else backward search */
			{
			SIncrm = -1L;
			EBPtr1 = GapBeg;
			EBPtr1--;
			EndSAr = GapBeg + Ln2Chr(NArgmt);
			RhtSid = GapBeg;
			RhtSid--;
			}
		}
	if (SSerch() == FAILURE)
#if DEBUGGING
{if(DbgLvl>=2)
{DbgMsg();DbgDBf("DoFBFC: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
		return(FAILURE);
#if DEBUGGING
}
#endif

	if (Matchd)				/* if search succeeded */
		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 the edit buffer gap was shuffled earlier (because the gap fell into the
   m,n area),  then we need to reverse shuffle it to leave things as they
   were.
*/

		if (Shuffl != 0L)		/* if buffer was shuffled */
			{
			ZCpyBl(Shuffl, GapEnd+1L, GapBeg);
			GapBeg += Shuffl;
			GapEnd += Shuffl;
			}

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