Link with C++ linker
[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 "dtscreen.h"
51
52 #define SAVE            100     /* this is a good constant to tweak */
53 #define REPS            50
54
55 #define MAXANGLE        10000.0 /* irrectangular */
56 #define DEFAULTCOUNT    3
57
58 typedef unsigned char Boolean;
59
60 #define IDENT(X)        X
61 #if defined (__STDC__) || defined (AIXV3)
62 #define CAT(X,Y)        X##Y
63 #else
64 #define CAT(X,Y)        IDENT(X)Y
65 #endif
66
67 struct elem {
68     float       angle;
69     float       radius;
70     float       start_radius;
71     float       end_radius;
72     float       radius_drift_max;
73     float       radius_drift_now;
74
75     float       ratio;
76     float       start_ratio;
77     float       end_ratio;
78     float       ratio_drift_max;
79     float       ratio_drift_now;
80 };
81
82 typedef struct flightstruct {
83     struct elem *elements;
84     int         pix;
85     int         lastx,
86                 lasty;
87     int         num,
88                 rotor,
89                 prev;
90     int         savex[SAVE],
91                 savey[SAVE];
92     float       angle;
93     int         centerx,
94                 centery;
95     Boolean     firsttime;
96     Boolean     smallscreen;    /* for iconified view */
97     Boolean     forward;
98     Boolean     unused;
99 }           flightstruct;
100
101
102 void
103 initrotor(pwin)
104     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(pwin)
170     perwindow *pwin;
171 {
172     register flightstruct *fs;
173     register struct elem *pelem;
174     int         thisx,
175                 thisy;
176     int         i,
177                 rp;
178     int         x1,
179                 y1,
180                 x2,
181                 y2;
182
183 #define SCALE(W,N)      CAT(W,N)/=12; CAT(W,N)+=(CAT(fs->center,W)-2)
184 #define SCALEIFSMALL()    if (fs->smallscreen) {        \
185                               SCALE(x,1); SCALE(x,2);   \
186                               SCALE(y,1); SCALE(y,2);   \
187                           }
188
189     fs = (flightstruct *)pwin->data;
190     for (rp = 0; rp < REPS; rp++) {
191         thisx = fs->centerx;
192         thisy = fs->centery;
193
194         for (i = fs->num, pelem = fs->elements; --i >= 0; pelem++) {
195             if (pelem->radius_drift_max <= pelem->radius_drift_now) {
196                 pelem->start_radius = pelem->end_radius;
197                 pelem->end_radius =
198                     (float) (random() % 40000) / 100.0 - 200.0;
199                 pelem->radius_drift_max =
200                     (float) (random() % 100000) + 10000.0;
201                 pelem->radius_drift_now = 0.0;
202             }
203             if (pelem->ratio_drift_max <= pelem->ratio_drift_now) {
204                 pelem->start_ratio = pelem->end_ratio;
205                 pelem->end_ratio =
206                     (float) (random() % 2000) / 100.0 - 10.0;
207                 pelem->ratio_drift_max =
208                     (float) (random() % 100000) + 10000.0;
209                 pelem->ratio_drift_now = 0.0;
210             }
211             pelem->ratio = pelem->start_ratio +
212                 (pelem->end_ratio - pelem->start_ratio) /
213                 pelem->ratio_drift_max * pelem->ratio_drift_now;
214             pelem->angle = fs->angle * pelem->ratio;
215             pelem->radius = pelem->start_radius +
216                 (pelem->end_radius - pelem->start_radius) /
217                 pelem->radius_drift_max * pelem->radius_drift_now;
218
219             thisx += (int) (cos(pelem->angle) * pelem->radius);
220             thisy += (int) (sin(pelem->angle) * pelem->radius);
221
222             pelem->ratio_drift_now += 1.0;
223             pelem->radius_drift_now += 1.0;
224         }
225
226         if (fs->firsttime)
227             fs->firsttime = False;
228         else {
229             XSetForeground(dsp, pwin->gc, BlackPixelOfScreen(pwin->perscreen->screen));
230
231             x1 = (int) fs->savex[fs->rotor];
232             y1 = (int) fs->savey[fs->rotor];
233             x2 = (int) fs->savex[fs->prev];
234             y2 = (int) fs->savey[fs->prev];
235
236             SCALEIFSMALL()
237
238             XDrawLine(dsp, pwin->w, pwin->gc, x1, y1, x2, y2);
239
240             if (!mono && pwin->perscreen->npixels > 2) {
241                 XSetForeground(dsp, pwin->gc,
242                                pwin->perscreen->pixels[fs->pix]);
243                 if (++fs->pix >= pwin->perscreen->npixels)
244                     fs->pix = 0;
245             } else
246                 XSetForeground(dsp, pwin->gc, 
247                   WhitePixelOfScreen(pwin->perscreen->screen));
248
249             x1 = fs->lastx;
250             y1 = fs->lasty;
251             x2 = thisx;
252             y2 = thisy;
253
254             SCALEIFSMALL()
255
256             XDrawLine(dsp, pwin->w, pwin->gc, x1, y1, x2, y2);
257         }
258         fs->savex[fs->rotor] = fs->lastx = thisx;
259         fs->savey[fs->rotor] = fs->lasty = thisy;
260
261         ++fs->rotor;
262         fs->rotor %= SAVE;
263         ++fs->prev;
264         fs->prev %= SAVE;
265         if (fs->forward) {
266             fs->angle += 0.01;
267             if (fs->angle >= MAXANGLE) {
268                 fs->angle = MAXANGLE;
269                 fs->forward = False;
270             }
271         } else {
272             fs->angle -= 0.1;
273             if (fs->angle <= 0) {
274                 fs->angle = 0.0;
275                 fs->forward = True;
276             }
277         }
278     }
279 }