#include	"sysdef.h"

#include	"scerrd.h"
#include	"scterm.h"
#define	then
#define	true	1
#define	false	0
#define	TRUE	1
#define	FALSE	0
#define	SPACE	040
#define	TAB	011
#define	CR	015
#define	LF	012
#define	ESC	033

extern int	*curline,*loclow,*lochigh,*maxline,termtype ;
extern int	sts_one ;




/*	GETFUNCOMMAND()						*/
/*								*/
/*	For VT100 and ANSI, return the third character from the	*/
/*	escape sequence. For the VT220, return the 3rd character*/
/*	if it's not a digit, else look ahead for another digit.	*/
/*	Return numeric value of the digit string, 1..34		*/

int getfuncommand()
{
	register int ch,ch1 ;

	switch( termtype ) {
	  case _ANSI:
	  case _VT100:
	  case _VT220:
		vtgetc() ;
		ch = vtgetc() ;
		if ( isdigit(ch) )
		  then	{
			ch1 = vtgetc() ;
			if ( isdigit(ch1) )
			  then	{
				vtgetc() ;
				return( (ch-'0')*10 + (ch1-'0') ) ;
				}
			  else	return( ch-'0' ) ;
			}
		  else	return( ch ) ;
		}
}



/*	SCREMCHAR()							*/
/*									*/
/*	 Do something intelligent about removing  a single character	*/
/*	from the display, most useful for VT220. Note that the VT220	*/
/*	DCH editing function is executed by the  firmware AFTER tabs	*/
/*	are mapped to spaces,  thus we can't use it if there are any	*/
/*	tabs from the current position to the end of the line.		*/

#define	NOP

scremchar(ch)
char ch ;
{
	extern int termtype ;
	extern int chposition,worklength ;
	extern char workbuffer[] ;
	register char *cp ;
	register int i ;
	register int f ;

	switch( termtype ) {
	  case _VT100:
		scmove() ;
		lkill() ;
		partdump() ;
		scmove() ;
		break ;
	  case _ANSI:
	  case _VT220:
		cp = &workbuffer[chposition] ;
		for (i=chposition;i<worklength && (f=(*cp++==TAB))==0;i++) NOP;
		if ( f || ch == TAB )
		  then	{
			scmove() ;
			lkill() ;
			partdump() ;
			scmove() ;
			}
		  else	{
			scmove() ;
			putbin("\033[P",0) ;
			}
		break ;
		}
}



/*	SCINECHO(CH)							*/
/*									*/
/*	Decide how to insert a character into the display		*/

scinecho(ch)
char ch ;
{
	extern int erasef,termtype ;
	extern int chposition,worklength ;
	extern char workbuffer[] ;
	register char *cp ;
	register int i ;
	register int f ;

	switch( termtype ) {
	  case _VT100:
		if ( erasef || ch == TAB ) then lkill() ;
		puttrbin(&ch,1) ;
		partdump() ;
		scmove() ;
		break ;
	  case _ANSI:
	  case _VT220:
		cp = &workbuffer[chposition] ;
		for (i=chposition;i<worklength && (f=(*cp++==TAB))==0;i++) NOP;
		if ( f || ch == TAB )
		  then	{
			lkill() ;
			puttrbin(&ch,1) ;
			partdump() ;
			scmove() ;
			}
		  else	{
			putbin("\033[@",0) ;
			puttrbin(&ch,1) ;
			scmove() ;
			}
		break ;
		}		
}



puttrbin(s,passedlen)
register char *s ;
int passedlen ;
{
	register char *cp ;
	register int i,len,size ;
	extern int escprint,read_only,termtype ;

	if ( ( len = passedlen ) == 0 ) then len = strlen(s) ;
	if ( escprint == 0 || read_only )
	  then	putbin(s,len) ;
	  else
		if ( instr(s,len,"\033",1) == 0 )
		  then	putbin(s,len) ;
		  else	{
			cp = s ;
			size = 0 ;
			for ( i=len; i>0; i-- ) {
			  if ( *s != ESC )
			    then {
				s++ ;
				size++ ;
				 }
			    else {
				if (size) then putbin(cp,size) ;
				cp = ++s ;
				size = 0 ;
				switch(termtype) {
				  case _VT100:
				  case _VT220:
					putbin("\033(0`\033(B",0) ;
					break ;
				  case _ANSI:
					putbin("$",1) ;
					break ;
				  default:
					putbin("$",1) ;
					break ;
					}	
				}
			}				/* end FOR */
			if (size) then putbin(cp,size) ;
		}
}




