http://ftp.x.org/contrib/applications/xscreensaver-3.06.tar.gz
authorZygo Blaxell <zblaxell@hungrycats.org>
Mon, 2 Mar 2009 05:42:31 +0000 (00:42 -0500)
committerZygo Blaxell <zblaxell@hungrycats.org>
Mon, 2 Mar 2009 05:42:31 +0000 (00:42 -0500)
-rw-r--r-- 1 zblaxell zblaxell 981196 Nov 21  1998 xscreensaver-3.06.tar.gz
bfd2d8852b00710dec41f2a2e335c008fe0b84de  xscreensaver-3.06.tar.gz

62 files changed:
README
driver/XScreenSaver.ad.in
driver/XScreenSaver_ad.h
driver/windows.c
driver/xscreensaver-command.man
driver/xscreensaver-demo.man
driver/xscreensaver.h
driver/xscreensaver.man
hacks/Makefile.in
hacks/attraction.c
hacks/blitspin.c
hacks/bsod.c
hacks/bubbles.c
hacks/compile_axp.com
hacks/compile_decc.com
hacks/coral.c
hacks/cynosure.c
hacks/decayscreen.c
hacks/deco.c
hacks/distort.c
hacks/epicycle.c
hacks/flame.c
hacks/glx/glplanet.c
hacks/glx/lament.c
hacks/glx/xpm-ximage.c
hacks/goop.c
hacks/greynetic.c
hacks/halo.c
hacks/helix.c
hacks/hypercube.c
hacks/imsmap.c
hacks/interference.c
hacks/jigsaw.c
hacks/kaleidescope.c
hacks/kumppa.c
hacks/lmorph.c
hacks/maze.c
hacks/moire.c
hacks/moire2.c
hacks/munch.c
hacks/noseguy.c
hacks/pedal.c
hacks/pyro.c
hacks/qix.c
hacks/rd-bomb.c
hacks/rocks.c
hacks/rorschach.c
hacks/screenhack.c
hacks/screenhack.h
hacks/slidescreen.c
hacks/sonar.c [new file with mode: 0644]
hacks/sonar.man [new file with mode: 0644]
hacks/starfish.c
hacks/truchet.c
hacks/xjack.c
hacks/xlockmore.c
hacks/xlyap.c
hacks/xroger-hack.c
setup.com
utils/version.h
xscreensaver.lsm
xscreensaver.spec

diff --git a/README b/README
index e866fcaabcc76e6c7e0d1368de19f6cf3d32191e..94da385a119a0aad2e8541ce96be801968c0a01f 100644 (file)
--- a/README
+++ b/README
@@ -77,6 +77,23 @@ http://www.jwz.org/xscreensaver/.
 
                               ============
 
+Changes since 3.05:   * Oops, the "default-n" visual descriptor was broken;
+                        it was always installing a colormap if the
+                        `installColormap' preference was set, meaning that
+                        `xearth', `xv' and friends were using the wrong
+                        colors on 8-bit systems.
+                      * Turned off HAVE_PING in `sonar', since it compiles
+                        on some Linux systems, but not others of similar
+                        vintage...
+Changes since 3.04:   * Fixed an off-by-1 in `distort'.
+                      * Added `sonar' hack.
+                      * New version of `glplanet' (with stars.)
+                      * Made all hacks exit when you type `q' or `ESC' at them,
+                        and made them obey the WM_DELETE_WINDOW ClientMessage.
+                      * Fixed a nonfatal buffer overrun in lament (note:
+                        lament still doesn't work with MesaGL 3.0: it dies in
+                        lambda_textured_triangle1(), which is Mesa's bug, not
+                        mine.)
 Changes since 3.03:   * Added an `xscreensaver.spec' file, to make it easier
                         for other folks to generate RPMs.
                       * Made the password code work on HPUX in the situation
index 0fee5d3e1706fab634d14a84a206bc9c46e2ee47..ce557228ca27c077b0ecf0aa02fc8eaa6b9eab8c 100644 (file)
@@ -4,8 +4,8 @@
 !            a screen saver and locker for the X window system
 !                            by Jamie Zawinski
 !
-!                              version 3.04
-!                                16-Nov-98
+!                              version 3.06
+!                                22-Nov-98
 !
 ! See "man xscreensaver" for more info.  The latest version is always
 ! available at http://www.jwz.org/xscreensaver/
                kumppa -root                                            \n\
                rd-bomb -root                                           \n\
                rd-bomb -root -speed 1 -size 0.1                        \n\
+               sonar -root                                             \n\
                                                                          \
        mono:   rocks -root                                             \n\
        color:  rocks -root -fg darksalmon                              \n\
index 61de93c455747af9ead805712175ba7865007e6e..b49fc28b3acdf1fe13b0dc25351c97831ce66e31 100644 (file)
@@ -98,6 +98,7 @@
                kumppa -root                                            \\n\
                rd-bomb -root                                           \\n\
                rd-bomb -root -speed 1 -size 0.1                        \\n\
+               sonar -root                                             \\n\
                                                                          \
        mono:   rocks -root                                             \\n\
        color:  rocks -root -fg darksalmon                              \\n\
index 73170415be7419b6ee7cbc2fbfc7cbde583c5cb2..e5231fb03270d7ab31c839929d9ef41046d406fe 100644 (file)
@@ -769,7 +769,7 @@ initialize_screensaver_window_1 (saver_screen_info *ssi)
 {
   saver_info *si = ssi->global;
   saver_preferences *p = &si->prefs;
-  Bool install_cmap_p = (ssi->install_cmap_p || p->install_cmap_p);
+  Bool install_cmap_p = ssi->install_cmap_p;   /* not p->install_cmap_p */
 
   /* This resets the screensaver window as fully as possible, since there's
      no way of knowing what some random client may have done to us in the
@@ -789,6 +789,7 @@ initialize_screensaver_window_1 (saver_screen_info *ssi)
     ssi->cmap = 0;
 
   if (ssi->current_visual != DefaultVisualOfScreen (ssi->screen))
+    /* It's not the default visual, so we have no choice but to install. */
     install_cmap_p = True;
 
   if (install_cmap_p)
@@ -1295,6 +1296,7 @@ select_visual (saver_screen_info *ssi, const char *visual_name)
   got_it = !!new_v;
 
   if (new_v && new_v != DefaultVisualOfScreen(ssi->screen))
+    /* It's not the default visual, so we have no choice but to install. */
     install_cmap_p = True;
 
   ssi->install_cmap_p = install_cmap_p;
index 5905b85d4fe8f3b96baf899f61928c6834d17586..48f81a35da9d84457813063028ed6e13df8b1216 100644 (file)
@@ -11,7 +11,7 @@
 .if n .sp 1
 .if t .sp .5
 ..
-.TH XScreenSaver 1 "16-Nov-98 (3.04)" "X Version 11"
+.TH XScreenSaver 1 "22-Nov-98 (3.06)" "X Version 11"
 .SH NAME
 xscreensaver-command - control a running xscreensaver process
 .SH SYNOPSIS
index 44611dd769e141b03ac0670a7c625dc0942ddb7f..aee5d9e213252c856110e5b9dcd804fa595a375e 100644 (file)
@@ -11,7 +11,7 @@
 .if n .sp 1
 .if t .sp .5
 ..
-.TH XScreenSaver 1 "16-Nov-98 (3.04)" "X Version 11"
+.TH XScreenSaver 1 "22-Nov-98 (3.06)" "X Version 11"
 .SH NAME
 xscreensaver-demo - interactively control the background xscreensaver daemon
 .SH SYNOPSIS
index 1926703ca48f413f5380522508601f4abf230255..be09025f7da5f3da5d648fe7902da7db7df89d74 100644 (file)
@@ -176,9 +176,11 @@ struct saver_screen_info {
                                   destroy and recreate it on different
                                   visuals. */
   Colormap cmap;               /* The colormap that goes with the window. */
-  Bool install_cmap_p;         /* whether we should use our own colormap.
-                                  This can be overridden on a per-hack basis.
-                                */
+  Bool install_cmap_p;         /* Whether this screen should have its own
+                                   colormap installed, for whichever of several
+                                   reasons.  This is definitive (even a false
+                                   value here overrides prefs->install_cmap_p.)
+                                 */
   Visual *current_visual;      /* The visual of the window. */
   Visual *default_visual;      /* visual to use when none other specified */
   int current_depth;           /* How deep the visual (and the window) are. */
index 94754b17f2fca70865ad0facb7fa392764c7c791..ff978401ea6999d355bc3044fde4c7a6ecee74c0 100644 (file)
@@ -11,7 +11,7 @@
 .if n .sp 1
 .if t .sp .5
 ..
-.TH XScreenSaver 1 "16-Nov-98 (3.04)" "X Version 11"
+.TH XScreenSaver 1 "22-Nov-98 (3.06)" "X Version 11"
 .SH NAME
 xscreensaver - graphics hack and screen locker, launched when the user is idle
 .SH SYNOPSIS
@@ -967,16 +967,30 @@ The
 .BR mwm (1)
 and
 .BR olwm (1)
-window managers don't seem to have this problem.  The race condition exists
-because X does not provide a way for an OverrideRedirect window to have its
-own colormap, short of grabbing the server (which is neither a good idea, nor
-really possible with the current design.)  What happens is that, as soon as
-the screensaver installs its colormap, \fBtwm\fP responds to 
-the \fBColormapNotify\fP event that is generated by re-instaling the default
-colormap.  Apparently, \fBtwm\fP doesn't \fIalways\fP do this; it seems to do
-it regularly if the screensaver is activated from a menu item, but seems to
-not do it if the screensaver comes on of its own volition, or is activated
-from another console.  Any thoughts on this problem are welcome...
+window managers don't have this problem.  The race condition exists
+because X (really, ICCCM) does not provide a way for an OverrideRedirect 
+window to have its own colormap, short of grabbing the server (which is 
+neither a good idea, nor really possible with the current design.)  What 
+happens is that, as soon as xscreensaver installs its colormap, \fBtwm\fP 
+responds to the resultant \fBColormapNotify\fP event by re-instaling the 
+default colormap.  Apparently, \fBtwm\fP doesn't \fIalways\fP do this; it 
+seems to do it regularly if the screensaver is activated from a menu item, 
+but seems to not do it if the screensaver comes on of its own volition, or 
+is activated from another console.  
+.RS 8
+.TP 4
+.B Attention, window manager authors!
+You should only call
+.BR XInstallColormap (3)
+in response to user events.  That is, it is appropriate to install a colormap
+in response to \fBFocusIn\fP, \fBFocusOut\fP, \fBEnterNotify\fP, 
+and \fBLeaveNotify\fP events; but it is not appropriate to call it in
+response to \fBColormapNotify\fP events.  If you install colormaps in
+response to \fIapplication\fP actions as well as in response to \fIuser\fP
+actions, then you create the situation where it is impossible for 
+override-redirect applications (such as xscreensaver) to display their
+windows in the proper colors.
+.RE
 .TP 8
 .B Colormap lossage: XV, XAnim, XEarth
 Some programs don't operate properly on visuals other than the default one,
@@ -985,8 +999,8 @@ magic "default-n" visual name in the description of the \fBprograms\fP
 resource in the \fIConfiguration\fP section.  When programs only work with
 the default colormap, you need to use a syntax like this:
 .EX
-    default-n: xv -root image-1.gif -quit  \\n\\
-    default-n: xearth -nostars -wait 0     \\n\\
+   default-n: xv -root image-1.gif -quit  \\n\\
+   default-n: xearth -nostars -wait 0     \\n\\
 .EE
 It would also work to turn off the \fBinstallColormap\fP option altogether,
 but that would deny extra colors to those programs that \fIcan\fP take
index de2c10e3f78636ef62d29a953df86d9a28da28fb..78726220a56308b69eb6399b98b070bc6d3994a4 100644 (file)
@@ -80,7 +80,8 @@ SRCS          = attraction.c blitspin.c bouboule.c braid.c bubbles.c \
                  rd-bomb.c coral.c mountain.c triangle.c lissie.c worm.c \
                  rotor.c ant.c xjack.c xlyap.c jigsaw.c xscreensaver-sgigl.c \
                  cynosure.c moire2.c flow.c epicycle.c interference.c \
-                 truchet.c bsod.c crystal.c discrete.c distort.c kumppa.c
+                 truchet.c bsod.c crystal.c discrete.c distort.c kumppa.c \
+                 sonar.c
 
 OBJS           = attraction.o blitspin.o bouboule.o braid.o bubbles.o \
                  bubbles-default.o decayscreen.o deco.o drift.o flag.o \
@@ -94,7 +95,8 @@ OBJS          = attraction.o blitspin.o bouboule.o braid.o bubbles.o \
                  rd-bomb.o coral.o mountain.o triangle.o lissie.o worm.o \
                  rotor.o ant.o xjack.o xlyap.o jigsaw.o xscreensaver-sgigl.o \
                  cynosure.o moire2.o flow.o epicycle.o interference.o \
-                 truchet.o bsod.o crystal.o discrete.o distort.o kumppa.o
+                 truchet.o bsod.o crystal.o discrete.o distort.o kumppa.o \
+                 sonar.o
 
 EXES           = attraction blitspin bouboule braid bubbles decayscreen deco \
                  drift flag flame forest vines galaxy grav greynetic halo \
@@ -104,7 +106,8 @@ EXES                = attraction blitspin bouboule braid bubbles decayscreen deco \
                  slip sphere spiral strange swirl xroger goop starfish munch \
                  fadeplot rd-bomb coral mountain triangle lissie worm rotor \
                  ant xjack xlyap jigsaw cynosure moire2 flow epicycle \
-                 interference truchet bsod crystal discrete distort kumppa
+                 interference truchet bsod crystal discrete distort kumppa \
+                 sonar
 
 HACK_OBJS_1    = $(UTILS_BIN)/resources.o $(UTILS_BIN)/visual.o \
                  $(UTILS_BIN)/usleep.o $(UTILS_BIN)/yarandom.o @XMU_OBJS@
@@ -127,7 +130,8 @@ MEN         = attraction.man blitspin.man bouboule.man braid.man \
                  rocks.man rorschach.man sierpinski.man slidescreen.man \
                  slip.man sphere.man spiral.man strange.man swirl.man \
                  xroger.man goop.man starfish.man munch.man rd-bomb.man \
-                 xjack.man xlyap.man jigsaw.man epicycle.man bsod.man
+                 xjack.man xlyap.man jigsaw.man epicycle.man bsod.man \
+                 sonar.man
 STAR           = *
 EXTRAS         = README Makefile.in xlock_23.h .gdbinit \
                  vidwhacker \
@@ -452,6 +456,9 @@ distort:             $(HACK_OBJS) distort.o $(GRAB) $(SHM)
 kumppa:                 $(HACK_OBJS) kumppa.o
        $(CC_HACK) -o $@ $(HACK_OBJS) kumppa.o $(HACK_LIBS)
 
+sonar:          $(HACK_OBJS) sonar.o $(COL)
+       $(CC_HACK) -o $@ $(HACK_OBJS) sonar.o $(COL) $(HACK_LIBS)
+
 
 # The rules for those hacks which follow the `xlockmore' API.
 #
@@ -1422,4 +1429,13 @@ kumppa.o: $(UTILS_SRC)/hsv.h
 kumppa.o: $(UTILS_SRC)/colors.h
 kumppa.o: $(UTILS_SRC)/grabscreen.h
 kumppa.o: $(UTILS_SRC)/visual.h
+sonar.o: $(srcdir)/screenhack.h
+sonar.o: ../config.h
+sonar.o: $(UTILS_SRC)/yarandom.h
+sonar.o: $(UTILS_SRC)/usleep.h
+sonar.o: $(UTILS_SRC)/resources.h
+sonar.o: $(UTILS_SRC)/hsv.h
+sonar.o: $(UTILS_SRC)/colors.h
+sonar.o: $(UTILS_SRC)/grabscreen.h
+sonar.o: $(UTILS_SRC)/visual.h
 
index 4b16af97b9b904d3201a2bd1ce5570065fd265e5..1a84833b80fb89a86becee326877b31260961108 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1997
+/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1997, 1998
  *  Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -605,7 +605,7 @@ run_balls (Display *dpy, Window window)
       abort ();
     }
 
-  XSync (dpy, True);
+  XSync (dpy, False);
 }
 
 \f
@@ -661,6 +661,7 @@ screenhack (Display *dpy, Window window)
   while (1)
     {
       run_balls (dpy, window);
+      screenhack_handle_events (dpy);
       if (delay) usleep (delay);
     }
 }
index cf2941b5484040a98c5a3e34906e552b0b65244a..1c5272537718321a6dc68c84d9206c324ef7ec12 100644 (file)
@@ -299,6 +299,7 @@ init (void)
 
   display (self);
   XSync(dpy, False);
+  screenhack_handle_events (dpy);
 }
 
 static void
@@ -326,7 +327,8 @@ display (Pixmap pixmap)
                  ((xgwa.width-size)>>1)-1, ((xgwa.height-size)>>1)-1,
                  size+2, size+2);
 */
