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

	FrstCh()

	This function deals with the following immediate mode commands:

	? 	display previous command string up to erroneous command
	/	display verbose explanation of last error
	*q	copy last command string to q-register q

	This function is called by ReadCS to read the very first command
typed by the user.  It handles the above immediate mode commands without
destroying the previous command buffer.  Once this function returns,  the
previous command string and error are considered lost by ReadCS,  which then
overwrites the old command string with a new one.
	This function does not deal with the LF and BS immediate mode commands
because of the following possible sequence of events: the user starts typing
a command string,  then does a ^U to delete it,  then tries to use LF or BS
to position himself in the edit buffer.  If this function were responsible for
LF and BS,  then they would not work.  ReadCS is responsible for handling the
LF and BS immediate mode commands.
*****************************************************************************/

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

extern	VOID	EchoIt();	/* echo a character */
extern	VOID	DoEvEs();	/* do an EV or ES mode control flag function */
extern	DEFAULT	FindQR();	/* find a q-register index */
extern	VOID	ZFree();	/* free memory */
extern	DEFAULT	MakRom();	/* make room for text in a q-register */
extern	VOID	TypESt();	/* type an error string */
extern	VOID	VrbErr();	/* display a verbose error message */
extern	char	ZChIn();	/* input a character from the terminal */
extern	VOID	ZCpyBl();	/* copy a block of memory */
extern	VOID	ZDspBf();	/* output a buffer to the terminal */
extern	VOID	ZDspCh();	/* output a character to the terminal */

EXTERN	char	*CBfPtr;	/* pointer into command buffer */
EXTERN	char	*CStBeg;	/* beginning of command string */
EXTERN	char	*CStEnd;	/* pointer to last char of command string */
EXTERN	WORD	EvFlag;		/* EV mode control flag */
EXTERN	BOOLEAN	GotCtC;		/* YES if the user just hit a CTRL_C */
EXTERN	WORD	LstErr;		/* number of last error message */
EXTERN	char	*(*QBfBeg);	/* start of q-register text area */
EXTERN	char	*(*QBfPtr);	/* ptr to end of q-reg text area, plus 1 */


char FrstCh()

{
	LOCAL	BOOLEAN	ImdCmd;		/* YES if it's '?', '*' or '/' */
	LOCAL	char	*LclStr = "xx";	/* local string for * processing */
	LOCAL	DEFAULT	Status;
	LOCAL	char	*TCBfPt;	/* temporary holder of CBfPtr */
	LOCAL	char	*TCStEn;	/* temporary holder of CStEnd */
	LOCAL	char	TmpChr;		/* temporary character */
	LOCAL	LONG	TmpSiz;

do {
	if (EvFlag)		/* if EV (edit verify) flag is set */
		DoEvEs(EvFlag);	/* handle EV flag */
	ZDspCh('*');		/* prompt */
	TmpChr = ZChIn();	/* get a character */
	ImdCmd = NO;		/* initialize "immediate command" flag */
	if (GotCtC)		/* if it was control-C */
		{
		GotCtC = NO;
		ImdCmd = YES;
		}
	else switch (TmpChr) {
		case DELETE:
		case CTRL_U:
			ZDspCh(CRETRN);
			ImdCmd = YES;
			break;
		case '/':
			if (LstErr != ERR_XXX)
				{
				ZDspCh('/');
				VrbErr(LstErr);
				ImdCmd = YES;
				}
			break;
		case '?':
			if (LstErr != ERR_XXX)
				{
				ZDspCh('?');
				TypESt();
				ImdCmd = YES;
				}
			break;
		case '*':
			ZDspCh('*');
			TmpChr = ZChIn();
			if (GotCtC)
				{
				GotCtC = NO;
				return(CTRL_C);
				}
			switch (TmpChr) {
				case CRETRN:
					TmpChr = '\0';
					break;
				case DELETE:
				case CTRL_U:
					ZDspCh(CRETRN);
					break;
				default:
					EchoIt(TmpChr);
					LclStr[0] = TmpChr;
					TCBfPt = CBfPtr;/* save CBfPtr */
					CBfPtr = &LclStr[0];
					TCStEn = CStEnd;/* save CStEnd */
					if (TmpChr == '.')
						{
						LclStr[1] = ZChIn();
						EchoIt(TmpChr);
						CStEnd = &LclStr[1];
						}
					else
						CStEnd = &LclStr[0];
					Status = FindQR();
					CBfPtr = TCBfPt;/* restore CBfPtr */
					CStEnd = TCStEn;/* restore CStEnd */
					if (Status == SUCCESS)
						{
						if (*QBfBeg != NULL)
							{
							ZFree(*QBfBeg);
							*QBfBeg = NULL;
							*QBfPtr = NULL;
							}
						TmpSiz = (CStEnd-CStBeg) + 1L;
						if (TmpSiz > 0L)
						{
						if (MakRom(TmpSiz) == FAILURE)
/* ??? */						return(FAILURE);
						ZCpyBl(TmpSiz,CStBeg,*QBfBeg);
						*QBfPtr = *QBfBeg + TmpSiz;
						}
						ZDspBf("\015\012", 2);
						}

					}	/* end switch */
				ImdCmd = YES;
				break;
		}				/* end switch */
} while (ImdCmd);				/* end do statement */

return(TmpChr);
}						/* end FrstCh function */
