/*
	hdemo.C

	Version 1.1

	Demonstrate Hercules Library

	Copyright (C) 1993, Geoff Friesen B.Sc.
	All rights reserved.

	Developed with: Borland C++ 3.1
*/

#if !defined(__LARGE__)
#error Large Memory Model Expected
#endif

#include <conio.H>
#include <dos.H>
#include <math.H>
#include <stdlib.H>

#include "hlib.H"

#define	IGNORE	1

#define	ANGLE	45

double cos_angle, sin_angle, tmp_angle;
double prm [] =
{
   300, 150, 550, 150, 5
};

int	cbreak		(void);
void	cleanup		(void);
void	curve		(double x1, double y1, double x2, double y2,
			 double res);
void	demo1		(char *title);
void	demo2		(char *title);
void	demo3		(char *title);
void	demo4		(char *title);

struct
{
   char *title;
   void (*demo) (char *title);
}
demos [] =
{
   { "DEMO1: Character Set", demo1 },
   { "DEMO2: Bezier Curves", demo2 },
   { "DEMO3: Random Circles", demo3 },
   { "DEMO4: Dragon Curve", demo4 }
};

#define	NDEMOS	(sizeof(demos)/sizeof(demos [0]))

void interrupt (*oldint5) (void);
void interrupt newint5 (void);

void main (void)
{
   int i = 0;

   ctrlbrk (cbreak);

   if (!hexist ())
   {
       cputs ("hdemo: Hercules adaptor not found.\n");
       return;
   }

   if (hdriver ("DMP130") < 0)
   {
       cputs ("hdemo: unable to load DMP130 driver.\n");
       return;
   }

   oldint5 = getvect (0x5);
   setvect (0x5, newint5);
   atexit (cleanup);
   hon ();

   do
   {
      (*demos [i].demo) (demos [i].title);
      if (kbhit ())
	  break;
      sleep (2);
      if (++i == NDEMOS)
      {
	  i = 0;
	  hsetstate (!hgetstate ());
      }
   }
   while (1);

   if (!getch ())
       (void) getch ();

   exit (0);
}

int cbreak (void)
{
   return IGNORE;
}

void cleanup (void)
{
   setvect (0x5, oldint5);
   hoff ();
}

void curve (double x1, double y1, double x2, double y2, double res)
{
   double xd, yd;
   double mx, my;
   double xdr, ydr;

   if (res > 0)
       sin_angle = tmp_angle;
   else
       sin_angle = -tmp_angle;

   xd = x2-x1;
   yd = y2-y1;

   if (((xd*xd)+(yd*yd)) <= (prm [4]*prm [4]) || kbhit ())
       hline (x1, y1, x2, y2);
   else
   {
       xdr = xd/2/cos_angle;
       ydr = yd/2/cos_angle;
       mx = x1+xdr*cos_angle-ydr*sin_angle;
       my = y1+xdr*sin_angle+ydr*cos_angle;
       curve (x1, y1, mx, my, ANGLE);
       curve (mx, my, x2, y2, -ANGLE);
   }
}

void demo1 (char *title)
{
   int cx, cy, i;

   hcls ();
   hrectangle (1, 1, 718, VSIZE-2);
   hcenter (title, &cx, &cy);
   hmoveto (cx, VSIZE-10);
   hputs (title);

   hmoveto (10, 10);
   hputs ("IBM PC Character Set");

   hmoveto (10, 28);

   for (i = 0; i <= 255; i++)
   {
	hmoveto ((!(i & 15)) ? 10 : hwherex ()+16,
		 (!(i & 15)) ? hwherey ()+16 : hwherey ());
	hputc (i);
   }
}

void demo2 (char *title)
{
   int cx, cy, mid;

   hcls ();
   hrectangle (1, 1, 718, VSIZE-2);
   hcenter (title, &cx, &cy);
   hmoveto (cx, VSIZE-10);
   hputs (title);

   hmoveto (1, 1);
   hlineto (718, VSIZE-2);
   hmoveto (718, 1);
   hlineto (1, VSIZE-2);

   mid = VSIZE/2;

   hbezier1 (1, 1, 359, VSIZE-2, 718, 1, 0.001);
   hbezier1 (1, VSIZE-2, 359, 1, 718, VSIZE-2, 0.001);

   hbezier1 (1, 1, 718, mid, 1, VSIZE-2, 0.001);
   hbezier1 (718, 1, 1, mid, 718, VSIZE-2, 0.001);
}

void demo3 (char *title)
{
   int cx, cy, i, rcx, rcy, rr;

   hcls ();
   hrectangle (1, 1, 718, VSIZE-2);
   hcenter (title, &cx, &cy);
   hmoveto (cx, VSIZE-10);
   hputs (title);

   for (i = 0; i < 50; i++)
   {
      rcx = random(720);
      rcy = random(VSIZE);
      rr = random(200);
      if (rcx-rr < 1 || rcx+rr > 718 || rcy-rr < 1 || rcy+rr > VSIZE-1)
	  continue;
      hcircle (rcx, rcy, rr);
   }
}

void demo4 (char *title)
{
   int cx, cy;

   hcls ();
   hrectangle (1, 1, 718, VSIZE-2);
   hcenter (title, &cx, &cy);
   hmoveto (cx, VSIZE-10);
   hputs (title);

   cos_angle = cos (ANGLE*M_PI/180);
   tmp_angle = sin (ANGLE*M_PI/180);

   curve (prm [0], prm [1], prm [2], prm [3], prm [4]);
}

void interrupt newint5 (void)
{
   static int active = 0;

   if (active)
       return;

   active = 1;
   enable();
   hdump ();
   disable ();
   active = 0;
}