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" \
44 # define SMOOTH_COLORS
45 # define release_rotor 0
46 # define reshape_rotor 0
47 # define rotor_handle_event 0
48 # include "xlockmore.h" /* in xscreensaver distribution */
49 #else /* STANDALONE */
50 # include "xlock.h" /* in xlockmore distribution */
51 #endif /* STANDALONE */
55 ENTRYPOINT ModeSpecOpt rotor_opts =
56 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
59 ModStruct rotor_description =
60 {"rotor", "init_rotor", "draw_rotor", (char *) NULL,
61 "refresh_rotor", "init_rotor", "free_rotor", &rotor_opts,
62 100, 4, 100, -6, 64, 0.3, "",
63 "Shows Tom's Roto-Rooter", 0, NULL};
68 * A 'batchcount' of 3 or 4 works best!
71 #define MAXANGLE 3000.0 /* irrectangular (was 10000.0) */
73 /* How many segments to draw per cycle when redrawing */
81 float radius_drift_max;
82 float radius_drift_now;
87 float ratio_drift_max;
88 float ratio_drift_now;
98 int prevcenterx, prevcentery;
99 unsigned char firsttime;
100 unsigned char iconifiedscreen; /* for iconified view */
101 unsigned char forward;
102 unsigned char unused;
105 int redrawing, redrawpos;
109 static rotorstruct *rotors = (rotorstruct *) NULL;
112 free_rotor(ModeInfo * mi)
114 rotorstruct *rp = &rotors[MI_SCREEN(mi)];
115 if (rp->elements != NULL) {
116 (void) free((void *) rp->elements);
117 rp->elements = (elem *) NULL;
119 if (rp->save != NULL) {
120 (void) free((void *) rp->save);
121 rp->save = (XPoint *) NULL;
126 init_rotor (ModeInfo * mi)
130 unsigned char wasiconified;
133 MI_INIT (mi, rotors);
134 rp = &rotors[MI_SCREEN(mi)];
137 jwxyz_XSetAntiAliasing (MI_DISPLAY(mi), MI_GC(mi), False);
140 rp->prevcenterx = rp->centerx;
141 rp->prevcentery = rp->centery;
143 rp->centerx = MI_WIDTH(mi) / 2;
144 rp->centery = MI_HEIGHT(mi) / 2;
148 * sometimes, you go into iconified view, only to see a really whizzy pattern
149 * that you would like to look more closely at. Normally, clicking in the
150 * icon reinitializes everything - but I don't, cuz I'm that kind of guy.
151 * HENCE, the wasiconified stuff you see here.
154 wasiconified = rp->iconifiedscreen;
155 rp->iconifiedscreen = MI_IS_ICONIC(mi);
157 if (wasiconified && !rp->iconifiedscreen)
158 rp->firsttime = True;
161 /* This is a fudge is needed since prevcenter may not be set when it comes
162 from the the random mode and return is pressed (and its not the first
163 mode that was running). This assumes that the size of the lock screen
164 window / size of the icon window = 12 */
165 if (!rp->prevcenterx)
166 rp->prevcenterx = rp->centerx * 12;
167 if (!rp->prevcentery)
168 rp->prevcentery = rp->centery * 12;
170 rp->num = MI_COUNT(mi);
172 rp->num = NRAND(-rp->num) + 1;
173 if (rp->elements != NULL) {
174 (void) free((void *) rp->elements);
175 rp->elements = (elem *) NULL;
178 if (rp->elements == NULL)
179 if ((rp->elements = (elem *) calloc(rp->num,
180 sizeof (elem))) == NULL) {
184 rp->nsave = MI_CYCLES(mi);
187 if (rp->save == NULL)
188 if ((rp->save = (XPoint *) malloc(rp->nsave *
189 sizeof (XPoint))) == NULL) {
193 for (x = 0; x < rp->nsave; x++) {
194 rp->save[x].x = rp->centerx;
195 rp->save[x].y = rp->centery;
198 pelem = rp->elements;
200 for (x = rp->num; --x >= 0; pelem++) {
201 pelem->radius_drift_max = 1.0;
202 pelem->radius_drift_now = 1.0;
204 pelem->end_radius = 100.0;
206 pelem->ratio_drift_max = 1.0;
207 pelem->ratio_drift_now = 1.0;
208 pelem->end_ratio = 10.0;
210 if (MI_NPIXELS(mi) > 2)
211 rp->pix = NRAND(MI_NPIXELS(mi));
215 rp->lastx = rp->centerx;
216 rp->lasty = rp->centery;
217 rp->angle = (float) NRAND((long) MAXANGLE) / 3.0;
218 rp->forward = rp->firsttime = True;
220 rp->linewidth = MI_SIZE(mi);
222 if (rp->linewidth == 0)
224 if (rp->linewidth < 0)
225 rp->linewidth = NRAND(-rp->linewidth) + 1;
231 draw_rotor (ModeInfo * mi)
233 Display *display = MI_DISPLAY(mi);
235 register elem *pelem;
238 int x_1, y_1, x_2, y_2;
243 rp = &rotors[MI_SCREEN(mi)];
244 if (rp->elements == NULL)
247 MI_IS_DRAWN(mi) = True;
248 if (!rp->iconifiedscreen) {
252 thisx = rp->prevcenterx;
253 thisy = rp->prevcentery;
255 XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), rp->linewidth,
256 LineSolid, CapButt, JoinMiter);
257 for (i = rp->num, pelem = rp->elements; --i >= 0; pelem++) {
258 if (pelem->radius_drift_max <= pelem->radius_drift_now) {
259 pelem->start_radius = pelem->end_radius;
260 pelem->end_radius = (float) NRAND(40000) / 100.0 - 200.0;
261 pelem->radius_drift_max = (float) NRAND(100000) + 10000.0;
262 pelem->radius_drift_now = 0.0;
264 if (pelem->ratio_drift_max <= pelem->ratio_drift_now) {
265 pelem->start_ratio = pelem->end_ratio;
266 pelem->end_ratio = (float) NRAND(2000) / 100.0 - 10.0;
267 pelem->ratio_drift_max = (float) NRAND(100000) + 10000.0;
268 pelem->ratio_drift_now = 0.0;
270 pelem->ratio = pelem->start_ratio +
271 (pelem->end_ratio - pelem->start_ratio) /
272 pelem->ratio_drift_max * pelem->ratio_drift_now;
273 pelem->angle = rp->angle * pelem->ratio;
274 pelem->radius = pelem->start_radius +
275 (pelem->end_radius - pelem->start_radius) /
276 pelem->radius_drift_max * pelem->radius_drift_now;
278 thisx += (int) (COSF(pelem->angle) * pelem->radius);
279 thisy += (int) (SINF(pelem->angle) * pelem->radius);
281 pelem->ratio_drift_now += 1.0;
282 pelem->radius_drift_now += 1.0;
285 rp->firsttime = False;
287 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
289 x_1 = (int) rp->save[rp->rotor].x;
290 y_1 = (int) rp->save[rp->rotor].y;
291 x_2 = (int) rp->save[rp->prev].x;
292 y_2 = (int) rp->save[rp->prev].y;
294 if (rp->iconifiedscreen) {
295 x_1 = x_1 * rp->centerx / rp->prevcenterx;
296 x_2 = x_2 * rp->centerx / rp->prevcenterx;
297 y_1 = y_1 * rp->centery / rp->prevcentery;
298 y_2 = y_2 * rp->centery / rp->prevcentery;
300 XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2);
302 if (MI_NPIXELS(mi) > 2) {
303 XSetForeground(display, gc, MI_PIXEL(mi, rp->pix));
304 if (++rp->pix >= MI_NPIXELS(mi))
307 XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
314 if (rp->iconifiedscreen) {
315 x_1 = x_1 * rp->centerx / rp->prevcenterx;
316 x_2 = x_2 * rp->centerx / rp->prevcenterx;
317 y_1 = y_1 * rp->centery / rp->prevcentery;
318 y_2 = y_2 * rp->centery / rp->prevcentery;
320 XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2);
322 rp->save[rp->rotor].x = rp->lastx = thisx;
323 rp->save[rp->rotor].y = rp->lasty = thisy;
326 rp->rotor %= rp->nsave;
328 rp->prev %= rp->nsave;
331 if (rp->angle >= MAXANGLE) {
332 rp->angle = MAXANGLE;
337 if (rp->angle <= 0) {
345 for (i = 0; i < REDRAWSTEP; i++) {
346 j = (rp->rotor - rp->redrawpos + rp->nsave) % rp->nsave;
348 x_1 = (int) rp->save[j].x;
349 y_1 = (int) rp->save[j].y;
350 x_2 = (int) rp->save[(j - 1 + rp->nsave) % rp->nsave].x;
351 y_2 = (int) rp->save[(j - 1 + rp->nsave) % rp->nsave].y;
353 if (rp->iconifiedscreen) {
354 x_1 = x_1 * rp->centerx / rp->prevcenterx;
355 x_2 = x_2 * rp->centerx / rp->prevcenterx;
356 y_1 = y_1 * rp->centery / rp->prevcentery;
357 y_2 = y_2 * rp->centery / rp->prevcentery;
359 XDrawLine(display, MI_WINDOW(mi), gc, x_1, y_1, x_2, y_2);
361 if (++(rp->redrawpos) >= rp->nsave) {
367 XSetLineAttributes(MI_DISPLAY(mi), MI_GC(mi), 1,
368 LineSolid, CapButt, JoinMiter);
373 refresh_rotor (ModeInfo * mi)
379 rp = &rotors[MI_SCREEN(mi)];
387 XSCREENSAVER_MODULE ("Rotor", rotor)
389 #endif /* MODE_rotor */