-  XSync (dpy, True);
+  XSync (dpy, False);
+  screenhack_handle_events (dpy);
 }
 
 \f
@@ -360,6 +362,7 @@ screenhack (Display *d, Window w)
   while (1)
     {
       rotate ();
+      screenhack_handle_events (d);
       if (delay2) usleep (delay2);
     }
 }
index 3f3cd346fb69de8f803e41174e2ddbe5ac1963b2..4e3516059a3e373413111fab029cbf99597c0420 100644 (file)
@@ -157,18 +157,25 @@ double_pixmap(Display *dpy, GC gc, Visual *visual, int depth, Pixmap pixmap,
 static Bool
 bsod_sleep(Display *dpy, int seconds)
 {
-  XEvent event;
   int q = seconds * 4;
-  int mask = KeyPressMask|ButtonPressMask;
   do
     {
       XSync(dpy, False);
-      if (XCheckMaskEvent(dpy, mask, &event))
-       {
-         while (XCheckMaskEvent(dpy, mask, &event))
-           ;
-         return True;
-       }
+      while (XPending (dpy))
+        {
+          XEvent event;
+          XNextEvent (dpy, &event);
+          if (event.xany.type == KeyPress)
+            {
+              KeySym keysym;
+              char c = 0;
+              XLookupString (&event.xkey, &c, 1, &keysym, 0);
+              if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
+                return True;
+            }
+          screenhack_handle_event (dpy, &event);
+        }
+
       if (q > 0)
        {
          q--;
@@ -1031,7 +1038,12 @@ screenhack (Display *dpy, Window window)
   if (delay < 3) delay = 3;
 
   if (!get_boolean_resource ("root", "Boolean"))
-    XSelectInput(dpy, window, KeyPressMask|ButtonPressMask);
+    {
+      XWindowAttributes xgwa;
+      XGetWindowAttributes (dpy, window, &xgwa);
+      XSelectInput (dpy, window,
+                    xgwa.your_event_mask | KeyPressMask | ButtonPressMask);
+    }
 
   while (1)
     {
@@ -1053,7 +1065,7 @@ screenhack (Display *dpy, Window window)
       if (loop > 100) j = -1;
       if (loop > 200) exit(-1);
       if (!did) continue;
-      XSync (dpy, True);
+      XSync (dpy, False);
       j = i;
       loop = 0;
     }
index 735033d191b587f2886a6aed4efa469e53e8cfe7..913fe03726df2c676d19b80902dfd24cbdb2a5db 100644 (file)
@@ -1,6 +1,6 @@
 /* bubbles.c - frying pan / soft drink in a glass simulation */
 
-/*$Id: bubbles.c,v 1.15 1998/06/21 23:49:25 jwz Exp $*/
+/*$Id: bubbles.c,v 1.16 1998/11/19 07:25:01 jwz Exp $*/
 
 /*
  *  Copyright (C) 1995-1996 James Macnicol
@@ -1302,7 +1302,7 @@ bubbles (Display *dpy, Window window)
   add_to_mesh(tmp);
   insert_new_bubble(tmp);
 
-  XSync (dpy, True);
+  XSync (dpy, False);
 }
 
 
@@ -1312,6 +1312,7 @@ screenhack (Display *dpy, Window window)
   init_bubbles (dpy, window);
   while (1) {
     bubbles (dpy, window);
+    screenhack_handle_events (dpy);
     if (delay)
       usleep(delay);
   }
index bcfa03f7739d2bf4911632f0a69124f23b6aed01..fc329272e07499fea3ba5d77965253a3bb64cf9e 100644 (file)
@@ -58,6 +58,7 @@ $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) SIERPINSKI.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) SLIDESCREEN.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) SLIP.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) SONAR.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) SPHERE.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) SPIRAL.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) STARFISH.C
index bcfa03f7739d2bf4911632f0a69124f23b6aed01..fc329272e07499fea3ba5d77965253a3bb64cf9e 100644 (file)
@@ -58,6 +58,7 @@ $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) SIERPINSKI.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) SLIDESCREEN.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) SLIP.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) SONAR.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) SPHERE.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) SPIRAL.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) STARFISH.C
index 55186747327297fbe731753507d061b0c3815064..7621d5eee4818b4b8b830547f9c77fc24535cf46 100644 (file)
@@ -170,7 +170,7 @@ coral(Display *dpy, Window window)
                  XDrawPoints(dpy, window, draw_gc, pointbuf, npoints,
                              CoordModeOrigin);
                  npoints = 0;
-                 XSync(dpy, True);
+                 XSync(dpy, False);
                }
 
                if (color) {
@@ -181,7 +181,7 @@ coral(Display *dpy, Window window)
                 }
 
                 if( 0 == nwalkers ) {
-                    XSync(dpy, True);
+                    XSync(dpy, False);
                    free(pointbuf);
                     return;
                 }
@@ -217,8 +217,9 @@ coral(Display *dpy, Window window)
            XDrawPoints(dpy, window, draw_gc, pointbuf, npoints,
                        CoordModeOrigin);
            npoints = 0;
-           XSync(dpy, True);
+           XSync(dpy, False);
          }
+          screenhack_handle_events (dpy);
          usleep(delay2);
        }
     }
@@ -253,6 +254,7 @@ Window window;
     while( 1 ) {
         init_coral(dpy, window);
         coral(dpy, window);
+        screenhack_handle_events (dpy);
         if( delay ) sleep(delay);
        erase_full_window(dpy, window);
     }
index 568825803ec0d71f114cad10131291a31c26604b..052a9444b35a894d7a1beb3f5aae6dacd4707d48 100644 (file)
@@ -214,6 +214,7 @@ void screenhack(Display *d, Window w)
        }
       paint();
       XSync(dpy, False);
+      screenhack_handle_events (dpy);
       if (delay)
        usleep(delay);
     }
index 7b91f63bbd52b0cc06a25f6fcf68e39b724b96f6..da6a5fef770826f6f955aa050f7a2642bf6850b8 100644 (file)
@@ -207,6 +207,7 @@ screenhack (Display *dpy, Window window)
       for (i = 0; i < 100; i++)
        decay1 (dpy, window);
       XSync(dpy, False);
+      screenhack_handle_events (dpy);
       if (delay) usleep (delay);
     }
 }
index 3b49c09a74be7afb589cebaf42908c2b7c459cbc..ae908051f05120448461673190127960ba973ba7 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1997 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1997, 1998 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
@@ -133,7 +133,8 @@ screenhack (Display *dpy, Window window)
       XFillRectangle(dpy, window, bgc, 0, 0, xgwa.width, xgwa.height);
       deco (dpy, window, xgwa.colormap, fgc, bgc,
            0, 0, xgwa.width, xgwa.height, 0);
-      XSync (dpy, True);
+      XSync (dpy, False);
+      screenhack_handle_events (dpy);
 
       if (!delay) continue;
       if (!writable)
@@ -144,6 +145,8 @@ screenhack (Display *dpy, Window window)
          while (start - delay < time((time_t) 0))
            {
              rotate_colors (dpy, xgwa.colormap, colors, ncolors, 1);
+              XSync (dpy, False);
+              screenhack_handle_events (dpy);
              if (cycle_delay)
                usleep (cycle_delay);
            }
index 7eed6281c8b9c4d3ecef180c77956506ae080fd9..dc8852d01cf79db38b4f22763288c675447fa524 100644 (file)
@@ -432,8 +432,8 @@ void reflect_draw(int k)
                        else {
                                int     x = xy_coo[k].x + cx + (lx * rsq / dist);
                                int     y = xy_coo[k].y + cy + (ly * rsq / dist);
-                               if (x < 0 || x > xgwa.width ||
-                                       y < 0 || y > xgwa.height)
+                               if (x < 0 || x >= xgwa.width ||
+                                       y < 0 || y >= xgwa.height)
                                        XPutPixel( buffer_map, j, i, black_pixel );
                                else
                                        XPutPixel( buffer_map, j, i,
@@ -592,7 +592,8 @@ void screenhack(Display *dpy, Window window)
                        draw(k);
                }
 
-               XSync(dpy, True);
+               XSync(dpy, False);
+        screenhack_handle_events (dpy);
                if (delay) usleep(delay);
        }
 
index eed186ca75551629d9b51cdc336ca949619b3797..b812e6ae38968adb6e036c9b8aed8d5e8e43c294 100644 (file)
@@ -534,6 +534,10 @@ check_events (void)                        /* X event handler [ rhess ] */
            printf("re-mapped!\n");
          unmapped = 0;
          break;
+
+        default:
+          screenhack_handle_event(dpy, &e);
+          break;
        }
                
       /* If we're unmapped, don't return to the caller.  This
@@ -580,8 +584,11 @@ setup(void)
     }
   else
     {
-      XSelectInput(dpy, window,
-                  ExposureMask|ButtonPressMask|StructureNotifyMask);
+      XWindowAttributes xgwa;
+      XGetWindowAttributes (dpy, window, &xgwa);
+      XSelectInput (dpy, window,
+                    xgwa.your_event_mask | ExposureMask |
+                    ButtonPressMask |StructureNotifyMask);
     }
   
 }
@@ -814,6 +821,7 @@ screenhack(Display *disp, Window win)
            {
              XSync (dpy, False);
 
+              check_events();
              if (holdtime)
                sleep(holdtime); /* show complete figure for a bit. */
 
@@ -821,6 +829,7 @@ screenhack(Display *disp, Window win)
            }
          
          
+         check_events();
          if (delay)
            usleep (delay);
          
index 521d3cb7400f6b525554d299e770404e56530d22..0cc7f65970fb5f0f8e1ca7d790319e97fb97504c 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1993, 1995, 1996
+/* xscreensaver, Copyright (c) 1993, 1995, 1996, 1998
  *  Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -167,7 +167,7 @@ recurse (double x, double y, int l, Display *dpy, Window win)
              XDrawPoints (dpy, win, gc, points, num_points, CoordModeOrigin);
              num_points = 0;
              /* if (delay) usleep (delay); */
-             /* XSync (dpy, True); */
+             /* XSync (dpy, False); */
            }
        }
     }
@@ -356,7 +356,7 @@ flame (Display *dpy, Window window)
   total_points = 0;
   (void) recurse (0.0, 0.0, 0, dpy, window);
   XDrawPoints (dpy, window, gc, points, num_points, CoordModeOrigin);
-  XSync (dpy, True);
+  XSync (dpy, False);
   if (delay) usleep (delay);
 }
 
@@ -405,5 +405,8 @@ screenhack (Display *dpy, Window window)
 {
   init_flame (dpy, window);
   while (1)
-    flame (dpy, window);
+    {
+      flame (dpy, window);
+      screenhack_handle_events (dpy);
+    }
 }
index ea74f429481af8ea117844fd79222694d8964183..7c71fc7d135c75e015801c462e70df6e16851c29 100644 (file)
@@ -20,6 +20,8 @@ static const char sccsid[] = "@(#)plate.c     4.07 97/11/24 xlockmore";
  * other special, indirect and consequential damages.
  *
  * Revision History:
+ * 9-Oct-98:  dek@cgl.ucsf.edu  Added stars.
+ *
  * 8-Oct-98:  jwz@jwz.org   Made the 512x512x1 xearth image be built in.
  *                          Made it possible to load XPM or XBM files.
  *                          Made the planet bounce and roll around.
@@ -27,13 +29,9 @@ static const char sccsid[] = "@(#)plate.c    4.07 97/11/24 xlockmore";
  * 8-Oct-98: Released initial version of "glplanet"
  * (David Konerding, dek@cgl.ucsf.edu)
  *
