/*************************************************************************
*
*
*       Name:  ibmtip.c
*
*       Description:  IBM TIP for sform routines.
*
*
*       History:
*       Date            By              Comments
*
*       04/20/84        waf		Modified from screen.c.
*		05/27/84		waf		Renamed fn's (prepended an 's').
*
*
*
*  This document contains confidential/proprietary information.
*
*  Copyright (c) 1983, 1984 by Digital Communication Assoc..
*
************************************************************************/




/*  Notes -

	**>> This is not the same as the 'CFood' version.
	This version is dedicated to the sform routines.

	NOTE that stputc() has * integer * args and stgetc() returns a * character *
	value. See notes in stputc().

	See also ibmtip.h.


	To Do -
	> Disable scrolling (don't use TTY output?).
	> Fill out TIP conversion code tables.

*/

/************************************************************************/
/*																		*/
/*	Screen Handling subroutines for the PC/XT.							*/
/*																		*/
/*	These routines are an adaptation and enhancement of the				*/
/*	IBMTIP routines, hence the similarity in name.						*/
/*																		*/
/*	These rotuines are NOT interchangeable with the others and			*/
/*	they contain features that the Lattice IBMTIP routines do not.		*/
/*																		*/
/************************************************************************/



#define		DBUG	0

#include        "ibmtip.h"


/* TIP global vars */
int		tp_ascii ;			/* ASCII value of last char input */
int		tp_vmode = 0x07 ;	/* video mode */
char	(*tp_dalptr)[] = (char (*)[]) matrlst ;
/* display attr list ptr.
							   This is a ptr to an array of attr bytes,
							   indexed by the attr code */


static	char	vab[4]	= {
	0,0,79,24};	/* video area block */
static	char	vnorm	= 0x07; 		/* normal */

static	char	vatrbyte = 0x07;		/* current video attribute */
static	unsigned vatrcode = TA_NORM ;	/* symbolic attr code */

stinit ()

/*
  Synopsis -
	Set up to use TIP routines (initialize).

  Description -

  Return -
	return val	= <undefined>

  Notes -
*/

{
	register int	i, j ;

	/* Get video mode */
	i = pcvgvm() ;
	j = i >> 8 ;
	j-- ;
	vab[2] = (char) j ;		/* # columns */
	tp_vmode = i & 255 ;	/* video mode */
#if DBUG
	printf(">>tinit: #col, mode = %d %d\n", (int)vab[2], tp_vmode) ;
#endif
	switch ( tp_vmode ) {
	case  3 :
		/* color monitor */
		tp_dalptr = (char (*)[]) catrlst ;		/* attribute list ptr */
		break ;
	default :
		/* assume monochrome */
		tp_dalptr = (char (*)[]) matrlst ;		/* attribute list ptr */
	}
}



stterm ()

/*
  Synopsis -
	Reset terminal characteristics.

  Description -
	$

  Return -
	return val	= <undefined>

  Notes -
*/

{

	/* Nothing to do */
}

/************************************************************************/
/*																		*/
/*	tputc - put a character to the screen.								*/
/*																		*/
/* synopsis																*/
/*																		*/
/*	n = tputc(c,d,e)													*/
/*	int	n;	returns an integer = number of chars used					*/
/*	char	c;	character to be output									*/
/*	char	d,e;	additional characters, used when c is a command		*/
/*																		*/
/* description															*/
/*																		*/
/*	This function will output the character c to the screen with		*/
/*	the attribute wich is currently selected.  If c is one of the		*/
/*	command characters defined in screen.c(c > 127) then tputc will		*/
/*	perform the desired screen function, in lieu of writing a 			*/
/*	character to the screen.											*/
/*
/* Notes -																*/
/* > Reverse video and underline attributes can not be combined on the PC. */
/*	**>> NOTE
		The input args are defined as INTEGER in this function, but
		the calling code may be sending a char value.
		This code takes advantage of the fact that 'char's are converted
		to 'int's before being used as a fn arg.
		Note that all 'sign extended' char input args can be differentiated 
		from TIP codes.													*/
