1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* lissie --- the Lissajous worm */
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)lissie.c 4.04 97/07/28 xlockmore";
9 * lissie.c - The Lissajous worm for xlock, the X Window System
12 * Copyright (c) 1996 by Alexander Jolk <ub9x@rz.uni-karlsruhe.de>
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.
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.
27 * 10-May-97: Compatible with xscreensaver
28 * 18-Aug-96: added refresh-hook.
33 # define PROGCLASS "Lissie"
34 # define HACK_INIT init_lissie
35 # define HACK_DRAW draw_lissie
36 # define lissie_opts xlockmore_opts
37 # define DEFAULTS "*delay: 10000 \n" \
42 # define SMOOTH_COLORS
43 # include "xlockmore.h" /* in xscreensaver distribution */
44 #else /* STANDALONE */
45 # include "xlock.h" /* in xlockmore distribution */
46 #endif /* STANDALONE */
48 ModeSpecOpt lissie_opts =
49 {0, NULL, 0, NULL, NULL};
54 if (lissie->loc[(n)].x > 0 && lissie->loc[(n)].y > 0 &&\
55 lissie->loc[(n)].x <= lp->width && lissie->loc[(n)].y <= lp->height) {\
57 XDrawPoint(display, MI_WINDOW(mi),\
58 gc, lissie->loc[(n)].x, lissie->loc[(n)].y);\
60 XDrawArc(display, MI_WINDOW(mi), gc,\
61 lissie->loc[(n)].x - lissie->ri / 2,\
62 lissie->loc[(n)].y - lissie->ri / 2,\
63 lissie->ri, lissie->ri, 0, 23040);\
66 #define FLOATRAND(min,max) ((min)+(LRAND()/MAXRAND)*((max)-(min)))
67 #define INTRAND(min,max) ((min)+NRAND((max)-(min)+1))
72 #define MAXLISSIELEN 100
73 #define MINLISSIELEN 10
76 /* How many segments to draw per cycle when redrawing */
80 double tx, ty, dtx, dty;
81 int xi, yi, ri, rx, ry, len, pos;
82 int redrawing, redrawpos;
83 XPoint loc[MAXLISSIELEN];
94 static lissstruct *lisses = NULL;
98 drawlissie(ModeInfo * mi, lissiestruct * lissie)
100 Display *display = MI_DISPLAY(mi);
102 lissstruct *lp = &lisses[MI_SCREEN(mi)];
103 int p = (++lissie->pos) % MAXLISSIELEN;
104 int oldp = (lissie->pos - lissie->len + MAXLISSIELEN) % MAXLISSIELEN;
106 /* Let time go by ... */
107 lissie->tx += lissie->dtx;
108 lissie->ty += lissie->dty;
109 if (lissie->tx > 2 * M_PI)
110 lissie->tx -= 2 * M_PI;
111 if (lissie->ty > 2 * M_PI)
112 lissie->ty -= 2 * M_PI;
114 /* vary both (x/y) speeds by max. 1% */
115 lissie->dtx *= FLOATRAND(0.99, 1.01);
116 lissie->dty *= FLOATRAND(0.99, 1.01);
117 if (lissie->dtx < MINDT)
119 else if (lissie->dtx > MAXDT)
121 if (lissie->dty < MINDT)
123 else if (lissie->dty > MAXDT)
126 lissie->loc[p].x = lissie->xi + (int) (sin(lissie->tx) * lissie->rx);
127 lissie->loc[p].y = lissie->yi + (int) (sin(lissie->ty) * lissie->ry);
130 XSetForeground(display, gc, MI_WIN_BLACK_PIXEL(mi));
134 if (MI_NPIXELS(mi) > 2) {
135 XSetForeground(display, gc, MI_PIXEL(mi, lissie->color));
136 if (++lissie->color >= MI_NPIXELS(mi))
139 XSetForeground(display, gc, MI_WIN_WHITE_PIXEL(mi));
141 if (lissie->redrawing) {
145 /* This compensates for the changed p
146 since the last callback. */
148 for (i = 0; i < REDRAWSTEP; i++) {
149 Lissie((p - lissie->redrawpos + MAXLISSIELEN) % MAXLISSIELEN);
150 if (++(lissie->redrawpos) >= lissie->len) {
151 lissie->redrawing = 0;
159 initlissie(ModeInfo * mi, lissiestruct * lissie)
161 lissstruct *lp = &lisses[MI_SCREEN(mi)];
162 int size = MI_SIZE(mi);
165 if (MI_NPIXELS(mi) > 2)
166 lissie->color = NRAND(MI_NPIXELS(mi));
168 lissie->color = MI_WIN_WHITE_PIXEL(mi);
169 /* Initialize parameters */
171 lissie->ri = NRAND(MIN(-size, MAX(MINSIZE,
172 MIN(lp->width, lp->height) / 4)) - MINSIZE + 1) + MINSIZE;
173 else if (size < MINSIZE) {
175 lissie->ri = MAX(MINSIZE, MIN(lp->width, lp->height) / 4);
177 lissie->ri = MINSIZE;
179 lissie->ri = MIN(size, MAX(MINSIZE, MIN(lp->width, lp->height) / 4));
180 lissie->xi = INTRAND(lp->width / 4 + lissie->ri,
181 lp->width * 3 / 4 - lissie->ri);
182 lissie->yi = INTRAND(lp->height / 4 + lissie->ri,
183 lp->height * 3 / 4 - lissie->ri);
184 lissie->rx = INTRAND(lp->width / 4,
185 MIN(lp->width - lissie->xi, lissie->xi)) - 2 * lissie->ri;
186 lissie->ry = INTRAND(lp->height / 4,
187 MIN(lp->height - lissie->yi, lissie->yi)) - 2 * lissie->ri;
188 lissie->len = INTRAND(MINLISSIELEN, MAXLISSIELEN - 1);
191 lissie->redrawing = 0;
193 lissie->tx = FLOATRAND(0, 2 * M_PI);
194 lissie->ty = FLOATRAND(0, 2 * M_PI);
195 lissie->dtx = FLOATRAND(MINDT, MAXDT);
196 lissie->dty = FLOATRAND(MINDT, MAXDT);
198 for (i = 0; i < MAXLISSIELEN; i++)
199 lissie->loc[i].x = lissie->loc[i].y = 0;
201 drawlissie(mi, lissie);
205 init_lissie(ModeInfo * mi)
210 if (lisses == NULL) {
211 if ((lisses = (lissstruct *) calloc(MI_NUM_SCREENS(mi),
212 sizeof (lissstruct))) == NULL)
215 lp = &lisses[MI_SCREEN(mi)];
217 lp->width = MI_WIN_WIDTH(mi);
218 lp->height = MI_WIN_HEIGHT(mi);
220 lp->nlissies = MI_BATCHCOUNT(mi);
221 if (lp->nlissies < -MINLISSIES) {
223 (void) free((void *) lp->lissie);
226 lp->nlissies = NRAND(-lp->nlissies - MINLISSIES + 1) + MINLISSIES;
227 } else if (lp->nlissies < MINLISSIES)
228 lp->nlissies = MINLISSIES;
233 lp->lissie = (lissiestruct *) calloc(lp->nlissies, sizeof (lissiestruct));
234 XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi));
235 for (ball = 0; ball < (unsigned char) lp->nlissies; ball++)
236 initlissie(mi, &lp->lissie[ball]);
241 draw_lissie(ModeInfo * mi)
243 lissstruct *lp = &lisses[MI_SCREEN(mi)];
244 register unsigned char ball;
246 if (++lp->loopcount > MI_CYCLES(mi))
249 for (ball = 0; ball < (unsigned char) lp->nlissies; ball++)
250 drawlissie(mi, &lp->lissie[ball]);
254 release_lissie(ModeInfo * mi)
256 if (lisses != NULL) {
259 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
260 lissstruct *lp = &lisses[screen];
263 (void) free((void *) lp->lissie);
267 (void) free((void *) lisses);
273 refresh_lissie(ModeInfo * mi)
275 if (lisses != NULL) {
276 lissstruct *lp = &lisses[MI_SCREEN(mi)];
279 for (i = 0; i < lp->nlissies; i++) {
280 lp->lissie[i].redrawing = 1;
281 lp->lissie[i].redrawpos = 0;