diff -u -N bomb.old/Makefile bomb/Makefile
--- bomb.old/Makefile	Mon Mar  9 01:13:15 1998
+++ bomb/Makefile	Thu Nov 12 13:33:53 1998
@@ -12,12 +12,15 @@
 
 
 PROGS = cmap_test bomb image2cmap
-flags = -g -DDATA_DIR=\"$(DATA_DIR)\" $(SCM_CFLAGS)
+flags = -g -DDATA_DIR=\"$(DATA_DIR)\" $(SCM_CFLAGS) 
 CFLAGS = -O $(flags)
 
 # LDFLAGS = $(SCM_LDFLAGS)
 
-# X11
+# X11 with mit shared mem
+# LOADLIBES = -lXext -lX11 -lm -ltiff -L/usr/X11/lib
+
+# X11 without mit shared mem
 # LOADLIBES = -lX11 -lm -ltiff -L/usr/X11/lib
 
 # OpenGL
@@ -26,11 +29,14 @@
 # linux/svgalib
 # LOADLIBES = -lvga -lm -ltiff
 
+# svgalib and x11 with X mit shared mem
+LOADLIBES = -lXext -lX11 -lvga -lm -ltiff -L/usr/X11/lib
+
 # svgalib and x11
-LOADLIBES = -lX11 -lvga -lm -ltiff -L/usr/X11/lib
+#LOADLIBES = -lX11 -lvga -lm -ltiff -L/usr/X11/lib
 
 
-LIBSRCS = libifs.c image.c gif.c zio.c
+LIBSRCS = libifs.c image.c gif.c zio.c xshm.c
 SRCS = cmap.c rug.c static.c acidlife.c brain.c rd.c sound.c \
 	anneal.c rug_rug.c rotor.c shade.c wave.c quad.c \
 	slip.c image_rule.c image_seq.c fuse.c rug_multi.c match.c \
diff -u -N bomb.old/bomb.c bomb/bomb.c
--- bomb.old/bomb.c	Mon Mar  9 00:55:43 1998
+++ bomb/bomb.c	Wed Nov 18 13:20:38 1998
@@ -23,6 +23,30 @@
 #include "bomb.h"
 #include "match.h"
 #include "sound.h"
+#include "vroot.h"
+
+/* begin caolan */
+#ifdef HAVE_XSHM_EXTENSION
+#include "xshm.h"
+#endif /* HAVE_XSHM_EXTENSION */
+
+int dest_x;		/*offset from left of offscreen image to onscreen image*/
+int dest_y;		/*offset from top of offscreen image to onscreen image*/
+int use_root=0; /*display in root flag*/
+int pix_rep=d_pix_rep;	/*glue to original pix_rep mechanism*/
+int multiply=-1; /*magnification factor*/
+int do_tile=0; /*whether to tile the 320x200 image into the window*/
+int notiles=0; /*no of tiles*/
+int fullscreen=0; /*if the tiles cover the screen, then we can use a background pixmap to smooth expose events*/
+int nobackpixmap=0; /*flag if to use a backing pixmap*/
+int use_shm=1; /*use shared memory*/
+char *progname="bomb"; /*keep the xshm.c file happy*/
+
+#ifdef HAVE_XSHM_EXTENSION
+  XShmSegmentInfo shm_info;
+#endif
+
+/* end caolan */
 
 board_t board[2];
 board_t board2[2];
@@ -113,7 +137,7 @@
 int *xws_lut;
 #if xws_bomb
 GC gc;
-XImage *xws_image;
+XImage *xws_image=NULL;
 char *image_buf;
 #endif
 #endif