- * TODO:
- * 1) stars
- * 3) better earth image
- * 4) "exploding" planet mode-- the surface will expand and explode
- * 5) Fix bug with annoying triangles moving on surface
- *
- *
+ * BUGS:
+ * -bounce is broken
+ * 
  *   For even more spectacular results, grab the images from the "SSysten"
  *   package (http://www.msu.edu/user/kamelkev/) and do this:
  *
@@ -68,7 +66,7 @@ static const char sccsid[] = "@(#)plate.c     4.07 97/11/24 xlockmore";
                                        "*wireframe:            False   \n"     \
                                        "*light:                        True    \n"     \
                                        "*texture:                      True    \n" \
-                                       "*stipple:                      False   \n" \
+                                       "*stars:                        True    \n" \
                                        "*image:                        BUILTIN \n" \
                                        "*imageForeground:      Green   \n" \
                                        "*imageBackground:      Blue    \n"
@@ -102,8 +100,8 @@ static const char sccsid[] = "@(#)plate.c   4.07 97/11/24 xlockmore";
 #define DEF_ROLL    "True"
 #define DEF_BOUNCE  "True"
 #define DEF_TEXTURE "True"
+#define DEF_STARS "True"
 #define DEF_LIGHT   "True"
-#define DEF_STIPPLE "False"
 #define DEF_IMAGE   "BUILTIN"
 
 #undef countof
@@ -113,8 +111,8 @@ static int do_rotate;
 static int do_roll;
 static int do_bounce;
 static int do_texture;
+static int do_stars;
 static int do_light;
-static int do_stipple;
 static char *which_image;
 static XrmOptionDescRec opts[] = {
   {"-rotate",  ".glplanet.rotate",  XrmoptionNoArg, (caddr_t) "true" },
@@ -125,10 +123,10 @@ static XrmOptionDescRec opts[] = {
   {"+bounce",  ".glplanet.bounce",  XrmoptionNoArg, (caddr_t) "false" },
   {"-texture", ".glplanet.texture", XrmoptionNoArg, (caddr_t) "true" },
   {"+texture", ".glplanet.texture", XrmoptionNoArg, (caddr_t) "false" },
+  {"-stars",   ".glplanet.stars",   XrmoptionNoArg, (caddr_t) "true" },
+  {"+stars",   ".glplanet.stars",   XrmoptionNoArg, (caddr_t) "false" },
   {"-light",   ".glplanet.light",   XrmoptionNoArg, (caddr_t) "true" },
   {"+light",   ".glplanet.light",   XrmoptionNoArg, (caddr_t) "false" },
-  {"-stipple", ".glplanet.stipple", XrmoptionNoArg, (caddr_t) "true" },
-  {"+stipple", ".glplanet.stipple", XrmoptionNoArg, (caddr_t) "false" },
   {"-image",   ".glplanet.image",  XrmoptionSepArg, (caddr_t) 0 },
 };
 
@@ -137,8 +135,8 @@ static argtype vars[] = {
   {(caddr_t *) &do_roll,     "roll",    "Roll",    DEF_ROLL,    t_Bool},
   {(caddr_t *) &do_bounce,   "bounce",  "Bounce",  DEF_BOUNCE,  t_Bool},
   {(caddr_t *) &do_texture,  "texture", "Texture", DEF_TEXTURE, t_Bool},
+  {(caddr_t *) &do_stars,  "stars", "Stars", DEF_STARS, t_Bool},
   {(caddr_t *) &do_light,    "light",   "Light",   DEF_LIGHT,   t_Bool},
-  {(caddr_t *) &do_stipple,  "stipple", "Stipple", DEF_STIPPLE, t_Bool},
   {(caddr_t *) &which_image, "image",   "Image",   DEF_IMAGE,   t_String},
 };
 
@@ -162,32 +160,23 @@ ModStruct   planet_description =
  * at the expense of rendering speed
  */
 
-#define SLICES 25
-#define STACKS 25
-#define NUM_PLATES (STACKS * (SLICES+1))
+#define NUM_STARS 1000
+#define SLICES 15
+#define STACKS 15
 
 /* radius of the sphere- fairly arbitrary */
-#define RADIUS 5.
+#define RADIUS 4
 
+/* distance away from the sphere model */
+#define DIST 40
 
 
-/*-
- * structure for holding the data for an individual plate.
- * RotationRate, Angle, Vector, Translation and Color
- * are not currently used, but may be used in the future
- */
-typedef struct {
-  GLfloat RotationRate;
-  GLfloat Angle[4];
-  GLfloat Vector[3];
-  GLfloat Translation[3];
-  GLfloat Color[3];
-  GLuint platelist;
-} plate;
 
 /* structure for holding the planet data */
 typedef struct {
-  plate plates[NUM_PLATES];
+  GLuint platelist;
+  GLuint starlist;
+  int screen_width, screen_height;
   GLXContext *glx_context;
   Window window;
 
@@ -205,6 +194,21 @@ typedef struct {
 static planetstruct *planets = NULL;
 
 
+static inline void
+normalize(GLfloat v[3])
+{
+       GLfloat     d = (GLfloat) sqrt((double) (v[0] * v[0] + v[1] * v[1] + v[2] * v[2]));
+
+       if (d != 0) {
+               v[0] /= d;
+               v[1] /= d;
+               v[2] /= d;
+       } else {
+               v[0] = v[1] = v[2] = 0;
+       }
+}
+
+
 /* Set up and enable texturing on our object */
 static void
 setup_xbm_texture (char *bits, int width, int height,
@@ -233,7 +237,6 @@ setup_xbm_texture (char *bits, int width, int height,
                *out++ = (word & 0x0000FF);
          }
 
-  glEnable(GL_TEXTURE_2D);
   glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0,
                           GL_RGB, GL_UNSIGNED_BYTE, data);
 
@@ -242,8 +245,8 @@ setup_xbm_texture (char *bits, int width, int height,
   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 }
 
 
@@ -263,7 +266,6 @@ setup_file_texture (ModeInfo *mi, char *filename)
          {
                XImage *image = xpm_to_ximage (dpy, visual, cmap, xpm_data);
 
-               glEnable(GL_TEXTURE_2D);
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
                                         image->width, image->height, 0,
                                         GL_RGBA, GL_UNSIGNED_BYTE, image->data);
@@ -275,8 +277,8 @@ setup_file_texture (ModeInfo *mi, char *filename)
                glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+               glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                return;
          }
          break;
@@ -354,52 +356,10 @@ setup_texture(ModeInfo * mi)
 static void
 setup_light(void)
 {
-
-  glEnable(GL_DEPTH_TEST);
-  glEnable(GL_AUTO_NORMAL);
-  glEnable(GL_NORMALIZE);
-  glShadeModel(GL_SMOOTH);
-
-  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-  glEnable(GL_LINE_SMOOTH);
+  /* set a number of parameters which make the scene look much nicer */
   glEnable(GL_BLEND);
-
-  glEnable(GL_LIGHTING);
-  glEnable(GL_LIGHT0);
-
-  glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
-  glEnable(GL_COLOR_MATERIAL);
-
-}
-
-
-/* a stipple pattern */
-static GLubyte halftone[] =
-{
-  0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
-  0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
-  0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
-  0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
-  0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
-  0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
-  0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
-  0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
-  0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
-  0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
-  0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
-  0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
-  0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
-  0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
-  0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
-  0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
-};
-
-/* Set up and enable stippling */
-static void
-setup_stipple(void)
-{
-  glEnable(GL_POLYGON_STIPPLE);
-  glPolygonStipple(halftone);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  glShadeModel(GL_SMOOTH);
 }
 
 
@@ -413,148 +373,194 @@ setup_face(void)
 
 
 /* Function for determining points on the surface of the sphere */
-void ParametricSphere(float theta, float rho, float *vector)
+static void inline ParametricSphere(float theta, float rho, GLfloat *vector)
 {
-    vector[0] = -sin(theta) * sin(rho);
-    vector[1] = cos(theta) * sin(rho);
-    vector[2] = cos(rho);
+  vector[0] = -sin(theta) * sin(rho);
+  vector[1] = cos(theta) * sin(rho);
+  vector[2] = cos(rho);
+
+#if DO_HELIX
+  vector[0] = -(1- cos(theta)) * cos(rho); 
+  vector[1] = -(1- cos(theta)) * sin(rho); 
+  vector[2] = -(sin(theta) + rho); 
+#endif /* DO_HELIX */
+
        return;
 }
 
 
+/* lame way to generate some random stars */
+void generate_stars(int width, int height)
+{
+  int i;
+/*  GLfloat size_range[2], size;*/
+  GLfloat x, y;
+
+  planetstruct *gp = &planets[MI_SCREEN(mi)];
+  
+/*    glGetFloatv(GL_POINT_SIZE_RANGE, size_range); */
+  
+/*    printf("size range: %f\t%f\n", size_range[0], size_range[1]); */
+  gp->starlist = glGenLists(1);
+  glNewList(gp->starlist, GL_COMPILE);
+
+  /* this hackery makes the viewport map one-to-one with Vertex arguments */
+  glMatrixMode(GL_PROJECTION);
+  glPushMatrix();
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluOrtho2D(0, width, 0, height);
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+
+  /* disable depth testing for the stars, so they don't obscure the planet */
+  glDisable(GL_DEPTH_TEST);
+  glEnable(GL_POINT_SMOOTH);
+  glEnable(GL_BLEND);
+  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  
+  glBegin(GL_POINTS);
+  for(i = 0 ; i < NUM_STARS ; i++)
+       {
+/*       size = (drand48()+size_range[0]) * size_range[1]/2.; */
+/*    glPointSize(size); */
+         x = drand48()*width;
+         y = drand48()*height;
+         glVertex2f(x,y);
+       }
+  glEnd();
+
+  /* return to original PROJECT and MODELVIEW */
+  glMatrixMode(GL_PROJECTION);
+  glPopMatrix();
+  glMatrixMode(GL_MODELVIEW);
+
+
+  glEndList();
+
+}
+
 /* Initialization function for screen saver */
 static void
 pinit(ModeInfo * mi)
 {
   Bool wire = MI_IS_WIREFRAME(mi);
   planetstruct *gp = &planets[MI_SCREEN(mi)];
-  int i, j, list, dllist;
+  int i, j;
   int stacks=STACKS, slices=SLICES;
   float radius=RADIUS;
 
   float drho, dtheta;
   float rho, theta;
-  float vector[3];
-  float ds, dt, t, s;;
+  GLfloat vector[3];
+  GLfloat ds, dt, t, s;;
 
-  if (wire)
+  if (wire) {
+       glEnable(GL_LINE_SMOOTH);
        do_texture = False;
+  }
 
   /* turn on various options we like */
   if (do_texture)
        setup_texture(mi);
   if (do_light)
        setup_light();
-  if (do_stipple)
-       setup_stipple();
 
   setup_face();
 
-  dllist=glGenLists(NUM_PLATES);
+  if (do_stars) {
+       glEnable(GL_POINT_SMOOTH);
+       generate_stars(MI_WIDTH(mi), MI_HEIGHT(mi));
+  }
 
-  drho = M_PI / stacks;
-  dtheta = 2.0 * M_PI / slices;
-  ds = 1.0 / slices;
-  dt = 1.0 / stacks;
-  t = 0.0 ;
-  
 
   /*-
-   * Generate a huge sphere with quadrilaterals.
-   * Each quad is stored in its own display list; this is so we can
-   * move the quads around later (not yet done).
+   * Generate a sphere with quadrilaterals.
    * Quad vertices are determined using a parametric sphere function.
    * For fun, you could generate practically any parameteric surface and
    * map an image onto it. 
    */
 
-  list = 0;
+  drho = M_PI / stacks;
+  dtheta = 2.0 * M_PI / slices;
+  ds = 1.0 / slices;
+  dt = 1.0 / stacks;
+  
+
+  gp->platelist=glGenLists(1);
+  glNewList(gp->platelist, GL_COMPILE);
+
+  glColor3f(1,1,1);
+  glBegin( wire ? GL_LINE_LOOP : GL_QUADS );
+
+  t = 0.0;
   for(i=0; i<stacks; i++) {
        rho = i * drho;
        s = 0.0;
-       for(j=0; j<slices+1; j++) {
+       for(j=0; j<slices; j++) {
          theta = j * dtheta;
 
-         gp->plates[i].Translation[0] = 0.;
-         gp->plates[i].Translation[1] = 0.;
-         gp->plates[i].Translation[2] = 0.;
-
-         gp->plates[i].RotationRate = 0.;
-         gp->plates[i].Angle[0] = 0.;
-         gp->plates[i].Angle[1] = 0.;
-         gp->plates[i].Angle[2] = 0.;
-         gp->plates[i].Angle[3] = 0.;
-
-         gp->plates[i].Color[0] = 1.;
-         gp->plates[i].Color[1] = 1.;
-         gp->plates[i].Color[2] = 1.;
-
-         gp->plates[list].platelist = dllist+list;
-         glNewList(gp->plates[list].platelist, GL_COMPILE);
-         glBegin( wire ? GL_LINE_LOOP : GL_QUADS );
-
-         glColor3f(gp->plates[i].Color[0], gp->plates[i].Color[1], gp->plates[i].Color[2]);
 
          glTexCoord2f(s,t);
          ParametricSphere(theta, rho, vector);
+         normalize(vector);
          glNormal3fv(vector);
+         ParametricSphere(theta, rho, vector);
          glVertex3f( vector[0]*radius, vector[1]*radius, vector[2]*radius );
 
          glTexCoord2f(s,t+dt);
          ParametricSphere(theta, rho+drho, vector);
+         normalize(vector);
          glNormal3fv(vector);
+         ParametricSphere(theta, rho+drho, vector);
          glVertex3f( vector[0]*radius, vector[1]*radius, vector[2]*radius );
 
          glTexCoord2f(s+ds,t+dt);
          ParametricSphere(theta + dtheta, rho+drho, vector);
+         normalize(vector);
          glNormal3fv(vector);
+         ParametricSphere(theta + dtheta, rho+drho, vector);
          glVertex3f( vector[0]*radius, vector[1]*radius, vector[2]*radius );
 
          glTexCoord2f(s+ds, t);
          ParametricSphere(theta + dtheta, rho, vector);
+         normalize(vector);
          glNormal3fv(vector);
+         ParametricSphere(theta + dtheta, rho, vector);
          glVertex3f( vector[0]*radius, vector[1]*radius, vector[2]*radius );
 
-         glEnd();
          s = s + ds;
 
-         glEndList();
-
-         list++;
        }
        t = t + dt;
   }
+  glEnd();
+  glEndList();
 
 
  }
 
 static void
-draw(ModeInfo * mi)
+draw_sphere(ModeInfo * mi)
 {
-  int i;
   planetstruct *gp = &planets[MI_SCREEN(mi)];
 
-  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  glEnable(GL_DEPTH_TEST);
+
+  /* turn on the various attributes for making the sphere look nice */
+  if (do_texture)
+       glEnable(GL_TEXTURE_2D);
+
+  if (do_light)
+       {
+         glEnable(GL_LIGHTING);
+         glEnable(GL_LIGHT0);
+         glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
+         glEnable(GL_COLOR_MATERIAL);
+       }
+
+  glCallList(gp->platelist);
 
-  for (i=0; i < NUM_PLATES; i++) {
-       glPushMatrix();
-       /* currently, the angle and translation are 0, but later this can
-        * help us move the surface around */
-#if 0
-       glRotatef(gp->plates[i].Angle[0],
-                         gp->plates[i].Angle[1],
-                         gp->plates[i].Angle[2],
-                         gp->plates[i].Angle[3]); 
-       glTranslatef(gp->plates[i].Translation[0],
-                                gp->plates[i].Translation[1],
-                                gp->plates[i].Translation[2]);
-#endif
-       glCallList(gp->plates[i].platelist);
-       glPopMatrix();
-#if 0
-       gp->plates[i].Angle[0] += gp->plates[i].RotationRate;
-#endif
-  }
 }
 
 
@@ -567,7 +573,7 @@ pick_velocity (ModeInfo * mi)
 
   gp->box_width =  15.0;
   gp->box_height = 15.0;
-  gp->box_depth =  60.0;
+  gp->box_depth =  5.0;
 
   gp->tx = 0.0;
   gp->ty = 0.0;
@@ -633,7 +639,6 @@ rotate_and_move (ModeInfo * mi)
 
 
 /* Standard reshape function */
-#define DIST 40
 static void
 reshape(int width, int height)
 {
@@ -652,9 +657,6 @@ reshape(int width, int height)
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   glTranslatef(0.0, 0.0, -DIST);
-  /* some messiness for orienting the earth normally */
-  glRotatef(90,0,0,1);
-  glRotatef(90,0,1,0);
   glLightfv(GL_LIGHT0, GL_POSITION, light);
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
@@ -727,18 +729,44 @@ draw_planet(ModeInfo * mi)
        return;
 
   glDrawBuffer(GL_BACK);
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
   glXMakeCurrent(display, window, *(gp->glx_context));
 
+
+  if (do_stars) {
+       /* protect our modelview matrix and attributes */
+       glPushMatrix();
+       glPushAttrib(GL_ALL_ATTRIB_BITS);
+       {
+         glColor3f(1,1,1);
+         /* draw the star field. */
+         glCallList(gp->starlist);
+
+       }
+       glPopMatrix();
+       glPopAttrib();
+  }
+
+  /* protect our modelview matrix and attributes */
   glPushMatrix();
+  glPushAttrib(GL_ALL_ATTRIB_BITS);
   {
+       /* this pair of rotations seem to be necessary to orient the earth correctly */
+       glRotatef(90,0,0,1);
+       glRotatef(90,0,1,0);
+
        glTranslatef(gp->xpos, gp->ypos, gp->zpos);
        glRotatef(gp->tx, 1, 0, 0);
        glRotatef(gp->ty, 0, 1, 0);
        glRotatef(gp->tz, 0, 0, 1);
-       draw(mi);
+       /* draw the sphere */
+       draw_sphere(mi);
   }
   glPopMatrix();
+  glPopAttrib();
+
+
 
   glFinish();
   glXSwapBuffers(display, window);
@@ -749,7 +777,6 @@ draw_planet(ModeInfo * mi)
 void
 release_planet(ModeInfo * mi)
 {
-  int i;
   if (planets != NULL) {
        int         screen;
 
@@ -760,10 +787,10 @@ release_planet(ModeInfo * mi)
                /* Display lists MUST be freed while their glXContext is current. */
                glXMakeCurrent(MI_DISPLAY(mi), gp->window, *(gp->glx_context));
 
-               for (i=0; i < NUM_PLATES; i++) {
-                 if (glIsList(gp->plates[i].platelist))
-                       glDeleteLists(gp->plates[i].platelist, 1);
-               }
+               if (glIsList(gp->platelist))
+                 glDeleteLists(gp->platelist, 1);
+               if (glIsList(gp->starlist))
+                 glDeleteLists(gp->starlist, 1);
          }
        }
        (void) free((void *) planets);
index 8a2360958900f81b257f6518e750c5bafd28f3ac..d79376dde97ecca177abf0bd3fb36be50bcb4d71 100644 (file)
@@ -565,7 +565,7 @@ star(ModeInfo *mi, Bool top, Bool wire)
 #endif /* HAVE_GLBINDTEXTURE */
   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, interior_color);
 
-  i = countof(points) - 3;
+  i = countof(points) - 9;
   do_normal(points[i+0][0], points[i+0][1], 0,
            points[i+4][0], points[i+4][1], 0,
            points[i+8][0], points[i+8][1], 0);
index 6ac712f0851f7fcdda1a72233b96a39c4e0e8404..44f64dbf3d97ae2425e03d11ce326fdc9a642045 100644 (file)
@@ -63,6 +63,8 @@ xpm_to_ximage (Display *dpy, Visual *visual, Colormap cmap, char **xpm_data)
   int bpl, wpl;
   XColor colors[255];
 
+  memset (&xpm_image, 0, sizeof(xpm_image));
+  memset (&xpm_info, 0, sizeof(xpm_info));
   result = XpmCreateXpmImageFromData (xpm_data, &xpm_image, &xpm_info);
   if (result != XpmSuccess)
     {
index 233708e6913fc714ae1d0845792d42a3198a47bb..ef0e8e667b7f5dde44ba1905aa877a80bbcffff8 100644 (file)
@@ -528,7 +528,8 @@ screenhack (Display *dpy, Window window)
   while (1)
     {
       run_goop (dpy, window, g);
-      XSync (dpy, True);
+      XSync (dpy, False);
+      screenhack_handle_events (dpy);
       if (delay) usleep (delay);
     }
 }
index b2ddec4c0593764330629609035ae0cf70004035..1377c95d61e5793022d2bf6c3fbb673ce54c8756 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1997
+/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1997, 1998
  *  Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -152,7 +152,7 @@ greynetic (Display *dpy, Window window)
     }
   XChangeGC (dpy, gc, GCStipple|GCForeground|GCBackground, &gcv);
   XFillRectangle (dpy, window, gc, x, y, w, h);
-  XSync (dpy, True);
+  XSync (dpy, False);
 }
 
 \f
@@ -177,6 +177,7 @@ screenhack (Display *dpy, Window window)
   while (1)
     {
       greynetic (dpy, window);
+      screenhack_handle_events (dpy);
       if (delay) usleep (delay);
     }
 }
index 474f0bc67962fede585b0fd22ae39359e17d01d5..7e8da8a2b2eead3e65baaa1045d9585eb22b7688 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1993, 1995, 1996, 1997
+/* xscreensaver, Copyright (c) 1993, 1995, 1996, 1997, 1998
  *  Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -365,7 +365,7 @@ run_circles (Display *dpy, Window window)
                 : (iterations & 1)))
     {
       XCopyPlane (dpy, buffer, window, copy_gc, 0, 0, width, height, 0, 0, 1);
-      XSync (dpy, True);
+      XSync (dpy, False);
       if (anim_p && done)
        XFillRectangle (dpy, buffer, erase_gc, 0, 0, width, height);
     }
@@ -374,7 +374,7 @@ run_circles (Display *dpy, Window window)
   XCopyPlane (dpy, pixmap, window, copy_gc, 0,0,width,height,width,height, 1);
   if (buffer)
     XCopyPlane (dpy, buffer, window, copy_gc, 0,0,width,height,0,height, 1);
-  XSync (dpy, True);
+  XSync (dpy, False);
 #endif
 
   if (done)
@@ -446,5 +446,8 @@ screenhack (Display *dpy, Window window)
 {
   init_circles (dpy, window);
   while (1)
-    run_circles (dpy, window);
+    {
+      run_circles (dpy, window);
+      screenhack_handle_events (dpy);
+    }
 }
index c2d81fa22dfd6785931160d3c8e03ed688e12135..27c9d43763b13fde1f26929949c82ebaffa89589 100644 (file)
@@ -268,13 +268,16 @@ random_helix_or_trig (Display *dpy, Window window)
   else
     random_trig(dpy, window, &color, &free_color);
 
-  XSync (dpy, True);
+  XSync (dpy, False);
+  screenhack_handle_events (dpy);
   sleep ( sleep_time );
 
+  screenhack_handle_events (dpy);
   erase_full_window(dpy, window);
 
   if (free_color) XFreeColors (dpy, cmap, &color.pixel, 1, 0);
-  XSync (dpy, True);
+  XSync (dpy, False);
+  screenhack_handle_events (dpy);
   sleep (1);
 }
 
index 560f1306df32699c6fac0fdd0bacfdc77a57515a..5150ec3bdfbc130e49f6bf6ae4c66ba03ffc85cd 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992, 1995, 1996
+/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1998
  *  Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -210,7 +210,8 @@ hyper (double xy, double xz, double yz, double xw, double yw, double zw)
       rotates (y,w);
       rotates (z,w);
 
-      XSync (dpy, True);
+      XSync (dpy, False);
+      screenhack_handle_events (dpy);
       if (delay) usleep (delay);
     }
 }
index fa861ac0be1f4177c43e762fbf5a7a5cedd58ca7..15cb66ae9eea9d69df270f6f5ec2c7f582a94650 100644 (file)
@@ -439,14 +439,15 @@ draw_map (Display *dpy, Window window)
       xstep = xnextStep;
       ystep = ynextStep;
       if (!mono_p)
-       XSync (dpy, True);
+       XSync (dpy, False);
+      screenhack_handle_events (dpy);
     }
   if (mono_p)
     /* in mono-mode, we do all the drawing at the end */
     floyd_steinberg (dpy, window);
   
   free (cell);
-  XSync (dpy, True);
+  XSync (dpy, False);
 }
 
 
