/* regisvdu.c - 19:29 GMT +10:00 Thu 22 July 1993 - modifier Geoffrey Tobin */

/* From input file "../include/globals.p" */

#include "config.h"
#include "globals.h"

#include "screenio.h"
#include "vdu.h"

#include "vt100vdu.h"
#include "regisvdu.h"

Static int charht;   /* set in REGISLoadFont and used in REGISShowChar */
Static int lastv;    /* REGISShowChar remembers last vertical coordinate */

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

Void REGISStartText (VOID)
{
  /* We are about to draw text in dialogue region. */

  WriteChar (ESC);
  WriteChar ('\\');   /* leave graphics mode */
}
/* REGISStartText */

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

/* REGISMoveToTextLine: use VT100MoveToTextLine */

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

/* REGISClearTextLine: use VT100ClearTextLine */

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

Void REGISStartGraphics (VOID)
{
  /* We are about to draw in window region. */

  WriteChar (ESC);
  WriteString ("Pp");   /* enter graphics mode */
  lastv = 999999;       /* undefined value for next REGISShowChar call */
}
/* REGISStartGraphics */

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

Void REGISClearScreen (VOID)
{
  VT100ClearScreen();
  REGISStartGraphics();   /* switch to REGIS mode */
  WriteString ("S(E)");   /* erase graphics plane */
  REGISStartText();       /* exit in text mode */
}
/* REGISClearScreen */

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

#ifdef __STDC__
Void REGISLoadFont (Char * fontname, int fontsize, double mag,
                    double hscale, double vscale)
#else
Void REGISLoadFont (fontname, fontsize, mag, hscale, vscale)
    Char * fontname;
    int fontsize;
    double mag;
    double hscale, vscale;
#endif
{
  /* Use the given information to select an appropriate character size
     (based on horizontal AND vertical scaling)
     for future calls of REGISShowChar.
  */

  int wd, ht;   /* we will send T ( Swd Hht ) */

  WriteChar ('T');
  WriteChar ('(');

  /* scale fontsize horizontally and choose an appropriate text width */
  wd = (int)(fontsize * mag * hscale + 0.5) / 9;
  if (wd > 16)   /* wd now in 0,1,2,...,16 */
    wd = 16;
  /* larger widths tend to be too big so adjust accordingly (trial and error) */
  if (wd > 1)
    wd /= 2;
  WriteChar ('S');
  WriteInt (wd);

  /* scale fontsize vertically and choose an appropriate text height */
  ht = (int) (fontsize * mag * vscale + 0.5) / 10;
  if (ht < 1)   /* ht now in 1,2,...,16 */
    ht = 1;   /* ht must not be 0 */
  else if (ht > 16)
    ht = 16;
  charht = ht * 10;   /* charht now in 10,20,30,...,160 */
  /* restrict charht to <= windowv,
     so screenv-charht in REGISShowChar will be >= 0.
  */
  if (charht > windowv)
  {
    charht = windowv;
    ht = windowv / 10;
  }
  /* now reduce charht by one fifth to allow for descenders in REGISShowChar */
  charht = charht * 4 / 5 - 1;   /* exact if charht is multiple of 10 */
  WriteChar ('H');
  WriteInt (ht);

  /* Note that VT125 and GIGI VDUs sometimes vary the vertical thickness
     of text (only for odd ht values? ? ?).
     VT240 does not; instead, charht is sometimes 1 pixel too much
     and baseline won't agree with Box/Full characters!
  */

  WriteChar (')');
}
/* REGISLoadFont */

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

#ifdef __STDC__
Void REGISShowChar (int screenh, int screenv, Char ch)
#else
Void REGISShowChar (screenh, screenv, ch)
    int screenh; int screenv; Char ch;
#endif
{
  /* Show the given Terse character (mapped to ASCII) using the given position.
     We remember the vertical position in lastv so we can reduce the output
     bytes needed to position the next Terse character on the same line.
     REGISStartGraphics resets lastv to an undefined state (= 999999).
  */

  Char newch;   /* = TeXtoASCII[ch] */

  WriteChar ('P');
  WriteChar ('[');
  WriteInt (screenh);
  /* charht allows for descenders and is used to shift ref pt of REGIS ch
     (top left pixel) so that REGIS and TeX baselines will match.
     REGISLoadFont guarantees that screenv - charht >= 0.
  */
  screenv -= charht;
  if (lastv != screenv)
  {
    /* we need to send new vertical coordinate */
    WriteChar (',');
    WriteInt (screenv);
    lastv = screenv;   /* remember for next REGISShowChar call */
  }
  WriteChar (']');
  WriteChar ('T');
  newch = TeXtoASCII[ch - NUL];   /* convert TeX ch to ASCII */
  if (newch != '\'')
  {
    WriteChar ('\'');   /* open quoted string */
    if (newch != '?')
    {
      /* newch is similar to TeX ch */
      WriteChar (newch);
    }
    else
    {
      /* attempt to display something other than ? */
      switch (ch)
      {
	case 11:
	case 12:
	case 13:
	case 14:
	case 15:   /* ff, fi, fl, ffi, ffl */
	  WriteChar ('f');
	  /* REGIS doesn't care if no room at right edge */
	  switch (ch)
	  {
	    case 0xb:
	      WriteChar ('f');
	      break;

	    case 0xc:
	      WriteChar ('i');
	      break;

	    case 0xd:
	      WriteChar ('l');
	      break;

	    case 0xe:
	    case 0xf:
	      WriteChar ('f');
	      if (ch == '\016')
		WriteChar ('i');
	      else
		WriteChar ('l');
	      break;
	  }
	  break;

	case 0x19:   /* German sharp S */
	  WriteChar ('B');
	  break;

	case 0x1a:
	case 0x1b:
	case 0x1d:
	case 0x1e:   /* diphthongs: ae, oe, AE, OE */
	  switch (ch)
	  {
	    case 0x1a:
	      WriteChar ('a');
	      break;

	    case 0x1b:
	      WriteChar ('o');
	      break;

	    case 0x1d:
	      WriteChar ('A');
	      break;

	    case 0x1e:
	      WriteChar ('O');
	      break;
	  }
	  switch (ch)
	  {
	    case 0x1a:
	    case 0x1b:
	      WriteChar ('e');
	      break;

	    case 0x1d:
	    case 0x1e:
	      WriteChar ('E');
	      break;
	  }
	  break;

	case 0x20:   /* Polish suppressed l and L */
	  WriteChar ('/');
	  break;

	default:
	  WriteChar ('?');
	  break;
      }
    }
    WriteChar ('\'');   /* close quoted string */
    return;
  }
  WriteChar ('\"');
  WriteChar ('\'');
  WriteChar ('\"');   /* send "'" */
}
/* REGISShowChar */

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

