
#include	"sysdef.h"

/*								*/
/*	Copyright Notice					*/
/*								*/
/*								*/
/*	C version Copyright (C) 1984 Change Software, Inc.	*/
/*	Copyright (C) 1978 1979 1980 1981 1982 1983 1984 1985	*/
/*		      Change Software, Inc.			*/
/*								*/
/*								*/
/*	This software is furnished under a license and may	*/
/*	be  used  and  copied  only in accordance with the	*/
/*	terms of such license and with  the  inclusion  of	*/
/*	the  above copyright notice.  This software or any	*/
/*	other copies thereof may not be provided or other-	*/
/*	wise made available to any other person.  No title	*/
/*	to and ownership of the software is hereby  trans-	*/
/*	ferred.							*/
/*								*/




#define	then
#include	"scerrd.h"
#include	"tempio.h"
#include	"scterm.h"

#define	SPACE	040
#define	CTRLZ	032
#define	ESC	033
#define	TAB	011
#define	true	1
#define	false	0
#define	TRUE	1
#define	FALSE	0
#define	CR	015
#define	LF	012
#define	FF	014

extern	int	worklength ;
extern	char	workbuffer[] ;
extern	int	maxlen ;
extern	int	oldstsone,sts_one,sts_two ;
extern	char	curch,oldch ;
extern	int	chposition, curposition,*curline, no_echo ;
extern	struct	deltype	lastdeleted ;
extern	int	w ;


vtedit()
{
	extern int erasef,macoffset,restart,vt_status,updheader ;

	if ( scinit()== 0 ) then return(0) ;
	vt_status = vtgetc() ;

	restart = 0 ;
	while ( vt_status ) {
		if ( ateofmark() ) then macfinish() ;
		erasef = 0 ;
		if ( testcc() ) then break ;
		scdoch() ;
		if ( vt_status <= 0 ) then break ;
		if ( ateofmark() ) then macfinish() ;
		if ( macoffset <= 0 && updheader ) then scupdheader() ;
		vtgetc() ;
		}
	scunloadline() ;	
	scbye()  ;
	*curline = 1 ;
	return(1) ;
}


vtstop()
{
	extern int restart,stvtedit,vt_status,waswild ;
	if ( w == 0 )
	  then	{
		vt_status = 0 ;
		oldstsone |= ed_end ;
		sts_one |= ed_end ;
		restart = ( waswild == 0 && stvtedit ) ?1:0 ;
		}
	  else	scwarning(w_winend) ;
}



static scdoch()
{

	extern   char	curch,oldch,cmdleadin();
	extern   int	goldcount,goldk,rept,termtype ;
	register int	status ;

	oldch = curch ;
	if ( cmdleadin() == curch )
	  then	doecmd() ;
	  else	{
		if ( dosetrpt()==0 )
		  then {
			status = dorubout() ;
			if ( status == 0 ) then status = dointmacro() ;
			if ( status == 0 ) then status = doinschar() ;
			rept = 0 ;
			goldcount = 0 ;
			goldk = 0 ;
			}
		}
}




vtgetc()
{

	curch = getc() ;
	learnsave() ;
	return( curch ) ;
}


static getc()
{
	extern int macoffset,macsize[],mactimes,maccurrent ;
	extern char *mapmacro() ;

	if ( macoffset == -1 )
	  then	return( curch = getbin() ) ;
	  else	{
		if ( macoffset >= macsize[maccurrent] )
		  then	{
			if ( --mactimes > 0 )
			  then	{
			    macoffset = 1 ;
			    return(curch = *mapmacro(maccurrent)) ;
				}
			  else	{
			    macoffset = -1 ;
			    mactimes = 0 ;
			    return( curch = getbin() ) ;
				}
			}
		  else	{
			curch = *(mapmacro(maccurrent)+macoffset) ;
			macoffset++ ;
			return( curch ) ;
			} ;
		}
}



/*	EXECMACRO()	execute a stored macro				*/
/*	LEARNSAVE()	save user text for later execution		*/
/*	VTLEARN()	turn on the learn process			*/
/*	MACFINISH()	shut off executing macro			*/

