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