1 /* Whirlygig -- an experiment in X programming
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
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
18 #include "screenhack.h"
20 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
22 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
25 #define FULL_CYCLE 429496729
30 /* Bool writable; / * Is the screen writable */
31 double xspeed; /* A factor to modify the horizontal movement */
32 double yspeed; /* A factor to modify vertical movement */
35 int whirlies; /* How many whirlies per line do you want? */
36 int nlines; /* How many lines of whirlies do you want? */
37 int half_width; /* 1/2 the width of the screen */
49 spin_mode, funky_mode, circle_mode, linear_mode, test_mode, fun_mode, innie_mode, lissajous_mode
56 XGCValues gcv; /* The structure to hold the GC data */
57 XWindowAttributes xgwa; /* A structure to hold window data */
58 Pixmap b, ba; /* double-buffer to reduce flicker */
59 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
62 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
68 unsigned long int current_time; /* The global int telling the current time */
69 unsigned long int start_time;
71 char *xmode_str, *ymode_str; /* holds the current mode for x and y computation */
73 /* pos is the current position x,y -- last_x contains one cell of
74 every x coordinate for every position of every whirly in every
75 line up to 100 whirlies in 100 lines -- lasy_y and last_size hold
76 the same information for y and size respectively */
78 int pos[2], last_x[100][100], last_y[100][100], last_size[100][100];
82 double modifier; /* for innie */
84 XColor colors[NCOLORS];
89 static void draw_explain_string(struct state *, int, int, Display *, Window, GC);
90 static void spin(struct state *, unsigned long int, struct info *, int *, int);
91 static void funky(struct state *, unsigned long int, struct info *, int *, int);
92 static void circle(struct state *, unsigned long int, struct info *, int *, int);
93 static void fun(struct state *, unsigned long int, struct info *, int *, int);
94 static void linear(struct state *, unsigned long int, struct info *, int *, int);
95 static void lissajous(struct state *, unsigned long int, struct info *, int *, int);
96 static void test(struct state *, unsigned long int, struct info *, int *, int);
97 static void innie(struct state *, unsigned long int, struct info *, int *, int, double);
101 static const char spin_explanation[] =
102 "Spin mode is a simple sin/cos with every argument modified";
104 static const char funky_explanation[] =
105 "Funky mode is me goofing off.";
107 static const char circle_explanation[] =
108 "Circle mode graphs the x and y positions as you trace the edge of a circle over time.";
110 static const char linear_explanation[] =
111 "Linear mode draws a straight line";
113 static const char test_explanation[] =
114 "Test mode is a mode that I play around with ideas in.";
116 static const char fun_explanation[] =
117 "Fun mode is the coolest.";
119 static const char innie_explanation[] =
120 "Innie mode does something or other. Looks cool, though.";
122 static const char lissajous_explanation[] =
123 "Lissajous mode draws a slightly modified lissajous curve";
126 draw_explain_string(struct state *st, int mode, int offset, Display *dpy, Window window, GC fgc)
130 XDrawString(st->dpy, st->window, st->fgc, 50, offset,
131 (char*) spin_explanation, strlen(spin_explanation));
134 XDrawString(st->dpy, st->window, st->fgc, 50, offset,
135 (char*) funky_explanation, strlen(funky_explanation));
138 XDrawString(st->dpy, st->window, st->fgc, 50, offset,
139 (char*) circle_explanation, strlen(circle_explanation));
142 XDrawString(st->dpy, st->window, st->fgc, 50, offset,
143 (char*) linear_explanation, strlen(linear_explanation));
146 XDrawString(st->dpy, st->window, st->fgc, 50, offset,
147 (char*) test_explanation, strlen(test_explanation));
150 XDrawString(st->dpy, st->window, st->fgc, 50, offset,
151 (char*) fun_explanation, strlen(fun_explanation));
154 XDrawString(st->dpy, st->window, st->fgc, 50, offset,
155 (char*) innie_explanation, strlen(innie_explanation));
158 XDrawString(st->dpy, st->window, st->fgc, 50, offset,
159 (char*) lissajous_explanation, strlen(linear_explanation));
164 funky(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index)
166 double new_time = ((the_time % 360 ) / 180.0) * M_PI;
168 double time_modifier = cos(new_time / 180.0);
169 double the_cos = cos((new_time * (double)st->info->xspeed) + (time_modifier * 80.0));
170 double dist_mod_x = cos(new_time) * (st->info->half_width - 50);
171 st->pos[index]= st->info->xamplitude * (the_cos * dist_mod_x) + st->info->half_width;
174 double new_time = ((the_time % 360 ) / 180.0) * M_PI;
175 double time_modifier = sin(new_time / 180.0);
176 double the_sin = sin((new_time * (double)st->info->yspeed) + (time_modifier * 80.0));
177 double dist_mod_y = sin(new_time) * (st->info->half_height - 50);
178 st->pos[index] = st->info->yamplitude * (the_sin * dist_mod_y) + st->info->half_height;
183 innie(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index, double modifier)
185 double frequency = 2000000.0 + (st->modifier * cos(((double)the_time / 100.0)));
186 double arg = (double)the_time / frequency;
187 double amplitude = 200.0 * cos(arg);
188 double fun = 150.0 * cos((double)the_time / 2000.0);
189 int vert_mod, horiz_mod;
191 horiz_mod = (int)(fun * cos((double)the_time / 100.0)) + st->info->half_width;
192 st->pos[index] = (amplitude * cos((double)the_time / 100.0 * st->info->xspeed)) + horiz_mod;
195 vert_mod = (int)(fun * sin((double)the_time / 100.0)) + st->info->half_height;
196 st->pos[index] = (amplitude * sin((double)the_time / 100.0 * st->info->yspeed)) + vert_mod;
201 lissajous(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index)
203 /* This is a pretty standard lissajous curve
206 The n and c modifiers are cyclic as well, however... */
208 double time = (double)the_time / 100.0;
209 double fun = 15.0 * cos((double)the_time / 800.0);
210 double weird = cos((time / 1100000.0) / 1000.0);
213 result = st->info->xamplitude * 200.0 * sin((weird * time) + fun) + st->info->half_width;
216 result = st->info->yamplitude * 200.0 * sin(time) + st->info->half_height;
218 st->pos[index] = result;
222 circle(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index)
226 result = st->info->xamplitude * (cos((double)the_time / 100.0 * st->info->xspeed) * (st->info->half_width / 2)) + st->info->half_width;
229 result = st->info->yamplitude * (sin((double)the_time / 100.0 * st->info->yspeed) * (st->info->half_height / 2)) + st->info->half_height;
231 st->pos[index] = result;
236 mod(unsigned long int the_time, struct info *info, int pos[], int index)
239 int max = st->info->half_width;
240 if ((the_time % (max * 2)) < max)
241 amplitude = max - ((the_time % (max * 2)) - max);
243 amplitude = the_time % (max * 2);
244 amplitude = amplitude - max;
249 spin(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index)
251 double funky = (((the_time % 360) * 1.0) / 180.0) * M_PI;
253 double the_cos = cos((double)the_time / (180.0 * st->info->xspeed));
254 double dist_mod_x = cos((double)funky) * (st->info->half_width - 50);
255 st->pos[index] = st->info->xamplitude * (the_cos * dist_mod_x) + st->info->half_width;
258 double the_sin = sin((double)the_time / (180.0 * st->info->yspeed));
259 double dist_mod_y = sin((double)funky) * (st->info->half_height - 50);
260 st->pos[index] = st->info->yamplitude * (the_sin * dist_mod_y) + st->info->half_height;
265 fun(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index)
268 int max = st->info->half_width;
269 if ((the_time % (max * 2)) < max)
270 amplitude = max - ((the_time % (max * 2)) - max);
272 amplitude = the_time % (max * 2);
273 amplitude = amplitude - max;
275 st->pos[index] = (amplitude * cos((double)the_time / 100.0 * st->info->xspeed)) + st->info->half_width;
278 st->pos[index] = (amplitude * sin((double)the_time / 100.0 * st->info->yspeed)) + st->info->half_height;
283 linear(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index)
285 if (index == 0) /* Calculate for the x axis */
286 st->pos[index] = ((the_time / 2) % (st->info->half_width * 2));
288 st->pos[index] = ((the_time / 2) % (st->info->half_height * 2));
292 test(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index)
295 st->pos[index] = st->info->xamplitude * (cos((double)the_time / 100.0 * st->info->xspeed) * (st->info->half_width / 2)) + st->info->half_width;
298 st->pos[index] = st->info->yamplitude * (sin((double)the_time / 100.0 * st->info->yspeed) * (st->info->half_height / 2)) + st->info->half_height;
302 static int preen(int current, int max) {
312 smoothen(struct state *st, int x, int lastx, int y, int lasty, int size, int last_color, XColor *colors, Display *dpy, Window window, GC bgc, int screen, struct info *info)
314 double xdistance = abs((double)x-(double)lastx);
315 double ydistance = abs((double)y-(double)lasty);
316 double distance = sqrt(((xdistance * xdistance) + (ydistance * ydistance)) );
317 double slope = (((double)y-(double)lasty) / ((double)x-(double)lastx));
318 printf("Starting smoothen with values: %f, %f, %f, %f\n", xdistance, ydistance, distance, slope);
319 if (distance > 2.0) {
320 int newx = (int)((xdistance / distance) * slope);
321 int newy = (int)((ydistance / distance) * slope);
322 if (! st->info->trail) {
323 XSetForeground(st->dpy, st->bgc, BlackPixel(st->dpy, st->screen));
324 XFillArc(st->dpy, st->window, st->bgc, lastx, lasty, size, size, START_ARC, END_ARC);
326 XSetForeground(st->dpy, st->bgc, st->colors[last_color].pixel);
327 XFillArc(st->dpy, st->window, st->bgc, newx, newy, size, size, START_ARC, END_ARC);
328 smoothen(st, newx, x, newy, y, size, last_color, st->colors, st->dpy, st->window, st->bgc, st->screen, st->info);
335 whirlygig_init (Display *dpy, Window window)
337 struct state *st = (struct state *) calloc (1, sizeof(*st));
341 st->ncolors = NCOLORS;
343 st->dbuf = get_boolean_resource (st->dpy, "doubleBuffer", "Boolean");
345 # ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */
349 st->start_time = st->current_time;
350 st->info = (struct info *)malloc(sizeof(struct info));
352 st->screen = DefaultScreen(st->dpy);
353 XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
356 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
357 if (get_boolean_resource(st->dpy,"useDBE","Boolean"))
359 st->dbeclear_p = get_boolean_resource (st->dpy, "useDBEClear",
362 st->b = xdbe_get_backbuffer (st->dpy, st->window, XdbeBackground);
364 st->b = xdbe_get_backbuffer (st->dpy, st->window, XdbeUndefined);
367 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
371 st->ba = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height,st->xgwa.depth);
380 st->gcv.foreground = get_pixel_resource(st->dpy, st->xgwa.colormap, "foreground", "Foreground");
381 st->fgc = XCreateGC (st->dpy, st->b, GCForeground, &st->gcv);
382 st->gcv.foreground = get_pixel_resource(st->dpy, st->xgwa.colormap, "background", "Background");
383 st->bgc = XCreateGC (st->dpy, st->b, GCForeground, &st->gcv);
385 #ifdef HAVE_COCOA /* #### should turn off double-buffering instead */
386 jwxyz_XSetAntiAliasing (dpy, st->fgc, False);
387 jwxyz_XSetAntiAliasing (dpy, st->bgc, False);
391 Bool writable_p = False;
392 make_uniform_colormap (st->dpy, st->xgwa.visual, st->xgwa.colormap, st->colors, &st->ncolors, True, &writable_p, True);
395 if (st->ba) XFillRectangle (st->dpy, st->ba, st->bgc, 0, 0, st->xgwa.width, st->xgwa.height);
397 /* info is a structure holding all the random pieces of information I may want to
398 pass to my baby functions -- much of it I may never use, but it is nice to
399 have around just in case I want it to make a funky function funkier */
400 /* info->writable = get_boolean_resource (dpy, "cycle", "Boolean"); */
401 st->info->xspeed = get_float_resource(st->dpy, "xspeed" , "Float");
402 st->info->yspeed = get_float_resource(st->dpy, "yspeed" , "Float");
403 st->info->xamplitude = get_float_resource(st->dpy, "xamplitude", "Float");
404 st->info->yamplitude = get_float_resource(st->dpy, "yamplitude", "Float");
405 st->info->offset_period = get_float_resource(st->dpy, "offset_period", "Float");
406 st->info->whirlies = get_integer_resource(st->dpy, "whirlies", "Integer");
407 st->info->nlines = get_integer_resource(st->dpy, "nlines", "Integer");
408 st->info->half_width = st->xgwa.width / 2;
409 st->info->half_height = st->xgwa.height / 2;
410 st->info->speed = get_integer_resource(st->dpy, "speed" , "Integer");
411 st->info->trail = get_boolean_resource(st->dpy, "trail", "Integer");
412 st->info->color_modifier = get_integer_resource(st->dpy, "color_modifier", "Integer");
413 st->info->xoffset = get_float_resource(st->dpy, "xoffset", "Float");
414 st->info->yoffset = get_float_resource(st->dpy, "yoffset", "Float");
415 st->xmode_str = get_string_resource(st->dpy, "xmode", "Mode");
416 st->ymode_str = get_string_resource(st->dpy, "ymode", "Mode");
417 st->wrap = get_boolean_resource(st->dpy, "wrap", "Boolean");
418 st->modifier = 3000.0 + frand(1500.0);
419 if (! st->xmode_str) st->xmode = spin_mode;
420 else if (! strcmp (st->xmode_str, "spin")) st->xmode = spin_mode;
421 else if (! strcmp (st->xmode_str, "funky")) st->xmode = funky_mode;
422 else if (! strcmp (st->xmode_str, "circle")) st->xmode = circle_mode;
423 else if (! strcmp (st->xmode_str, "linear")) st->xmode = linear_mode;
424 else if (! strcmp (st->xmode_str, "test")) st->xmode = test_mode;
425 else if (! strcmp (st->xmode_str, "fun")) st->xmode = fun_mode;
426 else if (! strcmp (st->xmode_str, "innie")) st->xmode = innie_mode;
427 else if (! strcmp (st->xmode_str, "lissajous")) st->xmode = lissajous_mode;
429 st->xmode = random() % (int) lissajous_mode;
431 if (! st->ymode_str) st->ymode = spin_mode;
432 else if (! strcmp (st->ymode_str, "spin")) st->ymode = spin_mode;
433 else if (! strcmp (st->ymode_str, "funky")) st->ymode = funky_mode;
434 else if (! strcmp (st->ymode_str, "circle")) st->ymode = circle_mode;
435 else if (! strcmp (st->ymode_str, "linear")) st->ymode = linear_mode;
436 else if (! strcmp (st->ymode_str, "test")) st->ymode = test_mode;
437 else if (! strcmp (st->ymode_str, "fun")) st->ymode = fun_mode;
438 else if (! strcmp (st->ymode_str, "innie")) st->ymode = innie_mode;
439 else if (! strcmp (st->ymode_str, "lissajous")) st->ymode = lissajous_mode;
441 st->ymode = random() % (int) lissajous_mode;
444 if (get_integer_resource(st->dpy, "start_time", "Integer") == -1)
445 st->current_time = (unsigned long int)(random());
447 st->current_time = get_integer_resource(st->dpy, "start_time", "Integer");
448 if (st->info->whirlies == -1)
449 st->info->whirlies = 1 + (random() % 15);
450 if (st->info->nlines == -1)
451 st->info->nlines = 1 + (random() % 5);
452 if (st->info->color_modifier == -1)
453 st->info->color_modifier = 1 + (random() % 25);
454 if (get_boolean_resource(st->dpy, "explain", "Integer"))
456 st->current_color = 1 + (random() % NCOLORS);
462 whirlygig_draw (Display *dpy, Window window, void *closure)
464 struct state *st = (struct state *) closure;
465 int wcount; /* wcount is a counter incremented for every whirly take note of
466 internal_time before you mess with it */
467 int change_time = 4000;
469 if (st->explaining == 1) {
470 XClearWindow (st->dpy, st->window);
471 draw_explain_string(st, st->xmode, st->info->half_height-100,
472 st->dpy, st->window, st->fgc);
475 } else if (st->explaining == 2) {
476 XClearWindow (st->dpy, st->window);
480 if (! strcmp (st->xmode_str, "change") && ! strcmp (st->ymode_str, "change")) {
481 if ((st->current_time - st->start_time) > change_time) {
482 st->start_time = st->current_time;
483 st->xmode = 1 + (random() % 4);
484 st->ymode = 1 + (random() % 4);
487 else if (! strcmp (st->xmode_str, "change")) {
488 if ((st->current_time - st->start_time) > change_time) {
489 st->start_time = st->current_time;
490 st->xmode = 1 + (random() % 4);
493 else if (! strcmp (st->ymode_str, "change")) {
494 if ((st->current_time - st->start_time) > change_time) {
495 st->start_time = st->current_time;
496 st->ymode = 1 + (random() % 3);
497 printf("Changing ymode to %d\n", st->ymode);
500 if (++st->current_color >= NCOLORS)
501 st->current_color = 0;
502 for (wcount = 0; wcount < st->info->whirlies; wcount++) {
503 int lcount; /* lcount is a counter for every line -- take note of the offsets changing */
504 int internal_time = st->current_time;
505 int color_offset = (st->current_color + (st->info->color_modifier * wcount)) % NCOLORS;
506 if (st->current_time == 0)
509 /* I want the distance between whirlies to increase more each whirly */
510 internal_time = st->current_time + (10 * wcount) + (wcount * wcount);
512 /* All these functions expect an int time, the struct info,
513 a pointer to an array of positions, and the index that the
514 the function will fill of the array */
516 spin(st, internal_time, st->info, st->pos, 0);
519 funky(st, internal_time, st->info, st->pos, 0);
522 circle(st, internal_time, st->info, st->pos, 0);
525 linear(st, internal_time, st->info, st->pos, 0);
528 fun(st, internal_time, st->info, st->pos, 0);
531 test(st, internal_time, st->info, st->pos, 0);
534 innie(st, internal_time, st->info, st->pos, 0, st->modifier);
537 lissajous(st, internal_time, st->info, st->pos, 0);
540 spin(st, internal_time, st->info, st->pos, 0);
542 } /* End of the switch for the x position*/
545 spin(st, internal_time, st->info, st->pos, 1);
548 funky(st, internal_time, st->info, st->pos, 1);
551 circle(st, internal_time, st->info, st->pos, 1);
554 linear(st, internal_time, st->info, st->pos, 1);
557 fun(st, internal_time, st->info, st->pos, 1);
560 test(st, internal_time, st->info, st->pos, 1);
563 innie(st, internal_time, st->info, st->pos, 1, st->modifier);
566 lissajous(st, internal_time, st->info, st->pos, 1);
569 spin(st, internal_time, st->info, st->pos, 1);
571 } /* End of the switch for the y position*/
572 for (lcount = 0; lcount < st->info->nlines; lcount++) {
573 double arg = (double)((internal_time * st->info->offset_period) / 90.0);
574 double line_offset = 20.0 * (double)lcount * sin(arg);
576 size = (int)(15.0 + 5.0 * sin((double)internal_time / 180.0));
577 /* First delete the old circle... */
579 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
580 && ( !st->dbeclear_p || !st->backb)
581 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
583 XSetForeground(st->dpy, st->bgc, BlackPixel(st->dpy, st->screen));
584 XFillArc(st->dpy, st->b, st->bgc, st->last_x[wcount][lcount], st->last_y[wcount][lcount], st->last_size[wcount][lcount], st->last_size[wcount][lcount], START_ARC, END_ARC);
586 /* Now, lets draw in the new circle */
587 { /* Starting new scope for local x_pos and y_pos */
590 xpos = preen((int)(st->info->xoffset*line_offset)+st->pos[0], st->info->half_width * 2);
591 ypos = preen((int)(st->info->yoffset*line_offset)+st->pos[1], st->info->half_height * 2);
594 xpos = (int)(st->info->xoffset*line_offset)+st->pos[0];
595 ypos = (int)(st->info->yoffset*line_offset)+st->pos[1];
597 if (st->start_time == st->current_time) {
598 /* smoothen should move from one mode to another prettily... */
600 /* Note: smoothen has not been modified to take the double
601 buffering code into account, and needs to be hacked on
605 smoothen(xpos, last_x[wcount][lcount], ypos, last_y[wcount][lcount], size, color_offset, colors, dpy, window, bgc, screen, info);
608 st->last_x[wcount][lcount] = xpos;
609 st->last_y[wcount][lcount] = ypos;
610 st->last_size[wcount][lcount] = size;
611 XSetForeground(st->dpy, st->bgc, st->colors[color_offset].pixel);
612 XFillArc(st->dpy, st->b, st->bgc, xpos, ypos, size, size, START_ARC, END_ARC);
613 } /* End of my temporary scope for xpos and ypos */
614 } /* End of the for each line in nlines */
615 } /* End of the for each whirly in whirlies */
618 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
621 XdbeSwapInfo info[1];
622 info[0].swap_window = st->window;
623 info[0].swap_action = (st->dbeclear_p ? XdbeBackground : XdbeUndefined);
624 XdbeSwapBuffers (st->dpy, info, 1);
627 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
630 XCopyArea (st->dpy, st->b, st->window, st->bgc, 0, 0,
631 st->xgwa.width, st->xgwa.height, 0, 0);
634 if (st->current_time == FULL_CYCLE)
635 st->current_time = 1;
637 st->current_time = st->current_time + st->info->speed;
644 whirlygig_reshape (Display *dpy, Window window, void *closure,
645 unsigned int w, unsigned int h)
650 whirlygig_event (Display *dpy, Window window, void *closure, XEvent *event)
656 whirlygig_free (Display *dpy, Window window, void *closure)
661 static const char *whirlygig_defaults [] = {
662 ".background: black",
663 ".foreground: white",
675 "*color_modifier: -1",
682 "*doubleBuffer: True",
683 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
684 "*useDBEClear: True",
686 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
690 static XrmOptionDescRec whirlygig_options [] = {
691 { "-xspeed", ".xspeed", XrmoptionSepArg, 0 },
692 /* xspeed is a modifier of the argument to cos -- changing it thus
693 changes the frequency of cos */
694 { "-yspeed", ".yspeed", XrmoptionSepArg, 0 },
695 /* Similiarly, yspeed changes the frequency of sin */
696 { "-xamplitude", ".xamplitude", XrmoptionSepArg, 0 },
697 /* A factor by which to increase/decrease the amplitude of the sin */
698 { "-yamplitude", ".yamplitude", XrmoptionSepArg, 0 },
699 /* A factor by which to increase/decrease the amplitude of the cos */
700 { "-whirlies", ".whirlies",XrmoptionSepArg, 0 },
701 /* whirlies defines the number of circles to draw per line */
702 { "-nlines", ".nlines",XrmoptionSepArg, 0 },
703 /* nlines is the number of lines of whirlies to draw */
704 { "-xmode", ".xmode", XrmoptionSepArg, 0 },
705 /* There are a few different modes that I have written -- each mode
706 is in theory a different experiment with the possible modifiers to sin/cos */
707 { "-ymode", ".ymode", XrmoptionSepArg, 0 },
708 { "-speed", ".speed", XrmoptionSepArg, 0 },
709 /* This will modify how often it should draw, changing it will probably suck */
710 { "-trail", ".trail", XrmoptionNoArg, "True" },
711 /* Control whether or not you want the old circles to be erased */
712 { "-color_modifier", ".color_modifier", XrmoptionSepArg, 0 },
713 /* How many colors away from the current should the next whirly be? */
714 { "-start_time", ".start_time", XrmoptionSepArg, 0 },
715 /* Specify exactly at what time to start graphing... */
716 { "-xoffset", ".xoffset", XrmoptionSepArg, 0 },
717 /* Tell the whirlies to be offset by this factor of a sin */
718 { "-yoffset", ".yoffset", XrmoptionSepArg, 0 },
719 /* Tell the whirlies to be offset by this factor of a cos */
720 { "-offset_period", ".offset_period", XrmoptionSepArg, 0 },
721 /* Change the period of an offset cycle */
722 { "-explain", ".explain", XrmoptionNoArg, "True" },
723 /* Specify whether or not to print an explanation of the function used. */
724 { "-wrap", ".wrap", XrmoptionNoArg, "True" },
725 { "-no-wrap", ".wrap", XrmoptionNoArg, "False" },
726 /* Specify if you want whirlies which are out of the boundary of the screen to be
727 wrapped around to the other side */
728 { "-db", ".doubleBuffer", XrmoptionNoArg, "True" },
729 { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" },
733 XSCREENSAVER_MODULE ("Whirlygig", whirlygig)