dtwm: Remove define MOTIF_ONE_DOT_ONE, backwards compatibility for motif 1.1, CDE...
[oweals/cde.git] / cde / programs / dtscreen / swarm.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: swarm.c /main/3 1995/11/02 16:08:42 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  * swarm.c - swarm of bees for dtscreen, the X Window System lockscreen.
34  *
35  * Copyright (c) 1991 by Patrick J. Naughton.
36  *
37  * Revision History:
38  * 31-Aug-90: Adapted from xswarm by Jeff Butterworth. (butterwo@ncsc.org)
39  */
40
41 #include <stdlib.h>
42 #include "dtscreen.h"
43
44 #define TIMES   4               /* number of time positions recorded */
45 #define BEEACC  3               /* acceleration of bees */
46 #define WASPACC 5               /* maximum acceleration of wasp */
47 #define BEEVEL  11              /* maximum bee velocity */
48 #define WASPVEL 12              /* maximum wasp velocity */
49 #define BORDER  50              /* wasp won't go closer than this to the edge */
50
51 /* Macros */
52 #define X(t,b)  (sp->x[(t)*sp->beecount+(b)])
53 #define Y(t,b)  (sp->y[(t)*sp->beecount+(b)])
54 #define RAND(v) ((random()%(v))-((v)/2))        /* random number around 0 */
55
56 typedef struct {
57     int         pix;
58     long        startTime;
59     int         width;
60     int         height;
61     int         beecount;       /* number of bees */
62     XSegment   *segs;           /* bee lines */
63     XSegment   *old_segs;       /* old bee lines */
64     short      *x;
65     short      *y;              /* bee positions x[time][bee#] */
66     short      *xv;
67     short      *yv;             /* bee velocities xv[bee#] */
68     short       wx[3];
69     short       wy[3];
70     short       wxv;
71     short       wyv;
72 }           swarmstruct;
73
74 void
75 initswarm(perwindow *pwin)
76 {
77     XWindowAttributes xgwa;
78     swarmstruct *sp;
79     int         b;
80
81     if (pwin->data) free(pwin->data);
82     pwin->data = (void *)malloc(sizeof(swarmstruct));
83     memset(pwin->data, '\0', sizeof(swarmstruct));
84     sp = (swarmstruct *)pwin->data;
85     sp->startTime = seconds();
86     sp->beecount = batchcount;
87
88     XGetWindowAttributes(dsp, pwin->w, &xgwa);
89     sp->width = xgwa.width;
90     sp->height = xgwa.height;
91
92     /* Clear the background. */
93     XSetForeground(dsp, pwin->gc, BlackPixelOfScreen(pwin->perscreen->screen));
94     XFillRectangle(dsp, pwin->w, pwin->gc, 0, 0, sp->width, sp->height);
95
96     /* Allocate memory. */
97
98     sp->segs = (XSegment *) malloc(sizeof(XSegment) * sp->beecount);
99     sp->old_segs = (XSegment *) malloc(sizeof(XSegment) * sp->beecount);
100     sp->x = (short *) malloc(sizeof(short) * sp->beecount * TIMES);
101     sp->y = (short *) malloc(sizeof(short) * sp->beecount * TIMES);
102     sp->xv = (short *) malloc(sizeof(short) * sp->beecount);
103     sp->yv = (short *) malloc(sizeof(short) * sp->beecount);
104
105     /* Initialize point positions, velocities, etc. */
106
107     /* wasp */
108     sp->wx[0] = BORDER + random() % (sp->width - 2 * BORDER);
109     sp->wy[0] = BORDER + random() % (sp->height - 2 * BORDER);
110     sp->wx[1] = sp->wx[0];
111     sp->wy[1] = sp->wy[0];
112     sp->wxv = 0;
113     sp->wyv = 0;
114
115     /* bees */
116     for (b = 0; b < sp->beecount; b++) {
117         X(0, b) = random() % sp->width;
118         X(1, b) = X(0, b);
119         Y(0, b) = random() % sp->height;
120         Y(1, b) = Y(0, b);
121         sp->xv[b] = RAND(7);
122         sp->yv[b] = RAND(7);
123     }
124 }
125
126
127
128 void
129 drawswarm(perwindow *pwin)
130 {
131     swarmstruct *sp;
132     int         b;
133
134     sp = (swarmstruct *)pwin->data;
135     /* <=- Wasp -=> */
136     /* Age the arrays. */
137     sp->wx[2] = sp->wx[1];
138     sp->wx[1] = sp->wx[0];
139     sp->wy[2] = sp->wy[1];
140     sp->wy[1] = sp->wy[0];
141     /* Accelerate */
142     sp->wxv += RAND(WASPACC);
143     sp->wyv += RAND(WASPACC);
144
145     /* Speed Limit Checks */
146     if (sp->wxv > WASPVEL)
147         sp->wxv = WASPVEL;
148     if (sp->wxv < -WASPVEL)
149         sp->wxv = -WASPVEL;
150     if (sp->wyv > WASPVEL)
151         sp->wyv = WASPVEL;
152     if (sp->wyv < -WASPVEL)
153         sp->wyv = -WASPVEL;
154
155     /* Move */
156     sp->wx[0] = sp->wx[1] + sp->wxv;
157     sp->wy[0] = sp->wy[1] + sp->wyv;
158
159     /* Bounce Checks */
160     if ((sp->wx[0] < BORDER) || (sp->wx[0] > sp->width - BORDER - 1)) {
161         sp->wxv = -sp->wxv;
162         sp->wx[0] += sp->wxv;
163     }
164     if ((sp->wy[0] < BORDER) || (sp->wy[0] > sp->height - BORDER - 1)) {
165         sp->wyv = -sp->wyv;
166         sp->wy[0] += sp->wyv;
167     }
168     /* Don't let things settle down. */
169     sp->xv[random() % sp->beecount] += RAND(3);
170     sp->yv[random() % sp->beecount] += RAND(3);
171
172     /* <=- Bees -=> */
173     for (b = 0; b < sp->beecount; b++) {
174         int         distance,
175                     dx,
176                     dy;
177         /* Age the arrays. */
178         X(2, b) = X(1, b);
179         X(1, b) = X(0, b);
180         Y(2, b) = Y(1, b);
181         Y(1, b) = Y(0, b);
182
183         /* Accelerate */
184         dx = sp->wx[1] - X(1, b);
185         dy = sp->wy[1] - Y(1, b);
186         distance = abs(dx) + abs(dy);   /* approximation */
187         if (distance == 0)
188             distance = 1;
189         sp->xv[b] += (dx * BEEACC) / distance;
190         sp->yv[b] += (dy * BEEACC) / distance;
191
192         /* Speed Limit Checks */
193         if (sp->xv[b] > BEEVEL)
194             sp->xv[b] = BEEVEL;
195         if (sp->xv[b] < -BEEVEL)
196             sp->xv[b] = -BEEVEL;
197         if (sp->yv[b] > BEEVEL)
198             sp->yv[b] = BEEVEL;
199         if (sp->yv[b] < -BEEVEL)
200             sp->yv[b] = -BEEVEL;
201
202         /* Move */
203         X(0, b) = X(1, b) + sp->xv[b];
204         Y(0, b) = Y(1, b) + sp->yv[b];
205
206         /* Fill the segment lists. */
207         sp->segs[b].x1 = X(0, b);
208         sp->segs[b].y1 = Y(0, b);
209         sp->segs[b].x2 = X(1, b);
210         sp->segs[b].y2 = Y(1, b);
211         sp->old_segs[b].x1 = X(1, b);
212         sp->old_segs[b].y1 = Y(1, b);
213         sp->old_segs[b].x2 = X(2, b);
214         sp->old_segs[b].y2 = Y(2, b);
215     }
216
217     XSetForeground(dsp, pwin->gc, BlackPixelOfScreen(pwin->perscreen->screen));
218     XDrawLine(dsp, pwin->w, pwin->gc,
219               sp->wx[1], sp->wy[1], sp->wx[2], sp->wy[2]);
220     XDrawSegments(dsp, pwin->w, pwin->gc, sp->old_segs, sp->beecount);
221
222     XSetForeground(dsp, pwin->gc, WhitePixelOfScreen(pwin->perscreen->screen));
223     XDrawLine(dsp, pwin->w, pwin->gc,
224               sp->wx[0], sp->wy[0], sp->wx[1], sp->wy[1]);
225     if (!mono && pwin->perscreen->npixels > 2) {
226         XSetForeground(dsp, pwin->gc, pwin->perscreen->pixels[sp->pix]);
227         if (++sp->pix >= pwin->perscreen->npixels)
228             sp->pix = 0;
229     }
230     XDrawSegments(dsp, pwin->w, pwin->gc, sp->segs, sp->beecount);
231 }