#ifdef __STDC__
Void REGISShowRectangle (int screenh, int screenv, int width, int height,
                         Char ch)
#else
Void REGISShowRectangle (screenh, screenv, width, height, ch)
    int screenh, screenv;  /* top left pixel */
    int width, height;     /* size of rectangle */
    Char ch;               /* black pixel */
#endif
{
  /* Display the given rectangle
     (_without_ using the given black pixel character).
     DVItoVDU ensures the top left position is visible
     and the given dimensions do not go beyond the window edges.
  */

  if (height == 1)
  {
    /* show row vector */
    WriteChar ('P');
    WriteChar ('[');   /* move cursor to start of row */
    WriteInt (screenh);
    WriteChar (',');
    WriteInt (screenv);
    /* call @R macrograph to draw starting pixel and begin row */
    WriteChar ('@');
    WriteChar ('R');
    WriteInt (width - 1);
    WriteChar (']');
    return;
  }
  if (width == 1)
  {
    /* show column vector */
    WriteChar ('P');
    WriteChar ('[');   /* move cursor to start of column */
    WriteInt (screenh);
    WriteChar (',');
    WriteInt (screenv);
    /* call @C macrograph to draw starting pixel and begin column */
    WriteChar ('@');
    WriteChar ('C');
    WriteInt (height - 1);
    WriteChar (']');
    return;
  }
  else
  {
    /* assume height and width > 1 and use shading to fill rectangle */
    WriteChar ('P');
    WriteChar ('[');
    WriteChar (',');   /* position to last row */
    WriteInt (screenv + height - 1);
    /* call @E macrograph to define shading reference line and start
       position command that moves to start of first row */
    WriteChar ('@');
    WriteChar ('E');
    WriteInt (screenh);
    WriteChar (',');
    WriteInt (screenv);
    /* call @R macrograph to draw starting pixel and begin rectangle */
    WriteChar ('@');
    WriteChar ('R');
    WriteInt (width - 1);
    /* call @D macrograph to disable shading */
    WriteChar ('@');
    WriteChar ('D');
  }
}
/* REGISShowRectangle */

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

Void REGISResetVDU (VOID)
{
  /* We don't do a hardware reset, but leave VDU gracefully. */

  REGISStartGraphics();   /* for following REGIS commands */
  WriteString ("@.");     /* clear macrograph storage */
  WriteString ("T(E)");   /* restore Text attributes saved inInitREGIS */
  REGISStartText();       /* safer to leave in text mode */
}
/* REGISResetVDU */

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

Void InitREGIS (VOID)
{
  /* The dialogue region is the top 4 lines.
     The window region is the remaining area of the screen.
  */

  DVIstatusl = 1;
  windowstatusl = 2;
  messagel = 3;
  commandl = 4;
  bottoml = 24;
  /* DVItoVDU's coordinate scheme is the same as the REGIS scheme. */

  windowh = 0;
  windowv = 80;   /* = height of 4 dialogue lines
                       (better for REGISLoadFont if
                           windowv is a multiple of 10) */
  windowwd = 768;
  windowht = 480 - windowv;

  textlinewidth = 72;  /* text characters per line - a guess */

  MoveToTextLine = VT100MoveToTextLine;
  ClearTextLine = VT100ClearTextLine;
  ClearScreen    = REGISClearScreen;
  StartText      = REGISStartText;
  StartGraphics  = REGISStartGraphics;
  LoadFont       = REGISLoadFont;
  ShowChar       = REGISShowChar;
  ShowRectangle  = REGISShowRectangle;
  ResetVDU       = REGISResetVDU;

  REGISStartGraphics();   /* for following REGIS commands */

  /* Set Text and Writing attributes to known initial states. */
  /* save current Text attributes; will be restored by REGISResetVDU */
  WriteString ("T(B)");
  /* default character set, no italic slant, direction right, default text size */
  WriteString ("T(A0,I0,D0,S1)");
  /* solid fill, no alternate, normal, shading disabled, overlay */
  WriteString ("W(P1,A0,N0,S0,V)");

  /* Define some macrographs for frequently used strings in REGISShowRectangle. */
  WriteString ("@.");
      /* clear macrograph storage */
  WriteString ("@:E]W(S1)P[@;");
      /* @E = enable shading for filled rectangle */
  WriteString ("@:D]W(S0)@;");
      /* @D = disable shading */
  WriteString ("@:R]V[]V[+@;");
      /* @R = mid part of drawing a row vector */
  WriteString ("@:C]V[]V[,+@;");
      /* @C = mid part of drawing a column vector */

  REGISStartText();   /* safer to leave in text mode */
}
/*InitREGIS */

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

/* end regisvdu.c */
