# define graphics_IMP
# include "graphics.hh"

#ifndef SW
# include <curses.h>
#else
# include <stdio.h>
# include <suntool/gfx_hs.h>
#endif

#ifdef SW
#define w_sqr(x, y, s)\
	pw_writebackground (room->gfx_pixwin,\
			    x-(s/2), y-(s/2), s, s, PIX_CLR);

#define b_sqr(x, y, s)\
	pw_writebackground (room->gfx_pixwin,\
			    x-(s/2), y-(s/2), s, s, PIX_SET);

/* graphic window */

PRIVATE	struct gfxsubwindow *room;

PRIVATE	struct snapshot {	/* current status for redrawing */
	int  phil[4];	/*  1: standup; 0: sitdown  */
	int  chst[4];	/* -1: table;   i: phil[i]  */
	} snapshot;
#endif
/* philosophers' addresses */

#ifndef SW
PRIVATE	int pyup [4]= {  1,  6, 11, 16};	/* stand up */
PRIVATE	int pxup [4]= {  0,  0,  0,  0};

PRIVATE	int pydn [4]= {  2,  9, 16,  9};	/* sit down */
PRIVATE	int pxdn [4]= { 39, 51, 39, 24};

/* chopsticks' addresses */

PRIVATE	int cyup [4][4]= { {  4,  0,  0,  4},	/* on hands */
		           {  7, 13,  0,  0},
		           {  0, 16, 16,  0},
		           {  0,  0, 13,  7} };
PRIVATE	int cxup [4][4]= { { 42,  0,  0, 32},
		           { 51, 51,  0,  0},
		           {  0, 42, 32,  0},
		           {  0,  0, 23, 23} };

PRIVATE	int cydn [4]= {  4, 16, 16,  4};	/* on table */
PRIVATE	int cxdn [4]= { 50, 50, 24, 24};
#else
PRIVATE	int pyup [4]= {90, 150, 210, 270};	/* stand up */
PRIVATE	int pxup [4]= {40, 40, 40, 40};

PRIVATE	int pydn [4]= {70, 150, 230, 150};	/* sit down */
PRIVATE	int pxdn [4]= {300, 380, 300, 220};

/* chopsticks' addresses */

PRIVATE	int cyup [4][4]= { { 80,   0,   0,  80},	/* on hands */
			   {120, 180,   0,   0},
			   {  0, 220, 220,   0},
			   {  0,   0, 180, 120} };
PRIVATE	int cxup [4][4]= { {330,   0,   0, 270},
			   {370, 370,   0,   0},
			   {  0, 330, 270,   0},
			   {  0,   0, 230, 230} };

PRIVATE	int cydn [4]= { 80, 220, 220,  80};	/* on table */
PRIVATE	int cxdn [4]= {370, 370, 230, 230};
#endif

/*****   auxiliary functions   *****/

#ifdef SW
PRIVATE	void	printout	();
#endif
PRIVATE	void
drawphilo (y, x)
     int y, x;
{
#ifndef SW
	move (y, x); addch ('o');
	y++;
	move (y, x); addch ('!');
	x++;
	move (y, x); addch ('_');
	y++; x++;
	move (y, x); addch ('!');
#else
	b_sqr (x, y, 40);
#endif
}

PRIVATE	void
clearphilo (y, x)
     int y, x;
{
#ifndef SW
	move (y, x); addch (' ');
	y++;
	move (y, x); addch (' ');
	x++;
	move (y, x); addch (' ');
	y++; x++;
	move (y, x); addch (' ');
#else
	w_sqr (x, y, 40);
#endif
}

PRIVATE	void
drawchop (y, x)
     int y, x;
{
#ifndef SW
    move (y, x); addstr ("=======");
#else
    b_sqr (x, y, 20);
#endif
}

PRIVATE	void
clearchop (y, x)
     int y, x;
{
#ifndef SW
	move (y, x); addstr ("       ");
#else
	w_sqr (x, y, 20);
#endif
}

#ifdef SW
PRIVATE	void
refresh	()
{
  /* check to see if window has changed size or been exposed */
  if (room->gfx_flags & GFX_DAMAGED)
    gfxsw_handlesigwinch (room);
  
  /* screen has been corrupted and must be redrawn */
  if (room->gfx_flags & GFX_RESTART) {
    room->gfx_flags &= ~GFX_RESTART;
    printout ();
    }
}
#endif

PRIVATE	int
otoi	(exp)
     kdatum	exp;
{
  int i;

  if (kd_gequal (exp, n1(), 0x2))
    i= 0;
  else if (kd_gequal (exp, n2(), 0x2))
    i= 1;
  else if (kd_gequal (exp, n3(), 0x2))
    i= 2;
  else if (kd_gequal (exp, n4(), 0x2))
    i= 3;
  else
    exit (1);
  kd_free (exp);
  return i;
}

/*****   functions called from LOTOS specification   *****/

