Merge branch 'master' of ssh://git.code.sf.net/p/cdesktopenv/code
[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 librararies 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(pwin)
105     perwindow *pwin;
106 {
107     flightstruct *fs;
108     XWindowAttributes xgwa;
109     int         x;
110     struct elem *pelem;
111     Boolean     wassmall;
112
113     if (pwin->data) free(pwin->data);
114     pwin->data = (void *)malloc(sizeof(flightstruct));
115     memset(pwin->data, 0, sizeof(flightstruct));
116     fs = (flightstruct *)pwin->data;
117     XGetWindowAttributes(dsp, pwin->w, &xgwa);
118     fs->centerx = xgwa.width / 2;
119     fs->centery = xgwa.height / 2;
120
121     /*
122      * sometimes, you go into small view, only to see a really whizzy pattern
123      * that you would like to look more closely at. Normally, clicking in the
124      * icon reinitializes everything - but I don't, cuz I'm that kind of guy.
125      * HENCE, the wassmall stuff you see here.
126      */
127
128     wassmall = fs->smallscreen;
129     fs->smallscreen = (xgwa.width < 100);
130
131     if (wassmall && !fs->smallscreen)
132         fs->firsttime = True;
133     else {
134         if (batchcount > 12)
135             batchcount = DEFAULTCOUNT;
136         fs->num = batchcount;
137
138         if ((fs->elements = (struct elem *)
139               malloc(sizeof(struct elem) * fs->num)) == 0) {
140                 perror("malloc");
141                 exit(1);
142         }
143         memset(fs->savex, 0, sizeof(fs->savex));
144
145         pelem = fs->elements;
146
147         for (x = fs->num; --x >= 0; pelem++) {
148             pelem->radius_drift_max = 1.0;
149             pelem->radius_drift_now = 1.0;
150
151             pelem->end_radius = 100.0;
152
153             pelem->ratio_drift_max = 1.0;
154             pelem->ratio_drift_now = 1.0;
155             pelem->end_ratio = 10.0;
156         }
157
158         fs->rotor = 0;
159         fs->prev = 1;
160         fs->lastx = fs->centerx;
161         fs->lasty = fs->centery;
162         fs->angle = (random() % (long) MAXANGLE) / 3;
163         fs->forward = fs->firsttime = True;
164     }
165     XSetForeground(dsp, pwin->gc, BlackPixelOfScreen(pwin->perscreen->screen));
166     XFillRectangle(dsp, pwin->w, pwin->gc, 0, 0, xgwa.width, xgwa.height);
167 }
168
169 void
170 drawrotor(pwin)
171     perwindow *pwin;
172 {
173     register flightstruct *fs;
174     register struct elem *pelem;
175     int         thisx,
176                 thisy;
177     int         i,
178                 rp;
179     int         x1,
180                 y1,
181                 x2,
182                 y2;
183
184 #define SCALE(W,N)      CAT(W,N)/=12; CAT(W,N)+=(CAT(fs->center,W)-2)
185 #define SCALEIFSMALL()    if (fs->smallscreen) {        \
186                               SCALE(x,1); SCALE(x,2);   \
187                               SCALE(y,1); SCALE(y,2);   \
188                           }
189
190     fs = (flightstruct *)pwin->data;
191     for (rp = 0; rp < REPS; rp++) {
192         thisx = fs->centerx;
193         thisy = fs->centery;
194
195         for (i = fs->num, pelem = fs->elements; --i >= 0; pelem++) {
196             if (pelem->radius_drift_max <= pelem->radius_drift_now) {
197                 pelem->start_radius = pelem->end_radius;
198                 pelem->end_radius =
199                     (float) (random() % 40000) / 100.0 - 200.0;
200                 pelem->radius_drift_max =
201                     (float) (random() % 100000) + 10000.0;
202                 pelem->radius_drift_now = 0.0;
203             }
204             if (pelem->ratio_drift_max <= pelem->ratio_drift_now) {
205                 pelem->start_ratio = pelem->end_ratio;
206                 pelem->end_ratio =
207                     (float) (random() % 2000) / 100.0 - 10.0;
208                 pelem->ratio_drift_max =
209                     (float) (random() % 100000) + 10000.0;
210                 pelem->ratio_drift_now = 0.0;
211             }
212             pelem->ratio = pelem->start_ratio +
213                 (pelem->end_ratio - pelem->start_ratio) /
214                 pelem->ratio_drift_max * pelem->ratio_drift_now;
215             pelem->angle = fs->angle * pelem->ratio;
216             pelem->radius = pelem->start_radius +
217                 (pelem->end_radius - pelem->start_radius) /
218                 pelem->radius_drift_max * pelem->radius_drift_now;
219
220             thisx += (int) (cos(pelem->angle) * pelem->radius);
221             thisy += (int) (sin(pelem->angle) * pelem->radius);
222
223             pelem->ratio_drift_now += 1.0;
224             pelem->radius_drift_now += 1.0;
225         }
226
227         if (fs->firsttime)
228             fs->firsttime = False;
229         else {
230             XSetForeground(dsp, pwin->gc, BlackPixelOfScreen(pwin->perscreen->screen));
231
232             x1 = (int) fs->savex[fs->rotor];
233             y1 = (int) fs->savey[fs->rotor];
234             x2 = (int) fs->savex[fs->prev];
235             y2 = (int) fs->savey[fs->prev];
236
237             SCALEIFSMALL()
238
239             XDrawLine(dsp, pwin->w, pwin->gc, x1, y1, x2, y2);
240
241             if (!mono && pwin->perscreen->npixels > 2) {
242                 XSetForeground(dsp, pwin->gc,
243                                pwin->perscreen->pixels[fs->pix]);
244                 if (++fs->pix >= pwin->perscreen->npixels)
245                     fs->pix = 0;
246             } else
247                 XSetForeground(dsp, pwin->gc, 
248                   WhitePixelOfScreen(pwin->perscreen->screen));
249
250             x1 = fs->lastx;
251             y1 = fs->lasty;
252             x2 = thisx;
253             y2 = thisy;
254
255             SCALEIFSMALL()
256
257             XDrawLine(dsp, pwin->w, pwin->gc, x1, y1, x2, y2);
258         }
259         fs->savex[fs->rotor] = fs->lastx = thisx;
260         fs->savey[fs->rotor] = fs->lasty = thisy;
261
262         ++fs->rotor;
263         fs->rotor %= SAVE;
264         ++fs->prev;
265         fs->prev %= SAVE;
266         if (fs->forward) {
267             fs->angle += 0.01;
268             if (fs->angle >= MAXANGLE) {
269                 fs->angle = MAXANGLE;
270                 fs->forward = False;
271             }
272         } else {
273             fs->angle -= 0.1;
274             if (fs->angle <= 0) {
275                 fs->angle = 0.0;
276                 fs->forward = True;
277             }
278         }
279     }
280 }