@@ -503,7 +527,8 @@
 #if (xws_bomb|ogl_bomb)
    {
      XEvent ev;
-     if (XCheckWindowEvent(disp, win, KeyPressMask, &ev)) {
+	 /*keep an eye an the key presses of all interesting windows*/
+     if (XCheckMaskEvent(disp, KeyPressMask, &ev)) {
        KeySym s;
        s = XKeycodeToKeysym(disp, ev.xkey.keycode, 0);
        /* doesn't work for shifted digits */
@@ -618,7 +643,11 @@
    }
 #endif
 
-#if pix_rep
+#if d_pix_rep
+/*if usersettable
+else
+*/
+pix_rep = d_pix_rep;
 #ifdef copy_bits
       if (1) {
       extern PixMapPtr  offscreenPixMapP, windowPixMapP;
@@ -746,6 +775,15 @@
   XGCValues argh;
   int fb_sz;
   unsigned long valuemask;
+/*caolan begin*/
+  int tempwidth,tempheight;
+  int stat;
+  Window parent, *children, *child2,winret;
+  unsigned int nchildren,i;
+
+/*caolan end*/
+
+
   disp = XOpenDisplay(NULL);
   if (NULL == disp) {
     fprintf(stderr, "couldn't open display.\n");
@@ -771,13 +809,99 @@
     valuemask |= CWColormap;
     attr.colormap = xws_cmap;
   }
-  win = XCreateWindow(disp,
-		      RootWindowOfScreen(scrn),
-		      (WidthOfScreen(scrn)-pix_rep*320)/2,
-		      (HeightOfScreen(scrn)-pix_rep*200)/2,
-		      pix_rep*320, pix_rep*200, 5, CopyFromParent,
-		      InputOutput, visual, valuemask, &attr);
-  XMapWindow(disp, win);
+
+
+/*	begin caolan */
+if ((multiply == 0) && (!do_tile))
+	{
+	tempwidth = (WidthOfScreen(scrn))/320;
+	if ((tempwidth * 320) <  (WidthOfScreen(scrn)))
+		tempwidth++;
+	tempheight = (HeightOfScreen(scrn))/200;
+	if ((tempheight * 200) <  (HeightOfScreen(scrn)))
+		tempheight++;
+
+	if (tempwidth > tempheight)
+		pix_rep = tempwidth;
+	else 
+		pix_rep = tempheight;
+	}
+else if (multiply > 0)
+	pix_rep = multiply;
+
+
+if ((do_tile) && (notiles == 0))
+	{
+	tempwidth = (WidthOfScreen(scrn))/(320*pix_rep);
+	if ((tempwidth * (320*pix_rep)) <  (WidthOfScreen(scrn)))
+		tempwidth++;
+	tempheight = (HeightOfScreen(scrn))/(200*pix_rep);
+	if ((tempheight * (200*pix_rep)) <  (HeightOfScreen(scrn)))
+		tempheight++;
+
+	if (tempwidth > tempheight)
+		notiles = tempwidth;
+	else 
+		notiles = tempheight;
+	}
+else if (!do_tile)
+	notiles=1;
+  
+/* use root window or not, use default magnification or user defined value */
+/* determine offset into offscreen representation to show at 0,0 */
+if (!use_root)
+	{
+	win = XCreateWindow(disp,
+				RootWindowOfScreen(scrn),
+				(WidthOfScreen(scrn)-pix_rep*320)/2,
+				(HeightOfScreen(scrn)-pix_rep*200)/2,
+				pix_rep*320, pix_rep*200, 5, CopyFromParent,
+				InputOutput, visual, valuemask, &attr);
+	XMapWindow(disp, win);
+	/*get keystrokes from this main window */
+	XSelectInput(disp, win, KeyPressMask);
+
+	dest_x=0;
+	dest_y=0;
+  	}
+else
+	{
+	win = RootWindowOfScreen(scrn);
+	/*the default is to find a pix_rep that will fully cover the screen*/
+
+if (!do_tile)
+	{
+	dest_x = (WidthOfScreen(scrn)-pix_rep*320)/2;
+	dest_y = (HeightOfScreen(scrn)-pix_rep*200)/2;
+	}
+else
+	{
+	dest_x = (WidthOfScreen(scrn)-pix_rep*notiles*320)/2;
+	dest_y = (HeightOfScreen(scrn)-pix_rep*notiles*200)/2;
+	}
+
+	if (((pix_rep*notiles*320) >= (WidthOfScreen(scrn))) &&
+		((pix_rep*notiles*200) >= (HeightOfScreen(scrn))) )
+		fullscreen=1;
+	/*get keystrokes from this main window */
+	XSelectInput(disp, win, KeyPressMask);
+	/*but this is different for RootWindows, lets try and see if we can get
+	the real input that the user might try and input into the RootWindow*/
+	stat = XQueryTree(disp, win, &winret, &parent, &children, &nchildren);
+	for(i=0; i < nchildren; i++)
+		XSelectInput(disp, children[i], KeyPressMask);
+
+	/*XSetWindowBackground(disp,win,BlackPixelOfScreen(scrn));*/
+    attr.backing_store=0;
+    valuemask = CWBackingStore;
+	XChangeWindowAttributes(disp,win,valuemask,&attr);
+  	}
+
+	XGetWindowAttributes(disp,win,&xgwa);
+	printf("bit_gravity is %d\nwin_gravity is %d\nclass is %d\n,backing_store is %d\nbacking_planes is %d\n,backing_pixel is %d\nsave_under is %d\n",xgwa.bit_gravity,xgwa.win_gravity,xgwa.class,xgwa.backing_store,xgwa.backing_planes,xgwa.backing_pixel,xgwa.save_under);
+	
+/* end caolan */
+
   depth = visual_depth(DefaultScreenOfDisplay(disp), visual);
 
 #if xws_bomb
@@ -799,9 +923,24 @@
       image_buf = (char *) fb.p;
     else
       image_buf = malloc(320 * 200 * pix_rep * pix_rep * fb_bpp);
-    xws_image = XCreateImage(disp, visual, depth,
-			     ZPixmap, 0, image_buf,
-			     pix_rep*320, pix_rep*200, 8, 0);
+#ifdef HAVE_XSHM_EXTENSION
+	xws_image = create_xshm_image(disp, visual, depth, ZPixmap, 0, &shm_info, 
+		pix_rep*320, pix_rep*200);
+	if (xws_image)
+		{
+		free(image_buf);
+		image_buf = xws_image->data;
+		}
+	else
+		{
+		use_shm=0;
+		fprintf(stderr,"XSHM extension not working, using slower method\n");
+		}
+#endif /* HAVE_XSHM_EXTENSION */
+
+	 if (xws_image == NULL) 
+		xws_image = XCreateImage(disp, visual, depth, ZPixmap, 0, image_buf, 
+			pix_rep*320, pix_rep*200, 8, 0);
   }
 #endif
 #if ogl_bomb
@@ -2757,6 +2896,76 @@
 }
 
 #else
+/* begin caolan */
+/* only look for the command line options in the X version of bomb */
+/* allow display in root window, and take an optional magnification factor,
+and allow tiling and take a tiling factor, and allow disabling of background
+pixmap for faster running, but crappy expose event handling*/
+#if !mac_bomb && !win_bomb
+void main(int argc,char *argv[])
+{
+char *endptr;
+
+ argc--, argv++;
+ while (argc > 0) 
+	{
+    if (strcmp(*argv, "-root") == 0)
+		{
+		if ((multiply == -1) && (!do_tile))
+			multiply=0;
+    	use_root = 1;
+		}
+	else if (strcmp(*argv, "-nobackpixmap") == 0)
+		nobackpixmap=1;
+	else if (strcmp(*argv, "-noshm") == 0)
+		use_shm=0;
+    else if (strcmp(*argv, "-tile") == 0)
+		{
+		do_tile=1;
+		if (multiply == 0)
+			multiply=-1;
+    	use_root = 1;
+
+    	argc--, argv++;
+		if (argc > 0)
+			{
+			notiles = strtol(*argv,&endptr,10);
+			if ((**argv == '\0') || (*endptr  != '\0'))
+    			argc++, argv--;
+			}
+		else
+			break;
+		
+		}
+	else if ( (strcmp(*argv, "-magnify") == 0)  
+		|| (strcmp(*argv, "-multiply") == 0) )
+		{
+    	argc--, argv++;
+		if (argc > 0)
+			{
+			multiply = strtol(*argv,&endptr,10);
+			if ((**argv == '\0') || (*endptr  != '\0'))
+				printf("multiply has to be followed by a number\n");
+			}
+		else
+			{
+			printf("multiply has to be followed by a number\n");
+			break;
+			}
+		}
+	else
+		fprintf(stderr,"unknown option %s\n",*argv);
+    argc--, argv++;
+    }
+
+   init();
+   
+   while (1) {
+     bomb_work();
+   }
+}
+/* end caolan */
+#else
 void
 main()
 {
@@ -2766,6 +2975,7 @@
      bomb_work();
    }
 }
