
/* ------------------------------------------------------------------- */
/* ----                     New demo routines                     ---- */
/* ------------------------------------------------------------------- */


int _max(int a, int b)
{
  return ( a>b ? a : b );
}

int _min(int a, int b)
{
  return ( a<b ? a : b );
}

void ShiftDac(char pal[][3])
{
  int r,g,b;
  int k, l;

  for (k=0;k<=1;k++) {
    r=pal[254][0];
    g=pal[254][1];
    b=pal[254][2];
    for (l=254;l>=1;l--) {
      pal[l][0]=pal[l-1][0];
      pal[l][1]=pal[l-1][1];
      pal[l][2]=pal[l-1][2];
    }
    pal[1][0]=r;
    pal[1][1]=g;
    pal[1][2]=b;
  }
  for (k=0;k<=255;k++)
    setrgbpalette(k,pal[k][0],pal[k][1],pal[k][2]);
}

void PlayRGBpalette(void)
/* This is partially copyrighted by COPYRIGHT(C) 1990 by H+BEDV  */
{
  typedef char _PAL[256][3];

  int x,c, m, maxx, maxy, radius, height, ycenter;
  float pc;
  _PAL cpal;
  struct viewporttype     viewinfo;

  if ( getmaxcolor() != 255) return;

  for (c=0;c<=255;c++) {
    m= (c*3)>>1;
    if ((m<64)) {
      cpal[c][0]=63;
      cpal[c][1]=m;
      cpal[c][2]=0;
    }
    if ((m>63) && (m<128)) {
      cpal[c][0]=127-m;
      cpal[c][1]=63;
      cpal[c][2]=0;
    }
    if ((m>127) && (m<192)) {
      cpal[c][0]=0;
      cpal[c][1]=63;
      cpal[c][2]=m-128;
    }
    if ((m>191) && (m<256)) {
      cpal[c][0]=0;
      cpal[c][1]=255-m;
      cpal[c][2]=63;
    }
    if ((m>255) && (m<320)) {
      cpal[c][0]=m-256;
      cpal[c][1]=0;
      cpal[c][2]=63;
    }
    if ((m>319)) {
      cpal[c][0]=63;
      cpal[c][1]=0;
      cpal[c][2]=383-m;
    }
  }
  cpal[0][0]=0;
  cpal[0][1]=0;
  cpal[0][2]=0;
  cpal[255][0]=63;
  cpal[255][1]=63;
  cpal[255][2]=63;
  ShiftDac( cpal);

  MainWindowColor( "Play RGB palette", 255);
  getviewsettings( &viewinfo );
  maxx = abs(viewinfo.right-viewinfo.left)-1;
  maxy = abs(viewinfo.top-viewinfo.bottom)-1;
  setcolor(255);

  height = maxy/8;
  c=1;
  for (x=5; x <= maxx+1-5; ++x) {
    setcolor(c);
    if (++c > 254) c = 1;
    line(x,maxy-5,x,maxy-5-height);
  }

  pc=1.0;
  ycenter = (maxy-5-height) / 2;
  radius = _min(maxy-5-height, maxx)*9/20;
  for (x=0;x<=356;x++) {
    setcolor(pc);
    setfillstyle(SOLID_FILL,pc);
    pieslice(maxx/2,ycenter,x,x+4,radius);
    pc=pc+254.0/360.0;
  }

  StatusLineColor( StopMsg, 255);

  do {
    ShiftDac(cpal);
  } while (!(kbhit()));
  getch();
  for (c=1; c < 255; ++c) {
    cpal[c][0] = _dac_g256[c][0];
    cpal[c][1] = _dac_g256[c][1];
    cpal[c][2] = _dac_g256[c][2];
  }

  StatusLineColor( PauseMsg, 255);
  do {
    ShiftDac(cpal);
  } while (!(kbhit()));

  setbkcolor(BLACK);
  clearviewport();
  setrgbdefaults();
  Pause();                              /* Pause for user to read screen*/
}

/* The Sierpinski demo was mainly taken from
   N. Wirth: Algorithmen und Datenstrukturen  */
#define SIRP_N     4
#define SIRP_H0    320

static int SIRP_x, SIRP_y, h;

static void SIRP_a(int i);
static void SIRP_b(int i);
static void SIRP_c(int i);
static void SIRP_d(int i);

static void SIRP_a(int i)
{
  if (i>0) {
    SIRP_a(i-1); SIRP_x += h;   SIRP_y -= h; lineto( SIRP_x, SIRP_y);
    SIRP_b(i-1); SIRP_x += 2*h;              lineto( SIRP_x, SIRP_y);
    SIRP_d(i-1); SIRP_x += h;   SIRP_y += h; lineto( SIRP_x, SIRP_y);
    SIRP_a(i-1);
  }
}