/* > The 'clear screen' and 'erase to end of line' fill with 'normal'
     display characteristics.
	 Codes could be added to 'paint' (screen/to end of line/blk) with
	 any given characteristic.
/*																		*/
/*																		*/
/************************************************************************/


stputc(c,d,e)
int	 c,d,e;			/* <<** NOTE */
{
	int x;
	char row,col,n,y,rsave,csave,sb[4];
	register unsigned ic ;


	ic = (c < 0)? (0 -c) : c ;		/* <<** NOTE */

	n = 1;					/* return value of 1 */
	pcvgcp(&row,&col);			/* get current cursor pos */

	if ( ic > 255 /* NOTE */ ) switch (ic) {

	case TO_INIT:
	case TO_CS:			/* clear the screen */
		pcvsu(vab,0,vnorm);
	case TO_MCH:			/* move the cursor home */
		row =0; 
		col = 0;
		goto move;

#if	(SMALLTIP == 0)
	case TO_MCU:			/* move cursor up one line */
		--row;
		goto move;
	case TO_MCD:			/* move cursor down one line */
		++row;
		goto move;
	case TO_MCR:			/* move cursor right one */
		++col;
		goto move;
#endif

	case TO_MCL:			/* move cursor left one */
		--col;
		goto move;

#if	(SMALLTIP == 0)
	case TO_MCV:			/* move cursor vertically */
		row = d;
		col = 0;
		n = 2;
		goto move;
#endif

	case TO_MC:			/* move cursor */
		row = d;
		col = e;
		n = 3;			/* uses three characters */
move:					/* do the movement */
		if(row == 255)
			break;
		if(col == 255)
			break;
		if(row > vab[3])	/* test boundaries */
			break;
		if(col > vab[2])
			break;
		pcvscp(row,col);	/* put cursor at new position */
		break;

	case TO_ERL:			/* erase to end of line */
		pcvwca(vab[2]-col+1,' ',vnorm);
		break;

#if	(SMALLTIP == 0)
	case TO_ERS:			/* erase to end of screen */
		rsave = row;  
		csave = col;
		while(row <= vab[3]) {
			pcvscp(row++,col);
			pcvwca(vab[2]-col+1,' ',vnorm);
			col = 0;
		}
		pcvscp(rsave,csave);	/* restore cursor */
		break;
	case TO_INS:			/* insert a line */
		sb[0] = vab[0];
		sb[1] = row;
		sb[2] = vab[2];
		sb[3] = vab[3];
		pcvsd(sb,1,vattr);
		pcvscp(row,vab[0]);
		break;
	case TO_DELLN:			/* delete a line */
		sb[0] = vab[0];
		sb[1] = row;
		sb[2] = vab[2];
		sb[3] = vab[3];
		pcvsu(sb,1,vattr);
		pcvscp(row,vab[0]);
		break;
	case TO_INSP:			/* insert a  space */
		csave = col;
		y = ' ';
		do {
			x = pcvrca();	/* read a character */
			pcvwrt(y);	/* write previous character */
			y = x;
		} 
		while( col++ <= vab[2]);
		pcvscp(row,csave);	/* replace the cursor */
		break;
	case TO_DEL:			/* delete a character */
		csave = col;
		while( col < vab[2] - 1) {
			pcvscp(row,col + 1);
			x = pcvrca();
			pcvscp(row,col++);
			pcvwrt(x);
		}
		pcvwrt(' ');
		pcvscp(row,csave);
		break;

#if	DAREDUN
	case TO_VN:			/* video normal */
		vattr = vnorm;
		goto attr;

	case TO_VR:			/* video reverse */
		vattr = vrvrs;
		goto attr;

	case TO_VNF:			/* video normal flashing */
		vattr = vnormf;
		goto attr;

	case TO_VRF:			/* video reverse flashing */
		vattr = vrvrsf;
		goto attr;
	case TO_VB:			/* video bright */
		vattr = vbright;
		goto attr;
#endif

	case TO_FRA:			/* the the rows attributes */
		csave = col;
		col = 0;
		while(col <= vab[2]) {
			pcvscp(row,col++);	/* position cursor */
			y = pcvrca();		/* read the character */
			pcvwca(1,y,vattr);	/* write char + attr */
		}
		pcvscp(row,csave);
		break;
#endif

		/* DG style video attribute control */
	case TO_SDIM :		/* Start dim field */
		vatrcode |= TA_DIM ;
		goto attr ;
	case  TO_EDIM :		/* End dim field */
		vatrcode &= ~TA_DIM ;
		goto attr ;
	case  TO_SUNDL :	/* Start Underline */
		vatrcode |= TA_UNDL ;
		goto attr ;
	case  TO_EUNDL :	/* End Underline */
		vatrcode &= ~TA_UNDL ;
		goto attr ;
	case  TO_SBLNK :	/* Start Blinking */
		vatrcode |= TA_BLNK ;
		goto attr ;
	case  TO_EBLNK :	/* End Blinking */
		vatrcode &= ~TA_BLNK ;
		goto attr ;
	case  TO_SREV :		/* Start Reverse Video */
		vatrcode |= TA_REV ;
		goto attr ;
	case  TO_EREV :		/* End Reverse Video */
		vatrcode &= ~TA_REV ;
		goto attr ;
	case  TO_VNORM :		/* Set to 'normal' attrs */
		vatrcode = TA_NORM ;
attr:
		/* Set attr char, using vatrcode value */
		vatrbyte = (*tp_dalptr)[vatrcode] ;
		pcvsfc(vatrbyte);		/* set foreground color */
		break;	

	case  TO_BELL :			/* Sound Bell */
		stputc(TP_BELL) ;
		break ;

	default:			/* not a command */
		/* pcvwca(1,' ',vatrbyte);	waf */
		/* pcvwrt(c);			waf */
		n = 0;
	}
	else {					/* an ordinary character */
		if ( ((int) c & 255) >= 32 )		/* waf */
			pcvwca(1,' ',vatrbyte);
		pcvwrt(c);
	}
	return(n);
}