@@ -493,10 +494,14 @@ screenhack (Display *dpy, Window window)
                    rotate_colors (dpy, cmap, colors, ncolors,
                                   cycle_direction);
                    if (cycle_delay) usleep(cycle_delay);
+                    screenhack_handle_events (dpy);
                  }
              }
            else
-             sleep (delay);
+              {
+                screenhack_handle_events (dpy);
+                sleep (delay);
+              }
          }
       }
 }
index d877a01b1cd44c8804f4182dab33814a4b5b40ab..d856f30eb5213945c4bee39cb9aac8f168315f8c 100644 (file)
@@ -450,7 +450,7 @@ void screenhack(Display *dpy, Window win)
   inter_init(dpy, win, &c);
   while(1) {
     do_inter(&c); 
-    if(delay) 
-      usleep(delay);
+    screenhack_handle_events (dpy);
+    if(delay) usleep(delay);
   }
 }
index 83dcbe922f3e95cf2922d0ea2445872130a78f3e..246c9da77402f70df1b9a94b8b47705a36f77c8d 100644 (file)
@@ -567,10 +567,12 @@ screenhack (Display *dpy, Window window)
       while (!done())
        {
          unshuffle(dpy, window);
-         XSync (dpy, True);
+         XSync (dpy, False);
+          screenhack_handle_events (dpy);
          if (delay) usleep (delay);
        }
 
+      screenhack_handle_events (dpy);
       if (delay2)
        usleep (delay2 * 1000000);
 
index 78890147c097c1e17388177a0ccc584fda9e7da6..6e66fdd837a0e08c6de6959b505e7611dac25a24 100644 (file)
@@ -444,9 +444,10 @@ screenhack (Display *dpy, Window window)
   while (1)
     {
      draw_objects ();
-     XSync (dpy, True);
+     XSync (dpy, False);
      if(g.delay) {
-       screenhack_usleep(g.delay);
+       screenhack_handle_events (dpy);
+       usleep(g.delay);
      }
      propogate_objects(); 
    }
index 640a856ebb88ab0d64d5a1eb4dcbaa9640169263..bcc137af3d10110c6923a3f50495b84df6dd73e6 100644 (file)
@@ -529,7 +529,8 @@ while (0==0)
 #ifdef HAVE_XDBE_EXTENSION
        if (usedouble) XdbeSwapBuffers(dpy,&xdswp,1);
 #endif /* HAVE_XDBE_EXTENSION */
-       XSync(dpy,True);
+       XSync(dpy, False);
+        screenhack_handle_events (dpy);
        if (delay) usleep (delay);
        }
 }
index f372c1eeff7c8463bda4cda0fe5c826c0c9fa7aa..11099d26bcb58ced25ff3b344f8f44ba9705ae95 100644 (file)
@@ -507,6 +507,7 @@ screenhack(Display *disp, Window win)
     initLMorph();
     for (;;) {
        animateLMorph();
-       screenhack_usleep(delay);
+        screenhack_handle_events (dpy);
+       usleep(delay);
     }
 }
index 7690555d2249f17439912edbb9b40be327325250..40edf41b58bf9e8dfdc310585680c9b963d037a2 100644 (file)
@@ -201,6 +201,9 @@ check_events (void)                        /* X event handler [ rhess ] */
     case Expose:
       restart = 1;
       break;
+    default:
+      screenhack_handle_event(dpy, &e);
+      break;
     }
     return(1);
   }
@@ -1367,7 +1370,7 @@ find_dead_regions(void)
          }
        }
       }
-    XSync(dpy, 0);
+    XSync(dpy, False);
 }
 
 static void
@@ -1612,7 +1615,13 @@ screenhack(Display *display, Window window)
   set_maze_sizes (xgwa.width, xgwa.height);
 
   if (! root)
-    XSelectInput (dpy, win, ExposureMask|ButtonPressMask|StructureNotifyMask);
+    {
+      XWindowAttributes xgwa;
+      XGetWindowAttributes (dpy, window, &xgwa);
+      XSelectInput (dpy, win,
+                    xgwa.your_event_mask | ExposureMask |
+                    ButtonPressMask |StructureNotifyMask);
+    }
   
   gc  = XCreateGC(dpy, win, 0, 0);
   cgc = XCreateGC(dpy, win, 0, 0);
index f01fa28fe4e7e3bf9a73da888e83aded87684334..9b95c6b943e92bfb608da884d37e3aa16f741b78 100644 (file)
@@ -230,7 +230,8 @@ screenhack (Display *dpy, Window window)
     {
       init_moire (dpy, window);
       moire (dpy, window, offset, colors, ncolors);
-      XSync (dpy, True);
+      XSync (dpy, False);
+      screenhack_handle_events (dpy);
       if (delay)
        sleep(delay);
     }
index e714b5e085b879323561c05dc49ef1ea53719f39..96bfd9ac0e4a1c87b8801f8144c9c5f87d9085c1 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1997 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1997, 1998 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
@@ -270,6 +270,7 @@ screenhack (Display *dpy, Window window)
          for (i = 0; i < color_shift; i++)
            {
              moire2 (dpy, window);
+              screenhack_handle_events (dpy);
              if (delay)
                usleep(delay);
            }
index 84ff9608e332359332a29cb51590cc00503ebaa9..b3cd73517d2c477dc638eb727a72a7bdd1586476 100644 (file)
@@ -133,6 +133,7 @@ static void munchOnce (Display* dpy, Window w,
           same time (one for each value of x, surprisingly enough)
           */
        XSync(dpy, False);
+        screenhack_handle_events (dpy);
        if (delay) usleep(delay);
     }
 }
@@ -246,6 +247,7 @@ screenhack (dpy, w) Display *dpy; Window w;
                  (randflags & GRAV)
                  );
        
+        screenhack_handle_events (dpy);
        if (hold) usleep(hold);
        
        if (clear && ++n >= clear) {
index 0afb52c85d58d8ec531d5535540bd8c068eb181b..9ea9f4e54204247a6b4c8ce8475b46c0283e802c 100644 (file)
@@ -713,7 +713,8 @@ screenhack (Display *d, Window w)
   while (1)
     {
       next_fn();
-      XSync (dpy, True);
+      XSync (dpy, False);
+      screenhack_handle_events (dpy);
       usleep (interval * 1000);
     }
 }
index 4306f8a2a2395270e1767cb35542112d7e9ee818..7f8e5bd6c8470d52a08e8da3b6010cd5afea989b 100644 (file)
@@ -276,7 +276,8 @@ fade_foreground (Display *dpy, Colormap cmap,
       inbetween.blue  = from.blue  + (to.blue  - from.blue)  * i / steps ;
       XStoreColor (dpy, cmap, &inbetween);
       /* If we don't sync, these can bunch up */
-      XSync(dpy, 0);
+      XSync(dpy, False);
+      screenhack_handle_events (dpy);
       usleep(udelay);
     }
 }
@@ -317,7 +318,7 @@ pedal (Display *dpy, Window window)
        XColor color;
        hsv_to_rgb (random()%360, 1.0, 1.0,
                   &color.red, &color.green, &color.blue);
-       XSync(dpy, 0);
+       XSync(dpy, False);
        if (fade_p)
         {
           foreground.red = color.red;
@@ -335,7 +336,7 @@ pedal (Display *dpy, Window window)
           foreground.blue = color.blue;
           foreground.pixel = color.pixel;
         }
-       XSync(dpy, 0);
+       XSync(dpy, False);
      }
 
     /* Fade in by bringing the foreground back from background */
@@ -374,7 +375,8 @@ screenhack (Display *dpy, Window window)
     init_pedal (dpy, window);
     for (;;) {
        pedal (dpy, window);
-       XSync(dpy, 0);
+       XSync(dpy, False);
+        screenhack_handle_events (dpy);
        if (delay) sleep (delay);
     }
 }
index 05c12763b23c626e696778001bd5b58f2df733da..ddace3910fbeb3b942a2d5a321e4a4f472bb84af 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992, 1994, 1996
+/* xscreensaver, Copyright (c) 1992, 1994, 1996, 1998
  *  Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -164,7 +164,8 @@ pyro (Display *dpy, Window window, Colormap cmap)
       launch (xlim, ylim, g, dpy, cmap);
     }
 
-  XSync (dpy, True);
+  XSync (dpy, False);
+  screenhack_handle_events (dpy);
   usleep (10000);
 
   for (i = 0; i < how_many; i++)
index c19f3bc6a33f9cd5e4f5f40438188739fefef91b..924b5422595c810d907477673f5c7fb58e1c3dca 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1997
+/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1997, 1998
  *  Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -504,7 +504,8 @@ screenhack (Display *dpy, Window window)
     for (qn = q1; *qn; qn++)
       {
        qix1 (dpy, window, *qn);
-       XSync (dpy, True);
+       XSync (dpy, False);
+        screenhack_handle_events (dpy);
        if (delay) usleep (delay);
       }
 }
index 990abcf89dbd7121421f0a20bed5360dd83a069e..a537eadc6b49168ea367d294326cb61452460f61 100644 (file)
@@ -541,6 +541,7 @@ screenhack (Display *dpy, Window win)
     frame++;
 
     XSync(dpy, False);
+    screenhack_handle_events (dpy);
     if (delay > 0)
       usleep(1000 * delay);
   }
index aceef3bcf8073fe2b30981bbad08a16527777f7a..e5e0df5beaa78e8738d2fda0cfb264d6f62e509f 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1997
+/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1997, 1998
  *  Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -527,7 +527,8 @@ screenhack (Display *dpy, Window window)
   while (1)
     {
       rocks_once ();
-      XSync (dpy, True);
+      XSync (dpy, False);
+      screenhack_handle_events (dpy);
       if (delay) usleep (delay);
     }
 }
index 3c1a20e5fe9a9a59af3fdff586c336cfccf95082..430fa9dfb3373464428651dd90fd56ddef1da39e 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992, 1996 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1992, 1996, 1998 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
@@ -92,7 +92,8 @@ hurm (Display *dpy, Window window)
          j++;
        }
       XDrawPoints (dpy, window, draw_gc, points, j, CoordModeOrigin);
-      XSync (dpy, True);
+      XSync (dpy, False);
+      screenhack_handle_events (dpy);
     }
   sleep ( sleep_time );
 
@@ -100,7 +101,8 @@ hurm (Display *dpy, Window window)
 
   XClearWindow (dpy, window);
   if (got_color) XFreeColors (dpy, cmap, &color.pixel, 1, 0);
-  XSync (dpy, True);
+  XSync (dpy, False);
+  screenhack_handle_events (dpy);
   sleep (1);
 }
 
index 4d169939018de416fe59c05513d15aaab4b5ea1c..0e1c678e1039dc5451afec54ab5eca1ec7d14140 100644 (file)
@@ -37,6 +37,7 @@
 #include <X11/CoreP.h>
 #include <X11/Shell.h>
 #include <X11/StringDefs.h>
+#include <X11/Xutil.h>
 
 #ifdef __sgi
 # include <X11/SGIScheme.h>    /* for SgiUseSchemes() */
@@ -167,6 +168,70 @@ extern void pre_merge_options (void);
 #endif
 
 
+static Atom XA_WM_PROTOCOLS, XA_WM_DELETE_WINDOW;
+
+/* Dead-trivial event handling: exits if "q" or "ESC" are typed.
+   Exit if the WM_PROTOCOLS WM_DELETE_WINDOW ClientMessage is received.
+ */
+void
+screenhack_handle_event (Display *dpy, XEvent *event)
+{
+  switch (event->xany.type)
+    {
+    case KeyPress:
+      {
+        KeySym keysym;
+        char c = 0;
+        XLookupString (&event->xkey, &c, 1, &keysym, 0);
+        if (c == 'q' ||
+            c == 'Q' ||
+            c == 3 ||  /* ^C */
+            c == 27)   /* ESC */
+          exit (0);
+      }
+    case ButtonPress:
+      XBell (dpy, 0);
+      break;
+    case ClientMessage:
+      {
+        if (event->xclient.message_type != XA_WM_PROTOCOLS)
+          {
+            char *s = XGetAtomName(dpy, event->xclient.message_type);
+            if (!s) s = "(null)";
+            fprintf (stderr, "%s: unknown ClientMessage %s received!\n",
+                     progname, s);
+          }
+        else if (event->xclient.data.l[0] != XA_WM_DELETE_WINDOW)
+          {
+            char *s1 = XGetAtomName(dpy, event->xclient.message_type);
+            char *s2 = XGetAtomName(dpy, event->xclient.data.l[0]);
+            if (!s1) s1 = "(null)";
+            if (!s2) s2 = "(null)";
+            fprintf (stderr, "%s: unknown ClientMessage %s[%s] received!\n",
+                     progname, s1, s2);
+          }
+        else
+          {
+            exit (0);
+          }
+      }
+      break;
+    }
+}
+
+
+void
+screenhack_handle_events (Display *dpy)
+{
+  while (XPending (dpy))
+    {
+      XEvent event;
+      XNextEvent (dpy, &event);
+      screenhack_handle_event (dpy, &event);
+    }
+}
+
+
 
 int
 main (int argc, char **argv)
@@ -208,12 +273,20 @@ main (int argc, char **argv)
   XtGetApplicationNameAndClass (dpy, &progname, &progclass);
   XSetErrorHandler (screenhack_ehandler);
 
+  XA_WM_PROTOCOLS = XInternAtom (dpy, "WM_PROTOCOLS", False);
+  XA_WM_DELETE_WINDOW = XInternAtom (dpy, "WM_DELETE_WINDOW", False);
+
   {
     char *v = (char *) strdup(strchr(screensaver_id, ' '));
-    char *s = (char *) strchr(v, ',');
-    *s = 0;
-    sprintf (version, "%s: from the XScreenSaver%s distribution.",
-            progclass, v);
+    char *s1, *s2, *s3, *s4;
+    s1 = (char *) strchr(v,  ' '); s1++;
+    s2 = (char *) strchr(s1, ' ');
+    s3 = (char *) strchr(v,  '('); s3++;
+    s4 = (char *) strchr(s3, ')');
+    *s2 = 0;
+    *s4 = 0;
+    sprintf (version, "%s: from the XScreenSaver %s distribution (%s.)",
+            progclass, s1, s3);
     free(v);
   }
 
@@ -359,6 +432,18 @@ main (int argc, char **argv)
        }
 
       XtVaSetValues(toplevel, XtNtitle, version, 0);
