http://slackware.bholcomb.com/slackware/slackware-11.0/source/xap/xscreensaver/xscree...
[xscreensaver] / hacks / helix.c
index 7ca03da7760377aed93d87006bac39bb71ae977d..9e28c9fd07f7ecad9351e34a5cbce9e23abd4224 100644 (file)
@@ -1,5 +1,4 @@
-/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1997
- *  Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1992-2006 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
 #include "screenhack.h"
 #include "erase.h"
 
-static double sins [360];
-static double coss [360];
+enum draw_state { HELIX, DRAW_HELIX, TRIG, DRAW_TRIG, LINGER, ERASE };
 
-static GC draw_gc;
-static unsigned int default_fg_pixel;
-static int sleep_time;
-static int subdelay;
+struct state {
+  enum draw_state dstate;
+  double sins [360];
+  double coss [360];
 
-static void
-init_helix (Display *dpy, Window window)
+  GC draw_gc;
+  unsigned int default_fg_pixel;
+  int sleep_time;
+  int subdelay;
+  eraser_state *eraser;
+
+  int width, height;
+  Colormap cmap;
+
+  int x1, y1, x2, y2, angle, i;
+
+  int radius1, radius2, d_angle, factor1, factor2, factor3, factor4;
+  int d_angle_offset;
+  int offset, dir, density;
+};
+
+static void *
+helix_init (Display *dpy, Window window)
 {
+  struct state *st = (struct state *) calloc (1, sizeof(*st));
   int i;
   XGCValues gcv;
   XWindowAttributes xgwa;
-  Colormap cmap;
+
+  st->sleep_time = get_integer_resource(dpy, "delay", "Integer");
+  st->subdelay = get_integer_resource(dpy, "subdelay", "Integer");
+
   XGetWindowAttributes (dpy, window, &xgwa);
-  cmap = xgwa.colormap;
-  gcv.foreground = default_fg_pixel =
-    get_pixel_resource ("foreground", "Foreground", dpy, cmap);
-  draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
-  gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
+  st->width = xgwa.width;
+  st->height = xgwa.height;
+  st->cmap = xgwa.colormap;
+  gcv.foreground = st->default_fg_pixel =
+    get_pixel_resource (dpy, st->cmap, "foreground", "Foreground");
+  st->draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+  gcv.foreground = get_pixel_resource (dpy, st->cmap, "background", "Background");
 
   for (i = 0; i < 360; i++)
     {
-      sins [i] = sin ((((double) i) / 180.0) * M_PI);
-      coss [i] = cos ((((double) i) / 180.0) * M_PI);
+      st->sins [i] = sin ((((double) i) / 180.0) * M_PI);
+      st->coss [i] = cos ((((double) i) / 180.0) * M_PI);
     }
+
+  st->dstate = (random() & 1) ? HELIX : TRIG;
+
+  return st;
 }
 
 static int
@@ -69,254 +93,260 @@ gcd (int a, int b)
 }
 
 static void
-helix (Display *dpy, Window window,
-       int radius1, int radius2, int d_angle,
-       int factor1, int factor2, int factor3, int factor4)
+helix (Display *dpy, Window window, struct state *st)
 {
-  XWindowAttributes xgwa;
-  int width, height;
-  int xmid, ymid;
-  int x1, y1, x2, y2, angle, limit;
-  int i;
+  int xmid = st->width / 2;
+  int ymid = st->height / 2;
+  int limit = 1 + (360 / gcd (360, st->d_angle));
 
-  XClearWindow (dpy, window);
-  XGetWindowAttributes (dpy, window, &xgwa);
-  width = xgwa.width;
-  height = xgwa.height;
-
-  xmid = width / 2;
-  ymid = height / 2;
-  x1 = xmid;
-  y1 = ymid + radius2;
-  x2 = xmid;
-  y2 = ymid + radius1;
-  angle = 0;
-  limit = 1 + (360 / gcd (360, d_angle));
+  if (st->i == 0)
+    {
+      st->x1 = xmid;
+      st->y1 = ymid + st->radius2;
+      st->x2 = xmid;
+      st->y2 = ymid + st->radius1;
+      st->angle = 0;
+    }
   
-  for (i = 0; i < limit; i++)
+/*  for (st->i = 0; st->i < limit; st->i++)*/
     {
       int tmp;
 #define pmod(x,y) (tmp=((x) % (y)), (tmp >= 0 ? tmp : (tmp + (y))))
 
-      x1 = xmid + (((double) radius1) * sins [pmod ((angle * factor1), 360)]);
-      y1 = ymid + (((double) radius2) * coss [pmod ((angle * factor2), 360)]);
-      XDrawLine (dpy, window, draw_gc, x1, y1, x2, y2);
-      x2 = xmid + (((double) radius2) * sins [pmod ((angle * factor3), 360)]);
-      y2 = ymid + (((double) radius1) * coss [pmod ((angle * factor4), 360)]);
-      XDrawLine (dpy, window, draw_gc, x1, y1, x2, y2);
-      angle += d_angle;
-
-      /* if we sleep every time, it's too slow */
-      if(subdelay && i%16 == 0) usleep(subdelay);
-
-      XFlush (dpy);
+      st->x1 = xmid + (((double) st->radius1) * st->sins [pmod ((st->angle * st->factor1), 360)]);
+      st->y1 = ymid + (((double) st->radius2) * st->coss [pmod ((st->angle * st->factor2), 360)]);
+      XDrawLine (dpy, window, st->draw_gc, st->x1, st->y1, st->x2, st->y2);
+      st->x2 = xmid + (((double) st->radius2) * st->sins [pmod ((st->angle * st->factor3), 360)]);
+      st->y2 = ymid + (((double) st->radius1) * st->coss [pmod ((st->angle * st->factor4), 360)]);
+      XDrawLine (dpy, window, st->draw_gc, st->x1, st->y1, st->x2, st->y2);
+      st->angle += st->d_angle;
     }
+    st->i++;
+
+    if (st->i >= limit)
+      st->dstate = LINGER;
 }
 
 static void
