/**********************************************************************\
*                                                                      *
*  char.c -- character display and management routines                 *
*                                                                      *
\**********************************************************************/

#include "defs.h"

char *font;
char *pfont;
int  ptsize;
int  *spacing;

int spacing_08pt[] = {
/* !  "  #  $  %  &  '  (  )  *  +  ,  - */
   3, 4, 7, 7, 8, 8, 4, 5, 5, 9, 7, 4, 6,

/* .  /  0  1  2  3  4  5  6  7  8  9  : */
   3, 6, 7, 4, 7, 7, 7, 7, 7, 7, 7, 7, 3,

/* ;  <  =  >  ?  @  A  B  C  D  E  F  G */
   4, 6, 7, 6, 7, 9, 7, 7, 7, 7, 7, 7, 7,

/* H  I  J  K  L  M  N  O  P  Q  R  S  T */
   7, 5, 7, 7, 7,10, 8, 7, 7, 7, 7, 7, 7,

/* U  V  W  X  Y  Z  [  \  ]  ^  _  `  a */
   7, 7,11, 7, 7, 7, 5, 6, 5, 7, 7, 4, 7,

/* b  c  d  e  f  g  h  i  j  k  l  m  n */
   7, 7, 7, 7, 7, 7, 7, 3, 6, 6, 3, 9, 7,

/* o  p  q  r  s  t  u  v  w  x  y  z  { */
   7, 7, 7, 6, 7, 6, 7, 7,11, 7, 7, 7, 6,

/* |  }  ~ */
   3, 6, 7};

int spacing_14pt[] = {
/* !  "  #  $  %  &  '  (  )  *  +  ,  - */
   4, 7, 9, 8,13, 9, 4, 5, 5, 8, 8, 4, 6,

/* .  /  0  1  2  3  4  5  6  7  8  9  : */
   4, 5, 8, 6, 8, 8, 8, 8, 8, 8, 8, 8, 4,

/* ;  <  =  >  ?  @  A  B  C  D  E  F  G */
   4, 8, 8, 8, 8,13,10,10, 9,10, 9, 9,10,

/* H  I  J  K  L  M  N  O  P  Q  R  S  T */
  10, 4, 7, 9, 9,12,10,10,10,10,11, 9,10,

/* U  V  W  X  Y  Z  [  \  ]  ^  _  `  a */
  10,10,16,10,12,11, 5, 6, 5, 7, 9, 6, 8,

/* b  c  d  e  f  g  h  i  j  k  l  m  n */
   8, 8, 8, 8, 5, 8, 8, 4, 4, 8, 4,12, 8,

/* o  p  q  r  s  t  u  v  w  x  y  z  { */
   8, 8, 8, 7, 8, 5, 8,10,12,10,10, 8, 6,

/* |  }  ~ */
   5, 6,12};


/**********************************************************************\
*                                                                      *
*  center_pstring -- display proportional characters, centered         *
*                                                                      *
\**********************************************************************/

void center_pstring(string,x1,x2,y)
char *string;
int x1, x2, y;
{
   int x;

   x = get_center(string,x1,x2);
   put_pstring(string,x,y);
}


/**********************************************************************\
*                                                                      *
*  center_string -- display fixed-pitch characters, centered           *
*                                                                      *
\**********************************************************************/

void center_string(string,x1,x2,y)
char *string;
int x1, x2, y;
{
   register int i;
   register int nchar;
   int index;
   int x;
   char ch;

   nchar = strlen(string);
   if (nchar == 0) return;

   /* calculate center */

   x = ((x1 + x2) / 2) - (nchar * 4);

   /* display each character as a bitmap */

   for (i = 0; i < nchar; i++)
   {
      ch = string[i] - 33;
      if (ch >= 0)
      {
         index = ch * ptsize;
         fg_move(x,y);
         fg_drawmap(&font[index],1,ptsize);
      }
      x += 8;
   }
}

/**********************************************************************\
*                                                                      *
*  erase_char -- erase a single fixed-pitch character                  *
*                                                                      *
\**********************************************************************/

