http://ftp.x.org/contrib/applications/xscreensaver-3.24.tar.gz
[xscreensaver] / hacks / xflame.c
1 /* xflame, Copyright (c) 1996-1999 Carsten Haitzler <raster@redhat.com>
2  *
3  * Permission to use, copy, modify, distribute, and sell this software and its
4  * documentation for any purpose is hereby granted without fee, provided that
5  * the above copyright notice appear in all copies and that both that
6  * copyright notice and this permission notice appear in supporting
7  * documentation.  No representations are made about the suitability of this
8  * software for any purpose.  It is provided "as is" without express or 
9  * implied warranty.
10  */
11
12 /* Version history as near as I (jwz) can piece together:
13
14    * Carsten Haitzler <raster@redhat.com> wrote the first version in 1996.
15
16    * Rahul Jain <rahul@rice.edu> added support for TrueColor displays.
17
18    * Someone did a rough port of it to use the xscreensaver utility routines
19      instead of creating its own window by hand.
20
21    * Someone (probably Raster) came up with a subsequent version that had
22      a Red Hat logo hardcoded into it.
23
24    * Daniel Zahn <stumpy@religions.com> found that version in 1998, and 
25      hacked it to be able to load a different logo from a PGM (P5) file, 
26      with a single hardcoded pathname.
27
28    * Jamie Zawinski <jwz@jwz.org> found several versions of xflame in
29      March 1999, and pieced them together.  Changes:
30
31        - Correct and fault-tolerant use of the Shared Memory extension;
32          previous versions of xflame did not work when $DISPLAY was remote.
33
34        - Replaced PGM-reading code with code that can read arbitrary XBM
35          and XPM files (color ones will be converted to grayscale.)
36
37        - Command-line options all around -- no hardcoded pathnames or
38          behavioral constants.
39
40        - General cleanup and portability tweaks.
41
42    * 4-Oct-99, jwz: added support for packed-24bpp (versus 32bpp.)
43
44  */
45
46
47 /* portions by Daniel Zahn <stumpy@religions.com> */
48
49
50 #include "screenhack.h"
51 #include <X11/Xutil.h>
52 #include <limits.h>
53
54 #ifdef HAVE_XSHM_EXTENSION
55 # include "xshm.h"
56 #endif /* HAVE_XSHM_EXTENSION */
57
58 #ifdef HAVE_XPM
59 # include <X11/xpm.h>
60 # ifndef PIXEL_ALREADY_TYPEDEFED
61 #  define PIXEL_ALREADY_TYPEDEFED /* Sigh, Xmu/Drawing.h needs this... */
62 # endif
63 #endif
64
65 #ifdef HAVE_XMU
66 # ifndef VMS
67 #  include <X11/Xmu/Drawing.h>
68 # else  /* VMS */
69 #  include <Xmu/Drawing.h>
70 # endif /* VMS */
71 #endif /* HAVE_XMU */
72
73 #include "images/bob.xbm"
74
75 #define MAX_VAL             255
76
77 static Display         *display;
78 static Window          window;
79 static int             depth;
80 static int             width;
81 static int             height;
82 static Colormap        colormap;
83 static Visual          *visual;
84 static Bool            shared;
85 static Bool            bloom;
86 static XImage          *xim;
87 #ifdef HAVE_XSHM_EXTENSION
88 static XShmSegmentInfo shminfo;
89 #endif /* HAVE_XSHM_EXTENSION */
90 static GC              gc;
91 static int             ctab[256];
92
93 static unsigned char  *flame;
94 static unsigned char  *theim;
95 static int             fwidth;
96 static int             fheight;
97 static int             top;
98 static int             hspread;
99 static int             vspread;
100 static int             residual;
101
102 static int ihspread;
103 static int ivspread;
104 static int iresidual;
105 static int variance;
106 static int vartrend;
107
108 static void
109 GetXInfo(Display *disp, Window win)
110 {
111   XWindowAttributes xwa;
112    
113   XGetWindowAttributes(disp,win,&xwa);
114
115   window   = win;
116   display  = disp;
117   colormap = xwa.colormap;
118   depth    = xwa.depth;
119   visual   = xwa.visual;
120   width    = xwa.width;
121   height   = xwa.height;
122
123   if (width%2)
124     width++;
125   if (height%2)
126     height++;
127 }
128
129 static void
130 MakeImage(void)
131 {
132   XGCValues gcv;
133
134 #ifdef HAVE_XSHM_EXTENSION
135   shared = True;
136   xim = create_xshm_image (display, visual, depth, ZPixmap, NULL,
137                            &shminfo, width, height);
138 #else  /* !HAVE_XSHM_EXTENSION */
139   xim = 0;
140 #endif /* !HAVE_XSHM_EXTENSION */
141
142   if (!xim)
143     {
144       shared = False;
145       xim = XCreateImage (display, visual, depth, ZPixmap, 0, NULL,
146                           width, height, 32, 0);
147       if (xim)
148         xim->data = (char *) calloc(xim->height, xim->bytes_per_line);
149       if (!xim || !xim->data)
150         {
151           fprintf(stderr,"%s: out of memory.\n", progname);
152           exit(1);
153         }
154     }
155
156   gc = XCreateGC(display,window,0,&gcv);
157   if (!gc) exit (1);
158 }
159
160
161 static void
162 InitColors(void)
163 {
164   int i = 0, j = 0, red = 0, green = 0, blue = 0;
165   XColor fg;
166
167   /* Make it possible to set the color of the flames, 
168      by Raymond Medeiros <ray@stommel.marine.usf.edu> and jwz.
169   */
170   fg.pixel = get_pixel_resource ("foreground", "Foreground",
171                                  display, colormap);
172   XQueryColor (display, colormap, &fg);
173
174   red   = 255 - (fg.red   >> 8);
175   green = 255 - (fg.green >> 8);
176   blue  = 255 - (fg.blue  >> 8);
177
178
179   for (i = 0; i < 256 * 2; i += 2)
180     {
181       XColor xcl;
182       int r = (i - red)   * 3;
183       int g = (i - green) * 3;
184       int b = (i - blue)  * 3;
185     
186       if (r < 0)   r = 0;
187       if (r > 255) r = 255;
188       if (g < 0)   g = 0;
189       if (g > 255) g = 255;
190       if (b < 0)   b = 0;
191       if (b > 255) b = 255;
192
193       xcl.red   = (unsigned short)((r << 8) | r);
194       xcl.green = (unsigned short)((g << 8) | g);
195       xcl.blue  = (unsigned short)((b << 8) | b);
196       xcl.flags = DoRed | DoGreen | DoBlue;
197
198       XAllocColor(display,colormap,&xcl);
199
200       ctab[j++] = (int)xcl.pixel;
201     }
202 }
203
204
205 static void
206 DisplayImage(void)
207 {
208 #ifdef HAVE_XSHM_EXTENSION
209   if (shared)
210     XShmPutImage(display, window, gc, xim, 0,(top - 1) << 1, 0,
211                  (top - 1) << 1, width, height - ((top - 1) << 1), False);
212   else
213 #endif /* HAVE_XSHM_EXTENSION */
214     XPutImage(display, window, gc, xim, 0, (top - 1) << 1, 0,
215               (top - 1) << 1, width, height - ((top - 1) << 1));
216 }
217
218
219 static void
220 InitFlame(void)
221 {
222   fwidth  = width / 2;
223   fheight = height / 2;
224   flame   = (unsigned char *) malloc((fwidth + 2) * (fheight + 2)
225                                      * sizeof(unsigned char));
226
227   if (!flame)
228     {
229       fprintf(stderr,"%s: out of memory\n", progname);
230       exit(1);
231     }
232
233   top      = 1;
234   ihspread  = get_integer_resource("hspread", "Integer");
235   ivspread  = get_integer_resource("vspread", "Integer");
236   iresidual = get_integer_resource("residual", "Integer");
237   variance  = get_integer_resource("variance", "Integer");
238   vartrend  = get_integer_resource("vartrend", "Integer");
239   bloom     = get_boolean_resource("bloom",    "Boolean");
240
241 # define THROTTLE(VAR,NAME) \
242   if (VAR < 0 || VAR > 255) { \
243     fprintf(stderr, "%s: %s must be in the range 0-255 (not %d).\n", \
244             progname, NAME, VAR); \
245     exit(1); }
246   THROTTLE (ihspread, "hspread");
247   THROTTLE (ivspread, "vspread");
248   THROTTLE (iresidual,"residual");
249   THROTTLE (variance, "variance");
250   THROTTLE (vartrend, "vartrend");
251 # undef THROTTLE
252
253
254
255   hspread = ihspread;
256   vspread = ivspread;
257   residual = iresidual;
258 }
259
260
261 static void
262 Flame2Image16(void)
263 {
264   int x,y;
265   unsigned short *ptr;
266   unsigned char *ptr1;
267   int v1,v2,v3,v4;
268
269   ptr  = (unsigned short *)xim->data;
270   ptr += (top << 1) * width;
271   ptr1 = flame + 1 + (top * (fwidth + 2));
272
273   for(y = top; y < fheight; y++)
274     {
275       for( x = 0; x < fwidth; x++)
276         {
277           v1 = (int)*ptr1;
278           v2 = (int)*(ptr1 + 1);
279           v3 = (int)*(ptr1 + fwidth + 2);
280           v4 = (int)*(ptr1 + fwidth + 2 + 1);
281           ptr1++;
282           *ptr++ = (unsigned short)ctab[v1];
283           *ptr   = (unsigned short)ctab[(v1 + v2) >> 1];
284           ptr   += width - 1;
285           *ptr++ = (unsigned short)ctab[(v1 + v3) >> 1];
286           *ptr   = (unsigned short)ctab[(v1 + v4) >> 1];
287           ptr   -= width - 1;
288         }
289       ptr  += width;
290       ptr1 += 2;
291     }
292 }
293
294 static void
295 Flame2Image32(void)
296 {
297   int x,y;
298   unsigned int *ptr;
299   unsigned char *ptr1;
300   int v1,v2,v3,v4;
301
302   ptr  = (unsigned int *)xim->data;
303   ptr += (top << 1) * width;
304   ptr1 = flame + 1 + (top * (fwidth + 2));
305
306   for( y = top; y < fheight; y++)
307     {
308       for( x = 0; x < fwidth; x++)
309         {
310           v1 = (int)*ptr1;
311           v2 = (int)*(ptr1 + 1);
312           v3 = (int)*(ptr1 + fwidth + 2);
313           v4 = (int)*(ptr1 + fwidth + 2 + 1);
314           ptr1++;
315           *ptr++ = (unsigned int)ctab[v1];
316           *ptr   = (unsigned int)ctab[(v1 + v2) >> 1];
317           ptr   += width - 1;
318           *ptr++ = (unsigned int)ctab[(v1 + v3) >> 1];
319           *ptr   = (unsigned int)ctab[(v1 + v4) >> 1];
320           ptr   -= width - 1;
321         }
322       ptr  += width;
323       ptr1 += 2;
324     }
325 }
326
327 static void
328 Flame2Image24(void)
329 {
330   int x,y;
331   unsigned char *ptr;
332   unsigned char *ptr1;
333   int v1,v2,v3,v4;
334
335   ptr  = (unsigned char *)xim->data;
336   ptr += (top << 1) * xim->bytes_per_line;
337   ptr1 = flame + 1 + (top * (fwidth + 2));
338
339   for( y = top; y < fheight; y++)
340     {
341       unsigned char *last_ptr = ptr;
342       for( x = 0; x < fwidth; x++)
343         {
344           v1 = (int)*ptr1;
345           v2 = (int)*(ptr1 + 1);
346           v3 = (int)*(ptr1 + fwidth + 2);
347           v4 = (int)*(ptr1 + fwidth + 2 + 1);
348           ptr1++;
349
350           ptr[2] = ((unsigned int)ctab[v1] & 0x00FF0000) >> 16;
351           ptr[1] = ((unsigned int)ctab[v1] & 0x0000FF00) >> 8;
352           ptr[0] = ((unsigned int)ctab[v1] & 0x000000FF);
353           ptr += 3;
354
355           ptr[2] = ((unsigned int)ctab[(v1 + v2) >> 1] & 0x00FF0000) >> 16;
356           ptr[1] = ((unsigned int)ctab[(v1 + v2) >> 1] & 0x0000FF00) >> 8;
357           ptr[0] = ((unsigned int)ctab[(v1 + v2) >> 1] & 0x000000FF);
358           ptr += ((width - 1) * 3);
359
360           ptr[2] = ((unsigned int)ctab[(v1 + v3) >> 1] & 0x00FF0000) >> 16;
361           ptr[1] = ((unsigned int)ctab[(v1 + v3) >> 1] & 0x0000FF00) >> 8;
362           ptr[0] = ((unsigned int)ctab[(v1 + v3) >> 1] & 0x000000FF);
363           ptr += 3;
364
365           ptr[2] = ((unsigned int)ctab[(v1 + v4) >> 1] & 0x00FF0000) >> 16;
366           ptr[1] = ((unsigned int)ctab[(v1 + v4) >> 1] & 0x0000FF00) >> 8;
367           ptr[0] = ((unsigned int)ctab[(v1 + v4) >> 1] & 0x000000FF);
368           ptr -= ((width - 1) * 3);
369         }
370
371       ptr = last_ptr + (xim->bytes_per_line << 1);
372       ptr1 += 2;
373     }
374 }
375
376 static void
377 Flame2Image8(void)
378 {
379   int x,y;
380   unsigned char *ptr;
381   unsigned char *ptr1;
382   int v1,v2,v3,v4;
383
384   ptr  = (unsigned char *)xim->data;
385   ptr += (top << 1) * width;
386   ptr1 = flame + 1 + (top * (fwidth + 2));
387
388   for(y=top;y<fheight;y++)
389     {
390       for(x=0;x<fwidth;x++)
391         {
392           v1 = (int)*ptr1;
393           v2 = (int)*(ptr1 + 1);
394           v3 = (int)*(ptr1 + fwidth + 2);
395           v4 = (int)*(ptr1 + fwidth + 2 + 1);
396           ptr1++;
397           *ptr++ = (unsigned char)ctab[v1];
398           *ptr   = (unsigned char)ctab[(v1 + v2) >> 1];
399           ptr   += width - 1;
400           *ptr++ = (unsigned char)ctab[(v1 + v3) >> 1];
401           *ptr   = (unsigned char)ctab[(v1 + v4) >> 1];
402           ptr   -= width - 1;
403         }
404       ptr  += width;
405       ptr1 += 2;
406     }
407 }
408
409 static void
410 Flame2Image1234567(void)
411 {
412   int x,y;
413   unsigned char *ptr1;
414   int v1,v2,v3,v4;
415
416   ptr1 = flame + 1 + (top * (fwidth + 2));
417
418   for( y = top; y < fheight; y++)
419     {
420       for( x = 0; x < fwidth; x++)
421         {
422           v1 = (int)*ptr1;
423           v2 = (int)*(ptr1 + 1);
424           v3 = (int)*(ptr1 + fwidth + 2);
425           v4 = (int)*(ptr1 + fwidth + 2 + 1);
426           ptr1++;
427           XPutPixel(xim,(x << 1),    (y << 1),    ctab[v1]);
428           XPutPixel(xim,(x << 1) + 1,(y << 1),    ctab[(v1 + v2) >> 1]);
429           XPutPixel(xim,(x << 1),    (y << 1) + 1,ctab[(v1 + v3) >> 1]);
430           XPutPixel(xim,(x << 1) + 1,(y << 1) + 1,ctab[(v1 + v4) >> 1]);
431         }
432     }
433 }
434
435 static void
436 Flame2Image(void)
437 {
438   switch (xim->bits_per_pixel)
439     {
440     case 32: Flame2Image32(); break;
441     case 24: Flame2Image24(); break;
442     case 16: Flame2Image16(); break;
443     case 8:  Flame2Image8();  break;
444     default:
445       if (xim->bits_per_pixel <= 7)
446         Flame2Image1234567();
447       else
448         abort();
449       break;
450     }
451 }
452
453
454 static void
455 FlameActive(void)
456 {
457   int x,v1;
458   unsigned char *ptr1;
459    
460   ptr1 = flame + ((fheight + 1) * (fwidth + 2));
461
462   for (x = 0; x < fwidth + 2; x++)
463     {
464       v1      = *ptr1;
465       v1     += ((random() % variance) - vartrend);
466       *ptr1++ = v1 % 255;
467     }
468
469   if (bloom)
470     {
471       v1= (random() % 100);
472       if (v1 == 10)
473         residual += (random()%10);
474       else if (v1 == 20)
475         hspread += (random()%15);
476       else if (v1 == 30)
477         vspread += (random()%20);
478     }
479
480   residual = ((iresidual* 10) + (residual *90)) / 100;
481   hspread  = ((ihspread * 10) + (hspread  *90)) / 100;
482   vspread  = ((ivspread * 10) + (vspread  *90)) / 100;
483 }
484
485
486 static void
487 FlameAdvance(void)
488 {
489   int x,y;
490   unsigned char *ptr2;
491   int newtop = top;
492
493   for (y = fheight + 1; y >= top; y--)
494     {
495       int used = 0;
496       unsigned char *ptr1 = flame + 1 + (y * (fwidth + 2));
497       for (x = 0; x < fwidth; x++)
498         {
499           int v1 = (int)*ptr1;
500           int v2, v3;
501           if (v1 > 0)
502             {
503               used = 1;
504               ptr2 = ptr1 - fwidth - 2;
505               v3   = (v1 * vspread) >> 8;
506               v2   = (int)*(ptr2);
507               v2  += v3;
508               if (v2 > MAX_VAL) 
509                 v2 = MAX_VAL;
510
511               *(ptr2) = (unsigned char)v2;
512               v3  = (v1 * hspread) >> 8;
513               v2  = (int)*(ptr2 + 1);
514               v2 += v3;
515               if (v2 > MAX_VAL) 
516                 v2 = MAX_VAL;
517           
518               *(ptr2 + 1) = (unsigned char)v2;
519               v2          = (int)*(ptr2 - 1);
520               v2         += v3;
521               if (v2 > MAX_VAL) 
522                 v2 = MAX_VAL;
523           
524               *(ptr2 - 1) = (unsigned char)v2;
525         
526               if (y < fheight + 1)
527                 {
528                   v1    = (v1 * residual) >> 8;
529                   *ptr1 = (unsigned char)v1;
530                 }
531             }
532           ptr1++;
533           if (used) 
534             newtop = y - 1;
535         }
536     }
537
538   top = newtop - 1;
539
540   if (top < 1)
541     top = 1;
542 }
543
544
545 static void
546 FlameFill(int val)
547 {
548   int x, y;
549   for (y = 0; y < fheight + 1; y++)
550     {
551       unsigned char *ptr1 = flame + 1 + (y * (fwidth + 2));
552       for (x = 0; x < fwidth; x++)
553         {
554           *ptr1 = val;
555           ptr1++;
556         }
557     }
558 }
559
560
561 static void
562 FlamePasteData(unsigned char *d, int xx, int yy, int w, int h)
563 {
564   unsigned char *ptr1,*ptr2;
565   ptr2 = d;
566
567   if (xx < 0) xx = 0;
568   if (yy < 0) yy = 0;
569
570   if ((xx >= 0) &&
571       (yy >= 0) &&
572       (xx + w <= fwidth) &&
573       (yy + h <= fheight))
574     {
575       int x, y;
576       for (y = 0; y < h; y++)
577         {
578           ptr1 = flame + 1 + xx + ((yy + y) * (fwidth + 2));
579           for (x = 0; x < w; x++)
580             {
581               if (*ptr2 / 24)
582                 *ptr1 += random() % (*ptr2 / 24);
583
584               ptr1++;
585               ptr2++;
586             }
587         }
588     }
589   else
590     {
591       static Bool warned = False;
592       if (!warned)
593         {
594           fprintf (stderr, "%s: window is %dx%d; image must be "
595                    "smaller than %dx%d (not %dx%d).\n",
596                    progname, width, height, fwidth, fheight, w, h);
597           warned = True;
598         }
599     }
600 }
601
602
603 static unsigned char *
604 loadBitmap(int *w, int *h)
605 {
606   char *bitmap_name = get_string_resource ("bitmap", "Bitmap");
607
608   if (!bitmap_name ||
609       !*bitmap_name ||
610       !strcmp(bitmap_name, "none"))
611     ;
612   else if (!strcmp(bitmap_name, "(default)"))   /* use the builtin */
613     {
614       XImage *ximage;
615       unsigned char *result, *o;
616       char *bits = (char *) malloc (sizeof(bob_bits));
617       int x, y;
618       int scale = ((width > bob_width * 11) ? 2 : 1);
619  
620       memcpy (bits, bob_bits, sizeof(bob_bits));
621       ximage = XCreateImage (display, visual, 1, XYBitmap, 0, bits,
622                              bob_width, bob_height, 8, 0);
623       ximage->byte_order = LSBFirst;
624       ximage->bitmap_bit_order = LSBFirst;
625       *w = ximage->width * scale;
626       *h = ximage->height * scale;
627       o = result = (unsigned char *) malloc ((*w * scale) * (*h * scale));
628       for (y = 0; y < *h; y++)
629         for (x = 0; x < *w; x++)
630           *o++ = (XGetPixel(ximage, x/scale, y/scale) ? 255 : 0);
631        
632       return result;
633     }
634   else  /* load a bitmap file */
635     {
636 #ifdef HAVE_XPM
637       XpmInfo xpm_info = { 0, };
638       XpmImage xpm_image = { 0, };
639
640       int result = XpmReadFileToXpmImage (bitmap_name, &xpm_image, &xpm_info);
641       if (result == XpmSuccess)
642         {
643           int x, y;
644           unsigned char *result, *o;
645           unsigned char *grays;
646           XWindowAttributes xgwa;
647
648           *w = xpm_image.width;
649           *h = xpm_image.height;
650           result = (unsigned char *) malloc ((*w) * (*h));
651           if (!result)
652             {
653               fprintf(stderr, "%s: out of memory loading %s\n",
654                       progname, bitmap_name);
655               exit (1);
656             }
657
658           XGetWindowAttributes (display, window, &xgwa);
659
660           grays = (unsigned char *) calloc (xpm_image.ncolors+1, 1);
661           for (x = 0; x < xpm_image.ncolors; x++)
662             {
663               XColor xc;
664               XpmColor *xpmc = &xpm_image.colorTable[x];
665               char *cstring = 0;
666               if (xpmc->g_color && *xpmc->g_color)
667                 cstring = xpmc->g_color;
668               else if (xpmc->g4_color && *xpmc->g4_color)
669                 cstring = xpmc->g4_color;
670               else if (xpmc->c_color && *xpmc->c_color)
671                 cstring = xpmc->c_color;
672               else
673                 cstring = xpmc->m_color;
674
675               memset (&xc, 0, sizeof(xc));
676               if (!cstring ||
677                   !*cstring ||
678                   !XParseColor (display, xgwa.colormap, cstring, &xc))
679                 grays[x] = 0;
680               else
681                 grays[x] = (int) (((xc.red   * 0.299) +
682                                    (xc.green * 0.587) +
683                                    (xc.blue  * 0.114))
684                                   / 255);
685             }
686
687           o = result;
688           for (y = 0; y < *h; y++)
689             for (x = 0; x < *w; x++)
690               {
691                 int color = xpm_image.data[(y * (*w)) + x];
692                 if (color < 0 || color > xpm_image.ncolors) abort();
693                 *o++ = grays[color];
694               }
695           return result;
696         }
697       else      /* failed to read XPM -- fall through and try XBM */
698 #endif /* HAVE_XPM */
699         {
700 #ifdef HAVE_XMU
701           XImage *ximage = 0;
702           int width, height, xh, yh;
703           int x, y;
704           unsigned char *result, *o;
705           Pixmap bitmap =
706             XmuLocateBitmapFile (DefaultScreenOfDisplay (display),
707                                  bitmap_name, 0, 0, &width, &height, &xh, &yh);
708           if (!bitmap)
709             {
710               fprintf(stderr, "%s: unable to load bitmap file %s\n",
711                       progname, bitmap_name);
712               exit (1);
713             }
714           ximage = XGetImage (display, bitmap, 0, 0, width, height,
715                               1L, XYPixmap);
716           XFreePixmap (display, bitmap);
717
718           if (ximage->depth != 1) abort();
719
720           *w = ximage->width;
721           *h = ximage->height;
722           result = (unsigned char *) malloc ((*w) * (*h));
723           if (!result)
724             {
725               fprintf(stderr, "%s: out of memory loading %s\n",
726                       progname, bitmap_name);
727               exit (1);
728             }
729
730           o = result;
731           for (y = 0; y < *h; y++)
732             for (x = 0; x < *w; x++)
733               *o++ = (XGetPixel(ximage, x, y) ? 255 : 0);
734
735           return result;
736
737 #else  /* !XMU */
738           fprintf (stderr,
739                    "%s: your vendor doesn't ship the standard Xmu library.\n",
740                    progname);
741           fprintf (stderr, "\tWe can't load XBM files without it.\n");
742           exit (1);
743 #endif /* !XMU */
744         }
745     }
746
747   *w = 0;
748   *h = 0;
749   return 0;
750
751 }
752
753
754 \f
755 char *progclass = "XFlame";
756
757 char *defaults [] = {
758   ".background:     black",
759   ".foreground:     #FFAF5F",
760   "*bitmap:         (default)",
761   "*bitmapBaseline: 20",
762   "*delay:          10000",
763   "*hspread:        30",
764   "*vspread:        97",
765   "*residual:       99",
766   "*variance:       50",
767   "*vartrend:       20",
768   "*bloom:          True",   
769
770 #ifdef HAVE_XSHM_EXTENSION
771   "*useSHM: False",   /* xshm turns out not to help. */
772 #endif /* HAVE_XSHM_EXTENSION */
773    0
774 };
775
776 XrmOptionDescRec options [] = {
777   { "-delay",     ".delay",          XrmoptionSepArg, 0 },
778   { "-bitmap",    ".bitmap",         XrmoptionSepArg, 0 },
779   { "-baseline",  ".bitmapBaseline", XrmoptionSepArg, 0 },
780   { "-hspread",   ".hspread",        XrmoptionSepArg, 0 },
781   { "-vspread",   ".vspread",        XrmoptionSepArg, 0 },
782   { "-residual",  ".residual",       XrmoptionSepArg, 0 },
783   { "-variance",  ".variance",       XrmoptionSepArg, 0 },
784   { "-vartrend",  ".vartrend",       XrmoptionSepArg, 0 },
785   { "-bloom",     ".bloom",          XrmoptionNoArg, "True" },
786   { "-no-bloom",  ".bloom",          XrmoptionNoArg, "False" },
787 #ifdef HAVE_XSHM_EXTENSION
788   { "-shm",       ".useSHM",         XrmoptionNoArg, "True" },
789   { "-no-shm",    ".useSHM",         XrmoptionNoArg, "False" },
790 #endif /* HAVE_XSHM_EXTENSION */
791   { 0, 0, 0, 0 }
792 };
793
794 void
795 screenhack (Display *disp, Window win)
796 {
797   int theimx = 0, theimy = 0;
798   int baseline = get_integer_resource ("bitmapBaseline", "Integer");
799   int delay = get_integer_resource ("delay", "Integer");
800   xim      = NULL;
801   top      = 1;
802   flame    = NULL;
803
804   GetXInfo(disp,win);
805   InitColors();
806   theim = loadBitmap(&theimx, &theimy);
807
808   /* utils/xshm.c doesn't provide a way to free the shared-memory image, which
809      makes it hard for us to react to window resizing.  So, punt for now.  The
810      size of the window at startup is the size it will stay.
811   */
812   GetXInfo(disp,win);
813
814   MakeImage();
815   InitFlame();
816   FlameFill(0);
817
818   while (1)
819     {
820       FlameActive();
821
822       if (theim)
823         FlamePasteData(theim, (fwidth - theimx) / 2,
824                        fheight - theimy - baseline, theimx, theimy);
825
826       FlameAdvance();
827       Flame2Image();
828       DisplayImage();
829
830       XSync(display,False);
831       screenhack_handle_events(display);
832       if (delay)
833         usleep (delay);
834     }
835 }