+#endif
 #endif
 message(char *s) {}
 #endif
diff -u -N bomb.old/bomb.h bomb/bomb.h
--- bomb.old/bomb.h	Thu Feb 19 12:13:33 1998
+++ bomb/bomb.h	Thu Nov 12 13:42:04 1998
@@ -84,6 +84,7 @@
 void bomb_set_cycle_background(int);
 void bomb_set_remap_colors(int);
 
+
 extern int display_fps;
 
 #ifdef __cplusplus
diff -u -N bomb.old/defs.h bomb/defs.h
--- bomb.old/defs.h	Mon Mar  9 00:53:25 1998
+++ bomb/defs.h	Thu Nov 12 13:15:24 1998
@@ -23,10 +23,10 @@
 #define ogl_bomb 0
 #define win_bomb 0
 
-
-
 #define use_guile 0
 
+#define HAVE_XSHM_EXTENSION
+
 #if use_guile
 #include <gh.h>
 #endif
@@ -272,8 +272,8 @@
 #endif
 
 #if mac_bomb
-/* if pix_rep is 0 then write directly on the screen */
-#define pix_rep 0
+/* if d_pix_rep is 0 then write directly on the screen */
+#define d_pix_rep 0
 #define use_sioux 0
 #endif
 
@@ -286,7 +286,7 @@
 #include <X11/X.h>
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
-#define pix_rep 1
+#define d_pix_rep 1
 extern char *image_buf;
 extern Display *disp;
 extern Window win;
@@ -304,12 +304,15 @@
 #include <GL/glx.h>
 #include <X11/X.h>
 #include <X11/Xutil.h>
-#define pix_rep 3
+#define d_pix_rep 3
 extern Display *disp;
 extern Window win;
 extern Colormap xws_cmap;
 #endif
-
+/*begin caolan*/
+/*pix_rep changed to d_pix_rep and pix_rep is now a variable*/
+extern int pix_rep;
+/*end caolan*/
 
 #ifdef __cplusplus
 }