stputa ( ary, cnt )

int		ary[] ;		/* list of chars / codes */
int		cnt ;		/* # of chars / codes */

/*
  Synopsis -
	stputc() a list of characters / TIP codes.

  Description -
	This fn takes the place of 'stputs()'. It can handle both 'characters'
	and TIP codes.

  Return -
	return val	= <undefined>

  Notes -
  **>> NOTE - The input values are * integer *.
  > Note that this fn is no more efficient than calling stputc() for each
  value.
*/

{
	register int	ix ;
	register int	i ;


	ix = 0 ;
	while ( ix < cnt ) {
		if ( (i = stputc(ary[ix], ary[ix+1], ary[ix+2])) )
			ix += i ;
		else
			ix++ ;		/* ignore undefined code */
	}
}



stputs ( str )

char	*str ;

/*
  Synopsis -
	stputc() a list of CHARACTER values.
	This fn will NOT handle TIP codes.

  Description -
	The string must be null terminated.

  Return -
	return val	= $

  Notes -
  > Note that this is a much simpler version of the original tputs().
	This version CAN NOT HANDLE CONTROL CODES.
*/

{
	register char	*cp ;
	register char	c ;


	cp = str ;
	while ( (c = *cp++) )
		stputc(c) ;
}

/*****************************
**							**
**		Input routines		**
**							**
*****************************/


static	int		pushchar = 0 ;		/* 'Push stack' */



/* Extended control code to TIP code conversion table
   (Function keys not included) */
static	char	ecc2tip[][2] = {
	/*	ECC		TIP			*/
	TP_DEL,	TI_DEL,		/* DEL key		*/
	TP_BTAB, TI_BTAB,	/* Back Tab		*/
	0,		TI_UNDCC
} 
;

