http://packetstormsecurity.org/UNIX/admin/xscreensaver-4.01.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    * 16-Jan-2002, jwz: added gdk_pixbuf support.
44
45  */
46
47
48 /* portions by Daniel Zahn <stumpy@religions.com> */
49
50
51 #include "screenhack.h"
52 #include "xpm-pixmap.h"
53 #include <X11/Xutil.h>
54 #include <limits.h>
55
56 #ifdef HAVE_XSHM_EXTENSION
57 # include "xshm.h"
58 #endif /* HAVE_XSHM_EXTENSION */
59
60 #include "images/bob.xbm"
61
62 #define MAX_VAL             255
63
64 static Display         *display;
65 static Window          window;
66 static int             depth;
67 static int             width;
68 static int             height;
69 static Colormap        colormap;
70 static Visual          *visual;
71 static Bool            shared;
72 static Bool            bloom;
73 static XImage          *xim;
74 #ifdef HAVE_XSHM_EXTENSION
75 static XShmSegmentInfo shminfo;
76 #endif /* HAVE_XSHM_EXTENSION */
77 static GC              gc;
78 static int             ctab[256];
79
80 static unsigned char  *flame;
81 static unsigned char  *theim;
82 static int             fwidth;
83 static int             fheight;
84 static int             top;
85 static int             hspread;
86 static int             vspread;
87 static int             residual;
88
89 static int ihspread;
90 static int ivspread;
91 static int iresidual;
92 static int variance;
93 static int vartrend;
94
95 static void
96 GetXInfo(Display *disp, Window win)
97 {
98   XWindowAttributes xwa;
99    
100   XGetWindowAttributes(disp,win,&xwa);
101
102   window   = win;
103   display  = disp;
104   colormap = xwa.colormap;
105   depth    = xwa.depth;
106   visual   = xwa.visual;
107   width    = xwa.width;
108   height   = xwa.height;
109
110   if (width%2)
111     width++;
112   if (height%2)
113     height++;
114 }
115
116 static void
117 MakeImage(void)
118 {
119   XGCValues gcv;
120
121 #ifdef HAVE_XSHM_EXTENSION
122   shared = True;
123   xim = create_xshm_image (display, visual, depth, ZPixmap, NULL,
124                            &shminfo, width, height);
125 #else  /* !HAVE_XSHM_EXTENSION */
126   xim = 0;
127 #endif /* !HAVE_XSHM_EXTENSION */
128
129   if (!xim)
130     {
131       shared = False;
132       xim = XCreateImage (display, visual, depth, ZPixmap, 0, NULL,
133                           width, height, 32, 0);
134       if (xim)
135         xim->data = (char *) calloc(xim->height, xim->bytes_per_line);
136       if (!xim || !xim->data)
137         {
138           fprintf(stderr,"%s: out of memory.\n", progname);
139           exit(1);
140         }
141     }
142
143   gc = XCreateGC(display,window,0,&gcv);
144   if (!gc) exit (1);
145 }
146
147
148 static void
149 InitColors(void)
150 {
151   int i = 0, j = 0, red = 0, green = 0, blue = 0;
152   XColor fg;
153
154   /* Make it possible to set the color of the flames, 
155      by Raymond Medeiros <ray@stommel.marine.usf.edu> and jwz.
156   */
157   fg.pixel = get_pixel_resource ("foreground", "Foreground",
158                                  display, colormap);
159   XQueryColor (display, colormap, &fg);
160
161   red   = 255 - (fg.red   >> 8);
162   green = 255 - (fg.green >> 8);
163   blue  = 255 - (fg.blue  >> 8);
164
165
166   for (i = 0; i < 256 * 2; i += 2)
167     {
168       XColor xcl;
169       int r = (i - red)   * 3;
170       int g = (i - green) * 3;
171       int b = (i - blue)  * 3;
172     
173       if (r < 0)   r = 0;
174       if (r > 255) r = 255;
175       if (g < 0)   g = 0;
176       if (g > 255) g = 255;
177       if (b < 0)   b = 0;
178       if (b > 255) b = 255;
179
180       xcl.red   = (unsigned short)((r << 8) | r);
181       xcl.green = (unsigned short)((g << 8) | g);
182       xcl.blue  = (unsigned short)((b << 8) | b);
183       xcl.flags = DoRed | DoGreen | DoBlue;
184
185       XAllocColor(display,colormap,&xcl);
186
187       ctab[j++] = (int)xcl.pixel;
188     }
189 }
190
191
192 static void
193 DisplayImage(void)
194 {
195 #ifdef HAVE_XSHM_EXTENSION
196   if (shared)
197     XShmPutImage(display, window, gc, xim, 0,(top - 1) << 1, 0,
198                  (top - 1) << 1, width, height - ((top - 1) << 1), False);
199   else
200 #endif /* HAVE_XSHM_EXTENSION */
201     XPutImage(display, window, gc, xim, 0, (top - 1) << 1, 0,
202               (top - 1) << 1, width, height - ((top - 1) << 1));
203 }
204
205
206 static void
207 InitFlame(void)
208 {
209   fwidth  = width / 2;
210   fheight = height / 2;
211   flame   = (unsigned char *) malloc((fwidth + 2) * (fheight + 2)
212                                      * sizeof(unsigned char));
213
214   if (!flame)
215     {
216       fprintf(stderr,"%s: out of memory\n", progname);
217       exit(1);
218     }
219
220   top      = 1;
221   ihspread  = get_integer_resource("hspread", "Integer");
222   ivspread  = get_integer_resource("vspread", "Integer");
223   iresidual = get_integer_resource("residual", "Integer");
224   variance  = get_integer_resource("variance", "Integer");
225   vartrend  = get_integer_resource("vartrend", "Integer");
226   bloom     = get_boolean_resource("bloom",    "Boolean");
227
228 # define THROTTLE(VAR,NAME) \
229   if (VAR < 0 || VAR > 255) { \
230     fprintf(stderr, "%s: %s must be in the range 0-255 (not %d).\n", \
231             progname, NAME, VAR); \
232     exit(1); }
233   THROTTLE (ihspread, "hspread");
234   THROTTLE (ivspread, "vspread");
235   THROTTLE (iresidual,"residual");
236   THROTTLE (variance, "variance");
237   THROTTLE (vartrend, "vartrend");
238 # undef THROTTLE
239
240
241
242   hspread = ihspread;
243   vspread = ivspread;
244   residual = iresidual;
245 }
246
247
248 static void
249 Flame2Image16(void)
250 {
251   int x,y;
252   unsigned short *ptr;
253   unsigned char *ptr1;
254   int v1,v2,v3,v4;
255
256   ptr  = (unsigned short *)xim->data;
257   ptr += (top << 1) * width;
258   ptr1 = flame + 1 + (top * (fwidth + 2));
259
260   for(y = top; y < fheight; y++)
261     {
262       for( x = 0; x < fwidth; x++)
263         {
264           v1 = (int)*ptr1;
265           v2 = (int)*(ptr1 + 1);
266           v3 = (int)*(ptr1 + fwidth + 2);
267           v4 = (int)*(ptr1 + fwidth + 2 + 1);
268           ptr1++;
269           *ptr++ = (unsigned short)ctab[v1];
270           *ptr   = (unsigned short)ctab[(v1 + v2) >> 1];
271           ptr   += width - 1;
272           *ptr++ = (unsigned short)ctab[(v1 + v3) >> 1];
273           *ptr   = (unsigned short)ctab[(v1 + v4) >> 1];
274           ptr   -= width - 1;
275         }
276       ptr  += width;
277       ptr1 += 2;
278     }
279 }
280
281 static void
282 Flame2Image32(void)
283 {
284   int x,y;
285   unsigned int *ptr;
286   unsigned char *ptr1;
287   int v1,v2,v3,v4;
288
289   ptr  = (unsigned int *)xim->data;
290   ptr += (top << 1) * width;
291   ptr1 = flame + 1 + (top * (fwidth + 2));
292
293   for( y = top; y < fheight; y++)
294     {
295       for( x = 0; x < fwidth; x++)
296         {
297           v1 = (int)*ptr1;
298           v2 = (int)*(ptr1 + 1);
299           v3 = (int)*(ptr1 + fwidth + 2);
300           v4 = (int)*(ptr1 + fwidth + 2 + 1);
301           ptr1++;
302           *ptr++ = (unsigned int)ctab[v1];
303           *ptr   = (unsigned int)ctab[(v1 + v2) >> 1];
304           ptr   += width - 1;
305           *ptr++ = (unsigned int)ctab[(v1 + v3) >> 1];
306           *ptr   = (unsigned int)ctab[(v1 + v4) >> 1];
307           ptr   -= width - 1;
308         }
309       ptr  += width;
310       ptr1 += 2;
311     }
312 }
313
314 static void
315 Flame2Image24(void)
316 {
317   int x,y;
318   unsigned char *ptr;
319   unsigned char *ptr1;
320   int v1,v2,v3,v4;
321
322   ptr  = (unsigned char *)xim->data;
323   ptr += (top << 1) * xim->bytes_per_line;
324   ptr1 = flame + 1 + (top * (fwidth + 2));
325
326   for( y = top; y < fheight; y++)
327     {
328       unsigned char *last_ptr = ptr;
329       for( x = 0; x < fwidth; x++)
330         {
331           v1 = (int)*ptr1;
332           v2 = (int)*(ptr1 + 1);
333           v3 = (int)*(ptr1 + fwidth + 2);
334           v4 = (int)*(ptr1 + fwidth + 2 + 1);
335           ptr1++;
336
337           ptr[2] = ((unsigned int)ctab[v1] & 0x00FF0000) >> 16;
338           ptr[1] = ((unsigned int)ctab[v1] & 0x0000FF00) >> 8;
339           ptr[0] = ((unsigned int)ctab[v1] & 0x000000FF);
340           ptr += 3;
341
342           ptr[2] = ((unsigned int)ctab[(v1 + v2) >> 1] & 0x00FF0000) >> 16;
343           ptr[1] = ((unsigned int)ctab[(v1 + v2) >> 1] & 0x0000FF00) >> 8;
344           ptr[0] = ((unsigned int)ctab[(v1 + v2) >> 1] & 0x000000FF);
345           ptr += ((width - 1) * 3);
346
347           ptr[2] = ((unsigned int)ctab[(v1 + v3) >> 1] & 0x00FF0000) >> 16;
348           ptr[1] = ((unsigned int)ctab[(v1 + v3) >> 1] & 0x0000FF00) >> 8;
349           ptr[0] = ((unsigned int)ctab[(v1 + v3) >> 1] & 0x000000FF);
350           ptr += 3;
351
352           ptr[2] = ((unsigned int)ctab[(v1 + v4) >> 1] & 0x00FF0000) >> 16;
353           ptr[1] = ((unsigned int)ctab[(v1 + v4) >> 1] & 0x0000FF00) >> 8;
354           ptr[0] = ((unsigned int)ctab[(v1 + v4) >> 1] & 0x000000FF);
355           ptr -= ((width - 1) * 3);
356         }
357
358       ptr = last_ptr + (xim->bytes_per_line << 1);
359       ptr1 += 2;
360     }
361 }
362
363 static void
364 Flame2Image8(void)
365 {
366   int x,y;
367   unsigned char *ptr;
368   unsigned char *ptr1;
369   int v1,v2,v3,v4;
370
371   ptr  = (unsigned char *)xim->data;
372   ptr += (top << 1) * width;
373   ptr1 = flame + 1 + (top * (fwidth + 2));
374
375   for(y=top;y<fheight;y++)
376     {
377       for(x=0;x<fwidth;x++)
378         {
379           v1 = (int)*ptr1;
380           v2 = (int)*(ptr1 + 1);
381           v3 = (int)*(ptr1 + fwidth + 2);
382           v4 = (int)*(ptr1 + fwidth + 2 + 1);
383           ptr1++;
384           *ptr++ = (unsigned char)ctab[v1];
385           *ptr   = (unsigned char)ctab[(v1 + v2) >> 1];
386           ptr   += width - 1;
387           *ptr++ = (unsigned char)ctab[(v1 + v3) >> 1];
388           *ptr   = (unsigned char)ctab[(v1 + v4) >> 1];
389           ptr   -= width - 1;
390         }
391       ptr  += width;
392       ptr1 += 2;
393     }
394 }
395
396 static void
397 Flame2Image1234567(void)
398 {
399   int x,y;
400   unsigned char *ptr1;
401   int v1,v2,v3,v4;
402
403   ptr1 = flame + 1 + (top * (fwidth + 2));
404
405   for( y = top; y < fheight; y++)
406     {
407       for( x = 0; x < fwidth; x++)
408         {
409           v1 = (int)*ptr1;
410           v2 = (int)*(ptr1 + 1);
411           v3 = (int)*(ptr1 + fwidth + 2);
412           v4 = (int)*(ptr1 + fwidth + 2 + 1);
413           ptr1++;
414           XPutPixel(xim,(x << 1),    (y << 1),    ctab[v1]);
415           XPutPixel(xim,(x << 1) + 1,(y << 1),    ctab[(v1 + v2) >> 1]);
416           XPutPixel(xim,(x << 1),    (y << 1) + 1,ctab[(v1 + v3) >> 1]);
417           XPutPixel(xim,(x << 1) + 1,(y << 1) + 1,ctab[(v1 + v4) >> 1]);
418         }
419     }
420 }
421
422 static void
423 Flame2Image(void)
424 {
425   switch (xim->bits_per_pixel)
426     {
427     case 32: Flame2Image32(); break;
428     case 24: Flame2Image24(); break;
429     case 16: Flame2Image16(); break;
430     case 8:  Flame2Image8();  break;
431     default:
432       if (xim->bits_per_pixel <= 7)
433         Flame2Image1234567();
434       else
435         abort();
436       break;
437     }
438 }
439
440
441 static void
442 FlameActive(void)
443 {
444   int x,v1;
445   unsigned char *ptr1;
446    
447   ptr1 = flame + ((fheight + 1) * (fwidth + 2));
448
449   for (x = 0; x < fwidth + 2; x++)
450     {
451       v1      = *ptr1;
452       v1     += ((random() % variance) - vartrend);
453       *ptr1++ = v1 % 255;
454     }
455
456   if (bloom)
457     {
458       v1= (random() % 100);
459       if (v1 == 10)
460         residual += (random()%10);
461       else if (v1 == 20)
462         hspread += (random()%15);
463       else if (v1 == 30)
464         vspread += (random()%20);
465     }
466
467   residual = ((iresidual* 10) + (residual *90)) / 100;
468   hspread  = ((ihspread * 10) + (hspread  *90)) / 100;
469   vspread  = ((ivspread * 10) + (vspread  *90)) / 100;
470 }
471
472
473 static void
474 FlameAdvance(void)
475 {
476   int x,y;
477   unsigned char *ptr2;
478   int newtop = top;
479
480   for (y = fheight + 1; y >= top; y--)
481     {
482       int used = 0;
483       unsigned char *ptr1 = flame + 1 + (y * (fwidth + 2));
484       for (x = 0; x < fwidth; x++)
485         {
486           int v1 = (int)*ptr1;
487           int v2, v3;
488           if (v1 > 0)
489             {
490               used = 1;
491               ptr2 = ptr1 - fwidth - 2;
492               v3   = (v1 * vspread) >> 8;
493               v2   = (int)*(ptr2);
494               v2  += v3;
495               if (v2 > MAX_VAL) 
496                 v2 = MAX_VAL;
497
498               *(ptr2) = (unsigned char)v2;
499               v3  = (v1 * hspread) >> 8;
500               v2  = (int)*(ptr2 + 1);
501               v2 += v3;
502               if (v2 > MAX_VAL) 
503                 v2 = MAX_VAL;
504           
505               *(ptr2 + 1) = (unsigned char)v2;
506               v2          = (int)*(ptr2 - 1);
507               v2         += v3;
508               if (v2 > MAX_VAL) 
509                 v2 = MAX_VAL;
510           
511               *(ptr2 - 1) = (unsigned char)v2;
512         
513               if (y < fheight + 1)
514                 {
515                   v1    = (v1 * residual) >> 8;
516                   *ptr1 = (unsigned char)v1;
517                 }
518             }
519           ptr1++;
520           if (used) 
521             newtop = y - 1;
522         }
523  
524       /* clean up the right gutter */
525       {
526         int v1 = (int)*ptr1;
527         v1 = (v1 * residual) >> 8;
528         *ptr1 = (unsigned char)v1;
529       }
530     }
531
532   top = newtop - 1;
533
534   if (top < 1)
535     top = 1;
536 }
537
538
539 static void
540 FlameFill(int val)
541 {
542   int x, y;
543   for (y = 0; y < fheight + 1; y++)
544     {
545       unsigned char *ptr1 = flame + 1 + (y * (fwidth + 2));
546       for (x = 0; x < fwidth; x++)
547         {
548           *ptr1 = val;
549           ptr1++;
550         }
551     }
552 }
553
554
555 static void
556 FlamePasteData(unsigned char *d, int xx, int yy, int w, int h)
557 {
558   unsigned char *ptr1,*ptr2;
559   ptr2 = d;
560
561   if (xx < 0) xx = 0;
562   if (yy < 0) yy = 0;
563
564   if ((xx >= 0) &&
565       (yy >= 0) &&
566       (xx + w <= fwidth) &&
567       (yy + h <= fheight))
568     {
569       int x, y;
570       for (y = 0; y < h; y++)
571         {
572           ptr1 = flame + 1 + xx + ((yy + y) * (fwidth + 2));
573           for (x = 0; x < w; x++)
574             {
575               if (*ptr2 / 24)
576                 *ptr1 += random() % (*ptr2 / 24);
577
578               ptr1++;
579               ptr2++;
580             }
581         }
582     }
583   else
584     {
585       static Bool warned = False;
586       if (!warned)
587         {
588           fprintf (stderr, "%s: window is %dx%d; image must be "
589                    "smaller than %dx%d (not %dx%d).\n",
590                    progname, width, height, fwidth, fheight, w, h);
591           warned = True;
592         }
593     }
594 }
595
596
597 static unsigned char *
598 loadBitmap(int *w, int *h)
599 {
600   char *bitmap_name = get_string_resource ("bitmap", "Bitmap");
601
602   if (!bitmap_name ||
603       !*bitmap_name ||
604       !strcmp(bitmap_name, "none"))
605     ;
606   else if (!strcmp(bitmap_name, "(default)"))   /* use the builtin */
607     {
608       XImage *ximage;
609       unsigned char *result, *o;
610       char *bits = (char *) malloc (sizeof(bob_bits));
611       int x, y;
612       int scale = ((width > bob_width * 11) ? 2 : 1);
613  
614       memcpy (bits, bob_bits, sizeof(bob_bits));
615       ximage = XCreateImage (display, visual, 1, XYBitmap, 0, bits,
616                              bob_width, bob_height, 8, 0);
617       ximage->byte_order = LSBFirst;
618       ximage->bitmap_bit_order = LSBFirst;
619       *w = ximage->width * scale;
620       *h = ximage->height * scale;
621       o = result = (unsigned char *) malloc ((*w * scale) * (*h * scale));
622       for (y = 0; y < *h; y++)
623         for (x = 0; x < *w; x++)
624           *o++ = (XGetPixel(ximage, x/scale, y/scale) ? 255 : 0);
625        
626       return result;
627     }
628   else  /* load a bitmap file */
629     {
630       Pixmap pixmap =
631         xpm_file_to_pixmap (display, window, bitmap_name, &width, &height, 0);
632       XImage *image;
633       int x, y;
634       unsigned char *result, *o;
635
636       image = XGetImage (display, pixmap, 0, 0, width, height, ~0L, ZPixmap);
637       XFreePixmap(display, pixmap);
638
639       result = (unsigned char *) malloc (width * height);
640       o = result;
641       for (y = 0; y < height; y++)
642         for (x = 0; x < width; x++)
643           {
644             int rgba = XGetPixel (image, x, y);
645             /* This is *so* not handling all the cases... */
646             int gray = (image->depth > 16
647                         ? ((((rgba >> 24) & 0xFF) +
648                             ((rgba >> 16) & 0xFF) +
649                             ((rgba >>  8) & 0xFF) +
650                             ((rgba      ) & 0xFF)) >> 2)
651                         : ((((rgba >> 12) & 0x0F) +
652                             ((rgba >>  8) & 0x0F) +
653                             ((rgba >>  4) & 0x0F) +
654                             ((rgba      ) & 0x0F)) >> 1));
655             *o++ = 255 - gray;
656           }
657
658       XFree (image->data);
659       image->data = 0;
660       XDestroyImage (image);
661
662       *w = width;
663       *h = height;
664       return result;
665     }
666
667   *w = 0;
668   *h = 0;
669   return 0;
670
671 }
672
673
674 \f
675 char *progclass = "XFlame";
676
677 char *defaults [] = {
678   ".background:     black",
679   ".foreground:     #FFAF5F",
680   "*bitmap:         (default)",
681   "*bitmapBaseline: 20",
682   "*delay:          10000",
683   "*hspread:        30",
684   "*vspread:        97",
685   "*residual:       99",
686   "*variance:       50",
687   "*vartrend:       20",
688   "*bloom:          True",   
689
690 #ifdef HAVE_XSHM_EXTENSION
691   "*useSHM: False",   /* xshm turns out not to help. */
692 #endif /* HAVE_XSHM_EXTENSION */
693    0
694 };
695
696 XrmOptionDescRec options [] = {
697   { "-delay",     ".delay",          XrmoptionSepArg, 0 },
698   { "-bitmap",    ".bitmap",         XrmoptionSepArg, 0 },
699   { "-baseline",  ".bitmapBaseline", XrmoptionSepArg, 0 },
700   { "-hspread",   ".hspread",        XrmoptionSepArg, 0 },
701   { "-vspread",   ".vspread",        XrmoptionSepArg, 0 },
702   { "-residual",  ".residual",       XrmoptionSepArg, 0 },
703   { "-variance",  ".variance",       XrmoptionSepArg, 0 },
704   { "-vartrend",  ".vartrend",       XrmoptionSepArg, 0 },
705   { "-bloom",     ".bloom",          XrmoptionNoArg, "True" },
706   { "-no-bloom",  ".bloom",          XrmoptionNoArg, "False" },
707 #ifdef HAVE_XSHM_EXTENSION
708   { "-shm",       ".useSHM",         XrmoptionNoArg, "True" },
709   { "-no-shm",    ".useSHM",         XrmoptionNoArg, "False" },
710 #endif /* HAVE_XSHM_EXTENSION */
711   { 0, 0, 0, 0 }
712 };
713
714 void
715 screenhack (Display *disp, Window win)
716 {
717   int theimx = 0, theimy = 0;
718   int baseline = get_integer_resource ("bitmapBaseline", "Integer");
719   int delay = get_integer_resource ("delay", "Integer");
720   xim      = NULL;
721   top      = 1;
722   flame    = NULL;
723
724   GetXInfo(disp,win);
725   InitColors();
726   theim = loadBitmap(&theimx, &theimy);
727
728   /* utils/xshm.c doesn't provide a way to free the shared-memory image, which
729      makes it hard for us to react to window resizing.  So, punt for now.  The
730      size of the window at startup is the size it will stay.
731   */
732   GetXInfo(disp,win);
733
734   MakeImage();
735   InitFlame();
736   FlameFill(0);
737
738   while (1)
739     {
740       FlameActive();
741
742       if (theim)
743         FlamePasteData(theim, (fwidth - theimx) / 2,
744                        fheight - theimy - baseline, theimx, theimy);
745
746       FlameAdvance();
747       Flame2Image();
748       DisplayImage();
749
750       XSync(display,False);
751       screenhack_handle_events(display);
752       if (delay)
753         usleep (delay);
754     }
755 }