http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.14.tar.gz
[xscreensaver] / hacks / helix.c
index 84c4fd8ca42340e49b3cc9f7e29f60ba7eae01cc..7ca03da7760377aed93d87006bac39bb71ae977d 100644 (file)
@@ -1,4 +1,5 @@
-/* xscreensaver, Copyright (c) 1992, 1995 Jamie Zawinski <jwz@netscape.com>
+/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1997
+ *  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
  * implied warranty.
  */
 
+/* Algorithm from a Mac program by Chris Tate, written in 1988 or so. */
+
+/* 18-Sep-97: Johannes Keukelaar (johannes@nada.kth.se): Improved screen
+ *            eraser.
+ * 10-May-97: merged ellipse code by Dan Stromberg <strombrg@nis.acs.uci.edu>
+ *            as found in xlockmore 4.03a10.
+ * 1992:      jwz created.
+ */
+
+/* 25 April 2002: Matthew Strait <straitm@mathcs.carleton.edu> added
+-subdelay option so the drawing process can be watched */
+
 #include <math.h>
 #include "screenhack.h"
+#include "erase.h"
 
 static double sins [360];
 static double coss [360];
 
-static GC draw_gc, erase_gc;
+static GC draw_gc;
 static unsigned int default_fg_pixel;
+static int sleep_time;
+static int subdelay;
 
 static void
-init_helix (dpy, window)
-     Display *dpy;
-     Window window;
+init_helix (Display *dpy, Window window)
 {
   int i;
   XGCValues gcv;
@@ -33,7 +47,6 @@ init_helix (dpy, window)
     get_pixel_resource ("foreground", "Foreground", dpy, cmap);
   draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
   gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
-  erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
 
   for (i = 0; i < 360; i++)
     {
@@ -43,8 +56,7 @@ init_helix (dpy, window)
 }
 
 static int
-gcd (a, b)
-     int a, b;
+gcd (int a, int b)
 {
   while (b > 0)
     {
@@ -57,13 +69,9 @@ gcd (a, b)
 }
 
 static void
-helix (dpy, window,
-       radius1, radius2, d_angle,
-       factor1, factor2, factor3, factor4)
-     Display *dpy;
-     Window window;
-     int radius1, radius2, d_angle;
-     int factor1, factor2, factor3, factor4;
+helix (Display *dpy, Window window,
+       int radius1, int radius2, int d_angle,
+       int factor1, int factor2, int factor3, int factor4)
 {
   XWindowAttributes xgwa;
   int width, height;
@@ -88,7 +96,8 @@ helix (dpy, window,
   for (i = 0; i < limit; i++)
     {
       int tmp;
-#define pmod(x,y) (tmp = (x % y), (tmp >= 0 ? tmp : tmp + y))
+#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);
@@ -96,6 +105,52 @@ helix (dpy, window,
       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);
+    }
+}
+
+static void
+trig (Display *dpy, Window window,
+      int d_angle, int factor1, int factor2,
+      int offset, int d_angle_offset, int dir, int density)
+{
+  XWindowAttributes xgwa;
+  int width, height;
+  int xmid, ymid;
+  int x1, y1, x2, y2;
+  int tmp, angle;
+  Colormap cmap;
+
+  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)
+    {
+      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);
+      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);
     }
 }
@@ -103,16 +158,12 @@ helix (dpy, window,
 #define min(a,b) ((a)<(b)?(a):(b))
 
 static void
-random_helix (dpy, window)
-     Display *dpy;
-     Window window;
+random_helix (Display *dpy, Window window, XColor *color, Bool *got_color)
 {
   Colormap cmap;
   int width, height;
   int radius, radius1, radius2, d_angle, factor1, factor2, factor3, factor4;
   double divisor;
-  XColor color;
-  int i, got_color = 0;
   XWindowAttributes xgwa;
   XGetWindowAttributes (dpy, window, &xgwa);
   width = xgwa.width;
@@ -160,29 +211,86 @@ random_helix (dpy, window)
   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);
+                 &color->red, &color->green, &color->blue);
+      if ((*got_color = XAllocColor (dpy, cmap, color)))
+       XSetForeground (dpy, draw_gc, color->pixel);
       else
        XSetForeground (dpy, draw_gc, default_fg_pixel);
     }
   helix (dpy, window, radius1, radius2, d_angle,
         factor1, factor2, factor3, factor4);
+}
+
+static void
+random_trig (Display *dpy, Window window, XColor *color, Bool *got_color)
+{
+  Colormap cmap;
+  int width, height;
+  int radius, d_angle, factor1, factor2;
+  int offset, d_angle_offset, dir, density;
 
-  XSync (dpy, True);
-  sleep (5);
+  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;
+  do {
+    factor2 = (random() % 8) + 1;
+  } while (factor1 == factor2);
 
-  for (i = 0; i < height; i++)
+  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 */
+
+  if (mono_p)
+    XSetForeground (dpy, draw_gc, default_fg_pixel);
+  else
     {
-      int y = (random () % height);
-      XDrawLine (dpy, window, erase_gc, 0, y, width, y);
-      XFlush (dpy);
-      if ((i % 50) == 0)
-       usleep (10000);
+      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);
+      else
+       XSetForeground (dpy, draw_gc, default_fg_pixel);
     }
-  XClearWindow (dpy, window);
-  if (got_color) XFreeColors (dpy, cmap, &color.pixel, 1, 0);
-  XSync (dpy, True);
+  trig (dpy, window, d_angle, factor1, factor2,
+       offset, d_angle_offset, dir, density);
+}
+
+static void
+random_helix_or_trig (Display *dpy, Window window)
+{
+  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;
+
+  if (random() & 1)
+    random_helix(dpy, window, &color, &free_color);
+  else
+    random_trig(dpy, window, &color, &free_color);
+
+  XSync (dpy, False);
+  screenhack_handle_events (dpy);
+  sleep ( sleep_time );
+
+  screenhack_handle_events (dpy);
+  erase_full_window(dpy, window);
+
+  if (free_color) XFreeColors (dpy, cmap, &color.pixel, 1, 0);
+  XSync (dpy, False);
+  screenhack_handle_events (dpy);
   sleep (1);
 }
 
@@ -190,19 +298,25 @@ random_helix (dpy, window)
 char *progclass = "Helix";
 
 char *defaults [] = {
-  "Helix.background: black",           /* to placate SGI */
+  ".background: black",
+  "*delay:      5",
+  "*subdelay:  0",
   0
 };
 
-XrmOptionDescRec options [] = { { 0, } };
-int options_size = 0;
+XrmOptionDescRec options [] = {   
+  { "-delay",           ".delay",               XrmoptionSepArg, 0 },
+  { "-subdelay",        ".subdelay",            XrmoptionSepArg, 0 },
+  { 0,                 0,                      0,               0 },
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
 
 void
-screenhack (dpy, window)
-     Display *dpy;
-     Window window;
+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 (dpy, window);
+    random_helix_or_trig (dpy, window);
 }