+
+      /* For screenhack_handle_events(): select KeyPress, and
+         announce that we accept WM_DELETE_WINDOW. */
+      {
+        XWindowAttributes xgwa;
+        XGetWindowAttributes (dpy, window, &xgwa);
+        XSelectInput (dpy, window,
+                      xgwa.your_event_mask | KeyPressMask | ButtonPressMask);
+        XChangeProperty (dpy, window, XA_WM_PROTOCOLS, XA_ATOM, 32,
+                         PropModeReplace,
+                         (unsigned char *) &XA_WM_DELETE_WINDOW, 1);
+      }
     }
 
   if (!dont_clear)
index bb0344fb7543ec30f007ffef34168f53c20331eb..63222520c25bfa7ae193c7ec7b3db78d38e00a73 100644 (file)
@@ -94,5 +94,7 @@ extern XrmOptionDescRec options [];
 extern char *defaults [];
 
 extern void screenhack (Display*,Window);
+extern void screenhack_handle_event (Display*, XEvent*);
+extern void screenhack_handle_events (Display*);
 
 #endif /* __SCREENHACK_H__ */
index 9415ac22049aaccd5842e29d0b1784558e8aee97..c2fc03324b2900ac3e11113018ceb80737587f4e 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992, 1993, 1994, 1996, 1997 
+/* xscreensaver, Copyright (c) 1992, 1993, 1994, 1996, 1997, 1998 
  * Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -197,7 +197,7 @@ init_slide (Display *dpy, Window window)
       XFillRectangle (dpy, d, gc, 0, bitmap_h - yoff, bitmap_w, yoff);
     }
 
-  XSync (dpy, True);
+  XSync (dpy, False);
   if (delay2) usleep (delay2 * 2);
  for (i = 0; i < grid_size; i += pix_inc)
    {
@@ -228,7 +228,7 @@ init_slide (Display *dpy, Window window)
      points[2].y = points[1].y;
      XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
 
-     XSync (dpy, True);
+     XSync (dpy, False);
      if (delay) usleep (delay);
    }
 
@@ -309,7 +309,7 @@ slide1 (Display *dpy, Window window)
         break;
        }
 
-     XSync (dpy, True);
+     XSync (dpy, False);
      if (delay) usleep (delay);
    }
  switch (dir)
@@ -357,6 +357,7 @@ screenhack (Display *dpy, Window window)
   while (1)
     {
       slide1 (dpy, window);
+      screenhack_handle_events (dpy);
       if (delay2) usleep (delay2);
     }
 }
diff --git a/hacks/sonar.c b/hacks/sonar.c
new file mode 100644 (file)
index 0000000..3c49218
--- /dev/null
@@ -0,0 +1,1687 @@
+/* sonar.c --- Simulate a sonar screen.
+ *
+ * This is an implementation of a general purpose reporting tool in the
+ * format of a Sonar display. It is designed such that a sensor is read
+ * on every movement of a sweep arm and the results of that sensor are
+ * displayed on the screen. The location of the display points (targets) on the
+ * screen are determined by the current localtion of the sweep and a distance
+ * value associated with the target. 
+ *
+ * Currently the only two sensors that are implemented are the simulator
+ * (the default) and the ping sensor. The simulator randomly creates a set
+ * of bogies that move around on the scope while the ping sensor can be
+ * used to display hosts on your network.
+ *
+ * The ping code is only compiled in if you define HAVE_PING, because, 
+ * unfortunately, creating an ICMP socket is a privileged operation, the
+ * program needs to be installed SUID root if you want to use the ping
+ * mode. If you check the code you will see that this privilige is given up
+ * immediately after the socket is created.
+ *
+ * It should be easy to extend this code to support other sorts of sensors.
+ * Some ideas:
+ *   - search the output of "netstat" for the list of hosts to ping;
+ *   - plot the contents of /proc/interrupts;
+ *   - plot the process table, by process size, cpu usage, or total time;
+ *   - plot the logged on users by idle time or cpu usage.
+ *
+ * Copyright (C) 1998 by Stephen Martin (smartin@canada.com).
+ * 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.
+ *
+ * $Revision: 1.6 $
+ *
+ * Version 1.0 April 27, 1998.
+ * - Initial version
+ * - Submitted to RedHat Screensaver Contest
+ * 
+ * Version 1.1 November 3, 1998.
+ * - Added simulation mode.
+ * - Added enhancements by Thomas Bahls <thommy@cs.tu-berlin.de>
+ * - Fixed huge memory leak.
+ * - Submitted to xscreensavers
+ * 
+ * Version 1.2
+ * - All ping code is now ifdef-ed by the compile time symbol HAVE_PING;
+ *   use -DHAVE_PING to include it when you compile.
+ * - Sweep now uses gradients.
+ * - Fixed portability problems with icmphdr on some systems.
+ * - removed lowColor option/resource.
+ * - changed copyright notice so that it could be included in the xscreensavers
+ *   collection.
+ *
+ * Version 1.3 November 16, 1998.
+ * - All ping code is now ifdef-ed by the compile time symbol PING use -DPING
+ *   to include it when you compile.
+ * - Sweep now uses gradients.
+ * - Fixed portability problems with icmphdr on some systems.
+ * - removed lowcolour option/resource.
+ * - changed copyright notice so that it could be included in the xscreensavers
+ *   collection.
+ *
+ * Version 1.4 November 18, 1998.
+ * - More ping portability fixes.
+ *
+ * Version 1.5 November 19, 1998.
+ * - Synced up with jwz's changes.
+ * - Now need to define HAVE_PING to compile in the ping stuff.
+ */
+
+/* Include Files */
+
+#ifdef HAVE_PING
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/udp.h>
+#include <arpa/inet.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <signal.h>
+#include <limits.h>
+#endif /* HAVE_PING */
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "screenhack.h"
+#include "colors.h"
+#include "hsv.h"
+#include <X11/extensions/XShm.h>
+
+/* Defines */
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a - 50):(b - 10))
+#endif /* MIN */
+
+/* Forward References */
+
+#ifdef HAVE_PING
+static u_short checksum(u_short *, int);
+#endif
+static long delta(struct timeval *, struct timeval *);
+
+/* Data Structures */
+
+/*
+ * The Bogie.
+ *
+ * This represents an object that is visable on the scope.
+ */
+
+typedef struct Bogie {
+    char *name;                        /* The name of the thing being displayed */
+    int distance;              /* The distance to this thing (0 - 100) */
+    int tick;                  /* The tick that it was found on */
+    int ttl;                   /* The time to live */
+    int age;                    /* How long it's been around */
+    struct Bogie *next;                /* The next one in the list */
+} Bogie;
+
+/*
+ * Sonar Information.
+ *
+ * This contains all of the runtime information about the sonar scope.
+ */
+
+typedef struct {
+    Display *dpy;              /* The X display */
+    Window win;                        /* The window */
+    GC hi,                     /* The leading edge of the sweep */
+       lo,                     /* The trailing part of the sweep */
+       erase,                  /* Used to erase things */
+       grid,                   /* Used to draw the grid */
+       text;                   /* Used to draw text */
+    Colormap cmap;             /* The colormap */
+    XFontStruct *font;          /* The font to use for the labels */
+    int text_steps;            /* How many steps to fade text. */
+    XColor *text_colors;       /* Pixel values used to fade text */
+    int sweep_degrees;         /* How much of the circle the sweep uses */
+    int sweep_segs;            /* How many gradients in the sweep. */
+    XColor *sweep_colors;        /* The sweep pixel values */
+    int width, height;         /* Window dimensions */
+    int minx, miny, maxx, maxy, /* Bounds of the scope */
+       centrex, centrey, radius; /* Parts of the scope circle */
+    Bogie *visable;            /* List of visable objects */
+    int current;               /* Current position of sweep */
+
+    int delay;                 /* how long between each frame of the anim */
+
+} sonar_info;
+
+/* 
+ * Variables to support the differnt Sonar modes.
+ */
+
+Bogie *(*sensor)(sonar_info *, void *);        /* The current sensor */
+void *sensor_info;                     /* Information about the sensor */
+
+/*
+ * A list of targets to ping.
+ */
+
+#ifdef HAVE_PING
+typedef struct ping_target {
+    char *name;                        /* The name of the target */
+    struct sockaddr address;   /* The address of the target */
+    struct ping_target *next;  /* The next one in the list */
+} ping_target;
+
+/*
+ * Ping Information.
+ *
+ * This contains the information for the ping sensor.
+ */
+
+typedef struct {
+    int icmpsock;              /* Socket for sending pings */
+    int pid;                   /* Our process ID */
+    int seq;                   /* Packet sequence number */
+    int timeout;               /* Timeout value for pings */
+    ping_target *targets;      /* List of targets to ping */
+    int numtargets;             /* The number of targets to ping */
+} ping_info;
+
+/* Flag to indicate that the timer has expired on us */
+
+static int timer_expired;
+
+
+#endif /* HAVE_PING */
+
+/*
+ * A list of targets for the simulator
+ */
+
+typedef struct sim_target {
+    char *name;                        /* The name of the target */
+    int nexttick;              /* The next tick that this will be seen */
+    int nextdist;              /* The distance on that tick */
+    int movedlasttick;         /* Flag to indicate we just moved this one */
+} sim_target;
+
+/*
+ * Simulator Information.
+ *
+ * This contains the information for the simulator mode.
+ */
+
+typedef struct {
+    sim_target *teamA;         /* The bogies for the A team */
+    int numA;                  /* The number of bogies in team A */
+    char *teamAID;             /* The identifier for bogies in team A */
+    sim_target *teamB;         /* The bogies for the B team */
+    int numB;                  /* The number of bogies in team B */
+    char *teamBID;             /* The identifier for bogies in team B */
+} sim_info;
+
+/* Name of the Screensaver hack */
+
+char *progclass="sonar";
+
+/* Application Defaults */
+
+char *defaults [] = {
+    ".background:      #000000",
+    ".sweepColor:      #00FF00",
+    "*delay:          100000",
+    "*scopeColor:      #003300",
+    "*gridColor:       #00AA00",
+    "*textColor:       #FFFF00",
+    "*ttl:             90",
+    "*mode:            default",
+    "*font:            fixed",
+    "*sweepDegrees:    30",
+
+    "*textSteps:       80",    /* npixels */
+    "*sweepSegments:   80",    /* npixels */
+
+#ifdef HAVE_PING
+    "*pingTimeout:     3000",
+    "*pingSource:      file",
+    "*pingFile:        /etc/hosts",
+    "*pingList:        localhost",
+#endif /* HAVE_PING */
+    "*teamAName:       F18",
+    "*teamBName:       MIG",
+    "*teamACount:      4",
+    "*teamBCount:      4",
+    0
+};
+
+/* Options passed to this program */
+
+XrmOptionDescRec options [] = {
+    {"-background",   ".background",   XrmoptionSepArg, 0 },
+    {"-sweep-color",  ".sweepColor",   XrmoptionSepArg, 0 },
+    {"-scope-color",  ".scopeColor",   XrmoptionSepArg, 0 },
+    {"-grid-color",   ".gridColor",    XrmoptionSepArg, 0 },
+    {"-text-color",   ".textColor",    XrmoptionSepArg, 0 },
+    {"-ttl",          ".ttl",          XrmoptionSepArg, 0 },
+    {"-mode",         ".mode",         XrmoptionSepArg, 0 },
+    {"-font",         ".font",         XrmoptionSepArg, 0 },
+#ifdef HAVE_PING
+    {"-ping-timeout", ".pingTimeout",  XrmoptionSepArg, 0 },
+    {"-ping-source",  ".pingSource",   XrmoptionSepArg, 0 },
+    {"-ping-file",    ".pingFile",     XrmoptionSepArg, 0 },
+    {"-ping-list",    ".pingList",     XrmoptionSepArg, 0 },
+#endif /* HAVE_PING */
+    {"-team-a-name",   ".teamAName",   XrmoptionSepArg, 0 },
+    {"-team-b-name",   ".teamBName",   XrmoptionSepArg, 0 },
+    {"-team-a-count",  ".teamACount",  XrmoptionSepArg, 0 },
+    {"-team-b-count",  ".teamBCount",  XrmoptionSepArg, 0 },
+    { 0, 0, 0, 0 }
+};
+
+/*
+ * The number of ticks that bogies are visable on the screen before they
+ * fade away.
+ */
+
+static int TTL;
+
+/*
+ * Create a new Bogie and set some initial values.
+ *
+ * Args:
+ *    name     - The name of the bogie.
+ *    distance - The distance value.
+ *    tick     - The tick value.
+ *    ttl      - The time to live value.
+ *
+ * Returns:
+ *    The newly allocated bogie or null if a memory problem occured.
+ */
+
+static Bogie *
+newBogie(char *name, int distance, int tick, int ttl) 
+{
+
+    /* Local Variables */
+
+    Bogie *new;
+
+    /* Allocate a bogie and initialize it */
+
+    if ((new = (Bogie *) calloc(1, sizeof(Bogie))) == NULL) {
+       fprintf(stderr, "Out of Memory\n");
+       return NULL;
+    }
+    new->name = name;
+    new->distance = distance;
+    new->tick = tick;
+    new->ttl = ttl;
+    new->age = 0;
+    new->next = (Bogie *) 0;
+    return new;
+}
+
+/*
+ * Free a Bogie.
+ *
+ * Args:
+ *    b - The bogie to free.
+ */
+
+static void
+freeBogie(Bogie *b) 
+{
+    if (b->name != (char *) 0)
+       free(b->name);
+    free(b);
+}
+
+/*
+ * Find a bogie by name in a list.
+ *
+ * This does a simple linear search of the list for a given name.
+ *
+ * Args:
+ *    bl   - The Bogie list to search.
+ *    name - The name to look for.
+ *
+ * Returns:
+ *    The requested Bogie or null if it wasn't found.
+ */
+
+static Bogie *
+findNode(Bogie *bl, char *name) 
+{
+
+    /* Local Variables */
+
+    Bogie *p;
+
+    /* Abort if the list is empty or no name is given */
+
+    if ((name == NULL) || (bl == NULL))
+       return NULL;
+
+    /* Search the list for the desired name */
+
+    p = bl;
+    while (p != NULL) {
+       if (strcmp(p->name, name) == 0)
+           return p;
+       p = p->next;
+    }
+
+    /* Not found */
+
+    return NULL;
+}
+
+#ifdef HAVE_PING
+
+/*
+ * Lookup the address for a ping target;
+ *
+ * Args:
+ *    target - The ping_target fill in the address for.
+ *
+ * Returns:
+ *    1 if the host was successfully resolved, 0 otherwise.
+ */
+
+static int
+lookupHost(ping_target *target) 
+{
+
+    /* Local Variables */
+
+    struct sockaddr_in *iaddr;
+
+    /* Set up the target address we first assume that the name is the
+       IP address as a string */
+
+    iaddr = (struct sockaddr_in *) &(target->address);
+    iaddr->sin_family = AF_INET;
+    if ((iaddr->sin_addr.s_addr = inet_addr(target->name)) == -1) {
+
+       /* Conversion of IP address failed, try to look the host up by name */
+
+       struct hostent *hent = gethostbyname(target->name);
+       if (hent == NULL) {
+           fprintf(stderr, "Could not resolve host %s\n", target->name);
+           return 0;
+       }
+       memcpy(&iaddr->sin_addr, hent->h_addr_list[0],
+              sizeof(iaddr->sin_addr));
+    }
+
+    /* Done */
+
+    return 1;
+}
+
+/*
+ * Create a target for a host.
+ *
+ * Args:
+ *    name - The name of the host.
+ *
+ * Returns:
+ *    A newly allocated target or null if the host could not be resolved.
+ */
+
+static ping_target *
+newHost(char *name) 
+{
+
+    /* Local Variables */
+
+    ping_target *target = NULL;
+
+    /* Create the target */
+
+    if ((target = calloc(1, sizeof(ping_target))) == NULL) {
+       fprintf(stderr, "Out of Memory\n");
+       goto target_init_error;
+    }
+    if ((target->name = strdup(name)) == NULL) {
+       fprintf(stderr, "Out of Memory\n");
+       goto target_init_error;
+    }
+
+    /* Lookup the host */
+
+    if (! lookupHost(target))
+       goto target_init_error;
+
+    /* Done */
+
+    return target;
+
+    /* Handle errors here */
+
+target_init_error:
+    if (target != NULL)
+       free(target);
+    return NULL;
+}
+
+/*
+ * Generate a list of ping targets from the entries in a file.
+ *
+ * Args:
+ *    fname - The name of the file. This file is expected to be in the same
+ *            format as /etc/hosts.
+ *
+ * Returns:
+ *    A list of targets to ping or null if an error occured.
+ */
+
+static ping_target *
+readPingHostsFile(char *fname) 
+{
+
+    /* Local Variables */
+
+    FILE *fp;
+    char buf[LINE_MAX];
+    char *p;
+    ping_target *list = NULL;
+    char *addr, *name;
+    ping_target *new;
+
+    /* Make sure we in fact have a file to process */
+
+    if ((fname == NULL) || (fname[0] == '\0')) {
+       fprintf(stderr, "Invalid ping host file name\n");
+       return NULL;
+    }
+
+    /* Open the file */
+
+    if ((fp = fopen(fname, "r")) == NULL) {
+       char msg[1024];
+       sprintf(msg, "Unable to open host file %s", fname);
+       perror(msg);
+       return NULL;
+    }
+
+    /* Read the file line by line */
+
+    while ((p = fgets(buf, LINE_MAX, fp)) != NULL) {
+
+       /*
+        * Parse the line skipping those that start with '#'.
+        * The rest of the lines in the file should be in the same
+        * format as a /etc/hosts file. We are only concerned with
+        * the first two field, the IP address and the name
+        */
+
+       while ((*p == ' ') || (*p == '\t'))
+           p++;
+       if (*p == '#')
+           continue;
+
+       /* Get the name and address */
+
+       name = addr = NULL;
+       if ((addr = strtok(buf, " \t\n")) != NULL)
+           name = strtok(NULL, " \t\n");
+       else
+           continue;
+
+       /* Create a new target using first the name then the address */
+
+       new = NULL;
+       if (name != NULL)
+           new = newHost(name);
+       if (new == NULL)
+           new = newHost(addr);
+
+       /* Add it to the list if we got one */
+
+       if (new != NULL) {
+           new->next = list;
+           list = new;
+       }
+    }
+
+    /* Close the file and return the list */
+
+    fclose(fp);
+    return list;
+}
+
+/*
+ * Generate a list of ping targets from the entries in a string.
+ *
+ * Args:
+ *    list - A list of comma separated host names.
+ *
+ * Returns:
+ *    A list of targets to ping or null if an error occured.
+ */
+
+static ping_target *
+readPingHostsList(char *list) 
+{
+
+    /* Local Variables */
+
+    char *host;
+    ping_target *hostlist = NULL;
+    ping_target *new;
+
+    /* Check that there is a list */
+
+    if ((list == NULL) || (list[0] == '\0'))
+       return NULL;
+
+    /* Loop through the hosts and add them to the list to return */
+
+    host = strtok(list, ",");
+    while (host != NULL) {
+       new = newHost(host);
+       if (new != NULL) {
+           new->next = hostlist;
+           hostlist = new;
+       }
+       host = strtok(NULL, ",");
+    }
+
+    /* Done */
+
+    return hostlist;
+}
+
+/*
+ * Generate a list ping targets consisting of all of the entries on
+ * the same subnet.
+ *
+ * Returns:
+ *    A list of all of the hosts on this net.
+ */
+
+static ping_target *
+subnetHostsList(void) 
+{
+
+    /* Local Variables */
+
+    char hostname[BUFSIZ];
+    char address[BUFSIZ];
+    struct hostent *hent;
+    char *p;
+    int i;
+    ping_target *new;
+    ping_target *list = NULL;
+
+    /* Get our hostname */
+
+    if (gethostname(hostname, BUFSIZ)) {
+       fprintf(stderr, "Unable to get local hostname\n");
+       return NULL;
+    }
+
+    /* Get our IP address and convert it to a string */
+
+    if ((hent = gethostbyname(hostname)) == NULL) {
+       fprintf(stderr, "Unable to lookup our IP address\n");
+       return NULL;
+    }
+    strcpy(address, inet_ntoa(*((struct in_addr *)hent->h_addr_list[0])));
+
+    /* Get a pointer to the last "." in the string */
+
+    if ((p = strrchr(address, '.')) == NULL) {
+       fprintf(stderr, "Can't parse IP address %s\n", address);
+       return NULL;
+    }
+    p++;
+
+    /* Construct targets for all addresses in this subnet */
+
+    for (i = 254; i > 0; i--) {
+       sprintf(p, "%d", i);
+       new = newHost(address);
+       if (new != NULL) {
+           new->next = list;
+           list = new;
+       }
+    }
+  
+    /* Done */
+
+    return list;
+}
+
+/*
+ * Initialize the ping sensor.
+ *
+ * Returns:
+ *    A newly allocated ping_info structure or null if an error occured.
+ */
+
+static ping_info *
+init_ping(void) 
+{
+
+    /* Local Variables */
+
+    ping_info *pi = NULL;              /* The new ping_info struct */
+    char *src;                         /* The source of the ping hosts */
+    ping_target *pt;                   /* Used to count the targets */
+
+    /* Create the ping info structure */
+
+    if ((pi = (ping_info *) calloc(1, sizeof(ping_info))) == NULL) {
+       fprintf(stderr, "Out of memory\n");
+       goto ping_init_error;
+    }
+
+    /* Create the ICMP socket and turn off SUID */
+
+    if ((pi->icmpsock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
+       perror("Can't create ICMP socket");
+       fprintf(stderr,
+         "%s: this program must be setuid to root for `ping mode' to work.\n",
+                progname);
+       goto ping_init_error;
+    }
+    setuid(getuid());
+    pi->pid = getpid() & 0xFFFF;
+    pi->seq = 0;
+    pi->timeout = get_integer_resource("pingTimeout", "PingTimeout");
+
+    /* Generate a list of targets */
+
+    src = get_string_resource("pingSource", "PingSource");
+    if (strcmp(src, "file") == 0) {
+
+       /*
+         * The list of ping targets is to come from a file in
+        * /etc/hosts format
+        */
+
+       pi->targets = readPingHostsFile(get_string_resource("pingFile",
+                                                           "PingFile"));
+
+    } else if (strcmp(src, "list") == 0) {
+
+       /* The list of hosts is to come from the pinghostlist resource */
+
+       pi->targets = readPingHostsList(get_string_resource("pingList",
+                                                           "PingList"));
+
+    } else if (strcmp(src, "subnet") == 0) {
+
+       pi->targets = subnetHostsList();
+
+    } else {
+
+       /* Unknown source */
+
+       fprintf(stderr, "Illegal pingSource: %s\n", src);
+       goto ping_init_error;
+    }
+
+    /* Make sure there is something to ping */
+
+    if (pi->targets == NULL) {
+       fprintf(stderr, "Nothing to ping");
+       goto ping_init_error;
+    }
+
+    /* Count the targets */
+
+    pt = pi->targets;
+    pi->numtargets = 0;
+    while (pt != NULL) {
+       pi->numtargets++;
+       pt = pt->next;
+    }
+
+    /* Done */
+
+    return pi;
+
+    /* Handle initialization errors here */
+
+ping_init_error:
+    if (pi != NULL)
+       free(pi);
+    return NULL;
+}
+
+/*
+ * Ping a host.
+ *
+ * Args:
+ *    pi   - The ping information strcuture.
+ *    host - The name or IP address of the host to ping (in ascii).
+ */
+
+static void
+sendping(ping_info *pi, ping_target *pt) 
+{
+
+    /* Local Variables */
+
+    u_char *packet;
+    struct icmp *icmph;
+    int result;
+
+    /*
+     * Note, we will send the character name of the host that we are
+     * pinging in the packet so that we don't have to keep track of the
+     * name or do an address lookup when it comes back.
+     */
+
+    int pcktsiz = sizeof(struct icmp) + sizeof(struct timeval) +
+       strlen(pt->name) + 1;
+
+    /* Create the ICMP packet */
+
+    if ((packet = (u_char *) malloc(pcktsiz)) == (void *) 0)
+       return;  /* Out of memory */
+    icmph = (struct icmp *) packet;
+    icmph->icmp_type = ICMP_ECHO;
+    icmph->icmp_code = 0;
+    icmph->icmp_cksum = 0;
+    icmph->icmp_id = pi->pid;
+    icmph->icmp_seq = pi->seq++;
+    gettimeofday((struct timeval *) &packet[sizeof(struct icmp)],
+                (struct timezone *) 0);
+    strcpy((char *) &packet[sizeof(struct icmp) + sizeof(struct timeval)],
+          pt->name);
+    icmph->icmp_cksum = checksum((u_short *)packet, pcktsiz);
+
+    /* Send it */
+
+    if ((result = sendto(pi->icmpsock, packet, pcktsiz, 0, 
+                        &pt->address, sizeof(pt->address))) !=  pcktsiz) {
+#if 0
+        char errbuf[BUFSIZ];
+        sprintf(errbuf, "Error sending ping to %s", pt->name);
+       perror(errbuf);
+#endif
+    }
+}
+
+/*
+ * Catch a signal and do nothing.
+ *
+ * Args:
+ *    sig - The signal that was caught.
+ */
+
+static void
+sigcatcher(int sig)
+{
+    timer_expired = 1;
+}
+
+/*
+ * Compute the checksum on a ping packet.
+ *
+ * Args:
+ *    packet - A pointer to the packet to compute the checksum for.
+ *    size   - The size of the packet.
+ *
+ * Returns:
+ *    The computed checksum
+ *    
+ */
+
+static u_short
+checksum(u_short *packet, int size) 
+{
+
+    /* Local Variables */
+
+    register int nleft = size;
+    register u_short *w = packet;
+    register int sum = 0;
+    u_short answer = 0;
+
+    /*
+     * Our algorithm is simple, using a 32 bit accumulator (sum), we add
+     * sequential 16 bit words to it, and at the end, fold back all the
+     * carry bits from the top 16 bits into the lower 16 bits.
+     */
+
+    while (nleft > 1)  {
+       sum += *w++;
+       nleft -= 2;
+    }
+
+    /* mop up an odd byte, if necessary */
+
+    if (nleft == 1) {
+       *(u_char *)(&answer) = *(u_char *)w ;
+       sum += answer;
+    }
+
+    /* add back carry outs from top 16 bits to low 16 bits */
+
+    sum = (sum >> 16) + (sum & 0xffff);     /* add hi 16 to low 16 */
+    sum += (sum >> 16);                     /* add carry */
+    answer = ~sum;                          /* truncate to 16 bits */
+
+    /* Done */
+
+    return(answer);
+}
+
+/*
+ * Look for ping replies.
+ *
+ * Retrieve all outstanding ping replies.
+ *
+ * Args:
+ *    si - Information about the sonar.
+ *    pi - Ping information.
+ *    ttl - The time each bogie is to live on the screen
+ *
+ * Returns:
+ *    A Bogie list of all the machines that replied.
+ */
+
+static Bogie *
+getping(sonar_info *si, ping_info *pi, int ttl) 
+{
+
+    /* Local Variables */
+
+    struct sockaddr from;
+    int fromlen;
+    int result;
+    u_char packet[1024];
+    struct timeval now;
+    struct timeval *then;
+    struct ip *ip;
+    int iphdrlen;
+    struct icmp *icmph;
+    Bogie *bl = NULL;
+    Bogie *new;
+    char *name;
+    struct sigaction sa;
+    struct itimerval it;
+
+    /* Set up a signal to interupt our wait for a packet */
+
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = sigcatcher;
+    if (sigaction(SIGALRM, &sa, 0) == -1) {
+       perror("Unable to trap sigalarm");
+       exit(1);
+    }
+
+    /* Set up a timer to interupt us if we don't get a packet */
+
+    it.it_interval.tv_sec = 0;
+    it.it_interval.tv_usec = 0;
+    it.it_value.tv_sec = 0;
+    it.it_value.tv_usec = pi->timeout;
+    timer_expired = 0;
+    setitimer(ITIMER_REAL, &it, NULL);
+
+    /* Wait for a result packet */
+
+    fromlen = sizeof(from);
+    while (! timer_expired &&
+          (result = recvfrom(pi->icmpsock, packet, sizeof(packet),
+                             0, &from, &fromlen)) > 0) {
+
+       /* Check the packet */
+
+       gettimeofday(&now, (struct timezone *) 0);
+       ip = (struct ip *) packet;
+       iphdrlen = ip->ip_hl << 2;
+       icmph = (struct icmp *) &packet[iphdrlen];
+
+       /* Was the packet a reply?? */
+
+       if (icmph->icmp_type != ICMP_ECHOREPLY) {
+           /* Ignore anything but ICMP Replies */
+           continue; /* Nope */
+       }
+
+       /* Was it for us? */
+
+       if (icmph->icmp_id != pi->pid) {
+           /* Ignore packets not set from us */
+           continue; /* Nope */
+       }
+
+       /* Copy the name of the bogie */
+
+       if ((name =
+            strdup((char *) &packet[iphdrlen + 
+                                   + sizeof(struct icmp)
+                                   + sizeof(struct timeval)])) == NULL) {
+           fprintf(stderr, "Out of memory\n");
+           return bl;
+       }
+
+        /* If the name is an IP addr, try to resolve it. */
+        {
+          int iip[4];
+          char c;
+          if (4 == sscanf(name, " %d.%d.%d.%d %c",
+                          &iip[0], &iip[1], &iip[2], &iip[3], &c))
+            {
+              unsigned char ip[4];
+              struct hostent *h;
+              ip[0] = iip[0]; ip[1] = iip[1]; ip[2] = iip[2]; ip[3] = iip[3];
+              h = gethostbyaddr ((char *) ip, 4, AF_INET);
+              if (h && h->h_name && *h->h_name)
+                {
+                  free (name);
+                  name = strdup (h->h_name);
+                }
+            }
+        }
+
+       /* Create the new Bogie and add it to the list we are building */
+
+       if ((new = newBogie(name, 0, si->current, ttl)) == NULL)
+           return bl;
+       new->next = bl;
+       bl = new;
+
+       /* Compute the round trip time */
+
+       then =  (struct timeval *) &packet[iphdrlen +
+                                         sizeof(struct icmp)];
+       new->distance = delta(then, &now) / 100;
+       if (new->distance == 0)
+               new->distance = 2; /* HACK */
+    }
+
+    /* Done */
+
+    return bl;
+}
+
+/*
+ * Ping hosts.
+ *
+ * Args:
+ *    si - Sonar Information.
+ *    pi - Ping Information.
+ *
+ * Returns:
+ *    A list of hosts that replied to pings or null if there were none.
+ */
+
+static Bogie *
+ping(sonar_info *si, void *vpi) 
+{
+
+    ping_info *pi = (ping_info *) vpi;
+    static ping_target *ptr = NULL;
+
+    int tick = si->current * -1 + 1;
+    if ((ptr == NULL) && (tick == 1))
+       ptr = pi->targets;
+
+    if (pi->numtargets <= 90) {
+       int xdrant = 90 / pi->numtargets;
+       if ((tick % xdrant) == 0) {
+           if (ptr != (ping_target *) 0) {
+               sendping(pi, ptr);
+               ptr = ptr->next;
+           }
+       }
+
+    } else if (pi->numtargets > 90) {
+       if (ptr != (ping_target *) 0) {
+           sendping(pi, ptr);
+           ptr = ptr->next;
+       }
+    }
+
+    /* Get the results */
+
+    return getping(si, pi, TTL);
+}
+
+#endif /* HAVE_PING */
+
+/*
+ * Calculate the difference between two timevals in microseconds.
+ *
+ * Args:
+ *    then - The older timeval.
+ *    now  - The newer timeval.
+ *
+ * Returns:
+ *   The difference between the two in microseconds.
+ */
+
+static long
+delta(struct timeval *then, struct timeval *now) 
+{
+    return (((now->tv_sec - then->tv_sec) * 1000000) + 
+              (now->tv_usec - then->tv_usec));  
+}
+
+/*
+ * Initialize the simulation mode.
+ */
+
+static sim_info *
+init_sim(void) 
+{
+
+    /* Local Variables */
+
+    sim_info *si;
+    int i;
+
+    /* Seed the random number generator */
+
+    srand((int) time(NULL));
+
+    /* Create the simulation info structure */
+
+    if ((si = (sim_info *) calloc(1, sizeof(sim_info))) == NULL) {
+       fprintf(stderr, "Out of memory\n");
+       return NULL;
+    }
+
+    /* Team A */
+
+    si->numA = get_integer_resource("teamACount", "TeamACount");
+    if ((si->teamA = (sim_target *)calloc(si->numA, sizeof(sim_target)))
+       == NULL) {
+       free(si);
+       fprintf(stderr, "Out of Memory\n");
+       return NULL;
+    }
+    si->teamAID = get_string_resource("teamAName", "TeamAName");
+    for (i = 0; i < si->numA; i++) {
+       if ((si->teamA[i].name = (char *) malloc(strlen(si->teamAID) + 4))
+           == NULL) {
+           free(si);
+           fprintf(stderr, "Out of Memory\n");
+           return NULL;
+       }
+       sprintf(si->teamA[i].name, "%s%03d", si->teamAID, i+1);
+       si->teamA[i].nexttick = (int) (90.0 * rand() / RAND_MAX);
+       si->teamA[i].nextdist = (int) (100.0 * rand() / RAND_MAX);
+    }
+
+    /* Team B */
+
+    si->numB = get_integer_resource("teamBCount", "TeamBCount");
+    if ((si->teamB = (sim_target *)calloc(si->numB, sizeof(sim_target)))
+       == NULL) {
+       free(si);
+       fprintf(stderr, "Out of Memory\n");
+       return NULL;
+    }
+    si->teamBID = get_string_resource("teamBName", "TeamBName");
+    for (i = 0; i < si->numB; i++) {
+       if ((si->teamB[i].name = (char *) malloc(strlen(si->teamBID) + 4))
+           == NULL) {
+           free(si);
+           fprintf(stderr, "Out of Memory\n");
+           return NULL;
+       }
+       sprintf(si->teamB[i].name, "%s%03d", si->teamBID, i+1);
+       si->teamB[i].nexttick = (int) (90.0 * rand() / RAND_MAX);
+       si->teamB[i].nextdist = (int) (100.0 * rand() / RAND_MAX);
+    }
+
+    /* Done */
+
+    return si;
+}
+
+/*
+ * Initialize the Sonar.
+ *
+ * Args:
+ *    dpy - The X display.
+ *    win - The X window;
+ *
+ * Returns:
+ *   A sonar_info strcuture or null if memory allocation problems occur.
+ */
+
+static sonar_info *
+init_sonar(Display *dpy, Window win) 
+{
+
+    /* Local Variables */
+
+    XGCValues gcv;
+    XWindowAttributes xwa;
+    sonar_info *si;
+    XColor start, end;
+    int h1, h2;
+    double s1, s2, v1, v2;
+
+    /* Create the Sonar information structure */
+
+    if ((si = (sonar_info *) calloc(1, sizeof(sonar_info))) == NULL) {
+       fprintf(stderr, "Out of memory\n");
+       return NULL;
+    }
+
+    /* Initialize the structure for the current environment */
+
+    si->dpy = dpy;
+    si->win = win;
+    si->visable = NULL;
+    XGetWindowAttributes(dpy, win, &xwa);
+    si->cmap = xwa.colormap;
+    si->width = xwa.width;
+    si->height = xwa.height;
+    si->centrex = si->width / 2;
+    si->centrey = si->height / 2;
+    si->maxx = si->centrex + MIN(si->centrex, si->centrey) - 10;
+    si->minx = si->centrex - MIN(si->centrex, si->centrey) + 10;
+    si->maxy = si->centrey + MIN(si->centrex, si->centrey) - 10;
+    si->miny = si->centrey - MIN(si->centrex, si->centrey) + 10;
+    si->radius = si->maxx - si->centrex;
+    si->current = 0;
+
+    /* Get the font */
+
+    if (((si->font = XLoadQueryFont(dpy, get_string_resource ("font", "Font")))
+        == NULL) &&
+       ((si->font = XLoadQueryFont(dpy, "fixed")) == NULL)) {
+       fprintf(stderr, "Can't load an appropriate font\n");
+       return NULL;
+    }
+
+    /* Get the delay between animation frames */
+
+    si->delay = get_integer_resource ("delay", "Integer");
+    if (si->delay < 0) si->delay = 0;
+
+    /* Create the Graphics Contexts that will be used to draw things */
+
+    gcv.foreground = 
+       get_pixel_resource ("sweepColor", "SweepColor", dpy, si->cmap);
+    si->hi = XCreateGC(dpy, win, GCForeground, &gcv);
+    gcv.font = si->font->fid;
+    si->text = XCreateGC(dpy, win, GCForeground|GCFont, &gcv);
+    gcv.foreground = get_pixel_resource("scopeColor", "ScopeColor",
+                                       dpy, si->cmap);
+    si->erase = XCreateGC (dpy, win, GCForeground, &gcv);
+    gcv.foreground = get_pixel_resource("gridColor", "GridColor",
+                                       dpy, si->cmap);
+    si->grid = XCreateGC (dpy, win, GCForeground, &gcv);
+
+    /* Compute pixel values for fading text on the display */
+
+    XParseColor(dpy, si->cmap, 
+               get_string_resource("textColor", "TextColor"), &start);
+    XParseColor(dpy, si->cmap, 
+               get_string_resource("scopeColor", "ScopeColor"), &end);
+
+    rgb_to_hsv (start.red, start.green, start.blue, &h1, &s1, &v1);
+    rgb_to_hsv (end.red, end.green, end.blue, &h2, &s2, &v2);
+
+    si->text_steps = get_integer_resource("textSteps", "TextSteps");
+    if (si->text_steps < 0 || si->text_steps > 255)
+      si->text_steps = 10;
+
+    si->text_colors = (XColor *) calloc(si->text_steps, sizeof(XColor));
+    make_color_ramp (dpy, si->cmap,
+                     h1, s1, v1,
+                     h2, s2, v2,
+                     si->text_colors, &si->text_steps,
+                     False, True, False);
+
+    /* Compute the pixel values for the fading sweep */
+
+    XParseColor(dpy, si->cmap, 
+                get_string_resource("sweepColor", "SweepColor"), &start);
+
+    rgb_to_hsv (start.red, start.green, start.blue, &h1, &s1, &v1);
+
+    si->sweep_degrees = get_integer_resource("sweepDegrees", "Degrees");
+    if (si->sweep_degrees <= 0) si->sweep_degrees = 20;
+    if (si->sweep_degrees > 350) si->sweep_degrees = 350;
+
+    si->sweep_segs = get_integer_resource("sweepSegments", "SweepSegments");
+    if (si->sweep_segs < 1 || si->sweep_segs > 255)
+      si->sweep_segs = 255;
+
+    si->sweep_colors = (XColor *) calloc(si->sweep_segs, sizeof(XColor));
+    make_color_ramp (dpy, si->cmap,
+                     h1, s1, v1,
+                     h2, s2, v2,
+                     si->sweep_colors, &si->sweep_segs,
+                     False, True, False);
+
+    /* Done */
+
+    return si;
+}
+
+/*
+ * Update the location of a simulated bogie.
+ */
+
+static void
+updateLocation(sim_target *t) 
+{
+
+    int xdist, xtick;
+
+    t->movedlasttick = 1;
+    xtick = (int) (3.0 * rand() / RAND_MAX) - 1;
+    xdist = (int) (11.0 * rand() / RAND_MAX) - 5;
+    if (((t->nexttick + xtick) < 90) && ((t->nexttick + xtick) >= 0))
+       t->nexttick += xtick;
+    else
+       t->nexttick -= xtick;
+    if (((t->nextdist + xdist) < 100) && ((t->nextdist+xdist) >= 0))
+       t->nextdist += xdist;
+    else
+       t->nextdist -= xdist;
+}
+
+/*
+ * The simulator. This uses information in the sim_info to simulate a bunch
+ * of bogies flying around on the screen.
+ */
+
+/*
+ * TODO: It would be cool to have the two teams chase each other around and
+ *       shoot it out.
+ */
+
+static Bogie *
+simulator(sonar_info *si, void *vinfo) 
+{
+
+    /* Local Variables */
+
+    int i;
+    Bogie *list = NULL;
+    Bogie *new;
+    sim_target *t;
+    sim_info *info = (sim_info *) vinfo;
+
+    /* Check team A */
+
+    for (i = 0; i < info->numA; i++) {
+       t = &info->teamA[i];
+       if (!t->movedlasttick && (t->nexttick == (si->current * -1))) {
+           new = newBogie(strdup(t->name), t->nextdist, si->current, TTL);
+           if (list != NULL)
+               new->next = list;
+           list = new;
+           updateLocation(t);
+       } else
+           t->movedlasttick = 0;
+    }
+
+    /* Team B */
+
+    for (i = 0; i < info->numB; i++) {
+       t = &info->teamB[i];
+       if (!t->movedlasttick && (t->nexttick == (si->current * -1))) {
+           new = newBogie(strdup(t->name), t->nextdist, si->current, TTL);
+           if (list != NULL)
+               new->next = list;
+           list = new;
+           t->movedlasttick = 1;
+           updateLocation(t);
+       } else
+           t->movedlasttick = 0;
+    }
+
+    /* Done */
+
+    return list;
+}
+
+/*
+ * Compute the X coordinate of the label.
+ *
+ * Args:
+ *    si - The sonar info block.
+ *    label - The label that will be drawn.
+ *    x - The x coordinate of the bogie.
+ *
+ * Returns:
+ *    The x coordinate of the start of the label.
+ */
+
+static int
+computeStringX(sonar_info *si, char *label, int x) 
+{
+
+    int width = XTextWidth(si->font, label, strlen(label));
+    return x - (width / 2);
+}
+
+/*
+ * Compute the Y coordinate of the label.
+ *
+ * Args:
+ *    si - The sonar information.
+ *    y - The y coordinate of the bogie.
+ *
+ * Returns:
+ *    The y coordinate of the start of the label.
+ */
+
+/* TODO: Add smarts to keep label in sonar screen */
+
+static int
+computeStringY(sonar_info *si, int y) 
+{
+
+    int fheight = si->font->ascent + si->font->descent;
+    return y + 5 + fheight;
+}
+
+/*
+ * Draw a Bogie on the radar screen.
+ *
+ * Args:
+ *    si       - Sonar Information.
+ *    draw     - A flag to indicate if the bogie should be drawn or erased.
+ *    name     - The name of the bogie.
+ *    degrees  - The number of degrees that it should apprear at.
+ *    distance - The distance the object is from the centre.
+ *    ttl      - The time this bogie has to live.
+ *    age      - The time this bogie has been around.
+ */
+
+static void
+DrawBogie(sonar_info *si, int draw, char *name, int degrees, 
+         int distance, int ttl, int age) 
+{
+
+    /* Local Variables */
+
+    int x, y;
+    GC gc;
+    int ox = si->centrex;
+    int oy = si->centrey;
+    int index, delta;
+
+    /* Compute the coordinates of the object */
+
+    distance = (log((double) distance) / 10.0) * si->radius;
+    x = ox + ((double) distance * cos(4.0 * ((double) degrees)/57.29578));
+    y = oy - ((double) distance * sin(4.0 * ((double) degrees)/57.29578));
+
+    /* Set up the graphics context */
+
+    if (draw) {
+
+       /* Here we attempt to compute the distance into the total life of
+        * object that we currently are. This distance is used against
+        * the total lifetime to compute a fraction which is the index of
+        * the color to draw the bogie.
+        */
+
+       if (si->current <= degrees)
+           delta = (si->current - degrees) * -1;
+       else
+           delta = 90 + (degrees - si->current);
+       delta += (age * 90);
+       index = (si->text_steps - 1) * ((float) delta / (90.0 * (float) ttl));
+       gc = si->text;
+       XSetForeground(si->dpy, gc, si->text_colors[index].pixel);
+
+    } else
+       gc = si->erase;
+
+  /* Draw (or erase) the Bogie */
+
+    XFillArc(si->dpy, si->win, gc, x, y, 5, 5, 0, 360 * 64);
+    XDrawString(si->dpy, si->win, gc,
+               computeStringX(si, name, x),
+               computeStringY(si, y), name, strlen(name));
+}
+
+
+/*
+ * Draw the sonar grid.
+ *
+ * Args:
+ *    si - Sonar information block.
+ */
+
+static void
+drawGrid(sonar_info *si) 
+{
+
+    /* Local Variables */
+
+    int i;
+    int width = si->maxx - si->minx;
+    int height = si->maxy - si->miny;
+  
+    /* Draw the circles */
+
+    XDrawArc(si->dpy, si->win, si->grid, si->minx - 10, si->miny - 10, 
+            width + 20, height + 20,  0, (360 * 64));
+
+    XDrawArc(si->dpy, si->win, si->grid, si->minx, si->miny, 
+            width, height,  0, (360 * 64));
+
+    XDrawArc(si->dpy, si->win, si->grid, 
+            (int) (si->minx + (.166 * width)), 
+            (int) (si->miny + (.166 * height)), 
+            (unsigned int) (.666 * width), (unsigned int)(.666 * height),
+            0, (360 * 64));
+
+    XDrawArc(si->dpy, si->win, si->grid, 
+            (int) (si->minx + (.333 * width)),
+            (int) (si->miny + (.333 * height)), 
+            (unsigned int) (.333 * width), (unsigned int) (.333 * height),
+            0, (360 * 64));
+
+    /* Draw the radial lines */
+
+    for (i = 0; i < 360; i += 10)
+       if (i % 30 == 0)
+           XDrawLine(si->dpy, si->win, si->grid, si->centrex, si->centrey,
+                     (int) (si->centrex +
+                     (si->radius + 10) * (cos((double) i / 57.29578))),
+                     (int) (si->centrey -
+                     (si->radius + 10)*(sin((double) i / 57.29578))));
+       else
+           XDrawLine(si->dpy, si->win, si->grid, 
+                     (int) (si->centrex + si->radius *
+                            (cos((double) i / 57.29578))),
+                     (int) (si->centrey - si->radius *
+                            (sin((double) i / 57.29578))),
+                     (int) (si->centrex +
+                     (si->radius + 10) * (cos((double) i / 57.29578))),
+                     (int) (si->centrey - 
+                     (si->radius + 10) * (sin((double) i / 57.29578))));
+}
+
+/*
+ * Update the Sonar scope.
+ *
+ * Args:
+ *    si - The Sonar information.
+ *    bl - A list  of bogies to add to the scope.
+ */
+
+static void
+Sonar(sonar_info *si, Bogie *bl) 
+{
+
+    /* Local Variables */
+
+    Bogie *bp, *prev;
+    int i;
+
+    /* Check for expired tagets and remove them from the visable list */
+
+    prev = NULL;
+    for (bp = si->visable; bp != NULL; bp = bp->next) {
+
+       /*
+        * Remove it from the visable list if it's expired or we have
+        * a new target with the same name.
+        */
+
+       bp->age ++;
+
+       if (((bp->tick == si->current) && (++bp->age >= bp->ttl)) ||
+           (findNode(bl, bp->name) != NULL)) {
+           DrawBogie(si, 0, bp->name, bp->tick,
+                     bp->distance, bp->ttl, bp->age);
+           if (prev == NULL)
+               si->visable = bp->next;
+           else
+               prev->next = bp->next;
+           freeBogie(bp);
+       } else
+           prev = bp;
+    }
+
+    /* Draw the sweep */
+
+    {
+      int seg_deg = (si->sweep_degrees * 64) / si->sweep_segs;
+      int start_deg = si->current * 4 * 64;
+      if (seg_deg <= 0) seg_deg = 1;
+      for (i = 0; i < si->sweep_segs; i++) {
+       XSetForeground(si->dpy, si->hi, si->sweep_colors[i].pixel);
+       XFillArc(si->dpy, si->win, si->hi, si->minx, si->miny, 
+                si->maxx - si->minx, si->maxy - si->miny,
+                 start_deg + (i * seg_deg),
+                 seg_deg);
+      }
+
+      /* Remove the trailing wedge the sonar */
+      XFillArc(si->dpy, si->win, si->erase, si->minx, si->miny, 
+               si->maxx - si->minx, si->maxy - si->miny, 
+               start_deg + (i * seg_deg),
+               (4 * 64));
+    }
+
+    /* Move the new targets to the visable list */
+
+    for (bp = bl; bp != (Bogie *) 0; bp = bl) {
+       bl = bl->next;
+       bp->next = si->visable;
+       si->visable = bp;
+    }
+
+    /* Draw the visable targets */
+
+    for (bp = si->visable; bp != NULL; bp = bp->next) {
+       if (bp->age < bp->ttl)          /* grins */
+          DrawBogie(si, 1, bp->name, bp->tick, bp->distance, bp->ttl,bp->age);
+    }
+
+    /* Redraw the grid */
+
+    drawGrid(si);
+}
+
+/*
+ * Main screen saver hack.
+ *
+ * Args:
+ *    dpy - The X display.
+ *    win - The X window.
+ */
+
+void 
+screenhack(Display *dpy, Window win) 
+{
+
+    /* Local Variables */
+
+    sonar_info *si;
+    struct timeval start, finish;
+    Bogie *bl;
+    long sleeptime;
+    char *mode;
+
+    /* 
+     * Initialize 
+     * Adding new sensors would involve supporting more modes other than
+     * ping and initiailizing the sensor in the same way.
+     */
+
+    mode = get_string_resource("mode", "Mode");
+
+    if (!mode || !*mode || !strcmp(mode, "default")) /* Pick a good default. */
+      {
+#ifdef HAVE_PING
+        if (geteuid() == 0)    /* we're root or setuid -- ping will work. */
+          mode = "ping";
+        else
+#endif
+          mode = "simulation";
+      }
+
+#ifdef HAVE_PING
+    if (strcmp(mode, "ping") == 0) {
+       sensor = ping;
+       if ((sensor_info = (void *) init_ping()) == (void *) 0)
+          {
+            fprintf (stderr, "%s: running in `simulation mode' instead.\n",
+                     progname);
+           goto SIM;
+          }
+    } else
+#endif /* HAVE_PING */
+    if (strcmp(mode, "simulation") == 0) {
+#ifdef HAVE_PING
+    SIM:
+#endif
+       sensor = simulator;
+       if ((sensor_info = (void *) init_sim()) == NULL)
+           exit(1);
+    } else {
+       fprintf(stderr, "Unsupported Sonar mode: %s\n", mode);
+       fprintf(stderr,
+                "\tCurrently supported modes are `ping' and `simulation'\n");
+       exit(1);
+    }
+    if ((si = init_sonar(dpy, win)) == (sonar_info *) 0)
+       exit(1);
+  
+    /* Sonar loop */
+
+    TTL = get_integer_resource("ttl", "TTL");
+
+    while (1) {
+
+       /* Call the sensor and display the results */
+
+       gettimeofday(&start, (struct timezone *) 0);
+       bl = sensor(si, sensor_info);
+       Sonar(si, bl);
+
+        /* Set up and sleep for the next one */
+
+       si->current = (si->current - 1) % 90;
+       XSync (dpy, False);
+       gettimeofday(&finish, (struct timezone *) 0);
+       sleeptime = si->delay - delta(&start, &finish);
+        screenhack_handle_events (dpy);
+       if (sleeptime > 0L)
+           usleep(sleeptime);
+    }
+}
diff --git a/hacks/sonar.man b/hacks/sonar.man
new file mode 100644 (file)
index 0000000..7fe7761
--- /dev/null
@@ -0,0 +1,167 @@
+.TH Sonar 1 "3-Nov-98" "X Version 11"
+.SH NAME
+sonar - display a sonar scope
+.SH SYNOPSIS
+.B sonar
+[\-background \fIcolor\fP]
+[\-sweep\-color \fIcolor\fP]
+[\-low\-color \fIcolor\fP] 
+[\-scope\-color \fIcolor\fP]
+[\-grid\-color \fIcolor\fP]
+[\-text\-color \fIcolor\fP]
+[\-ttl \fIinteger\fP]
+[\-mode ping]
+[\-font \fIfont\fP]
+[\-ping\-timeout \fIint\fP]
+[\-ping\-source list | file | subnet ] 
+[\-ping\-file \fIhosts-file\fP]
+[\-ping\-list \fIhost-name-list\fP]
+[\-team-a-name \fIstring\fP] 
+[\-team-b-name \fIstring\fP]
+[\-team-a-count \fIint\fP]
+[\-team-b-count \fIint\fP]
+.SH DESCRIPTION
+The \fIsonar\fP program displays a sonar scope on the computer's screen.
+This scope polls a sensor as the sweep goes around the scope and displays
+what it finds as bogies on the screen.  The program is designed to support
+different modes representing different types of sensors.  Currently the
+only implemented sensors are a simulator, and a network ping function that
+pings hosts and plots the results on the scope.
+.SH OPTIONS
+.I sonar
+understands the following options:
+.TP 8
+.B \-background \fIColor\fP
+The background Color of the screen not covered by the scope.
+.TP 8
+.B \-sweep\-color \fIColor\fP
+The color of the brightest part of the sweep.
+.TP 8
+.B \-scope\-color \fIColor\fP
+The color of the circular part of the scope.
+.TP 8
+.B \-grid\-color \fIColor\fP
+The color to the grid lines overlaying the scope.
+.TP 8
+.B \-text\-color \fIColor\fP
+The color of the text identifying bogies on the scope.
+.TP 8
+.B \-ttl \fIinteger\fP
+"Time to live": visible time of a Bogie. Try values between 10 (very short)
+and 100. 
+.TP 8
+.B \-mode \fIsimulation | ping\fP
+The sensor mode to use, the currently supported modes \fIsimulate\fP (the
+default) and \fIping\fP.
+.TP 8
+.B \-font \fIfont\fP
+The font used to display text on the scope.  Default "fixed".
+.TP 8
+.B \-ping\-timeout \fIint\fP
+The amount of time in milliseconds the program will wait for an answer
+to a ping.
+.TP 8
+.B \-ping\-source list | file | subnet
+Th source of the list of hosts to ping. Valid values are: \fIlist\fP,
+\fIfile\fP, \fIsubnet\fP.  The first two values are described below;
+and \fIsubnet\fP indicates that the sonar should ping all hosts in the 
+same subnet as the current machine.  (All addresses are treated
+as class C nets, therefore this will at most ping about 256 hosts.)
+.TP 8
+.B \-ping\-file \fIfilename\fP
+The path to a file in \fI/etc/hosts\fP format. Only used when \fIpingSource\fP 
+is set to \fIfile\fP.
+.TP 8
+.B \-ping\-list \fIlist\fP
+A comma separated list of hostnames, eg \fI"pinky,brain,dot"\fP.
+Only used when \fIpingSource\fP is set to \fIlist\fP.
+.TP 8
+.B \-team-a-name \fIstring\fP
+The name of team A, in simulation-mode.
+.TP 8
+.B \-team-b-name \fIstring\fP
+The name of team B, in simulation-mode.
+.TP 8
+.B \-team-a-count \fIint\fP
+The number of bogies on team A, in simulation-mode.
+.TP 8
+.B \-team-b-count \fIint\fP
+The number of bogies on team B, in simulation-mode.
+.SH RESOURCES
+Configuration of the targets to ping is best done by setting X Resources.
+.PP
+.TP 8
+.B background \fI(Color)\fP
+See option \-background, above; default value is \fIblack\fP.
+.TP 8
+.B sweepColor \fI(Color)\fP
+See option \-sweep\-color, above; default value is \fI#00ff00\fP.
+.TP 8
+.B scopeColor \fI(Color)\fP
+See option \-scope\-color, above; default value is \fI#003300\fP.
+.TP 8
+.B gridColor \fI(Color)\fP
+See option \-grid\-color, above; default value is \fI#00aa00\fP.
+.TP 8
+.B textColor \fI(Color)\fP
+See option \-text\-color, above; default value is \fI#ffff00\fP.
+.TP 8
+.B ttl \fI(integer)\fP
+See option \-ttl, above; default value is \fI90\fP or one sweep.
+.TP 8
+.B mode \fI(ping)\fP
+See option \-mode, above.  If set to \fIdefault\fP, it will ping hosts if
+possible, otherwise, will run in simulation-mode.
+.TP 8
+.B font \fI(font)\fP
+See option \-font, above; default value is \fIfixed\fP.
+.TP 8
+.B pingTimeout \fI(Integer)\fP
+See option \-pingtimeout, above; default value is \fI3000\fP.
+.TP 8
+.B pingSource \fIlist | file | subnet\fP
+See option \-ping\-source, above.  Default value is \fIhostfile\fP.
+.TP 8
+.B pingFile \fIpathname\fP
+See option \-ping\-file, above.  Default value is \fI/etc/hosts\fP.
+.TP 8
+.B pingList \fIhost,host,host...\fP
+See option \-ping\-list, above; default value is \fI"localhost"\fP.
+.TP 8
+.B teamAName \fIstring\fP
+See option \-team\-a\-name, above.  Default value is "F18".
+.TP 8
+.B teamBName \fIstring\fP
+See option \-teamBName, above.  Default value is "MIG".
+.TP 8
+.B teamACount \fIint\fP
+See option \-teamACount, above.  Default value is 4.
+.TP 8
+.B teamBCount \fIint\fP
+See option \-teamBCount, above.  Default value is 4.
+.SH NOTES
+In order to use the ping sensor, this program must be installed as 
+setuid root, so that it can create an ICMP socket.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR ping (8)
+.SH COPYRIGHT
+Copyright \(co 1998 by Stephen Martin. (smartin@canada.com)
+
+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.
+
+.SH AUTHORS
+Stephen Martin <smartin@canada.com>, 3-nov-98.
+
+Thanks to Tom Kelly for suggesting a modular approach to the sensor
+amoung other things.
+
+Thomas Bahls <thommy@cs.tu-berlin.de> hacked the "ttl" option, 12-jul-98.
+
index e368164d07b273609e232fb42c6c90648cc898bc..070c034109a1d3ec901c18ae0fb2a71c9555a3f2 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1997 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1997, 1998 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
@@ -470,8 +470,9 @@ screenhack (Display *dpy, Window window)
   while (1)
     {
       run_starfish (dpy, window, s);
-      XSync (dpy, True);
+      XSync (dpy, False);
 
+      screenhack_handle_events (dpy);
       if (cycle_p && cycle_delay)
        {
          if (cycle_delay <= delay)
@@ -518,6 +519,7 @@ screenhack (Display *dpy, Window window)
                  while (i < delay2)
                    {
                      rotate_colors (dpy, cmap, colors, ncolors, direction);
+                      screenhack_handle_events (dpy);
                      usleep(cycle_delay);
                      i += cycle_delay;
                    }
index 66cec3db7f4c69b1e8f19eb5107b8e95d764c1a4..cb5391348b475e0a8ba8509331cbce218c4168fe 100644 (file)
@@ -458,8 +458,10 @@ void screenhack(Display *disp, Window win)
          delay = 0;
        }
       else
-       XSync(disp,True);
+       XSync(disp, False);
       
+      screenhack_handle_events (disp);
+
       /* the delay to try to minimize seizures */
       usleep((delay*1000)); 
       count++;
@@ -488,7 +490,7 @@ static void scroll_area(Display *disp, Window win, int delay, int step_size)
   while(scrollcount_x <= scroll)
     {
       XCopyArea(disp, frame, win, agc,scrollcount_x+offset,scrollcount_y+offset, xgwa.width, xgwa.height, 0,0);
-      XSync(disp,True);
+      XSync(disp, False);
       scrollcount_x=scrollcount_x+step_size;
       scrollcount_y=scrollcount_y+step_size;
       usleep(1000*delay); 
@@ -496,7 +498,7 @@ static void scroll_area(Display *disp, Window win, int delay, int step_size)
   while(scrollcount_x >= 0)
     {
       XCopyArea(disp, frame, win, agc,scrollcount_x+offset,scrollcount_y+offset, xgwa.width, xgwa.height, 0,0);
-      XSync(disp,True);
+      XSync(disp, False);
       scrollcount_y=scrollcount_y+step_size;
       scrollcount_x=scrollcount_x-step_size;
       usleep(1000*delay); 
@@ -504,7 +506,7 @@ static void scroll_area(Display *disp, Window win, int delay, int step_size)
   while(scrollcount_y >= scroll)
     {
       XCopyArea(disp, frame, win, agc,scrollcount_x+offset,scrollcount_y+offset, xgwa.width, xgwa.height, 0,0);
-      XSync(disp,True);
+      XSync(disp, False);
       scrollcount_x=scrollcount_x-step_size;
       scrollcount_y=scrollcount_y-step_size;
       usleep(1000*delay); 
@@ -512,13 +514,13 @@ static void scroll_area(Display *disp, Window win, int delay, int step_size)
   while(scrollcount_y > 0)
     {
       XCopyArea(disp, frame, win, agc,scrollcount_x+offset,scrollcount_y+offset, xgwa.width, xgwa.height, 0,0);
-      XSync(disp,True);
+      XSync(disp, False);
       scrollcount_y=scrollcount_y-step_size;
       scrollcount_x=scrollcount_x+step_size;
       usleep(1000*delay); 
     }
   
-  XSync(disp,True);
+  XSync(disp, False);
   scrollcount_x=0;
   scrollcount_y=0;
   
index 8f8c1a343dcb76e1c20fa47cc4811a9fce679640..4f50635bb161322aff18a849df7493fec348c2d4 100644 (file)
@@ -171,7 +171,7 @@ screenhack (Display *dpy, Window window)
                              hspace, xgwa.height, False);
                  y--;
                  lines--;
-                 XSync (dpy, True);
+                 XSync (dpy, False);
                  if (delay) usleep (delay * 10);
                }
              if (y < 0) y = 0;
@@ -238,7 +238,7 @@ screenhack (Display *dpy, Window window)
            {
              x--;
              s--;
-             XSync (dpy, True);
+             XSync (dpy, False);
              if (delay) usleep (0xFFFF & (delay + (random() % (delay * 10))));
            }
        }
@@ -306,7 +306,7 @@ screenhack (Display *dpy, Window window)
          s = source;
        }
 
-      XSync (dpy, True);
+      XSync (dpy, False);
       if (delay)
        {
          usleep (delay);
@@ -340,7 +340,7 @@ screenhack (Display *dpy, Window window)
                  if (x >= columns) x = 0, y++;
                  n1++;
                }
-             XSync (dpy, True);
+             XSync (dpy, False);
              usleep (5000000);
              while (*n2)
                {
@@ -353,9 +353,10 @@ screenhack (Display *dpy, Window window)
                  n2++;
                }
              y++;
-             XSync (dpy, True);
+             XSync (dpy, False);
              usleep (500000);
            }
        }
