/* Original Author:         Andrew Trevorrow
   Implementation: Modula-2 under VAX/UNIX 4.2 BSD
   Date Started:   June, 1986

   Description:
   Implements the InitANSI()procedure that initializes the generic VDU routines
   and parameters used in DVItoVDU.
   DVItoVDU assumes text lines start at 1 and increase down the screen; the
   same numbering scheme is used by ANSI standard terminals.  When updating the
   window (via ShowChar/ShowRectangle calls), DVItoVDU assumes the top left
   pixel on the screen is (0,0).  We need to add 1 to both DVItoVDU coordinates
   to get the correct position on the ANSI screen, since the top left position
   is actually (1,1).

   This version converted to C and ported to BSD and System V UNIX by
   some chaps at Kernel Technology up to September 1989.  Contact
   mjh@uk.co.kernel (Mark J. Hewitt) with bug fixes etc.

   Involved were:	Mark J. Hewitt
   			Dave Dixon
			Marc Hadley
*/

#include "def.h"

static char *sccsid[] = "@(#)ansivdu.c	1.1";

Void ANSIStartText ();
Void ANSIMoveToTextLine ();
void MoveAbs ();
Void ANSIClearTextLine ();
Void ANSIClearScreen ();
Void ANSIStartGraphics ();
Void ANSILoadFont ();
Void ANSIShowChar ();
Void ANSIShowRectangle ();
Void ANSIResetVDU ();

unsigned int  cursrow, curscol;	/* ANSI(*ShowChar)()remembers cursor location */

/******************************************************************************/

void InitANSI ()
{
/* For ANSI VDUs a screen pixel has to be an entire character position.
   The dialogue region will be the top 4 lines.
   The window region will be lines 5 to 24; it is 20 pixels high by 80
   pixels wide.
*/

  DVIstatusl = 1;
  windowstatusl = 2;
  messagel = 3;
  commandl = 4;
  bottoml = 24;

/* (windowh,windowv) uses DVItoVDU's coordinate scheme in which the top left
   pixel is at (0,0) */

  windowh = 0;
  windowv = 4;
  windowwd = 80;		/* changed to 132 if VDU==VT100132 */
  windowht = 20;

  StartText = ANSIStartText;
  MoveToTextLine = ANSIMoveToTextLine;
  ClearTextLine = ANSIClearTextLine;
  ClearScreen = ANSIClearScreen;
  StartGraphics = ANSIStartGraphics;
  LoadFont = ANSILoadFont;
  ShowChar = ANSIShowChar;
  ShowRectangle = ANSIShowRectangle;
  ResetVDU = ANSIResetVDU;
}

/******************************************************************************/

Void ANSIStartText ()
{
/* do nothing; text and graphics the same */
}

/******************************************************************************/

Void ANSIMoveToTextLine (line)
unsigned int  line;
{
/* Move cursor to start of given line. */

  MoveAbs (line, 1);
}

/******************************************************************************/

void MoveAbs (row, col)
unsigned int  row, col;
{
/* Move cursor to given screen position. */

  Write (ESC);
  Write ('[');
  WriteCard (row);
  Write (';');
  WriteCard (col);
  Write ('H');
}

/******************************************************************************/

Void ANSIClearTextLine (line)
unsigned int  line;
{

/* Erase given line; note that DVItoVDU does not assume anything about the
   cursor location at the end of this routine.
*/

  MoveAbs (line, 1);
  Write (ESC);
  WriteString ("[K");		/* erase to end of line */
}

/******************************************************************************/

Void ANSIClearScreen ()
{
  Write (ESC);
  WriteString ("[2J");		/* erase entire screen */
}

/******************************************************************************/

Void ANSIStartGraphics ()
{
/* ANSI VDUs make no distinction between text and graphics.
   All we do is reset the current cursor position to some undefined state for
   use in the next ANSIShowChar() call.
*/

  cursrow = 0;
}

/******************************************************************************/

/*ARGSUSED*/
Void ANSILoadFont (fontname, fontsize, localmag, hscale, vscale)
unsigned int  fontsize;
char  fontname[];
float   localmag, hscale, vscale;
{
/* only one character size available on most ANSI VDUs, so do nothing */
}

/******************************************************************************/

/* Show the given Terse character (mapped to ASCII) at the given position.
   We remember the cursor position (cursrow,curscol) so we can reduce the
   output bytes needed to position the next Terse character.
   StartGraphics resets the position to an undefined state (cursrow = 0).
   We also reset when the cursor reaches the right edge (= windowwd) to
   avoid possibility of any auto wrap.
*/

Void ANSIShowChar (screenh, screenv, ch)
unsigned int  screenh, screenv;
char  ch;
{
  unsigned int  amount;

/* first translate DVItoVDU coordinates into actual screen location */
  screenh++;
  screenv++;
  if (cursrow == screenv)
  {
  /* The cursor is on the same line as in previous ShowChar call so we only need to
     move left or right, and probably just a small amount (if at all). */
    if (screenh == curscol)
    {				/* cursor in correct location */
      curscol++;		/* cursor will move right when ch written */
    }
    else
      if (screenh < curscol)
      {				/* move cursor left */
	amount = curscol - screenh;
	Write (ESC);
	Write ('[');
	if (amount > 1)
	{			/* default is 1 col */
	  WriteCard (amount);
	  curscol -= (amount - 1);/* no need to do this if amount==1 */
	}
	Write ('D');
      }
      else			/* move cursor right */
      {
	amount = screenh - curscol;
	Write (ESC);
	Write ('[');
	if (amount > 1)
	{
	  WriteCard (amount);	/* default is 1 col */
	}
	curscol += amount + 1;
	Write ('C');
      }
  }
  else				/* cursrow undefined or ch on a new line */
  {
    MoveAbs (screenv, screenh);
    cursrow = screenv;
    curscol = screenh + 1;	/* cursor will move right when ch written */
  }
  if (screenh == ((unsigned) windowwd))
  {
  /* ch will be written at right edge */
    cursrow = 0;		/* so avoid auto wrap next time around */
  }
  Write (TeXtoASCII[ch]);
}

/******************************************************************************/

Void ANSIShowRectangle (screenh, screenv, width, height, ch)/* black pixel */
unsigned int  screenh, screenv, width, height;
char  ch;
{
/* Display the given rectangle using the given black pixel character.
   DVItoVDU ensures the entire rectangle is visible.
*/

  unsigned int  i, j;

/* first convert TeX ch to ASCII */
  ch = TeXtoASCII[ch];
  screenh++;
  for (i = 1; i <= height; i++)	/* adding 1 to screenv here! */
  {
  /* move cursor to start of next row */
    MoveAbs (screenv + i, screenh);
    for (j = 1; j <= width; j++)
    {
      Write (ch);
    }
  }
}

/******************************************************************************/

Void ANSIResetVDU ()
{
/* no need to do anything */
}

/******************************************************************************/



