X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?p=xscreensaver;a=blobdiff_plain;f=hacks%2Fwhirlygig.c;h=d4205bf8b141c3165b2b0ff028ec8e5dbae93900;hp=118d7dd961c1a49a10513dd1d93f00c4959c9307;hb=49f5b54f312fe4ac2e9bc47581a72451bd0e8439;hpb=ccb7f4903325f92555a9722bba74b58346654ba0 diff --git a/hacks/whirlygig.c b/hacks/whirlygig.c index 118d7dd9..d4205bf8 100644 --- a/hacks/whirlygig.c +++ b/hacks/whirlygig.c @@ -12,6 +12,7 @@ * by the beauty of the shapes one receives when playing with sine waves * Here is a little experiment to show that beauty is simple */ + #include #include #include "screenhack.h" @@ -41,98 +42,62 @@ struct info { double xoffset; double yoffset; double offset_period; - int wrap; + Bool wrap; }; enum object_mode { spin_mode, funky_mode, circle_mode, linear_mode, test_mode, fun_mode, innie_mode, lissajous_mode -} mode; - -static void explain(int, int, struct info *, Display *, Window, GC); -static void draw_explain_string(int, int, Display *, Window, GC); -static void spin(unsigned long int, struct info *, int *, int); -static void funky(unsigned long int, struct info *, int *, int); -static void circle(unsigned long int, struct info *, int *, int); -static void fun(unsigned long int, struct info *, int *, int); -static void linear(unsigned long int, struct info *, int *, int); -static void lissajous(unsigned long int, struct info *, int *, int); -static void test(unsigned long int, struct info *, int *, int); -static void innie(unsigned long int, struct info *, int *, int, double); - -XColor colors[NCOLORS]; -int ncolors = NCOLORS; -char *progclass = "Whirlygig"; - -char *defaults [] = { - ".background: black", - ".foreground: white", - "*xspeed: 1.0", - "*yspeed: 1.0", - "*xamplitude: 1.0", - "*yamplitude: 1.0", - "*whirlies: -1", - "*nlines: -1", - "*xmode: change", - "*ymode: change", - "*speed: 1", - "*trail: 0", - "*color_modifier: -1", - "*start_time: -1", - "*explain: False", - "*xoffset: 1.0", - "*yoffset: 1.0", - "*offset_period: 1", - "*wrap: 0", - "*doubleBuffer: True", +}; + +struct state { + Display *dpy; + Window window; + + XGCValues gcv; /* The structure to hold the GC data */ + XWindowAttributes xgwa; /* A structure to hold window data */ + Pixmap b, ba; /* double-buffer to reduce flicker */ #ifdef HAVE_DOUBLE_BUFFER_EXTENSION - "*useDBE: True", - "*useDBEClear: True", + Bool dbeclear_p; + XdbeBackBuffer backb; #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ - 0 -}; -XrmOptionDescRec options [] = { - { "-xspeed", ".xspeed", XrmoptionSepArg, 0 }, - /* xspeed is a modifier of the argument to cos -- changing it thus - changes the frequency of cos */ - { "-yspeed", ".yspeed", XrmoptionSepArg, 0 }, - /* Similiarly, yspeed changes the frequency of sin */ - { "-xamplitude", ".xamplitude", XrmoptionSepArg, 0 }, - /* A factor by which to increase/decrease the amplitude of the sin */ - { "-yamplitude", ".yamplitude", XrmoptionSepArg, 0 }, - /* A factor by which to increase/decrease the amplitude of the cos */ - { "-whirlies", ".whirlies",XrmoptionSepArg, 0 }, - /* whirlies defines the number of circles to draw per line */ - { "-nlines", ".nlines",XrmoptionSepArg, 0 }, - /* nlines is the number of lines of whirlies to draw */ - { "-xmode", ".xmode", XrmoptionSepArg, 0 }, - /* There are a few different modes that I have written -- each mode - is in theory a different experiment with the possible modifiers to sin/cos */ - { "-ymode", ".ymode", XrmoptionSepArg, 0 }, - { "-speed", ".speed", XrmoptionSepArg, 0 }, - /* This will modify how often it should draw, changing it will probably suck */ - { "-trail", ".trail", XrmoptionSepArg, 0 }, - /* Control whether or not you want the old circles to be erased */ - { "-color_modifier", ".color_modifier", XrmoptionSepArg, 0 }, - /* How many colors away from the current should the next whirly be? */ - { "-start_time", ".start_time", XrmoptionSepArg, 0 }, - /* Specify exactly at what time to start graphing... */ - { "-xoffset", ".xoffset", XrmoptionSepArg, 0 }, - /* Tell the whirlies to be offset by this factor of a sin */ - { "-yoffset", ".yoffset", XrmoptionSepArg, 0 }, - /* Tell the whirlies to be offset by this factor of a cos */ - { "-offset_period", ".offset_period", XrmoptionSepArg, 0 }, - /* Change the period of an offset cycle */ - { "-explain", ".explain", XrmoptionNoArg, "True" }, - /* Specify whether or not to print an explanation of the function used. */ - { "-wrap", ".wrap", XrmoptionSepArg, 0 }, - /* Specify if you want whirlies which are out of the boundary of the screen to be - wrapped around to the other side */ - { "-db", ".doubleBuffer", XrmoptionNoArg, "True" }, - { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" }, - { 0, 0, 0, 0 } + GC fgc, bgc; + int screen; + Bool dbuf; + + unsigned long int current_time; /* The global int telling the current time */ + unsigned long int start_time; + struct info *info; + char *xmode_str, *ymode_str; /* holds the current mode for x and y computation */ + + /* pos is the current position x,y -- last_x contains one cell of + every x coordinate for every position of every whirly in every + line up to 100 whirlies in 100 lines -- lasy_y and last_size hold + the same information for y and size respectively */ + + int pos[2], last_x[100][100], last_y[100][100], last_size[100][100]; + int current_color; + Bool wrap; + int xmode, ymode; + double modifier; /* for innie */ + + XColor colors[NCOLORS]; + int ncolors; + int explaining; }; +static void draw_explain_string(struct state *, int, int, Display *, Window, GC); +static void spin(struct state *, unsigned long int, struct info *, int *, int); +static void funky(struct state *, unsigned long int, struct info *, int *, int); +static void circle(struct state *, unsigned long int, struct info *, int *, int); +static void fun(struct state *, unsigned long int, struct info *, int *, int); +static void linear(struct state *, unsigned long int, struct info *, int *, int); +static void lissajous(struct state *, unsigned long int, struct info *, int *, int); +static void test(struct state *, unsigned long int, struct info *, int *, int); +static void innie(struct state *, unsigned long int, struct info *, int *, int, double); + + + static const char spin_explanation[] = "Spin mode is a simple sin/cos with every argument modified"; @@ -158,93 +123,82 @@ static const char lissajous_explanation[] = "Lissajous mode draws a slightly modified lissajous curve"; static void -explain(int xmode, int ymode, struct info *info, Display *display, Window window, GC fgc) -{ - XClearWindow(display, window); - draw_explain_string(xmode, info->half_height-100, display, window, fgc); -/* draw_explain_string(ymode, info->half_height-50, display, window, fgc);*/ - XSync(display, False); - sleep(3); - XClearWindow(display, window); -} - -static void -draw_explain_string(int mode, int offset, Display *display, Window window, GC fgc) +draw_explain_string(struct state *st, int mode, int offset, Display *dpy, Window window, GC fgc) { switch(mode) { case spin_mode: - XDrawString(display, window, fgc, 50, offset, spin_explanation, - strlen(spin_explanation)); + XDrawString(st->dpy, st->window, st->fgc, 50, offset, + (char*) spin_explanation, strlen(spin_explanation)); break; case funky_mode: - XDrawString(display, window, fgc, 50, offset, funky_explanation, - strlen(funky_explanation)); + XDrawString(st->dpy, st->window, st->fgc, 50, offset, + (char*) funky_explanation, strlen(funky_explanation)); break; case circle_mode: - XDrawString(display, window, fgc, 50, offset, circle_explanation, - strlen(circle_explanation)); + XDrawString(st->dpy, st->window, st->fgc, 50, offset, + (char*) circle_explanation, strlen(circle_explanation)); break; case linear_mode: - XDrawString(display, window, fgc, 50, offset, linear_explanation, - strlen(linear_explanation)); + XDrawString(st->dpy, st->window, st->fgc, 50, offset, + (char*) linear_explanation, strlen(linear_explanation)); break; case test_mode: - XDrawString(display, window, fgc, 50, offset, test_explanation, - strlen(test_explanation)); + XDrawString(st->dpy, st->window, st->fgc, 50, offset, + (char*) test_explanation, strlen(test_explanation)); break; case fun_mode: - XDrawString(display, window, fgc, 50, offset, fun_explanation, - strlen(fun_explanation)); + XDrawString(st->dpy, st->window, st->fgc, 50, offset, + (char*) fun_explanation, strlen(fun_explanation)); break; case innie_mode: - XDrawString(display, window, fgc, 50, offset, innie_explanation, - strlen(innie_explanation)); + XDrawString(st->dpy, st->window, st->fgc, 50, offset, + (char*) innie_explanation, strlen(innie_explanation)); break; case lissajous_mode: - XDrawString(display, window, fgc, 50, offset, lissajous_explanation, - strlen(linear_explanation)); + XDrawString(st->dpy, st->window, st->fgc, 50, offset, + (char*) lissajous_explanation, strlen(linear_explanation)); } } static void -funky(unsigned long int the_time, struct info *info, int pos[], int index) +funky(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index) { double new_time = ((the_time % 360 ) / 180.0) * M_PI; if (index == 0) { double time_modifier = cos(new_time / 180.0); - double the_cos = cos((new_time * (double)info->xspeed) + (time_modifier * 80.0)); - double dist_mod_x = cos(new_time) * (info->half_width - 50); - pos[index]= info->xamplitude * (the_cos * dist_mod_x) + info->half_width; + double the_cos = cos((new_time * (double)st->info->xspeed) + (time_modifier * 80.0)); + double dist_mod_x = cos(new_time) * (st->info->half_width - 50); + st->pos[index]= st->info->xamplitude * (the_cos * dist_mod_x) + st->info->half_width; } else { double new_time = ((the_time % 360 ) / 180.0) * M_PI; double time_modifier = sin(new_time / 180.0); - double the_sin = sin((new_time * (double)info->yspeed) + (time_modifier * 80.0)); - double dist_mod_y = sin(new_time) * (info->half_height - 50); - pos[index] = info->yamplitude * (the_sin * dist_mod_y) + info->half_height; + double the_sin = sin((new_time * (double)st->info->yspeed) + (time_modifier * 80.0)); + double dist_mod_y = sin(new_time) * (st->info->half_height - 50); + st->pos[index] = st->info->yamplitude * (the_sin * dist_mod_y) + st->info->half_height; } } static void -innie(unsigned long int the_time, struct info *info, int pos[], int index, double modifier) +innie(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index, double modifier) { - double frequency = 2000000.0 + (modifier * cos(((double)the_time / 100.0))); + double frequency = 2000000.0 + (st->modifier * cos(((double)the_time / 100.0))); double arg = (double)the_time / frequency; double amplitude = 200.0 * cos(arg); double fun = 150.0 * cos((double)the_time / 2000.0); int vert_mod, horiz_mod; if (index == 0) { - horiz_mod = (int)(fun * cos((double)the_time / 100.0)) + info->half_width; - pos[index] = (amplitude * cos((double)the_time / 100.0 * info->xspeed)) + horiz_mod; + horiz_mod = (int)(fun * cos((double)the_time / 100.0)) + st->info->half_width; + st->pos[index] = (amplitude * cos((double)the_time / 100.0 * st->info->xspeed)) + horiz_mod; } else { - vert_mod = (int)(fun * sin((double)the_time / 100.0)) + info->half_height; - pos[index] = (amplitude * sin((double)the_time / 100.0 * info->yspeed)) + vert_mod; + vert_mod = (int)(fun * sin((double)the_time / 100.0)) + st->info->half_height; + st->pos[index] = (amplitude * sin((double)the_time / 100.0 * st->info->yspeed)) + vert_mod; } } static void -lissajous(unsigned long int the_time, struct info *info, int pos[], int index) +lissajous(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index) { /* This is a pretty standard lissajous curve x = a sin(nt + c) @@ -256,25 +210,25 @@ lissajous(unsigned long int the_time, struct info *info, int pos[], int index) double weird = cos((time / 1100000.0) / 1000.0); if (index == 0) { - result = info->xamplitude * 200.0 * sin((weird * time) + fun) + info->half_width; + result = st->info->xamplitude * 200.0 * sin((weird * time) + fun) + st->info->half_width; } else { - result = info->yamplitude * 200.0 * sin(time) + info->half_height; + result = st->info->yamplitude * 200.0 * sin(time) + st->info->half_height; } - pos[index] = result; + st->pos[index] = result; } static void -circle(unsigned long int the_time, struct info *info, int pos[], int index) +circle(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index) { int result; if (index == 0) { - result = info->xamplitude * (cos((double)the_time / 100.0 * info->xspeed) * (info->half_width / 2)) + info->half_width; + result = st->info->xamplitude * (cos((double)the_time / 100.0 * st->info->xspeed) * (st->info->half_width / 2)) + st->info->half_width; } else { - result = info->yamplitude * (sin((double)the_time / 100.0 * info->yspeed) * (info->half_height / 2)) + info->half_height; + result = st->info->yamplitude * (sin((double)the_time / 100.0 * st->info->yspeed) * (st->info->half_height / 2)) + st->info->half_height; } - pos[index] = result; + st->pos[index] = result; } #if 0 @@ -282,7 +236,7 @@ static void mod(unsigned long int the_time, struct info *info, int pos[], int index) { int amplitude; - int max = info->half_width; + int max = st->info->half_width; if ((the_time % (max * 2)) < max) amplitude = max - ((the_time % (max * 2)) - max); else @@ -292,56 +246,56 @@ mod(unsigned long int the_time, struct info *info, int pos[], int index) #endif static void -spin(unsigned long int the_time, struct info *info, int pos[], int index) +spin(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index) { double funky = (((the_time % 360) * 1.0) / 180.0) * M_PI; if (index ==0) { - double the_cos = cos((double)the_time / (180.0 * info->xspeed)); - double dist_mod_x = cos((double)funky) * (info->half_width - 50); - pos[index] = info->xamplitude * (the_cos * dist_mod_x) + info->half_width; + double the_cos = cos((double)the_time / (180.0 * st->info->xspeed)); + double dist_mod_x = cos((double)funky) * (st->info->half_width - 50); + st->pos[index] = st->info->xamplitude * (the_cos * dist_mod_x) + st->info->half_width; } else { - double the_sin = sin((double)the_time / (180.0 * info->yspeed)); - double dist_mod_y = sin((double)funky) * (info->half_height - 50); - pos[index] = info->yamplitude * (the_sin * dist_mod_y) + info->half_height; + double the_sin = sin((double)the_time / (180.0 * st->info->yspeed)); + double dist_mod_y = sin((double)funky) * (st->info->half_height - 50); + st->pos[index] = st->info->yamplitude * (the_sin * dist_mod_y) + st->info->half_height; } } static void -fun(unsigned long int the_time, struct info *info, int pos[], int index) +fun(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index) { int amplitude; - int max = info->half_width; + int max = st->info->half_width; if ((the_time % (max * 2)) < max) amplitude = max - ((the_time % (max * 2)) - max); else amplitude = the_time % (max * 2); amplitude = amplitude - max; if (index ==0) { - pos[index] = (amplitude * cos((double)the_time / 100.0 * info->xspeed)) + info->half_width; + st->pos[index] = (amplitude * cos((double)the_time / 100.0 * st->info->xspeed)) + st->info->half_width; } else { - pos[index] = (amplitude * sin((double)the_time / 100.0 * info->yspeed)) + info->half_height; + st->pos[index] = (amplitude * sin((double)the_time / 100.0 * st->info->yspeed)) + st->info->half_height; } } static void -linear(unsigned long int the_time, struct info *info, int pos[], int index) +linear(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index) { if (index == 0) /* Calculate for the x axis */ - pos[index] = ((the_time / 2) % (info->half_width * 2)); + st->pos[index] = ((the_time / 2) % (st->info->half_width * 2)); else - pos[index] = ((the_time / 2) % (info->half_height * 2)); + st->pos[index] = ((the_time / 2) % (st->info->half_height * 2)); } static void -test(unsigned long int the_time, struct info *info, int pos[], int index) +test(struct state *st, unsigned long int the_time, struct info *info, int pos[], int index) { if (index == 0) { - pos[index] = info->xamplitude * (cos((double)the_time / 100.0 * info->xspeed) * (info->half_width / 2)) + info->half_width; + st->pos[index] = st->info->xamplitude * (cos((double)the_time / 100.0 * st->info->xspeed) * (st->info->half_width / 2)) + st->info->half_width; } else { - pos[index] = info->yamplitude * (sin((double)the_time / 100.0 * info->yspeed) * (info->half_height / 2)) + info->half_height; + st->pos[index] = st->info->yamplitude * (sin((double)the_time / 100.0 * st->info->yspeed) * (st->info->half_height / 2)) + st->info->half_height; } } @@ -354,7 +308,7 @@ static int preen(int current, int max) { } static void -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) +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) { double xdistance = abs((double)x-(double)lastx); double ydistance = abs((double)y-(double)lasty); @@ -364,310 +318,413 @@ smoothen(int x, int lastx, int y, int lasty, int size, int last_color, XColor *c if (distance > 2.0) { int newx = (int)((xdistance / distance) * slope); int newy = (int)((ydistance / distance) * slope); - if (! info->trail) { - XSetForeground(display, bgc, BlackPixel(display, screen)); - XFillArc(display, window, bgc, lastx, lasty, size, size, START_ARC, END_ARC); + if (! st->info->trail) { + XSetForeground(st->dpy, st->bgc, BlackPixel(st->dpy, st->screen)); + XFillArc(st->dpy, st->window, st->bgc, lastx, lasty, size, size, START_ARC, END_ARC); } - XSetForeground(display, bgc, colors[last_color].pixel); - XFillArc(display, window, bgc, newx, newy, size, size, START_ARC, END_ARC); - XSync(display, False); - smoothen(newx, x, newy, y, size, last_color, colors, display, window, bgc, screen, info); + XSetForeground(st->dpy, st->bgc, st->colors[last_color].pixel); + XFillArc(st->dpy, st->window, st->bgc, newx, newy, size, size, START_ARC, END_ARC); + smoothen(st, newx, x, newy, y, size, last_color, st->colors, st->dpy, st->window, st->bgc, st->screen, st->info); } } -void -screenhack (Display *display, Window window) +static void * +whirlygig_init (Display *dpy, Window window) { - /* The following are all X related toys */ - XGCValues gcv; /* The structure to hold the GC data */ - XWindowAttributes xgwa; /* A structure to hold window data */ - Pixmap b=0, ba=0; /* double-buffer to reduce flicker */ -#ifdef HAVE_DOUBLE_BUFFER_EXTENSION - XdbeBackBuffer backb = 0; -#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + struct state *st = (struct state *) calloc (1, sizeof(*st)); + st->dpy = dpy; + st->window = window; - GC fgc, bgc; - int screen; - Bool dbuf = get_boolean_resource ("doubleBuffer", "Boolean"); - Bool dbeclear_p = get_boolean_resource ("useDBEClear", "Boolean"); + st->ncolors = NCOLORS; - unsigned long int current_time = 0; /* The global int telling the current time */ - unsigned long int start_time = current_time; - struct info *info = (struct info *)malloc(sizeof(struct info)); /* Dont forget to call free() later */ - char *xmode_str, *ymode_str; /* holds the current mode for x and y computation */ - /* pos is the current position x,y -- last_x contains one cell of every x coordinate - for every position of every whirly in every line up to 100 whirlies in 100 lines - -- lasy_y and last_size hold the same information for y and size respectively */ - int pos[2], last_x[100][100], last_y[100][100], last_size[100][100]; - int current_color; - int wrap; - int xmode, ymode; - double modifier; /* for innie */ - /* Set up the X toys that I will be using later */ - screen = DefaultScreen(display); - XGetWindowAttributes (display, window, &xgwa); - if (dbuf) + st->dbuf = get_boolean_resource (st->dpy, "doubleBuffer", "Boolean"); + +# ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */ + st->dbuf = False; +# endif + + st->start_time = st->current_time; + st->info = (struct info *)malloc(sizeof(struct info)); + + st->screen = DefaultScreen(st->dpy); + XGetWindowAttributes (st->dpy, st->window, &st->xgwa); + if (st->dbuf) { #ifdef HAVE_DOUBLE_BUFFER_EXTENSION - if (dbeclear_p) - b = xdbe_get_backbuffer (display, window, XdbeBackground); - else - b = xdbe_get_backbuffer (display, window, XdbeUndefined); - backb = b; + if (get_boolean_resource(st->dpy,"useDBE","Boolean")) + { + st->dbeclear_p = get_boolean_resource (st->dpy, "useDBEClear", + "Boolean"); + if (st->dbeclear_p) + st->b = xdbe_get_backbuffer (st->dpy, st->window, XdbeBackground); + else + st->b = xdbe_get_backbuffer (st->dpy, st->window, XdbeUndefined); + st->backb = st->b; + } #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ - if (!b) + if (!st->b) { - ba = XCreatePixmap (display, window, xgwa.width, xgwa.height,xgwa.depth); - b = ba; + st->ba = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height,st->xgwa.depth); + st->b = st->ba; } } else { - b = window; + st->b = st->window; } - gcv.foreground = get_pixel_resource("foreground", "Foreground", display, xgwa.colormap); - fgc = XCreateGC (display, b, GCForeground, &gcv); - gcv.foreground = get_pixel_resource("background", "Background", display, xgwa.colormap); - bgc = XCreateGC (display, b, GCForeground, &gcv); + st->gcv.foreground = get_pixel_resource(st->dpy, st->xgwa.colormap, "foreground", "Foreground"); + st->fgc = XCreateGC (st->dpy, st->b, GCForeground, &st->gcv); + st->gcv.foreground = get_pixel_resource(st->dpy, st->xgwa.colormap, "background", "Background"); + st->bgc = XCreateGC (st->dpy, st->b, GCForeground, &st->gcv); + +#ifdef HAVE_COCOA /* #### should turn off double-buffering instead */ + jwxyz_XSetAntiAliasing (dpy, st->fgc, False); + jwxyz_XSetAntiAliasing (dpy, st->bgc, False); +#endif + { Bool writable_p = False; - make_uniform_colormap (display, xgwa.visual, xgwa.colormap, colors, &ncolors, True, &writable_p, True); + make_uniform_colormap (st->dpy, st->xgwa.visual, st->xgwa.colormap, st->colors, &st->ncolors, True, &writable_p, True); } - if (ba) XFillRectangle (display, ba, bgc, 0, 0, xgwa.width, xgwa.height); + if (st->ba) XFillRectangle (st->dpy, st->ba, st->bgc, 0, 0, st->xgwa.width, st->xgwa.height); /* info is a structure holding all the random pieces of information I may want to pass to my baby functions -- much of it I may never use, but it is nice to have around just in case I want it to make a funky function funkier */ -/* info->writable = get_boolean_resource ("cycle", "Boolean"); */ - info->xspeed = get_float_resource("xspeed" , "Float"); - info->yspeed = get_float_resource("yspeed" , "Float"); - info->xamplitude = get_float_resource("xamplitude", "Float"); - info->yamplitude = get_float_resource("yamplitude", "Float"); - info->offset_period = get_float_resource("offset_period", "Float"); - info->whirlies = get_integer_resource("whirlies", "Integer"); - info->nlines = get_integer_resource("nlines", "Integer"); - info->half_width = xgwa.width / 2; - info->half_height = xgwa.height / 2; - info->speed = get_integer_resource("speed" , "Integer"); - info->trail = get_integer_resource("trail", "Integer"); - info->color_modifier = get_integer_resource("color_modifier", "Integer"); - info->xoffset = get_float_resource("xoffset", "Float"); - info->yoffset = get_float_resource("yoffset", "Float"); - xmode_str = get_string_resource("xmode", "Mode"); - ymode_str = get_string_resource("ymode", "Mode"); - wrap = get_integer_resource("wrap", "Integer"); - modifier = 3000.0 + frand(1500.0); - if (! xmode_str) xmode = spin_mode; - else if (! strcmp (xmode_str, "spin")) xmode = spin_mode; - else if (! strcmp (xmode_str, "funky")) xmode = funky_mode; - else if (! strcmp (xmode_str, "circle")) xmode = circle_mode; - else if (! strcmp (xmode_str, "linear")) xmode = linear_mode; - else if (! strcmp (xmode_str, "test")) xmode = test_mode; - else if (! strcmp (xmode_str, "fun")) xmode = fun_mode; - else if (! strcmp (xmode_str, "innie")) xmode = innie_mode; - else if (! strcmp (xmode_str, "lissajous")) xmode = lissajous_mode; +/* info->writable = get_boolean_resource (dpy, "cycle", "Boolean"); */ + st->info->xspeed = get_float_resource(st->dpy, "xspeed" , "Float"); + st->info->yspeed = get_float_resource(st->dpy, "yspeed" , "Float"); + st->info->xamplitude = get_float_resource(st->dpy, "xamplitude", "Float"); + st->info->yamplitude = get_float_resource(st->dpy, "yamplitude", "Float"); + st->info->offset_period = get_float_resource(st->dpy, "offset_period", "Float"); + st->info->whirlies = get_integer_resource(st->dpy, "whirlies", "Integer"); + st->info->nlines = get_integer_resource(st->dpy, "nlines", "Integer"); + st->info->half_width = st->xgwa.width / 2; + st->info->half_height = st->xgwa.height / 2; + st->info->speed = get_integer_resource(st->dpy, "speed" , "Integer"); + st->info->trail = get_integer_resource(st->dpy, "trail", "Integer"); + st->info->color_modifier = get_integer_resource(st->dpy, "color_modifier", "Integer"); + st->info->xoffset = get_float_resource(st->dpy, "xoffset", "Float"); + st->info->yoffset = get_float_resource(st->dpy, "yoffset", "Float"); + st->xmode_str = get_string_resource(st->dpy, "xmode", "Mode"); + st->ymode_str = get_string_resource(st->dpy, "ymode", "Mode"); + st->wrap = get_boolean_resource(st->dpy, "wrap", "Boolean"); + st->modifier = 3000.0 + frand(1500.0); + if (! st->xmode_str) st->xmode = spin_mode; + else if (! strcmp (st->xmode_str, "spin")) st->xmode = spin_mode; + else if (! strcmp (st->xmode_str, "funky")) st->xmode = funky_mode; + else if (! strcmp (st->xmode_str, "circle")) st->xmode = circle_mode; + else if (! strcmp (st->xmode_str, "linear")) st->xmode = linear_mode; + else if (! strcmp (st->xmode_str, "test")) st->xmode = test_mode; + else if (! strcmp (st->xmode_str, "fun")) st->xmode = fun_mode; + else if (! strcmp (st->xmode_str, "innie")) st->xmode = innie_mode; + else if (! strcmp (st->xmode_str, "lissajous")) st->xmode = lissajous_mode; else { - xmode = spin_mode; + st->xmode = random() % (int) lissajous_mode; } - if (! ymode_str) ymode = spin_mode; - else if (! strcmp (ymode_str, "spin")) ymode = spin_mode; - else if (! strcmp (ymode_str, "funky")) ymode = funky_mode; - else if (! strcmp (ymode_str, "circle")) ymode = circle_mode; - else if (! strcmp (ymode_str, "linear")) ymode = linear_mode; - else if (! strcmp (ymode_str, "test")) ymode = test_mode; - else if (! strcmp (ymode_str, "fun")) ymode = fun_mode; - else if (! strcmp (ymode_str, "innie")) ymode = innie_mode; - else if (! strcmp (ymode_str, "lissajous")) ymode = lissajous_mode; + if (! st->ymode_str) st->ymode = spin_mode; + else if (! strcmp (st->ymode_str, "spin")) st->ymode = spin_mode; + else if (! strcmp (st->ymode_str, "funky")) st->ymode = funky_mode; + else if (! strcmp (st->ymode_str, "circle")) st->ymode = circle_mode; + else if (! strcmp (st->ymode_str, "linear")) st->ymode = linear_mode; + else if (! strcmp (st->ymode_str, "test")) st->ymode = test_mode; + else if (! strcmp (st->ymode_str, "fun")) st->ymode = fun_mode; + else if (! strcmp (st->ymode_str, "innie")) st->ymode = innie_mode; + else if (! strcmp (st->ymode_str, "lissajous")) st->ymode = lissajous_mode; else { - ymode = spin_mode; + st->ymode = random() % (int) lissajous_mode; } - if (get_integer_resource("start_time", "Integer") == -1) - current_time = (unsigned long int)(random()); + if (get_integer_resource(st->dpy, "start_time", "Integer") == -1) + st->current_time = (unsigned long int)(random()); else - current_time = get_integer_resource("start_time", "Integer"); - if (info->whirlies == -1) - info->whirlies = 1 + (random() % 15); - if (info->nlines == -1) - info->nlines = 1 + (random() % 5); - if (info->color_modifier == -1) - info->color_modifier = 1 + (random() % 25); - if (get_boolean_resource("explain", "Integer")) - explain(xmode, ymode, info, display, window, fgc); - current_color = 1 + (random() % NCOLORS); - /* Now that info is full, lets play! */ - - while (1) { - int wcount; /* wcount is a counter incremented for every whirly take note of - internal_time before you mess with it */ - int change_time = 4000; - if (! strcmp (xmode_str, "change") && ! strcmp (ymode_str, "change")) { - if ((current_time - start_time) > change_time) { - start_time = current_time; - xmode = 1 + (random() % 4); - ymode = 1 + (random() % 4); - } + st->current_time = get_integer_resource(st->dpy, "start_time", "Integer"); + if (st->info->whirlies == -1) + st->info->whirlies = 1 + (random() % 15); + if (st->info->nlines == -1) + st->info->nlines = 1 + (random() % 5); + if (st->info->color_modifier == -1) + st->info->color_modifier = 1 + (random() % 25); + if (get_boolean_resource(st->dpy, "explain", "Integer")) + st->explaining = 1; + st->current_color = 1 + (random() % NCOLORS); + + return st; +} + +static unsigned long +whirlygig_draw (Display *dpy, Window window, void *closure) +{ + struct state *st = (struct state *) closure; + int wcount; /* wcount is a counter incremented for every whirly take note of + internal_time before you mess with it */ + int change_time = 4000; + + if (st->explaining == 1) { + XClearWindow (st->dpy, st->window); + draw_explain_string(st, st->xmode, st->info->half_height-100, + st->dpy, st->window, st->fgc); + st->explaining++; + return 3000000; + } else if (st->explaining == 2) { + XClearWindow (st->dpy, st->window); + st->explaining = 0; + } + + if (! strcmp (st->xmode_str, "change") && ! strcmp (st->ymode_str, "change")) { + if ((st->current_time - st->start_time) > change_time) { + st->start_time = st->current_time; + st->xmode = 1 + (random() % 4); + st->ymode = 1 + (random() % 4); + } + } + else if (! strcmp (st->xmode_str, "change")) { + if ((st->current_time - st->start_time) > change_time) { + st->start_time = st->current_time; + st->xmode = 1 + (random() % 4); + } + } + else if (! strcmp (st->ymode_str, "change")) { + if ((st->current_time - st->start_time) > change_time) { + st->start_time = st->current_time; + st->ymode = 1 + (random() % 3); + printf("Changing ymode to %d\n", st->ymode); + } + } + if (++st->current_color >= NCOLORS) + st->current_color = 0; + for (wcount = 0; wcount < st->info->whirlies; wcount++) { + int lcount; /* lcount is a counter for every line -- take note of the offsets changing */ + int internal_time = st->current_time; + int color_offset = (st->current_color + (st->info->color_modifier * wcount)) % NCOLORS; + if (st->current_time == 0) + internal_time = 0; + else + /* I want the distance between whirlies to increase more each whirly */ + internal_time = st->current_time + (10 * wcount) + (wcount * wcount); + switch (st->xmode) { + /* All these functions expect an int time, the struct info, + a pointer to an array of positions, and the index that the + the function will fill of the array */ + case spin_mode: + spin(st, internal_time, st->info, st->pos, 0); + break; + case funky_mode: + funky(st, internal_time, st->info, st->pos, 0); + break; + case circle_mode: + circle(st, internal_time, st->info, st->pos, 0); + break; + case linear_mode: + linear(st, internal_time, st->info, st->pos, 0); + break; + case fun_mode: + fun(st, internal_time, st->info, st->pos, 0); + break; + case test_mode: + test(st, internal_time, st->info, st->pos, 0); + break; + case innie_mode: + innie(st, internal_time, st->info, st->pos, 0, st->modifier); + break; + case lissajous_mode: + lissajous(st, internal_time, st->info, st->pos, 0); + break; + default: + spin(st, internal_time, st->info, st->pos, 0); + break; + } /* End of the switch for the x position*/ + switch (st->ymode) { + case spin_mode: + spin(st, internal_time, st->info, st->pos, 1); + break; + case funky_mode: + funky(st, internal_time, st->info, st->pos, 1); + break; + case circle_mode: + circle(st, internal_time, st->info, st->pos, 1); + break; + case linear_mode: + linear(st, internal_time, st->info, st->pos, 1); + break; + case fun_mode: + fun(st, internal_time, st->info, st->pos, 1); + break; + case test_mode: + test(st, internal_time, st->info, st->pos, 1); + break; + case innie_mode: + innie(st, internal_time, st->info, st->pos, 1, st->modifier); + break; + case lissajous_mode: + lissajous(st, internal_time, st->info, st->pos, 1); + break; + default: + spin(st, internal_time, st->info, st->pos, 1); + break; + } /* End of the switch for the y position*/ + for (lcount = 0; lcount < st->info->nlines; lcount++) { + double arg = (double)((internal_time * st->info->offset_period) / 90.0); + double line_offset = 20.0 * (double)lcount * sin(arg); + int size; + size = (int)(15.0 + 5.0 * sin((double)internal_time / 180.0)); + /* First delete the old circle... */ + if (!st->info->trail +#ifdef HAVE_DOUBLE_BUFFER_EXTENSION + && ( !st->dbeclear_p || !st->backb) +#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ + ) { + XSetForeground(st->dpy, st->bgc, BlackPixel(st->dpy, st->screen)); + 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); + } + /* Now, lets draw in the new circle */ + { /* Starting new scope for local x_pos and y_pos */ + int xpos, ypos; + if (st->wrap) { + xpos = preen((int)(st->info->xoffset*line_offset)+st->pos[0], st->info->half_width * 2); + ypos = preen((int)(st->info->yoffset*line_offset)+st->pos[1], st->info->half_height * 2); } - else if (! strcmp (xmode_str, "change")) { - if ((current_time - start_time) > change_time) { - start_time = current_time; - xmode = 1 + (random() % 4); - } + else { + xpos = (int)(st->info->xoffset*line_offset)+st->pos[0]; + ypos = (int)(st->info->yoffset*line_offset)+st->pos[1]; } - else if (! strcmp (ymode_str, "change")) { - if ((current_time - start_time) > change_time) { - start_time = current_time; - ymode = 1 + (random() % 3); - printf("Changing ymode to %d\n", ymode); - } + if (st->start_time == st->current_time) { + /* smoothen should move from one mode to another prettily... */ + + /* Note: smoothen has not been modified to take the double + buffering code into account, and needs to be hacked on + before uncommenting. + */ + /* + smoothen(xpos, last_x[wcount][lcount], ypos, last_y[wcount][lcount], size, color_offset, colors, dpy, window, bgc, screen, info); + */ } - if (++current_color >= NCOLORS) - current_color = 0; - for (wcount = 0; wcount < info->whirlies; wcount++) { - int lcount; /* lcount is a counter for every line -- take note of the offsets changing */ - int internal_time = current_time; - int color_offset = (current_color + (info->color_modifier * wcount)) % NCOLORS; - if (current_time == 0) - internal_time = 0; - else - /* I want the distance between whirlies to increase more each whirly */ - internal_time = current_time + (10 * wcount) + (wcount * wcount); - switch (xmode) { - /* All these functions expect an int time, the struct info, - a pointer to an array of positions, and the index that the - the function will fill of the array */ - case spin_mode: - spin(internal_time, info, pos, 0); - break; - case funky_mode: - funky(internal_time, info, pos, 0); - break; - case circle_mode: - circle(internal_time, info, pos, 0); - break; - case linear_mode: - linear(internal_time, info, pos, 0); - break; - case fun_mode: - fun(internal_time, info, pos, 0); - break; - case test_mode: - test(internal_time, info, pos, 0); - break; - case innie_mode: - innie(internal_time, info, pos, 0, modifier); - break; - case lissajous_mode: - lissajous(internal_time, info, pos, 0); - break; - default: - spin(internal_time, info, pos, 0); - break; - } /* End of the switch for the x position*/ - switch (ymode) { - case spin_mode: - spin(internal_time, info, pos, 1); - break; - case funky_mode: - funky(internal_time, info, pos, 1); - break; - case circle_mode: - circle(internal_time, info, pos, 1); - break; - case linear_mode: - linear(internal_time, info, pos, 1); - break; - case fun_mode: - fun(internal_time, info, pos, 1); - break; - case test_mode: - test(internal_time, info, pos, 1); - break; - case innie_mode: - innie(internal_time, info, pos, 1, modifier); - break; - case lissajous_mode: - lissajous(internal_time, info, pos, 1); - break; - default: - spin(internal_time, info, pos, 1); - break; - } /* End of the switch for the y position*/ - for (lcount = 0; lcount < info->nlines; lcount++) { - double arg = (double)((internal_time * info->offset_period) / 90.0); - double line_offset = 20.0 * (double)lcount * sin(arg); - int size; - size = (int)(15.0 + 5.0 * sin((double)internal_time / 180.0)); - /* First delete the old circle... */ - if (!info->trail && ( !dbeclear_p + st->last_x[wcount][lcount] = xpos; + st->last_y[wcount][lcount] = ypos; + st->last_size[wcount][lcount] = size; + XSetForeground(st->dpy, st->bgc, st->colors[color_offset].pixel); + XFillArc(st->dpy, st->b, st->bgc, xpos, ypos, size, size, START_ARC, END_ARC); + } /* End of my temporary scope for xpos and ypos */ + } /* End of the for each line in nlines */ + } /* End of the for each whirly in whirlies */ + + #ifdef HAVE_DOUBLE_BUFFER_EXTENSION - || !backb + if (st->backb) + { + XdbeSwapInfo info[1]; + info[0].swap_window = st->window; + info[0].swap_action = (st->dbeclear_p ? XdbeBackground : XdbeUndefined); + XdbeSwapBuffers (st->dpy, info, 1); + } + else #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ - )) { - XSetForeground(display, bgc, BlackPixel(display, screen)); - XFillArc(display, b, bgc, last_x[wcount][lcount], last_y[wcount][lcount], last_size[wcount][lcount], last_size[wcount][lcount], START_ARC, END_ARC); - } - /* Now, lets draw in the new circle */ - { /* Starting new scope for local x_pos and y_pos */ - int xpos, ypos; - if (wrap) { - xpos = preen((int)(info->xoffset*line_offset)+pos[0], info->half_width * 2); - ypos = preen((int)(info->yoffset*line_offset)+pos[1], info->half_height * 2); - } - else { - xpos = (int)(info->xoffset*line_offset)+pos[0]; - ypos = (int)(info->yoffset*line_offset)+pos[1]; - } - if (start_time == current_time) { - /* smoothen should move from one mode to another prettily... */ - - /* Note: smoothen has not been modified to take the double - buffering code into account, and needs to be hacked on - before uncommenting. - */ -/* - smoothen(xpos, last_x[wcount][lcount], ypos, last_y[wcount][lcount], size, color_offset, colors, display, window, bgc, screen, info); - */ - } - last_x[wcount][lcount] = xpos; - last_y[wcount][lcount] = ypos; - last_size[wcount][lcount] = size; - XSetForeground(display, bgc, colors[color_offset].pixel); - XFillArc(display, b, bgc, xpos, ypos, size, size, START_ARC, END_ARC); - } /* End of my temporary scope for xpos and ypos */ - } /* End of the for each line in nlines */ - } /* End of the for each whirly in whirlies */ + if (st->dbuf) + { + XCopyArea (st->dpy, st->b, st->window, st->bgc, 0, 0, + st->xgwa.width, st->xgwa.height, 0, 0); + } + + if (st->current_time == FULL_CYCLE) + st->current_time = 1; + else + st->current_time = st->current_time + st->info->speed; + + return 10000; +} + +static void +whirlygig_reshape (Display *dpy, Window window, void *closure, + unsigned int w, unsigned int h) +{ +} +static Bool +whirlygig_event (Display *dpy, Window window, void *closure, XEvent *event) +{ + return False; +} +static void +whirlygig_free (Display *dpy, Window window, void *closure) +{ +} + + +static const char *whirlygig_defaults [] = { + ".background: black", + ".foreground: white", + "*xspeed: 1.0", + "*yspeed: 1.0", + "*xamplitude: 1.0", + "*yamplitude: 1.0", + "*whirlies: -1", + "*nlines: -1", + "*xmode: change", + "*ymode: change", + "*speed: 1", + "*trail: 0", + "*color_modifier: -1", + "*start_time: -1", + "*explain: False", + "*xoffset: 1.0", + "*yoffset: 1.0", + "*offset_period: 1", + "*wrap: False", + "*doubleBuffer: True", #ifdef HAVE_DOUBLE_BUFFER_EXTENSION - if (backb) - { - XdbeSwapInfo info[1]; - info[0].swap_window = window; - info[0].swap_action = (dbeclear_p ? XdbeBackground : XdbeUndefined); - XdbeSwapBuffers (display, info, 1); - } - else + "*useDBEClear: True", + "*useDBE: True", #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ - if (dbuf) - { - XCopyArea (display, b, window, bgc, 0, 0, - xgwa.width, xgwa.height, 0, 0); - } - - XSync(display, False); - if (current_time == FULL_CYCLE) - current_time = 1; - else - current_time = current_time + info->speed; - screenhack_handle_events(display); -/* if (!info->writable) */ - usleep(10000); - } /* End the while loop! */ - free(info); -} + 0 +}; + +static XrmOptionDescRec whirlygig_options [] = { + { "-xspeed", ".xspeed", XrmoptionSepArg, 0 }, + /* xspeed is a modifier of the argument to cos -- changing it thus + changes the frequency of cos */ + { "-yspeed", ".yspeed", XrmoptionSepArg, 0 }, + /* Similiarly, yspeed changes the frequency of sin */ + { "-xamplitude", ".xamplitude", XrmoptionSepArg, 0 }, + /* A factor by which to increase/decrease the amplitude of the sin */ + { "-yamplitude", ".yamplitude", XrmoptionSepArg, 0 }, + /* A factor by which to increase/decrease the amplitude of the cos */ + { "-whirlies", ".whirlies",XrmoptionSepArg, 0 }, + /* whirlies defines the number of circles to draw per line */ + { "-nlines", ".nlines",XrmoptionSepArg, 0 }, + /* nlines is the number of lines of whirlies to draw */ + { "-xmode", ".xmode", XrmoptionSepArg, 0 }, + /* There are a few different modes that I have written -- each mode + is in theory a different experiment with the possible modifiers to sin/cos */ + { "-ymode", ".ymode", XrmoptionSepArg, 0 }, + { "-speed", ".speed", XrmoptionSepArg, 0 }, + /* This will modify how often it should draw, changing it will probably suck */ + { "-trail", ".trail", XrmoptionSepArg, 0 }, + /* Control whether or not you want the old circles to be erased */ + { "-color_modifier", ".color_modifier", XrmoptionSepArg, 0 }, + /* How many colors away from the current should the next whirly be? */ + { "-start_time", ".start_time", XrmoptionSepArg, 0 }, + /* Specify exactly at what time to start graphing... */ + { "-xoffset", ".xoffset", XrmoptionSepArg, 0 }, + /* Tell the whirlies to be offset by this factor of a sin */ + { "-yoffset", ".yoffset", XrmoptionSepArg, 0 }, + /* Tell the whirlies to be offset by this factor of a cos */ + { "-offset_period", ".offset_period", XrmoptionSepArg, 0 }, + /* Change the period of an offset cycle */ + { "-explain", ".explain", XrmoptionNoArg, "True" }, + /* Specify whether or not to print an explanation of the function used. */ + { "-wrap", ".wrap", XrmoptionNoArg, "True" }, + { "-no-wrap", ".wrap", XrmoptionNoArg, "False" }, + /* Specify if you want whirlies which are out of the boundary of the screen to be + wrapped around to the other side */ + { "-db", ".doubleBuffer", XrmoptionNoArg, "True" }, + { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" }, + { 0, 0, 0, 0 } +}; + +XSCREENSAVER_MODULE ("Whirlygig", whirlygig)