/* vis630vdu.c - 18:51 GMT +10:00 Sat 12 Jun 1993 - modifier Geoffrey Tobin */

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

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

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

#include "tek4010emu.h"
#include "vt100vdu.h"

Static int cursrow, curscol;   /* VIS630ShowChar remembers cursor location */
Static boolean textmode;   /* are we in VT200 mode? */

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

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

  WriteChar (CAN);

  textmode = true;
}
/* VIS630StartText */

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

#ifdef __STDC__
Void VIS630MoveToTextLine (int line)
#else
Void VIS630MoveToTextLine (line)
    int line;
#endif
{
  /* Move current position to start of given line. */

  WriteChar (CAN);

  textmode = true;
  VT100MoveToTextLine (line);
}
/* VIS630MoveToTextLine */

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

#ifdef __STDC__
Void VIS630ClearTextLine (int line)
#else
Void VIS630ClearTextLine (line)
int line;
#endif
{
  /* Erase given line; note that DVItoVDU does not assume anything about the
     current position at the end of this routine.
  */

  WriteChar (CAN);

  textmode = true;
  VT100ClearTextLine (line);
}
/* VIS630ClearTextLine */

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

Void VIS630ClearScreen (VOID)
{
  WriteChar (CAN);

  textmode = true;
  VT100ClearScreen();
  TEK4010ClearScreen();
  textmode = false;
}
/* VIS630ClearScreen */

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

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

  TEK4010StartGraphics();
  textmode = false;
  cursrow = 0;
}
/* VIS630StartGraphics */

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

#ifdef __STDC__
Void VIS630LoadFont (Char * fontname, int fontsize, double mag,
                     double hscale, double vscale)
#else
Void VIS630LoadFont (fontname, fontsize, mag, hscale, vscale)
    Char * fontname; int fontsize; double mag;
    double hscale, vscale;
#endif
{
  TEK4010LoadFont (fontname, fontsize, mag, hscale, vscale);
  textmode = false;
}
/* VIS630LoadFont */

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

#ifdef __STDC__
Void VIS630ShowChar (int screenh, int screenv, Char ch)
#else
Void VIS630ShowChar (screenh, screenv, ch)
    int screenh; int screenv; Char ch;
#endif
{
  /* We use VT200 text mode because it is much faster. */

  int amount;

  /* first translate DVItoVDU coordinates into actual screen location */
  if (!textmode)
  {
    WriteChar (CAN);

    textmode = true;
  }
  screenh = (int) (screenh * 132.0 / 1024);
  screenv = (int) (screenv * bottoml / 753);

  screenh++;
  screenv++;
  if (cursrow == screenv)
  {
    /* The cursor is on the same line as in previous VIS630ShowChar 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;
      WriteChar (ESC);
      WriteChar ('[');
      if (amount > 1)   /* default is 1 col */
      {
	WriteInt (amount);
	curscol += 1 - amount;   /* no need if amount = 1 */
      }
      WriteChar ('D');
    }
    else
    {   /* move cursor right */
      amount = screenh - curscol;
      WriteChar (ESC);
      WriteChar ('[');
      if (amount > 1)   /* default is 1 col */
	WriteInt (amount);
      curscol += amount + 1;
      WriteChar ('C');
    }
  }
  else   /* cursrow undefined or ch on a new line */
  {
    VT100MoveAbs (screenv, screenh);
    cursrow = screenv;
    curscol = screenh + 1;   /* cursor will move right when ch written */
  }
  if (screenh == windowwd)   /* ch will be written at right edge */
    cursrow = 0;
  /* so avoid auto wrap next time around */
  WriteChar (TeXtoASCII[ch - NUL]);
}
/* VIS630ShowChar */

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

#ifdef __STDC__
Void VIS630ShowRectangle (int screenh, int screenv, int width, int height,
                          Char ch)