void erase_char(x,y)
int x, y;
{
   register int color;

   /* save the current color */

   color = fg_getcolor();

   /* draw a black rectangle over the character */

   fg_setcolor(0);
   fg_rect(x,x+7,y+1-ptsize,y);

   /* set the color back to what it was */

   fg_setcolor(color);
}

/**********************************************************************\
*                                                                      *
*  first_nonblank -- find first character that is not a blank          *
*                                                                      *
\**********************************************************************/

char first_nonblank(string)
char *string;
{
   register int i;
   char c;

   i = 0;
   while (TRUE)
   {
      c = string[i++];
      if (c == 0)
         return(0);
      else if (c > 32)
         return(c);
   }
}

/**********************************************************************\
*                                                                      *
*  get_center -- locate center for proportionally-spaced characters    *
*                                                                      *
\**********************************************************************/

get_center(string,x1,x2)
char *string;
int x1, x2;
{
   return(((x1 + x2) / 2) - (length_pstring(string)/ 2));
}

/**********************************************************************\
*                                                                      *
*  get_font -- get the proportional and fixed-pitch character fonts    *
*                                                                      *
\**********************************************************************/

void get_font()
{
   register int i;
   register int index;
   int x, y;
   int yoffset;
   char fontfile[10];

   /* allocate dynamic memory for the fonts; also define font file name */

   if (mode11 || mode16)
   {
      font  = malloc(1316);
      pfont = malloc(2632);
      strcpy(fontfile,"14pt.fnt");   /* high res modes use 14 pt font */
      spacing = spacing_14pt;
      ptsize  = 14;
      yoffset = 18;
   }
   else
   {
      font  = malloc(752);
      pfont = malloc(1504);
      strcpy(fontfile,"08pt.fnt");  /* low res modes use 8 pt font */
      spacing = spacing_08pt;
      ptsize  = 8;
      yoffset = 90;
   }

   /* if the allocate failed or the font file isn't present, go no farther */

   if (font  == (char *)NULL) abort_program(0);
   if (pfont == (char *)NULL) abort_program(0);
   if (!exists(fontfile))     abort_program(1);

   /* display either the 8pt or 14pt fonts on the hidden page */

   fg_setpage(hidden);
   fg_move(0,199);
   fg_dispfile(fontfile,320,1);

   /* retrieve the proportionally spaced and fixed-pitch fonts */

   fg_setcolor(11);
   index = 0;

   for (i = 0; i < 94; i++)
   {
      x = 1 + (i/13) * 16;
      y = yoffset + (i%13) * (ptsize+1);
      fg_move(x,y);
      fg_getmap(&pfont[index*2],2,ptsize);  /* put in bitmap array */
      x = 129 + (i/13) * 9;
      fg_move(x,y);
      fg_getmap(&font[index],1,ptsize);
      index += ptsize;
   }
}

/**********************************************************************\
*                                                                      *
*  get_string -- accept and display a fixed-pitch character string     *
*                                                                      *
\**********************************************************************/

get_string(string,x,y,max_length,string_type)
char *string;
int x, y, max_length, string_type;
{
   register int i;
   int color, timer;
   int xmax, ymin;
   unsigned char key, aux;

   /* clear an area for the input string */

   fg_setcolor(0);
   xmax = x + 8*max_length;
   ymin = y - ptsize;
   fg_rect(x-2,xmax+1,ymin,y+1);

   i = 0;
   timer = 16;
   color = 15;
   fg_setcolor(15);

   while (i < max_length)
   {

      /* increment the timer to make the cursor blink */

      timer--;
      if (timer == 8)
         color = 0;
      else if (timer == 0)
      {
         timer = 16;
         color = 15;
      }
      put_cursor(x,y,color);

      /* pause, then get a keystroke */

      fg_waitfor(1);
      fg_intkey(&key,&aux);

      /* printable character */

      if (isalnum(key) || ((string_type != ALPHANUMERIC) && ispunct(key)))
      {
         put_cursor(x,y,0);
         put_char(key,x,y);
         x += 8;
         string[i++] = key;
      }

      /* backspace -- delete a character */

      else if (key == BS && i > 0)
      {
         put_cursor(x,y,0);
         x -= 8;
         erase_char(x,y);
         i--;
      }

      /* ESC key terminates input */

      else if (key == ESC)
         return(ESC);

      /* carriage return terminates input */

      else if (key == CR)
         break;
   }

   /* zero-length string? */

   if (i == 0) return(ESC);

   /* string terminator */

   string[i] = '\0';
   return(OK);
}