-trig (Display *dpy, Window window,
-      int d_angle, int factor1, int factor2,
-      int offset, int d_angle_offset, int dir, int density)
+trig (Display *dpy, Window window, struct state *st)
 {
-  XWindowAttributes xgwa;
-  int width, height;
-  int xmid, ymid;
-  int x1, y1, x2, y2;
-  int tmp, angle;
-  Colormap cmap;
+  int xmid = st->width / 2;
+  int ymid = st->height / 2;
 
-  XClearWindow (dpy, window);
-  XGetWindowAttributes (dpy, window, &xgwa);
-  cmap = xgwa.colormap;
-  width = xgwa.width;
-  height = xgwa.height;
-
-  xmid = width / 2;
-  ymid = height / 2;
-
-  while (d_angle >= -360 && d_angle <= 360)
+/*  while (st->d_angle >= -360 && st->d_angle <= 360)*/
     {
-      angle = d_angle + d_angle_offset;
-      x1 = (sins [pmod(angle * factor1, 360)] * xmid) + xmid;
-      y1 = (coss [pmod(angle * factor1, 360)] * ymid) + ymid;
-      x2 = (sins [pmod(angle * factor2 + offset, 360)] * xmid) + xmid;
-      y2 = (coss [pmod(angle * factor2 + offset, 360)] * ymid) + ymid;
-      XDrawLine(dpy, window, draw_gc, x1, y1, x2, y2);
-      tmp = (int) 360 / (2 * density * factor1 * factor2);
+      int tmp;
+      int angle = st->d_angle + st->d_angle_offset;
+      st->x1 = (st->sins [pmod(angle * st->factor1, 360)] * xmid) + xmid;
+      st->y1 = (st->coss [pmod(angle * st->factor1, 360)] * ymid) + ymid;
+      st->x2 = (st->sins [pmod(angle * st->factor2 + st->offset, 360)] * xmid) + xmid;
+      st->y2 = (st->coss [pmod(angle * st->factor2 + st->offset, 360)] * ymid) + ymid;
+      XDrawLine(dpy, window, st->draw_gc, st->x1, st->y1, st->x2, st->y2);
+      tmp = (int) 360 / (2 * st->density * st->factor1 * st->factor2);
       if (tmp == 0)    /* Do not want it getting stuck... */
        tmp = 1;        /* Would not need if floating point */
-      d_angle += dir * tmp;
-
-      /* this draws faster, so we sleep somewhat more often */
-      if(subdelay && d_angle%4 == 0) usleep(subdelay);
-      
-      /* without this, the subdelay effect is lost */
-      XFlush (dpy);
+      st->d_angle += st->dir * tmp;
     }
+
+  if (st->d_angle < -360 || st->d_angle > 360)
+    st->dstate = LINGER;
 }
 
+
 #define min(a,b) ((a)<(b)?(a):(b))
 
 static void
