http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.01.tar.gz
[xscreensaver] / hacks / whirlygig.c
1 /*  Whirlygig -- an experiment in X programming
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  *  When I was in trigonometry class as a kid, I remember being fascinated
12  *  by the beauty of the shapes one receives when playing with sine waves
13  *  Here is a little experiment to show that beauty is simple
14  */
15 #include <stdio.h>
16 #include <math.h>
17 #include "screenhack.h"
18
19 #define NCOLORS 100
20 #define FULL_CYCLE 429496729
21 #define START_ARC 0
22 #define END_ARC 23040
23
24 struct info {
25     Bool            writable;               /* Is the screen writable */
26     double         xspeed;               /* A factor to modify the horizontal movement */
27     double         yspeed;               /* A factor to modify vertical movement */
28     double         xamplitude;
29     double         yamplitude;
30     int                whirlies;               /*  How many whirlies per line do you want? */
31     int                nlines;                 /*  How many lines of whirlies do you want? */
32     int                half_width;         /* 1/2 the width of the screen */
33     int                half_height;
34     int                speed;
35     int                trail;
36     int                color_modifier;
37     double                xoffset;
38     double                yoffset;
39     double                offset_period;
40     int                       wrap;
41 };
42
43 enum object_mode {
44     spin_mode, funky_mode, circle_mode, linear_mode, test_mode, fun_mode, innie_mode, lissajous_mode
45 } mode;
46
47 static void explain(int, struct info *, Display *, Window, GC);
48
49 static void spin(unsigned long int, struct info *, int *, int);
50 static void funky(unsigned long int, struct info *, int *, int);
51 static void circle(unsigned long int, struct info *, int *, int);
52 static void fun(unsigned long int, struct info *, int *, int);
53 static void linear(unsigned long int, struct info *, int *, int);
54 static void lissajous(unsigned long int, struct info *, int *, int);
55 static void test(unsigned long int, struct info *, int *, int);
56 static void innie(unsigned long int, struct info *, int *, int, double);
57
58
59
60 XColor colors[NCOLORS];
61 int ncolors = NCOLORS;
62 char *progclass = "Whirlygig";
63
64 char *defaults [] = {
65   ".background: black",
66   ".foreground: white",
67   "*xspeed: 1.0",
68   "*yspeed: 1.0",
69   "*xamplitude: 1.0",
70   "*yamplitude: 1.0",
71   "*whirlies: -1",
72   "*nlines: -1",
73   "*xmode: change",
74   "*ymode: change",
75   "*speed: 1",
76   "*trail: 0",
77   "*color_modifier: -1",
78   "*start_time: -1",
79   "*explain: 0",
80   "*xoffset: 1.0",
81   "*yoffset: 1.0",
82   "*offset_period:    1",
83   "*wrap:               0",
84   0
85 };
86
87 XrmOptionDescRec options [] = {
88   { "-xspeed",          ".xspeed", XrmoptionSepArg, 0 },
89       /* xspeed is a modifier of the argument to cos -- changing it thus
90          changes the frequency of cos */
91   { "-yspeed",          ".yspeed", XrmoptionSepArg, 0 },
92       /*  Similiarly, yspeed changes the frequency of sin */
93   { "-xamplitude",      ".xamplitude", XrmoptionSepArg, 0 },
94       /* A factor by which to increase/decrease the amplitude of the sin */
95   { "-yamplitude",      ".yamplitude", XrmoptionSepArg, 0 },
96       /* A factor by which to increase/decrease the amplitude of the cos */
97   { "-whirlies",         ".whirlies",XrmoptionSepArg, 0 },
98       /*  whirlies defines the number of circles to draw per line */
99   { "-nlines",         ".nlines",XrmoptionSepArg, 0 },
100       /* nlines is the number of lines of whirlies to draw */
101   { "-xmode",        ".xmode", XrmoptionSepArg, 0 },
102       /*  There are a few different modes that I have written -- each mode
103           is in theory a different experiment with the possible modifiers to sin/cos */
104   { "-ymode",       ".ymode", XrmoptionSepArg, 0 },
105   { "-speed",        ".speed", XrmoptionSepArg, 0 },
106       /*  This will modify how often it should draw, changing it will probably suck */
107   { "-trail",           ".trail", XrmoptionSepArg, 0 },
108       /* Control whether or not you want the old circles to be erased */
109   { "-color_modifier",          ".color_modifier", XrmoptionSepArg, 0 },
110       /*  How many colors away from the current should the next whirly be? */
111   { "-start_time",                ".start_time", XrmoptionSepArg, 0 },
112       /*  Specify exactly at what time to start graphing...  */
113   { "-xoffset",                    ".xoffset", XrmoptionSepArg, 0 },
114       /*  Tell the whirlies to be offset by this factor of a sin */
115   { "-yoffset",                    ".yoffset", XrmoptionSepArg, 0 },
116       /*  Tell the whirlies to be offset by this factor of a cos */
117   { "-offset_period",          ".offset_period", XrmoptionSepArg, 0 },
118       /*  Change the period of an offset cycle */
119   { "-explain",                    ".explain", XrmoptionSepArg, 0 },
120       /*  Specify whether or not to print an explanation of the function used. */
121   { "-wrap",                      ".wrap", XrmoptionSepArg, 0 },
122       /* Specify if you want whirlies which are out of the boundary of the screen to be
123          wrapped around to the other side */
124   { 0, 0, 0, 0 }
125 };
126
127
128 static const char funky_explanation[] =
129 "Funky mode is me goofing off.";
130
131 static const char test_explanation[] =
132 "Test mode is a mode that I play around with ideas in.";
133
134 static const char spin_explanation[] =
135 "Spin mode is a simple sin/cos with every argument modified";
136
137 static const char circle_explanation[] =
138 "Circle mode graphs the x and y positions as you trace the edge of a circle over time.";
139
140 static const char fun_explanation[] =
141 "Fun mode is the coolest.";
142
143 static const char linear_explanation[] =
144 "I draw a straight line -- woo hoo";
145
146 static const char lissajous_explanation[] =
147 "This draws a slightly modified lissajous curve";
148
149 static void
150 explain(int mode, struct info *info, Display *display, Window window, GC fgc)
151 {
152     XClearWindow(display, window);
153     switch(mode) {
154         case spin_mode:
155             XDrawString(display, window, fgc, 50, info->half_height-100, spin_explanation, strlen(spin_explanation));
156             break;
157         case funky_mode:
158             XDrawString(display, window, fgc, 50, info->half_height-100, funky_explanation, strlen(funky_explanation));
159             break;
160         case circle_mode:
161             XDrawString(display, window, fgc, 50, info->half_height-100, circle_explanation, strlen(circle_explanation));
162             break;
163         case fun_mode:
164             XDrawString(display, window, fgc, 50, info->half_height-100, fun_explanation, strlen(fun_explanation));
165             break;
166         case linear_mode:
167             XDrawString(display, window, fgc, 50, info->half_height-100, linear_explanation, strlen(linear_explanation));
168             break;
169     case lissajous_mode:
170             XDrawString(display, window, fgc, 50, info->half_height-100, lissajous_explanation, strlen(linear_explanation));
171       
172     }
173     XSync(display, False);
174     sleep(3);
175     XClearWindow(display, window);
176 }
177
178 static void
179 funky(unsigned long int the_time, struct info *info, int pos[], int index)
180 {
181     double new_time = ((the_time % 360 ) / 180.0) * M_PI;
182     if (index == 0) {
183         double time_modifier = cos(new_time / 180.0);
184         double the_cos = cos((new_time * (double)info->xspeed) + (time_modifier * 80.0));
185         double dist_mod_x = cos(new_time) * (info->half_width - 50);
186         pos[index]= info->xamplitude * (the_cos * dist_mod_x) + info->half_width;
187     }
188     else {
189         double new_time = ((the_time % 360 ) / 180.0) * M_PI;
190         double time_modifier = sin(new_time / 180.0);
191         double the_sin = sin((new_time * (double)info->yspeed) + (time_modifier * 80.0));
192         double dist_mod_y = sin(new_time) * (info->half_height - 50);
193         pos[index] = info->yamplitude * (the_sin * dist_mod_y) + info->half_height;
194     }
195 }
196
197 static void
198 innie(unsigned long int the_time, struct info *info, int pos[], int index, double modifier)
199 {
200     double frequency = 2000000.0 + (modifier * cos(((double)the_time / 100.0)));
201     double arg = (double)the_time / frequency;
202     double amplitude = 200.0 * cos(arg);
203     double fun = 150.0 * cos((double)the_time / 2000.0);
204     int vert_mod, horiz_mod;
205     if (index == 0) {
206         horiz_mod = (int)(fun * cos((double)the_time / 100.0)) + info->half_width;
207         pos[index] = (amplitude * cos((double)the_time / 100.0 * info->xspeed)) + horiz_mod;
208     }
209     else {
210         vert_mod = (int)(fun * sin((double)the_time / 100.0)) + info->half_height;
211         pos[index] = (amplitude * sin((double)the_time / 100.0 * info->yspeed)) + vert_mod;
212     }
213 }
214
215 static void
216 lissajous(unsigned long int the_time, struct info *info, int pos[], int index)
217 {
218       /*  This is a pretty standard lissajous curve
219            x = a sin(nt + c) 
220            y = b sin(t) 
221            The n and c modifiers are cyclic as well, however... */
222   int result;
223   double time = (double)the_time / 100.0;
224   double fun = 15.0 * cos((double)the_time / 800.0);
225   double weird = cos((time / 1100000.0) / 1000.0);
226
227   if (index == 0) {
228       result = info->xamplitude * 200.0 * sin((weird * time) + fun) + info->half_width;
229   }
230   else {
231       result = info->yamplitude * 200.0 * sin(time) + info->half_height;
232   }
233   pos[index] = result;
234
235
236 static void
237 circle(unsigned long int the_time, struct info *info, int pos[], int index)
238 {
239     int result;
240     if (index == 0) {
241         result = info->xamplitude * (cos((double)the_time / 100.0 * info->xspeed) * (info->half_width / 2)) + info->half_width;
242     }
243     else {
244         result = info->yamplitude * (sin((double)the_time / 100.0 * info->yspeed) * (info->half_height / 2)) + info->half_height;
245     }
246     pos[index] = result;
247 }
248
249 #if 0
250 static void
251 mod(unsigned long int the_time, struct info *info, int pos[], int index)
252 {
253     int amplitude;
254     int max = info->half_width;
255     if ((the_time % (max * 2)) < max)
256         amplitude = max - ((the_time % (max * 2)) - max);
257     else
258         amplitude = the_time % (max * 2);
259     amplitude = amplitude - max;
260 }
261 #endif
262
263 static void
264 spin(unsigned long int the_time, struct info *info, int pos[], int index)
265 {
266     double funky = (((the_time % 360) * 1.0) / 180.0) * M_PI;
267     if (index ==0) {
268     double the_cos = cos((double)the_time / (180.0 * info->xspeed));
269     double dist_mod_x = cos((double)funky) * (info->half_width - 50);
270     pos[index] = info->xamplitude * (the_cos * dist_mod_x) + info->half_width;
271     }
272     else {
273     double the_sin = sin((double)the_time / (180.0 * info->yspeed));
274     double dist_mod_y = sin((double)funky) * (info->half_height - 50);
275     pos[index] = info->yamplitude * (the_sin * dist_mod_y) + info->half_height;
276     }
277 }
278
279 static void
280 fun(unsigned long int the_time, struct info *info, int pos[], int index)
281 {
282     int amplitude;
283     int max = info->half_width;
284     if ((the_time % (max * 2)) < max)
285         amplitude = max - ((the_time % (max * 2)) - max);
286     else
287         amplitude = the_time % (max * 2);
288     amplitude = amplitude - max;
289     if (index ==0) {
290         pos[index] = (amplitude * cos((double)the_time / 100.0 * info->xspeed)) + info->half_width;
291     }
292     else {
293         pos[index] = (amplitude * sin((double)the_time / 100.0 * info->yspeed)) + info->half_height;
294     }
295 }
296
297 static void
298 linear(unsigned long int the_time, struct info *info, int pos[], int index)
299 {
300     if (index == 0)   /* Calculate for the x axis */
301         pos[index] = ((the_time / 2) % (info->half_width * 2));
302     else
303         pos[index] = ((the_time / 2) % (info->half_height * 2));
304 }
305
306 static void
307 test(unsigned long int the_time, struct info *info, int pos[], int index)
308 {
309     if (index == 0) {
310         pos[index] = info->xamplitude * (cos((double)the_time / 100.0 * info->xspeed) * (info->half_width / 2)) + info->half_width;
311     }
312     else {
313         pos[index] = info->yamplitude * (sin((double)the_time / 100.0 * info->yspeed) * (info->half_height / 2)) + info->half_height;
314     }   
315 }
316
317 static int preen(int current, int max) {
318     if (current > max)
319         current=current-max;
320     if (current < 0)
321         current=current+max;
322     return(current);
323 }
324
325 static void
326 smoothen(int x, int lastx, int y, int lasty, int size, int last_color, XColor *colors, Display *display, Window window, GC bgc, int screen, struct info *info)
327 {
328     double xdistance = abs((double)x-(double)lastx);
329     double ydistance = abs((double)y-(double)lasty);
330     double distance = sqrt(((xdistance * xdistance) + (ydistance * ydistance)) );
331     double slope = (((double)y-(double)lasty) / ((double)x-(double)lastx));
332     printf("Starting smoothen with values: %f, %f, %f, %f\n", xdistance, ydistance, distance, slope);
333     if (distance > 2.0) {
334         int newx = (int)((xdistance / distance) * slope);
335         int newy = (int)((ydistance / distance) * slope);
336         if (! info->trail) {
337             XSetForeground(display, bgc, BlackPixel(display, screen));
338             XFillArc(display, window, bgc, lastx, lasty, size, size, START_ARC, END_ARC);
339         }
340         XSetForeground(display, bgc, colors[last_color].pixel);
341         XFillArc(display, window, bgc, newx, newy, size, size, START_ARC, END_ARC);
342         XSync(display, False);
343         smoothen(newx, x, newy, y, size, last_color, colors, display, window, bgc, screen, info);
344     }
345 }
346
347
348 void
349 screenhack (Display *display, Window window)
350 {
351         /*  The following are all X related toys */
352     XGCValues gcv;      /* The structure to hold the GC data */
353     XWindowAttributes xgwa;       /*  A structure to hold window data */
354     GC fgc, bgc;
355     int screen;
356
357     unsigned long int current_time = 0; /* The global int telling the current time */
358     unsigned long int start_time = current_time;
359     struct info  *info = (struct info *)malloc(sizeof(struct info));      /* Dont forget to call free() later */
360     char *xmode_str, *ymode_str; /* holds the current mode for x and y computation */
361         /* pos is the current position x,y -- last_x contains one cell of every x coordinate
362            for every position of every whirly in every line up to 100 whirlies in 100 lines
363            -- lasy_y and last_size hold the same information for y and size respectively */
364     int pos[2], last_x[100][100], last_y[100][100], last_size[100][100];
365     int current_color;
366     int wrap;
367     int xmode, ymode;
368     double modifier;    /* for innie */
369         /* Set up the X toys that I will be using later */
370     screen = DefaultScreen(display);
371     XGetWindowAttributes (display, window, &xgwa);
372     gcv.foreground = get_pixel_resource("foreground", "Foreground", display, xgwa.colormap);
373     fgc = XCreateGC (display, window, GCForeground, &gcv);
374     gcv.foreground = get_pixel_resource("background", "Background", display, xgwa.colormap);
375     bgc = XCreateGC (display, window, GCForeground, &gcv);
376     make_uniform_colormap (display, xgwa.visual, xgwa.colormap, colors, &ncolors, True, &info->writable, True);
377         /* info is a structure holding all the random pieces of information I may want to 
378            pass to my baby functions -- much of it I may never use, but it is nice to
379            have around just in case I want it to make a funky function funkier */
380     info->writable = get_boolean_resource ("cycle", "Boolean");
381     info->xspeed = get_float_resource("xspeed" , "Float");
382     info->yspeed = get_float_resource("yspeed" , "Float");
383     info->xamplitude = get_float_resource("xamplitude", "Float");
384     info->yamplitude = get_float_resource("yamplitude", "Float");
385     info->offset_period = get_float_resource("offset_period", "Float");
386     info->whirlies = get_integer_resource("whirlies", "Integer");
387     info->nlines = get_integer_resource("nlines", "Integer");
388     info->half_width = xgwa.width / 2;
389     info->half_height = xgwa.height / 2;
390     info->speed = get_integer_resource("speed" , "Integer");
391     info->trail = get_integer_resource("trail", "Integer");
392     info->color_modifier = get_integer_resource("color_modifier", "Integer");
393     info->xoffset = get_float_resource("xoffset", "Float");
394     info->yoffset = get_float_resource("yoffset", "Float");
395     xmode_str = get_string_resource("xmode", "Mode");
396     ymode_str = get_string_resource("ymode", "Mode");
397     wrap = get_integer_resource("wrap", "Integer");
398     modifier = 3000.0 + (1500.0 * random() / (RAND_MAX + 1.0));
399     if (! xmode_str) xmode = spin_mode;
400     else if (! strcmp (xmode_str, "spin")) xmode = spin_mode;
401     else if (! strcmp (xmode_str, "funky")) xmode = funky_mode;
402     else if (! strcmp (xmode_str, "linear")) xmode = linear_mode;
403     else if (! strcmp (xmode_str, "fun")) xmode = fun_mode;
404     else if (! strcmp (xmode_str, "innie")) xmode = innie_mode;
405     else if (! strcmp (xmode_str, "lissajous")) xmode = lissajous_mode;
406     else if (! strcmp (xmode_str, "test")) xmode = test_mode;
407     else {
408         xmode = spin_mode;
409     }
410     if (! ymode_str) ymode = spin_mode;
411     else if (! strcmp (ymode_str, "spin")) ymode = spin_mode;
412     else if (! strcmp (ymode_str, "funky")) ymode = funky_mode;
413     else if (! strcmp (ymode_str, "linear")) ymode = linear_mode;
414     else if (! strcmp (ymode_str, "fun")) ymode = fun_mode;
415     else if (! strcmp (ymode_str, "innie")) ymode = innie_mode;
416     else if (! strcmp (ymode_str, "lissajous")) ymode = lissajous_mode;
417     else if (! strcmp (ymode_str, "test")) ymode = test_mode;
418     else {
419         ymode = spin_mode;
420     }
421
422     if (get_integer_resource("start_time", "Integer") == -1)
423         current_time = (unsigned long int)(random());
424     else
425         current_time = get_integer_resource("start_time", "Integer");
426     if (info->whirlies == -1)
427         info->whirlies = 1 + (int)(15.0 * random() / (RAND_MAX + 1.0));
428     if (info->nlines == -1)
429         info->nlines = 1 + (int)(5.0 * random() / (RAND_MAX + 1.0));
430     if (info->color_modifier == -1)
431         info->color_modifier = 1 + (int)(25.0 * random() / (RAND_MAX + 1.0));
432     if (get_integer_resource("explain", "Integer") == 1)
433         explain(mode, info, display, window, fgc);
434     current_color = 1 + (int)((double)NCOLORS * random() / (RAND_MAX + 1.0));
435         /* Now that info is full, lets play! */
436     
437     while (1) {
438         int wcount;  /* wcount is a counter incremented for every whirly take note of
439                         internal_time before you mess with it */
440         int change_time = 4000;
441         if (! strcmp (xmode_str, "change") && ! strcmp (ymode_str, "change")) {
442             if ((current_time - start_time) > change_time) {
443                 start_time = current_time;
444                 xmode = 1 + (int)(4.0 * random() / (RAND_MAX + 1.0));
445                 ymode = 1 + (int)(4.0 * random() / (RAND_MAX + 1.0));
446             }
447         }
448         else if (! strcmp (xmode_str, "change")) {
449             if ((current_time - start_time) > change_time) {
450                 start_time = current_time;
451                 xmode = 1 + (int)(3.5 * random() / (RAND_MAX + 1.0));
452             }
453         }
454         else if (! strcmp (ymode_str, "change")) {
455             if ((current_time - start_time) > change_time) {
456                 start_time = current_time;
457                 ymode = 1 + (int)(3.0 * random() / (RAND_MAX + 1.0));
458                 printf("Changing ymode to %d\n", ymode);
459             }
460         }
461         if (++current_color >= NCOLORS)
462             current_color = 0;
463         for (wcount = 0; wcount < info->whirlies; wcount++) {
464             int lcount; /* lcount is a counter for every line -- take note of the offsets changing */
465             int internal_time = current_time;
466             int color_offset = (current_color + (info->color_modifier * wcount)) % NCOLORS;
467             if (current_time == 0)
468                 internal_time = 0;
469             else
470                     /* I want the distance between whirlies to increase more each whirly */
471                 internal_time = current_time + (10 * wcount) + (wcount * wcount); 
472             switch (xmode) {
473                     /* All these functions expect an int time, the struct info, a pointer to an array of positions, 
474                        and the index that the the function will fill of the array */
475                 case spin_mode:
476                     spin(internal_time, info, pos, 0);
477                     break;
478                 case funky_mode:
479                     funky(internal_time, info, pos, 0);
480                     break;
481                 case circle_mode:
482                     circle(internal_time, info, pos, 0);
483                     break;
484                 case linear_mode:
485                     linear(internal_time, info, pos, 0);
486                     break;
487                 case fun_mode:
488                     fun(internal_time, info, pos, 0);
489                     break;
490                 case test_mode:
491                     test(internal_time, info, pos, 0);
492                     break;
493                 case innie_mode:
494                     innie(internal_time, info, pos, 0, modifier);
495                     break;
496                 case lissajous_mode:
497                     lissajous(internal_time, info, pos, 0);
498                     break;
499                 default:
500                     spin(internal_time, info, pos, 0);
501                     break;
502             }   /* End of the switch for the x position*/
503             switch (ymode) {
504                 case spin_mode:
505                     spin(internal_time, info, pos, 1);
506                     break;
507                 case funky_mode:
508                     funky(internal_time, info, pos, 1);
509                     break;
510                 case circle_mode:
511                     circle(internal_time, info, pos, 1);
512                     break;
513                 case linear_mode:
514                     linear(internal_time, info, pos, 1);
515                     break;
516                 case fun_mode:
517                     fun(internal_time, info, pos, 1);
518                     break;
519                 case test_mode:
520                     test(internal_time, info, pos, 1);
521                     break;
522                 case innie_mode:
523                     innie(internal_time, info, pos, 1, modifier);
524                     break;
525                 case lissajous_mode:
526                     lissajous(internal_time, info, pos, 1);
527                     break;
528                 default:
529                     spin(internal_time, info, pos, 1);
530                     break;
531             } /* End of the switch for the y position*/
532             for (lcount = 0; lcount < info->nlines; lcount++) {
533                 double arg = (double)((internal_time * info->offset_period) / 90.0); 
534                 double line_offset = 20.0 * (double)lcount * sin(arg); 
535                 int size;
536                 size = (int)(15.0 + 5.0 * sin((double)internal_time / 180.0));
537 /* First delete the old circle... */
538                 if (! info->trail) {
539                     XSetForeground(display, bgc, BlackPixel(display, screen));
540                     XFillArc(display, window, bgc, last_x[wcount][lcount], last_y[wcount][lcount], last_size[wcount][lcount], last_size[wcount][lcount], START_ARC, END_ARC);
541                 }
542                     /* Now, lets draw in the new circle */
543                 {  /* Starting new scope for local x_pos and y_pos */
544                     int xpos, ypos;
545                     if (wrap) {
546                         xpos = preen((int)(info->xoffset*line_offset)+pos[0], info->half_width * 2);
547                         ypos = preen((int)(info->yoffset*line_offset)+pos[1], info->half_height * 2);
548                     }
549                     else {
550                         xpos = (int)(info->xoffset*line_offset)+pos[0];
551                         ypos = (int)(info->yoffset*line_offset)+pos[1]; 
552                     }
553                     if (start_time == current_time) {
554                             /* smoothen should move from one mode to another prettily... */
555 /* 
556    smoothen(xpos, last_x[wcount][lcount], ypos, last_y[wcount][lcount], size, color_offset, colors, display, window, bgc, screen, info);
557  */
558                     }
559                     last_x[wcount][lcount] = xpos;
560                     last_y[wcount][lcount] = ypos;
561                     last_size[wcount][lcount] = size;
562                     XSetForeground(display, bgc, colors[color_offset].pixel);
563                     XFillArc(display, window, bgc, xpos, ypos, size, size, START_ARC, END_ARC);
564                 } /* End of my temporary scope for xpos and ypos */
565             }  /* End of the for each line in nlines */
566         } /* End of the for each whirly in whirlies */
567         XSync(display, False);
568         if (current_time == FULL_CYCLE)
569             current_time = 1;
570         else
571             current_time = current_time + info->speed;
572         screenhack_handle_events(display);
573         if (!info->writable)
574             usleep(10000);
575     }   /*  End the while loop! */
576     free(info);
577 }