/* vdu.c - 15:12 GMT +10:00 Wed 4 Aug 1993 - modifier Geoffrey Tobin */
/* VDU driver interface */

#include "config.h"
#include "globals.h"
#include "vdu.h"
#include "options.h"
#include "screenio.h"

/* Additional imported functions : VDU initialisation routines */

extern Void InitNCSATEL(), InitVT100(), InitVT100132(), InitAED512(),
  InitVT640(), InitVIS500(), InitVIS550(), InitVIS630(), InitVIS603(),
  InitREGIS(), InitVIS240(), InitVT220();

#ifdef __linux__
extern Void InitLINUX();
#endif

/* Exported via "vdu.h" */

boolean vdu_clears_lines;  /* Can current VDU clear a single line? */
boolean vdu_unixio = 1;    /* Use normal Unix terminal I/O?        */
boolean vdu_scroll = 0;    /* Can VDU do scrolling?                */
boolean vdu_bitmap = 0;    /* Does VDU prefer bitmaps?             */

/* pointers to VDU functions */

Void (*StartText) (VOID);
Void (*MoveToTextLine) __((int line));
Void (*ClearTextLine) __((int line));
Void (*ClearScreen) (VOID);
Void (*StartGraphics) (VOID);
Void (*LoadFont) __((Char *fontname, int fontsize, double mag,
                     double hscale, double vscale));
Void (*ShowChar) __((int screenh, int screenv, Char ch));
Void (*ShowRectangle) __((int screenh, int screenv, int width, int height,
                          Char ch));
Void (*ResetVDU) (VOID);
Void (*WriteTextChar) __((Char c));
Void (*ReadTextString) __((Char *s));
Void (*ScrollRegion) __((int x1, int y1, int w, int h, int x2, int y2));
Void (*ClearRegion) __((int x1, int y1, int x2, int y2));

/* Local types and variables */

struct vdu_block
{
  char * vdu_name;
  Void (*vdu_init_func)(VOID);
  boolean vdu_clears_lines;
};

struct vdu_block InitVDUlist[] =
{
  {"aed512", InitAED512, true},
  {"gigi", InitREGIS, true},
  {"regis", InitREGIS, true},
  {"vis240", InitVIS240, true},  /* I think vis240 can clear a line */
  {"vis241", InitVIS240, true},  /* I think vis241 can, too */
  {"vis500", InitVIS500, true},
  {"vis550", InitVIS550, true},
  {"vis603", InitVIS603, true},  /* BUT IF vis603 is like Tek4010, it can't! */
  {"vis630", InitVIS630, true},
  {"vk100", InitREGIS, true},  /* I think vk100 can clear a line */
  {"vt125", InitREGIS, true},
  {"vt200", InitVT220, true},
  {"vt220", InitVT220, true},
  {"vt240", InitREGIS, true},
  {"vt640", InitVT640, true},
#ifdef __linux__
  {"linux", InitLINUX, true},  /* Linux SVGA driver */
#endif
  {"kermit", InitNCSATEL, false},  /* temporarily for MS-Kermit Tek4010 emu. */
  {"ncsatel", InitNCSATEL, false},  /* emulates tek4010 */
  {"tek4010", InitNCSATEL, false},  /* temporarily? */
  {"vt100", InitVT100, true},
  {"vt100132", InitVT100132, true},  /* I think vt100132 can clear a line */
  {"vt102", InitVT100, true}  /* I think vt102 can clear a line */
};

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

Void InitVDU (VOID)
{
  int i;
  int n = sizeof (InitVDUlist) / sizeof (struct vdu_block);
  struct vdu_block * vdu_block_p;

  vdu_clears_lines = false;

  for (i = n, vdu_block_p = InitVDUlist;  i > 0;  i--, vdu_block_p++)
  {
    if (!strcmp (vdu, vdu_block_p->vdu_name))
    {
      vdu_block_p->vdu_init_func();
      vdu_clears_lines = vdu_block_p->vdu_clears_lines;
      break;
    }
  }
  /* If i == 0 then invalid VDU.
   * If any of the function pointers are still NULL, then invalid driver.
   */
  if (i == 0)
  {
    string msgstr;
    RestoreTerminal();
    sprintf (msgstr, "Terminal type \"%s\" not supported.", vdu);
    MesgString (msgstr);  MesgLine();
    sprintf (msgstr,
      "Either use the \"-v\" option or the TERM environment variable");
    MesgString (msgstr);  MesgLine();
    sprintf (msgstr, "to specify one of the following terminal types:");
    MesgString (msgstr);  MesgLine();
#define TERMS_PER_LINE (5)
    for (vdu_block_p = InitVDUlist, i = n ;i > 0;)
    {
      int j;
      for (j = i < TERMS_PER_LINE? i: TERMS_PER_LINE;
           j > 0; j--, vdu_block_p++)
      {
        sprintf (msgstr,  "\t%s", vdu_block_p->vdu_name);
        MesgString (msgstr);
      } /* endfor */
      i -= TERMS_PER_LINE;
      MesgLine();
    } /* endfor */
#undef TERMS_PER_LINE
    RestoreTerminal();  /* GT - to be safe */
    exit (1);
  }
  else
  {
    string msgstr;
    /* gt - specialised types for the following comparisons */

    typedef Void (*TLFP) __((int line));
    typedef Void (*SCFP) __((int screenh, int screenv, Char ch));
    typedef Void (*SRFP) __((int screenh, int screenv,
                             int width, int height, Char ch));
    typedef Void (*LFFP) __((Char * fontname, int fontsize, double mag,
                             double hscale, double vscale));

    if (StartText == (VFP) NULL
        || MoveToTextLine == (TLFP) NULL
        || ClearTextLine == (TLFP) NULL
        || ClearScreen == (VFP) NULL
        || StartGraphics == (VFP) NULL
        || LoadFont == (LFFP) NULL
        || ShowChar == (SCFP) NULL
        || ShowRectangle == (SRFP) NULL
        || ResetVDU == (VFP) NULL)
    {
      RestoreTerminal();
      sprintf (msgstr,  "Error in configuration for \"%s\" vdu.", vdu);
      MesgString (msgstr);  MesgLine();
      RestoreTerminal();  /* GT - to be safe */
      exit (1);
    } /* fi */
  } /* fi */
} /* End InitVDU () */

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

Void LogClearScreen (VOID)
{
  ClearScreen();
  if (logfile != NULL)
  {
    fprintf (logfile, "\n");
    fflush (logfile);
  }
}
/* LogClearScreen */

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

/* end vdu.c */