Common subdirectories: bomb.old/dribble and bomb/dribble
diff -u -N bomb.old/fast.c bomb/fast.c
--- bomb.old/fast.c	Mon Mar  9 00:27:12 1998
+++ bomb/fast.c	Wed Nov 18 12:55:36 1998
@@ -21,6 +21,23 @@
 #include "image.h"
 #include "image_db.h"
 #include "bomb.h"
+#include "vroot.h"
+/* begin caolan, see bomb.c for details */
+void PutImage(Drawable win,int src_x, int src_y,int dest_x,int dest_y,unsigned int width, unsigned int height);
+
+#ifdef HAVE_XSHM_EXTENSION
+# include "xshm.h"
+#endif /* HAVE_XSHM_EXTENSION */
+
+extern int dest_x;
+extern int dest_y;
+extern int notiles;
+extern int use_root;
+extern do_tile;
+extern int fullscreen;
+extern int nobackpixmap;
+extern int use_shm;
+/* end caolan */
 
 
 #if 0
@@ -584,7 +601,7 @@
 #endif
 }
 
-#if mac_bomb && pix_rep
+#if mac_bomb && d_pix_rep
 #ifdef copy_bits
 #include <Quickdraw.h>
 #include <QDOffscreen.h>
@@ -598,6 +615,9 @@
 /* int world_x, world_y; */
 
 void image8_flush() {
+/*caolan begin*/
+  int k;
+/*caolan end*/
 #if win_bomb
   HBITMAP bm;
   int i, j;
@@ -612,7 +632,7 @@
 #endif
 
 
-#if mac_bomb && pix_rep
+#if mac_bomb && d_pix_rep
 #ifdef copy_bits
   /* AJW */
   if ((*offscreenPixMapP->pmTable)->ctSeed != (*windowPixMapP->pmTable)->ctSeed)
@@ -692,27 +712,60 @@
 #endif
 
 #if xws_bomb && vga_bomb
+  int l,m,xoffset,yoffset,temp;
+  Pixmap test = XCreatePixmap(disp, win, 320*pix_rep, 200*pix_rep, visual_depth(DefaultScreenOfDisplay(disp), visual));
+  
+
   if (running_x)
 #endif
 #if xws_bomb
   {
+/*begin caolan*/
+/* allow offscreen representation to be displayed at an offset to the window
+useful for root window display*/
+/*extend the number of options and a modification or two to allow X display 
+in 8,16 and 24 bits at a multiple of 320x200*/
+
+
+for (m=0;m<notiles;m++)
+for (l=0;l<notiles;l++)
+	{
+	k=0;
     if (1 == pix_rep && 1 == fb_bpp)
-      XPutImage(disp, win, gc, xws_image, 0, 0, 0, 0, 320, 200);
+      PutImage(win,0, 0, dest_x+(l*320*pix_rep), dest_y+(m*200*pix_rep),320,200);
     else if (1 == pix_rep && 2 == fb_bpp) {
       int i, j, k = fb.stride;
       for (i = 0; i < 200; i++)
 	for (j = 0; j < 320; j++)
 	  ((short *) image_buf) [i * 320 + j] =
 	    index_to_pixels[fb.p[i * k + j]];
-      XPutImage(disp, win, gc, xws_image, 0, 0, 0, 0, 320, 200);
+      PutImage(win,0, 0, dest_x+(l*320*pix_rep), dest_y+(m*200*pix_rep),320,200);
+	  
+	  
     } else if (1 == pix_rep && 4 == fb_bpp) {
       int i, j, k = fb.stride;
       for (i = 0; i < 200; i++)
 	for (j = 0; j < 320; j++)
 	  ((int *) image_buf) [i * 320 + j] =
 	    index_to_pixels[fb.p[i * k + j]];
-      XPutImage(disp, win, gc, xws_image, 0, 0, 0, 0, 320, 200);
-    } else {
+      PutImage(win,0, 0, dest_x+(l*320*pix_rep), dest_y+(m*200*pix_rep),320,200);
+    } else if (2 == fb_bpp) {
+      extern image8_t fb;
+      int i, j, ii, jj;
+
+      /* copy fb.p to image_buf, replicating pixels and
+	 expanding to number of bytes per pixel */
+      for (i = 0; i < 200; i++)
+	for (j = 0; j < 320; j++)
+	  for (ii = 0; ii < pix_rep; ii++)
+	    for (jj = 0; jj < pix_rep; jj++)
+	      ((short *)image_buf)[((i*pix_rep + ii) * (320*pix_rep)) +
+		       (j*pix_rep + jj)] = index_to_pixels[fb.p[i * fb.stride + j]];
+
+      PutImage(win,0, 0, dest_x+(320*pix_rep*l), dest_y+(m*200*pix_rep),
+		pix_rep*320, pix_rep*200);
+		
+    } else if (4 == fb_bpp) {
       extern image8_t fb;
       int i, j, ii, jj;
 
@@ -722,13 +775,60 @@
 	for (j = 0; j < 320; j++)
 	  for (ii = 0; ii < pix_rep; ii++)
 	    for (jj = 0; jj < pix_rep; jj++)
-	      image_buf[(i*pix_rep + ii) * (320*pix_rep) +
+	      ((int *)image_buf)[((i*pix_rep + ii) * (320*pix_rep)) +
 		       (j*pix_rep + jj)] =
-		fb.p[i * fb.stride + j];
-      XPutImage(disp, win, gc, xws_image, 0, 0, 0, 0,
+	    index_to_pixels[fb.p[i * fb.stride + j]];
+      PutImage(win,0, 0, dest_x+(320*pix_rep*l), dest_y+(m*200*pix_rep),
+		pix_rep*320, pix_rep*200);
+
+		
+    } else {
+      extern image8_t fb;
+      int i, j, ii, jj;
+
+      /* copy fb.p to image_buf, replicating pixels and
+	 expanding to number of bytes per pixel */
+      for (i = 0; i < 200; i++)
+	for (j = 0; j < 320; j++)
+	  for (ii = 0; ii < pix_rep; ii++)
+	    for (jj = 0; jj < pix_rep; jj++)
+	      image_buf[((i*pix_rep + ii) * (320*pix_rep)) +
+		       (j*pix_rep + jj)] = fb.p[i * fb.stride + j];
+      PutImage(win,0, 0, dest_x+(320*pix_rep*l), dest_y+(m*200*pix_rep),
 		pix_rep*320, pix_rep*200);
     }
-  }
+	}
+
+	/*
+	the purpose of all of this is to create a background pixmap that matches the tiled foreground
+	so that if the user moves a window when the image is running as a tiled background that the
+	blank areas under windows will be tiled with the current image, so that nasty incorrect areas
+	(like pure black) dont show up to annoy them, the reason i dont just use the background and
+	dont bother with the foreground is that youd have to use XClearWindow on the root window and
+	in may cases i see that it makes the cursor flash so hard that you feel a fit coming on, though
+	this might just be a pecularity of one of the machines i use myself
+	*/
+if ((use_root) && (fullscreen) && (!nobackpixmap) )
+	{
+	xoffset = dest_x/(320*pix_rep);
+	temp = xoffset/320*pix_rep;
+	xoffset = xoffset-temp*320*pix_rep;
+	xoffset = -dest_x + xoffset*320*pix_rep;
+
+	yoffset = dest_y/(200*pix_rep);
+	temp = yoffset/200*pix_rep;
+	yoffset = yoffset-temp*200*pix_rep;
+	yoffset = -dest_y + yoffset*200*pix_rep;
+
+	PutImage(test, xoffset, yoffset, 0, 0,320*pix_rep-xoffset,200*pix_rep-yoffset);
+	PutImage(test, 0, yoffset, 320*pix_rep-xoffset, 0,xoffset,200*pix_rep-yoffset);
+	PutImage(test, xoffset, 0, 0, 200*pix_rep-yoffset,320*pix_rep-xoffset,yoffset);
+	PutImage(test, 0, 0, 320*pix_rep-xoffset, 200*pix_rep-yoffset,xoffset,yoffset);
+	XSetWindowBackgroundPixmap(disp,win,test);
+	XFreePixmap(disp,test);
+	}
+/* end caolan */	
+  }	
 #endif
 #if ogl_bomb
   if (1) {
@@ -941,3 +1041,15 @@
       }
    }
 }
