Merge branch 'cde-fixups-1' of ssh://git.code.sf.net/p/cdesktopenv/code into cde...
[oweals/cde.git] / cde / programs / dtscreen / rotor.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: rotor.c /main/3 1995/11/02 16:08:34 rswiston $ */
24 /*
25  */
26 /*                                                                      *
27  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
28  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
29  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
30  * (c) Copyright 1993, 1994 Novell, Inc.                                *
31  */
32 /*-
33  * rotor.c - A swirly rotor for dtscreen, the X Window System lockscreen.
34  *
35  * Copyright (c) 1991 by Patrick J. Naughton.
36  *
37  * See dtscreen.c for copying information.
38  *
39  * Revision History:
40  * 11-Nov-90: put into dtscreen (by Steve Zellers, zellers@sun.com)
41  * 16-Oct-90: Received from Tom Lawrence (tcl@cs.brown.edu: 'flight' simulator)
42  */
43
44 /*
45  * A 'batchcount' of 3 or 4 works best!
46  */
47
48 #include <stdio.h>
49 #include <math.h>
50 #include <stdlib.h>
51 #include "dtscreen.h"
52
53 #define SAVE            100     /* this is a good constant to tweak */
54 #define REPS            50
55
56 #define MAXANGLE        10000.0 /* irrectangular */
57 #define DEFAULTCOUNT    3
58
59 /*typedef unsigned char Boolean; */
60
61 #define IDENT(X)        X
62 #if defined (__STDC__) || defined (AIXV3)
63 #define CAT(X,Y)        X##Y
64 #else
65 #define CAT(X,Y)        IDENT(X)Y
66 #endif
67
68 struct elem {
69     float       angle;
70     float       radius;
71     float       start_radius;
72     float       end_radius;
73     float       radius_drift_max;
74     float       radius_drift_now;
75
76     float       ratio;
77     float       start_ratio;
78     float       end_ratio;
79     float       ratio_drift_max;
80     float       ratio_drift_now;
81 };
82
83 typedef struct flightstruct {
84     struct elem *elements;
85     int         pix;
86     int         lastx,
87                 lasty;
88     int         num,
89                 rotor,
90                 prev;
91     int         savex[SAVE],
92                 savey[SAVE];
93     float       angle;
94     int         centerx,
95                 centery;
96     Boolean     firsttime;
97     Boolean     smallscreen;    /* for iconified view */
98     Boolean     forward;
99     Boolean     unused;
100 }           flightstruct;
101
102
103 void
104 initrotor(perwindow *pwin)
105 {
106     flightstruct *fs;
107     XWindowAttributes xgwa;
108     int         x;
109     struct elem *pelem;
110     Boolean     wassmall;
111
112     if (pwin->data) free(pwin->data);
113     pwin->data = (void *)malloc(sizeof(flightstruct));
114     memset(pwin->data, 0, sizeof(flightstruct));
115     fs = (flightstruct *)pwin->data;
116     XGetWindowAttributes(dsp, pwin->w, &xgwa);
117     fs->centerx = xgwa.width / 2;
118     fs->centery = xgwa.height / 2;
119
120     /*
121      * sometimes, you go into small view, only to see a really whizzy pattern
122      * that you would like to look more closely at. Normally, clicking in the
123      * icon reinitializes everything - but I don't, cuz I'm that kind of guy.
124      * HENCE, the wassmall stuff you see here.
125      */
126
127     wassmall = fs->smallscreen;
128     fs->smallscreen = (xgwa.width < 100);
129
130     if (wassmall && !fs->smallscreen)
131         fs->firsttime = True;
132     else {
133         if (batchcount > 12)
134             batchcount = DEFAULTCOUNT;
135         fs->num = batchcount;
136
137         if ((fs->elements = (struct elem *)
138               malloc(sizeof(struct elem) * fs->num)) == 0) {
139                 perror("malloc");
140                 exit(1);
141         }
142         memset(fs->savex, 0, sizeof(fs->savex));
143
144         pelem = fs->elements;
145
146         for (x = fs->num; --x >= 0; pelem++) {
147             pelem->radius_drift_max = 1.0;
148             pelem->radius_drift_now = 1.0;
149
150             pelem->end_radius = 100.0;
151
152             pelem->ratio_drift_max = 1.0;
153             pelem->ratio_drift_now = 1.0;
154             pelem->end_ratio = 10.0;
155         }
156
157         fs->rotor = 0;
158         fs->prev = 1;
159         fs->lastx = fs->centerx;
160         fs->lasty = fs->centery;
161         fs->angle = (random() % (long) MAXANGLE) / 3;
162         fs->forward = fs->firsttime = True;
163     }
164     XSetForeground(dsp, pwin->gc, BlackPixelOfScreen(pwin->perscreen->screen));
165     XFillRectangle(dsp, pwin->w, pwin->gc, 0, 0, xgwa.width, xgwa.height);
166 }
167
168 void
169 drawrotor(perwindow *pwin)
170 {
171     register flightstruct *fs;
172     register struct elem *pelem;
173     int         thisx,
174                 thisy;
175     int         i,
176                 rp;
177     int         x1,
178                 y1,
179                 x2,
180                 y2;
181
182 #define SCALE(W,N)      CAT(W,N)/=12; CAT(W,N)+=(CAT(fs->center,W)-2)
183 #define SCALEIFSMALL()    if (fs->smallscreen) {        \
184                               SCALE(x,1); SCALE(x,2);   \
185                               SCALE(y,1); SCALE(y,2);   \
186                           }
187
188     fs = (flightstruct *)pwin->data;
189     for (rp = 0; rp < REPS; rp++) {
190         thisx = fs->centerx;
191         thisy = fs->centery;
192
193         for (i = fs->num, pelem = fs->elements; --i >= 0; pelem++) {
194             if (pelem->radius_drift_max <= pelem->radius_drift_now) {
195                 pelem->start_radius = pelem->end_radius;
196                 pelem->end_radius =
197                     (float) (random() % 40000) / 100.0 - 200.0;
198                 pelem->radius_drift_max =
199                     (float) (random() % 100000) + 10000.0;
200                 pelem->radius_drift_now = 0.0;
201             }
202             if (pelem->ratio_drift_max <= pelem->ratio_drift_now) {
203                 pelem->start_ratio = pelem->end_ratio;
204                 pelem->end_ratio =
205                     (float) (random() % 2000) / 100.0 - 10.0;
206                 pelem->ratio_drift_max =
207                     (float) (random() % 100000) + 10000.0;
208                 pelem->ratio_drift_now = 0.0;
209             }
210             pelem->ratio = pelem->start_ratio +
211                 (pelem->end_ratio - pelem->start_ratio) /
212                 pelem->ratio_drift_max * pelem->ratio_drift_now;
213             pelem->angle = fs->angle * pelem->ratio;
214             pelem->radius = pelem->start_radius +
215                 (pelem->end_radius - pelem->start_radius) /
216                 pelem->radius_drift_max * pelem->radius_drift_now;
217
218             thisx += (int) (cos(pelem->angle) * pelem->radius);
219             thisy += (int) (sin(pelem->angle) * pelem->radius);
220
221             pelem->ratio_drift_now += 1.0;
222             pelem->radius_drift_now += 1.0;
223         }
224
225         if (fs->firsttime)
226             fs->firsttime = False;
227         else {
228             XSetForeground(dsp, pwin->gc, BlackPixelOfScreen(pwin->perscreen->screen));
229
230             x1 = (int) fs->savex[fs->rotor];
231             y1 = (int) fs->savey[fs->rotor];
232             x2 = (int) fs->savex[fs->prev];
233             y2 = (int) fs->savey[fs->prev];
234
235             SCALEIFSMALL()
236
237             XDrawLine(dsp, pwin->w, pwin->gc, x1, y1, x2, y2);
238
239             if (!mono && pwin->perscreen->npixels > 2) {
240                 XSetForeground(dsp, pwin->gc,
241                                pwin->perscreen->pixels[fs->pix]);
242                 if (++fs->pix >= pwin->perscreen->npixels)
243                     fs->pix = 0;
244             } else
245                 XSetForeground(dsp, pwin->gc, 
246                   WhitePixelOfScreen(pwin->perscreen->screen));
247
248             x1 = fs->lastx;
249             y1 = fs->lasty;
250             x2 = thisx;
251             y2 = thisy;
252
253             SCALEIFSMALL()
254
255             XDrawLine(dsp, pwin->w, pwin->gc, x1, y1, x2, y2);
256         }
257         fs->savex[fs->rotor] = fs->lastx = thisx;
258         fs->savey[fs->rotor] = fs->lasty = thisy;
259
260         ++fs->rotor;
261         fs->rotor %= SAVE;
262         ++fs->prev;
263         fs->prev %= SAVE;
264         if (fs->forward) {
265             fs->angle += 0.01;
266             if (fs->angle >= MAXANGLE) {
267                 fs->angle = MAXANGLE;
268                 fs->forward = False;
269             }
270         } else {
271             fs->angle -= 0.1;
272             if (fs->angle <= 0) {
273                 fs->angle = 0.0;
274                 fs->forward = True;
275             }
276         }
277     }
278 }