1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* world --- world spinner */
3
4 #if 0
5 static const char sccsid[] = "@(#)world.c 5.00 2000/11/01 xlockmore";
6
7 #endif
8
9 /*-
10 * Copyright (c) 1993 Matthew Moyle-Croft <matthew@moyle-croft.com>
11 *
12 * Permission to use, copy, modify, and distribute this software and its
13 * documentation for any purpose and without fee is hereby granted,
14 * provided that the above copyright notice appear in all copies and that
15 * both that copyright notice and this permission notice appear in
16 * supporting documentation.
17 *
18 * This file is provided AS IS with no warranties of any kind. The author
19 * shall have no liability with respect to the infringement of copyrights,
20 * trade secrets or any patents by this file or any part thereof. In no
21 * event will the author be liable for any lost revenue or profits or
22 * other special, indirect and consequential damages.
23 *
24 * Revision History:
25 * 01-Nov-2000:
26 * 10-May-1997: Compatible with xscreensaver
27 * 04-Oct-1995: multiscreen patch, thanks to Grant McDorman <grant@isgtec.com>.
28 * 10-Jul-1995: Backward spinning jump fixed by Neale Pickett <zephyr@nmt.edu>.
29 * 17-Jul-1994: Got batchcount to work.
30 * 09-Jan-1994: Written [ Modified from image.c ]
31 * 29-Jul-1990: image.c written. Copyright (c) 1991 by Patrick J. Naughton.
32 */
33
34 #ifdef STANDALONE
35 #define MODE_world
36 #define DEFAULTS "*delay: 100000 \n" \
37 "*count: -16 \n" \
38 "*ncolors: 200 \n" \
39
40 # define free_world 0
41 # define reshape_world 0
42 # define world_handle_event 0
43 #include "xlockmore.h" /* in xscreensaver distribution */
44 #else /* STANDALONE */
45 #include "xlock.h" /* in xlockmore distribution */
46 #endif /* STANDALONE */
47
48 #ifdef MODE_world
49
50 ENTRYPOINT ModeSpecOpt world_opts =
51 {0, (XrmOptionDescRec *) NULL, 0, (argtype *) NULL, (OptionStruct *) NULL};
52
53 #ifdef USE_MODULES
54 ModStruct world_description =
55 {"world", "init_world", "draw_world", "release_world",
56 "refresh_world", "init_world", (char *) NULL, &world_opts,
57 100000, -16, 1, 1, 64, 0.3, "",
58 "Shows spinning Earths", 0, NULL};
59
60 #endif
61
62 #include "bitmaps/terra-00.xbm"
63 #include "bitmaps/terra-01.xbm"
64 #include "bitmaps/terra-02.xbm"
65 #include "bitmaps/terra-03.xbm"
66 #include "bitmaps/terra-04.xbm"
67 #include "bitmaps/terra-05.xbm"
68 #include "bitmaps/terra-06.xbm"
69 #include "bitmaps/terra-07.xbm"
70 #include "bitmaps/terra-08.xbm"
71 #include "bitmaps/terra-09.xbm"
72 #include "bitmaps/terra-10.xbm"
73 #include "bitmaps/terra-11.xbm"
74 #include "bitmaps/terra-12.xbm"
75 #include "bitmaps/terra-13.xbm"
76 #include "bitmaps/terra-14.xbm"
77 #include "bitmaps/terra-15.xbm"
78 #include "bitmaps/terra-16.xbm"
79 #include "bitmaps/terra-17.xbm"
80 #include "bitmaps/terra-18.xbm"
81 #include "bitmaps/terra-19.xbm"
82 #include "bitmaps/terra-20.xbm"
83 #include "bitmaps/terra-21.xbm"
84 #include "bitmaps/terra-22.xbm"
85 #include "bitmaps/terra-23.xbm"
86 #include "bitmaps/terra-24.xbm"
87 #include "bitmaps/terra-25.xbm"
88 #include "bitmaps/terra-26.xbm"
89 #include "bitmaps/terra-27.xbm"
90 #include "bitmaps/terra-28.xbm"
91 #include "bitmaps/terra-29.xbm"
92
93 #define NUM_EARTHS 30
94 #define SIZE_X terra00_width /* 64 */
95 #define SIZE_Y terra00_height /* 64 */
96 #define NUM_REV 4
97 #define MINWORLDS 1
98
99 static XImage Earths[NUM_EARTHS] =
100 {
101 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra00_bits, LSBFirst, 8, LSBFirst, 8, 1},
102 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra01_bits, LSBFirst, 8, LSBFirst, 8, 1},
103 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra02_bits, LSBFirst, 8, LSBFirst, 8, 1},
104 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra03_bits, LSBFirst, 8, LSBFirst, 8, 1},
105 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra04_bits, LSBFirst, 8, LSBFirst, 8, 1},
106 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra05_bits, LSBFirst, 8, LSBFirst, 8, 1},
107 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra06_bits, LSBFirst, 8, LSBFirst, 8, 1},
108 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra07_bits, LSBFirst, 8, LSBFirst, 8, 1},
109 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra08_bits, LSBFirst, 8, LSBFirst, 8, 1},
110 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra09_bits, LSBFirst, 8, LSBFirst, 8, 1},
111 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra10_bits, LSBFirst, 8, LSBFirst, 8, 1},
112 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra11_bits, LSBFirst, 8, LSBFirst, 8, 1},
113 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra12_bits, LSBFirst, 8, LSBFirst, 8, 1},
114 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra13_bits, LSBFirst, 8, LSBFirst, 8, 1},
115 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra14_bits, LSBFirst, 8, LSBFirst, 8, 1},
116 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra15_bits, LSBFirst, 8, LSBFirst, 8, 1},
117 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra16_bits, LSBFirst, 8, LSBFirst, 8, 1},
118 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra17_bits, LSBFirst, 8, LSBFirst, 8, 1},
119 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra18_bits, LSBFirst, 8, LSBFirst, 8, 1},
120 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra19_bits, LSBFirst, 8, LSBFirst, 8, 1},
121 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra20_bits, LSBFirst, 8, LSBFirst, 8, 1},
122 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra21_bits, LSBFirst, 8, LSBFirst, 8, 1},
123 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra22_bits, LSBFirst, 8, LSBFirst, 8, 1},
124 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra23_bits, LSBFirst, 8, LSBFirst, 8, 1},
125 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra24_bits, LSBFirst, 8, LSBFirst, 8, 1},
126 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra25_bits, LSBFirst, 8, LSBFirst, 8, 1},
127 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra26_bits, LSBFirst, 8, LSBFirst, 8, 1},
128 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra27_bits, LSBFirst, 8, LSBFirst, 8, 1},
129 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra28_bits, LSBFirst, 8, LSBFirst, 8, 1},
130 {SIZE_X, SIZE_Y, 0, XYBitmap, (char *) terra29_bits, LSBFirst, 8, LSBFirst, 8, 1}};
131
132 typedef struct {
133 int x;
134 int y;
135 unsigned long color;
136 int frame;
137 int direction;
138 } planetstruct;
139
140 typedef struct {
141 int width;
142 int height;
143 int nrows;
144 int ncols;
145 int xb;
146 int yb;
147 int frame_num;
148 int nplanets;
149 planetstruct *planets;
150 } worldstruct;
151
152 static worldstruct *worlds = (worldstruct *) NULL;
153
154 static void
free_world_screen(worldstruct * wp)155 free_world_screen(worldstruct * wp)
156 {
157 if (wp == NULL) {
158 return;
159 }
160 if (wp->planets != NULL)
161 free(wp->planets);
162 wp = NULL;
163 }
164
165 ENTRYPOINT void
init_world(ModeInfo * mi)166 init_world(ModeInfo * mi)
167 {
168 int i;
169 worldstruct *wp;
170
171 MI_INIT(mi, worlds);
172 wp = &worlds[MI_SCREEN(mi)];
173 wp->frame_num = NUM_EARTHS * NUM_REV;
174 for (i = 0; i < NUM_EARTHS; i++)
175 Earths[i].bytes_per_line = 8;
176 wp->width = MI_WIDTH(mi);
177 wp->height = MI_HEIGHT(mi);
178 wp->ncols = wp->width / SIZE_X;
179 if (!wp->ncols)
180 wp->ncols = 1;
181 wp->nrows = wp->height / SIZE_Y;
182 if (!wp->nrows)
183 wp->nrows = 1;
184 wp->xb = (wp->width - SIZE_X * wp->ncols) / 2;
185 wp->yb = (wp->height - SIZE_Y * wp->nrows) / 2;
186 wp->nplanets = MI_COUNT(mi);
187 if (wp->nplanets < -MINWORLDS)
188 wp->nplanets = NRAND(-wp->nplanets - MINWORLDS + 1) + MINWORLDS;
189 else if (wp->nplanets < MINWORLDS)
190 wp->nplanets = MINWORLDS;
191
192 if (wp->nplanets > wp->ncols * wp->nrows)
193 wp->nplanets = wp->ncols * wp->nrows;
194 #ifndef NOFLASH
195 if (wp->nplanets > wp->ncols)
196 wp->nplanets = wp->ncols;
197 #endif
198 if (wp->planets != NULL)
199 free(wp->planets);
200 if ((wp->planets = (planetstruct *) malloc(wp->nplanets *
201 sizeof (planetstruct))) == NULL) {
202 return;
203 }
204 for (i = 0; i < wp->nplanets; i++)
205 wp->planets[i].x = wp->planets[i].y = -1;
206
207 MI_CLEARWINDOW(mi);
208 }
209
210 ENTRYPOINT void
draw_world(ModeInfo * mi)211 draw_world(ModeInfo * mi)
212 {
213 Display *display = MI_DISPLAY(mi);
214 GC gc = MI_GC(mi);
215 int i;
216 #ifndef NOFLASH
217 int *col, j;
218 #endif
219 worldstruct *wp;
220
221 if (worlds == NULL)
222 return;
223 wp = &worlds[MI_SCREEN(mi)];
224 if (wp->planets == NULL)
225 return;
226
227 #ifndef NOFLASH
228 if ((col = (int *) calloc(wp->ncols, sizeof (int))) == NULL)
229 return;
230 #endif
231
232 MI_IS_DRAWN(mi) = True;
233
234 if (wp->frame_num == NUM_EARTHS * NUM_REV) {
235 wp->frame_num = 0;
236 XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
237 for (i = 0; i < wp->nplanets; i++) {
238 XFillRectangle(display, MI_WINDOW(mi), gc,
239 wp->xb + SIZE_X * wp->planets[i].x,
240 wp->yb + SIZE_Y * wp->planets[i].y,
241 SIZE_X, SIZE_Y);
242 #ifdef NOFLASH
243 wp->planets[i].x = NRAND(wp->ncols);
244 #else
245 do {
246 j = NRAND(wp->ncols);
247 if (!col[j])
248 wp->planets[i].x = j;
249 col[j]++;
250 } while (col[j] > 1);
251 #endif
252 wp->planets[i].y = NRAND(wp->nrows);
253 wp->planets[i].direction = (int) (LRAND() & 1);
254 wp->planets[i].frame = NRAND(NUM_EARTHS);
255 if (MI_NPIXELS(mi) > 2)
256 wp->planets[i].color = MI_PIXEL(mi, NRAND(MI_NPIXELS(mi)));
257 else
258 wp->planets[i].color = MI_WHITE_PIXEL(mi);
259 }
260 }
261 #ifndef NOFLASH
262 free(col);
263 #endif
264 for (i = 0; i < wp->nplanets; i++) {
265 XSetForeground(display, gc, wp->planets[i].color);
266 if (wp->planets[i].frame == NUM_EARTHS)
267 wp->planets[i].frame = 0;
268 else {
269 if ((wp->planets[i].frame < 0) && wp->planets[i].direction == 0)
270 wp->planets[i].frame = NUM_EARTHS - 1;
271 }
272 (void) XPutImage(display, MI_WINDOW(mi), gc,
273 (Earths + wp->planets[i].frame), 0, 0,
274 wp->xb + SIZE_X * wp->planets[i].x,
275 wp->yb + SIZE_Y * wp->planets[i].y,
276 SIZE_X, SIZE_Y);
277
278 (wp->planets[i].direction) ? wp->planets[i].frame++ : wp->planets[i].frame--;
279 }
280 wp->frame_num++;
281 }
282
283 ENTRYPOINT void
release_world(ModeInfo * mi)284 release_world(ModeInfo * mi)
285 {
286 if (worlds != NULL) {
287 int screen;
288
289 for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
290 free_world_screen(&worlds[screen]);
291 free(worlds);
292 worlds = (worldstruct *) NULL;
293 }
294 }
295
296 #ifndef STANDALONE
297 ENTRYPOINT void
refresh_world(ModeInfo * mi)298 refresh_world(ModeInfo * mi)
299 {
300 MI_CLEARWINDOW(mi);
301 }
302 #endif
303
304 XSCREENSAVER_MODULE ("World", world)
305
306 #endif /* MODE_world */
307