/* falco5220e , copied from vt220 to take advantage of falco's
   larger character matrix */

/* Marc Hadley.  Kernel Technology Limited.  July 1989 */

#include "def.h"

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

extern Void ANSIClearTextLine(),
            ANSIMoveToTextLine(),
            ANSILoadFont();

extern void InitVT220();

Void FalcoShowBitmap ();
Void FalcoClearScreen ();
Void FalcoStartGraphics ();
Void FalcoShowChar ();
Void FalcoShowRectangle ();
Void FalcoResetVDU ();
Void FalcoLoadPixels ();
Void FalcoMoveQuick ();

unsigned int  Fcursrow, Fcurscol;/* VT220ShowChar()remembers cursor location */

#define HPIXELS 1		/* horizontal pixels per char position */
#define VPIXELS 4		/* vertical pixels per char position */
#define FLAG 7			/* SYSDEP: to overcome a compiler limitation */
#define HSCREENMAX 131		/* max horizontal char coordinate */
#define VSCREENMAX 23		/* max vertical char coordinate */

typedef short FBitValue;

 /* SYSDEP: was 0..VPIXELS but compiler seemed to have trouble with an array element
    size of 6 bits!!! */
typedef short FByteSet;

int  Frectcount;	/* keeps a count of FalcoShowRectangle calls; reset
				   in FalcoShowBitmap() */
short   FBitmap[HSCREENMAX + 1][VSCREENMAX + 1];

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

void InitFalco ()
{

/* The dialogue region is the top 4 lines.
   The window region is the remaining area of the screen
   (the bottom 20 rows in Bitmap).
*/

  DVIstatusl = 1;
  windowstatusl = 2;
  messagel = 3;
  commandl = 4;
  bottoml = VSCREENMAX + 1;
/* DVItoVDU's coordinate scheme is the same as the Falco scheme. */
  windowh = 0;
  windowv = 4 * VPIXELS;	/* = height of 4 dialogue lines */
  windowwd = (HSCREENMAX + 1) * HPIXELS;
  windowht = (VSCREENMAX + 1) * VPIXELS - windowv;

  StartText = FalcoShowBitmap;	/* flush the graphics Bitmap */
  MoveToTextLine = ANSIMoveToTextLine;
  ClearTextLine = ANSIClearTextLine;
  ClearScreen = FalcoClearScreen;
  StartGraphics = FalcoStartGraphics;
  LoadFont = ANSILoadFont;
  ShowChar = FalcoShowChar;
  ShowRectangle = FalcoShowRectangle;
  ResetVDU = FalcoResetVDU;

  Write (ESC);
  WriteString ("[?3h");		/* 132 column mode */
  FalcoLoadPixels ();
}

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

Void FalcoLoadPixels ()
{

/* Down-load the chunky graphics character set into the Falco. */

  Write (ESC);
  Write ('P');
  WriteString ("<1;1;0;2{E");
  WriteString ("NNNNNNNN/????????/????????;");
  WriteString ("oooooooo/BBBBBBBB/????????;");
  WriteString ("~~~~~~~~/BBBBBBBB/????????;");
  WriteString ("????????/{{{{{{{{/????????;");
  WriteString ("NNNNNNNN/{{{{{{{{/????????;");
  WriteString ("oooooooo/~~~~~~~~/????????;");
  WriteString ("~~~~~~~~/~~~~~~~~/????????;");
  WriteString ("????????/????????/NNNNNNNN;");
  WriteString ("NNNNNNNN/????????/NNNNNNNN;");
  WriteString ("oooooooo/BBBBBBBB/NNNNNNNN;");
  WriteString ("~~~~~~~~/BBBBBBBB/NNNNNNNN;");
  WriteString ("????????/{{{{{{{{/NNNNNNNN;");
  WriteString ("NNNNNNNN/{{{{{{{{/NNNNNNNN;");
  WriteString ("oooooooo/~~~~~~~~/NNNNNNNN;");
  WriteString ("~~~~~~~~/~~~~~~~~/NNNNNNNN");

 /* SYSDEP: compiler did not like '\' !!! */
  Write (ESC);
  Write (0134);

  Write (ESC);
  WriteString ("*E");		/* set as G1 character set */
}

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