/**********************************************************************\
*                                                                      *
*  length_pstring -- compute the length of a proportional string       *
*                                                                      *
\**********************************************************************/

length_pstring(string)
char *string;
{
   register int i;
   register int nchar;
   int length;
   char ch;

   /* number of characters in the string */

   nchar = strlen(string);
   if (nchar == 0) return(0);

   length = 0;

   /* total up pixel width of each character */

   for (i = 0; i < nchar; i++)
   {
      ch = string[i] - 33;
      if (ch < 0)
         length += 8;
      else
         length += spacing[ch];
   }

   return(length);
}

/**********************************************************************\
*                                                                      *
*  put_char -- display a single fixed-pitch character                  *
*                                                                      *
\**********************************************************************/

void put_char(ch,x,y)
char ch;
int x, y;
{
   register int index;

   /* 32 is space, 33 is first printable ASCII character */

   ch -= 33;
   if (ch >= 0)
   {
      /* calculate index into the bitmap array */

      index = ch * ptsize;

      /* draw the character as a mode independent bitmap */

      fg_move(x,y);
      fg_drawmap(&font[index],1,ptsize);
   }
}

/**********************************************************************\
*                                                                      *
*  put_cursor -- display the cursor line                               *
*                                                                      *
\**********************************************************************/

void put_cursor(x,y,cursor_color)
int x, y;
int cursor_color;
{
   register int color;

   /* preserve current foreground color */

   color = fg_getcolor();

   /* draw the cursor */

   fg_setcolor(cursor_color);
   fg_rect(x,x+7,y,y);

   /* restore the foreground color */

   fg_setcolor(color);
}

/**********************************************************************\
*                                                                      *
*  put_pstring -- display proportionally-spaced characters             *
*                                                                      *
\**********************************************************************/

void put_pstring(string,x,y)
char *string;
int x, y;
{
   register int i;
   register int nchar;
   int index;
   int twice_ptsize;
   char ch;

   /* get the length of the string */

   nchar = strlen(string);
   if (nchar == 0) return;

   twice_ptsize = ptsize * 2;

   /* adjust y coordinate for screen resolution (it looks better) */

   if (ptsize == 8) y--;

   /* display each character as a mode-independent bitmap */

   for (i = 0; i < nchar; i++)
   {
      ch = string[i] - 33;

      /* printable character: greater than ASCII 32 */

      if (ch >= 0)
      {
         index = ch * twice_ptsize;
         fg_move(x,y);
         fg_drawmap(&pfont[index],2,ptsize);

         /* increment x depending on the proportional space */

         x += spacing[ch];
      }

      /* assume that white space will be 8 pixels wide */

      else
         x += 8;
   }
}

/**********************************************************************\
*                                                                      *
*  put_string -- display fixed-pitch characters                        *
*                                                                      *
\**********************************************************************/

void put_string(string,x,y)
char *string;
int x, y;
{
   register int i;
   register int nchar;
   int index;
   char ch;

   /* determine the length of the string */

   nchar = strlen(string);
   if (nchar == 0) return;

   for (i = 0; i < nchar; i++)
   {
      ch = string[i] - 33;
      if (ch >= 0)
      {
         index = ch * ptsize;
         fg_move(x,y);
         fg_drawmap(&font[index],1,ptsize);
      }

      /* always increment by 8, not proportionally spaced */

      x += 8;
   }
}

/**********************************************************************\
*                                                                      *
*  put_tstring -- display ROM BIOS text                                *
*                                                                      *
\**********************************************************************/

void put_tstring(string,row,col)
char *string;
int row, col;
{
   /* character space is defined in rows and columns */

   fg_locate(row,col);

   /* ROM text */

   fg_text(string,strlen(string));
}

/**********************************************************************\
*                                                                      *
*  row_offset -- return the row offset for any font                    *
*                                                                      *
\**********************************************************************/

row_offset(nrows)
int nrows;
{
   return(nrows*ptsize);
}