+
+void PutImage(Drawable win,int src_x, int src_y,int dest_x,int dest_y,unsigned int width, unsigned int height)
+	{
+#if 0	
+#ifdef HAVE_XSHM_EXTENSION
+	if (use_shm)
+    	XShmPutImage(disp, win, gc, xws_image, src_x, src_y,dest_x, dest_y, width, height,False); 
+	else
+#endif /* HAVE_XSHM_EXTENSION */
+#endif
+    	XPutImage(disp, win, gc, xws_image, src_x, src_y, dest_x, dest_y,width,height);
+	}
Common subdirectories: bomb.old/ice-9 and bomb/ice-9
diff -u -N bomb.old/manual.txt bomb/manual.txt
--- bomb.old/manual.txt	Mon Mar  9 00:47:46 1998
+++ bomb/manual.txt	Thu Nov 12 13:32:33 1998
@@ -19,6 +19,32 @@
 
   set the "fps" environment variable to control the frames per second.
 
+  five command line options exist
+
+  1) -root, causes the image to be displayed in the root window, 
+  automatically a single image is magnified to fit the screen and a backing
+  pixmap is used.
+  2) -magnify x, causes the 320x200 image to be scaled by a factor of x.
+  3) -tile [x], causes the image to be tiled on the root window, can be
+  used in combination with magnify, without an argument enough tiles are
+  created to cover the root, with an option an x by x grid of tiles centered
+  on the center of the screen will be created, if the screen is filled 
+  automatically a backing pixmap is used.
+  4) -nobackpixmap, by default when the bomb images fill the screen a root 
+  background image is created that layers the background to allow seamless 
+  movement of windows across a working bomb without blank areas appearing 
+  and reappearing, but this can be slow especially with a single large image.
+  so if this is too slow, or if you dont want it use this feature use this 
+  option.
+  5) -noshm, the MIT SHM is used by default if compiled in, use this if for
+  some reason you dont want to use it.
+
+
+  notes:
+
+  I find that the best effect is to use bomb -tile. It creates the smoothest
+  animation, and as it has the smallest generated pixmap you get smooth
+  window movement across bomb without too much of a computential hit.
 
 mac
 
