1 /* -*- Mode: C; tab-width: 4 -*- */
2 /* pyro --- fireworks */
3 
4 #if 0
5 static const char sccsid[] = "@(#)pyro2.c	5.26 2008/02/07 xlockmore";
6 #endif
7 
8 
9 /*-
10  * 1991, Pezhman Givy.
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  */
26 
27 #ifdef STANDALONE
28 #define MODE_pyro2
29 #define DEFAULTS "*delay: 15000 \n" \
30 	"*count: 1 \n" \
31 	"*size: -3 \n" \
32 	"*ncolors: 200 \n" \
33 	"*use3d: False \n" \
34 	"*delta3d: 1.5 \n" \
35 	"*right3d: red \n" \
36 	"*left3d: blue \n" \
37 	"*both3d: magenta \n" \
38 	"*none3d: black \n" \
39 
40 # define free_pyro2 0
41 # define reshape_pyro2 0
42 # define pyro2_handle_event 0
43 # define UNIFORM_COLORS
44 # include "xlockmore.h"		/* in xscreensaver distribution */
45 #else /* STANDALONE */
46 # include "xlock.h"		/* in xlockmore distribution */
47 # include "color.h"
48 # include "iostuff.h"
49 #endif /* STANDALONE */
50 
51 #define PYRO_NHUES    7
52 #define PYRO_NSHADES  20
53 #define PYRO_NCOLORS (PYRO_NHUES*PYRO_NSHADES)
54 #define PYRO_NPOINTS  3  /* colorpath */
55 
56 
57 #ifdef MODE_pyro2
58 
59 #define DEF_INVERT  "False"
60 
61 static Bool invert;
62 
63 typedef unsigned int uint32;
64 
65 #ifdef __VMS
66 #define DEFAULT_MSG	"&0&1&2&3&4&5&6&7&8&9&a&b OpenVMS &a&b"
67 #else
68 #ifdef WIN32
69 #define DEFAULT_MSG	"&0&1&2&3&4&5&6&7&8&9&a&b Windows &a&b"
70 #else
71 #define DEFAULT_MSG	"&0&1&2&3&4&5&6&7&8&9&a&b Unix &a&b"
72 #endif
73 #endif
74 #define DEFAULT_FNT	"-*-helvetica-bold-r-*-240-*"
75 
76 static int pyrocnt;
77 static char *modparam_msg, *modparam_fnt;
78 static XFontStruct *messagefont = None;
79 
80 static XrmOptionDescRec opts[] = {
81 	{(char *) "-invert", (char *) ".pyro2.invert", XrmoptionNoArg, (caddr_t) "on"},
82 	{(char *) "+invert", (char *) ".pyro2.invert", XrmoptionNoArg, (caddr_t) "off"},
83 	{(char *) "-msg", (char *) ".pyro2.msg", XrmoptionSepArg, (caddr_t) NULL},
84 	{(char *) "-fnt", (char *) ".pyro2.fnt", XrmoptionSepArg, (caddr_t) NULL}
85 };
86 
87 static argtype vars[] = {
88 	{(void *) &invert, (char *) "invert", (char *) "Invert", (char *) DEF_INVERT, t_Bool},
89 	{(void *) &modparam_msg, (char *) "msg", (char *) "Msg", (char *) DEFAULT_MSG, t_String},
90 	{(void *) &modparam_fnt, (char *) "fnt", (char *) "Fnt", (char *) DEFAULT_FNT, t_String}
91 };
92 
93 static OptionStruct desc[] = {
94         {(char *) "-/+invert", (char *) "turn on/off inverting of sparks for image"},
95 	{(char *) "-msg str", (char *) "Pyro command (default: " DEFAULT_MSG ")"},
96 	{(char *) "-fnt font", (char *) "Font to use (default " DEFAULT_FNT ")"}
97 };
98 
99 ENTRYPOINT ModeSpecOpt pyro2_opts =
100 {	sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
101 
102 #ifdef USE_MODULES
103 ModStruct   pyro2_description =
104 {	"pyro2",		/* cmdline_arg: mode name */
105 	"init_pyro2",		/* init_name: name of init a mode */
106 	"draw_pyro2",		/* callback_name: name of run (tick) a mode */
107 	"release_pyro2",	/* release_name: name of shutdown of a mode */
108 	"refresh_pyro2",	/* refresh_name: name of mode to repaint */
109 	"init_pyro2",		/* change_name: name of mode to change */
110 	(char *) NULL,		/* unused_name: name for future expansion */
111 	&pyro2_opts,		/* msopt: this mode's def resources */
112 	30000,			/* def_delay: default delay for mode */
113 	400,			/* def_count: */
114 	1,			/* def_cycles: */
115 	-3,			/* def_size: */
116 	1024,			/* def_ncolors: */
117 	1.0,			/* def_saturation: */
118 	"",			/* def_bitmap: */
119 	"Shows other fireworks",/* desc: text description of mode */
120 	0,			/* flags: state flags for this mode */
121 	NULL			/* userdata: for use by the mode */
122 };
123 
124 #endif
125 
126 static char * ostext = NULL;
127 
128 /*
129  * 26051990 phg
130  */
131 
132 #include <stdlib.h>
133 #include <stdio.h>
134 #include <errno.h>
135 #include <string.h>
136 #include <math.h>
137 
138 #ifdef USE_XVMSUTILS
139 #include <X11/unix_time.h>
140 #endif
141 #if HAVE_SYS_TIME_H
142 #include <sys/time.h>
143 #else
144 #if HAVE_SYS_SELECT_H
145 #include <sys/select.h>
146 #endif
147 #endif
148 
149 #if !defined(FALSE)
150 #define FALSE	0
151 #endif /* !defined(FALSE) */
152 
153 #if !defined(TRUE)
154 #define TRUE	1
155 #endif /* !defined(TRUE) */
156 
157 #define RAD(x)	((x) / 180.0 * M_PI)
158 #define DEG(x)	((x)/M_PI * 180.0)
159 #if !defined(ABS)
160 #define ABS(x)	((x) >=0? (x):(-(x)))
161 #endif /* !defined(ABS) */
162 
163 #define SIN(x)	(sin(RAD(x)))
164 #define COS(x)	(cos(RAD(x)))
165 #define TAN(x)	(tan(RAD(x)))
166 #define NOP(x)	(1.0)
167 
168 #define WAIT		0
169 #define PARABEL		1
170 #define EXPLOSION	2
171 #define READY		3
172 
173 #ifndef WIN32
174 #ifndef STANDALONE
175 /* aliases for vars defined in the bitmap file */
176 #define LOGO_WIDTH   image_width
177 #define LOGO_HEIGHT    image_height
178 #define LOGO_BITS    image_bits
179 
180 #include "pyro2.xbm"
181 
182 #ifdef HAVE_XPM
183 #define LOGO_NAME  image_name
184 #include "pyro2.xpm"
185 #define DEFAULT_XPM 0
186 #endif
187 #endif
188 
189 #if !defined( VMS ) || ( __VMS_VER >= 70000000 )
190 #include <sys/utsname.h>
191 #else
192 #ifdef USE_XVMSUTILS
193 #if 0
194 #include "../xvmsutils/utsname.h"
195 #else
196 #include <X11/utsname.h>
197 #endif
198 #endif /* USE_XVMSUTILS */
199 #endif
200 #endif
201 
202 typedef struct para {
203 	int init;	/* == true : initialization needed */
204 	int color;
205 	double t;
206 	double th;
207 	double v0;
208 	double phi;
209 	int x1, y1;
210 	int x2, y2;
211 }PARA;
212 
213 /*
214 for the moment there are 11 distinct internal explosion types.
215 Each type has its own ID. An ID is a character between
216 '0' and '9' or 'a' and 'z'. 'a' corresponds to 10 and
217 'z' to 35. The type ID 42 is reserved for glyph explosions.
218 
219 you can address a particular internal explosion by typing '&' followed by
220 its ID. When the applied ID is not (yet) used the last used ID is assumed.
221 
222 Each explosion consists of several generations.
223 a collection of sparks created at same time is denoted as a generation of sparks
224 how many generations are produced is controlled by the defined EXP_MAX_GENERATION
225 */
226 
227 typedef struct	{
228 	int init;
229 	int x0, y0;
230 	double *time;	/* time since explosion for each spark :-) */
231 	double *v0;	/* initial speed of each spark */
232 	double *delta_t;/* value to be added to the time in each iteration for each spark */
233 	double *angle;	/* angle of the each spark as it leaves the explosion center */
234 	double *m;	/* */
235 	int *generation;/* the generation of each spark */
236 	int *x1, *y1;
237 	int *x2, *y2;
238 	int *ttl;	/* time to leave of each spark (max = EXP_MAX_TTL) */
239 	int current_generation;/* current generation of sparks */
240 	int sparkcnt;	/* current count of sparks */
241 	unsigned int type;	/* type of spark */
242 	int firsttime;
243 	int *color;
244 	union	{	/* custom data for each explosion type, if needed */
245 		int integer;
246 		double *dbl_ptr;
247 		int *int_ptr;
248 		char *chr_ptr;
249 		long *lng_ptr;
250 	} typedata;
251 }EXPL;
252 
253 typedef struct	{
254 	int dotcnt;
255 	float *phi;
256 	float *v0;
257 	XImage *image;
258 } LOGO_BITMAP;
259 
260 #define TEXT_LEN 256
261 typedef struct pyro {
262 	int stat;	/* status der rakette: parabell, explosion, fertig */
263 	int wait;	/* warten bevor start */
264 	int textlen;
265 	char text[TEXT_LEN];
266 	LOGO_BITMAP *bitmap;
267 	unsigned int etype;
268 	PARA para;
269 	EXPL expl;
270 	int  color1, color2; /* startcolor, index in pp->colors */
271 }PYRO;
272 
273 typedef struct {
274 	GC		gc;
275 	Colormap	cmap;
276 	XColor		*colors;
277 	int		ncolors;
278 	unsigned long	blackpixel, whitepixel, fg, bg, love;
279 
280 	int		nhues;
281 	int		nsteps;
282 } pyrostruct;
283 
284 static void parabel(ModeInfo * mi, PYRO *p);
285 static void explosion(ModeInfo * mi, PYRO *p);
286 static int calc(ModeInfo * mi, PYRO *p);
287 
288 static PYRO *pyro;
289 
290 static pyrostruct *pyros = NULL;
291 
292 static void
free_a_pyro(PYRO * p)293 free_a_pyro(PYRO *p)
294 {
295 
296 	if(p->expl.time)	{free(p->expl.time);	p->expl.time = NULL;}
297 	if(p->expl.v0)		{free(p->expl.v0);	p->expl.v0 = NULL;}
298 	if(p->expl.delta_t)	{free(p->expl.delta_t);	p->expl.delta_t = NULL;}
299 	if(p->expl.angle)	{free(p->expl.angle);	p->expl.angle = NULL;}
300 	if(p->expl.generation)	{free(p->expl.generation);	p->expl.generation = NULL;}
301 	if(p->expl.color)	{free(p->expl.color);	p->expl.color = NULL; }
302 	if(p->expl.ttl)		{free(p->expl.ttl);	p->expl.ttl = NULL;}
303 
304 	return;
305 }
306 
307 static void
free_pyro2_screen(ModeInfo * mi,Display * display,pyrostruct * pp)308 free_pyro2_screen(ModeInfo *mi, Display *display, pyrostruct *pp)
309 {
310 	if (pp == NULL) {
311 		return;
312 	}
313 	if (MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
314 		if(pp->colors && pp->ncolors) { /* FIXME: if !no_colors */
315 			free_colors(
316 #ifdef STANDALONE
317 				MI_SCREENPTR(mi),
318 #else
319 				display,
320 #endif
321 				pp->cmap, pp->colors, pp->ncolors);
322 		}
323 		if (pp->colors != NULL) {
324 			free(pp->colors);
325 		}
326 		if (pp->cmap) {
327 			XFreeColormap(display, pp->cmap);
328 		}
329 		if (pp->gc != None) {
330 			MI_WHITE_PIXEL(mi) = pp->whitepixel;
331 			MI_BLACK_PIXEL(mi) = pp->blackpixel;
332 #ifndef STANDALONE
333 			MI_FG_PIXEL(mi) = pp->fg;
334 			MI_BG_PIXEL(mi) = pp->bg;
335 #endif
336 			XFreeGC(display, pp->gc);
337 		}
338 	}
339 	pp = NULL;
340 }
341 
342 /*#define delay(x)	usleep(x)*/
343 #define delay(x)	(x)
calc(ModeInfo * mi,PYRO * pyro)344 static int calc(ModeInfo * mi, PYRO *pyro)
345 {
346 	int i, ret;
347 
348 	ret = 0;
349 
350 	for(i=0;i<pyrocnt;++i)
351 		switch(pyro[i].stat) {
352 			case WAIT:
353 				ret = 1;
354 				if(--pyro[i].wait <= 0) {
355 					pyro[i].stat = PARABEL;
356 				}
357 				/*else
358 					delay(1);*/
359 				break;
360 			case PARABEL:
361 				ret = 1;
362 				parabel(mi, &pyro[i]);
363 				/*delay(1);*/
364 				break;
365 			case EXPLOSION:
366 				ret = 1;
367 				explosion(mi, &pyro[i]);
368 				break;
369 			default:
370 				pyro[i].stat = READY;
371 				free_a_pyro(&pyro[i]);
372 				/*delay(1);*/
373 		}
374 
375 
376 	return ret;
377 }
378 
379 /*
380  * A bang body of the mass m leaves at the time t=0 the origin
381  * of a xy-coordinate system with a start velocity v0 and angle phi.
382  * Then the following aplies:
383  *
384  * x(t) = (v0*cos(phi))*t;
385  * y(t) = (v0*sin(phi))*t - 1/2*g*t*t;
386  *
387  * The time at which the maximum ascend is arrived (th) will be
388  * th = (v0*sin(phi))/g;
389  *
390  * "H. Heuser, Lehrbuch der Analysis, Part I, page 328 (Wurf)
391  */
392 
393 
394 /*
395  * ein knallkoerper der masse m verlasse zur zeit t=0 den nullpunkt
396  * eines xy-koordinatensystems mit einer anfangsgeschwindigkeit vom
397  * betrage v0 unter dem winkel phi (0<phi<=pi/2).
398  * so gilt:
399  *	x(t) = (v0*cos(phi))*t;
400  *	y(t) = (v0*sin(phi))*t - 1/2*g*t*t;
401  * die steigzeit th der maximalen steighoehe betraegt
402  * th = (v0*sin(phi))/g;
403  *
404  * aus h. heuser, lehrbuch der analysis teil 1, seite 328(wurf)
405  *
406  * 30.10.1994, luftreibung wird nicht beruecksichtig
407  */
408 
parabel(ModeInfo * mi,PYRO * p)409 static void parabel(ModeInfo * mi, PYRO *p)
410 {
411 	Display    *display = MI_DISPLAY(mi);
412 	GC          gc = MI_GC(mi);
413 	Window      window = MI_WINDOW(mi);
414 	PARA *pa;
415 	int x, y;
416 
417 	pa = &p->para;
418 
419 	if(pa->init == FALSE) {
420 		pa->phi = 80.0 + (double)NRAND(20);
421 		/*pa->phi = 60.0 + (double)NRAND(60);*/
422 		pa->v0 = 23.0;
423 		/*pa->v0 = 10.0 + NRAND(10);*/
424 		pa->th = pa->v0 * SIN(pa->phi) / 9.81;
425 		pa->t = 0.0;
426 	}
427 
428 	/*
429 	x = MI_WIDTH(mi) /2 + (int)(pa->v0*COS(pa->phi)*pa->t*30.0);
430 	y = MI_HEIGHT(mi) - (int)((pa->v0*SIN(pa->phi)*pa->t - 0.5*9.81*pa->t*pa->t)*30.0);
431 	*/
432 
433 	x = MI_WIDTH(mi) /2 + (int)(pa->v0*COS(pa->phi)*pa->t* MI_WIDTH(mi)/35.0 );
434 	y = MI_HEIGHT(mi) - (int)((pa->v0*SIN(pa->phi)*pa->t - 0.5*9.81*pa->t*pa->t)* MI_HEIGHT(mi)/35.0 );
435 
436 	if(x<0 || x>=MI_WIDTH(mi) || y<0 || y>=MI_HEIGHT(mi))	x = y = -1;
437 
438 	if(pa->init == FALSE) {
439 		pa->x1 = x;
440 		pa->y1 = y;
441 		pa->x2 = -1;
442 		pa->y2 = -1;
443 	}
444 	else
445 		if(pa->x1>=0 && pa->y1>=0 && pa->x2>=0 && pa->y2>=0) {
446 			XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
447 			XDrawLine(display, window, gc, pa->x1, pa->y1, pa->x2, pa->y2);
448 		}
449 
450 	if(pa->t<pa->th-0.02 && pa->x2>=0 && pa->y2>=0 && x>=0 && y>=0) {
451 		XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
452 		XDrawLine(display, window, gc, pa->x2, pa->y2, x, y);
453 	}
454 
455 	pa->x1 = pa->x2;
456 	pa->y1 = pa->y2;
457 	pa->x2 = x;
458 	pa->y2 = y;
459 	if(pa->init == FALSE)	pa->init = TRUE;
460 	if((pa->t += 0.02) > pa->th) {
461 		p->stat = EXPLOSION;
462 		pa->init = FALSE;
463 	}
464 
465 	return;
466 }
467 
468 #define EXP_MAX_GENERATION	(30)
469 #define EXP_MAX_TTL		(200)
470 /*#define EXP_MAX_TTL		(250)*/
471 /*#define EXP_MIN_SPARKS		(10)*/
472 #define EXP_MIN_SPARKS		(20)
473 #define EXP_RND_SPARKS		(20)
474 #define EXP_MAX_SPARKS		(EXP_MIN_SPARKS + EXP_RND_SPARKS)
475 #define EXP_MAX_DOTS		(EXP_MAX_GENERATION * EXP_MAX_SPARKS * 20)
476 
477 /*
478 static int rbits, gbits, bbits;
479 static int rpos, gpos, bpos;
480 
481 static int get_red(double val)
482 {
483 	return ((int)(val*(double)((1<<rbits)-1))&((1<<rbits)-1)) << rpos;
484 }
485 
486 static int get_green(double val)
487 {
488 	return ((int)(val*(double)((1<<gbits)-1))&((1<<gbits)-1)) << gpos;
489 }
490 
491 static int get_blue(double val)
492 {
493 	return (int)(val*(double)((1<<bbits)-1))&((1<<bbits)-1) << bpos;
494 }
495 
496 #define COLOR(r,g,b)	(get_red(r)|get_green(g)|get_blue(b))
497 */
498 
499 double heart[] = {
500 0.80999300,0.80999300,0.82499300,0.82599300,0.82699300,0.82799300,0.82899300,0.83099300,
501 0.83299300,0.84999300,0.83799300,0.83999300,0.84299300,0.84599300,0.84999300,0.85399300,
502 0.85799300,0.84699300,0.85199300,0.85699300,0.86199300,0.85199300,0.85799300,0.85299300,
503 0.85499300,0.85699300,0.85299300,0.85249300,0.85199300,0.84399300,0.83999300,0.83799300,
504 0.83599300,0.82799300,0.82899300,0.82999300,0.81299300,0.81499300,0.79999400,0.79999400,
505 0.78899400,0.78599400,0.77899400,0.76499400,0.76399400,0.75799400,0.74499400,0.73299500,
506 0.72099500,0.70999500,0.69999500,0.70799500,0.67999500,0.67099500,0.66299600,0.65399600,
507 0.64699600,0.63899600,0.63199600,0.60799600,0.60199700,0.57999700,0.57399700,0.56899700,
508 0.54799700,0.54399700,0.52299800,0.50399800,0.49999800,0.48099800,0.46299900,0.45999900,
509 0.44199900,0.42399900,0.40699900,0.40500000,0.38800000,0.35700000,0.34100100,0.34000100,
510 0.30900100,0.30800100,0.27800100,0.27800100,0.23300100,0.23300100,0.23300100,0.20300000,
511 0.20300000,0.20300000,0.20300000,0.20300000,0.20300000,0.20300000,0.20400000,0.23300100,
512 0.23300100,0.23400100,0.27800100,0.27900100,0.30900100,0.34000100,0.34100100,0.37200000,
513 0.38800000,0.39000000,0.40699900,0.42399900,0.45699900,0.45999900,0.46299900,0.48099800,
514 0.49999800,0.51899800,0.52299800,0.54399700,0.54799700,0.56899700,0.57399700,0.59599700,
515 0.60199700,0.60799600,0.63199600,0.63899600,0.64699600,0.65399600,0.66299600,0.67099500,
516 0.67999500,0.70799500,0.69999500,0.70999500,0.72099500,0.73299500,0.74499400,0.75799400,
517 0.76599400,0.76499400,0.77899400,0.78799400,0.78899400,0.80199300,0.79999400,0.81699300,
518 0.81299300,0.83199300,0.82899300,0.82999300,0.83799300,0.84399300,0.83999300,0.84499300,
519 0.85399300,0.84599300,0.85499300,0.85699300,0.85699300,0.85299300,0.85999300,0.85399300,
520 0.86399300,0.85899300,0.85399300,0.84899300,0.85999300,0.85499300,0.85199300,0.84799300,
521 0.84499300,0.84199300,0.83899300,0.83699300,0.83399300,0.83199300,0.83099300,0.82899300,
522 0.82799300,0.82699300,0.81199300,0.81199300,0.81199300,0.81199300,0.81199300,0.79799400,
523 0.79899400,0.78599400,0.78699400,0.77399400,0.76099400,0.76299400,0.75099400,0.75299400,
524 0.74099400,0.72899500,0.71799500,0.70599500,0.69399500,0.69299500,0.67099500,0.66699600,
525 0.66399600,0.64699600,0.64099600,0.62999600,0.61899600,0.61699600,0.59699700,0.60199700,
526 0.58599700,0.58099700,0.57899700,0.56199700,0.56499700,0.55799700,0.54399700,0.53099800,
527 0.53799700,0.52999800,0.51799800,0.52299800,0.51799800,0.50799800,0.50799800,0.50999800,
528 0.49999800,0.49299800,0.50199800,0.49499800,0.48699800,0.48699800,0.49199800,0.48499800,
529 0.47799800,0.48299800,0.48299800,0.47799800,0.47199900,0.47999800,0.47799800,0.47299800,
530 0.46799900,0.47199850,0.47599800,0.47999800,0.48399800,0.47999800,0.47599800,0.48399800,
531 0.48399800,0.48699800,0.49299800,0.48999800,0.48699800,0.49799800,0.49699800,0.50699800,
532 0.50799800,0.51799800,0.51799800,0.53099800,0.52999800,0.54299700,0.54099700,0.55499700,
533 0.56099700,0.56699700,0.59499700,0.59499700,0.62299600,0.65199600,0.65199600,0.65199600,
534 0.62299600,0.59499700,0.59499700,0.58199700,0.55299700,0.55499700,0.54099700,0.54299700,
535 0.52999800,0.52799800,0.51799800,0.51199800,0.50799800,0.50099800,0.49699800,0.49299800,
536 0.48699800,0.48999800,0.49299800,0.48299800,0.48399800,0.47999800,0.47599800,0.47999800,
537 0.48399800,0.47699800,0.47599800,0.47699800,0.46799900,0.47299800,0.47799800,0.47799800,
538 0.47199900,0.47799800,0.48299800,0.47999800,0.47799800,0.48499800,0.49199800,0.48499800,
539 0.48699800,0.49499800,0.49999800,0.49199800,0.49999800,0.50999800,0.50599800,0.50799800,
540 0.51799800,0.52099800,0.51799800,0.52999800,0.54199700,0.54699700,0.54399700,0.55799700,
541 0.56299700,0.56199700,0.57899700,0.57899700,0.58599700,0.60099700,0.59599700,0.61699600,
542 0.61799600,0.62999600,0.63999600,0.64699600,0.66199600,0.66699600,0.66899500,0.69299500,
543 0.69199500,0.70399500,0.71599500,0.71299500,0.73999400,0.75199400,0.74899400,0.74699400,
544 0.75999400,0.77299400,0.78599400,0.78399400,0.79799400,0.79699400,0.81099300,0.80999300
545 };
546 
explosion(ModeInfo * mi,PYRO * p)547 static void explosion(ModeInfo * mi, PYRO *p)
548 {
549 	Display    *display = MI_DISPLAY(mi);
550 	Window      window = MI_WINDOW(mi);
551 	int xk1, yk1, xk2, yk2;
552 	EXPL *e = &p->expl;
553 	double x1, y1, x2, y2;
554 	double phi, m, step;
555 	int i, sparks;
556 	int sumttl;
557 	static int num = 0;
558 
559 	double v0, dt, t;
560 
561 	pyrostruct *pp = &pyros[MI_SCREEN(mi)];
562 
563 	GC          gc = pp->gc;
564 
565 	++num;
566 	if(e->init == FALSE) {
567 		/* every spark has its own angle and initial speed (v0) */
568 		e->angle = (double *) calloc(EXP_MAX_DOTS, sizeof(double));
569 		e->time = (double *) calloc(EXP_MAX_DOTS, sizeof(double));
570 		e->delta_t = (double *) calloc(EXP_MAX_DOTS, sizeof(double));
571 		e->v0 = (double *) calloc(EXP_MAX_DOTS, sizeof(double));
572 		e->ttl = (int *) calloc(EXP_MAX_DOTS, sizeof(int));
573 		e->generation = (int *) calloc(EXP_MAX_DOTS, sizeof(int));
574 		e->x1 = (int *) calloc(EXP_MAX_DOTS, sizeof(int));
575 		e->y1 = (int *) calloc(EXP_MAX_DOTS, sizeof(int));
576 		e->x2 = (int *) calloc(EXP_MAX_DOTS, sizeof(int));
577 		e->y2 = (int *) calloc(EXP_MAX_DOTS, sizeof(int));
578 		e->color = (int *) calloc(EXP_MAX_DOTS, sizeof(int));
579 		e->m = (double *) calloc(EXP_MAX_DOTS, sizeof(double));
580 		e->current_generation = 0;
581 		e->firsttime = 0;
582 		e->x0 = p->para.x2;
583 		e->y0 = p->para.y2;
584 		e->sparkcnt = 0;
585 		e->init = TRUE;
586 
587 		e->type = p->etype;
588 
589 		switch(e->type)	{
590 			case 4:
591 				e->typedata.integer = 1;
592 				break;
593 			default:
594 				e->typedata.integer = 0;
595 				break;
596 		}
597 	}
598 	else
599 		++e->current_generation;
600 
601 /* rho = 1.293 g/l = 0.001293 kg/l */
602 #define rho (5.0)
603 #define factor (2)
604 /*#define rho (3.0)*/
605 /*#define factor (2.0)*/
606 
607 	sumttl = 0;
608 	for(i=0;i<e->sparkcnt;++i) sumttl += e->ttl[i]>0? e->ttl[i]:0;
609 
610 	for(i=0;i<e->sparkcnt;++i)	{
611 		--e->ttl[i];
612 		phi = e->angle[i];
613 		v0 = e->v0[i];
614 		t = e->time[i];
615 		dt = e->delta_t[i];
616 		m = e->m[i];
617 
618 		x1 = m * v0 * COS(phi) / rho * (1-exp(-rho/m*t));
619 		y1 = m/rho * (v0 * SIN(phi) + m*9.81/rho)*(1-exp(-rho/m*t)) - m*9.81/rho * t;
620 		xk1 = e->x0 + x1;
621 		yk1 = e->y0 - y1;
622 
623 		if(e->firsttime == 1 && e->ttl[i] >= 0){
624 			XSetForeground(display, gc, MI_BLACK_PIXEL(mi));
625 			XDrawLine(display, window, gc, e->x1[i], e->y1[i], e->x2[i], e->y2[i]);
626 		}
627 
628 		if(sumttl < 1)	{
629 			p->stat = READY;
630 			e->init = FALSE;
631 			continue;
632 		}
633 
634 		if(e->ttl[i] < 1)	continue;
635 
636 		t = e->time[i] + dt;
637 
638 		x2 = m * v0 * COS(phi) / rho * (1-exp(-rho/m*t));
639 		y2 = m/rho * (v0 * SIN(phi) + m*9.81/rho)*(1-exp(-rho/m*t)) - m*9.81/rho * t;
640 		xk2 = e->x0 + x2;
641 		yk2 = e->y0 - y2;
642 
643 		e->x1[i] = xk1;
644 		e->y1[i] = yk1;
645 		e->x2[i] = xk2;
646 		e->y2[i] = yk2;
647 
648 		/*
649 		XSetForeground(display, gc,
650 			pp->colors[ (int)
651 			(((double)e->ttl[i]/(double)EXP_MAX_TTL)*pp->ncolors)].pixel);
652 		*/
653 
654 
655 
656 
657 		if(MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
658 		XSetForeground(display, gc,
659 			pp->colors[ e->color[i] + PYRO_NSHADES-1 - (int)
660 			(((double)e->ttl[i]/(double)EXP_MAX_TTL)*PYRO_NSHADES)].pixel);
661 		} else {
662 			if (MI_NPIXELS(mi) > 2)
663 				XSetForeground(display, gc, (MI_PIXEL(mi, e->color[i] + PYRO_NSHADES-1 - (int) (((double)e->ttl[i]/(double)EXP_MAX_TTL)*PYRO_NSHADES) % MI_NCOLORS(mi))));
664 			else
665 				XSetForeground(display, gc, MI_WHITE_PIXEL(mi));
666 		}
667 
668 
669 		XDrawLine(display, window, gc, xk1, yk1, xk2, yk2);
670 
671 		e->time[i] = t;
672 		e->delta_t[i] += 0.001;
673 		/*e->delta_t[i] += MI_DELAY(mi) / 1000000.0;*/
674 	}
675 
676 	if(e->current_generation >= EXP_MAX_GENERATION) {
677 		return;
678 	}
679 	e->firsttime = 1;
680 
681 	sparks = (p->bitmap != NULL && (e->type == 42 || e->type == 23))? p->bitmap->dotcnt:EXP_MIN_SPARKS+NRAND(EXP_RND_SPARKS);
682 
683 	if(e->type == 42 && e->current_generation > 0) {
684 		return;
685 	}
686 
687 	step = 360.0 / sparks;
688 	phi = 1.0+(double)NRAND(10);
689 
690 	for(i=0;i<sparks;++i)	{
691 		e->angle[e->sparkcnt] = phi;
692 		e->color[e->sparkcnt] = ( (e->sparkcnt & 1) && p->color2!=-1) ? p->color2 : p->color1;
693 
694 		e->ttl[e->sparkcnt] = EXP_MAX_TTL/2+NRAND(EXP_MAX_TTL/1);
695 		e->generation[e->sparkcnt] = e->current_generation;
696 		e->time[e->sparkcnt] = 0.0;
697 		e->delta_t[e->sparkcnt] = 0; /*0.001;*/
698 		/*e->m[e->sparkcnt] = 0.5 + NRAND(10)/10.0;*/ /*NRAND(2)? 1.0:1.3;*/
699 		e->m[e->sparkcnt] = 2 + NRAND(2)/2.0; /*NRAND(2)? 1.0:1.3;*/
700 
701 		switch(e->type)	{
702 			case 0:	{/* ? */
703 				double tmp = (double)e->current_generation/(double)EXP_MAX_GENERATION;
704 
705 				e->ttl[e->sparkcnt] = EXP_MAX_TTL/10+NRAND(EXP_MAX_TTL/2);
706 				e->v0[e->sparkcnt] = NRAND(30)+SIN(tmp *90.0) * MI_WIDTH(mi)/10 * factor;
707 			}
708 			break;
709 			case 1:	{
710 				double tmp = (double)e->current_generation/(double)EXP_MAX_GENERATION;
711 				e->v0[e->sparkcnt] = NRAND(30)+SIN(tmp *360.0) * MI_WIDTH(mi)/10 * factor;
712 			}
713 			break;
714 			case 2:	{
715 					double tmp = (double)e->current_generation/(double)EXP_MAX_GENERATION;
716 					e->v0[e->sparkcnt] = NRAND(30)+COS(tmp *180.0) * MI_WIDTH(mi)/5 * factor;
717 					/*e->v0[e->sparkcnt] = NRAND(30)+COS(tmp *180.0) * 200;*/
718 				}
719 			break;
720 			case 3:	{
721 					double tmp = (double)e->current_generation/(double)EXP_MAX_GENERATION;
722 					e->v0[e->sparkcnt] = NRAND(30)+SIN(tmp*360.0) * COS(tmp*360.0) * MI_WIDTH(mi)/5 * factor;
723 				}
724 			break;
725 			case 4: {
726 					if(i == 0)	e->typedata.integer = -e->typedata.integer;
727 					e->v0[e->sparkcnt] = NRAND(30)+(i+2)*e->typedata.integer*MI_WIDTH(mi)/200 * factor;
728 				}
729 			break;
730 			case 5:	{
731 				/*double tmp = (double)e->current_generation/(double)EXP_MAX_GENERATION;*/
732 				e->v0[e->sparkcnt] = NRAND(30)+COS((int)((double)e->current_generation/(double)EXP_MAX_GENERATION *360.0) % 90) * COS((double)e->current_generation/(double)EXP_MAX_GENERATION *360.0) * MI_WIDTH(mi)/5 * factor;
733 			}
734 			break;
735 			case 6:	{
736 				double tmp = (double)e->current_generation/(double)EXP_MAX_GENERATION;
737 				e->v0[e->sparkcnt] = NRAND(30)+((i-sparks/2)*SIN(phi*10)*SIN(tmp*360.0))*MI_WIDTH(mi)/100 * factor;
738 			}
739 			break;
740 			case 7:	{
741 				/*double tmp = (double)e->current_generation/(double)EXP_MAX_GENERATION;*/
742 				e->v0[e->sparkcnt] = NRAND(30)+((i-sparks/2)*SIN(phi*10)*SIN((int)((double)e->current_generation/(EXP_MAX_GENERATION)*360.0)%90))*MI_WIDTH(mi)/50 * factor;
743 			}
744 			break;
745 			case 8:
746 				e->v0[e->sparkcnt] = NRAND(30)+(SIN((i+1.0)/(EXP_MIN_SPARKS+EXP_RND_SPARKS)*360.0)*(1.0*i))*MI_WIDTH(mi)/100 * factor;
747 				break;
748 			case 9:	{
749 				double tmp = (double)e->current_generation/(double)EXP_MAX_GENERATION;
750 				e->v0[e->sparkcnt] = NRAND(30)+SIN(tmp *360.0*4.0) * MI_WIDTH(mi)/10 * factor;
751 			}
752 			break;
753 			case 10:
754 				e->ttl[e->sparkcnt] = EXP_MAX_TTL/2+NRAND(EXP_MAX_TTL/1)+5;
755 				e->v0[e->sparkcnt] = heart[(int)((double)i/(double)sparks *360.0)] * (e->current_generation)*MI_WIDTH(mi)/150 * factor;
756 				if (MI_IS_INSTALL(mi))
757 					e->color[e->sparkcnt] = PYRO_NSHADES; /* pp->love; MI_RED_MASK(mi); */
758 				else
759 					e->color[e->sparkcnt] = MI_NCOLORS(mi) - 2; /* pp->love; MI_RED_MASK(mi); */
760 				break;
761 			case 11:	{
762 				double tmp = (double)i/(double)sparks;
763 				e->v0[e->sparkcnt] = NRAND(30) + SIN(tmp*90)*COS(tmp*180)*i*(i&1? 1:-1)*MI_WIDTH(mi)/100 * factor;
764 				break;
765 			}
766 			case 13:	{
767 				/*double tmp = (double)e->current_generation/(double)EXP_MAX_GENERATION;*/
768 				e->v0[e->sparkcnt] = NRAND(2)? i * 20:(sparks-i)*20;
769 				break;
770 
771 			}
772 			case 14:	{
773 				/*double tmp = (double)e->current_generation/(double)EXP_MAX_GENERATION;*/
774 				e->v0[e->sparkcnt] = 5+ (NRAND(20) == 3? i:(sparks-i))*20;
775 				break;
776 
777 			}
778 			case 23:
779 			case 42:	/* glyphs */
780 				if (p->bitmap != NULL) {
781 				/*e->angle[e->sparkcnt] = (double)p->glyph->phi[i]/1000000.0;*/
782 				/*e->v0[e->sparkcnt] = (double)p->glyph->dist[i]/1000000.0 * 600;*/
783 				/*e->color[e->sparkcnt] = MI_RED_MASK(mi)|MI_GREEN_MASK(mi);*/
784 
785 				e->angle[e->sparkcnt] = (double)p->bitmap->phi[i];
786 				e->v0[e->sparkcnt] = (double)p->bitmap->v0[i] * MI_WIDTH(mi)/4 * factor;
787 				/*e->v0[e->sparkcnt] = (double)p->bitmap->v0[i] * 300.0;*/
788 				e->m[e->sparkcnt] = 1.0 + NRAND(50)/800.0;
789 
790 				e->current_generation = EXP_MAX_GENERATION;
791 				break;
792 				}
793 			default:
794 			case 12:	{
795 				double tmp = (double)e->current_generation/(double)EXP_MAX_GENERATION;
796 				/*e->v0[e->sparkcnt] = NRAND(30) + ABS(SIN(tmp * 90.0 * 3) * tmp ) * 200;*/
797 				/*e->v0[e->sparkcnt] = NRAND(30) + (tmp <= 0.3 ? SIN(tmp * 90.0):tmp <= 0.6? SIN((tmp-0.3) * 90.0):SIN((tmp-0.6)*90.0)) * (tmp + 0.5)* 200+10;*/
798 				e->v0[e->sparkcnt] = NRAND(10)+15 + (tmp <= 0.3 ? SIN(tmp * 90.0):tmp <= 0.6? SIN((tmp-0.3) * 90.0):SIN((tmp-0.6)*90.0)) * (tmp + 0.5)* MI_WIDTH(mi)/5 * factor;
799 				/*e->v0[e->sparkcnt] = NRAND(10)+15 + (tmp <= 0.3 ? SIN(tmp * 90.0):tmp <= 0.6? SIN((tmp-0.3) * 90.0):SIN((tmp-0.6)*90.0)) * (tmp + 0.5)* 200;*/
800 				break;
801 			}
802 		}
803 
804 		phi += step;
805 		++e->sparkcnt;
806 	}
807 
808 	return;
809 }
810 
811 #ifndef WIN32
text2image(ModeInfo * mi,char * msg,XImage ** image)812 static Bool text2image(ModeInfo * mi, char *msg, XImage ** image)
813 {
814 	Display    *display = MI_DISPLAY(mi);
815 	char       *text1, *text2;
816 	char       *line, *token;
817 	int         width, height;
818 	int         lines;
819 	int         margin = 2;
820 	XCharStruct overall;
821 	XGCValues   gcv;
822 	GC          gc;
823 	Pixmap      text_pixmap;
824 
825 	text1 = strdup(msg);
826 
827 	while (*text1 && (text1[strlen(text1) - 1] == '\r' ||
828 			text1[strlen(text1) - 1] == '\n'))
829 		text1[strlen(text1) - 1] = 0;
830 
831 	if ((text2 = (char *) strdup(text1)) == NULL) {
832 		free(text1);
833 		return False;
834 	}
835 
836 	(void) memset(&overall, 0, sizeof (overall));
837 	token = text1;
838 	lines = 0;
839 	while ((line = strtok(token, "\r\n"))) {
840 		XCharStruct o2;
841 		int         ascent, descent, direction;
842 
843 		token = 0;
844 		(void) XTextExtents(messagefont, line, strlen(line),
845 			&direction, &ascent, &descent, &o2);
846 		overall.lbearing = MAX(overall.lbearing, o2.lbearing);
847 		overall.rbearing = MAX(overall.rbearing, o2.rbearing);
848 		lines++;
849 	}
850 
851 	width = overall.lbearing + overall.rbearing + margin + margin + 1;
852 	height = ((messagefont->ascent + messagefont->descent) * lines) +
853 		margin + margin;
854 
855 	if ((text_pixmap = XCreatePixmap(display, MI_WINDOW(mi),
856 			width, height, 1)) == None) {
857 		free(text1);
858 		free(text2);
859 		return False;
860 	}
861 
862 	gcv.font = messagefont->fid;
863 	gcv.foreground = 0;
864 	gcv.background = 0;
865 	if ((gc = XCreateGC(display, text_pixmap,
866 			GCFont | GCForeground | GCBackground, &gcv)) == None) {
867 		XFreePixmap(display, text_pixmap);
868 		free(text1);
869 		free(text2);
870 		return False;
871 	}
872 	XFillRectangle(display, text_pixmap, gc, 0, 0, width, height);
873 	XSetForeground(display, gc, 1);
874 
875 	token = text2;
876 	lines = 0;
877 	while ((line = strtok(token, "\r\n"))) {
878 		XCharStruct o2;
879 		int         ascent, descent, direction, xoff;
880 
881 		token = 0;
882 
883 		(void) XTextExtents(messagefont, line, strlen(line),
884 			&direction, &ascent, &descent, &o2);
885 		xoff = ((overall.lbearing + overall.rbearing) -
886 			(o2.lbearing + o2.rbearing)) / 2;
887 
888 		(void) XDrawString(display, text_pixmap, gc,
889 			overall.lbearing + margin + xoff,
890 			((messagefont->ascent * (lines + 1)) +
891 			(messagefont->descent * lines) + margin),
892 			line, strlen(line));
893 		lines++;
894 	}
895 	free(text1);
896 	free(text2);
897 	/*XUnloadFont(display, messagefont->fid); */
898 	XFreeGC(display, gc);
899 
900 	if ((*image = XGetImage(display, text_pixmap, 0, 0, width, height,
901 			1L, XYPixmap)) == NULL) {
902 		XFreePixmap(display, text_pixmap);
903 		return False;
904 	}
905 	XFreePixmap(display, text_pixmap);
906 
907 	return True;
908 }
909 
XImage2bitmap(XImage * image,LOGO_BITMAP * bitmap,int white)910 static Bool XImage2bitmap(XImage *image, LOGO_BITMAP *bitmap, int white)
911 {
912 	int x, y, offset;
913 	char mask;
914 	int xbeg, xend, ybeg, yend;
915 	int xmid, ymid, dotcnt = 0;
916 	double maxdist;
917 	int xstep, ystep;
918 
919 	xbeg = image->width;
920 	xend = 0;
921 	ybeg = image->height;
922 	yend = 0;
923 	dotcnt = 0;
924 	xstep = 1;
925 	ystep = 1;
926 
927 	for(y=0;y<image->height;y+=ystep)	{
928 		for(x=0;x<image->width;x+=xstep)	{
929 			offset = image->bytes_per_line * y + x / 8;
930 			mask = 1 << (x%8);
931 
932 			if (((image->data[offset] & mask) == (white << (x%8)) && invert) ||
933 			((image->data[offset] & mask) != (white << (x%8)) && !invert)) {
934 				/* fprintf(stderr, "X");*/
935 				if(x < xbeg)	xbeg = x;
936 				if(x > xend)	xend = x;
937 				if(y < ybeg)	ybeg = y;
938 				if(y > yend)	yend = y;
939 				++dotcnt;
940 			}
941 			/* else
942 				fprintf(stderr, "_"); */
943 		}
944 		/* fprintf(stderr, "\n");*/
945 
946 	}
947 
948 	bitmap->dotcnt = dotcnt;
949 	bitmap->phi = (float *) calloc(dotcnt, sizeof(float));
950 	bitmap->v0 = (float *) calloc(dotcnt, sizeof(float));
951 
952 	xmid = xbeg + (xend - xbeg) / 2;
953 	ymid = ybeg + (yend - ybeg) / 2;
954 
955 	maxdist = sqrt( (xend - xbeg)*(xend - xbeg) + (yend - ybeg)*(yend - ybeg) ) / 2;
956 
957 	dotcnt = 0;
958 	for(y=0;y<image->height;y+=ystep)	{
959 		for(x=0;x<image->width;x+=xstep)	{
960 			offset = y * image->bytes_per_line  + x / 8;
961 			mask = 1 << (x%8);
962 
963 			if (((image->data[offset] & mask) == (white << (x%8)) && invert) ||
964 			((image->data[offset] & mask) != (white << (x%8)) && !invert)) {
965 				double a = x - xmid;
966 				double b = y - ymid;
967 				double dist = sqrt(a * a + b * b) / maxdist;
968 				double phi = -DEG(fabs(a) < 1 && fabs(b) < 1? 0 : atan2(b, a));
969 
970 				bitmap->phi[dotcnt] = phi;
971 				bitmap->v0[dotcnt] = dist;
972 
973 				++dotcnt;
974 			}
975 		}
976 	}
977 
978 	return TRUE;
979 }
980 
text2bitmap(ModeInfo * mi,char * text)981 static LOGO_BITMAP *text2bitmap(ModeInfo *mi, char *text)
982 {
983 	LOGO_BITMAP *bitmap;
984 
985 	if(!(bitmap = (LOGO_BITMAP *) calloc(1, sizeof(LOGO_BITMAP))))	return NULL;
986 
987 	if(!text2image(mi, text, &bitmap->image))	{
988 		free(bitmap);
989 		return NULL;
990 	}
991 
992 	XImage2bitmap(bitmap->image, bitmap, 1);
993 
994 	return bitmap;
995 }
996 #endif
997 
998 #ifndef STANDALONE
999 	extern char *background;
1000 	extern char *foreground;
1001 #endif
1002 
1003 ENTRYPOINT void
release_pyro2(ModeInfo * mi)1004 release_pyro2(ModeInfo * mi)
1005 {
1006 	if (pyros != NULL) {
1007 		int         screen;
1008 		Display *display = MI_DISPLAY(mi);
1009 
1010 		for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++)
1011 			free_pyro2_screen(mi, display, &pyros[screen]);
1012 		free(pyros);
1013 		pyros = (pyrostruct *) NULL;
1014 	}
1015 	if (messagefont != None) {
1016 		XFreeFont(MI_DISPLAY(mi), messagefont);
1017 		messagefont = None;
1018 	}
1019 	if (ostext != NULL) {
1020 		free(ostext);
1021 		ostext = NULL;
1022 	}
1023 }
1024 
1025 ENTRYPOINT void
init_pyro2(ModeInfo * mi)1026 init_pyro2(ModeInfo * mi)
1027 {
1028 	int i;
1029 	/*time_t t = time(NULL);*/
1030 	int text_in_buffer = FALSE;
1031 	char *rov;
1032 	/*static char defaultString[] =
1033 #ifdef __VMS
1034 	"&0&1&2&3&4&5&6&7&8&9&a&b OpenVMS &a&b";
1035 #else
1036 	"&0&1&2&3&4&5&6&7&8&9&a&b Unix &a&b";
1037 #endif*/
1038 	Display *display = MI_DISPLAY(mi);
1039 	Window  window = MI_WINDOW(mi);
1040 	pyrostruct *pp;
1041 
1042 	MI_INIT(mi, pyros);
1043         if (messagefont == None) {
1044 		if (modparam_fnt != NULL &&
1045 				!(messagefont = XLoadQueryFont(display, modparam_fnt)))	{
1046 			(void) fprintf(stderr, "can not find font '%s', using %s\n", modparam_fnt, DEFAULT_FNT);
1047 		}
1048         	if (messagefont == None) {
1049 			if ((messagefont = getFont(display)) == None) {
1050 				release_pyro2(mi);
1051 				return;
1052 			}
1053 		}
1054 	}
1055 
1056 	pp = &pyros[MI_SCREEN(mi)];
1057 	if(!pp->gc) {
1058 		if(MI_IS_INSTALL(mi) && MI_NPIXELS(mi) > 2) {
1059 #ifdef STANDALONE
1060 			Screen *screen = MI_SCREENPTR(mi);
1061 			Visual *visual = MI_VISUAL(mi);
1062 #endif
1063 			XColor      color;
1064 			int hue, ncol;
1065 
1066 #ifndef STANDALONE
1067 			pp->fg = MI_FG_PIXEL(mi);
1068 			pp->bg = MI_BG_PIXEL(mi);
1069 #endif
1070 			pp->blackpixel = MI_BLACK_PIXEL(mi);
1071 			pp->whitepixel = MI_WHITE_PIXEL(mi);
1072 			pp->cmap = XCreateColormap(display, window,
1073 					MI_VISUAL(mi), AllocNone);
1074 			XSetWindowColormap(display, window, pp->cmap);
1075 			(void) XParseColor(display, pp->cmap, "black", &color);
1076 			(void) XAllocColor(display, pp->cmap, &color);
1077 			MI_BLACK_PIXEL(mi) = color.pixel;
1078 			(void) XParseColor(display, pp->cmap, "white", &color);
1079 			(void) XAllocColor(display, pp->cmap, &color);
1080 			MI_WHITE_PIXEL(mi) = color.pixel;
1081 #ifndef STANDALONE
1082 			(void) XParseColor(display, pp->cmap, background, &color);
1083 			(void) XAllocColor(display, pp->cmap, &color);
1084 			MI_BG_PIXEL(mi) = color.pixel;
1085 			(void) XParseColor(display, pp->cmap, foreground, &color);
1086 			(void) XAllocColor(display, pp->cmap, &color);
1087 			MI_FG_PIXEL(mi) = color.pixel;
1088 
1089 			(void) XParseColor(display, pp->cmap, "red", &color);
1090 			(void) XAllocColor(display, pp->cmap, &color);
1091 			pp->love = color.pixel;
1092 #endif
1093 
1094 			pp->ncolors = PYRO_NCOLORS;
1095 
1096 			if((pp->colors = (XColor *) calloc(pp->ncolors,sizeof(XColor))) == NULL) {
1097 				return;
1098 			}
1099 #undef PYRO_RAMP
1100 #ifdef PYRO_RAMP
1101 			/* glitter, huebsch */
1102 			make_color_ramp(
1103 #ifdef STANDALONE
1104 							screen, visual,
1105 #else
1106 							display,
1107 #endif
1108 							pp->cmap,
1109 							45,(double)0.0,(double)0.0,
1110 							0,(double)1.0,(double)1.0,
1111 							pp->colors,
1112 							&pp->ncolors,
1113 							False,
1114 							True,
1115 							False);
1116 #endif
1117 
1118 			pp->ncolors = 0;
1119 
1120 			for(hue=0; hue < PYRO_NHUES ; ++hue ) {
1121 				int h;
1122 
1123 				h = hue ? (360/(PYRO_NHUES-1)) * (hue-1) : 0;
1124 
1125 				ncol = PYRO_NSHADES/10;
1126 				make_color_ramp(
1127 #ifdef STANDALONE
1128 								screen, visual,
1129 #else
1130 								display,
1131 #endif
1132 								pp->cmap,
1133 								h,!hue?0.0:(double)atof(getenv("S1") ? getenv("S1") : "0.0"),(double)atof(getenv("B1") ? getenv("B1") : "1.0"),
1134 								h,!hue?0.0:(double)atof(getenv("S2") ? getenv("S2") : "0.8"),(double)atof(getenv("B2") ? getenv("B1") : "1.0"),
1135 								&pp->colors[hue*PYRO_NSHADES],
1136 								&ncol,
1137 								False,
1138 								True,
1139 								False);
1140 
1141 #if defined(DEBUG)
1142 				fprintf(stderr, "1Got %d colors\n", ncol);
1143 #endif /* defined(DEBUG) */
1144 				pp->ncolors += ncol;
1145 
1146 				ncol = PYRO_NSHADES/10*9;
1147 				make_color_ramp(
1148 #ifdef STANDALONE
1149 								screen, visual,
1150 #else
1151 								display,
1152 #endif
1153 								pp->cmap,
1154 								h,!hue?0.0:(double)atof(getenv("S2") ? getenv("S2") : "0.8"),(double)atof(getenv("B2") ? getenv("B2") : "1.0"),
1155 								h,!hue?0.0:(double)atof(getenv("S3") ? getenv("S3") : "1.0"),(double)atof(getenv("B3") ? getenv("B3") : "0.0"),
1156 								&pp->colors[hue*PYRO_NSHADES+PYRO_NSHADES/10],
1157 								&ncol,
1158 								False,
1159 								True,
1160 								False);
1161 
1162 #if defined(DEBUG)
1163 				fprintf(stderr, "2Got %d colors\n", ncol);
1164 #endif /* defined(DEBUG) */
1165 				pp->ncolors += ncol;
1166 			}
1167 
1168 
1169 			/*
1170 			make_color_path(display, pp->cmap,
1171 						PYRO_NHUES * PYRO_NPOINTS,
1172 						col_h, col_s, col_b,
1173 						pp->colors,
1174 						&pp->ncolors,
1175 						True,
1176 						False);
1177 
1178 			fprintf(stderr, "Got %d colors\n", pp->ncolors);
1179 			*/
1180 		}
1181 
1182 		if ((pp->gc = XCreateGC(display, MI_WINDOW(mi), (unsigned long) 0, (XGCValues *) NULL)) == None) return;
1183 	}
1184 
1185 	/* Clear Display */
1186 	MI_CLEARWINDOW(mi);
1187 
1188 	if(pyro) {
1189 		for(i=0;i<pyrocnt;++i)
1190 			if(pyro[i].bitmap)	{
1191 				free(pyro[i].bitmap->phi);
1192 				free(pyro[i].bitmap->v0);
1193 				free(pyro[i].bitmap);
1194 			}
1195 
1196 		free(pyro);
1197 	}
1198 
1199 #if !defined( __VMS ) && !defined( WIN32 )
1200 	if (!modparam_msg || !*modparam_msg) {
1201 		struct utsname uts;
1202 
1203 		if (uname(&uts) < 0) {
1204 			ostext = (char *) strdup("uname() failed");
1205 		} else {
1206 			if ((ostext = (char *) malloc(strlen(uts.sysname) +
1207 					31)) != NULL)
1208 				(void) sprintf(ostext,
1209 					"&0&1&2&3&4&5&6&7&8&9&a&b %s &a&b",
1210 					uts.sysname);
1211 		}
1212 	}
1213 #endif
1214 	if (!modparam_msg || !*modparam_msg) {
1215 		if (ostext == NULL)
1216 			rov = (char *) DEFAULT_MSG;
1217 		else
1218 			rov = ostext;
1219 	} else
1220 		rov = modparam_msg;
1221 	pyrocnt = 0;
1222 	text_in_buffer = FALSE;
1223 
1224 	while(*rov)	{
1225 		switch(*rov)	{
1226 			case '&':		/* internal explosion type */
1227 				rov += 2;
1228 				if(text_in_buffer == TRUE)	++pyrocnt;
1229 				text_in_buffer = FALSE;
1230 				++pyrocnt;
1231 				break;
1232 			case '#':
1233 				++rov;
1234 				if(text_in_buffer == TRUE)	++pyrocnt;
1235 				text_in_buffer = FALSE;
1236 				++pyrocnt;
1237 				break;
1238 			case ' ':
1239 				++rov;
1240 				break;
1241 			default:
1242 
1243 				if(*rov == ' ' && text_in_buffer == FALSE)
1244 					/*++rov;*/
1245 					break;
1246 
1247 				if(*rov == '\\')
1248 					switch(rov[1])	{
1249 						case '&':
1250 						case '\\':
1251 						case '#':
1252 						case ' ':
1253 							++rov;
1254 							break;
1255 						default:
1256 							break;
1257 				}
1258 				text_in_buffer = TRUE;
1259 				++rov;
1260 				break;
1261 		}
1262 	}
1263 	if(text_in_buffer)	++pyrocnt;
1264 
1265 	pyro = (PYRO *) calloc(pyrocnt, sizeof(PYRO));
1266 	if (!modparam_msg || !*modparam_msg) {
1267 		if (ostext == NULL)
1268 			rov = (char*) DEFAULT_MSG;
1269 		else
1270 			rov = ostext;
1271 	} else
1272 		rov = modparam_msg;
1273 	text_in_buffer = FALSE;
1274 	i = 0;
1275 
1276 	while(*rov)	{
1277 		switch(*rov)	{
1278 			case '&':	{
1279 				static char buf[8];
1280 				int type = 0;
1281 				if(text_in_buffer == TRUE)	++i;
1282 				text_in_buffer = FALSE;
1283 
1284 				memset(buf, 0, sizeof(buf));
1285 				++rov;
1286 				*buf = *rov++;
1287 				if(*buf >= '0' && *buf <= '9')	type = *buf - '0';
1288 				if(*buf >= 'a' && *buf <= 'z')	type = *buf - 'a' + 10;
1289 				if(*buf >= 'A' && *buf <= 'Z')	type = *buf - 'A' + 10;
1290 				pyro[i].etype = type;
1291 				++i;
1292 			}
1293 			break;
1294 #if !defined(STANDALONE) && !defined(WIN32)
1295 			case '#':	{	/* logo */
1296 				XImage *image;
1297 				int graphics_format;
1298 				Colormap cmap;
1299 				unsigned long black;
1300 				LOGO_BITMAP *bitmap;
1301 
1302 				if(text_in_buffer == TRUE)	++i;
1303 				text_in_buffer = FALSE;
1304 
1305 				getImage(mi, &image, LOGO_WIDTH, LOGO_HEIGHT, LOGO_BITS,
1306 #ifdef HAVE_XPM
1307 				DEFAULT_XPM, LOGO_NAME,
1308 #endif
1309 				&graphics_format, &cmap, &black);
1310 				bitmap = (LOGO_BITMAP *) calloc(1, sizeof(LOGO_BITMAP));
1311 				XImage2bitmap(image, bitmap, 0);
1312 				pyro[i].bitmap = bitmap;
1313 				pyro[i].etype = 23;
1314 				++i;
1315 				++rov;
1316 
1317 				break;
1318 			}
1319 #endif
1320 			default:	{
1321 				uint32 charcode = 0;
1322 
1323 				if(*rov == ' ' && text_in_buffer == FALSE)	{
1324 					++rov;
1325 					break;
1326 				}
1327 
1328 				if(*rov == '\\')
1329 					switch(rov[1])	{
1330 						case '&':
1331 						case '\\':
1332 						case ' ':
1333 							++rov;
1334 							break;
1335 						case 'n':
1336 							++rov;
1337 							++rov;
1338 							charcode = '\n';
1339 							break;
1340 						default:
1341 							/*++rov;*/
1342 							break;
1343 					}
1344 
1345 				if(!charcode)
1346 					charcode = ((unsigned char)*rov++) & 0xFF;
1347 				/*if (pyro[i].textlen >= TEXT_LEN - 1)
1348 					pyro[i].textlen = 0;
1349 				else*/
1350 					pyro[i].textlen++;
1351 				pyro[i].text[pyro[i].textlen] = charcode;
1352 				pyro[i].etype = 42;
1353 				text_in_buffer = TRUE;
1354 			}
1355 			break;
1356 		}
1357 	}
1358 
1359 	for(i=0;i<pyrocnt;++i)	{
1360 #ifndef WIN32
1361 		if(pyro[i].textlen)
1362 			pyro[i].bitmap = text2bitmap(mi, pyro[i].text);
1363 #endif
1364 
1365 		pyro[i].stat = WAIT;
1366 		pyro[i].wait = i * 100;
1367 
1368 		pyro[i].color1 = NRAND(PYRO_NHUES)*PYRO_NSHADES; /* offset into pp->colors */
1369 		pyro[i].color2 = getenv("MULTICOL") ? NRAND(PYRO_NHUES)*PYRO_NSHADES : -1; /* offset into pp->colors */
1370 	}
1371 }
1372 
1373 ENTRYPOINT void
draw_pyro2(ModeInfo * mi)1374 draw_pyro2(ModeInfo * mi)
1375 {
1376 	Display    *display = MI_DISPLAY(mi);
1377 	GC          gc = MI_GC(mi);
1378 	Window      window = MI_WINDOW(mi);
1379 	int i;
1380 
1381 	pyrostruct *pp = &pyros[MI_SCREEN(mi)];
1382 
1383 #if 1
1384 
1385 	if(getenv("COLTEST")) {
1386 #if defined(DEBUG)
1387 		fprintf(stderr, "red   = %08lX\n", MI_RED_MASK(mi));
1388 		fprintf(stderr, "green = %08lX\n", MI_GREEN_MASK(mi));
1389 		fprintf(stderr, "blue  = %08lX\n", MI_BLUE_MASK(mi));
1390 #endif /* defined(DEBUG) */
1391 
1392 		for(i=0;i<MI_WIDTH(mi);++i)	{
1393 			XSetForeground(display, gc, pp->colors[i / (MI_WIDTH(mi)/pp->ncolors + 1)].pixel);
1394 			XDrawLine(display, window, gc, i, 0, i, MI_HEIGHT(mi));
1395 		}
1396 
1397 		return;
1398 	}
1399 #endif
1400 
1401 	if(!calc(mi, pyro)) init_pyro2(mi);
1402 }
1403 
1404 #ifndef STANDALONE
1405 ENTRYPOINT void
refresh_pyro2(ModeInfo * mi)1406 refresh_pyro2(ModeInfo * mi)
1407 {
1408 	if (MI_IS_INSTALL(mi) && MI_IS_USE3D(mi)) {
1409 		MI_CLEARWINDOWCOLOR(mi, MI_NONE_COLOR(mi));
1410 	} else {
1411 		MI_CLEARWINDOW(mi);
1412 	}
1413 }
1414 #endif
1415 
1416 XSCREENSAVER_MODULE ("Pyro2", pyro2)
1417 
1418 #endif /* MODE_pyro2 */
1419