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