1 /* squiral, by "Jeff Epler" <jepler@inetnebr.com>, 18-mar-1999.
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
12 #include "screenhack.h"
17 #define R(x) (abs(random())%x)
18 #define PROB(x) (frand(1.0) < (x))
20 #define NCOLORSMAX 255
23 /* 0- 3 left-winding */
24 /* 4- 7 right-winding */
39 int width, height, count, cycle;
40 double frac, disorder, handedness;
43 XColor colors[NCOLORSMAX];
57 #define CLEAR1(x,y) (!st->fill[((y)%st->height)*st->width+(x)%st->width])
58 #define MOVE1(x,y) (st->fill[((y)%st->height)*st->width+(x)%st->width]=1, XDrawPoint(st->dpy, st->window, st->draw_gc, (x)%st->width,(y)%st->height), st->cov++)
60 #define CLEARDXY(x,y,dx,dy) CLEAR1(x+dx, y+dy) && CLEAR1(x+dx+dx, y+dy+dy)
61 #define MOVEDXY(x,y,dx,dy) MOVE1 (x+dx, y+dy), MOVE1 (x+dx+dx, y+dy+dy)
63 #define CLEAR(d) CLEARDXY(w->h,w->v, st->dirh[d],st->dirv[d])
64 #define MOVE(d) (XSetForeground(st->dpy, st->draw_gc, st->colors[w->c].pixel), \
65 MOVEDXY(w->h,w->v, st->dirh[d],st->dirv[d]), \
66 w->h=w->h+st->dirh[d]*2, \
67 w->v=w->v+st->dirv[d]*2, dir=d)
69 #define RANDOM (void) (w->h = R(st->width), w->v = R(st->height), w->c = R(st->ncolors), \
70 type=R(2), dir=R(4), (st->cycle && (w->cc=R(3)+st->ncolors)))
74 #define SUCC(x) ((x+1)%4)
75 #define PRED(x) ((x+3)%4)
78 #define REV ((dir+2)%4)
80 #define TRY(x) if (CLEAR(x)) { MOVE(x); break; }
83 do_worm(struct state *st, struct worm *w)
88 w->c = (w->c+w->cc) % st->ncolors;
90 if (PROB(st->disorder)) type=PROB(st->handedness);
106 w->h = w->h % st->width;
107 w->v = w->v % st->height;
111 squiral_init_1 (struct state *st)
114 if (st->worms) free (st->worms);
115 if (st->fill) free (st->fill);
117 st->worms=calloc(st->count, sizeof(struct worm));
118 st->fill=calloc(st->width*st->height, sizeof(int));
120 st->dirh[0]=0; st->dirh[1]=1; st->dirh[2]=0; st->dirh[3]=st->width-1;
121 st->dirv[0]=st->height-1; st->dirv[1]=0; st->dirv[2]=1; st->dirv[3]=0;
122 for(i=0;i<st->count;i++) {
123 st->worms[i].h=R(st->width);
124 st->worms[i].v=R(st->height);
125 st->worms[i].s=R(4)+4*PROB(st->handedness);
126 st->worms[i].c=R(st->ncolors);
127 if(st->cycle) { st->worms[i].cc=R(3)+st->ncolors; }
128 else st->worms[i].cc=0;
133 squiral_init (Display *dpy, Window window)
135 struct state *st = (struct state *) calloc (1, sizeof(*st));
138 XWindowAttributes xgwa;
139 Bool writeable = False;
144 st->delay= get_integer_resource(st->dpy, "delay", "Integer");
146 XClearWindow(st->dpy, st->window);
147 XGetWindowAttributes(st->dpy, st->window, &xgwa);
148 st->width = xgwa.width;
149 st->height = xgwa.height;
151 cmap = xgwa.colormap;
152 gcv.foreground = get_pixel_resource(st->dpy, cmap, "foreground",
154 st->draw_gc = XCreateGC(st->dpy, st->window, GCForeground, &gcv);
155 gcv.foreground = get_pixel_resource (st->dpy, cmap, "background", "Background");
156 st->erase_gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv);
157 cmap = xgwa.colormap;
159 free_colors(st->dpy, cmap, st->colors, st->ncolors);
164 st->colors[0].pixel=get_pixel_resource(st->dpy, cmap, "foreground","Foreground");
166 st->ncolors = get_integer_resource(st->dpy, "ncolors", "Integer");
167 if (st->ncolors < 0 || st->ncolors > NCOLORSMAX)
168 st->ncolors = NCOLORSMAX;
169 make_uniform_colormap(st->dpy, xgwa.visual, cmap, st->colors, &st->ncolors, True,
171 if (st->ncolors <= 0) {
173 st->colors[0].pixel=get_pixel_resource(st->dpy, cmap, "foreground","Foreground");
176 st->count= get_integer_resource(st->dpy, "count", "Integer");
177 st->frac = get_integer_resource(st->dpy, "fill", "Integer")*0.01;
178 st->cycle= get_boolean_resource(st->dpy, "cycle", "Cycle");
179 st->disorder=get_float_resource(st->dpy, "disorder", "Float");
180 st->handedness=get_float_resource(st->dpy, "handedness", "Float");
182 if(st->frac<0.01) st->frac=0.01;
183 if(st->frac>0.99) st->frac=0.99;
184 if(st->count==0) st->count=st->width/32;
185 if(st->count<1) st->count=1;
186 if(st->count>1000) st->count=1000;
188 if(st->worms) free(st->worms);
189 if(st->fill) free(st->fill);
197 squiral_draw (Display *dpy, Window window, void *closure)
199 struct state *st = (struct state *) closure;
202 if(st->inclear<st->height) {
203 XDrawLine(st->dpy, st->window, st->erase_gc, 0, st->inclear, st->width-1, st->inclear);
204 memset(&st->fill[st->inclear*st->width], 0, sizeof(int)*st->width);
205 XDrawLine(st->dpy, st->window, st->erase_gc, 0, st->height-st->inclear-1, st->width-1,
206 st->height-st->inclear-1);
207 memset(&st->fill[(st->height-st->inclear-1)*st->width], 0, sizeof(int)*st->width);
209 XDrawLine(st->dpy, st->window, st->erase_gc, 0, st->inclear, st->width-1, st->inclear);
210 if (st->inclear < st->height)
211 memset(&st->fill[st->inclear*st->width], 0, sizeof(int)*st->width);
212 XDrawLine(st->dpy, st->window, st->erase_gc, 0, st->height-st->inclear-1, st->width-1,
213 st->height-st->inclear-1);
214 if (st->height - st->inclear >= 1)
215 memset(&st->fill[(st->height-st->inclear-1)*st->width], 0, sizeof(int)*st->width);
217 if(st->inclear>st->height/2) st->inclear=st->height;
219 else if(st->cov>(st->frac*st->width*st->height)) {
223 for(i=0;i<st->count;i++) do_worm(st, &st->worms[i]);
228 squiral_reshape (Display *dpy, Window window, void *closure,
229 unsigned int w, unsigned int h)
231 struct state *st = (struct state *) closure;
235 XClearWindow (dpy, window);
239 squiral_event (Display *dpy, Window window, void *closure, XEvent *event)
245 squiral_free (Display *dpy, Window window, void *closure)
247 struct state *st = (struct state *) closure;
252 static const char *squiral_defaults[] = {
253 ".background: black",
254 ".foreground: white",
266 static XrmOptionDescRec squiral_options[] = {
267 {"-fill", ".fill", XrmoptionSepArg, 0},
268 {"-count", ".count", XrmoptionSepArg, 0},
269 {"-delay", ".delay", XrmoptionSepArg, 0},
270 {"-disorder", ".disorder", XrmoptionSepArg, 0},
271 {"-handedness", ".handedness", XrmoptionSepArg, 0},
272 {"-ncolors", ".ncolors", XrmoptionSepArg, 0},
273 {"-cycle", ".cycle", XrmoptionNoArg, "True"},
274 {"-no-cycle", ".cycle", XrmoptionNoArg, "False"},
278 XSCREENSAVER_MODULE ("Squiral", squiral)