http://www.ibiblio.org/pub/historic-linux/ftp-archives/sunsite.unc.edu/Sep-29-1996...
[xscreensaver] / hacks / hopalong.c
1 /* xscreensaver, Copyright (c) 1992, 1995 Jamie Zawinski <jwz@netscape.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 /* This file was ported from xlock for use in xscreensaver (and standalone)
13  * by jwz on 12-Aug-92.  Original copyright reads:
14  *
15  * hopalong.c - Real Plane Fractals for xlock, the X Window System lockscreen.
16  *
17  * Copyright (c) 1991 by Patrick J. Naughton.
18  *
19  * Permission to use, copy, modify, and distribute this software and its
20  * documentation for any purpose and without fee is hereby granted,
21  * provided that the above copyright notice appear in all copies and that
22  * both that copyright notice and this permission notice appear in
23  * supporting documentation.
24  *
25  * This file is provided AS IS with no warranties of any kind.  The author
26  * shall have no liability with respect to the infringement of copyrights,
27  * trade secrets or any patents by this file or any part thereof.  In no
28  * event will the author be liable for any lost revenue or profits or
29  * other special, indirect and consequential damages.
30  *
31  * Comments and additions should be sent to the author:
32  *
33  *                     naughton@eng.sun.com
34  *
35  *                     Patrick J. Naughton
36  *                     MS 21-14
37  *                     Sun Laboritories, Inc.
38  *                     2550 Garcia Ave
39  *                     Mountain View, CA  94043
40  *
41  * Revision History:
42  * 29-Oct-90: fix bad (int) cast.
43  * 29-Jul-90: support for multiple screens.
44  * 08-Jul-90: new timing and colors and new algorithm for fractals.
45  * 15-Dec-89: Fix for proper skipping of {White,Black}Pixel() in colors.
46  * 08-Oct-89: Fixed long standing typo bug in RandomInitHop();
47  *            Fixed bug in memory allocation in inithop();
48  *            Moved seconds() to an extern.
49  *            Got rid of the % mod since .mod is slow on a sparc.
50  * 20-Sep-89: Lint.
51  * 31-Aug-88: Forked from xlock.c for modularity.
52  * 23-Mar-88: Coded HOPALONG routines from Scientific American Sept. 86 p. 14.
53  */
54
55 #include <math.h>
56 #include "screenhack.h"
57
58 static GC gc;
59 static int batchcount = 1000;
60
61 static unsigned int *pixels = 0, fg_pixel, bg_pixel;
62 static int npixels;
63 static unsigned int delay;
64 static int timeout;
65
66 typedef struct {
67     int         centerx;
68     int         centery;        /* center of the screen */
69     double      a;
70     double      b;
71     double      c;
72     double      i;
73     double      j;              /* hopalong parameters */
74     int         inc;
75     int         pix;
76     long        startTime;
77 }           hopstruct;
78
79 static hopstruct hop;
80 static XPoint *pointBuffer = 0; /* pointer for XDrawPoints */
81
82 static void
83 inithop(dsp,win)
84      Display *dsp;
85     Window      win;
86 {
87     double      range;
88     XWindowAttributes xgwa;
89     hopstruct  *hp = &hop;
90     XGCValues gcv;
91     Colormap cmap;
92     XGetWindowAttributes (dsp, win, &xgwa);
93     cmap = xgwa.colormap;
94
95     if (! pixels)
96       {
97         XColor color;
98         int i = get_integer_resource ("ncolors", "Integer");
99         int shift;
100         if (i <= 2) i = 2, mono_p = True;
101         shift = 360 / i;
102         pixels = (unsigned int *) calloc (i, sizeof (unsigned int));
103         fg_pixel = get_pixel_resource ("foreground", "Foreground", dsp, cmap);
104         bg_pixel = get_pixel_resource ("background", "Background", dsp, cmap);
105         if (! mono_p)
106           {
107             hsv_to_rgb (random () % 360, 1.0, 1.0, 
108                         &color.red, &color.green, &color.blue);
109             for (npixels = 0; npixels < i; npixels++)
110               {
111                 if (! XAllocColor (dsp, cmap, &color))
112                   break;
113                 pixels[npixels] = color.pixel;
114                 cycle_hue (&color, shift);
115               }
116           }
117         timeout = get_integer_resource ("timeout", "Seconds");
118         if (timeout <= 0) timeout = 30;
119         delay = get_integer_resource ("delay", "Usecs");
120
121         gcv.foreground = fg_pixel;
122         gc = XCreateGC (dsp, win, GCForeground, &gcv);
123       }
124
125     XClearWindow (dsp, win);
126
127     hp->centerx = xgwa.width / 2;
128     hp->centery = xgwa.height / 2;
129     range = sqrt((double) hp->centerx * hp->centerx +
130                  (double) hp->centery * hp->centery) /
131         (10.0 + random() % 10);
132
133     hp->pix = 0;
134 #define frand0() (((double) random()) / ((unsigned int) (~0)))
135     hp->inc = (int) (frand0() * 200) - 100;
136     hp->a = frand0() * range - range / 2.0;
137     hp->b = frand0() * range - range / 2.0;
138     hp->c = frand0() * range - range / 2.0;
139     if (!(random() % 2))
140         hp->c = 0.0;
141
142     hp->i = hp->j = 0.0;
143
144     if (!pointBuffer)
145         pointBuffer = (XPoint *) malloc(batchcount * sizeof(XPoint));
146
147     XSetForeground(dsp, gc, bg_pixel);
148     XFillRectangle(dsp, win, gc, 0, 0,
149                    hp->centerx * 2, hp->centery * 2);
150     XSetForeground(dsp, gc, fg_pixel);
151     hp->startTime = time ((time_t *) 0);
152 }
153
154
155 static void
156 drawhop(dsp,win)
157      Display *dsp;
158     Window      win;
159 {
160     double      oldj;
161     int         k = batchcount;
162     XPoint     *xp = pointBuffer;
163     hopstruct  *hp = &hop;
164
165     hp->inc++;
166     if (! mono_p) {
167         XSetForeground(dsp, gc, pixels[hp->pix]);
168         if (++hp->pix >= npixels)
169             hp->pix = 0;
170     }
171     while (k--) {
172         oldj = hp->j;
173         hp->j = hp->a - hp->i;
174         hp->i = oldj + (hp->i < 0
175                         ? sqrt(fabs(hp->b * (hp->i + hp->inc) - hp->c))
176                         : -sqrt(fabs(hp->b * (hp->i + hp->inc) - hp->c)));
177         xp->x = hp->centerx + (int) (hp->i + hp->j);
178         xp->y = hp->centery - (int) (hp->i - hp->j);
179         xp++;
180     }
181     XDrawPoints(dsp, win, gc,
182                 pointBuffer, batchcount, CoordModeOrigin);
183     XSync (dsp, True);
184     if ((time ((time_t *) 0) - hp->startTime) > timeout)
185       {
186         int i;
187         XSetForeground(dsp, gc, bg_pixel);
188         for (i = 0; i < hp->centery; i++)
189           {
190             int y = (random () % (hp->centery << 1));
191             XDrawLine (dsp, win, gc, 0, y, hp->centerx << 1, y);
192             XFlush (dsp);
193             if ((i % 50) == 0)
194               usleep (10000);
195           }
196         XClearWindow (dsp, win);
197         XFlush (dsp);
198         sleep (1);
199         inithop(dsp,win);
200       }
201 }
202
203 \f
204 char *progclass = "Hopalong";
205
206 char *defaults [] = {
207   "Hopalong.background: black",         /* to placate SGI */
208   "Hopalong.foreground: white",
209   "*count:      1000",
210   "*ncolors:    100",
211   "*timeout:    20",
212   "*delay:      0",
213   0
214 };
215
216 XrmOptionDescRec options [] = {
217   { "-count",           ".count",       XrmoptionSepArg, 0 },
218   { "-ncolors",         ".ncolors",     XrmoptionSepArg, 0 },
219   { "-timeout",         ".timeout",     XrmoptionSepArg, 0 },
220   { "-delay",           ".delay",       XrmoptionSepArg, 0 },
221 };
222 int options_size = (sizeof (options) / sizeof (options[0]));
223
224 void
225 screenhack (dpy, window)
226      Display *dpy;
227      Window window;
228 {
229   inithop (dpy, window);
230   while (1)
231     {
232       drawhop (dpy, window);
233       XSync (dpy, True);
234       if (delay) usleep (delay);
235     }
236 }