-random_helix (Display *dpy, Window window, XColor *color, Bool *got_color)
+random_helix (Display *dpy, Window window, struct state *st,
+              XColor *color, Bool *got_color)
 {
-  Colormap cmap;
-  int width, height;
-  int radius, radius1, radius2, d_angle, factor1, factor2, factor3, factor4;
+  int radius;
   double divisor;
-  XWindowAttributes xgwa;
-  XGetWindowAttributes (dpy, window, &xgwa);
-  width = xgwa.width;
-  height = xgwa.height;
-  cmap = xgwa.colormap;
 
-  radius = min (width, height) / 2;
+  radius = min (st->width, st->height) / 2;
 
-  d_angle = 0;
-  factor1 = 2;
-  factor2 = 2;
-  factor3 = 2;
-  factor4 = 2;
+  st->i = 0;
+  st->d_angle = 0;
+  st->factor1 = 2;
+  st->factor2 = 2;
+  st->factor3 = 2;
+  st->factor4 = 2;
 
   divisor = ((frand (3.0) + 1) * (((random() & 1) * 2) - 1));
 
   if ((random () & 1) == 0)
     {
-      radius1 = radius;
-      radius2 = radius / divisor;
+      st->radius1 = radius;
+      st->radius2 = radius / divisor;
     }
   else
     {
-      radius2 = radius;
-      radius1 = radius / divisor;
+      st->radius2 = radius;
+      st->radius1 = radius / divisor;
     }
 
-  while (gcd (360, d_angle) >= 2)
-    d_angle = random () % 360;
+  while (gcd (360, st->d_angle) >= 2)
+    st->d_angle = random () % 360;
 
 #define random_factor()                                \
   (((random() % 7) ? ((random() & 1) + 1) : 3) \
    * (((random() & 1) * 2) - 1))
 
-  while (gcd (gcd (gcd (factor1, factor2), factor3), factor4) != 1)
+  while (gcd (gcd (gcd (st->factor1, st->factor2), st->factor3), st->factor4) != 1)
     {
-      factor1 = random_factor ();
-      factor2 = random_factor ();
-      factor3 = random_factor ();
-      factor4 = random_factor ();
+      st->factor1 = random_factor ();
+      st->factor2 = random_factor ();
+      st->factor3 = random_factor ();
+      st->factor4 = random_factor ();
     }
 
   if (mono_p)
-    XSetForeground (dpy, draw_gc, default_fg_pixel);
+    XSetForeground (dpy, st->draw_gc, st->default_fg_pixel);
   else
     {
       hsv_to_rgb (random () % 360, frand (1.0), frand (0.5) + 0.5,
                  &color->red, &color->green, &color->blue);
-      if ((*got_color = XAllocColor (dpy, cmap, color)))
-       XSetForeground (dpy, draw_gc, color->pixel);
+      if ((*got_color = XAllocColor (dpy, st->cmap, color)))
+       XSetForeground (dpy, st->draw_gc, color->pixel);
       else
-       XSetForeground (dpy, draw_gc, default_fg_pixel);
+       XSetForeground (dpy, st->draw_gc, st->default_fg_pixel);
     }
-  helix (dpy, window, radius1, radius2, d_angle,
-        factor1, factor2, factor3, factor4);
+
+  XClearWindow (dpy, window);
 }
 
 static void
-random_trig (Display *dpy, Window window, XColor *color, Bool *got_color)
+random_trig (Display *dpy, Window window, struct state *st,
+             XColor *color, Bool *got_color)
 {
-  Colormap cmap;
-  int width, height;
-  int radius, d_angle, factor1, factor2;
-  int offset, d_angle_offset, dir, density;
-
-  XWindowAttributes xgwa;
-  XGetWindowAttributes (dpy, window, &xgwa);
-  width = xgwa.width;
-  height = xgwa.height;
-  cmap = xgwa.colormap;
-
-  radius = min (width, height) / 2;
-
-  d_angle = 0;
-  factor1 = (random() % 8) + 1;
+  st->d_angle = 0;
+  st->factor1 = (random() % 8) + 1;
   do {
-    factor2 = (random() % 8) + 1;
-  } while (factor1 == factor2);
+    st->factor2 = (random() % 8) + 1;
+  } while (st->factor1 == st->factor2);
 
-  dir = (random() & 1) ? 1 : -1;
-  d_angle_offset = random() % 360;
-  offset = ((random() % ((360 / 4) - 1)) + 1) / 4;
-  density = 1 << ((random() % 4) + 4); /* Higher density, higher angles */
+  st->dir = (random() & 1) ? 1 : -1;
+  st->d_angle_offset = random() % 360;
+  st->offset = ((random() % ((360 / 4) - 1)) + 1) / 4;
+  st->density = 1 << ((random() % 4) + 4);     /* Higher density, higher angles */
 
   if (mono_p)