void FalcoClearBitmap ()
{
/* Clear the Bitmap. */
  unsigned int  h, v;

  for (v = 4; v <= VSCREENMAX; v++)/* ignore dialogue lines 0..3 */
  {
    for (h = 0; h <= HSCREENMAX; h++)
    {
      FBitmap[h][v] = 0;	/* ByteSet {} */
    }
  }
}

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

Void FalcoShowBitmap ()
{

/* Display only the flagged characters in the Bitmap. */

  unsigned int  h, v;

/*Write(SO);    assume only working over 7 bit comm lines */

  Write (ESC);
  Write ('n');
  for (v = 4; v <= VSCREENMAX; v++)/* ignore dialogue lines */
  {
    for (h = 0; h <= HSCREENMAX; h++)
    {
      if ((1 << FLAG) & FBitmap[h][v])
      {
      /* send flagged character */
	FBitmap[h][v] = (FBitmap[h][v] & (~(1 << FLAG)));/* clear flag */
	FalcoMoveQuick (h, v);
	Write ((char) (((unsigned) FBitmap[h][v]) + 32));
      }
    }
  }
  Write (SI);			/* assume only working over 7 bit comm lines */
  WriteBuffer ();
  Frectcount = 0;
}

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

Void FalcoClearScreen ()
{
  Write (ESC);
  WriteString ("[2J");		/* erase entire screen */
  FalcoClearBitmap ();		/* reset Bitmap */
}

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

Void FalcoStartGraphics ()
{

/* Note that DVItoVDU will only call LoadFont, ShowChar and ShowRectangle
   while in graphics mode.
*/
  Frectcount = 0;
  Fcursrow = 0;			/* for FalcoMoveQuick() */
}

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

Void FalcoMoveQuick (screenh, screenv)
unsigned int  screenh, screenv;
{

/* Move cursor to given screen position.
   We remember the cursor position (cursrow,curscol) so we can reduce the
   output bytes needed to do the next MoveQuick()
   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.
*/
  unsigned int  amount;

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

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

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

/* Show the given Terse character (mapped to ASCII) at the given position. */

  if (Frectcount > 0)
  {
  /* flush Bitmap if ShowRectangle/s are pending */
    FalcoShowBitmap ();
  }
  FalcoMoveQuick (screenh, screenv / VPIXELS);
  Write (TeXtoASCII[ch]);
}

/******************************************************************************/
/*ARGSUSED*/
Void FalcoShowRectangle (screenh, screenv,/* top left pixel */
  width, height,		/* size of rectangle */
  ch)				/* black pixel */
unsigned int  screenh, screenv, width, height;
char  ch;
{
/* Set the given rectangular Bitmap region.
   DVItoVDU ensures the top left position is visible and the given
   dimensions do not go beyond the window edges.
*/

  unsigned int  h, v, vrow;

  for (v = screenv; v <= screenv + height - 1; v++)
  {
    for (h = screenh; h <= screenh + width - 1; h++)
    {
    /* set bit h,v in Bitmap */
      vrow = v / VPIXELS;
      FBitmap[h][vrow] = (FBitmap[h][vrow] | (1 << (v % VPIXELS)));
      FBitmap[h][vrow] = (FBitmap[h][vrow] | (1 << FLAG));
    /* flag so char will be sent */
    }
  }
  Frectcount++;
  if (Frectcount == 400)
  {
  /* avoid too much of a pause before flushing Bitmap */
    FalcoShowBitmap ();
  }
}

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

Void FalcoResetVDU ()
{

/* We don't do a hardware reset, but leave VDU in 80 column mode. */
/* we should really save the state in InitVT220()and restore it here */

  Write (ESC);
  WriteString ("[?3l");		/* 80 column mode */
}

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










