#include <xsimple.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>

#define WIN_X 110
#define WIN_Y 75
#define WIN_W 800
#define WIN_H 600

#define COUNT 100000
#define SCALE 60
#define XOFF 0
#define YOFF 0

#define BGCOLOR BLACK
#define FGCOLOR GREEN

unsigned long bgcolor, fgcolor;

double scale = SCALE;
int xoff = XOFF, yoff = YOFF;

XImage *img;
int pad;


static void draw()
{
   static double x, y;
   double r;
   double a, b, c, d, e, f;
   double newx, newy;
   int sx, sy;

   r = (double)rand() / (double)RAND_MAX;
   if (r <= .01) {
       a = 0.; b = 0.; c = 0.; d = .16; e = 0.; f = 0.;
   } else if (r > .01 && r <= .86) {
       a = .85; b = .04; c = -.04; d = .85; e = 0.; f = 1.6;
   } else if (r > .86 && r <= .93) {
       a = .2; b = -.26; c = .23; d = .22; e = 0.; f = 1.6;
   } else {
       a = -.15; b = .28; c = .26; d = .24; e = 0.; f = .44;
   }

   newx = (a * x) + (b * y) + e;
   newy = (c * x) + (d * y) + f;
   x = newx; y = newy;

   sx = (int)(x * scale) + (WIN_W / 2) + xoff;
   sy = (WIN_H - 1) - ((int)(y * scale) - yoff);
   psetximage(img, sx, sy, FGCOLOR);
}

static void init()
{
   xinit("ifsfern", "Ifsfern", "IFS Fern", WIN_X, WIN_Y, WIN_W, WIN_H, 0,
           "black", "black", 0);
   img = mkximage(WIN_W, WIN_H, xv.depth, &pad);
   cls(BGCOLOR);
   update(0, 0, 0, 0);
   srand(time(NULL));
}

int main(int argc, char **argv)
{
   int i, count = COUNT;

   if (argc > 1) {
       if (argc < 5) {
           fprintf(stderr, "usage: ifsfern [count scale xoff yoff]\n");
           exit(1);
       }
       count = atoi(argv[1]);
       scale = atof(argv[2]);
       xoff = atoi(argv[3]);
       yoff = atoi(argv[4]);
   }

   init();

   for (i = 0; i < count; i++)
       draw();

   putximage(img, 0, 0, 0, 0, WIN_W, WIN_H);
   update(0, 0, 0, 0);

   for (;;) {
       XEvent e;

       while (getevent(&e)) {
           switch (e.type) {
               case Expose:
                   doexpose(&e);
                   break;
               case KeyPress:
                   if (XLookupKeysym((XKeyEvent *)&e, 0) == XK_q)
                       exit(0);
                   break;
           }
       }
       usleep(1000);
   }
}