+      screenhack_handle_events (dpy);
     }
 }
index ff18c4a0764f0ee8dd332166c99379157381f2b9..62c2dc79341ae86e56659006d35d591b95ac1400 100644 (file)
@@ -328,6 +328,7 @@ xlockmore_screenhack (Display *dpy, Window window,
   do {
     hack_draw (&mi);
     XSync(dpy, False);
+    screenhack_handle_events (dpy);
     if (mi.pause)
       usleep(mi.pause);
     mi.pause = orig_pause;
index 7557dce35064c6a212aeb027323bd0bb6176a2bc..b180fc43341828a85e6225e2fcb788491b2b6ad1 100644 (file)
@@ -582,6 +582,9 @@ main_event(void)
          break;
            case ButtonRelease:
     EndRubberBand(canvas, &rubber_data, &event);
+         break;
+            default: 
+    screenhack_handle_event (dpy, &event);
          break;
            }
        }
index 278189c50216dfbbce98eef8333215c983dc59c0..f4fa11640811d6cd6d1ee2bf24798de6fe01b4a2 100644 (file)
@@ -73,7 +73,8 @@ screenhack (dpy, window)
 
 
       skull (dpy, window, draw_gc, erase_gc, x, y, ww, hh);
-      XSync (dpy, True);
+      XSync (dpy, False);
+      screenhack_handle_events (dpy);
       start_time = time ((time_t *) 0);
       if (mono_p)
        sleep (delay);
