/* Driver for Linux VGA mode */
/*  Rob Malouf, 4-Sep-1993   */

#ifdef linux

#include "config.h"
#include "screenio.h" 
#include "unixio.h"
#include "vdu.h"
#include "linuxvdu.h"
#include <vga.h>

Static int currx, curry; /* Current position for text output */

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

Void LINUXDoNothing (VOID)
{
  /* Dummy routine */
}  /* LINUXDoNothing */


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

#ifdef __STDC__
Void LINUXShowRectangle (int screenh, int screenv, int width, int height, 
                         Char ch)
#else
Void LINUXShowRectangle (screenh, screenv, width, height)
    int screenh, screenv, width, height;
Char ch;
#endif
{
  int i;

  if ((height == 1) || (width == 1)) {  /* show row or column vector */
    vga_drawline(screenh, screenv, screenh + width - 1, screenv + height - 1);
    return;
  } else {
    /* assume height and width > 1 and use shading to fill rectangle */
    for (i = screenv; i <= screenv + height - 1; i++)
      vga_drawline(screenh, i, screenh + width - 1, i);
  } 
}  /* LINUXShowRectangle */


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

#ifdef __STDC__
Void LINUXMoveToTextLine (int line)
#else
Void LINUXMoveToTextLine (line)
    int line;
#endif
{
  /* Move current position to start of given line. */
  currx = 0;
  curry = line * FONT_LINES;
}  /* LINUXMoveToTextLine */


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

#ifdef __STDC__
Void LINUXClearTextLine (int line)
#else
Void LINUXClearTextLine (line)
    int line;
#endif
{
  int i;

  vga_setcolor(0);
  for (i=(line*FONT_LINES)-(FONT_LINES-1); i<line*FONT_LINES; i++) 
    vga_drawline(0,i,windowwd,i);
  vga_setcolor(1);
}  /* LINUXClearTextLine */

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

Void LINUXClearScreen (VOID)
{
  vga_clear(); 
}  /* LINUXClearScreen */


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

#ifdef __STDC__
Void LINUXLoadFont (Char *fontname, int fontsize, double mag, double hscale,
                    double vscale)
#else
Void LINUXLoadFont (fontname, fontsize, mag, hscale, vscale)
    Char *fontname;
    int fontsize;
    double mag, hscale, double vscale;
#endif
{
  /* only one character size available, so do nothing */
}  /* LINUXLoadFont */

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

#ifdef __STDC__
Static Void PutTextChar (int h, int v, Char chr)
#else
Static Void PutTextChar (h, v, chr)
    int h, v;
    Char chr;
#endif
{
  int x, y, i, mask;

  y = v - FONT_LINES;
  for (i = FONT_LINES * chr; i < FONT_LINES * (chr + 1); i++) {
    mask = 128;
    for (x = h; x < ((h + 8 < windowwd) ? h + 8 : windowwd); x++) {
      if (font_bits[i] & mask) 
	vga_drawpixel(x, y);
      mask = mask >> 1;
    }
    y++;
  }
} /* PutTextChar */
 
/******************************************************************************/

#ifdef __STDC__
Void LINUXWriteTextChar (Char ch)
#else
Void LINUXWriteTextChar (ch)
    Char ch;
#endif
{
  switch (ch) {
  case '\n':
    currx = 0;
    curry = curry + FONT_LINES;
    break;
  case '\b':
  case 127:
    break;
  default:
    PutTextChar(currx, curry, ch);
    currx += 8;
    break;
  } 
} /* LINUXWriteTextChar */


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

#ifdef __STDC__
Void LINUXReadTextString (Char *s)
#else
Void LINUXReadTextString (s)
    Char *s;
#endif
{
  Char ch;
  int i;

  i = 0;

  while (1) {
    ReadChar(&ch);
    switch (ch) {
    case '\n':
      s[i] = '\0';      
      return;
    case '\b':
    case 127:
      if (i > 0) {
	currx -= 8;
	vga_setcolor(0);
	LINUXShowRectangle(currx, curry - FONT_LINES, 8, FONT_LINES, 0);
	vga_setcolor(1);
	i--;
      }
      break;
    default:
      s[i++] = ch;
      break;
    }
  }
} /* LINUXReadTextString */

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

