http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.14.tar.gz
[xscreensaver] / hacks / decayscreen.c
index 32f8167ccae35583e27ab2d088a013a383fc645a..fa6561c1dae1a2e160ab87edc466193a9b972e27 100644 (file)
@@ -1,4 +1,5 @@
-/* xscreensaver, Copyright (c) 1992, 1993, 1994 Jamie Zawinski <jwz@mcom.com>
+/* xscreensaver, Copyright (c) 1992, 1993, 1994, 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
  *
  *  Vivek Khera <khera@cs.duke.edu>
  *  5-AUG-1993
+ *
+ *  Hacked by jwz, 28-Nov-97 (sped up and added new motion directions)
+ *  R. Schultz
+ *  Added "melt" & "stretch" modes 28-Mar-1999
+ *
  */
 
 #include "screenhack.h"
 static int sizex, sizey;
 static int delay;
 static GC gc;
+static int mode;
+static int iterations=100;
+
+#define SHUFFLE 0
+#define UP 1
+#define LEFT 2
+#define RIGHT 3
+#define DOWN 4
+#define UPLEFT 5
+#define DOWNLEFT 6
+#define UPRIGHT 7
+#define DOWNRIGHT 8
+#define IN 9
+#define OUT 10
+#define MELT 11
+#define STRETCH 12
+#define FUZZ 13
 
 static void
-init_decay (dpy, window)
-     Display *dpy;
-     Window window;
+init_decay (Display *dpy, Window window)
 {
   XGCValues gcv;
   XWindowAttributes xgwa;
-  int root_p;
-  Pixmap pixmap;
+  long gcflags;
+  unsigned long bg;
+
+  char *s = get_string_resource("mode", "Mode");
+  if      (s && !strcmp(s, "shuffle")) mode = SHUFFLE;
+  else if (s && !strcmp(s, "up")) mode = UP;
+  else if (s && !strcmp(s, "left")) mode = LEFT;
+  else if (s && !strcmp(s, "right")) mode = RIGHT;
+  else if (s && !strcmp(s, "down")) mode = DOWN;
+  else if (s && !strcmp(s, "upleft")) mode = UPLEFT;
+  else if (s && !strcmp(s, "downleft")) mode = DOWNLEFT;
+  else if (s && !strcmp(s, "upright")) mode = UPRIGHT;
+  else if (s && !strcmp(s, "downright")) mode = DOWNRIGHT;
+  else if (s && !strcmp(s, "in")) mode = IN;
+  else if (s && !strcmp(s, "out")) mode = OUT;
+  else if (s && !strcmp(s, "melt")) mode = MELT;
+  else if (s && !strcmp(s, "stretch")) mode = STRETCH;
+  else if (s && !strcmp(s, "fuzz")) mode = FUZZ;
+  else {
+    if (s && *s && !!strcmp(s, "random"))
+      fprintf(stderr, "%s: unknown mode %s\n", progname, s);
+    mode = random() % (FUZZ+1);
+  }
 
   delay = get_integer_resource ("delay", "Integer");
-  root_p = get_boolean_resource ("root", "Boolean");
 
   if (delay < 0) delay = 0;
 
+  XGetWindowAttributes (dpy, window, &xgwa);
+
   gcv.function = GXcopy;
   gcv.subwindow_mode = IncludeInferiors;
-  gc = XCreateGC (dpy, window, GCForeground |GCFunction | GCSubwindowMode,
-                 &gcv);
 
-  XGetWindowAttributes (dpy, window, &xgwa);
+  if (mode == MELT || mode == STRETCH) {
+    bg = get_pixel_resource ("background", "Background", dpy, xgwa.colormap);
+    gcv.foreground = bg;
+  }
+
+  gcflags = GCForeground |GCFunction;
+  if (use_subwindow_mode_p(xgwa.screen, window)) /* see grabscreen.c */
+    gcflags |= GCSubwindowMode;
+  gc = XCreateGC (dpy, window, gcflags, &gcv);
+
   sizex = xgwa.width;
   sizey = xgwa.height;
 
-  copy_default_colormap_contents (dpy, xgwa.colormap, xgwa.visual);
-  pixmap = grab_screen_image (dpy, window, root_p);
+  load_random_image (xgwa.screen, window, window, NULL);
+  
+  if (mode == MELT || mode == STRETCH) {
+    /* make sure screen eventually turns background color */
+    XDrawLine(dpy, window, gc, 0, 0, sizex, 0); 
+
+    /* slow down for smoother melting*/
+    iterations = 1;
+  }
+
 }
 
 