execmacro()
{
	extern int lrnmod,macsize[],macoffset,mactimes,rept ;
	extern int maccurrent ;

	if ( mactimes ) then return(0) ;
	if ( lrnmod )
	  then	{
		scwarning( w_lrno ) ;
		lrnmod = 0 ;
		}
	if ( macsize[maccurrent] > 0 )
	  then	{
		if ( (mactimes = rept) == 0 ) then mactimes = 1 ;
		rept = 0 ;
		macoffset = 0 ;
		return(1) ;
		}
	  else	return(0) ;
}


macfinish()
{
	extern int macoffset,mactimes ;
	macoffset = -1 ;
	mactimes = 0 ;
	return(1) ;
}


static learnsave()
{
	extern int lrnmod,macsize[],mactimes,maccurrent ;
	extern char *mapmacro() ;

	if ( lrnmod && mactimes <= 0 )
	  then
	    if ( macsize[maccurrent] < _MACSIZE-1 )
		then {
		     *(mapmacro(maccurrent)+macsize[maccurrent]) = curch ;
		     macsize[maccurrent]++ ;
		     }
		else {
		     scwarning(w_lrnx) ;
		     lrnmod = 0 ;
		     }
	return(1) ;
}

vtlearn()
{
	extern int lrnmod,macsize[],mactimes,maccurrent ;

	if ( mactimes ) then return(0) ;
	if ( lrnmod )
	  then	{
		scwarning(w_lrno) ;
		lrnmod = 0 ;
		}
	  else	{
		scwarning(w_lrn) ;
		lrnmod = 1 ;
		macsize[maccurrent] = 0 ;
		}
	return(1) ;
}




doecmd()
{
	extern int goldcount,goldk,rept ;
	register char thech ;

	goldk = 0 ;
	thech = getfuncommand() ;
	while ( goldk == 0 && rept >= 0 ) {
		funcommand( thech ) ;
		if ( testcc() )
		  then	{
			noecho() ;
			scwarning( w_abort ) ;
			ref_screen() ;
			scloadline() ;
			break ;
			}
		if ( goldk == 0 ) then rept-- ;
		}			
	if ( goldk == 0 )
	  then	{
		goldcount = 0 ;
		rept = 0 ;
		}
}



#define	ins_failure	0
#define	ins_noecho	1
#define	ins_normal	2
#define	ins_noprint	3

static doinschar()


{
	register int  save1 ;
	register char ch ;
	register int  status ;
	extern   int  noins, erasef, read_only ;
	extern  char  curch ;
	

	ch = curch ;
	save1 = noins ;
	if (isdelimiter(ch))
	  then status = docrlfin() ;
	  else	{
		if ( ch < SPACE && ch != TAB )
		  then
		    status = doctlchar() ;
		  else	{
		    status = dogoldletter() ;
		    if ( status == 0 )
		      then {
			status = do_ins(ch) ;
			if ( ch == TAB ) then erasef = 1 ;
			   }
			}
		}
	if ( status == ins_normal )
	  then	{
		if ( no_echo == 0 )
		  then	{
			if (erasef) then lkill() ;
			partdump() ;
			scmove() ;
			}
		erasef = 0 ;
		}

	noins = save1 ;
	return(1) ;

}		    



/*	DOCRLFIN()							*/
/*									*/
/*	Process a carriage return, line feed or form feed input		*/

static docrlfin()
{

	register int null_line ;
	extern   int chposition, read_only ;
	extern  char curch ;

	if ( curch == LF ) then return (ins_normal) ;
	null_line = (atcrlf() && !(worklength == 1 && workbuffer[0] == FF)) ;
	if ( chposition == 0 && null_line == 0 )
	  then	sclinsert(curch) ;
	  else	{
		if (null_line)
		  then	{
			creset() ;
			scunloadline() ;
			mvdown() ;
			sclinsert(curch) ;
			}
		  else	{
			if ( read_only == 0 )
			  then	{
				sveoln(chposition) ;	
				deleoln(chposition) ;
				lkill() ;
				scunloadline() ;
				mvdown() ;
				sclinsert(curch) ;
				findeoln() ;
				if (svlinsert(chposition) !=0) then retype() ;
				}
			}
		}
	return(ins_normal) ;
}
		
