1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* lissie --- the Lissajous worm */
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)lissie.c 5.00 2000/11/01 xlockmore";
10 * lissie.c - The Lissajous worm for xlock, the X Window System
13 * Copyright (c) 1996 by Alexander Jolk <ub9x@rz.uni-karlsruhe.de>
15 * Permission to use, copy, modify, and distribute this software and its
16 * documentation for any purpose and without fee is hereby granted,
17 * provided that the above copyright notice appear in all copies and that
18 * both that copyright notice and this permission notice appear in
19 * supporting documentation.
21 * This file is provided AS IS with no warranties of any kind. The author
22 * shall have no liability with respect to the infringement of copyrights,
23 * trade secrets or any patents by this file or any part thereof. In no
24 * event will the author be liable for any lost revenue or profits or
25 * other special, indirect and consequential damages.
28 * 01-Nov-2000: Allocation checks
29 * 10-May-1997: Compatible with xscreensaver
30 * 18-Aug-1996: added refresh-hook.
31 * 01-May-1996: written.
36 #define PROGCLASS "Lissie"
37 #define HACK_INIT init_lissie
38 #define HACK_DRAW draw_lissie
39 #define lissie_opts xlockmore_opts
40 #define DEFAULTS "*delay: 10000 \n" \
46 #include "xlockmore.h" /* in xscreensaver distribution */
47 #else /* STANDALONE */
48 #include "xlock.h" /* in xlockmore distribution */
49 #endif /* STANDALONE */
53 ModeSpecOpt lissie_opts =
54 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
57 ModStruct lissie_description =
58 {"lissie", "init_lissie", "draw_lissie", "release_lissie",
59 "refresh_lissie", "init_lissie", (char *) NULL, &lissie_opts,
60 10000, 1, 2000, -200, 64, 0.6, "",
61 "Shows lissajous worms", 0, NULL};
68 if (lissie->loc[(n)].x > 0 && lissie->loc[(n)].y > 0 &&\
69 lissie->loc[(n)].x <= lp->width && lissie->loc[(n)].y <= lp->height) {\
71 XDrawPoint(display, MI_WINDOW(mi),\
72 gc, lissie->loc[(n)].x, lissie->loc[(n)].y);\
74 XDrawArc(display, MI_WINDOW(mi), gc,\
75 lissie->loc[(n)].x - lissie->ri / 2,\
76 lissie->loc[(n)].y - lissie->ri / 2,\
77 lissie->ri, lissie->ri, 0, 23040);\
80 #define FLOATRAND(min,max) ((min)+(LRAND()/MAXRAND)*((max)-(min)))
81 #define INTRAND(min,max) ((min)+NRAND((max)-(min)+1))
86 #define MAXLISSIELEN 100
87 #define MINLISSIELEN 10
90 /* How many segments to draw per cycle when redrawing */
94 double tx, ty, dtx, dty;
95 int xi, yi, ri, rx, ry, len, pos;
96 int redrawing, redrawpos;
97 XPoint loc[MAXLISSIELEN];
105 lissiestruct *lissie;
109 static lissstruct *lisses = (lissstruct *) NULL;
113 drawlissie(ModeInfo * mi, lissiestruct * lissie)
115 Display *display = MI_DISPLAY(mi);
117 lissstruct *lp = &lisses[MI_SCREEN(mi)];
118 int p = (++lissie->pos) % MAXLISSIELEN;
119 int oldp = (lissie->pos - lissie->len + MAXLISSIELEN) % MAXLISSIELEN;
121 /* Let time go by ... */
122 lissie->tx += lissie->dtx;
123 lissie->ty += lissie->dty;
124 if (lissie->tx > 2 * M_PI)
125 lissie->tx -= 2 * M_PI;
126 if (lissie->ty > 2 * M_PI)
127 lissie->ty -= 2 * M_PI;
129 /* vary both (x/y) speeds by max. 1% */
130 lissie->dtx *= FLOATRAND(0.99, 1.01);
131 lissie->dty *= FLOATRAND(0.99, 1.01);
132 if (lissie->dtx < MINDT)
134 else if (lissie->dtx > MAXDT)
136 if (lissie->dty < MINDT)
138 else if (lissie->dty > MAXDT)
141 lissie->loc[p].x = lissie->xi + (int) (sin(lissie->tx) * lissie->rx);
142 lissie->loc[p].y = lissie->yi + (int) (sin(lissie->ty) * lissie->ry);
145 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
149 if (MI_NPIXELS(mi) > 2) {
150 XSetForeground(display, gc, MI_PIXEL(mi, lissie->color));
151 if (++lissie->color >= (unsigned) MI_NPIXELS(mi))
154 XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
156 if (lissie->redrawing) {
160 /* This compensates for the changed p
161 since the last callback. */
163 for (i = 0; i < REDRAWSTEP; i++) {
164 Lissie((p - lissie->redrawpos + MAXLISSIELEN) % MAXLISSIELEN);
165 if (++(lissie->redrawpos) >= lissie->len) {
166 lissie->redrawing = 0;
174 initlissie(ModeInfo * mi, lissiestruct * lissie)
176 lissstruct *lp = &lisses[MI_SCREEN(mi)];
177 int size = MI_SIZE(mi);
180 if (MI_NPIXELS(mi) > 2)
181 lissie->color = NRAND(MI_NPIXELS(mi));
183 lissie->color = MI_WHITE_PIXEL(mi);
184 /* Initialize parameters */
186 lissie->ri = NRAND(MIN(-size, MAX(MINSIZE,
187 MIN(lp->width, lp->height) / 4)) - MINSIZE + 1) + MINSIZE;
188 else if (size < MINSIZE) {
190 lissie->ri = MAX(MINSIZE, MIN(lp->width, lp->height) / 4);
192 lissie->ri = MINSIZE;
194 lissie->ri = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) / 4));
195 lissie->xi = INTRAND(lp->width / 4 + lissie->ri,
196 lp->width * 3 / 4 - lissie->ri);
197 lissie->yi = INTRAND(lp->height / 4 + lissie->ri,
198 lp->height * 3 / 4 - lissie->ri);
199 lissie->rx = INTRAND(lp->width / 4,
200 MIN(lp->width - lissie->xi, lissie->xi)) - 2 * lissie->ri;
201 lissie->ry = INTRAND(lp->height / 4,
202 MIN(lp->height - lissie->yi, lissie->yi)) - 2 * lissie->ri;
203 lissie->len = INTRAND(MINLISSIELEN, MAXLISSIELEN - 1);
206 lissie->redrawing = 0;
208 lissie->tx = FLOATRAND(0, 2 * M_PI);
209 lissie->ty = FLOATRAND(0, 2 * M_PI);
210 lissie->dtx = FLOATRAND(MINDT, MAXDT);
211 lissie->dty = FLOATRAND(MINDT, MAXDT);
213 for (i = 0; i < MAXLISSIELEN; i++)
214 lissie->loc[i].x = lissie->loc[i].y = 0;
216 drawlissie(mi, lissie);
220 init_lissie(ModeInfo * mi)
225 if (lisses == NULL) {
226 if ((lisses = (lissstruct *) calloc(MI_NUM_SCREENS(mi),
227 sizeof (lissstruct))) == NULL)
230 lp = &lisses[MI_SCREEN(mi)];
232 lp->width = MI_WIDTH(mi);
233 lp->height = MI_HEIGHT(mi);
235 lp->nlissies = MI_COUNT(mi);
236 if (lp->nlissies < -MINLISSIES) {
238 (void) free((void *) lp->lissie);
239 lp->lissie = (lissiestruct *) NULL;
241 lp->nlissies = NRAND(-lp->nlissies - MINLISSIES + 1) + MINLISSIES;
242 } else if (lp->nlissies < MINLISSIES)
243 lp->nlissies = MINLISSIES;
247 if (lp->lissie == NULL)
248 if ((lp->lissie = (lissiestruct *) calloc(lp->nlissies,
249 sizeof (lissiestruct))) == NULL)
255 for (ball = 0; ball < (unsigned char) lp->nlissies; ball++)
256 initlissie(mi, &lp->lissie[ball]);
261 draw_lissie(ModeInfo * mi)
263 register unsigned char ball;
268 lp = &lisses[MI_SCREEN(mi)];
269 if (lp->lissie == NULL)
272 MI_IS_DRAWN(mi) = True;
274 if (++lp->loopcount > MI_CYCLES(mi)) {
278 for (ball = 0; ball < (unsigned char) lp->nlissies; ball++)
279 drawlissie(mi, &lp->lissie[ball]);
284 release_lissie(ModeInfo * mi)
286 if (lisses != NULL) {
289 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
290 lissstruct *lp = &lisses[screen];
292 if (lp->lissie != NULL) {
293 (void) free((void *) lp->lissie);
294 /* lp->lissie = NULL; */
297 (void) free((void *) lisses);
298 lisses = (lissstruct *) NULL;
303 refresh_lissie(ModeInfo * mi)
310 lp = &lisses[MI_SCREEN(mi)];
311 if (lp->lissie == NULL)
316 for (i = 0; i < lp->nlissies; i++) {
317 lp->lissie[i].redrawing = 1;
318 lp->lissie[i].redrawpos = 0;
323 #endif /* MODE_lissie */