/* ASCII control code to TIP code conversion table */
static	char	asc2tip[][2] = {
	/*	ASCII	TIP			*/
	TP_CR,	TI_UNP,		/* Unpend		*/
	TP_NL,	TI_UNP,		/* Unpend		*/
	TP_BS,	TI_DEL,		/* Delete (???) */
	TP_ESC,	TI_ESC,		/* Escape key	*/
	TP_QUIT, TI_QUIT,	/* Quit (^C)	*/
	TP_LCAN, TI_CAN,	/* Line cancel (^U) */
	TP_FTAB, TI_FTAB,	/* Fwd Tab		*/
	0,		TI_UNDCC
} 
;

int		stgetc ()

/*
  Synopsis -
	Get next input character.
	Control chars are translated to TIP codes.
	NOTE that return value is an integer, and is NOT sign-extended.

  Description -
	$

  Return -
	return val	= Integer value representing
					an ASCII char or code ( 0 - 127 )
				  or
					TIP code ( 128 - 255 )

  Notes -
*/

{
	register unsigned  scan, ascii ;
	int		tpop() ;




	/* Chk 'stack' */
	if ( pushchar ) {
		/* Return stk value */
		tp_ascii = (int) tpop() ;
		return(tp_ascii) ;
	}


	/** Get next char **/
	while ( pckchk() == 0 )
		;			/* wait for char */
	ascii = pckrc() ;		/* get scan code and ascii code */
	scan = ascii >> 8 ;	/* scan code */
	ascii = ascii & 255 ;	/* BIOS ascii translation */
	tp_ascii = ascii ;		/* save ascii code */
	if ( ascii ) {

		/* ASCII value */
		if ( ascii < 32 ) {		/* ??? */
			/* ASCII control code */
			ascii = tipcode((char)ascii, asc2tip) ;	/* Convert to TIP code */
		}
	}
	else {

		/* Extended character.
				   Get 'extended' code using scan code value */
		if ( scan >= TP_FLO && scan <= TP_AFHI ) {

			/* Function key */
			if ( scan <= TP_FHI )
				/* Normal */
				ascii = TI_F1 + (scan - TP_FLO) ;
			else if ( scan < TP_SFLO )
				goto getecc ;		/* control code */
			else if ( scan <= TP_SFHI )
				/* Shifted */
				ascii = TI_SF1 + (scan - TP_SFLO) ;
			else if ( scan <= TP_CFHI )
				/* Control */
				ascii = TI_CF1 + (scan - TP_CFLO) ;
			else
				/* Alt */
				ascii = TI_AF1 + (scan - TP_AFLO) ;
		}

		else {

getecc:
			/* Extended Control code */
			ascii = tipcode((char)scan, ecc2tip) ;
		}
	}

	return(ascii) ;
}

stgets ( strptr )

char	*strptr ;

/* Get a string, which is a sequence of 0 or more characters terminated
   with the TI_UNP char.
   The return string is null terminated (and does not contain the unpend
   character).
*/

{
	register char	*cp ;


	cp = strptr ;
	while ( (*cp = stgetc()) != TI_UNP )
		cp++ ;
	*cp = '\0' ;		/* null term return str */
}

static	tipcode ( code, codetbl )

char	code ;			/* value to convert to TIP code */
char	codetbl[][2] ;	/* code conversion table */

/* Convert the input value to a TIP code, using the input conversion table.
   The table is terminated by a code value of '0' and a TIP code of 'TI_UNDCC'.
   
   Return value = TIP (int) code (from table),
				  or TI_UNDEF if value not in table.
*/

{
	register int	ix ;
	register char	x ;
	int		rv ;


	for ( ix = 0 ; (x = codetbl[ix][0]) ; ix++ ) {
		if ( x == code )
			break ;
	}

	rv = ((int) codetbl[ix][1]) & 255 ;		/* TIP code */
	return(rv) ;
}

stpush ( c )

int		c ;

/* Push a char.

   Notes -
   > '0' flag is currently ignored.
   > 'Stack' overflow is NOT checked.
*/

{


	if ( c != 0 )
		pushchar = c ;		/* overflow not checked */
}



static	int		tpop ()

/* 'Pop' the top value on the input char stack.
*/

{
	register int	rv ;


	rv = pushchar ;
	pushchar = 0 ;		/* 'Clear' the stack */
	return(rv) ;
}
