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