#ifdef __STDC__
Void LINUXShowChar (int screenh, int screenv, Char ch)
#else
Void LINUXShowChar (screenh, screenv, ch)
    int screenh, screenv; 
    Char ch;
#endif
{
  Char newch;   /* = TeXtoASCII[ch] */
  int v;

  v = screenv + 5; /* Match characters with TeX baseline */
  newch = TeXtoASCII[ch - NUL];   /* convert TeX ch to ASCII */
  if (newch != '?') {
    PutTextChar(screenh, v, newch);
  } else {
    switch (ch) {
    case 0x00: /* Gamma */
      PutTextChar(screenh, v, 226);
      break;
    case 0x02: /* Theta */
      PutTextChar(screenh, v, 233);
      break;
    case 0x05: /* Pi */
      PutTextChar(screenh, v, 227);
      break;
    case 0x06: /* Sigma */
      PutTextChar(screenh, v, 228);
      break;
    case 0x08: /* Phi */
      PutTextChar(screenh, v, 232);
      break;
    case 0x0a: /* Omega */
      PutTextChar(screenh, v, 233);
      break;
    case 0x0b: /* ff */
      PutTextChar(screenh, v, 'f');
      PutTextChar(screenh+8, v, 'f');
      break;
    case 0x0c: /* fi */
      PutTextChar(screenh, v, 'f');
      PutTextChar(screenh+8, v, 'i');
      break;
    case 0x0d: /* fl */
      PutTextChar(screenh, v, 'f');
      PutTextChar(screenh+8, v, 'l');
      break;
    case 0x0e: /* ffi */
      PutTextChar(screenh, v, 'f');
      PutTextChar(screenh+8, v, 'f');
      PutTextChar(screenh+8, v, 'i');
      break;
    case 0x0f: /* ffl */
      PutTextChar(screenh, v, 'f');
      PutTextChar(screenh+8, v, 'f');
      PutTextChar(screenh+16, v, 'l');
      break;
    case 0x17: /* Degree mark */
      PutTextChar(screenh, v, 248);
      break;
    case 0x19: /* German sharp S */
      PutTextChar(screenh, v, 225);
      break;
/*    case 0x19:*/ /* German sharp S */
/*      PutTextChar(screenh, v, 237);
      break; */
    case 0x1a: /* ae */
      PutTextChar(screenh, v, 145);
      break;
    case 0x1b: /* oe */
      PutTextChar(screenh, v, 'o');
      PutTextChar(screenh+8, v, 'e');
      break;
    case 0x1d: /* AE */
      PutTextChar(screenh, v, 146);
      break;
    case 0x1e: /* OE */
      PutTextChar(screenh, v, 'O');
      PutTextChar(screenh+8, v, 'E');
      break;
    case 0x3c: /* ! */
      PutTextChar(screenh, v, 173);
      break;
    case 0x3e: /* ? */
      PutTextChar(screenh, v, 168);
      break;
    default:
      PutTextChar(screenh+8, v, '?');
      break;
    }
  }
}  /* LINUXShowChar */


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

Void LINUXResetVDU (VOID)
{
  vga_setmode(TEXT);
}  /* LINUXResetVDU */


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

Void InitLINUX (VOID)
{
  int vgamode;

  if ((vgamode = vga_getdefaultmode()) == -1)
    vgamode = G640x480x2;

  restore_init_tty();
  
  vga_setmode(vgamode);
  vga_setpalette(0,0,0,0);
  vga_setpalette(1,180,180,180);
  vga_setcolor(1);

  /* 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;
  windowh = 0;
  windowv = 64; /* (FONT_LINES * 4) */
  windowwd = vga_getxdim();
  windowht = vga_getydim() - windowv;

  MoveToTextLine = LINUXMoveToTextLine;
  ClearTextLine  = LINUXClearTextLine;
  ClearScreen    = LINUXClearScreen;
  StartText      = LINUXDoNothing;
  StartGraphics  = LINUXDoNothing;
  LoadFont       = LINUXLoadFont;
  ShowChar       = LINUXShowChar;
  ShowRectangle  = LINUXShowRectangle;
  ResetVDU       = LINUXResetVDU;
  WriteTextChar  = LINUXWriteTextChar;
  ReadTextString = LINUXReadTextString;

  vdu_unixio = 0;
  currx = 0;
  curry = 0;

}  /*InitLINUX */

#endif /* linux */
/* End. */
