ftp://ftp.zenez.com/pub/SCO/Skunk96/UnixWare/FreeBird/x11/utils/xscreensaver-1.18...
[xscreensaver] / hacks / slidescreen.c
1 /* xscreensaver, Copyright (c) 1992, 1993 Jamie Zawinski <jwz@lucid.com>
2  *
3  * Permission to use, copy, modify, distribute, and sell this software and its
4  * documentation for any purpose is hereby granted without fee, provided that
5  * the above copyright notice appear in all copies and that both that
6  * copyright notice and this permission notice appear in supporting
7  * documentation.  No representations are made about the suitability of this
8  * software for any purpose.  It is provided "as is" without express or 
9  * implied warranty.
10  */
11
12 #include "screenhack.h"
13
14 static int grid_size;
15 static int pix_inc;
16 static int hole_x, hole_y;
17 static int bitmap_w, bitmap_h;
18 static int xoff, yoff;
19 static int grid_w, grid_h;
20 static int delay, delay2;
21 static GC gc;
22
23 static void
24 init_slide (dpy, window)
25      Display *dpy;
26      Window window;
27 {
28   int i;
29   XGCValues gcv;
30   XWindowAttributes xgwa;
31   int border;
32   int root_p;
33   unsigned long fg;
34   Pixmap pixmap;
35   Drawable d;
36   Colormap cmap;
37
38   XGetWindowAttributes (dpy, window, &xgwa);
39   cmap = xgwa.colormap;
40
41   delay = get_integer_resource ("delay", "Integer");
42   delay2 = get_integer_resource ("delay2", "Integer");
43   grid_size = get_integer_resource ("gridSize", "Integer");
44   pix_inc = get_integer_resource ("pixelIncrement", "Integer");
45   border = get_integer_resource ("internalBorderWidth", "InternalBorderWidth");
46   fg = get_pixel_resource ("background", "Background", dpy, cmap);
47   root_p = get_boolean_resource ("root", "Boolean");
48
49   if (delay < 0) delay = 0;
50   if (delay2 < 0) delay2 = 0;
51   if (pix_inc < 1) pix_inc = 1;
52   if (grid_size < 1) grid_size = 1;
53
54   gcv.foreground = fg;
55   gcv.function = GXcopy;
56   gcv.subwindow_mode = IncludeInferiors;
57   gc = XCreateGC (dpy, window, GCForeground |GCFunction | GCSubwindowMode,
58                   &gcv);
59
60   pixmap = grab_screen_image (dpy, window, root_p);
61
62   XGetWindowAttributes (dpy, window, &xgwa);
63   bitmap_w = xgwa.width;
64   bitmap_h = xgwa.height;
65
66   grid_w = bitmap_w / grid_size;
67   grid_h = bitmap_h / grid_size;
68   hole_x = random () % grid_w;
69   hole_y = random () % grid_h;
70   xoff = (bitmap_w - (grid_w * grid_size)) / 2;
71   yoff = (bitmap_h - (grid_h * grid_size)) / 2;
72
73   d = (pixmap ? pixmap : window);
74
75   if (border)
76     {
77       int i;
78       for (i = 0; i <= bitmap_w; i += grid_size)
79         XFillRectangle (dpy, d, gc, xoff+i-border/2, yoff, border, bitmap_h);
80       for (i = 0; i <= bitmap_h; i += grid_size)
81         XFillRectangle (dpy, d, gc, xoff, yoff+i-border/2, bitmap_w, border);
82     }
83
84   if (xoff)
85     {
86       XFillRectangle (dpy, d, gc, 0, 0, xoff, bitmap_h);
87       XFillRectangle (dpy, d, gc, bitmap_w - xoff, 0, xoff, bitmap_h);
88     }
89   if (yoff)
90     {
91       XFillRectangle (dpy, d, gc, 0, 0, bitmap_w, yoff);
92       XFillRectangle (dpy, d, gc, 0, bitmap_h - yoff, bitmap_w, yoff);
93     }
94
95   if (pixmap) XClearWindow (dpy, window);
96   XSync (dpy, True);
97   if (delay2) usleep (delay2 * 2);
98  for (i = 0; i < grid_size; i += pix_inc)
99    {
100      XPoint points [3];
101      points[0].x = xoff + grid_size * hole_x;
102      points[0].y = yoff + grid_size * hole_y;
103      points[1].x = points[0].x + grid_size;
104      points[1].y = points[0].y;
105      points[2].x = points[0].x;
106      points[2].y = points[0].y + i;
107      XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
108
109      points[1].x = points[0].x;
110      points[1].y = points[0].y + grid_size;
111      points[2].x = points[0].x + i;
112      points[2].y = points[0].y + grid_size;
113      XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
114
115      points[0].x = points[1].x + grid_size;
116      points[0].y = points[1].y;
117      points[2].x = points[0].x;
118      points[2].y = points[0].y - i;
119      XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
120
121      points[1].x = points[0].x;
122      points[1].y = points[0].y - grid_size;
123      points[2].x = points[1].x - i;
124      points[2].y = points[1].y;
125      XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
126
127      XSync (dpy, True);
128      if (delay) usleep (delay);
129    }
130
131   XFillRectangle (dpy, window, gc,
132                   xoff + grid_size * hole_x,
133                   yoff + grid_size * hole_y,
134                   grid_size, grid_size);
135 }
136
137 static void
138 slide1 (dpy, window)
139      Display *dpy;
140      Window window;
141 {
142   /* this code is a total kludge, but who cares, it works... */
143  int i, x, y, ix, iy, dx, dy, dir, w, h, size, inc;
144  static int last = -1;
145  do {
146    dir = random () % 4;
147    switch (dir)
148      {
149      case 0: dx = 0,  dy = 1;  break;
150      case 1: dx = -1, dy = 0;  break;
151      case 2: dx = 0,  dy = -1; break;
152      case 3: dx = 1,  dy = 0;  break;
153      }
154  } while (dir == last ||
155           hole_x + dx < 0 || hole_x + dx >= grid_w ||
156           hole_y + dy < 0 || hole_y + dy >= grid_h);
157  if (grid_w > 1 && grid_h > 1)
158    last = (dir == 0 ? 2 : dir == 2 ? 0 : dir == 1 ? 3 : 1);
159
160  switch (dir)
161    {
162    case 0: size = 1 + (random()%(grid_h - hole_y - 1)); h = size; w = 1; break;
163    case 1: size = 1 + (random()%hole_x);                w = size; h = 1; break;
164    case 2: size = 1 + (random()%hole_y);                h = size; w = 1; break;
165    case 3: size = 1 + (random()%(grid_w - hole_x - 1)); w = size; h = 1; break;
166    }
167
168  if (dx == -1) hole_x -= (size - 1);
169  else if (dy == -1) hole_y -= (size - 1);
170
171  ix = x = xoff + (hole_x + dx) * grid_size;
172  iy = y = yoff + (hole_y + dy) * grid_size;
173  inc = pix_inc;
174  for (i = 0; i < grid_size; i += inc)
175    {
176      if (inc + i > grid_size)
177        inc = grid_size - i;
178      XCopyArea (dpy, window, window, gc, x, y, grid_size * w, grid_size * h,
179                 x - dx * inc, y - dy * inc);
180      x -= dx * inc;
181      y -= dy * inc;
182      switch (dir)
183        {
184        case 0: XFillRectangle (dpy, window, gc,
185                                ix, y + grid_size * h, grid_size * w, iy - y);
186          break;
187        case 1: XFillRectangle (dpy, window, gc, ix, iy, x - ix, grid_size * h);
188          break;
189        case 2: XFillRectangle (dpy, window, gc, ix, iy, grid_size * w, y - iy);
190          break;
191        case 3: XFillRectangle (dpy, window, gc,
192                                x + grid_size * w, iy, ix - x, grid_size * h);
193          break;
194        }
195
196      XSync (dpy, True);
197      if (delay) usleep (delay);
198    }
199  switch (dir)
200    {
201    case 0: hole_y += size; break;
202    case 1: hole_x--; break;
203    case 2: hole_y--; break;
204    case 3: hole_x += size; break;
205    }
206 }
207
208 \f
209 char *progclass = "SlidePuzzle";
210
211 char *defaults [] = {
212   "SlidePuzzle.mappedWhenManaged:false",
213   "SlidePuzzle.dontClearWindow:  true",
214   "*background:                 black",
215   "*gridSize:                   70",
216   "*pixelIncrement:             10",
217   "*internalBorderWidth:        1",
218   "*delay:                      50000",
219   "*delay2:                     1000000",
220   0
221 };
222
223 XrmOptionDescRec options [] = {
224   { "-grid-size",       ".gridSize",            XrmoptionSepArg, 0 },
225   { "-ibw",             ".internalBorderWidth", XrmoptionSepArg, 0 },
226   { "-increment",       ".pixelIncrement",      XrmoptionSepArg, 0 },
227   { "-delay",           ".delay",               XrmoptionSepArg, 0 },
228   { "-delay2",          ".delay2",              XrmoptionSepArg, 0 },
229 };
230
231 int options_size = (sizeof (options) / sizeof (options[0]));
232
233 void
234 screenhack (dpy, window)
235      Display *dpy;
236      Window window;
237 {
238   init_slide (dpy, window);
239   while (1)
240     {
241       slide1 (dpy, window);
242       if (delay2) usleep (delay2);
243     }
244 }