int scdelline(nlines)
int nlines ;
{

	register int res,savecurline ;

	switch (termtype) {

		case _VT100:
			res = dvt100(nlines) ;
			break ;
		case _VT220:
			res = dansi(nlines) ;
			break ;
		case _ANSI:
			res = dansi(nlines) ;
			break ;

		default:
			res = 0 ;
			break ;

		}
	scloadline() ;
	scmove() ;
	return(res) ;
}


static char del_line[] = { '\033','[','M' } ;

static int dansi(nlines)
int nlines ;

{
	register int temp ;
	int savecurline   ;


	temp = *lochigh - nlines ;
	if ( nlines > 4 || temp <= 0 )
	  then	{
	     ref_screen() ;
	     return(1) ;
		}
	  else	{
		
	     while ( nlines > 0 ) {

		scmove() ;
		putbin(del_line,3) ;
		savecurline = *curline ;
		*curline = *lochigh ;
		scmove() ;
		*curline -= (nlines-1) ;
		scloadline() ;
		dumpworkbuffer() ;
		*curline = savecurline ;
		scloadline() ;
		scmove() ;
		nlines-- ;
		}
		if ( (_vtnolines & sts_one)==0 ) then redolines() ;
	      }
	return(1) ;
}
		


static int dvt100(nlines)
int nlines ;

{
	register int temp,temp1 ;
	int savecurline   ;


	temp = *lochigh - nlines ;
	if ( nlines > 3 || temp <= 0 )
	  then	{
	     ref_screen() ;
	     return(1) ;
		}
	  else	{
		
	     while ( nlines > 0 ) {

		scmove() ;
		lkill() ;
		temp = *curline - *loclow + 2 ;
		temp1 = *lochigh - *loclow + 3 ;
		setscrolling(temp,temp1) ;
		savecurline = *curline ;
		*curline = *lochigh ;
		scmove() ;
		putbin("\033[B\015\012\033[J",0) ;
		scmove() ;
		*curline -= (nlines-1) ;
		scloadline() ;
		dumpworkbuffer() ;
		*curline = savecurline ;
		nlines-- ;
		}
		setscrolling(2,23) ;
		if ( (_vtnolines & sts_one) == 0 ) then redolines() ;
	      }
	return(1) ;
}





#define	ESCAPE	033

setscrolling(lowline,highline)
int lowline,highline;

{
	char tbuffer[10] ;
	register char *cp ;

	if ( termtype != _VT100 ) then return(0) ;
	cp = tbuffer ;
	*cp++ = ESCAPE ;
	*cp++ = '[' ;
	*cp++ = ( lowline/10 ) + '0' ;
	*cp++ = ( lowline % 10 ) + '0' ;
	*cp++ = ';' ;
	*cp++ = ( highline/10 ) + '0' ;
	*cp++ = ( highline % 10 ) + '0' ;
	*cp++ = 'r' | 040 ;
	*cp++ = '\0' ;
	putbin(tbuffer,0) ;
	return(0) ;
}
	




static char eofrec[] = "\033[7m  <EOF>\033[0m" ;

inseofmark()
{
	extern int termtype ;

	switch(termtype) {
	  case	_VT100:
	  case	_VT220:
	  case	_ANSI:
		doinsert(*maxline,eofrec,strlen(eofrec)) ;
		break ;
		}
	return(1) ;
}

deleofmark()
{
	extern int worklength ;
	extern char workbuffer[] ;

	if ( *maxline == 2 )
	  then	{
		*curline = 1 ;
		scloadline() ;
		workbuffer[0] = CR ;
		workbuffer[1] = LF ;
		worklength = 2 ;
		scunloadline() ;
		return(1) ;
		}
	  else
		return( delline(*maxline-1) ) ;
}


ateofmark()
{
	extern int *curline,*maxline ;

	return(*curline == *maxline-1 ) ;
}





char *genmove(s)
char *s ;
{

	*s = 0 ;
	switch (termtype) {

	  case _VT100:
	  case _VT220:
	  case _ANSI:
		mvt100_cursor(s) ;
		break ;
	  default:
		break ;
	}
	return(s) ;
}