#else
Void VIS630ShowRectangle (screenh, screenv, width, height, ch)
    int screenh, screenv;  /* (screenh, screenv) = top left pixel */
    int width, height;     /* (width, height) = size of rectangle */
    Char ch;               /* ch = black pixel */
#endif
{
  /* Display the given rectangle. */

  int pos;

  textmode = false;
  if (height == 1)
  {
    /* show row vector */
    pos = 779 - screenv;

    WriteChar (GS);

    SendXY (screenh, pos);   /* move cursor to start of row */
    SendXY (screenh + width - 1, pos);   /* draw vector to end of row */
  }
  else if (width == 1)
  {
    /* show column vector */
    pos = 779 - screenv;

    WriteChar (GS);

    SendXY (screenh, pos);   /* move cursor to start of column */
    SendXY (screenh, pos - height + 1);   /* draw vector to end of column */
  }
  else
  {
    /* assume height and width > 1; draw and fill rectangle */
    pos = 780 - height - screenv;

    WriteChar (ESC);
    WriteChar ('/');
    WriteInt (screenh);
    WriteChar (';');   /* left */
    WriteInt (pos);
    WriteChar (';');   /* bottom */
    WriteInt (width - 1);
    WriteChar (';');
    WriteInt (height + 1);
    WriteChar ('y');

    /* Note that there are a few problems with this command:
       - we need to subtract 1 from width.  While this prevents exceeding the
         right edge (reason unknown), it causes missing pixel columns.
       - we need to ADD 1 to height to avoid missing pixel rows.
       - the smallest rectangle drawn is 2 by 2.
       - the new cursor position is undefined.
       IS THIS TRUE FOR VIS 630???
       These funnies are outweighed by the improved efficiency
       in drawing large rectangles.
    */

    havesentxy = false;   /* need to re-synch cursor position */
  }
}
/* VIS630ShowRectangle */

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

Void VIS630ResetVDU (VOID)
{
  WriteChar (ESC);
  WriteString ("[?50h");
      /* 80 COL ITAG + graphics */

  WriteChar (CAN);

  textmode = true;
}
/* VIS630ResetVDU */

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

Void InitVIS630 (VOID)
{
  /* The dialog region will be the top 4 text lines in VT200 mode:
        Line 1 = DVI status line,
        Line 2 = window status line,
        Line 3 = message line,
        Line 4 = command line.
     The window region will be text lines 5 to 50 in VT200 mode.
  */

  InitTEK4010emu();

  /* The following values assume the VIS630 is in VT200 mode. */

  DVIstatusl = 1;   /* DVItoVDU assumes top text line = 1 */
  windowstatusl = 2;
  messagel = 3;
  commandl = 4;
  bottoml = 50;   /* also number of text lines on screen */

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

  /* The following values assume it is emulating a Tektronix 4010.
     Note that windowv must be given a value using DVItoVDU's
     coordinate scheme, where top left pixel is (0,0).
  */

  windowv = 55;
  /* approx. height in TEK4010 pixels of 4 text lines
                              i.e. ~ 4 * 780/50 */
  windowh = 0;
  windowht = 753 - windowv;   /* avoid drawing in status line */
  windowwd = 1024;

  MoveToTextLine = VIS630MoveToTextLine;
  ClearTextLine = VIS630ClearTextLine;
  ClearScreen    = VIS630ClearScreen;
  StartText      = VIS630StartText;
  StartGraphics  = VIS630StartGraphics;
  LoadFont       = VIS630LoadFont;
  ShowChar       = VIS630ShowChar;
  ShowRectangle  = VIS630ShowRectangle;
  ResetVDU       = VIS630ResetVDU;

  WriteChar (GS);

  WriteChar (ESC);
  WriteChar ('@');   /* solid fill for rectangular draw and fill */
  WriteChar (ESC);
  WriteString ("[?40h");
      /* 132 COL ITAG + graphics */

  WriteChar (CAN);

  textmode = true;
}
/*InitVIS630 */

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

/* end vis630vdu.c */