index d6d2d1e0124c597813a397849c9337694777c6a6..b32920af5806c4db7f13fe543d99e966c4e9b686 100644 (file)
--- a/setup.com
+++ b/setup.com
@@ -61,6 +61,7 @@ $ rotor               :== $'mydir'rotor
 $ sierpinski   :== $'mydir'sierpinski
 $ slidescreen  :== $'mydir'slidescreen
 $ slip         :== $'mydir'slip
+$ sonar                :== $'mydir'sonar
 $ sphere       :== $'mydir'sphere
 $ spiral       :== $'mydir'spiral
 $ starfish     :== $'mydir'starfish
index 4b67aa21eb3c78a9237d145703e5ccb7ab3c7f0a..0ef8295f2f24a9ef9e115c00be70db9b2886a298 100644 (file)
@@ -1,2 +1,2 @@
 static const char screensaver_id[] =
-       "@(#)xscreensaver 3.04 (15-Nov-98), by Jamie Zawinski (jwz@jwz.org)";
+       "@(#)xscreensaver 3.06 (21-Nov-98), by Jamie Zawinski (jwz@jwz.org)";
index f74c39209a3e37a8e9d55f7851d58b129fb58ca5..babdbccb827e1876607a8d184e15322ede64c7ab 100644 (file)
@@ -1,7 +1,7 @@
 Begin3
 Title:          xscreensaver