vtopenline()
{
	register char savech ;
	register int oldcurline ;
	int oldchposition,oldcurposition ;

	oldcurposition = curposition ;
	oldchposition  = chposition  ;
	oldcurline = *curline ;
	savech = curch ;
	curch = CR ;
	docrlfin() ;
	scunloadline() ;
	curposition = oldcurposition ;
	chposition  = oldchposition  ;
	*curline = oldcurline ;
	curch = savech ;
	scloadline() ;
	scmove() ;
	return(1) ;
}
		
		




/*	DOCTLCHAR()							*/
/*									*/
/*	Process control character other than CR,LF,FF and TAB		*/


#define	CTRLA	01
#define	CTRLB	02
#define	CTRLC	03
#define	CTRLD	04
#define	CTRLE	05
#define	CTRLF	06
#define	CTRLG	07
#define	CTRLH	010
#define	CTRLK	013
#define	CTRLN	016
#define	CTRLP	020
#define	CTRLR	022
#define	CTRLT	024
#define	CTRLU	025
#define	CTRLV	026
#define	CTRLW	027
#define	CTRLX	030
#define	CTRLY	031
#define	CTRLZ	032
#define	CTRLBCK 034

static doctlchar()
{
	register int status ;
	extern   int goldcount,read_only,vt_status ;

	status = ins_noprint ;
	switch (curch) {

	  case CTRLA:
		if ( w == 0 )
		  then vt_status = 0 ;
		  else scwarning(w_winend) ;
		break ;
	  case CTRLB:
		vtlastpage() ;
		break ;
	  case CTRLD:
		vtdeleteline() ;
		break ;
	  case CTRLE:
		execmacro() ;
		break ;
	  case CTRLF:
		vtnxtword() ;
		break ;
	  case CTRLG:
		if ( read_only == 0 )
		  then	{
			puttxtsave(chposition) ;
			partdump() ;
			scmove() ;
			}
		break ;
	  case CTRLH:
		if ( atcrlf() )
		  then vtboln() ;
		  else vteoln() ;
		break ;
	  case CTRLN:
		vtdorep() ;
		break ;
	  case CTRLP:
		terinit() ;
		sctopline() ;
		screfscreen() ;
		kpapplication() ;
		break ;
	  case CTRLR:
		vtlstword() ;
		break ;
	  case CTRLT:
		vtfirstpage() ;
		break ;
	  case CTRLU:
		vtdboln() ;
		break ;
	  case CTRLV:
		vtsetcommand() ;
		break ;
	  case CTRLW:
		gettxtsave(0) ;
		break ;
	  case CTRLX:
		readmacro() ;
		break ;
	  case CTRLZ:
		creset() ;
		retype() ;
		scmove() ;
		break ;
	  case CTRLBCK:
		vtscroll() ;
		break ;
	  default:
		status = ins_failure ;
		break ;
		}
	goldcount = 0 ;
	return( status ) ;
}

static dogoldletter()
{
	extern int goldcount ;

	if ( goldcount != 0 )
	  then return( fungoldcommand( curch ) ) ;
	  else return( ins_failure ) ;
}




static do_ins(ch)
char ch ;
{
	extern int erasef,escprint,worklength,rept,no_echo,read_only ;

	if ( read_only ) then sclinsert(CR) ;
	if ( rept == 0 ) then rept = 1 ;
	if ( ch == ESC ) then escprint = 1 ;
	if ( overwrite(ch) != ins_normal )
	  then
	    while ( rept > 0 && worklength < maxlen ) {
		scxins(ch) ;
		if ( no_echo == 0 )
		  then scinecho(ch) ;
		dowrap() ;
		rept-- ;
		}
	rept = 0 ;
	if ( ch == TAB ) then erasef = 1 ;
	return( ins_noecho ) ;
}


static overwrite(ch)
char ch ;
{
	extern char workbuffer[] ;
	extern int  chposition,noins ;
	register int rflag ;

	if ( noins == 0 ) then return( ins_failure ) ;
	if ( atcrlf() )
	  then	{
		noins = 0 ;
		return( ins_failure ) ;
		}
	  else	{
		rflag = ( workbuffer[chposition] == TAB ) ;
		workbuffer[chposition] = ch ;
		putbin(&ch,1) ;
		txtmod() ;
		pinc() ;
		fixposition() ;
		if ( rflag ) then retype() ;
		return( ins_normal ) ;
		}
}


