#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <signal.h>
#include "grxlib.h"

#define Real float

#ifndef GRX_SCALE
#  define GRX_SCALE	10000
#endif

#define DEFAULT_DATA_FILE	"data"

static void
axis_round (Real *min, Real *max, Real *grid_spacing)
{
   int logspace;

   logspace = (int)(log10 ((*max  - *min)/10.0) + 0.5);
   *grid_spacing = pow (10, (double)logspace);
   *min = (Real)((int)(*min / (*grid_spacing))) * (*grid_spacing);
   *max = (Real)((int)(*max / (*grid_spacing))+1) * (*grid_spacing);
}

static int
nice_end (int junk)
{
   CloseGraphics ();
   putchar ('\n');
   exit (EXIT_SUCCESS);
   return 0;
}

int
main (int argc, char **argv)
{
   char line[256], *file = NULL;
   long id,winclick;
   int Do_Start = 1,tmp;
   Real x[1000000], y[1000000];
   Real nls[1000];
   int m, p, i, j, n, nchars, theight, twidth, xclick, yclick;
   int downx = 1000,downy = 1000,upx,upy;
   Real xmax, xmin, ymax, ymin, xdiff, ydiff, xgrid_spacing, ygrid_spacing;
   FILE *fd;
   char axis[100];
 
   LineFunction linetype = StartLine;

   ymax = xmax = -HUGE_VAL;
   ymin = xmin = HUGE_VAL;

   for (i = 1; i < argc; i++)
     {
	if (*argv[i] == '-')
	  {
	     if (!strcmp (argv[i], "-nl"))
	       linetype = StartPoint;
	     else if (argv[i][1] == '\0')	/* use stdin */
	       file = argv [i];
	     else
	       {

		  fprintf(stderr,
			  "Usage:\n\t %s [options] [file]\n\n", argv[0]);
		  fprintf(stderr,
			  "where options include:\n"
			  "  -pt                   plot with points instead of lines\n\n");

		  fprintf(stderr,
			  "file name `-' specifies stdin\n"
			  "if no file name is specified, "
			  "the default is \"%s\"\n\n",
			  DEFAULT_DATA_FILE);

		  return EXIT_FAILURE;
	       }
	  }
	else
	  {
	     file = argv [i];
	  }
     }

   if (!strcmp (file, "-"))
     {
	fd = stdin;
	file = "stdin";
     }
   else
     {
	if (file == NULL) file = DEFAULT_DATA_FILE;

	if ((fd = fopen (file, "r")) == NULL)
	  {
	     fprintf (stderr, "%s: can't open file \"%s\"\n", argv[0], file);
	     return EXIT_FAILURE;
	  }
     }
   m = 0;
   p = 0;
   while (fgets(line, sizeof(line),fd) != NULL)
     {
	if (sscanf(line,"%f %f",&x[m], &y[m]) == 2)
	  {
	     if (x[m] > xmax) xmax = x[m]; else if (x[m] < xmin) xmin = x[m];
	     if (y[m] > ymax) ymax = y[m]; else if (y[m] < ymin) ymin = y[m];
	     m++;
	  }
	else
	  {
	     nls [p] = m;
	     p++;
	  }
     }
   nls [p++] = m;

   if (m == 0)
     return;

#ifndef AMIGA
   signal(SIGTERM, nice_end);
   signal(SIGSTOP, nice_end);
   signal(SIGTSTP, nice_end);
   signal(SIGINT,  nice_end);
   signal(SIGQUIT, nice_end);
#endif

   if (!InitializeGraphics (1))
     return EXIT_FAILURE;

   n = 1;
   do
     {
	axis_round (&xmin, &xmax, &xgrid_spacing);
	axis_round (&ymin, &ymax, &ygrid_spacing);

	id = CreateWin (0, 0, GRX_SCALE, GRX_SCALE);
	if (id == 0)
	  {
	     fprintf (stderr,"Help id = 0\n");
	     return EXIT_FAILURE;
	  }
	/* Fill the window in black for real eye-catching graphics! */
	ForeColor (0);
	StartFill (id);
	FillArea (0, 0, GRX_SCALE, GRX_SCALE);
	Done ();

	/* draw outline box in white */
	ForeColor (7);

	/* Draw outline box */
	StartLine(id);
	Extend (1000, 1000);
	Extend (1000, 9000);
	Extend (9000, 9000);
	Extend (9000, 1000);
	Extend (1000, 1000);
	Done();

	/* Draw the data - either lines or dots */
	xdiff = 8000 / (xmax-xmin);
	ydiff = 8000 / (ymax-ymin);

	for (i = j = 0; j < p; j++)
	  {
	     int n = 0;

	     ForeColor (j%6+1);
	     while (((x[i] < xmin) || (x[i] > xmax) ||
		     (y[i] < ymin) || (y[i] > ymax)) && (i < nls [j]))
	       i++;

	     while (i < nls [j])
	       {
		  if (n == 0)
		    linetype (id);
		  Extend (1000+(x[i]-xmin)*xdiff,9000-(y[i]-ymin)*ydiff);
		  n++;
		  if (n > 450)
		    {
		       Done ();
		       n = 0;
		       continue;
		    }
		  i++;
		  while ((i < nls [j]) &&
			 ((x [i] < xmin) || (x [i] > xmax) ||
			  (y [i] < ymin) || (y [i] > ymax)))
		    i++;
	       }
	     if (n > 0)
	       Done ();
	  }

	/* Do axis labels in black */
	ForeColor (7);
	QueryWin (id, &twidth,&theight);
	PlaceText (id, GRX_SCALE/2, 0, HCENTER_TEXT|TOP_TEXT, file);
	PlaceText (id, GRX_SCALE/2, GRX_SCALE, HCENTER_TEXT|BOTTOM_TEXT, "X");
	PlaceText (id, 0, GRX_SCALE/2, LEFT_TEXT|VCENTER_TEXT, "Y");
	sprintf (axis, "%f", ymax);
	nchars = 1000 / twidth;

	axis [nchars] = 0;
	PlaceText (id, GRX_SCALE/10, GRX_SCALE/10,
		   RIGHT_TEXT|TOP_TEXT, axis);
	sprintf (axis, "%f", ymin);
	axis [nchars] = 0;
	PlaceText (id, GRX_SCALE/10, 9*GRX_SCALE/10,
		   RIGHT_TEXT|BOTTOM_TEXT,axis);
	sprintf (axis, "%f",xmax);
	PlaceText (id, 9*GRX_SCALE/10, 9*GRX_SCALE/10,
		   HCENTER_TEXT|TOP_TEXT,axis);
	sprintf (axis,"%f",xmin);
	PlaceText (id, GRX_SCALE/10, 9*GRX_SCALE/10,
		   HCENTER_TEXT|TOP_TEXT,axis);
	fflush (stdout);

	do
	  {
	     n = WaitForCarriageReturn (&winclick, &xclick, &yclick);
	     switch (n) {
	      case 1:
		downx = xclick;
		downy = yclick;
		break;
	      case 2:
		upx = xclick;
		upy = yclick;
		if (upx < downx)
		  {
		     tmp = downx;
		     downx = upx;
		     upx = tmp;
		  }
		if (upy < downy)
		  {
		     tmp = downy;
		     downy = upy;
		     upy = tmp;
		  }
		xmin = (xmax - xmin) * (downx - 1000) / (8000) + xmin;
		xmax = (xmax - xmin) * (upx - 1000) / (8000) + xmin;
		ymax = ymax - (ymax - ymin) * (downy - 1000) / (8000);
		ymin = ymax - (ymax - ymin) * (upy - 1000) / (8000);
		break;
	     }
	  }
	while (n && (n != 2));
     }
   while (n);
   nice_end (EXIT_SUCCESS);
   return EXIT_SUCCESS;
}
/*----------------------- end-of-file (C source) -----------------------*/
