1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* rotor --- a swirly rotor */
4 #if !defined( lint ) && !defined( SABER )
5 static const char sccsid[] = "@(#)rotor.c 5.00 2000/11/01 xlockmore";
10 * Copyright (c) 1991 by Patrick J. Naughton.
12 * Permission to use, copy, modify, and distribute this software and its
13 * documentation for any purpose and without fee is hereby granted,
14 * provided that the above copyright notice appear in all copies and that
15 * both that copyright notice and this permission notice appear in
16 * supporting documentation.
18 * This file is provided AS IS with no warranties of any kind. The author
19 * shall have no liability with respect to the infringement of copyrights,
20 * trade secrets or any patents by this file or any part thereof. In no
21 * event will the author be liable for any lost revenue or profits or
22 * other special, indirect and consequential damages.
25 * 01-Nov-2000: Allocation checks
26 * 10-May-1997: Compatible with xscreensaver
27 * 08-Mar-1995: CAT stuff for ## was tripping up some C compilers. Removed.
28 * 01-Dec-1993: added patch for AIXV3 from Tom McConnell
29 * <tmcconne@sedona.intel.com>
30 * 11-Nov-1990: put into xlock by Steve Zellers <zellers@sun.com>
31 * 16-Oct-1990: Received from Tom Lawrence (tcl@cs.brown.edu: 'flight'
37 #define PROGCLASS "Rotor"
38 #define HACK_INIT init_rotor
39 #define HACK_DRAW draw_rotor
40 #define rotor_opts xlockmore_opts
41 #define DEFAULTS "*delay: 10000 \n" \
47 #include "xlockmore.h" /* in xscreensaver distribution */
48 #else /* STANDALONE */
49 #include "xlock.h" /* in xlockmore distribution */
50 #endif /* STANDALONE */
54 ModeSpecOpt rotor_opts =
55 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
58 ModStruct rotor_description =
59 {"rotor", "init_rotor", "draw_rotor", "release_rotor",
60 "refresh_rotor", "init_rotor", (char *) NULL, &rotor_opts,
61 100, 4, 100, -6, 64, 0.3, "",
62 "Shows Tom's Roto-Rooter", 0, NULL};
67 * A 'batchcount' of 3 or 4 works best!
70 #define MAXANGLE 3000.0 /* irrectangular (was 10000.0) */
72 /* How many segments to draw per cycle when redrawing */
80 float radius_drift_max;
81 float radius_drift_now;
86 float ratio_drift_max;
87 float ratio_drift_now;
97 int prevcenterx, prevcentery;
98 unsigned char firsttime;
99 unsigned char iconifiedscreen; /* for iconified view */
100 unsigned char forward;
101 unsigned char unused;
104 int redrawing, redrawpos;
108 static rotorstruct *rotors = (rotorstruct *) NULL;
111 free_rotor(rotorstruct *rp)
113 if (rp->elements != NULL) {
114 (void) free((void *) rp->elements);
115 rp->elements = (elem *) NULL;
117 if (rp->save != NULL) {
118 (void) free((void *) rp->save);
119 rp->save = (XPoint *) NULL;
124 init_rotor(ModeInfo * mi)
128 unsigned char wasiconified;
131 if (rotors == NULL) {
132 if ((rotors = (rotorstruct *) calloc(MI_NUM_SCREENS(mi),
133 sizeof (rotorstruct))) == NULL)
136 rp = &rotors[MI_SCREEN(mi)];
138 rp->prevcenterx = rp->centerx;
139 rp->prevcentery = rp->centery;
141 rp->centerx = MI_WIDTH(mi) / 2;
142 rp->centery = MI_HEIGHT(mi) / 2;
146 * sometimes, you go into iconified view, only to see a really whizzy pattern
147 * that you would like to look more closely at. Normally, clicking in the
148 * icon reinitializes everything - but I don't, cuz I'm that kind of guy.
149 * HENCE, the wasiconified stuff you see here.
152 wasiconified = rp->iconifiedscreen;
153 rp->iconifiedscreen = MI_IS_ICONIC(mi);
155 if (wasiconified && !rp->iconifiedscreen)
156 rp->firsttime = True;
159 /* This is a fudge is needed since prevcenter may not be set when it comes
160 from the the random mode and return is pressed (and its not the first
161 mode that was running). This assumes that the size of the lock screen
162 window / size of the icon window = 12 */
163 if (!rp->prevcenterx)
164 rp->prevcenterx = rp->centerx * 12;
165 if (!rp->prevcentery)
166 rp->prevcentery = rp->centery * 12;
168 rp->num = MI_COUNT(mi);
170 rp->num = NRAND(-rp->num) + 1;
171 if (rp->elements != NULL) {
172 (void) free((void *) rp->elements);
173 rp->elements = (elem *) NULL;
176 if (rp->elements == NULL)
177 if ((rp->elements = (elem *) calloc(rp->num,
178 sizeof (elem))) == NULL) {
182 rp->nsave = MI_CYCLES(mi);
185 if (rp->save == NULL)
186 if ((rp->save = (XPoint *) malloc(rp->nsave *
187 sizeof (XPoint))) == NULL) {
191 for (x = 0; x < rp->nsave; x++) {
192 rp->save[x].x = rp->centerx;
193 rp->save[x].y = rp->centery;
196 pelem = rp->elements;
198 for (x = rp->num; --x >= 0; pelem++) {
199 pelem->radius_drift_max = 1.0;
200 pelem->radius_drift_now = 1.0;
202 pelem->end_radius = 100.0;
204 pelem->ratio_drift_max = 1.0;
205 pelem->ratio_drift_now = 1.0;
206 pelem->end_ratio = 10.0;
208 if (MI_NPIXELS(mi) > 2)
209 rp->pix = NRAND(MI_NPIXELS(mi));
213 rp->lastx = rp->centerx;
214 rp->lasty = rp->centery;
215 rp->angle = (float) NRAND((long) MAXANGLE) / 3.0;
216 rp->forward = rp->firsttime = True;
218 rp->linewidth = MI_SIZE(mi);
220 if (rp->linewidth == 0)
222 if (rp->linewidth < 0)
223 rp->linewidth = NRAND(-rp->linewidth) + 1;
229 draw_rotor(ModeInfo * mi)
231 Display *display = MI_DISPLAY(mi);
233 register elem *pelem;
236 int x_1, y_1, x_2, y_2;
241 rp = &rotors[MI_SCREEN(mi)];
242 if (rp->elements == NULL)
245 MI_IS_DRAWN(mi) = True;
246 if (!rp->iconifiedscreen) {
250 thisx = rp->prevcenterx;
251 thisy = rp->prevcentery;
253 XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), rp->linewidth,
254 LineSolid, CapButt, JoinMiter);
255 for (i = rp->num, pelem = rp->elements; --i >= 0; pelem++) {
256 if (pelem->radius_drift_max <= pelem->radius_drift_now) {
257 pelem->start_radius = pelem->end_radius;
258 pelem->end_radius = (float) NRAND(40000) / 100.0 - 200.0;
259 pelem->radius_drift_max = (float) NRAND(100000) + 10000.0;
260 pelem->radius_drift_now = 0.0;
262 if (pelem->ratio_drift_max <= pelem->ratio_drift_now) {
263 pelem->start_ratio = pelem->end_ratio;
264 pelem->end_ratio = (float) NRAND(2000) / 100.0 - 10.0;
265 pelem->ratio_drift_max = (float) NRAND(100000) + 10000.0;
266 pelem->ratio_drift_now = 0.0;
268 pelem->ratio = pelem->start_ratio +
269 (pelem->end_ratio - pelem->start_ratio) /
270 pelem->ratio_drift_max * pelem->ratio_drift_now;
271 pelem->angle = rp->angle * pelem->ratio;
272 pelem->radius = pelem->start_radius +
273 (pelem->end_radius - pelem->start_radius) /
274 pelem->radius_drift_max * pelem->radius_drift_now;
276 thisx += (int) (COSF(pelem->angle) * pelem->radius);
277 thisy += (int) (SINF(pelem->angle) * pelem->radius);
279 pelem->ratio_drift_now += 1.0;
280 pelem->radius_drift_now += 1.0;
283 rp->firsttime = False;
285 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
287 x_1 = (int) rp->save[rp->rotor].x;
288 y_1 = (int) rp->save[rp->rotor].y;
289 x_2 = (int) rp->save[rp->prev].x;
290 y_2 = (int) rp->save[rp->prev].y;
292 if (rp->iconifiedscreen) {
293 x_1 = x_1 * rp->centerx / rp->prevcenterx;
294 x_2 = x_2 * rp->centerx / rp->prevcenterx;
295 y_1 = y_1 * rp->centery / rp->prevcentery;
296 y_2 = y_2 * rp->centery / rp->prevcentery;
298 XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2);
300 if (MI_NPIXELS(mi) > 2) {
301 XSetForeground(display, gc, MI_PIXEL(mi, rp->pix));
302 if (++rp->pix >= MI_NPIXELS(mi))
305 XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
312 if (rp->iconifiedscreen) {
313 x_1 = x_1 * rp->centerx / rp->prevcenterx;
314 x_2 = x_2 * rp->centerx / rp->prevcenterx;
315 y_1 = y_1 * rp->centery / rp->prevcentery;
316 y_2 = y_2 * rp->centery / rp->prevcentery;
318 XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2);
320 rp->save[rp->rotor].x = rp->lastx = thisx;
321 rp->save[rp->rotor].y = rp->lasty = thisy;
324 rp->rotor %= rp->nsave;
326 rp->prev %= rp->nsave;
329 if (rp->angle >= MAXANGLE) {
330 rp->angle = MAXANGLE;
335 if (rp->angle <= 0) {
343 for (i = 0; i < REDRAWSTEP; i++) {
344 j = (rp->rotor - rp->redrawpos + rp->nsave) % rp->nsave;
346 x_1 = (int) rp->save[j].x;
347 y_1 = (int) rp->save[j].y;
348 x_2 = (int) rp->save[(j - 1 + rp->nsave) % rp->nsave].x;
349 y_2 = (int) rp->save[(j - 1 + rp->nsave) % rp->nsave].y;
351 if (rp->iconifiedscreen) {
352 x_1 = x_1 * rp->centerx / rp->prevcenterx;
353 x_2 = x_2 * rp->centerx / rp->prevcenterx;
354 y_1 = y_1 * rp->centery / rp->prevcentery;
355 y_2 = y_2 * rp->centery / rp->prevcentery;
357 XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2);
359 if (++(rp->redrawpos) >= rp->nsave) {
365 XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 1,
366 LineSolid, CapButt, JoinMiter);
370 release_rotor(ModeInfo * mi)
372 if (rotors != NULL) {
375 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
376 free_rotor(&rotors[screen]);
377 (void) free((void *) rotors);
378 rotors = (rotorstruct *) NULL;
383 refresh_rotor(ModeInfo * mi)
389 rp = &rotors[MI_SCREEN(mi)];
396 #endif /* MODE_rotor */