scmove()
{
	char buffer[20] ;
	putbin(genmove(buffer),0) ;
	return(1) ;
}


static mvt100_cursor(buffer)
char *buffer ;
{
	register char *cp ;
	register int temp ;

	extern int curposition,*curline,fastio,lastx,lasty,*loclow ;
	extern int leftmargin,rltime,termtype ;


	cp = buffer ;
	if (fastio != 0 && *curline == lasty)
	  then	{
		if ( (temp = curposition - lastx) == 0 ) then return(0) ;
		if (temp < 0) then temp = (-temp) ;
		if ( --temp == 0 && ++rltime < 6 )
		  then	{
			*cp++ = ESCAPE ;
			*cp++ = '[' ;
			*cp++ = (curposition-lastx > 0) ? 'C' : 'D' ;
			*cp++ = 0 ;
			}
		  else	moveabs(cp) ;
		 }
          else	moveabs(cp) ;

	lastx = curposition ;
	lasty = *curline ;
	return(0) ;
}



static moveabs(cp)
char *cp ;
{
	register int temp ;

	extern int curposition,*curline,fastio,lastx,lasty,*loclow ;
	extern int leftmargin,rltime,termtype ;

	rltime = 0 ;
	temp = ( termtype==_VT100 || termtype==_VT220 ) ?2:1 ;
	temp = *curline - *loclow + temp ;
	*cp++ = ESCAPE ;
	*cp++ = '[' ;
	*cp++ = temp/10 + '0' ;
	*cp++ = temp % 10 + '0' ;
	*cp++ = ';' ;
	if ( (temp = curposition + leftmargin) >= 100 )
	  then	{
		*cp++ = temp/100 + '0' ;
		temp = temp % 100 ;
		}
	*cp++ = temp/10 + '0' ;
	*cp++ = temp % 10 + '0' ;
	*cp++ = 'H' & 0137 ;
	*cp   = '\0' ;
}



scxnewline()
{
	extern int termtype ;

	switch (termtype) {

		case _VT100:
			nlvt100() ;
			break ;
		case _VT220:
		case _ANSI:
			nlansi() ;
			break ;
		default:
			break ;
		}
}




static char crlf[] = { '\015','\012' } ;

static putcrlf()
{
	putbin(crlf,2) ;
}


static char mind[] = { 033,'M' } ;

static nlvt100()
{
	extern int *curline,doiref,dopage,*loclow,*lochigh;

	doiref = 0 ;
	if ( dopage )
	  then	{
		scmove() ;
		putcrlf() ;
		lnext() ;
		scmove() ;
		lkill() ;
		dopage = 0 ;
		}
	  else	{
		setscrolling( *curline - *loclow + 2,23) ;
		scmove() ;
		putbin(mind,2) ;
		setscrolling(2,23) ;
		scmove() ;
		if ( *curline >= *lochigh ) then lkill() ;
		}
}


static char insl[] = { 033,'[','L' } ;

static nlansi()
{
	extern int *curline,doiref,dopage,*loclow,*lochigh;

	doiref = 0 ;
	scmove() ;
	if ( dopage == 0 )
	  then	{
		putbin(insl,3) ;
		scmove() ;
		}
	  else	{
		putcrlf() ;
		lnext() ;
		scmove() ;
		skill() ;
		dopage = 0 ;
		}
}	





static char savpos[] = { 033,'7',0 } ;
static char rstpos[] = { 033,'8',0 } ;

loading()
{
	extern int termtype ;

	switch( termtype ) {
	  case	_VT100:
	  case	_VT220:
		putbin("\015\033[K",0) ;
		putbin("\033[7mLoading...\033[0m\015",0) ;
		settimerast(6,loading) ;
		break ;
	  default:
		break ;
		} ;
}


working()
{
	extern int termtype ;

	switch( termtype ) {
	  case	_VT100:
	  case	_VT220:
		putbin(savpos,0) ;
		ceol24() ;
		rvon() ;
		putbin("Working...",0) ;
		rvoff() ;
		putbin(rstpos,0) ;
		settimerast(3,working) ;
		break ;
	  case	_ANSI:
	  default:
		break ;
		}
}
