/*
 * $Id: dumb.trm,v 3.26 92/03/24 22:34:48 woo Exp Locker: woo $
 */

/* GNUPLOT - dumb.trm */
/*
 * Copyright (C) 1991, 1992
 *
 * Permission to use, copy, and distribute this software and its
 * documentation for any purpose with or without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.
 *
 * Permission to modify the software is granted, but not the right to
 * distribute the modified code.  Modifications are to be distributed
 * as patches to released version.
 *
 * This software  is provided "as is" without express or implied warranty.
 *
 * This file is included by ../term.c.
 *
 * This terminal driver supports:
 *   DUMB terminals
 *
 * AUTHORS
 *   Francois Pinard, 91-04-03
 *           INTERNET: pinard@iro.umontreal.ca
 *
 * send your comments or suggestions to (info-gnuplot@ames.arc.nasa.gov).
 *
 */

#define DUMB_AXIS_CONST '\1'
#define DUMB_BORDER_CONST '\2'

#define DUMB_XMAX 79
#define DUMB_YMAX 24

static char *dumb_matrix = NULL;      /* matrix of characters */
static char *dumb_priority = NULL;    /* matrix of priority at each position */
static char dumb_pen;                 /* current character used to draw */
static int dumb_x;                    /* current X position */
static int dumb_y;                    /* current Y position */
static int dumb_xmax = DUMB_XMAX;
static int dumb_ymax = DUMB_YMAX;

#define DUMB_PIXEL(x,y) dumb_matrix[dumb_xmax*(y)+(x)]


dumb_set_pixel(x,y,v,p)
int x,y,v,p;
{
  if (p > dumb_priority[dumb_xmax*y+x])
    {
      dumb_matrix[dumb_xmax*y+x] = v;
      dumb_priority[dumb_xmax*y+x] = p;
    }
}


DUMB_options()
{
  int x,y;
  struct value a;
  extern struct value *const_express();
  extern double real();

  if (!END_OF_COMMAND) {
    x = (int) real(const_express(&a));
    if (!END_OF_COMMAND) {
      y = (int) real(const_express(&a));
      dumb_xmax = term_tbl[term].xmax = x;
      dumb_ymax = term_tbl[term].ymax = y;
    }
  }

  sprintf(term_options, "%d %d",dumb_xmax,dumb_ymax);
}


DUMB_init()
{
  if (dumb_matrix)
    free(dumb_matrix);

  dumb_matrix = alloc (dumb_xmax * dumb_ymax * 2, "dumb terminal");

  dumb_priority = dumb_matrix + dumb_xmax * dumb_ymax;
}


char *
DUMB_str_state()
{
   static char str[80];

   sprintf( str, "%d %d", dumb_xmax, dumb_ymax );

   return str;
}


DUMB_graphics ()
{
  int i;
  char *pm = dumb_matrix, *pp = dumb_priority;

  for ( i = dumb_xmax * dumb_ymax; i > 0; i-- ) {
    *pm++ = ' ';
    *pp++ = 0;
  }
}


DUMB_text ()
{
  int x, y, l;

  putc ('\f', outfile);
  for (y = dumb_ymax - 1; y >= 0; y--)
    {
      for (l = dumb_xmax; l > 0 && DUMB_PIXEL (l - 1, y) == ' '; l--)
       ;
      for (x = 0; x < l; x++)
       putc (DUMB_PIXEL (x, y), outfile);
      if (y > 0)
       putc ('\n', outfile);
    }
  fflush (outfile);
}


DUMB_reset()
{
  free (dumb_matrix);
  dumb_matrix = NULL;
}


DUMB_linetype(linetype)
int linetype;
{
  static char pen_type[7] = {'*', '#', '$', '%', '@', '&', '='};

  if (linetype == -2)
    dumb_pen = DUMB_BORDER_CONST;
  else if (linetype == -1)
    dumb_pen = DUMB_AXIS_CONST;
  else
    {
      linetype = linetype % 7;
      dumb_pen = pen_type[linetype];
    }
}


DUMB_move(x, y)
int x, y;
{
  dumb_x = x;
  dumb_y = y;
}


DUMB_point(x,y,point)
int x,y,point;
{
  dumb_set_pixel (x, y, point == -1 ? '.' : point % 26 + 'A', 4);
}


DUMB_vector(x,y)
int x,y;
{
  char pen, pen1;
  int priority;
  int delta;

  if (abs (y - dumb_y) > abs (x - dumb_x))
    {
      switch (dumb_pen)
       {
       case DUMB_AXIS_CONST:
         pen = ':';
         pen1 = '+';
         priority = 1;
         break;

       case DUMB_BORDER_CONST:
         pen = '|';
         pen1 = '+';
         priority = 2;
         break;

       default:
         pen = dumb_pen;
         pen1 = dumb_pen;
         priority = 3;
         break;
       }
      dumb_set_pixel (dumb_x, dumb_y, pen1, priority);
      for (delta = 1; delta < abs (y - dumb_y); delta++)
       dumb_set_pixel (dumb_x
                       + (int) ((double) (x - dumb_x) * delta / abs(y - dumb_y)
                                + 0.5),
                       dumb_y + delta * sign (y - dumb_y),
                       pen, priority);
      dumb_set_pixel (x, y, pen1, priority);
    }
  else if (abs (x - dumb_x) > abs (y - dumb_y))
    {
      switch (dumb_pen)
       {
       case DUMB_AXIS_CONST:
         pen = '.';
         pen1 = '+';
         priority = 1;
         break;

       case DUMB_BORDER_CONST:
         pen = '-';
         pen1 = '+';
         priority = 2;
         break;

       default:
         pen = dumb_pen;
         pen1 = dumb_pen;
         priority = 3;
         break;
       }
      dumb_set_pixel (dumb_x, dumb_y, pen1, priority);
      for (delta = 1; delta < abs (x - dumb_x); delta++)
       dumb_set_pixel (dumb_x + delta * sign (x - dumb_x),
                       dumb_y +
                       (int) ((double) (y - dumb_y) * delta / abs(x - dumb_x)
                              + 0.5),
                       pen, priority);
      dumb_set_pixel (x, y, pen1, priority);
    }
  else
    {
      switch (dumb_pen)
       {
       case DUMB_AXIS_CONST:	/* zero length axis */
         pen = '+';
         priority = 1;
         break;

       case DUMB_BORDER_CONST:	/* zero length border */
         pen = '+';
         priority = 2;
         break;

       default:
         pen = dumb_pen;
         priority = 3;
         break;
       }
      for (delta = 0; delta <= abs (x - dumb_x); delta++)
	dumb_set_pixel (dumb_x + delta * sign (x - dumb_x),
			dumb_y + delta * sign (y - dumb_y),
			pen, priority);
    }
  dumb_x = x;
  dumb_y = y;
}


DUMB_put_text(x,y,str)
int x, y;
char *str;
{
  int length;
  int delta;

  length = strlen(str);
  if (x + length > dumb_xmax)
    x = max (0, dumb_xmax - length);

  for (; x < dumb_xmax && *str; x++, str++)
    dumb_set_pixel (x, y, *str, 5);
}


DUMB_arrow (sx,sy,ex,ey)
int sx,sy,ex,ey;
{
  char saved_pen;
  char saved_x;
  char saved_y;

  saved_pen = dumb_pen;
  saved_x = dumb_x;
  saved_y = dumb_y;

  dumb_pen = '>';
  dumb_x = sx;
  dumb_y = sy;
  DUMB_vector (ex,ey);

  dumb_pen = saved_pen;
  dumb_x = saved_x;
  dumb_y = saved_y;
}
