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