static void SIRP_b(int i)
{
  if (i>0) {
    SIRP_b(i-1); SIRP_x -= h; SIRP_y -= h;   lineto( SIRP_x, SIRP_y);
    SIRP_c(i-1);              SIRP_y -= 2*h; lineto( SIRP_x, SIRP_y);
    SIRP_a(i-1); SIRP_x += h; SIRP_y -= h;   lineto( SIRP_x, SIRP_y);
    SIRP_b(i-1);
  }
}

static void SIRP_c(int i)
{
  if (i>0) {
    SIRP_c(i-1); SIRP_x -= h;   SIRP_y += h; lineto( SIRP_x, SIRP_y);
    SIRP_d(i-1); SIRP_x -= 2*h;              lineto( SIRP_x, SIRP_y);
    SIRP_b(i-1); SIRP_x -= h;   SIRP_y -= h; lineto( SIRP_x, SIRP_y);
    SIRP_c(i-1);
  }
}

static void SIRP_d(int i)
{
  if (i>0) {
    SIRP_d(i-1); SIRP_x += h; SIRP_y += h;   lineto( SIRP_x, SIRP_y);
    SIRP_a(i-1);              SIRP_y += 2*h; lineto( SIRP_x, SIRP_y);
    SIRP_c(i-1); SIRP_x -= h; SIRP_y += h;   lineto( SIRP_x, SIRP_y);
    SIRP_d(i-1);
  }
}

void sierpinski(void)
{
  int i, h0, x0, y0, bx, by;
  int border, color;
  struct viewporttype vp;
  struct fillsettingstype fs;

  MainWindow( "Floodfill demo");
  StatusLine(PauseMsg);
  getviewsettings( &vp);
  getfillsettings( &fs);

  setviewport( (bx=_max((getmaxx() - SIRP_H0) / 2, vp.left)),
	       (by=_max((getmaxy() - SIRP_H0) / 2, vp.top)),
	       _min((getmaxx() + SIRP_H0) / 2 + 5, vp.right),
	       _min((getmaxy() + SIRP_H0) / 2 + 5, vp.bottom),
	       TRUE );

  switch (random(6)) {
    case 0 : border = LIGHTCYAN;  break;
    case 1 : border = YELLOW;     break;
    case 2 : border = RED;        break;
    case 3 : border = GREEN;      break;
    case 4 : border = BLUE;       break;
    default: border = WHITE;      break;
  }
  setcolor( border);
  h0 = SIRP_H0;
  h = h0 / 4;
  x0 = 2*h;
  y0 = 3*h;
  for (i=1; i <= SIRP_N; ++i) {
    x0 -= h;
    h /= 2;
    y0 += h;
    SIRP_x = x0; SIRP_y = y0;
    moveto( SIRP_x, SIRP_y);
    SIRP_a(i); SIRP_x += h; SIRP_y -= h; lineto(SIRP_x,SIRP_y);
    SIRP_b(i); SIRP_x -= h; SIRP_y -= h; lineto(SIRP_x,SIRP_y);
    SIRP_c(i); SIRP_x -= h; SIRP_y += h; lineto(SIRP_x,SIRP_y);
    SIRP_d(i); SIRP_x += h; SIRP_y += h; lineto(SIRP_x,SIRP_y);
  }
  setviewport( vp.left, vp.top, vp.right, vp.bottom, vp.clip);
  bx += h0/2 - vp.left;
  by += h0/2 - vp.top;
  do {
    do
      color = random(getmaxcolor()+1);
    while (color == WHITE || color == BLACK || color == border);
    setfillstyle(random(USER_FILL-1)+1, color);
    floodfill( bx, by, border);
    floodfill(  1,  1, border);
  } while ( !kbhit());
  setfillstyle( fs.pattern, fs.color);

  Pause();                              /* Pause for user to read screen*/
}

void RandomSolidBars(void)
{
  int color;

  MainWindow( "Random Solid/Line Bars" );
  StatusLine( PauseMsg );               /* Put msg at bottom of screen   */
  while( !kbhit() ){                    /* Until user enters a key...   */
    color = random( MaxColors-1 )+1;
    setcolor( color );
    /* SOLID_FILL && LINE_FILL are much faster */
    setfillstyle( SOLID_FILL+random(2), color );
    bar3d( random( getmaxx() ), random( getmaxy() ),
	   random( getmaxx() ), random( getmaxy() ), 0, OFF);
  }

  Pause();                              /* Pause for user's response    */

}

