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

	ExeX()

	This function executes an X command.

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

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

extern	DEFAULT	FindQR();	/* find q-register index */
extern	DEFAULT	IncCBP();	/* increment CBfPtr */
extern	DEFAULT	GetAra();	/* get m,n area */
extern	DEFAULT	GetNmA();	/* get numeric argument */
extern	LONG	Ln2Chr();	/* convert line offset to character offset */
extern	DEFAULT	MakRom();	/* make room for text in q-register */
extern	VOID	StCopy();	/* string copy */
extern	VOID	UMinus();	/* handle a unary minus */
extern	VOID	ZCpyBl();	/* copy a block of memory */
extern	VOID	ZFree();	/* free memory */

EXTERN	char	*AraBeg;	/* beginning of m,n area */
EXTERN	char	*AraEnd;	/* end of m,n area */
EXTERN	BYTE	CmdMod;		/* command modifiers flags for @, :, etc. */
EXTERN	char	ErrTxt[];	/* holds part of error message */
EXTERN	WORD	EStBot;		/* expression stack bottom */
EXTERN	WORD	EStTop;		/* expression stack top */
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	LONG	NArgmt;		/* numeric argument */
EXTERN	char	*(*QBfBeg);	/* beginning of q-register text area */
EXTERN	char	*(*QBfPtr);	/* end of q-register test area, plus 1 */


DEFAULT ExeX()			/* execute an X command */
{
	LOCAL	LONG	TmpSiz;

#if DEBUGGING
DbgInd+=2;if(DbgLvl>=1){DbgMsg();
DbgDBf("ExeX: called.\015\012");DbgROf();}
#endif
	if (EStTop == EStBot)			/* if no numeric argument */
		NArgmt = 1L;			/* default is 1X */
	else
		{
		UMinus();			/* if it's -X, make it -1X */
		if (GetNmA() == FAILURE)	/* get numeric argument */
#if DEBUGGING
{if(DbgLvl>=1){DbgMsg();
DbgDBf("ExeX: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
			return(FAILURE);
#if DEBUGGING
}
#endif
		}

	if (IncCBP() == FAILURE)		/* move to char after X */
		return(FAILURE);
	if (FindQR() == FAILURE)	/* find q-register values */
#if DEBUGGING
{if(DbgLvl>=1){DbgMsg();
DbgDBf("ExeX: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
		return(FAILURE);
#if DEBUGGING
}
#endif

	if ((CmdMod & COLON) == '\0')		/* if no colon modifier */
		if (*QBfBeg != NULL)		/* if text area not empty */
			{
			ZFree(*QBfBeg);		/* free allocated memory */
			*QBfBeg = NULL;
			*QBfPtr = NULL;
			}

	if ((CmdMod & MARGIS) == '\0')		/* if it's nXq (not m,nXq) */
		{
		NArgmt = Ln2Chr(NArgmt);
		if (NArgmt > 0L)
			{
			if (MakRom(NArgmt) == FAILURE)
#if DEBUGGING
{if(DbgLvl>=1){DbgMsg();
DbgDBf("ExeX: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
				return(FAILURE);
#if DEBUGGING
}
#endif
			ZCpyBl(NArgmt, GapEnd+1L, *QBfPtr);
			*QBfPtr += NArgmt;
			}
		else if (NArgmt < 0L)
			{
			if (MakRom(-NArgmt) == FAILURE)
#if DEBUGGING
{if(DbgLvl>=1){DbgMsg();
DbgDBf("ExeX: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
				return(FAILURE);
#if DEBUGGING
}
#endif
			ZCpyBl(-NArgmt, GapBeg+NArgmt, *QBfPtr);
			*QBfPtr -= NArgmt;
			}
		}
	else if (NArgmt != MArgmt)		/* else (it's m,nXq) */
		{
		StCopy(ErrTxt, "m,nX");
		if (GetAra() == FAILURE)
#if DEBUGGING
{if(DbgLvl>=1){DbgMsg();
DbgDBf("ExeX: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
			return(FAILURE);
#if DEBUGGING
}
#endif
		if ((AraBeg < GapBeg) && (AraEnd > GapEnd))
			{
			TmpSiz = (GapBeg-AraBeg) + (AraEnd-GapEnd);
			if (TmpSiz > 0L)
				{
				if (MakRom(TmpSiz) == FAILURE)
#if DEBUGGING
{if(DbgLvl>=1){DbgMsg();
DbgDBf("ExeX: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
					return(FAILURE);
#if DEBUGGING
}
#endif
				ZCpyBl(GapBeg-AraBeg, AraBeg, *QBfPtr);
				*QBfPtr += GapBeg-AraBeg;
				ZCpyBl(AraEnd-GapEnd, GapEnd+1L, *QBfPtr);
				*QBfPtr += AraEnd-GapEnd;
				}
			}
		else			/* else area is contiguous */
			{
			TmpSiz = (AraEnd - AraBeg) + 1L;
			if (TmpSiz > 0L)
				{
				if (MakRom(TmpSiz) == FAILURE)
#if DEBUGGING
{if(DbgLvl>=1){DbgMsg();
DbgDBf("ExeX: returning FAILURE.\015\012");DbgROf();}DbgInd-=2;
#endif
					return(FAILURE);
#if DEBUGGING
}
#endif
				ZCpyBl(TmpSiz, AraBeg, *QBfPtr);
				*QBfPtr += TmpSiz;
				}
			}
		}

	CmdMod = '\0';
#if DEBUGGING
if(DbgLvl>=1){DbgMsg();
DbgDBf("ExeX: returning SUCCESS.\015\012");DbgROf();}DbgInd-=2;
#endif
	return(SUCCESS);
}
