/*
 * Name:	MicroEMACS
 *		Amiga console device virtual terminal display
 * Version:	31
 * Last Edit:	21-Apr-86
 * Created:	19-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
 * Modified:	21-Apr-86 ...!ihnp4!seismo!ut-sally!ut-ngp!mic
 *		In ttresize() use ttmove(HUGE,HUGE) and cursor
 *		position report to get the new window size 
 */

#include	"def.h"


#define	BEL	0x07			/* BEL character.		*/
#define	ESC	0x1B			/* ESC character.		*/

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 Amiga.
 */
ttinit()
{
}

/*
 * Clean up the terminal, in anticipation of
 * a return to the command interpreter. This is a no-op
 * on the Amiga.
 */
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 a scrolling region that starts at row
 * "row" and extends down to row "bot". Deal with the one
 * line case, which is a little bit special, with special
 * case code.
 *
 * Since we don't really have a scrolling region,
 * delete the block of lines that would have been deleted if
 * we'd had one, then insert blank lines to move the rest
 * of the screen back to where it belongs.  This idea from
 * the Heath driver.
 */
ttinsl(row, bot, nchunk)
{
	register int	i;

	if (row == bot) {			/* Funny case.		*/
		if (nchunk != 1)
			abort();
		ttmove(row, 0);
		tteeol();
		return;
	} 
	ttmove(1+bot-nchunk, 0);
	if (nchunk > 0) {		/* Delete a chunk of lines	*/
		ttputc(ESC);		/* nchunk in size.  Rest of	*/
		ttputc('[');		/* screen moves up.		*/
		asciiparm(nchunk);
		ttputc('M');
	}
	ttmove(row, 0);
	if (nchunk > 0) {		/* Insert a chunk nchunk in size*/
		ttputc(ESC);		/* before current line,	sliding	*/
		ttputc('[');		/* rest of screen down.		*/
		asciiparm(nchunk);
		ttputc('L');
	}
	ttrow = row;			/* End up on current line	*/
	ttcol = 0;
}

/*
 * 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.  This is done by deleting nchunk lines at
 * the appropriate spot, then inserting nchunk lines to make
 * up for the empty space at the bottom of the virtual scrolling
 * region.
 */
ttdell(row, bot, nchunk)
{
	register int	i;

	if (row == bot) {		/* One line special case	*/
		ttmove(row, 0);
		tteeol();
		return;
	}
	if (nchunk > 0) {
		ttmove(row, 0);
		ttputc(ESC);
		ttputc('[');
		asciiparm(nchunk);
		ttputc('M');
	}
	ttmove(1+bot-nchunk,0);
	if (nchunk > 0) {
		ttputc(ESC);		/* For all lines in chunk	*/
		ttputc('[');		/* INS line before bottom	*/
		asciiparm(nchunk);	/* Bottom of window (and rest 	*/
		ttputc('L');		/* of screen) moves down */
	}
	ttrow = HUGE;			/* Force ttmove() to do the move*/
	ttcol = HUGE;
	ttmove(bot-nchunk,0);
}

/*
 * No-op.
 */
ttwindow(top,bot)
{
}

/*
 * No-op.
 */
ttnowindow()
{
}

/*
 * 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.
 */
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, is 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.
 */
#define	CSI	0x9B

ttresize()
{
	register int newnrow, newncol;

	ttmove(HUGE,HUGE);		/* Go to bottom right		*/
	ttputc(CSI);			/* See where cursor went to	*/
	ttputc('6');
	ttputc('n');
	ttflush();

	if (ttgetc() != CSI)			/* parse the report 	*/
		return;
	if ((newnrow = readparm(';')) == -1)
		return;
	if ((newncol = readparm('R')) == -1)
		return;

	if (newnrow < 1)			/* check limits.	*/
		newnrow = 1;
	else if (newnrow > NROW)
		newnrow = NROW;
	if (newncol < 1)
		newncol = 1;
	else if (newncol > NCOL)
		newncol = NCOL;
	nrow = newnrow;
	ncol = newncol;
}

/*
 * Read an unsigned number from the terminal
 */
static readparm(delim)
char delim;
{
	register int 	parm;
	register int	c;

	parm = 0;
	while ((c=ttgetc()) >= '0' && c <= '9')
		parm = 10 * parm + c - '0';
	return (c == delim) ? parm : -1;
}

