1 | /* -*- Mode: C; tab-width: 4 -*- */ |
---|
2 | /* lissie --- the Lissajous worm */ |
---|
3 | |
---|
4 | #if 0 |
---|
5 | static const char sccsid[] = "@(#)lissie.c 5.00 2000/11/01 xlockmore"; |
---|
6 | #endif |
---|
7 | |
---|
8 | /*- |
---|
9 | * lissie.c - The Lissajous worm for xlock, the X Window System |
---|
10 | * lockscreen. |
---|
11 | * |
---|
12 | * Copyright (c) 1996 by Alexander Jolk <ub9x@rz.uni-karlsruhe.de> |
---|
13 | * |
---|
14 | * Permission to use, copy, modify, and distribute this software and its |
---|
15 | * documentation for any purpose and without fee is hereby granted, |
---|
16 | * provided that the above copyright notice appear in all copies and that |
---|
17 | * both that copyright notice and this permission notice appear in |
---|
18 | * supporting documentation. |
---|
19 | * |
---|
20 | * This file is provided AS IS with no warranties of any kind. The author |
---|
21 | * shall have no liability with respect to the infringement of copyrights, |
---|
22 | * trade secrets or any patents by this file or any part thereof. In no |
---|
23 | * event will the author be liable for any lost revenue or profits or |
---|
24 | * other special, indirect and consequential damages. |
---|
25 | * |
---|
26 | * Revision History: |
---|
27 | * 01-Nov-2000: Allocation checks |
---|
28 | * 10-May-1997: Compatible with xscreensaver |
---|
29 | * 18-Aug-1996: added refresh-hook. |
---|
30 | * 01-May-1996: written. |
---|
31 | */ |
---|
32 | |
---|
33 | #ifdef STANDALONE |
---|
34 | #define MODE_lissie |
---|
35 | #define PROGCLASS "Lissie" |
---|
36 | #define HACK_INIT init_lissie |
---|
37 | #define HACK_DRAW draw_lissie |
---|
38 | #define lissie_opts xlockmore_opts |
---|
39 | #define DEFAULTS "*delay: 10000 \n" \ |
---|
40 | "*count: 1 \n" \ |
---|
41 | "*cycles: 20000 \n" \ |
---|
42 | "*size: -200 \n" \ |
---|
43 | "*ncolors: 200 \n" |
---|
44 | #define SMOOTH_COLORS |
---|
45 | #include "xlockmore.h" /* in xscreensaver distribution */ |
---|
46 | #else /* STANDALONE */ |
---|
47 | #include "xlock.h" /* in xlockmore distribution */ |
---|
48 | #endif /* STANDALONE */ |
---|
49 | |
---|
50 | #ifdef MODE_lissie |
---|
51 | |
---|
52 | ModeSpecOpt lissie_opts = |
---|
53 | {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL}; |
---|
54 | |
---|
55 | #ifdef USE_MODULES |
---|
56 | ModStruct lissie_description = |
---|
57 | {"lissie", "init_lissie", "draw_lissie", "release_lissie", |
---|
58 | "refresh_lissie", "init_lissie", (char *) NULL, &lissie_opts, |
---|
59 | 10000, 1, 2000, -200, 64, 0.6, "", |
---|
60 | "Shows lissajous worms", 0, NULL}; |
---|
61 | |
---|
62 | #endif |
---|
63 | |
---|
64 | #define MINSIZE 1 |
---|
65 | |
---|
66 | #define Lissie(n)\ |
---|
67 | if (lissie->loc[(n)].x > 0 && lissie->loc[(n)].y > 0 &&\ |
---|
68 | lissie->loc[(n)].x <= lp->width && lissie->loc[(n)].y <= lp->height) {\ |
---|
69 | if (lissie->ri < 2)\ |
---|
70 | XDrawPoint(display, MI_WINDOW(mi),\ |
---|
71 | gc, lissie->loc[(n)].x, lissie->loc[(n)].y);\ |
---|
72 | else\ |
---|
73 | XDrawArc(display, MI_WINDOW(mi), gc,\ |
---|
74 | lissie->loc[(n)].x - lissie->ri / 2,\ |
---|
75 | lissie->loc[(n)].y - lissie->ri / 2,\ |
---|
76 | lissie->ri, lissie->ri, 0, 23040);\ |
---|
77 | } |
---|
78 | |
---|
79 | #define FLOATRAND(min,max) ((min)+(LRAND()/MAXRAND)*((max)-(min))) |
---|
80 | #define INTRAND(min,max) ((min)+NRAND((max)-(min)+1)) |
---|
81 | |
---|
82 | #define MINDT 0.01 |
---|
83 | #define MAXDT 0.15 |
---|
84 | |
---|
85 | #define MAXLISSIELEN 100 |
---|
86 | #define MINLISSIELEN 10 |
---|
87 | #define MINLISSIES 1 |
---|
88 | |
---|
89 | /* How many segments to draw per cycle when redrawing */ |
---|
90 | #define REDRAWSTEP 3 |
---|
91 | |
---|
92 | typedef struct { |
---|
93 | double tx, ty, dtx, dty; |
---|
94 | int xi, yi, ri, rx, ry, len, pos; |
---|
95 | int redrawing, redrawpos; |
---|
96 | XPoint loc[MAXLISSIELEN]; |
---|
97 | unsigned long color; |
---|
98 | } lissiestruct; |
---|
99 | |
---|
100 | typedef struct { |
---|
101 | Bool painted; |
---|
102 | int width, height; |
---|
103 | int nlissies; |
---|
104 | lissiestruct *lissie; |
---|
105 | int loopcount; |
---|
106 | } lissstruct; |
---|
107 | |
---|
108 | static lissstruct *lisses = (lissstruct *) NULL; |
---|
109 | |
---|
110 | |
---|
111 | static void |
---|
112 | drawlissie(ModeInfo * mi, lissiestruct * lissie) |
---|
113 | { |
---|
114 | Display *display = MI_DISPLAY(mi); |
---|
115 | GC gc = MI_GC(mi); |
---|
116 | lissstruct *lp = &lisses[MI_SCREEN(mi)]; |
---|
117 | int p = (++lissie->pos) % MAXLISSIELEN; |
---|
118 | int oldp = (lissie->pos - lissie->len + MAXLISSIELEN) % MAXLISSIELEN; |
---|
119 | |
---|
120 | /* Let time go by ... */ |
---|
121 | lissie->tx += lissie->dtx; |
---|
122 | lissie->ty += lissie->dty; |
---|
123 | if (lissie->tx > 2 * M_PI) |
---|
124 | lissie->tx -= 2 * M_PI; |
---|
125 | if (lissie->ty > 2 * M_PI) |
---|
126 | lissie->ty -= 2 * M_PI; |
---|
127 | |
---|
128 | /* vary both (x/y) speeds by max. 1% */ |
---|
129 | lissie->dtx *= FLOATRAND(0.99, 1.01); |
---|
130 | lissie->dty *= FLOATRAND(0.99, 1.01); |
---|
131 | if (lissie->dtx < MINDT) |
---|
132 | lissie->dtx = MINDT; |
---|
133 | else if (lissie->dtx > MAXDT) |
---|
134 | lissie->dtx = MAXDT; |
---|
135 | if (lissie->dty < MINDT) |
---|
136 | lissie->dty = MINDT; |
---|
137 | else if (lissie->dty > MAXDT) |
---|
138 | lissie->dty = MAXDT; |
---|
139 | |
---|
140 | lissie->loc[p].x = lissie->xi + (int) (sin(lissie->tx) * lissie->rx); |
---|
141 | lissie->loc[p].y = lissie->yi + (int) (sin(lissie->ty) * lissie->ry); |
---|
142 | |
---|
143 | /* Mask */ |
---|
144 | XSetForeground(display, gc, MI_BLACK_PIXEL(mi)); |
---|
145 | Lissie(oldp); |
---|
146 | |
---|
147 | /* Redraw */ |
---|
148 | if (MI_NPIXELS(mi) > 2) { |
---|
149 | XSetForeground(display, gc, MI_PIXEL(mi, lissie->color)); |
---|
150 | if (++lissie->color >= (unsigned) MI_NPIXELS(mi)) |
---|
151 | lissie->color = 0; |
---|
152 | } else |
---|
153 | XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); |
---|
154 | Lissie(p); |
---|
155 | if (lissie->redrawing) { |
---|
156 | int i; |
---|
157 | |
---|
158 | lissie->redrawpos++; |
---|
159 | /* This compensates for the changed p |
---|
160 | since the last callback. */ |
---|
161 | |
---|
162 | for (i = 0; i < REDRAWSTEP; i++) { |
---|
163 | Lissie((p - lissie->redrawpos + MAXLISSIELEN) % MAXLISSIELEN); |
---|
164 | if (++(lissie->redrawpos) >= lissie->len) { |
---|
165 | lissie->redrawing = 0; |
---|
166 | break; |
---|
167 | } |
---|
168 | } |
---|
169 | } |
---|
170 | } |
---|
171 | |
---|
172 | static void |
---|
173 | initlissie(ModeInfo * mi, lissiestruct * lissie) |
---|
174 | { |
---|
175 | lissstruct *lp = &lisses[MI_SCREEN(mi)]; |
---|
176 | int size = MI_SIZE(mi); |
---|
177 | int i; |
---|
178 | |
---|
179 | if (MI_NPIXELS(mi) > 2) |
---|
180 | lissie->color = NRAND(MI_NPIXELS(mi)); |
---|
181 | else |
---|
182 | lissie->color = MI_WHITE_PIXEL(mi); |
---|
183 | /* Initialize parameters */ |
---|
184 | if (size < -MINSIZE) |
---|
185 | lissie->ri = NRAND(MIN(-size, MAX(MINSIZE, |
---|
186 | MIN(lp->width, lp->height) / 4)) - MINSIZE + 1) + MINSIZE; |
---|
187 | else if (size < MINSIZE) { |
---|
188 | if (!size) |
---|
189 | lissie->ri = MAX(MINSIZE, MIN(lp->width, lp->height) / 4); |
---|
190 | else |
---|
191 | lissie->ri = MINSIZE; |
---|
192 | } else |
---|
193 | lissie->ri = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) / 4)); |
---|
194 | lissie->xi = INTRAND(lp->width / 4 + lissie->ri, |
---|
195 | lp->width * 3 / 4 - lissie->ri); |
---|
196 | lissie->yi = INTRAND(lp->height / 4 + lissie->ri, |
---|
197 | lp->height * 3 / 4 - lissie->ri); |
---|
198 | lissie->rx = INTRAND(lp->width / 4, |
---|
199 | MIN(lp->width - lissie->xi, lissie->xi)) - 2 * lissie->ri; |
---|
200 | lissie->ry = INTRAND(lp->height / 4, |
---|
201 | MIN(lp->height - lissie->yi, lissie->yi)) - 2 * lissie->ri; |
---|
202 | lissie->len = INTRAND(MINLISSIELEN, MAXLISSIELEN - 1); |
---|
203 | lissie->pos = 0; |
---|
204 | |
---|
205 | lissie->redrawing = 0; |
---|
206 | |
---|
207 | lissie->tx = FLOATRAND(0, 2 * M_PI); |
---|
208 | lissie->ty = FLOATRAND(0, 2 * M_PI); |
---|
209 | lissie->dtx = FLOATRAND(MINDT, MAXDT); |
---|
210 | lissie->dty = FLOATRAND(MINDT, MAXDT); |
---|
211 | |
---|
212 | for (i = 0; i < MAXLISSIELEN; i++) |
---|
213 | lissie->loc[i].x = lissie->loc[i].y = 0; |
---|
214 | /* Draw lissie */ |
---|
215 | drawlissie(mi, lissie); |
---|
216 | } |
---|
217 | |
---|
218 | void |
---|
219 | init_lissie(ModeInfo * mi) |
---|
220 | { |
---|
221 | lissstruct *lp; |
---|
222 | unsigned char ball; |
---|
223 | |
---|
224 | if (lisses == NULL) { |
---|
225 | if ((lisses = (lissstruct *) calloc(MI_NUM_SCREENS(mi), |
---|
226 | sizeof (lissstruct))) == NULL) |
---|
227 | return; |
---|
228 | } |
---|
229 | lp = &lisses[MI_SCREEN(mi)]; |
---|
230 | |
---|
231 | lp->width = MI_WIDTH(mi); |
---|
232 | lp->height = MI_HEIGHT(mi); |
---|
233 | |
---|
234 | lp->nlissies = MI_COUNT(mi); |
---|
235 | if (lp->nlissies < -MINLISSIES) { |
---|
236 | if (lp->lissie) { |
---|
237 | (void) free((void *) lp->lissie); |
---|
238 | lp->lissie = (lissiestruct *) NULL; |
---|
239 | } |
---|
240 | lp->nlissies = NRAND(-lp->nlissies - MINLISSIES + 1) + MINLISSIES; |
---|
241 | } else if (lp->nlissies < MINLISSIES) |
---|
242 | lp->nlissies = MINLISSIES; |
---|
243 | |
---|
244 | lp->loopcount = 0; |
---|
245 | |
---|
246 | if (lp->lissie == NULL) |
---|
247 | if ((lp->lissie = (lissiestruct *) calloc(lp->nlissies, |
---|
248 | sizeof (lissiestruct))) == NULL) |
---|
249 | return; |
---|
250 | |
---|
251 | MI_CLEARWINDOW(mi); |
---|
252 | lp->painted = False; |
---|
253 | |
---|
254 | for (ball = 0; ball < (unsigned char) lp->nlissies; ball++) |
---|
255 | initlissie(mi, &lp->lissie[ball]); |
---|
256 | |
---|
257 | } |
---|
258 | |
---|
259 | void |
---|
260 | draw_lissie(ModeInfo * mi) |
---|
261 | { |
---|
262 | register unsigned char ball; |
---|
263 | lissstruct *lp; |
---|
264 | |
---|
265 | if (lisses == NULL) |
---|
266 | return; |
---|
267 | lp = &lisses[MI_SCREEN(mi)]; |
---|
268 | if (lp->lissie == NULL) |
---|
269 | return; |
---|
270 | |
---|
271 | MI_IS_DRAWN(mi) = True; |
---|
272 | |
---|
273 | if (++lp->loopcount > MI_CYCLES(mi)) { |
---|
274 | init_lissie(mi); |
---|
275 | } else { |
---|
276 | lp->painted = True; |
---|
277 | for (ball = 0; ball < (unsigned char) lp->nlissies; ball++) |
---|
278 | drawlissie(mi, &lp->lissie[ball]); |
---|
279 | } |
---|
280 | } |
---|
281 | |
---|
282 | void |
---|
283 | release_lissie(ModeInfo * mi) |
---|
284 | { |
---|
285 | if (lisses != NULL) { |
---|
286 | int screen; |
---|
287 | |
---|
288 | for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) { |
---|
289 | lissstruct *lp = &lisses[screen]; |
---|
290 | |
---|
291 | if (lp->lissie != NULL) { |
---|
292 | (void) free((void *) lp->lissie); |
---|
293 | /* lp->lissie = NULL; */ |
---|
294 | } |
---|
295 | } |
---|
296 | (void) free((void *) lisses); |
---|
297 | lisses = (lissstruct *) NULL; |
---|
298 | } |
---|
299 | } |
---|
300 | |
---|
301 | void |
---|
302 | refresh_lissie(ModeInfo * mi) |
---|
303 | { |
---|
304 | int i; |
---|
305 | lissstruct *lp; |
---|
306 | |
---|
307 | if (lisses == NULL) |
---|
308 | return; |
---|
309 | lp = &lisses[MI_SCREEN(mi)]; |
---|
310 | if (lp->lissie == NULL) |
---|
311 | return; |
---|
312 | |
---|
313 | if (lp->painted) { |
---|
314 | MI_CLEARWINDOW(mi); |
---|
315 | for (i = 0; i < lp->nlissies; i++) { |
---|
316 | lp->lissie[i].redrawing = 1; |
---|
317 | lp->lissie[i].redrawpos = 0; |
---|
318 | } |
---|
319 | } |
---|
320 | } |
---|
321 | |
---|
322 | #endif /* MODE_lissie */ |
---|