/*
 * Name:	MicroEMACS
 *		AT&T UNIX PC 7300/3b1 terminal display
 * Version:	29
 * Last edit:	25-Apr-86
 * By:		{sun, amdahl, mtxinu, cbosgd}!rtech!daveb
 *
 * This is nearly the ansi/tty.c, except the 7300 has broken scroll
 * region support with index and reverse index.  Instead we do it
 * with parameterized insert/delete lines.
 *
 * It also has "smart" support for the window system.
 */
#include	"def.h"

#define	BEL	0x07			/* BEL character.		*/
#define	ESC	0x1B			/* ESC character.		*/
#define	LF	0x0A			/* Line feed.			*/

extern	int	ttrow;
extern	int	ttcol;
extern	int	tttop;
extern	int	ttbot;
extern	int	tthue;

int	tceeol	=	3;		/* Costs, ANSI display.		*/
int	tcinsl	= 	17;
int	tcdell	=	16;

/*
 * Initialize the terminal when the editor
 * gets started up. This is a no-op on the ANSI
 * display.
 */
ttinit()
{
}

/*
 * Clean up the terminal, in anticipation of
 * a return to the command interpreter. This is a no-op
 * on the ANSI display. On the SCALD display, it sets the
 * window back to half screen scrolling. Perhaps it should
 * query the display for the increment, and put it
 * back to what it was.
 */
tttidy()
{
}

/*
 * Move the cursor to the specified
 * origin 0 row and column position. Try to
 * optimize out extra moves; redisplay may
 * have left the cursor in the right
 * location last time!
 */
ttmove(row, col)
{
	if (ttrow!=row || ttcol!=col) {
		ttputc(ESC);
		ttputc('[');
		asciiparm(row+1);
		ttputc(';');
		asciiparm(col+1);
		ttputc('H');
		ttrow = row;
		ttcol = col;
	}
}

/*
 * Erase to end of line.
 */
tteeol()
{
	ttputc(ESC);
	ttputc('[');
	ttputc('K');
}

/*
 * Erase to end of page.
 */
tteeop()
{
	ttputc(ESC);
	ttputc('[');
	ttputc('J');
}

/*
 * Make a noise.
 */
ttbeep()
{
	ttputc(BEL);
	ttflush();
}

/*
 * Convert a number to decimal
 * ascii, and write it out. Used to
 * deal with numeric arguments.
 */
asciiparm(n)
register int	n;
{
	register int	q;

	q = n/10;
	if (q != 0)
		asciiparm(q);
	ttputc((n%10) + '0');
}

/*
 * Insert a block of blank lines onto the
 * screen, using parameterized insert and delete line commands.
 *
 * Deal with the one
 * line case, which is a little bit special, with special
 * case code. Put all of the back index commands out
 * in a block. The SCALDstation loses the position
 * of the cursor.
 */
ttinsl(row, bot, nchunk)
{
	if (row == bot) {			/* Funny case.		*/
		if (nchunk != 1)
			abort();
		ttmove(row, 0);
		tteeol();
	} else {				/* General case.	*/
		ttwindow(row, bot);

		/* delete the lines that are going away */
		ttmove(bot + 1 - nchunk , 0);
		ttputc(ESC);
		ttputc('[');
		asciiparm( nchunk );
		ttputc('M');

		/* add the lines */
		ttmove(row, 0);
		ttputc(ESC);
		ttputc('[');
		asciiparm( nchunk );
		ttputc('L');
	}
}

/*
 * Delete a block of lines, with the uppermost
 * line at row "row", in a screen slice that extends to
 * row "bot". The "nchunk" is the number of lines that have
 * to be deleted. Watch for the pathalogical 1 line case.
 * Done using delete and insert line commands.
 */
ttdell(row, bot, nchunk)
{
	if (row == bot) {			/* Funny case.		*/
		if (nchunk != 1)
			abort();
		ttmove(row, 0);
		tteeol();
	} else {				/* General case.	*/

		/* delete the lines that are going away */
		ttmove(row, 0);
		ttputc(ESC);
		ttputc('[');
		asciiparm( nchunk );
		ttputc('M');

		/* insert new lines to fill the empty space */
		ttmove(bot + 1 - nchunk , 0);
		ttputc(ESC);
		ttputc('[');
		asciiparm( nchunk );
		ttputc('L');

	}
}

/*
 * This routine sets the scrolling window
 * on the display to go from line "top" to line
 * "bot" (origin 0, inclusive). The caller checks
 * for the pathalogical 1 line scroll window that
 * doesn't work right, and avoids it. The "ttrow"
 * and "ttcol" variables are set to a crazy value
 * to ensure that the next call to "ttmove" does
 * not turn into a no-op (the window adjustment
 * moves the cursor).
 */
ttwindow(top, bot)
{
	/* No-op on 7300 */
}

/*
 * Switch to full screen scroll. This is
 * used by "spawn.c" just before is suspends the
 * editor, and by "display.c" when it is getting ready
 * to exit. This function gets to full screen scroll
 * by sending a DECSTBM with default parameters, but
 * I think that this is wrong. The SRM seems to say
 * that the default for Pb is 24, not the size of the
 * screen, which seems really dumb. Do I really have
 * to read the size of the screen as in "ttresize"
 * to do this right?
 */
ttnowindow()
{
	/* No-op on 7300 */
}

/*
 * Set the current writing color to the
 * specified color. Watch for color changes that are
 * not going to do anything (the color is already right)
 * and don't send anything to the display.
 * The rainbow version does this in putline.s on a
 * line by line basis, so don't bother sending
 * out the color shift.
 */
ttcolor(color)
register int	color;
{
	if (color != tthue) {
		if (color == CTEXT) {		/* Normal video.	*/
			ttputc(ESC);
			ttputc('[');
			ttputc('m');
		} else if (color == CMODE) {	/* Reverse video.	*/
			ttputc(ESC);
			ttputc('[');
			ttputc('7');
			ttputc('m');
		}
		tthue = color;			/* Save the color.	*/
	}
}

/*
 * This routine is called by the
 * "refresh the screen" command to try and resize
 * the display. The new size, which must be deadstopped
 * to not exceed the NROW and NCOL limits, it stored
 * back into "nrow" and "ncol". Display can always deal
 * with a screen NROW by NCOL. Look in "window.c" to
 * see how the caller deals with a change.
 */
ttresize()
{
# if 0
	register int	c;
	register int	newnrow;
	register int	newncol;

	else if (newnrow > NROW)
		newnrow = NROW;
	if (newncol < 1)
		newncol = 1;
	else if (newncol > NCOL)
		newncol = NCOL;
	nrow = newnrow;
	ncol = newncol;
# endif
}