vtoverwrite()
{
	extern int noins ;

	if ( noins )
	  then	{
		ledoff( l_overwrite ) ;
		noins = 0 ;
		}
	  else	{
		ledon(  l_overwrite ) ;
		noins = 1 ;
		}
}


static dowrap()
{
}





scxins(ch)
char ch ;
{
	extern int read_only ;
	register char *cp,*dp ;
	register int  i ;

	if ( worklength < maxlen && read_only == 0 )
	  then	{
		tabcheck(ch) ;
		txtmod() ;
		cp = &workbuffer[worklength] ;
		dp = cp ;
		for ( i=0; i<worklength-chposition; i++ ) *cp-- = *(--dp) ;
		workbuffer[chposition] = ch ;
		worklength++ ;
		pinc() ;
		}
}




/*	TABCHECK()							*/

/*	TABCHECK will look to see if a character insertion into the 	*/
/*	will cause a tab to move past a tabstop. If so, it will set	*/
/*	global ERASEF to be true (nonzero).				*/

static tabcheck(ch)
char ch ;
{

	register char *cp ;
	register int  i,tcur_pos ;
	int temp ;
	extern int erasef ;

	if ( erasef = (ch == TAB) ) then return( true ) ;
	temp = worklength - chposition ;
	cp = &workbuffer[chposition] ;
	tcur_pos = curposition - 1 ;
	for ( i=0; i < temp; i++ ) {
	  tcur_pos++ ;
	  if ( *cp++ == TAB )
	    then {
		if ( (tcur_pos & 7) == 0 )
		  then	{
			erasef = true ;
			return(true) ;
			}
		  else	tcur_pos += 8 - ( tcur_pos & 07 ) ;

		}
	}
	erasef = false ;
	return( false ) ;
}


dointmacro()
{
	return(0) ;
}




/*	DOSETRPT							*/
/*									*/
/*	Create a repeat count for the sequence GOLD digits. If a non	*/
/*	digit is typed (apart from CR and RUBOUT) then turn off GOLD	*/
/*	and call SCDOCH to process the command with the repeat count	*/

#define	RUB	0177
#define	CR	015

static dosetrpt()
{
	extern int goldcount,rept ;
	register int pos,val ;

	if ( goldcount == 0 ) then return(0) ;
	if ( curch == '*' )
	  then	{
		goldcount = 0 ;
		rept = 999 ;
		ceol24() ;
		scdecout( rept ) ;
		goback() ;
		return(1) ;
		}
	if ( ! ( curch >= '0' && curch <= '9' ) ) then return(0) ;
	goldcount = 0 ;
	pos = 0 ;
	val = 0 ;
	rept = 0 ;
	while ( pos >= 0 ) {
	  switch( curch ) {
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
		  if ( val > 999 )
			then vtbell() ;
			else {
			  val = val*10 + (curch-060) ;
			  pos++ ;
			  ceol24() ;
			  scdecout( val ) ;
			  goback() ;
			     }
		  break ;	
		case CR:
		  return( rept = val ) ;
		  break ;

		case RUB:
		  val = val/10 ;
		  pos-- ;
		  ceol24() ;
		  scdecout( val ) ;
		  goback() ;
		  break ;

		default:
		  rept = val ;
		  scdoch() ;
		  return(val) ;
		  break ;
		}
	  vtgetc() ;
	}
	return(0) ;
}

vtspins()
{
	register int temp ;
	extern int rept ;

	temp = rept ;
	rept = 0 ;
	if ( temp ) then do_ins(temp) ;
}




dorubout()
{
	extern int prevdelete,read_only ;
	register int eol ;
	register int ch ;

	if ( curch != RUB ) then return(0) ;
	eol = atcrlf() ;
	if ( eol && chposition == 0 ) then return(1) ;
	if ( eol ) then pdec() ;
	if ( read_only == 0 )
	  then	{
		if ( prevdelete != 0 && chposition != 0 && eol == 0 )
		  then vtel() ;
		ch = remchar(chposition) ;
		if ( eol )
		  then	{
			scmove() ;
			lkill() ;
			}
		  else	scremchar(ch) ;
		}
	return(1) ;
}

	  