@@ -68,51 +127,144 @@ init_decay (dpy, window)
  * perform one iteration of decay
  */
 static void
-decay1 (dpy, window)
-     Display *dpy;
-     Window window;
+decay1 (Display *dpy, Window window)
 {
-    int left, top, width, height;
+    int left, top, width, height, toleft, totop;
+
+#define L 101
+#define R 102
+#define U 103
+#define D 104
+    static int no_bias[]        = { L,L,L,L, R,R,R,R, U,U,U,U, D,D,D,D };
+    static int up_bias[]        = { L,L,L,L, R,R,R,R, U,U,U,U, U,U,D,D };
+    static int down_bias[]      = { L,L,L,L, R,R,R,R, U,U,D,D, D,D,D,D };
+    static int left_bias[]      = { L,L,L,L, L,L,R,R, U,U,U,U, D,D,D,D };
+    static int right_bias[]     = { L,L,R,R, R,R,R,R, U,U,U,U, D,D,D,D };
+
+    static int upleft_bias[]    = { L,L,L,L, L,R,R,R, U,U,U,U, U,D,D,D };
+    static int downleft_bias[]  = { L,L,L,L, L,R,R,R, U,U,U,D, D,D,D,D };
+    static int upright_bias[]   = { L,L,L,R, R,R,R,R, U,U,U,U, U,D,D,D };
+    static int downright_bias[] = { L,L,L,R, R,R,R,R, U,U,U,D, D,D,D,D };
+    static int *bias;
+
+    switch (mode) {
+      case SHUFFLE:    bias = no_bias; break;
+      case UP:         bias = up_bias; break;
+      case LEFT:       bias = left_bias; break;
+      case RIGHT:      bias = right_bias; break;
+      case DOWN:       bias = down_bias; break;
+      case UPLEFT:     bias = upleft_bias; break;
+      case DOWNLEFT:   bias = downleft_bias; break;
+      case UPRIGHT:    bias = upright_bias; break;
+      case DOWNRIGHT:  bias = downright_bias; break;
+      case IN:         bias = no_bias; break;
+      case OUT:                bias = no_bias; break;
+      case MELT:       bias = no_bias; break;
+      case STRETCH:    bias = no_bias; break;
+      case FUZZ:       bias = no_bias; break;
+     default: abort();
+    }
 
 #define nrnd(x) (random() % (x))
 
-    switch (random() % 8) {
-      case 0:                  /* move a block left */
-      case 1:
-       left = nrnd(sizex - 1) + 1;
-       top = nrnd(sizey);
-       width = nrnd(sizex - left);
-       height = nrnd(sizey - top);
-       XCopyArea (dpy, window, window, gc, left, top, width, height,
-                  left - 1, top);
-       break;
-      case 2:                  /* move a block right */
-      case 3:
-       left = nrnd(sizex - 1);
-       top = nrnd(sizey);
-       width = nrnd(sizex - 1 - left);
-       height = nrnd(sizey - top);
-       XCopyArea (dpy, window, window, gc, left, top, width, height,
-                  left + 1, top);
-       break;
-      case 4:                  /* move a block up */
-       left = nrnd(sizex);
-       top = nrnd(sizey - 1) + 1;
-       width = nrnd(sizex - left);
-       height = nrnd(sizey - top);
-       XCopyArea (dpy, window, window, gc, left, top, width, height,
-                  left, top - 1);
-       break;
-      default:                 /* move block down (biased to this) */
-       left = nrnd(sizex);
-       top = nrnd(sizey - 1);
-       width = nrnd(sizex - left);
-       height = nrnd(sizey - 1 - top);
-       XCopyArea (dpy, window, window, gc, left, top, width, height,
-                  left, top + 1);
-       break;
+    if (mode == MELT || mode == STRETCH) {
+      left = nrnd(sizex/2);
+      top = nrnd(sizey);
+      width = nrnd( sizex/2 ) + sizex/2 - left;
+      height = nrnd(sizey - top);
+      toleft = left;
+      totop = top+1;
+
+    } else if (mode == FUZZ) {  /* By Vince Levey <vincel@vincel.org>;
+                                   inspired by the "melt" mode of the
+                                   "scrhack" IrisGL program by Paul Haeberli
+                                   circa 1991. */
+      static int toggle = 0;
+
+      left = nrnd(sizex - 1);
+      top  = nrnd(sizey - 1);
+      toggle = !toggle;
+      if (toggle)
+        {
+          totop = top;
+          height = 1;
+          toleft = nrnd(sizex - 1);
+          if (toleft > left)
+            {
+              width = toleft-left;
+              toleft = left;
+              left++;
+            }
+          else
+            {
+              width = left-toleft;
+              left = toleft;
+              toleft++;
+            }
+        }
+      else
+        {
+          toleft = left;
+          width = 1;
+          totop  = nrnd(sizey - 1);
+          if (totop > top)
+            {
+              height = totop-top;
+              totop = top;
+              top++;
+            }
+          else
+            {
+              height = top-totop;
+              top = totop;
+              totop++;
+            }
+        }
+
+    } else {
+
+      left = nrnd(sizex - 1);
+      top = nrnd(sizey);
+      width = nrnd(sizex - left);
+      height = nrnd(sizey - top);
+      
+      toleft = left;
+      totop = top;
+      if (mode == IN || mode == OUT) {
+       int x = left+(width/2);
+       int y = top+(height/2);
+       int cx = sizex/2;
+       int cy = sizey/2;
+       if (mode == IN) {
+         if      (x > cx && y > cy)   bias = upleft_bias;
+         else if (x < cx && y > cy)   bias = upright_bias;
+         else if (x < cx && y < cy)   bias = downright_bias;
+         else /* (x > cx && y < cy)*/ bias = downleft_bias;
+       } else {
+         if      (x > cx && y > cy)   bias = downright_bias;
+         else if (x < cx && y > cy)   bias = downleft_bias;
+         else if (x < cx && y < cy)   bias = upleft_bias;
+         else /* (x > cx && y < cy)*/ bias = upright_bias;
+       }
+      }
+      
+      switch (bias[random() % (sizeof(no_bias)/sizeof(*no_bias))]) {
+      case L: toleft = left-1; break;
+      case R: toleft = left+1; break;
+      case U: totop = top-1; break;
+      case D: totop = top+1; break;
+      default: abort(); break;
+      }
+    }
+    
+    if (mode == STRETCH) {
+      XCopyArea (dpy, window, window, gc, 0, sizey-top-2, sizex, top+1, 
+                0, sizey-top-1); 
+    } else {
+      XCopyArea (dpy, window, window, gc, left, top, width, height,
+                toleft, totop);
     }
-    XSync (dpy, True);
+
 #undef nrnd
 }
 
@@ -120,26 +272,33 @@ decay1 (dpy, window)
 char *progclass = "DecayScreen";
 
 char *defaults [] = {
-  "DecayScreen.mappedWhenManaged:false",
-  "DecayScreen.dontClearWindow:         true",
-  "*delay:                     10",
+  "*dontClearRoot:             True",
+
+#ifdef __sgi   /* really, HAVE_READ_DISPLAY_EXTENSION */
+  "*visualID:                  Best",
+#endif
+
+  "*delay:                     10000",
+  "*mode:                      random",
   0
 };
 
 XrmOptionDescRec options [] = {
   { "-delay",          ".delay",               XrmoptionSepArg, 0 },
+  { "-mode",           ".mode",                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)
 {
     init_decay (dpy, window);
     while (1) {
+      int i;
+      for (i = 0; i < iterations; i++)
        decay1 (dpy, window);
-       if (delay) usleep (delay);
+      XSync(dpy, False);
+      screenhack_handle_events (dpy);
+      if (delay) usleep (delay);
     }
 }