Common subdirectories: bomb.old/scripts and bomb/scripts
Common subdirectories: bomb.old/suck and bomb/suck
diff -u -N bomb.old/utils.h bomb/utils.h
--- bomb.old/utils.h	Thu Jan  1 01:00:00 1970
+++ bomb/utils.h	Thu Nov 12 13:08:49 1998
@@ -0,0 +1,22 @@
+/* xscreensaver, Copyright (c) 1997 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xos.h>
diff -u -N bomb.old/vroot.h bomb/vroot.h
--- bomb.old/vroot.h	Thu Jan  1 01:00:00 1970
+++ bomb/vroot.h	Wed Nov 18 12:55:47 1998
@@ -0,0 +1,126 @@
+/*****************************************************************************/
+/**                   Copyright 1991 by Andreas Stolcke                     **/
+/**               Copyright 1990 by Solbourne Computer Inc.                 **/
+/**                          Longmont, Colorado                             **/
+/**                                                                         **/
+/**                           All Rights Reserved                           **/
+/**                                                                         **/
+/**    Permission to use, copy, modify, and distribute this software and    **/
+/**    its documentation  for  any  purpose  and  without  fee is hereby    **/
+/**    granted, provided that the above copyright notice appear  in  all    **/
+/**    copies and that both  that  copyright  notice  and  this  permis-    **/
+/**    sion  notice appear in supporting  documentation,  and  that  the    **/
+/**    name of Solbourne not be used in advertising                         **/
+/**    in publicity pertaining to distribution of the  software  without    **/
+/**    specific, written prior permission.                                  **/
+/**                                                                         **/
+/**    ANDREAS STOLCKE AND SOLBOURNE COMPUTER INC. DISCLAIMS ALL WARRANTIES **/
+/**    WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF    **/
+/**    MERCHANTABILITY  AND  FITNESS,  IN  NO  EVENT SHALL ANDREAS STOLCKE  **/
+/**    OR SOLBOURNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL    **/
+/**    DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA   **/
+/**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **/
+/**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **/
+/**    OR PERFORMANCE OF THIS SOFTWARE.                                     **/
+/*****************************************************************************/
+/*
+ * vroot.h -- Virtual Root Window handling header file
+ *
+ * This header file redefines the X11 macros RootWindow and DefaultRootWindow,
+ * making them look for a virtual root window as provided by certain `virtual'
+ * window managers like swm and tvtwm. If none is found, the ordinary root
+ * window is returned, thus retaining backward compatibility with standard
+ * window managers.
+ * The function implementing the virtual root lookup remembers the result of
+ * its last invocation to avoid overhead in the case of repeated calls
+ * on the same display and screen arguments. 
+ * The lookup code itself is taken from Tom LaStrange's ssetroot program.
+ *
+ * Most simple root window changing X programs can be converted to using
+ * virtual roots by just including
+ *
+ * #include <X11/vroot.h>
+ *
+ * after all the X11 header files.  It has been tested on such popular
+ * X clients as xphoon, xfroot, xloadimage, and xaqua.
+ * It also works with the core clients xprop, xwininfo, xwd, and editres
+ * (and is necessary to get those clients working under tvtwm).
+ * It does NOT work with xsetroot; get the xsetroot replacement included in
+ * the tvtwm distribution instead.
+ *
+ * Andreas Stolcke <stolcke@ICSI.Berkeley.EDU>, 9/7/90
+ * - replaced all NULL's with properly cast 0's, 5/6/91
+ * - free children list (suggested by Mark Martin <mmm@cetia.fr>), 5/16/91
+ * - include X11/Xlib.h and support RootWindowOfScreen, too 9/17/91
+ */
+
+#ifndef _VROOT_H_
+#define _VROOT_H_
+
+#if !defined(lint) && !defined(SABER)
+static const char vroot_rcsid[] = "#Id: vroot.h,v 1.4 1991/09/30 19:23:16 stolcke Exp stolcke #";
+#endif
+
+#include <X11/X.h>
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+
+static Window
+#ifdef __STDC__ /* ANSIfication added by jwz, to avoid superfluous warnings. */
+VirtualRootWindowOfScreen(Screen *screen)
+#else /* !__STDC__ */
+VirtualRootWindowOfScreen(screen) Screen *screen;
+#endif /* !__STDC__ */
+{
+	static Screen *save_screen = (Screen *)0;
+	static Window root = (Window)0;
+
+	if (screen != save_screen) {
+		Display *dpy = DisplayOfScreen(screen);
+		Atom __SWM_VROOT = None;
+		int i;
+		Window rootReturn, parentReturn, *children;
+		unsigned int numChildren;
+
+		root = RootWindowOfScreen(screen);
+
+		/* go look for a virtual root */
+		__SWM_VROOT = XInternAtom(dpy, "__SWM_VROOT", False);
+		if (XQueryTree(dpy, root, &rootReturn, &parentReturn,
+				 &children, &numChildren)) {
+			for (i = 0; i < numChildren; i++) {
+				Atom actual_type;
+				int actual_format;
+				unsigned long nitems, bytesafter;
+				Window *newRoot = (Window *)0;
+
+				if (XGetWindowProperty(dpy, children[i],
+					__SWM_VROOT, 0, 1, False, XA_WINDOW,
+					&actual_type, &actual_format,
+					&nitems, &bytesafter,
+					(unsigned char **) &newRoot) == Success
+				    && newRoot) {
+				    root = *newRoot;
+				    break;
+				}
+			}
+			if (children)
+				XFree((char *)children);
+		}
+
+		save_screen = screen;
+	}
+
+	return root;
+}
+
+#undef RootWindowOfScreen
+#define RootWindowOfScreen(s) VirtualRootWindowOfScreen(s)
+
+#undef RootWindow
+#define RootWindow(dpy,screen) VirtualRootWindowOfScreen(ScreenOfDisplay(dpy,screen))
+
+#undef DefaultRootWindow
+#define DefaultRootWindow(dpy) VirtualRootWindowOfScreen(DefaultScreenOfDisplay(dpy))
+
+#endif /* _VROOT_H_ */
diff -u -N bomb.old/xshm.c bomb/xshm.c
--- bomb.old/xshm.c	Thu Jan  1 01:00:00 1970
+++ bomb/xshm.c	Fri Nov 13 12:12:57 1998
@@ -0,0 +1,194 @@
+/* xscreensaver, Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
+ *  by Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ */
+
+/* The MIT-SHM (Shared Memory) extension is pretty tricky to use.
+   This file contains the common boiler-plate for creating a shared
+   XImage structure, and for making sure that the shared memory segments
+   get allocated and shut down cleanly.
+
+   This code currently deals only with shared XImages, not with shared Pixmaps.
+   It also doesn't use "completion events", but so far that doesn't seem to
+   be a problem (and I'm not entirely clear on when they would actually be
+   needed, anyway.)
+
+   If you don't have man pages for this extension, see
+   http://www.physik.uni-regensburg.de/~scs22156/sofie-0.2/mit-shm.html
+   or in the R6 sources as "xc/doc/specs/Xext/mit-shm.ms", for example,
+   ftp://ftp.x.org/pub/R6.4/xc/doc/specs/Xext/mit-shm.ms
+
+   (This document seems not to ever remain available on the web in one place
+   for very long; you can search for it by the title, "MIT-SHM -- The MIT
+   Shared Memory Extension".)
+
+   To monitor the system's shared memory segments, run "ipcs -m".
+  */
+
+#include "utils.h"
+#include "defs.h"
+
+#ifdef HAVE_XSHM_EXTENSION	/* whole file */
+
+/* #define DEBUG */
+
+#include <errno.h>		/* for perror() */
+#include <X11/Xutil.h>		/* for XDestroyImage() */
+
+#include "xshm.h"
+
+#ifdef DEBUG
+# include <X11/Xmu/Error.h>
+#endif
+
+extern char *progname;
+
+
+/* The documentation for the XSHM extension implies that if the server
+   supports XSHM but is not the local machine, the XShm calls will return
+   False; but this turns out not to be the case.  Instead, the server
+   throws a BadAccess error.  So, we need to catch X errors around all
+   of our XSHM calls, sigh.
+ */
+
+static Bool shm_got_x_error = False;
+XErrorHandler old_handler = 0;
+static int
+shm_ehandler (Display *dpy, XErrorEvent *error)
+{
+  shm_got_x_error = True;
+
+#ifdef DEBUG
+  fprintf (stderr, "\n%s: ignoring X error from XSHM:\n", progname);
+  XmuPrintDefaultErrorMessage (dpy, error, stderr);
+  fprintf (stderr, "\n");
+#endif
+
+  return 0;
+}
+
+
+#define CATCH_X_ERROR(DPY) do {				\
+  XSync((DPY), False); 					\
+  shm_got_x_error = False;				\
+  if (old_handler != shm_ehandler)			\
+    old_handler = XSetErrorHandler (shm_ehandler);	\
+} while(0)
+
+#define UNCATCH_X_ERROR(DPY) do {			\
+  XSync((DPY), False); 					\
+  if (old_handler)					\
+    XSetErrorHandler (old_handler);			\
+    old_handler = 0;					\
+} while(0)
+
+
+XImage *
+create_xshm_image (Display *dpy, Visual *visual,
+		   unsigned int depth,
+		   int format, char *data,
+		   XShmSegmentInfo *shm_info,
+		   unsigned int width, unsigned int height)
+{
+  Status status;
+  XImage *image = 0;
+  /*
+  if (!get_boolean_resource("useSHM", "Boolean"))
+    return 0;
+  */	
+
+  if (!XShmQueryExtension (dpy))
+    return 0;
+
+  CATCH_X_ERROR(dpy);
+  image = XShmCreateImage(dpy, visual, depth,
+			  format, data, shm_info, width, height);
+  UNCATCH_X_ERROR(dpy);
+  if (shm_got_x_error)
+    return 0;
+
+#ifdef DEBUG
+  fprintf(stderr, "\n%s: XShmCreateImage(... %d, %d)\n", progname,
+	  width, height);
+#endif
+
+  shm_info->shmid = shmget(IPC_PRIVATE,
+			   image->bytes_per_line * image->height,
+			   IPC_CREAT | 0777);
+#ifdef DEBUG
+  fprintf(stderr, "%s: shmget(IPC_PRIVATE, %d, IPC_CREAT | 0777) ==> %d\n",
+	  progname, image->bytes_per_line * image->height, shm_info->shmid);
+#endif
+
+  if (shm_info->shmid == -1)
+    {
+      char buf[1024];
+      sprintf (buf, "%s: shmget failed", progname);
+      perror(buf);
+      XDestroyImage (image);
+      image = 0;
+      XSync(dpy, False);
+    }
+  else
+    {
+      shm_info->readOnly = False;
+      image->data = shm_info->shmaddr = shmat(shm_info->shmid, 0, 0);
+
+#ifdef DEBUG
+      fprintf(stderr, "%s: shmat(%d, 0, 0) ==> %d\n", progname,
+	      shm_info->shmid, (int) image->data);
+#endif
+
+      CATCH_X_ERROR(dpy);
+      status = XShmAttach(dpy, shm_info);
+      UNCATCH_X_ERROR(dpy);
+      if (shm_got_x_error)
+	status = False;
+
+      if (!status)
+	{
+	  fprintf (stderr, "%s: XShmAttach failed!\n", progname);
+	  XDestroyImage (image);
+	  XSync(dpy, False);
+	  shmdt (shm_info->shmaddr);
+	  image = 0;
+	}
+
+#ifdef DEBUG
+      fprintf(stderr, "%s: XShmAttach(dpy, shm_info) ==> True\n", progname);
+#endif
+
+      XSync(dpy, False);
+
+      /* Delete the shared segment right now; the segment won't actually
+	 go away until both the client and server have deleted it.  The
+	 server will delete it as soon as the client disconnects, so we
+	 should delete our side early in case of abnormal termination.
+	 (And note that, in the context of xscreensaver, abnormal
+	 termination is the rule rather than the exception, so this would
+	 leak like a sieve if we didn't do this...)
+
+	 #### Are we leaking anyway?  Perhaps because of the window of
+	 opportunity between here and the XShmAttach call above, during
+	 which we might be killed?  Do we need to establish a signal
+	 handler for this case?
+       */
+      shmctl (shm_info->shmid, IPC_RMID, 0);
+
+#ifdef DEBUG
+      fprintf(stderr, "%s: shmctl(%d, IPC_RMID, 0)\n\n", progname,
+	      shm_info->shmid);
+#endif
+    }
+
+  return image;
+}
+
+#endif /* HAVE_XSHM_EXTENSION */
diff -u -N bomb.old/xshm.h bomb/xshm.h
--- bomb.old/xshm.h	Thu Jan  1 01:00:00 1970
+++ bomb/xshm.h	Thu Nov 12 13:24:30 1998
@@ -0,0 +1,34 @@
+/* xscreensaver, Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
+ *  by Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ */
+
+/* The MIT-SHM (Shared Memory) extension is pretty tricky to use.
+   This file contains the common boiler-plate for creating a shared
+   XImage structure, and for making sure that the shared memory segments
+   get allocated and shut down cleanly.
+ */
+
+#ifndef __XSCREENSAVER_XSHM_H__
+
+#ifdef HAVE_XSHM_EXTENSION
+# include <sys/ipc.h>
+# include <sys/shm.h>
+# include <X11/extensions/XShm.h>
+
+extern XImage *create_xshm_image (Display *dpy, Visual *visual,
+				  unsigned int depth,
+				  int format, char *data,
+				  XShmSegmentInfo *shm_info,
+				  unsigned int width, unsigned int height);
+
+#endif /* HAVE_XSHM_EXTENSION */
+
+#endif /* __XSCREENSAVER_XSHM_H__ */