PUBLIC	void
sitdown (oni)
     kdatum oni;
{
	int i;
  
  i= otoi (oni);	/* also makes an implicit kd_free */
  clearphilo (pyup [i], pxup [i]);
  drawphilo  (pydn [i], pxdn [i]);
#ifndef SW
  move (23,  0);
#else
  snapshot.phil[i]= 0;
#endif
  refresh ();
}

PUBLIC	void
standup (oni)
     kdatum oni;
{
  int i;
  
  i= otoi (oni);	/* also makes an implicit kd_free */
  clearphilo (pydn [i], pxdn [i]);
  drawphilo  (pyup [i], pxup [i]);
#ifndef SW
  move (23,  0); refresh ();
#else
  snapshot.phil[i]= 1;
#endif
  refresh ();
}

PUBLIC	void
pick (onp, onc)
     kdatum onp, onc;
{
  int p, c;
  
  p= otoi (onp);	/* also makes an implicit kd_free */
  c= otoi (onc);	/* also makes an implicit kd_free */
  clearchop (cydn [c], cxdn [c]);
  drawchop  (cyup [p][c], cxup [p][c]);
#ifndef SW
  move (23,  0); refresh ();
#else
  snapshot.chst[c]= p;
#endif
  refresh ();
}

PUBLIC	void
put (onp, onc)
     kdatum onp, onc;
{
  int p, c;
  
  p= otoi (onp);	/* also makes an implicit kd_free */
  c= otoi (onc);	/* also makes an implicit kd_free */
  clearchop (cyup [p][c], cxup [p][c]);
  drawchop  (cydn [c], cxdn [c]);
#ifndef SW
  move (23,  0); refresh ();
#else
  snapshot.chst[c]= -1;
#endif
  refresh ();
}

PUBLIC	void
table ()
{
  int i;
  
#ifndef SW
	initscr ();
	move ( 0, 40); addch  ('1');
	move ( 1, 36); addstr ("---------");
	move ( 2, 36); addstr ("!       !");
	
	move ( 5, 30); addstr ("+-------------------+");
	move ( 6, 30); addch  ('!');
	move ( 6, 50); addch  ('!');
	move ( 7, 30); addch  ('!');
	move ( 7, 50); addch  ('!');
	move ( 8, 23); addstr ("!--    !");
	move ( 8, 36); addstr ("ooooooooo");
	move ( 8, 50); addstr ("!    --!"); 
	move ( 9, 23); addstr ("!      !");
	move ( 9, 36); addstr ("ooooooooo");
	move ( 9, 50); addstr ("!      !"); 
	move (10, 20); addstr ("4  !      !");
	move (10, 36); addstr ("ooooooooo");
	move (10, 50); addstr ("!      !  2");
	move (11, 23); addstr ("!      !");
	move (11, 36); addstr ("ooooooooo");
	move (11, 50); addstr ("!      !"); 
	move (12, 23); addstr ("!--    !");
	move (12, 36); addstr ("ooooooooo");
	move (12, 50); addstr ("!    --!"); 
	move (13, 30); addch  ('!');
	move (13, 50); addch  ('!');
	move (14, 30); addch  ('!');
	move (14, 50); addch  ('!');
	move (15, 30); addstr ("+-------------------+");
	
	move (18, 36); addstr ("!       !");
	move (19, 36); addstr ("---------");
	move (20, 40); addch  ('3');

	standup (n1());
	standup (n2());
	standup (n3());
	standup (n4());

	put (n1(), n1());
	put (n2(), n2());
	put (n3(), n3());
	put (n4(), n4());
#else
  if ((room= gfxsw_init (0, NULL)) == NULL) {
    fprintf (stderr, "philosophers: cannot open room!\n");
    exit (1);
  }
  
  for (i= 0; i < 4; i++) {
    snapshot.phil[i]= 1;
    snapshot.chst[i]= -1;
  }
  
  printout ();
#endif
}

#ifndef SW
#else
PRIVATE	kdatum
genon	(i)
     int i;
{
  switch (i) {
  case 0:
    return n1();
  case 1:
    return n2();
  case 2:
    return n3();
  case 3:
    return n4();
  }
}

PRIVATE	void
printout ()
{
  int i;
  kdatum gi;
  
  pw_writebackground (room->gfx_pixwin,
		      0, 0,
		      room->gfx_rect.r_width,
		      room->gfx_rect.r_height,
		      PIX_CLR);
  
  b_sqr (300, 150, 100);
  w_sqr (300, 150, 60);

  for (i= 0; i < 4; i++) {
    gi= genon(i);
    if (snapshot.phil[i])
      standup (kd_copy(gi));
    else
      sitdown (kd_copy(gi));
    if (snapshot.chst[i] == -1)
      put (kd_copy(gi), kd_copy(gi));
    else
      pick (genon(snapshot.chst[i]), kd_copy(gi));
    kd_free (gi);
  }
}
#endif
