d64bdd519f5f336cb60b0514fc90217c31a320f7
[xscreensaver] / hacks / wander.c
1 /* wander, by Rick Campbell <rick@campbellcentral.org>, 19 December 1998.
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 <stdio.h>
13
14 #include "screenhack.h"
15 #include "colors.h"
16 #include "erase.h"
17
18 #define MAXIMUM_COLOR_COUNT (256)
19
20 static unsigned int advance     = 0;
21 static Bool         circles     = 0;
22 static Colormap     color_map   = (Colormap)NULL;
23 static int          color_count = 0;
24 static int          color_index = 0;
25 static XColor       colors      [MAXIMUM_COLOR_COUNT];
26 static GC           context     = (GC)NULL;
27 static unsigned int density     = 0;
28 static int          depth       = 0;
29 static int          height      = 0;
30 static unsigned int length      = 0;
31 static unsigned int reset       = 0;
32 static unsigned int size        = 0;
33 static int          width       = 0;
34
35 static void
36 init_wander (Display *display, Window window)
37 {
38     XGCValues values;
39     XWindowAttributes attributes;
40
41     XClearWindow (display, window);
42     XGetWindowAttributes (display, window, &attributes);
43     width = attributes.width;
44     height = attributes.height;
45     depth = attributes.depth;
46     color_map = attributes.colormap;
47     if (color_count)
48     {
49         free_colors (display, color_map, colors, color_count);
50         color_count = 0;
51     }
52     context = XCreateGC (display, window, GCForeground, &values);
53     color_count = MAXIMUM_COLOR_COUNT;
54     make_color_loop (display, color_map,
55                     0,   1, 1,
56                     120, 1, 1,
57                     240, 1, 1,
58                     colors, &color_count, True, False);
59     if (color_count <= 0)
60     {
61         color_count = 2;
62         colors [0].red = colors [0].green = colors [0].blue = 0;
63         colors [1].red = colors [1].green = colors [1].blue = 0xFFFF;
64         XAllocColor (display, color_map, &colors [0]);
65         XAllocColor (display, color_map, &colors [1]);
66     }
67     color_index = random () % color_count;
68     
69     advance = get_integer_resource ("advance", "Integer");
70     density = get_integer_resource ("density", "Integer");
71     if (density < 1) density = 1;
72     reset = get_integer_resource ("reset", "Integer");
73     if (reset < 100) reset = 100;
74     circles = get_boolean_resource ("circles", "Boolean");
75     size = get_integer_resource ("size", "Integer");
76     if (size < 1) size = 1;
77     width = width / size;
78     height = height / size;
79     length = get_integer_resource ("length", "Integer");
80     if (length < 1) length = 1;
81     XSetForeground (display, context, colors [color_index].pixel);
82 }
83
84
85 static void
86 wander (Display *display, Window window)
87 {
88     int x = random () % width;
89     int y = random () % height;
90     int last_x = x;
91     int last_y = y;
92     int width_1 = width - 1;
93     int height_1 = height - 1;
94     int length_limit = length;
95     int reset_limit = reset;
96     int color_index = random () % color_count;
97     unsigned long color = colors [random () % color_count].pixel;
98     Pixmap pixmap = XCreatePixmap (display, DefaultRootWindow (display), size,
99                                    size, depth);
100     XSetForeground (display, context,
101                     BlackPixel (display, DefaultScreen (display)));
102     XFillRectangle (display, pixmap, context, 0, 0,
103                     width * size, height * size);
104     XSetForeground (display, context, color);
105     XFillArc (display, pixmap, context, 0, 0, size, size, 0, 360*64);
106
107     while (1)
108     {
109         if (random () % density)
110         {
111             x = last_x;
112             y = last_y;
113         }
114         else
115         {
116             last_x = x;
117             last_y = y;
118             x = (x + width_1  + (random () % 3)) % width;
119             y = (y + height_1 + (random () % 3)) % height;
120         }
121         if ((random () % length_limit) == 0)
122         {
123             if (advance == 0)
124             {
125                 color_index = random () % color_count;
126             }
127             else
128             {
129                 color_index = (color_index + advance) % color_count;
130             }
131             color = colors [color_index].pixel;
132             XSetForeground (display, context, color);
133             if (circles)
134             {
135                 XFillArc (display, pixmap, context,
136                           0, 0, size, size, 0, 360 * 64);
137             }
138         }
139         if ((random () % reset_limit) == 0)
140         {
141             erase_full_window (display, window);
142             color = colors [random () % color_count].pixel;
143             x = random () % width;
144             y = random () % height;
145             last_x = x;
146             last_y = y;
147             if (circles)
148             {
149                 XFillArc (display, pixmap, context, 0, 0, size, size, 0, 360*64);
150             }
151         }
152         if (size == 1)
153         {
154             XDrawPoint (display, window, context, x, y);
155         }
156         else
157         {
158             if (circles)
159             {
160                 XCopyArea (display, pixmap, window, context, 0, 0, size, size,
161                            x * size, y * size);
162             }
163             else
164             {
165                 XFillRectangle (display, window, context, x * size, y * size,
166                                size, size);
167             }
168         }
169         screenhack_handle_events (display);
170     }
171 }
172
173 char *progclass = "Wander";
174
175 char *defaults [] =
176 {
177     ".advance:    1",
178     ".density:    2",
179     ".length:     25000",
180     ".delay:      1",
181     ".reset:      2500000",
182     ".circles:    False",
183     ".size:       1",
184     0
185 };
186
187 XrmOptionDescRec options [] =
188 {
189     { "-advance", ".advance", XrmoptionSepArg, 0 },
190     { "-circles", ".circles",   XrmoptionNoArg, "True" },
191     { "-no-circles",".circles", XrmoptionNoArg, "False" },
192     { "-density", ".density", XrmoptionSepArg, 0 },
193     { "-length",  ".length",  XrmoptionSepArg, 0 },
194     { "-delay",   ".delay",   XrmoptionSepArg, 0 },
195     { "-reset",   ".reset",   XrmoptionSepArg, 0 },
196     { "-size",    ".size",    XrmoptionSepArg, 0 },
197     { 0, 0, 0, 0 }
198 };
199
200 void
201 screenhack (display, window)
202     Display *display;
203     Window window;
204 {
205     int delay = get_integer_resource ("delay", "Integer");
206     while (1)
207     {
208         init_wander (display, window);
209         wander (display, window);
210         screenhack_handle_events (display);
211         if (delay) sleep (delay);
212         erase_full_window (display, window);
213     }
214 }