-    XSetForeground (dpy, draw_gc, default_fg_pixel);
+    XSetForeground (dpy, st->draw_gc, st->default_fg_pixel);
   else
     {
       hsv_to_rgb (random () % 360, frand (1.0), frand (0.5) + 0.5,
                  &color->red, &color->green, &color->blue);
-      if ((*got_color = XAllocColor (dpy, cmap, color)))
-       XSetForeground (dpy, draw_gc, color->pixel);
+      if ((*got_color = XAllocColor (dpy, st->cmap, color)))
+       XSetForeground (dpy, st->draw_gc, color->pixel);
       else
-       XSetForeground (dpy, draw_gc, default_fg_pixel);
+       XSetForeground (dpy, st->draw_gc, st->default_fg_pixel);
     }
-  trig (dpy, window, d_angle, factor1, factor2,
-       offset, d_angle_offset, dir, density);
+
+  XClearWindow (dpy, window);
 }
 
-static void
-random_helix_or_trig (Display *dpy, Window window)
+
+/* random_helix_or_trig */
+static unsigned long
+helix_draw (Display *dpy, Window window, void *closure)
 {
+  struct state *st = (struct state *) closure;
   Bool free_color = False;
   XColor color;
-  int width, height;
-  XWindowAttributes xgwa;
-  Colormap cmap;
-  XGetWindowAttributes (dpy, window, &xgwa);
-  width = xgwa.width;
-  height = xgwa.height;
-  cmap = xgwa.colormap;
+  int delay = st->subdelay;
+  int erase_delay = 10000;
+  int ii;
+
+  if (st->eraser) {
+    st->eraser = erase_window (dpy, window, st->eraser);
+    if (st->eraser) 
+      delay = erase_delay;
+    goto END;
+  }
+
+  switch (st->dstate) 
+    {
+    case LINGER:
+      delay = st->sleep_time * 1000000;
+      st->dstate = ERASE;
+      break;
+
+    case ERASE:
+      st->eraser = erase_window (dpy, window, st->eraser);
+      delay = erase_delay;
+      if (free_color) XFreeColors (dpy, st->cmap, &color.pixel, 1, 0);
+      st->dstate = (random() & 1) ? HELIX : TRIG;
+      break;
+
+    case DRAW_HELIX:
+      for (ii = 0; ii < 10; ii++) {
+        helix (dpy, window, st);
+        if (st->dstate != DRAW_HELIX)
+          break;
+      }
+      break;
+
+    case DRAW_TRIG:
+      for (ii = 0; ii < 5; ii++) {
+        trig (dpy, window, st);
+        if (st->dstate != DRAW_TRIG)
+          break;
+      }
+      break;
+
+    case HELIX:
+      random_helix (dpy, window, st, &color, &free_color);
+      st->dstate = DRAW_HELIX;
+      break;
+
+    case TRIG:
+      random_trig(dpy, window, st, &color, &free_color);
+      st->dstate = DRAW_TRIG;
+      break;
+
+    default: 
+      abort();
+    }
 
-  if (random() & 1)
-    random_helix(dpy, window, &color, &free_color);
-  else
-    random_trig(dpy, window, &color, &free_color);
+ END:
+  return delay;
+}
 
-  XSync (dpy, False);
-  screenhack_handle_events (dpy);
-  sleep ( sleep_time );
+static void
+helix_reshape (Display *dpy, Window window, void *closure, 
+                 unsigned int w, unsigned int h)
+{
+  struct state *st = (struct state *) closure;
+  st->width = w;
+  st->height = h;
+}
 
-  screenhack_handle_events (dpy);
-  erase_full_window(dpy, window);
+static Bool
+helix_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+  return False;
+}
 
-  if (free_color) XFreeColors (dpy, cmap, &color.pixel, 1, 0);
-  XSync (dpy, False);
-  screenhack_handle_events (dpy);
-  sleep (1);
+static void
+helix_free (Display *dpy, Window window, void *closure)
+{
+  struct state *st = (struct state *) closure;
+  free (st);
 }
 
-\f
-char *progclass = "Helix";
 
-char *defaults [] = {
+\f
+static const char *helix_defaults [] = {
   ".background: black",
+  ".foreground: white",
   "*delay:      5",
-  "*subdelay:  0",
+  "*subdelay:  20000",
   0
 };
 
-XrmOptionDescRec options [] = {   
+static XrmOptionDescRec helix_options [] = {   
   { "-delay",           ".delay",               XrmoptionSepArg, 0 },
   { "-subdelay",        ".subdelay",            XrmoptionSepArg, 0 },
   { 0,                 0,                      0,               0 },
 };
-int options_size = (sizeof (options) / sizeof (options[0]));
 
-void
-screenhack (Display *dpy, Window window)
-{
-  sleep_time = get_integer_resource("delay", "Integer");
-  subdelay = get_integer_resource("subdelay", "Integer");
-  init_helix (dpy, window);
-  while (1)
-    random_helix_or_trig (dpy, window);
-}
+XSCREENSAVER_MODULE ("Helix", helix)