-Version:        3.04
-Entered-date:   16NOV98
+Version:        3.06
+Entered-date:   22NOV98
 Description:    A modular screen saver and locker for the X Window System.
                 Highly customizable: allows the use of any program that
                 can draw on the root window as a display mode.
@@ -10,16 +10,16 @@ Keywords:       screen saver, screen lock, lock, xlock, X11
 Author:         jwz@jwz.org (Jamie Zawinski)
 Maintained-by:  jwz@jwz.org (Jamie Zawinski)
 Primary-site:   http://www.jwz.org/xscreensaver/
-                964K xscreensaver-3.04.tar.gz
-                25K  xscreensaver.README
+                981K xscreensaver-3.06.tar.gz
+                26K  xscreensaver.README
                 1K   xscreensaver.lsm
 Alternate-site: sunsite.unc.edu /pub/Linux/X11/screensavers/
-                964K xscreensaver-3.04.tar.gz
-                25K  xscreensaver.README
+                981K xscreensaver-3.06.tar.gz
+                26K  xscreensaver.README
                 1K   xscreensaver.lsm
 Alternate-site: ftp.x.org /contrib/applications/
-                964K xscreensaver-3.04.tar.gz
-                25K  xscreensaver.README
+                981K xscreensaver-3.06.tar.gz
+                26K  xscreensaver.README
                 1K   xscreensaver.lsm
 Platforms:      Linux, Irix, SunOS, Solaris, HPUX, AIX, FreeBSD, NetBSD,
                 BSDI, SCO, OSF1, Ultrix, VMS.
index c31c1ad1e8facb7aee359c170d79e141ebec3a4c..89dd6d9191b9a9abbbc948df540397619fe052d3 100644 (file)
@@ -1,7 +1,7 @@
 Name: xscreensaver
 Summary: X screen saver and locker
-Vendor: Jamie Zawinski
-Version: 3.04
+Vendor: Jamie Zawinski <jwz@jwz.org>
+Version: 3.06
 Release: 1
 URL: http://www.jwz.org/xscreensaver/
 Source: xscreensaver-%{version}.tar.gz