1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* rotor --- a swirly rotor */
5 static const char sccsid[] = "@(#)rotor.c 5.00 2000/11/01 xlockmore";
9 * Copyright (c) 1991 by Patrick J. Naughton.
11 * Permission to use, copy, modify, and distribute this software and its
12 * documentation for any purpose and without fee is hereby granted,
13 * provided that the above copyright notice appear in all copies and that
14 * both that copyright notice and this permission notice appear in
15 * supporting documentation.
17 * This file is provided AS IS with no warranties of any kind. The author
18 * shall have no liability with respect to the infringement of copyrights,
19 * trade secrets or any patents by this file or any part thereof. In no
20 * event will the author be liable for any lost revenue or profits or
21 * other special, indirect and consequential damages.
24 * 01-Nov-2000: Allocation checks
25 * 10-May-1997: Compatible with xscreensaver
26 * 08-Mar-1995: CAT stuff for ## was tripping up some C compilers. Removed.
27 * 01-Dec-1993: added patch for AIXV3 from Tom McConnell
28 * <tmcconne@sedona.intel.com>
29 * 11-Nov-1990: put into xlock by Steve Zellers <zellers@sun.com>
30 * 16-Oct-1990: Received from Tom Lawrence (tcl@cs.brown.edu: 'flight'
36 #define DEFAULTS "*delay: 10000 \n" \
41 "*fpsSolid: true \n" \
43 # define SMOOTH_COLORS
44 # define reshape_rotor 0
45 # define rotor_handle_event 0
46 # include "xlockmore.h" /* in xscreensaver distribution */
47 #else /* STANDALONE */
48 # include "xlock.h" /* in xlockmore distribution */
49 #endif /* STANDALONE */
53 ENTRYPOINT ModeSpecOpt rotor_opts =
54 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
57 ModStruct rotor_description =
58 {"rotor", "init_rotor", "draw_rotor", "release_rotor",
59 "refresh_rotor", "init_rotor", (char *) NULL, &rotor_opts,
60 100, 4, 100, -6, 64, 0.3, "",
61 "Shows Tom's Roto-Rooter", 0, NULL};
66 * A 'batchcount' of 3 or 4 works best!
69 #define MAXANGLE 3000.0 /* irrectangular (was 10000.0) */
71 /* How many segments to draw per cycle when redrawing */
79 float radius_drift_max;
80 float radius_drift_now;
85 float ratio_drift_max;
86 float ratio_drift_now;
96 int prevcenterx, prevcentery;
97 unsigned char firsttime;
98 unsigned char iconifiedscreen; /* for iconified view */
99 unsigned char forward;
100 unsigned char unused;
103 int redrawing, redrawpos;
107 static rotorstruct *rotors = (rotorstruct *) NULL;
110 free_rotor(rotorstruct *rp)
112 if (rp->elements != NULL) {
113 (void) free((void *) rp->elements);
114 rp->elements = (elem *) NULL;
116 if (rp->save != NULL) {
117 (void) free((void *) rp->save);
118 rp->save = (XPoint *) NULL;
123 init_rotor (ModeInfo * mi)
127 unsigned char wasiconified;
130 if (rotors == NULL) {
131 if ((rotors = (rotorstruct *) calloc(MI_NUM_SCREENS(mi),
132 sizeof (rotorstruct))) == NULL)
135 rp = &rotors[MI_SCREEN(mi)];
138 jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi), False);
141 rp->prevcenterx = rp->centerx;
142 rp->prevcentery = rp->centery;
144 rp->centerx = MI_WIDTH(mi) / 2;
145 rp->centery = MI_HEIGHT(mi) / 2;
149 * sometimes, you go into iconified view, only to see a really whizzy pattern
150 * that you would like to look more closely at. Normally, clicking in the
151 * icon reinitializes everything - but I don't, cuz I'm that kind of guy.
152 * HENCE, the wasiconified stuff you see here.
155 wasiconified = rp->iconifiedscreen;
156 rp->iconifiedscreen = MI_IS_ICONIC(mi);
158 if (wasiconified && !rp->iconifiedscreen)
159 rp->firsttime = True;
162 /* This is a fudge is needed since prevcenter may not be set when it comes
163 from the the random mode and return is pressed (and its not the first
164 mode that was running). This assumes that the size of the lock screen
165 window / size of the icon window = 12 */
166 if (!rp->prevcenterx)
167 rp->prevcenterx = rp->centerx * 12;
168 if (!rp->prevcentery)
169 rp->prevcentery = rp->centery * 12;
171 rp->num = MI_COUNT(mi);
173 rp->num = NRAND(-rp->num) + 1;
174 if (rp->elements != NULL) {
175 (void) free((void *) rp->elements);
176 rp->elements = (elem *) NULL;
179 if (rp->elements == NULL)
180 if ((rp->elements = (elem *) calloc(rp->num,
181 sizeof (elem))) == NULL) {
185 rp->nsave = MI_CYCLES(mi);
188 if (rp->save == NULL)
189 if ((rp->save = (XPoint *) malloc(rp->nsave *
190 sizeof (XPoint))) == NULL) {
194 for (x = 0; x < rp->nsave; x++) {
195 rp->save[x].x = rp->centerx;
196 rp->save[x].y = rp->centery;
199 pelem = rp->elements;
201 for (x = rp->num; --x >= 0; pelem++) {
202 pelem->radius_drift_max = 1.0;
203 pelem->radius_drift_now = 1.0;
205 pelem->end_radius = 100.0;
207 pelem->ratio_drift_max = 1.0;
208 pelem->ratio_drift_now = 1.0;
209 pelem->end_ratio = 10.0;
211 if (MI_NPIXELS(mi) > 2)
212 rp->pix = NRAND(MI_NPIXELS(mi));
216 rp->lastx = rp->centerx;
217 rp->lasty = rp->centery;
218 rp->angle = (float) NRAND((long) MAXANGLE) / 3.0;
219 rp->forward = rp->firsttime = True;
221 rp->linewidth = MI_SIZE(mi);
223 if (rp->linewidth == 0)
225 if (rp->linewidth < 0)
226 rp->linewidth = NRAND(-rp->linewidth) + 1;
232 draw_rotor (ModeInfo * mi)
234 Display *display = MI_DISPLAY(mi);
236 register elem *pelem;
239 int x_1, y_1, x_2, y_2;
244 rp = &rotors[MI_SCREEN(mi)];
245 if (rp->elements == NULL)
248 MI_IS_DRAWN(mi) = True;
249 if (!rp->iconifiedscreen) {
253 thisx = rp->prevcenterx;
254 thisy = rp->prevcentery;
256 XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), rp->linewidth,
257 LineSolid, CapButt, JoinMiter);
258 for (i = rp->num, pelem = rp->elements; --i >= 0; pelem++) {
259 if (pelem->radius_drift_max <= pelem->radius_drift_now) {
260 pelem->start_radius = pelem->end_radius;
261 pelem->end_radius = (float) NRAND(40000) / 100.0 - 200.0;
262 pelem->radius_drift_max = (float) NRAND(100000) + 10000.0;
263 pelem->radius_drift_now = 0.0;
265 if (pelem->ratio_drift_max <= pelem->ratio_drift_now) {
266 pelem->start_ratio = pelem->end_ratio;
267 pelem->end_ratio = (float) NRAND(2000) / 100.0 - 10.0;
268 pelem->ratio_drift_max = (float) NRAND(100000) + 10000.0;
269 pelem->ratio_drift_now = 0.0;
271 pelem->ratio = pelem->start_ratio +
272 (pelem->end_ratio - pelem->start_ratio) /
273 pelem->ratio_drift_max * pelem->ratio_drift_now;
274 pelem->angle = rp->angle * pelem->ratio;
275 pelem->radius = pelem->start_radius +
276 (pelem->end_radius - pelem->start_radius) /
277 pelem->radius_drift_max * pelem->radius_drift_now;
279 thisx += (int) (COSF(pelem->angle) * pelem->radius);
280 thisy += (int) (SINF(pelem->angle) * pelem->radius);
282 pelem->ratio_drift_now += 1.0;
283 pelem->radius_drift_now += 1.0;
286 rp->firsttime = False;
288 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
290 x_1 = (int) rp->save[rp->rotor].x;
291 y_1 = (int) rp->save[rp->rotor].y;
292 x_2 = (int) rp->save[rp->prev].x;
293 y_2 = (int) rp->save[rp->prev].y;
295 if (rp->iconifiedscreen) {
296 x_1 = x_1 * rp->centerx / rp->prevcenterx;
297 x_2 = x_2 * rp->centerx / rp->prevcenterx;
298 y_1 = y_1 * rp->centery / rp->prevcentery;
299 y_2 = y_2 * rp->centery / rp->prevcentery;
301 XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2);
303 if (MI_NPIXELS(mi) > 2) {
304 XSetForeground(display, gc, MI_PIXEL(mi, rp->pix));
305 if (++rp->pix >= MI_NPIXELS(mi))
308 XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
315 if (rp->iconifiedscreen) {
316 x_1 = x_1 * rp->centerx / rp->prevcenterx;
317 x_2 = x_2 * rp->centerx / rp->prevcenterx;
318 y_1 = y_1 * rp->centery / rp->prevcentery;
319 y_2 = y_2 * rp->centery / rp->prevcentery;
321 XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2);
323 rp->save[rp->rotor].x = rp->lastx = thisx;
324 rp->save[rp->rotor].y = rp->lasty = thisy;
327 rp->rotor %= rp->nsave;
329 rp->prev %= rp->nsave;
332 if (rp->angle >= MAXANGLE) {
333 rp->angle = MAXANGLE;
338 if (rp->angle <= 0) {
346 for (i = 0; i < REDRAWSTEP; i++) {
347 j = (rp->rotor - rp->redrawpos + rp->nsave) % rp->nsave;
349 x_1 = (int) rp->save[j].x;
350 y_1 = (int) rp->save[j].y;
351 x_2 = (int) rp->save[(j - 1 + rp->nsave) % rp->nsave].x;
352 y_2 = (int) rp->save[(j - 1 + rp->nsave) % rp->nsave].y;
354 if (rp->iconifiedscreen) {
355 x_1 = x_1 * rp->centerx / rp->prevcenterx;
356 x_2 = x_2 * rp->centerx / rp->prevcenterx;
357 y_1 = y_1 * rp->centery / rp->prevcentery;
358 y_2 = y_2 * rp->centery / rp->prevcentery;
360 XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2);
362 if (++(rp->redrawpos) >= rp->nsave) {
368 XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 1,
369 LineSolid, CapButt, JoinMiter);
373 release_rotor (ModeInfo * mi)
375 if (rotors != NULL) {
378 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
379 free_rotor(&rotors[screen]);
380 (void) free((void *) rotors);
381 rotors = (rotorstruct *) NULL;
386 refresh_rotor (ModeInfo * mi)
392 rp = &rotors[MI_SCREEN(mi)];
399 XSCREENSAVER_MODULE ("Rotor", rotor)
401 #endif /* MODE_rotor */