ftp://updates.redhat.com/enterprise/2.1AS/en/os/SRPMS/xscreensaver-3.33-4.rhel21...
authorZygo Blaxell <zblaxell@hungrycats.org>
Mon, 2 Mar 2009 05:42:47 +0000 (00:42 -0500)
committerZygo Blaxell <zblaxell@faye.furryterror.org>
Fri, 8 Feb 2013 17:53:44 +0000 (12:53 -0500)
-rw-r--r-- 1 zblaxell zblaxell 1651696 Feb 27 12:02 xscreensaver-3.33-4.rhel21.5.src.rpm
32bcfa7f9635305c480eb74c30456eb7806ef5a7  xscreensaver-3.33-4.rhel21.5.src.rpm

xscreensaver-3.33.tar.gz
-rw-rw-r-- 2 zblaxell zblaxell 1630284 Jun 25  2004 xscreensaver-3.33.tar.gz
b338583c8bf75307883684a427980d9d203fe363  xscreensaver-3.33.tar.gz

78 files changed:
Makefile.in
README
config.h.in
configure
configure.in
driver/Makefile.in
driver/XScreenSaver.ad.in
driver/XScreenSaver_ad.h
driver/demo-Gtk.c
driver/passwd-pam.c
driver/prefs.c
driver/prefs.h
driver/subprocs.c
driver/timers.c
driver/windows.c
driver/xscreensaver-command.man
driver/xscreensaver-demo.man
driver/xscreensaver-getimage-file
driver/xscreensaver-getimage-file.man
driver/xscreensaver-getimage-video.man
driver/xscreensaver-getimage.man
driver/xscreensaver.c
driver/xscreensaver.h
driver/xscreensaver.man
hacks/Makefile.in
hacks/attraction.c
hacks/attraction.man
hacks/bsod.c
hacks/compass.c
hacks/compile_axp.com
hacks/compile_decc.com
hacks/galaxy.man
hacks/glx/Makefile.in
hacks/glx/atlantis.c
hacks/glx/cage.c
hacks/glx/fps.c
hacks/glx/gflux.man
hacks/glx/glplanet.c
hacks/glx/lament.c
hacks/glx/molecule.c
hacks/glx/pulsar.c
hacks/glx/sproingiewrap.c
hacks/glx/starwars.c
hacks/images/molecules/dna.pdb
hacks/images/noseguy/nose-f1.xbm
hacks/images/noseguy/nose-f1.xpm
hacks/images/noseguy/nose-f2.xbm
hacks/images/noseguy/nose-f2.xpm
hacks/images/noseguy/nose-f3.xbm
hacks/images/noseguy/nose-f3.xpm
hacks/images/noseguy/nose-f4.xbm
hacks/images/noseguy/nose-f4.xpm
hacks/images/noseguy/nose-l1.xbm
hacks/images/noseguy/nose-l1.xpm
hacks/images/noseguy/nose-l2.xbm
hacks/images/noseguy/nose-l2.xpm
hacks/images/noseguy/nose-r1.xbm
hacks/images/noseguy/nose-r1.xpm
hacks/images/noseguy/nose-r2.xbm
hacks/images/noseguy/nose-r2.xpm
hacks/noseguy.c
hacks/noseguy.man
hacks/pyro.c
hacks/sonar.man
hacks/speedmine.c [new file with mode: 0644]
hacks/speedmine.man [new file with mode: 0644]
hacks/vidwhacker.man
hacks/webcollage
hacks/whirlygig.c [new file with mode: 0644]
hacks/whirlygig.man [new file with mode: 0644]
setup.com
utils/erase.c
utils/erase.h
utils/overlay.c
utils/version.h
xscreensaver.lsm
xscreensaver.lsm.sh
xscreensaver.spec

index 6fe2ba0ec3e652d872185de6943611853bc4d399..b7ed67e481c8039aeb86e29f4fb44618f35b7933 100644 (file)
@@ -63,6 +63,7 @@ tar:
   's/[^0-9]*\([0-9]\.[0-9][0-9]*\).*/xscreensaver-\1/p' utils/version.h` ;  \
   rm -rf $$NAME ; ln -s . $$NAME ;                                         \
   FILES= ;                                                                 \
+  ADIR=archive/ ;                                                          \
   for subdir in $(SUBDIRS) ; do                                                    \
     d=`pwd` ;                                                              \
     cd $$subdir ;                                                          \
@@ -71,8 +72,8 @@ tar:
       | sed \"s|^|$$subdir/|g;s| | $$subdir/|g\"                           \
       ` ";                                                                 \
     cd $$d ; done ;                                                        \
-  echo creating tar file $${NAME}.tar.gz... ;                              \
-  GZIP="-9v" $(TAR) -vchzf $${NAME}.tar.gz                                 \
+  echo creating tar file $$ADIR$$NAME.tar.gz... ;                          \
+  GZIP="-9v" $(TAR) -vchzf $$ADIR$$NAME.tar.gz                     \
     `echo $(TARFILES) $$FILES | sed "s|^|$$NAME/|g; s| | $$NAME/|g" ` ;            \
   rm $$NAME
 
@@ -127,11 +128,12 @@ bump-version::
   NEW=`echo $$MINOR + 1 | bc` ;                                                    \
   NEW=`echo $$NEW | sed 's/^\([0-9]\)$$/0\1/'` ;                           \
   D=`date '+%d-%b-%Y'`;                                                            \
-  if [ ! -f xscreensaver-$$MAJOR.$$MINOR.tar.gz ]; then                            \
-    echo "WARNING: xscreensaver-$$MAJOR.$$MINOR.tar.gz does not exist.";    \
+  ADIR=archive/ ;                                                          \
+  if [ ! -f $${ADIR}xscreensaver-$$MAJOR.$$MINOR.tar.gz ]; then                    \
+   echo "WARNING: $${ADIR}xscreensaver-$$MAJOR.$$MINOR.tar.gz does not exist.";\
   fi ;                                                                     \
-  if [ -f xscreensaver-$$MAJOR.$$NEW.tar.gz ]; then                        \
-    echo "WARNING: xscreensaver-$$MAJOR.$$NEW.tar.gz already exists.";     \
+  if [ -f $${ADIR}xscreensaver-$$MAJOR.$$NEW.tar.gz ]; then                \
+    echo "WARNING: $${ADIR}xscreensaver-$$MAJOR.$$NEW.tar.gz already exists.";\
   fi ;                                                                     \
   echo -n "Bumping $$MAJOR.$$MINOR to $$MAJOR.$$NEW ($$D), ok? ";          \
   read line;                                                               \
@@ -171,10 +173,11 @@ rpm::
   VERS=`sed -n 's/[^0-9]*\([0-9]\.[0-9][0-9]*\).*/\1/p' utils/version.h` ; \
   DIR=`pwd`/rpm_build ;                                                           \
   ARCH=`rpm --showrc | sed -n 's/^build arch *: //p'` ;                           \
+  ADIR=archive/ ;                                                         \
   rm -rf $$DIR ;                                                          \
   mkdir $$DIR ;                                                                   \
   ( cd $$DIR; mkdir BUILD RPMS RPMS/$$ARCH SOURCES SPECS SRPMS ) ;        \
-  cp -p xscreensaver-$$VERS.tar.gz $$DIR/SOURCES/ ;                       \
+  cp -p $${ADIR}xscreensaver-$$VERS.tar.gz $$DIR/SOURCES/ ;               \
   rpm --define "_topdir $$DIR"                                            \
       --define "USE_GL yes"                                               \
       -v -ba xscreensaver.spec ;                                          \
@@ -193,7 +196,8 @@ test-tar::
        @                                                                   \
   VERS=`sed -n 's/[^0-9]*\([0-9]\.[0-9][0-9]*\).*/\1/p' utils/version.h` ;  \
   D=xscreensaver-$$VERS ;                                                  \
-  NAME="$$D.tar.gz" ;                                                      \
+  ADIR=archive/ ;                                                          \
+  NAME="$${ADIR}$$D.tar.gz" ;                                              \
   if [ ! -f $$NAME ]; then                                                 \
     echo "$$NAME does not exist!  Did you forget to \`make tar'?" ;        \
     exit 1 ;                                                               \
@@ -206,7 +210,7 @@ test-tar::
    chmod -R u+w $$D ;                                                      \
   fi ;                                                                     \
   rm -rf $$D ;                                                             \
-  zcat $$D.tar.gz | tar -xf - ;                                                    \
+  zcat $${ADIR}$$D.tar.gz | tar -xf - ;                                            \
   cd $$D ;                                                                 \
   chmod -R a-w . ;                                                         \
   chmod u+w . ;                                                                    \
@@ -242,7 +246,8 @@ www::
   DEST=$$HOME/www/xscreensaver ;                                           \
   VERS=`sed -n 's/[^0-9]*\([0-9]\.[0-9][0-9]*\).*/\1/p' utils/version.h` ;  \
   HEAD="xscreensaver-$$VERS" ;                                             \
-  NAME="$$HEAD.tar.gz" ;                                                   \
+  ADIR=archive/ ;                                                          \
+  NAME="$$ADIR$$HEAD.tar.gz" ;                                             \
                                                                            \
   if [ ! -f $$NAME ]; then                                                 \
     echo "$$NAME does not exist!  Did you forget to \`make tar'?" ;        \
diff --git a/README b/README
index cedca8ea16fb61670d3043972f03ae18a51960b7..f66639b2995b973a9a6df803ea6220a6e2df1d7d 100644 (file)
--- a/README
+++ b/README
@@ -71,6 +71,32 @@ http://www.jwz.org/xscreensaver/.
 
                               ============
 
+Changes since 3.32:   * New hacks, `speedmine' and `whirlygig'.
+                      * Sped up `pyro', made the explosions look a bit better.
+                      * Added better stars to `glplanet' and `starwars'.
+                      * Many internal changes to `webcollage'.
+                      * Some new options to `attraction'.
+                      * Minor fix to `noseguy' to avoid un-erased pixels.
+                      * Rewrote the screen-eraser effects so that they complete
+                        in the same amount of time regardless of how slow
+                        your X server is (some of them were glacial on servers
+                        with slow blitting.)
+                      * Fixed a potential free memory reference that could
+                        sometimes cause a crash at startup.
+                      * Possibly fixed a problem that could cause the daemon
+                        to crash with an X error.  I was never able to
+                        reproduce this problem, but I think I might have
+                        figured out what caused it.
+                      * Worked around a problem that caused PAM authentication
+                        to fail on some Red Hat 7.x systems.
+                      * Added a `memoryLimit' parameter that controls the
+                        amount of memory a graphics hack may allocate: if they
+                        try to allocate more than this, malloc() will fail
+                        (and they will exit or (safely) crash, rather than
+                        hogging memory.)  Default is 50M.
+                      * Made `gnome-help-browser' be the default way to display
+                        man pages in `xscreensaver-demo', if running on a 
+                        GNOME system.
 Changes since 3.31:   * The image-manipulating hacks (`slidescreen', etc.) can
                         now operate on randomly chosen image files from disk,
                         or on frames captured from the system's video input,
index ed31807e2c84348d3a3b9f5f2a7b3c32d3eebba9..e3d4afc284c8012bb848baffa537442e344baa6c 100644 (file)
 /* Define if you have the sigaction function.  */
 #undef HAVE_SIGACTION
 
+/* Define this if you have the setrlimit function. */
+#undef HAVE_SETRLIMIT
+
 /* Define if you have the <unistd.h> header file.  */
 #undef HAVE_UNISTD_H
 
index 24e782b956078f94da555c2e6034de847f412ba8..1eb09070c9a84de417f47589e1e20e4ad1762918 100755 (executable)
--- a/configure
+++ b/configure
@@ -2143,7 +2143,7 @@ fi
 done
 
 
-for ac_func in sigaction syslog realpath
+for ac_func in sigaction syslog realpath setrlimit
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
 echo "configure:2161: checking for $ac_func" >&5
@@ -6945,6 +6945,44 @@ EOF
 fi
 
 
+# Check for the Gnome Help Browser.
+#
+if test "$have_gnome" = yes; then
+  # Extract the first word of "gnome-help-browser", so it can be a program name with args.
+set dummy gnome-help-browser; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:6966: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_have_gnome_help'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$have_gnome_help"; then
+  ac_cv_prog_have_gnome_help="$have_gnome_help" # Let the user override the test.
+else
+  IFS="${IFS=  }"; ac_save_ifs="$IFS"; IFS=":"
+  ac_dummy="$PATH"
+  for ac_dir in $ac_dummy; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_have_gnome_help="yes"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_prog_have_gnome_help" && ac_cv_prog_have_gnome_help="no"
+fi
+fi
+have_gnome_help="$ac_cv_prog_have_gnome_help"
+if test -n "$have_gnome_help"; then
+  echo "$ac_t""$have_gnome_help" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+else
+  have_gnome_help=no
+fi
+
+
 ###############################################################################
 #
 #       Checking whether Motif is really Lesstif.
@@ -6954,7 +6992,7 @@ fi
 have_lesstif=no
 if test "$have_motif" = yes ; then
   echo $ac_n "checking whether Motif is really LessTif""... $ac_c" 1>&6
-echo "configure:6969: checking whether Motif is really LessTif" >&5
+echo "configure:7007: checking whether Motif is really LessTif" >&5
 if eval "test \"`echo '$''{'ac_cv_have_lesstif'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -6965,14 +7003,14 @@ else
   fi
   CPPFLAGS="$CPPFLAGS $X_CFLAGS"
   cat > conftest.$ac_ext <<EOF
-#line 6980 "configure"
+#line 7018 "configure"
 #include "confdefs.h"
 #include <Xm/Xm.h>
 int main() {
 long vers = LesstifVersion;
 ; return 0; }
 EOF
-if { (eval echo configure:6987: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:7025: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_have_lesstif=yes
 else
@@ -6997,7 +7035,7 @@ if test "$have_lesstif" = yes ; then
   ltv=unknown
   echo unknown > conftest-lt
   echo $ac_n "checking LessTif version number""... $ac_c" 1>&6
-echo "configure:7012: checking LessTif version number" >&5
+echo "configure:7050: checking LessTif version number" >&5
 if eval "test \"`echo '$''{'ac_cv_lesstif_version_string'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -7012,7 +7050,7 @@ else
                      ac_cv_lesstif_version_string=unknown
 else
   cat > conftest.$ac_ext <<EOF
-#line 7027 "configure"
+#line 7065 "configure"
 #include "confdefs.h"
 #include <stdio.h>
                      #include <Xm/Xm.h>
@@ -7025,7 +7063,7 @@ else
                        exit(0);
                      }
 EOF
-if { (eval echo configure:7040: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:7078: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ltv=`cat conftest-lt`
                      ac_cv_lesstif_version=`echo $ltv | sed 's/ .*//'`
@@ -7055,7 +7093,7 @@ if test "$have_motif" = yes ; then
   mtv=unknown
   echo unknown > conftest-mt
   echo $ac_n "checking Motif version number""... $ac_c" 1>&6
-echo "configure:7070: checking Motif version number" >&5
+echo "configure:7108: checking Motif version number" >&5
 if eval "test \"`echo '$''{'ac_cv_motif_version_string'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -7070,7 +7108,7 @@ else
                      ac_cv_motif_version_string=unknown
 else
   cat > conftest.$ac_ext <<EOF
-#line 7085 "configure"
+#line 7123 "configure"
 #include "confdefs.h"
 #include <stdio.h>
                      #include <Xm/Xm.h>
@@ -7083,7 +7121,7 @@ else
                        exit(0);
                      }
 EOF
-if { (eval echo configure:7098: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:7136: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   mtv=`cat conftest-mt`
                      ac_cv_motif_version=`echo $mtv | sed 's/ .*//'`
@@ -7127,7 +7165,7 @@ fi
 motif_requires_xpm=no
 if test "$have_motif" = yes ; then
    echo $ac_n "checking whether Motif requires XPM""... $ac_c" 1>&6
-echo "configure:7142: checking whether Motif requires XPM" >&5
+echo "configure:7180: checking whether Motif requires XPM" >&5
    if test "$motif_version" = "unknown" || test "$motif_version" -ge 2000
    then
      motif_requires_xpm=yes
@@ -7169,7 +7207,7 @@ if test "$have_motif" = yes ; then
   LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
 
   echo $ac_n "checking for XpQueryExtension in -lXp""... $ac_c" 1>&6
-echo "configure:7184: checking for XpQueryExtension in -lXp" >&5
+echo "configure:7222: checking for XpQueryExtension in -lXp" >&5
 ac_lib_var=`echo Xp'_'XpQueryExtension | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -7177,7 +7215,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lXp -lX11 -lXext -lm $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 7192 "configure"
+#line 7230 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -7188,7 +7226,7 @@ int main() {
 XpQueryExtension()
 ; return 0; }
 EOF
-if { (eval echo configure:7203: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7241: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -7242,7 +7280,7 @@ if test "$have_motif" = yes ; then
   LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
 
   echo $ac_n "checking for _Xsetlocale in -lXintl""... $ac_c" 1>&6
-echo "configure:7257: checking for _Xsetlocale in -lXintl" >&5
+echo "configure:7295: checking for _Xsetlocale in -lXintl" >&5
 ac_lib_var=`echo Xintl'_'_Xsetlocale | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -7250,7 +7288,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lXintl -lX11 -lXext -lm $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 7265 "configure"
+#line 7303 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -7261,7 +7299,7 @@ int main() {
 _Xsetlocale()
 ; return 0; }
 EOF
-if { (eval echo configure:7276: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7314: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -7318,7 +7356,7 @@ fi
 
     /*)
      echo $ac_n "checking for GL headers""... $ac_c" 1>&6
-echo "configure:7333: checking for GL headers" >&5
+echo "configure:7371: checking for GL headers" >&5
      d=$with_gl/include
      if test -d $d; then
        X_CFLAGS="-I$d $X_CFLAGS"
@@ -7328,7 +7366,7 @@ echo "configure:7333: checking for GL headers" >&5
      fi
 
      echo $ac_n "checking for GL libs""... $ac_c" 1>&6
-echo "configure:7343: checking for GL libs" >&5
+echo "configure:7381: checking for GL libs" >&5
      d=$with_gl/lib
      if test -d $d; then
        X_LIBS="-L$d $X_LIBS"
@@ -7364,17 +7402,17 @@ if test "$with_gl" = yes; then
   CPPFLAGS="$CPPFLAGS $X_CFLAGS"
   ac_safe=`echo "GL/gl.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for GL/gl.h""... $ac_c" 1>&6
-echo "configure:7379: checking for GL/gl.h" >&5
+echo "configure:7417: checking for GL/gl.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7384 "configure"
+#line 7422 "configure"
 #include "confdefs.h"
 #include <GL/gl.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7389: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:7427: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -7405,17 +7443,17 @@ fi
   CPPFLAGS="$CPPFLAGS $X_CFLAGS"
   ac_safe=`echo "GL/glx.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for GL/glx.h""... $ac_c" 1>&6
-echo "configure:7420: checking for GL/glx.h" >&5
+echo "configure:7458: checking for GL/glx.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7425 "configure"
+#line 7463 "configure"
 #include "confdefs.h"
 #include <GL/glx.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7430: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:7468: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -7447,7 +7485,7 @@ fi
     # to link against.
     #
     echo $ac_n "checking whether GL is really MesaGL""... $ac_c" 1>&6
-echo "configure:7462: checking whether GL is really MesaGL" >&5
+echo "configure:7500: checking whether GL is really MesaGL" >&5
 if eval "test \"`echo '$''{'ac_cv_have_mesa_gl'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -7459,7 +7497,7 @@ else
   fi
   CPPFLAGS="$CPPFLAGS $X_CFLAGS"
   cat > conftest.$ac_ext <<EOF
-#line 7474 "configure"
+#line 7512 "configure"
 #include "confdefs.h"
 #include <GL/glx.h>
 EOF
@@ -7488,7 +7526,7 @@ echo "$ac_t""$ac_cv_have_mesa_gl" 1>&6
     #
     if test "$ac_have_mesa_gl" = yes; then
       echo $ac_n "checking for pthread_create in -lpthread""... $ac_c" 1>&6
-echo "configure:7503: checking for pthread_create in -lpthread" >&5
+echo "configure:7541: checking for pthread_create in -lpthread" >&5
 ac_lib_var=`echo pthread'_'pthread_create | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -7496,7 +7534,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lpthread  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 7511 "configure"
+#line 7549 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -7507,7 +7545,7 @@ int main() {
 pthread_create()
 ; return 0; }
 EOF
-if { (eval echo configure:7522: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7560: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -7554,7 +7592,7 @@ fi
   LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
 
   echo $ac_n "checking for glXCreateContext in -lMesaGL""... $ac_c" 1>&6
-echo "configure:7569: checking for glXCreateContext in -lMesaGL" >&5
+echo "configure:7607: checking for glXCreateContext in -lMesaGL" >&5
 ac_lib_var=`echo MesaGL'_'glXCreateContext | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -7562,7 +7600,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lMesaGL -lMesaGLU $GL_LIBS -lX11 -lXext -lm $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 7577 "configure"
+#line 7615 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -7573,7 +7611,7 @@ int main() {
 glXCreateContext()
 ; return 0; }
 EOF
-if { (eval echo configure:7588: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7626: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -7619,7 +7657,7 @@ fi
   LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
 
   echo $ac_n "checking for glXCreateContext in -lGL""... $ac_c" 1>&6
-echo "configure:7634: checking for glXCreateContext in -lGL" >&5
+echo "configure:7672: checking for glXCreateContext in -lGL" >&5
 ac_lib_var=`echo GL'_'glXCreateContext | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -7627,7 +7665,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lGL -lGLU $GL_LIBS -lX11 -lXext -lm $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 7642 "configure"
+#line 7680 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -7638,7 +7676,7 @@ int main() {
 glXCreateContext()
 ; return 0; }
 EOF
-if { (eval echo configure:7653: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7691: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -7696,12 +7734,12 @@ EOF
     if test "$ac_have_mesa_gl" = yes; then
 
       echo $ac_n "checking MesaGL version number""... $ac_c" 1>&6
-echo "configure:7711: checking MesaGL version number" >&5
+echo "configure:7749: checking MesaGL version number" >&5
 if eval "test \"`echo '$''{'ac_cv_mesagl_version_string'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7716 "configure"
+#line 7754 "configure"
 #include "confdefs.h"
 #include <GL/gl.h>
 #ifndef MESA_MAJOR_VERSION
@@ -7772,7 +7810,7 @@ echo "$ac_t""$ac_cv_mesagl_version_string" 1>&6
   LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
 
   echo $ac_n "checking for glBindTexture in -l$gl_lib_1""... $ac_c" 1>&6
-echo "configure:7787: checking for glBindTexture in -l$gl_lib_1" >&5
+echo "configure:7825: checking for glBindTexture in -l$gl_lib_1" >&5
 ac_lib_var=`echo $gl_lib_1'_'glBindTexture | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -7780,7 +7818,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-l$gl_lib_1 $GL_LIBS -lX11 -lXext -lm $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 7795 "configure"
+#line 7833 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -7791,7 +7829,7 @@ int main() {
 glBindTexture()
 ; return 0; }
 EOF
-if { (eval echo configure:7806: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7844: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -7852,7 +7890,7 @@ fi
 
     /*)
      echo $ac_n "checking for GLE headers""... $ac_c" 1>&6
-echo "configure:7867: checking for GLE headers" >&5
+echo "configure:7905: checking for GLE headers" >&5
      d=$with_gle/include
      if test -d $d; then
        X_CFLAGS="-I$d $X_CFLAGS"
@@ -7862,7 +7900,7 @@ echo "configure:7867: checking for GLE headers" >&5
      fi
 
      echo $ac_n "checking for GLE libs""... $ac_c" 1>&6
-echo "configure:7877: checking for GLE libs" >&5
+echo "configure:7915: checking for GLE libs" >&5
      d=$with_gle/lib
      if test -d $d; then
        X_LIBS="-L$d $X_LIBS"
@@ -7898,17 +7936,17 @@ if test "$with_gle" = yes; then
   CPPFLAGS="$CPPFLAGS $X_CFLAGS"
   ac_safe=`echo "GL/gle.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for GL/gle.h""... $ac_c" 1>&6
-echo "configure:7913: checking for GL/gle.h" >&5
+echo "configure:7951: checking for GL/gle.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7918 "configure"
+#line 7956 "configure"
 #include "confdefs.h"
 #include <GL/gle.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7923: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:7961: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -7941,17 +7979,17 @@ fi
   CPPFLAGS="$CPPFLAGS $X_CFLAGS"
   ac_safe=`echo "GL/gutil.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for GL/gutil.h""... $ac_c" 1>&6
-echo "configure:7956: checking for GL/gutil.h" >&5
+echo "configure:7994: checking for GL/gutil.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7961 "configure"
+#line 7999 "configure"
 #include "confdefs.h"
 #include <GL/gutil.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7966: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:8004: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -7982,17 +8020,17 @@ fi
   CPPFLAGS="$CPPFLAGS $X_CFLAGS"
   ac_safe=`echo "GL/tube.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for GL/tube.h""... $ac_c" 1>&6
-echo "configure:7997: checking for GL/tube.h" >&5
+echo "configure:8035: checking for GL/tube.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 8002 "configure"
+#line 8040 "configure"
 #include "confdefs.h"
 #include <GL/tube.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8007: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:8045: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -8038,7 +8076,7 @@ fi
   LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
 
   echo $ac_n "checking for gleCreateGC in -lgle""... $ac_c" 1>&6
-echo "configure:8053: checking for gleCreateGC in -lgle" >&5
+echo "configure:8091: checking for gleCreateGC in -lgle" >&5
 ac_lib_var=`echo gle'_'gleCreateGC | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -8046,7 +8084,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lgle $GL_LIBS -lX11 -lXext -lm $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 8061 "configure"
+#line 8099 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -8057,7 +8095,7 @@ int main() {
 gleCreateGC()
 ; return 0; }
 EOF
-if { (eval echo configure:8072: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8110: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -8117,7 +8155,7 @@ fi
   LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
 
   echo $ac_n "checking for uview_direction in -lgle""... $ac_c" 1>&6
-echo "configure:8132: checking for uview_direction in -lgle" >&5
+echo "configure:8170: checking for uview_direction in -lgle" >&5
 ac_lib_var=`echo gle'_'uview_direction | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -8125,7 +8163,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lgle $GL_LIBS -lX11 -lXext -lm $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 8140 "configure"
+#line 8178 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -8136,7 +8174,7 @@ int main() {
 uview_direction()
 ; return 0; }
 EOF
-if { (eval echo configure:8151: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8189: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -8181,7 +8219,7 @@ fi
   LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
 
   echo $ac_n "checking for uview_direction_d in -lmatrix""... $ac_c" 1>&6
-echo "configure:8196: checking for uview_direction_d in -lmatrix" >&5
+echo "configure:8234: checking for uview_direction_d in -lmatrix" >&5
 ac_lib_var=`echo matrix'_'uview_direction_d | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -8189,7 +8227,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lmatrix $GL_LIBS -lX11 -lXext -lm $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 8204 "configure"
+#line 8242 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -8200,7 +8238,7 @@ int main() {
 uview_direction_d()
 ; return 0; }
 EOF
-if { (eval echo configure:8215: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8253: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -8273,7 +8311,7 @@ fi
 
     /*)
      echo $ac_n "checking for XPM headers""... $ac_c" 1>&6
-echo "configure:8288: checking for XPM headers" >&5
+echo "configure:8326: checking for XPM headers" >&5
      d=$with_xpm/include
      if test -d $d; then
        X_CFLAGS="-I$d $X_CFLAGS"
@@ -8283,7 +8321,7 @@ echo "configure:8288: checking for XPM headers" >&5
      fi
 
      echo $ac_n "checking for XPM libs""... $ac_c" 1>&6
-echo "configure:8298: checking for XPM libs" >&5
+echo "configure:8336: checking for XPM libs" >&5
      d=$with_xpm/lib
      if test -d $d; then
        X_LIBS="-L$d $X_LIBS"
@@ -8316,17 +8354,17 @@ if test "$with_xpm" = yes; then
   CPPFLAGS="$CPPFLAGS $X_CFLAGS"
   ac_safe=`echo "X11/xpm.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for X11/xpm.h""... $ac_c" 1>&6
-echo "configure:8331: checking for X11/xpm.h" >&5
+echo "configure:8369: checking for X11/xpm.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 8336 "configure"
+#line 8374 "configure"
 #include "confdefs.h"
 #include <X11/xpm.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8341: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:8379: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -8392,7 +8430,7 @@ fi
 
     /*)
      echo $ac_n "checking for XSHM headers""... $ac_c" 1>&6
-echo "configure:8407: checking for XSHM headers" >&5
+echo "configure:8445: checking for XSHM headers" >&5
      d=$with_xshm/include
      if test -d $d; then
        X_CFLAGS="-I$d $X_CFLAGS"
@@ -8402,7 +8440,7 @@ echo "configure:8407: checking for XSHM headers" >&5
      fi
 
      echo $ac_n "checking for XSHM libs""... $ac_c" 1>&6
-echo "configure:8417: checking for XSHM libs" >&5
+echo "configure:8455: checking for XSHM libs" >&5
      d=$with_xshm/lib
      if test -d $d; then
        X_LIBS="-L$d $X_LIBS"
@@ -8437,17 +8475,17 @@ if test "$with_xshm" = yes; then
   CPPFLAGS="$CPPFLAGS $X_CFLAGS"
   ac_safe=`echo "X11/extensions/XShm.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for X11/extensions/XShm.h""... $ac_c" 1>&6
-echo "configure:8452: checking for X11/extensions/XShm.h" >&5
+echo "configure:8490: checking for X11/extensions/XShm.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 8457 "configure"
+#line 8495 "configure"
 #include "confdefs.h"
 #include <X11/extensions/XShm.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8462: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:8500: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -8481,17 +8519,17 @@ fi
   CPPFLAGS="$CPPFLAGS $X_CFLAGS"
   ac_safe=`echo "sys/ipc.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for sys/ipc.h""... $ac_c" 1>&6
-echo "configure:8496: checking for sys/ipc.h" >&5
+echo "configure:8534: checking for sys/ipc.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 8501 "configure"
+#line 8539 "configure"
 #include "confdefs.h"
 #include <sys/ipc.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8506: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:8544: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -8526,17 +8564,17 @@ fi
   CPPFLAGS="$CPPFLAGS $X_CFLAGS"
   ac_safe=`echo "sys/shm.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for sys/shm.h""... $ac_c" 1>&6
-echo "configure:8541: checking for sys/shm.h" >&5
+echo "configure:8579: checking for sys/shm.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 8546 "configure"
+#line 8584 "configure"
 #include "confdefs.h"
 #include <sys/shm.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8551: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:8589: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -8588,7 +8626,7 @@ fi
   LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
 
   echo $ac_n "checking for XShmQueryExtension in -lXextSam""... $ac_c" 1>&6
-echo "configure:8603: checking for XShmQueryExtension in -lXextSam" >&5
+echo "configure:8641: checking for XShmQueryExtension in -lXextSam" >&5
 ac_lib_var=`echo XextSam'_'XShmQueryExtension | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -8596,7 +8634,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lXextSam -lX11 -lXext -lm $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 8611 "configure"
+#line 8649 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -8607,7 +8645,7 @@ int main() {
 XShmQueryExtension()
 ; return 0; }
 EOF
-if { (eval echo configure:8622: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8660: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -8674,7 +8712,7 @@ fi
 
     /*)
      echo $ac_n "checking for DOUBLE-BUFFER headers""... $ac_c" 1>&6
-echo "configure:8689: checking for DOUBLE-BUFFER headers" >&5
+echo "configure:8727: checking for DOUBLE-BUFFER headers" >&5
      d=$with_xdbe/include
      if test -d $d; then
        X_CFLAGS="-I$d $X_CFLAGS"
@@ -8684,7 +8722,7 @@ echo "configure:8689: checking for DOUBLE-BUFFER headers" >&5
      fi
 
      echo $ac_n "checking for DOUBLE-BUFFER libs""... $ac_c" 1>&6
-echo "configure:8699: checking for DOUBLE-BUFFER libs" >&5
+echo "configure:8737: checking for DOUBLE-BUFFER libs" >&5
      d=$with_xdbe/lib
      if test -d $d; then
        X_LIBS="-L$d $X_LIBS"
@@ -8718,17 +8756,17 @@ if test "$with_xdbe" = yes; then
   CPPFLAGS="$CPPFLAGS $X_CFLAGS"
   ac_safe=`echo "X11/extensions/Xdbe.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for X11/extensions/Xdbe.h""... $ac_c" 1>&6
-echo "configure:8733: checking for X11/extensions/Xdbe.h" >&5
+echo "configure:8771: checking for X11/extensions/Xdbe.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 8738 "configure"
+#line 8776 "configure"
 #include "confdefs.h"
 #include <X11/extensions/Xdbe.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8743: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:8781: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -8791,7 +8829,7 @@ fi
 
     /*)
      echo $ac_n "checking for XReadDisplay headers""... $ac_c" 1>&6
-echo "configure:8806: checking for XReadDisplay headers" >&5
+echo "configure:8844: checking for XReadDisplay headers" >&5
      d=$with_readdisplay/include
      if test -d $d; then
        X_CFLAGS="-I$d $X_CFLAGS"
@@ -8801,7 +8839,7 @@ echo "configure:8806: checking for XReadDisplay headers" >&5
      fi
 
      echo $ac_n "checking for XReadDisplay libs""... $ac_c" 1>&6
-echo "configure:8816: checking for XReadDisplay libs" >&5
+echo "configure:8854: checking for XReadDisplay libs" >&5
      d=$with_readdisplay/lib
      if test -d $d; then
        X_LIBS="-L$d $X_LIBS"
@@ -8834,17 +8872,17 @@ if test "$with_readdisplay" = yes; then
   CPPFLAGS="$CPPFLAGS $X_CFLAGS"
   ac_safe=`echo "X11/extensions/readdisplay.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for X11/extensions/readdisplay.h""... $ac_c" 1>&6
-echo "configure:8849: checking for X11/extensions/readdisplay.h" >&5
+echo "configure:8887: checking for X11/extensions/readdisplay.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 8854 "configure"
+#line 8892 "configure"
 #include "confdefs.h"
 #include <X11/extensions/readdisplay.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8859: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:8897: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -8911,7 +8949,7 @@ if test -n "$with_zippy_req" ; then
   case "$with_zippy_req" in
     /*)
       echo $ac_n "checking for $with_zippy_req""... $ac_c" 1>&6
-echo "configure:8926: checking for $with_zippy_req" >&5
+echo "configure:8964: checking for $with_zippy_req" >&5
       if test -x "$with_zippy_req" ; then
         echo "$ac_t""yes" 1>&6
       else
@@ -8925,7 +8963,7 @@ echo "configure:8926: checking for $with_zippy_req" >&5
       # Extract the first word of "$with_zippy_req", so it can be a program name with args.
 set dummy $with_zippy_req; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:8940: checking for $ac_word" >&5
+echo "configure:8978: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_zip2'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -8975,7 +9013,7 @@ do
 # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:8990: checking for $ac_word" >&5
+echo "configure:9028: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_emacs_exe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9009,7 +9047,7 @@ do
 # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:9024: checking for $ac_word" >&5
+echo "configure:9062: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_xemacs_exe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9044,7 +9082,7 @@ done
 
   if test -n "$emacs_exe" ; then
     echo $ac_n "checking for emacs yow""... $ac_c" 1>&6
-echo "configure:9059: checking for emacs yow" >&5
+echo "configure:9097: checking for emacs yow" >&5
     #
     # get emacs to tell us where the libexec directory is.
     #
@@ -9066,7 +9104,7 @@ echo "configure:9059: checking for emacs yow" >&5
 
   if test -z "$ac_cv_zippy_program" ; then
     echo $ac_n "checking for xemacs yow""... $ac_c" 1>&6
-echo "configure:9081: checking for xemacs yow" >&5
+echo "configure:9119: checking for xemacs yow" >&5
     if test -n "$xemacs_exe" ; then
       #
       # get xemacs to tell us where the libexec directory is.
@@ -9125,7 +9163,7 @@ do
 # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:9140: checking for $ac_word" >&5
+echo "configure:9178: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_fortune'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9161,7 +9199,7 @@ do
 # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:9176: checking for $ac_word" >&5
+echo "configure:9214: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_fortune'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9236,7 +9274,7 @@ fi
 
     /*)
      echo $ac_n "checking for setuid hacks headers""... $ac_c" 1>&6
-echo "configure:9251: checking for setuid hacks headers" >&5
+echo "configure:9289: checking for setuid hacks headers" >&5
      d=$setuid_hacks/include
      if test -d $d; then
        X_CFLAGS="-I$d $X_CFLAGS"
@@ -9246,7 +9284,7 @@ echo "configure:9251: checking for setuid hacks headers" >&5
      fi
 
      echo $ac_n "checking for setuid hacks libs""... $ac_c" 1>&6
-echo "configure:9261: checking for setuid hacks libs" >&5
+echo "configure:9299: checking for setuid hacks libs" >&5
      d=$setuid_hacks/lib
      if test -d $d; then
        X_LIBS="-L$d $X_LIBS"
@@ -9349,6 +9387,7 @@ fi
 tab='  '
 if test "$have_gl" = yes; then
   GL_EXES='$(GL_EXES)'
+  GL_UTIL_EXES='$(GL_UTIL_EXES)'
   GL_MEN='$(GL_MEN)'
   GL_KLUDGE="${tab}  "
 else
@@ -9364,6 +9403,17 @@ else
 fi
 
 
+# Another substitution in the XScreenSaver.ad.in file:
+#
+if test "$have_gnome_help" = yes; then
+  GNOMEHELP_Y=''
+  GNOMEHELP_N='!    '
+else
+  GNOMEHELP_Y='!    '
+  GNOMEHELP_N=''
+fi
+
+
 ###############################################################################
 #
 #       Perform substitutions and write Makefiles.
@@ -9404,6 +9454,9 @@ fi
 
 
 
+
+
+
 
 
 
@@ -9573,6 +9626,7 @@ s%@X_EXTRA_LIBS@%$X_EXTRA_LIBS%g
 s%@glib_config@%$glib_config%g
 s%@gtk_config@%$gtk_config%g
 s%@gnome_config@%$gnome_config%g
+s%@have_gnome_help@%$have_gnome_help%g
 s%@zip2@%$zip2%g
 s%@emacs_exe@%$emacs_exe%g
 s%@xemacs_exe@%$xemacs_exe%g
@@ -9605,11 +9659,14 @@ s%@SAVER_GL_LIBS@%$SAVER_GL_LIBS%g
 s%@LOCK_SRCS@%$LOCK_SRCS%g
 s%@LOCK_OBJS@%$LOCK_OBJS%g
 s%@GL_EXES@%$GL_EXES%g
+s%@GL_UTIL_EXES@%$GL_UTIL_EXES%g
 s%@GL_MEN@%$GL_MEN%g
 s%@GL_KLUDGE@%$GL_KLUDGE%g
 s%@GLE_EXES@%$GLE_EXES%g
 s%@GLE_MEN@%$GLE_MEN%g
 s%@GLE_KLUDGE@%$GLE_KLUDGE%g
+s%@GNOMEHELP_Y@%$GNOMEHELP_Y%g
+s%@GNOMEHELP_N@%$GNOMEHELP_N%g
 s%@HACKDIR@%$HACKDIR%g
 s%@GNOME_DATADIR@%$GNOME_DATADIR%g
 s%@APPDEFAULTS@%$APPDEFAULTS%g
 
 
 if test "$have_gl" = yes -a "$ac_have_mesa_gl" = yes ; then
-  preferred_mesagl=3.0
+  preferred_mesagl=3.4
+  mgv="$ac_mesagl_version_string"
+  pgl="$preferred_mesagl"
 
   if test "$ac_mesagl_version" = unknown; then
     warnL "Unable to determine the MesaGL version number!"
     warn2 "Make sure you are using version $preferred_mesagl or newer."
 
   elif test \! "$ac_mesagl_version" -gt 2006; then
-    warnL "MesaGL version $ac_mesagl_version_string is being used."
-    warn2 "MesaGL versions 2.6 and earlier have a security bug."
-    warn2 "It is strongly recommended that you upgrade to at"
-    warn2 "least version $preferred_mesagl."
+    warnL "MesaGL version $mgv is being used.  MesaGL 2.6 and earlier"
+    warn2 "have a security bug.  It is strongly recommended that you"
+    warn2 "upgrade to at least version $preferred_mesagl."
+
+  elif test \! "$ac_mesagl_version" -gt 3003; then
+    warnL "MesaGL version $mgv is being used.  That version has some"
+    warn2 "bugs; it is recommended that you upgrade to $pgl or newer."
   fi
 fi
 
index 9fbdfe306982b546950a86c456d8b9b19eec1551..82fbc0a63c0b6a533ade28c3e4d37d5ab3afdf34 100644 (file)
@@ -765,7 +765,7 @@ AC_HEADER_DIRENT
 AC_GETTIMEOFDAY_ARGS
 AC_CHECK_FUNCS(select fcntl uname nice setpriority getcwd getwd putenv)
 
-AC_CHECK_FUNCS(sigaction syslog realpath)
+AC_CHECK_FUNCS(sigaction syslog realpath setrlimit)
 AC_CHECK_ICMP
 AC_CHECK_ICMPHDR
 AC_CHECK_HEADERS(crypt.h sys/select.h)
@@ -1850,6 +1850,15 @@ if test "$with_gtk" = yes; then
 fi
 
 
+# Check for the Gnome Help Browser.
+#
+if test "$have_gnome" = yes; then
+  AC_CHECK_PROG(have_gnome_help, gnome-help-browser, yes, no)
+else
+  have_gnome_help=no
+fi
+
+
 ###############################################################################
 #
 #       Checking whether Motif is really Lesstif.
@@ -2635,6 +2644,7 @@ fi
 tab='  '
 if test "$have_gl" = yes; then
   GL_EXES='$(GL_EXES)'
+  GL_UTIL_EXES='$(GL_UTIL_EXES)'
   GL_MEN='$(GL_MEN)'
   GL_KLUDGE="${tab}  "
 else
@@ -2650,6 +2660,17 @@ else
 fi
 
 
+# Another substitution in the XScreenSaver.ad.in file:
+#
+if test "$have_gnome_help" = yes; then
+  GNOMEHELP_Y=''
+  GNOMEHELP_N='!    '
+else
+  GNOMEHELP_Y='!    '
+  GNOMEHELP_N=''
+fi
+
+
 ###############################################################################
 #
 #       Perform substitutions and write Makefiles.
@@ -2686,11 +2707,14 @@ AC_SUBST(SAVER_GL_LIBS)
 AC_SUBST(LOCK_SRCS)
 AC_SUBST(LOCK_OBJS)
 AC_SUBST(GL_EXES)
+AC_SUBST(GL_UTIL_EXES)
 AC_SUBST(GL_MEN)
 AC_SUBST(GL_KLUDGE)
 AC_SUBST(GLE_EXES)
 AC_SUBST(GLE_MEN)
 AC_SUBST(GLE_KLUDGE)
+AC_SUBST(GNOMEHELP_Y)
+AC_SUBST(GNOMEHELP_N)
 AC_SUBST(HACKDIR)
 AC_SUBST(GNOME_DATADIR)
 
@@ -2877,17 +2901,22 @@ fi
 
 
 if test "$have_gl" = yes -a "$ac_have_mesa_gl" = yes ; then
-  preferred_mesagl=3.0
+  preferred_mesagl=3.4
+  mgv="$ac_mesagl_version_string"
+  pgl="$preferred_mesagl"
 
   if test "$ac_mesagl_version" = unknown; then
     warnL "Unable to determine the MesaGL version number!"
     warn2 "Make sure you are using version $preferred_mesagl or newer."
 
   elif test \! "$ac_mesagl_version" -gt 2006; then
-    warnL "MesaGL version $ac_mesagl_version_string is being used."
-    warn2 "MesaGL versions 2.6 and earlier have a security bug."
-    warn2 "It is strongly recommended that you upgrade to at"
-    warn2 "least version $preferred_mesagl."
+    warnL "MesaGL version $mgv is being used.  MesaGL 2.6 and earlier"
+    warn2 "have a security bug.  It is strongly recommended that you"
+    warn2 "upgrade to at least version $preferred_mesagl."
+
+  elif test \! "$ac_mesagl_version" -gt 3003; then
+    warnL "MesaGL version $mgv is being used.  That version has some"
+    warn2 "bugs; it is recommended that you upgrade to $pgl or newer."
   fi
 fi
 
index c71601427b3f0075d32efe21bff185592668c855..060966aa2ab7ade0136c85df179ea60d1c01b97f 100644 (file)
@@ -245,10 +245,16 @@ install-program: $(EXES)
        fi ;                                                                  \
        echo $$inst xscreensaver $(install_prefix)$(bindir)/xscreensaver ;    \
        $$inst xscreensaver $(install_prefix)$(bindir)/xscreensaver
+       @echo $(INSTALL_PROGRAM) xscreensaver-command \
+         $(install_prefix)$(bindir)/xscreensaver-command ; \
        $(INSTALL_PROGRAM) xscreensaver-command \
          $(install_prefix)$(bindir)/xscreensaver-command
+       @echo $(INSTALL_PROGRAM) xscreensaver-demo \
+         $(install_prefix)$(bindir)/xscreensaver-demo ; \
        $(INSTALL_PROGRAM) xscreensaver-demo \
          $(install_prefix)$(bindir)/xscreensaver-demo
+       @echo $(INSTALL_PROGRAM) xscreensaver-getimage \
+         $(install_prefix)$(bindir)/xscreensaver-getimage ; \
        $(INSTALL_PROGRAM) xscreensaver-getimage \
          $(install_prefix)$(bindir)/xscreensaver-getimage
 
index e2d79ebd8e7416d4e62283152d7cf42a20885dca..5796f021ff31977009527c544967fbd9f4e3edb3 100644 (file)
@@ -4,8 +4,8 @@
 !            a screen saver and locker for the X window system
 !                            by Jamie Zawinski
 !
-!                              version 3.32
-!                              15-Apr-2001
+!                              version 3.33
+!                              03-Jun-2001
 !
 ! See "man xscreensaver" for more info.  The latest version is always
 ! available at http://www.jwz.org/xscreensaver/
@@ -41,6 +41,7 @@
 *chooseRandomImages:   False
 *imageDirectory:       
 *nice:                 10
+*memoryLimit:          50M
 *lock:                 False
 *lockVTs:              True
 *verbose:              False
 *loadURL: netscape -remote 'openURL(%s)' || netscape '%s'
 
 ! This is what the "Manual" button in xscreensaver-demo runs (/bin/sh syntax.)
-*manualCommand: xterm +sb -fg black -bg gray75 -T '%s manual' \
-        -e /bin/sh -c 'man "%s" || read foo'
-! Gnome folks might prefer this:
-!*manualCommand: gnome-help-browser 'man:%s'
+@GNOMEHELP_N@*manualCommand: xterm +sb -fg black -bg gray75 -T '%s manual' \
+@GNOMEHELP_N@        -e /bin/sh -c 'man "%s" || read foo'
+! For GNOME systems:
+@GNOMEHELP_Y@*manualCommand: gnome-help-browser 'man:%s'
 
 
 ! The format used for printing the date and time in the password dialog box
 -         "RotZoomer (mobile)" rotzoomer -root -move                       \n\
 -         "RotZoomer (sweep)"  rotzoomer -root -sweep                      \n\
                                whirlwindwarp -root                         \n\
+                   "WhirlyGig" whirlygig -root -nlines 20 -whirlies 40       \
+                                  -xspeed 0.5                              \n\
+                   "SpeedMine" speedmine -root                             \n\
+                   "SpeedWorm" speedmine -root -worm                       \n\
   color:                       bubbles -root                               \n\
   default-n:                   webcollage -root                            \n\
   default-n:  "WebCollage (whacked)"                                         \
 !    default-n:  "Slideshow"   xv -root -rmode 5 -random -viewonly           \
 !                                -wloop -wait 30 $HOME/bitmaps/*.jpg       \n\
 !
-! or, if you prefer "xli" to "xv", like this: (but note that xli's "-delay"
-! option doesn't work in conjunction with "-onroot", so you need to add a
-! line for each image individually... "xv" is better in this respect.)
-!
-!    default-n: xli -quiet -onroot -center -border black                     \
-!                $HOME/bitmaps/pic1.jpg                                    \n\
-!    default-n: xli -quiet -onroot -center -border black                     \
-!                $HOME/bitmaps/pic2.jpg                                    \n\
-!    default-n: xli -quiet -onroot -center -border black                     \
-!                $HOME/bitmaps/pic3.jpg                                    \n\
+! Recipes for using other slideshow programs can be found in the
+! XScreenSaver FAQ: http://www.jwz.org/xscreensaver/faq.html
 !
 ! Note that we've used "default-n" as the visual name, rather than just
 ! "default": this means "default visual, no install", that is, it's like
@@ -631,27 +628,19 @@ Written by Juergen Nickelsen and Jamie Zawinski.
 
 *hacks.slidescreen.name: SlideScreen
 *hacks.slidescreen.documentation:                                      \
-This grabs an image of whatever is on your screen, divides it into a   \
-grid, and then randomly shuffles the squares around as if it was one   \
-of those annoying ``16-puzzle'' games, where there is a grid of                \
-squares, one of which is missing.  I hate trying to solve those                \
-puzzles, but watching one permute itself is more amusing.  Written by  \
-Jamie Zawinski.
+This takes an image, divides it into a grid, and then randomly shuffles \
+the squares around as if it was one of those annoying ``16-puzzle''     \
+games, where there is a grid of squares, one of which is missing.       \
+I hate trying to solve those puzzles, but watching one permute itself   \
+is more amusing.  Written by Jamie Zawinski.
 
 *hacks.decayscreen.name: DecayScreen
 *hacks.decayscreen.documentation:                                      \
-This grabs an image of whatever is on your screen, and makes it melt.  \
-You've no doubt seen this effect before, but no screensaver would      \
-really be complete without it. It works best if there's something      \
-colorful visible.  Warning, if the effect continues after the screen   \
-saver is off, seek medical attention.  Written by David Wald and       \
-Vivek Khera.                                                           \
-                                                                   \n\n\
-A number of these screenhacks have the ability to take an image of     \
-your desktop and manipulate it in some way.  On SGI systems, these     \
-programs are able to (at random) pull their source image from the      \
-system's video input instead!  This works nicely if you leave some     \
-some random television station plugged in.
+This takes an image and makes it melt.  You've no doubt seen this       \
+effect before, but no screensaver would really be complete without it.  \
+It works best if there's something colorful visible.  Warning, if the   \
+effect continues after the screen saver is off, seek medical attention. \
+Written by David Wald and Vivek Khera.
 
 *hacks.jigsaw.documentation:                                           \
 This grabs a screen image, carves it up into a jigsaw puzzle,          \
@@ -1286,6 +1275,15 @@ files as input.  Written by Jamie Zawinski.
 Draws a ball that periodically extrudes many random spikes.  Ouch!   \
 Written by Jamie Zawinski.
 
+*hacks.whirlygig.name: WhirlyGig
+*hacks.whirlygig.documentation:                                     \
+Draws zooming chains of sinusoidal spots.  Written by Ashton Trey Belew.
+
+*hacks.speedmine.name: SpeedMine
+*hacks.speedmine.documentation:                                     \
+Simulates speeding down a rocky mineshaft, or a funky dancing worm. \
+Written by Conrad Parker.
+
 
 !=============================================================================
 !
index f45b5c87a140b00acc974b1b4156d3e089c388fc..b4ca0b27229c90a9322c769f3db7c27366435b19 100644 (file)
@@ -14,6 +14,7 @@
 "*chooseRandomImages:  False",
 "*imageDirectory:      ",
 "*nice:                        10",
+"*memoryLimit:         50M",
 "*lock:                        False",
 "*lockVTs:             True",
 "*verbose:             False",
@@ -38,8 +39,7 @@
 "*prefsCommand: xscreensaver-demo -prefs",
 "*helpURL: http://www.jwz.org/xscreensaver/man.html",
 "*loadURL: netscape -remote 'openURL(%s)' || netscape '%s'",
-"*manualCommand: xterm +sb -fg black -bg gray75 -T '%s manual' \
-        -e /bin/sh -c 'man \"%s\" || read foo'",
+"*manualCommand: gnome-help-browser 'man:%s'",
 "*dateFormat:          %d-%b-%y (%a); %I:%M %p",
 "*installColormap:     True",
 "*programs:                                                                  \
 -         \"RotZoomer (mobile)\" rotzoomer -root -move                     \\n\
 -         \"RotZoomer (sweep)\"  rotzoomer -root -sweep                            \\n\
                                whirlwindwarp -root                         \\n\
+                   \"WhirlyGig\"       whirlygig -root -nlines 20 -whirlies 40       \
+                                  -xspeed 0.5                              \\n\
+                   \"SpeedMine\"       speedmine -root                             \\n\
+                   \"SpeedWorm\"       speedmine -root -worm                       \\n\
   color:                       bubbles -root                               \\n\
   default-n:                   webcollage -root                            \\n\
   default-n:  \"WebCollage (whacked)\"                                       \
@@ -426,26 +430,18 @@ others tend to generate images that look like heat-maps or CAT-scans.     \
 Written by Juergen Nickelsen and Jamie Zawinski.",
 "*hacks.slidescreen.name: SlideScreen",
 "*hacks.slidescreen.documentation:                                     \
-This grabs an image of whatever is on your screen, divides it into a   \
-grid, and then randomly shuffles the squares around as if it was one   \
-of those annoying ``16-puzzle'' games, where there is a grid of                \
-squares, one of which is missing.  I hate trying to solve those                \
-puzzles, but watching one permute itself is more amusing.  Written by  \
-Jamie Zawinski.",
+This takes an image, divides it into a grid, and then randomly shuffles \
+the squares around as if it was one of those annoying ``16-puzzle''     \
+games, where there is a grid of squares, one of which is missing.       \
+I hate trying to solve those puzzles, but watching one permute itself   \
+is more amusing.  Written by Jamie Zawinski.",
 "*hacks.decayscreen.name: DecayScreen",
 "*hacks.decayscreen.documentation:                                     \
-This grabs an image of whatever is on your screen, and makes it melt.  \
-You've no doubt seen this effect before, but no screensaver would      \
-really be complete without it. It works best if there's something      \
-colorful visible.  Warning, if the effect continues after the screen   \
-saver is off, seek medical attention.  Written by David Wald and       \
-Vivek Khera.                                                           \
-                                                                   \\n\\n\
-A number of these screenhacks have the ability to take an image of     \
-your desktop and manipulate it in some way.  On SGI systems, these     \
-programs are able to (at random) pull their source image from the      \
-system's video input instead!  This works nicely if you leave some     \
-some random television station plugged in.",
+This takes an image and makes it melt.  You've no doubt seen this       \
+effect before, but no screensaver would really be complete without it.  \
+It works best if there's something colorful visible.  Warning, if the   \
+effect continues after the screen saver is off, seek medical attention. \
+Written by David Wald and Vivek Khera.",
 "*hacks.jigsaw.documentation:                                          \
 This grabs a screen image, carves it up into a jigsaw puzzle,          \
 shuffles it, and then solves the puzzle.  This works especially well   \
@@ -969,6 +965,13 @@ files as input.  Written by Jamie Zawinski.",
 "*hacks.dangerball.documentation:                                     \
 Draws a ball that periodically extrudes many random spikes.  Ouch!   \
 Written by Jamie Zawinski.",
+"*hacks.whirlygig.name: WhirlyGig",
+"*hacks.whirlygig.documentation:                                     \
+Draws zooming chains of sinusoidal spots.  Written by Ashton Trey Belew.",
+"*hacks.speedmine.name: SpeedMine",
+"*hacks.speedmine.documentation:                                     \
+Simulates speeding down a rocky mineshaft, or a funky dancing worm. \
+Written by Conrad Parker.",
 "*hacks.xdaliclock.name: XDaliClock",
 "*hacks.xdaliclock.documentation:                                      \
 XDaliClock draws a large digital clock, the numbers of which change by \
index 2f04b6f0ac34010823a1f30a93209babec4f6094..d4052b62bab295d6b88b4b272051cbbca8fc6a09 100644 (file)
@@ -2399,7 +2399,7 @@ main (int argc, char **argv)
 
 # else  /* !HAVE_CRAPPLET */
         fprintf (stderr, "%s: not compiled with --crapplet support\n",
-                 real_progname[i]);
+                 real_progname);
         USAGE ();
         exit (1);
 # endif /* !HAVE_CRAPPLET */
index 9e6a7194f3150424abfa87cd61dd87f04ee83d91..43f2cbc2cddbaa0ae0d9d6e3815f5ab99a91dc92 100644 (file)
@@ -1,7 +1,7 @@
 /* passwd-pam.c --- verifying typed passwords with PAM
  * (Pluggable Authentication Modules.)
  * written by Bill Nottingham <notting@redhat.com> (and jwz) for
- * xscreensaver, Copyright (c) 1993-1998, 2000 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1993-2001 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
@@ -55,6 +55,8 @@ extern char *blurb(void);
 
 #include <sys/stat.h>
 
+extern void block_sigchld (void);
+extern void unblock_sigchld (void);
 
 /* blargh */
 #undef  Bool
@@ -211,9 +213,31 @@ pam_passwd_valid_p (const char *typed_passwd, Bool verbose_p)
   }
 
   /* Try to authenticate as the current user.
+     We must turn off our SIGCHLD handler for the duration of the call to
+     pam_authenticate(), because in some cases, the underlying PAM code
+     will do this:
+
+        1: fork a setuid subprocess to do some dirty work;
+        2: read a response from that subprocess;
+        3: waitpid(pid, ...) on that subprocess.
+
+    If we (the ignorant parent process) have a SIGCHLD handler, then there's
+    a race condition between steps 2 and 3: if the subprocess exits before
+    waitpid() was called, then our SIGCHLD handler fires, and gets notified
+    of the subprocess death; then PAM's call to waitpid() fails, because the
+    process has already been reaped.
+
+    I consider this a bug in PAM, since the caller should be able to have
+    whatever signal handlers it wants -- the PAM documentation doesn't say
+    "oh by the way, if you use PAM, you can't use SIGCHLD."
    */
+
   PAM_NO_DELAY(pamh);
+
+  block_sigchld();
   status = pam_authenticate (pamh, 0);
+  unblock_sigchld();
+
   if (verbose_p)
     fprintf (stderr, "%s:   pam_authenticate (...) ==> %d (%s)\n",
              blurb(), status, PAM_STRERROR(pamh, status));
index 629b1b31196c824e4f8e6b19462eaab70dfb32a7..55b4653c08fcc93ba9d7ff6c3a9ab729c92281df 100644 (file)
@@ -192,6 +192,39 @@ init_file_tmp_name (void)
     return 0;
 }
 
+static int
+get_byte_resource (char *name, char *class)
+{
+  char *s = get_string_resource (name, class);
+  char *s2 = s;
+  int n = 0;
+  if (!s) return 0;
+
+  while (isspace(*s2)) s2++;
+  while (*s2 >= '0' && *s2 <= '9')
+    {
+      n = (n * 10) + (*s2 - '0');
+      s2++;
+    }
+  while (isspace(*s2)) s2++;
+  if      (*s2 == 'k' || *s2 == 'K') n <<= 10;
+  else if (*s2 == 'm' || *s2 == 'M') n <<= 20;
+  else if (*s2 == 'g' || *s2 == 'G') n <<= 30;
+  else if (*s2)
+    {
+    LOSE:
+      fprintf (stderr, "%s: %s must be a number of bytes, not \"%s\".\n",
+               progname, name, s);
+      return 0;
+    }
+  s2++;
+  if (*s2 == 'b' || *s2 == 'B') s2++;
+  while (isspace(*s2)) s2++;
+  if (*s2) goto LOSE;
+
+  return n;
+}
+
 
 static const char * const prefs[] = {
   "timeout",
@@ -211,6 +244,7 @@ static const char * const prefs[] = {
   "helpURL",
   "loadURL",
   "nice",
+  "memoryLimit",
   "fade",
   "unfade",
   "fadeSeconds",
@@ -687,7 +721,7 @@ write_init_file (saver_preferences *p, const char *version_string,
     {
       char buf[255];
       const char *pr = prefs[j];
-      enum pref_type { pref_str, pref_int, pref_bool, pref_time
+      enum pref_type { pref_str, pref_int, pref_bool, pref_byte, pref_time
       } type = pref_str;
       const char *s = 0;
       int i = 0;
@@ -724,6 +758,7 @@ write_init_file (saver_preferences *p, const char *version_string,
       CHECK("helpURL")         type = pref_str,  s = p->help_url;
       CHECK("loadURL")         type = pref_str,  s = p->load_url_command;
       CHECK("nice")            type = pref_int,  i = p->nice_inferior;
+      CHECK("memoryLimit")     type = pref_byte, i = p->inferior_memory_limit;
       CHECK("fade")            type = pref_bool, b = p->fade_p;
       CHECK("unfade")          type = pref_bool, b = p->unfade_p;
       CHECK("fadeSeconds")     type = pref_time, t = p->fade_seconds;
@@ -785,6 +820,19 @@ write_init_file (saver_preferences *p, const char *version_string,
            s = buf;
          }
          break;
+       case pref_byte:
+         {
+            if      (i >= (1<<30) && i == ((i >> 30) << 30))
+              sprintf(buf, "%dG", i >> 30);
+            else if (i >= (1<<20) && i == ((i >> 20) << 20))
+              sprintf(buf, "%dM", i >> 20);
+            else if (i >= (1<<10) && i == ((i >> 10) << 10))
+              sprintf(buf, "%dK", i >> 10);
+            else
+              sprintf(buf, "%d", i);
+            s = buf;
+          }
+         break;
        default:
          abort();
          break;
@@ -924,6 +972,7 @@ load_init_file (saver_preferences *p)
   p->fade_ticks            = get_integer_resource ("fadeTicks", "Integer");
   p->install_cmap_p = get_boolean_resource ("installColormap", "Boolean");
   p->nice_inferior  = get_integer_resource ("nice", "Nice");
+  p->inferior_memory_limit = get_byte_resource ("memoryLimit", "MemoryLimit");
   p->splash_p       = get_boolean_resource ("splash", "Boolean");
   p->capture_stderr_p = get_boolean_resource ("captureStderr", "Boolean");
 
@@ -1091,7 +1140,7 @@ merge_system_screenhacks (saver_preferences *p,
               made_space = 10;
               p->screenhacks = (screenhack **)
                 realloc (p->screenhacks,
-                         (p->screenhacks_count + made_space
+                         (p->screenhacks_count + made_space + 1)
                          * sizeof(screenhack));
               if (!p->screenhacks) abort();
             }
@@ -1102,6 +1151,7 @@ merge_system_screenhacks (saver_preferences *p,
           nh->command   = oh->command ? strdup(oh->command) : 0;
 
           p->screenhacks[p->screenhacks_count++] = nh;
+          p->screenhacks[p->screenhacks_count] = 0;
           made_space--;
 
 #if 0
@@ -1329,7 +1379,7 @@ format_hack (screenhack *hack, Bool wrap_p)
 static void
 get_screenhacks (saver_preferences *p)
 {
-  int i = 0;
+  int i, j;
   int start = 0;
   int end = 0;
   int size;
@@ -1362,15 +1412,14 @@ get_screenhacks (saver_preferences *p)
 
 
   /* Count up the number of newlines (which will be equal to or larger than
-     the number of hacks.)
+     one less than the number of hacks.)
    */
-  i = 0;
-  for (i = 0; d[i]; i++)
+  for (i = j = 0; d[i]; i++)
     if (d[i] == '\n')
-      i++;
-  i++;
+      j++;
+  j++;
 
-  p->screenhacks = (screenhack **) calloc (sizeof (screenhack *), i+1);
+  p->screenhacks = (screenhack **) calloc (j + 1, sizeof (screenhack *));
 
   /* Iterate over the lines in `d' (the string with newlines)
      and make new strings to stuff into the `screenhacks' array.
index 0ff0ff829ea7d1034778e38acee89d8b68cdad53..fb4cd1bd79fb7af1ad672efd97d40ce9d9b8e2d4 100644 (file)
@@ -58,6 +58,7 @@ struct saver_preferences {
   int screenhacks_count;
 
   int nice_inferior;           /* nice value for subprocs */
+  int inferior_memory_limit;   /* setrlimit(LIMIT_AS) value for subprocs */
 
   Time initial_delay;          /* how long to sleep after launch */
   Time splash_duration;                /* how long the splash screen stays up */
index fd4cef834fd13d4c56e88bca266d20a63ad1c7b3..465b03fd8b9f39d72ffb2022fae8cf86387845c5 100644 (file)
@@ -1,6 +1,5 @@
 /* subprocs.c --- choosing, spawning, and killing screenhacks.
- * xscreensaver, Copyright (c) 1991, 1992, 1993, 1995, 1997, 1998, 1999, 2000
- *  Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright (c) 1991-2001 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
 # include <sys/wait.h>         /* for waitpid() and associated macros */
 #endif
 
-#if defined(HAVE_SETPRIORITY) && defined(PRIO_PROCESS)
+#if (defined(HAVE_SETPRIORITY) && defined(PRIO_PROCESS)) || \
+     defined(HAVE_SETRLIMIT)
 # include <sys/resource.h>     /* for setpriority() and PRIO_PROCESS */
+                               /* and also setrlimit() and RLIMIT_AS */
 #endif
 
 #ifdef VMS
@@ -106,6 +107,64 @@ nice_subproc (int nice_level)
 }
 
 
+/* RLIMIT_AS (called RLIMIT_VMEM on some systems) controls the maximum size
+   of a process's address space, i.e., the maximal brk(2) and mmap(2) values.
+   Setting this lets you put a cap on how much memory a process can allocate.
+ */
+#if defined(RLIMIT_VMEM) && !defined(RLIMIT_AS)
+# define RLIMIT_AS RLIMIT_VMEM
+#endif
+
+static void
+limit_subproc_memory (int address_space_limit, Bool verbose_p)
+{
+#if defined(HAVE_SETRLIMIT) && defined(RLIMIT_AS)
+  struct rlimit r;
+
+  if (address_space_limit < 10 * 1024)  /* let's not be crazy */
+    return;
+
+  if (getrlimit (RLIMIT_AS, &r) != 0)
+    {
+      char buf [512];
+      sprintf (buf, "%s: getrlimit(RLIMIT_AS) failed", blurb());
+      perror (buf);
+      return;
+    }
+
+  r.rlim_cur = address_space_limit;
+
+  if (setrlimit (RLIMIT_AS, &r) != 0)
+    {
+      char buf [512];
+      sprintf (buf, "%s: setrlimit(RLIMIT_AS, {%d, %d}) failed",
+               blurb(), r.rlim_cur, r.rlim_max);
+      perror (buf);
+      return;
+    }
+
+  if (verbose_p)
+    {
+      int i = address_space_limit;
+      char buf[100];
+      if      (i >= (1<<30) && i == ((i >> 30) << 30))
+        sprintf(buf, "%dG", i >> 30);
+      else if (i >= (1<<20) && i == ((i >> 20) << 20))
+        sprintf(buf, "%dM", i >> 20);
+      else if (i >= (1<<10) && i == ((i >> 10) << 10))
+        sprintf(buf, "%dK", i >> 10);
+      else
+        sprintf(buf, "%d bytes", i);
+
+      fprintf (stderr, "%s: limited pid %lu address space to %s.\n",
+               blurb(), (unsigned long) getpid (), buf);
+    }
+
+#endif /* HAVE_SETRLIMIT && RLIMIT_AS */
+}
+
+
+
 #ifndef VMS
 
 static void
@@ -475,7 +534,7 @@ static void describe_dead_child (saver_info *, pid_t, int wait_status);
 static int block_sigchld_handler = 0;
 
 
-static void
+void
 block_sigchld (void)
 {
 #ifdef HAVE_SIGACTION
@@ -488,7 +547,7 @@ block_sigchld (void)
   block_sigchld_handler++;
 }
 
-static void
+void
 unblock_sigchld (void)
 {
 #ifdef HAVE_SIGACTION
@@ -878,6 +937,7 @@ spawn_screenhack_1 (saver_screen_info *ssi, Bool first_time_p)
        case 0:
          close (ConnectionNumber (si->dpy));   /* close display fd */
          nice_subproc (p->nice_inferior);      /* change process priority */
+         limit_subproc_memory (p->inferior_memory_limit, p->verbose_p);
          hack_subproc_environment (ssi);       /* set $DISPLAY */
          exec_screenhack (si, hack->command);  /* this does not return */
          abort();
index d810b4924d32e934de1d62ddc3e0c271ef8c8be2..f2fdb24b9119205df6d5d850fcb0fbe52788b156 100644 (file)
@@ -243,14 +243,25 @@ cycle_timer (XtPointer closure, XtIntervalId *id)
         }
     }
 
-  si->cycle_id = XtAppAddTimeOut (si->app, how_long, cycle_timer,
-                                 (XtPointer) si);
+  if (how_long > 0)
+    {
+      si->cycle_id = XtAppAddTimeOut (si->app, how_long, cycle_timer,
+                                      (XtPointer) si);
 
-#ifdef DEBUG_TIMERS
-  if (p->verbose_p)
-    fprintf (stderr, "%s: starting cycle_timer (%ld, %ld)\n",
-           blurb(), how_long, si->cycle_id);
-#endif /* DEBUG_TIMERS */
+# ifdef DEBUG_TIMERS
+      if (p->verbose_p)
+        fprintf (stderr, "%s: starting cycle_timer (%ld, %ld)\n",
+                 blurb(), how_long, si->cycle_id);
+# endif /* DEBUG_TIMERS */
+    }
+# ifdef DEBUG_TIMERS
+  else
+    {
+      if (p->verbose_p)
+        fprintf (stderr, "%s: not starting cycle_timer: how_long == %d\n",
+                 blurb(), how_long);
+    }
+# endif /* DEBUG_TIMERS */
 }
 
 
index 29e046190fed02b12ece386ba3a496c2c3d875bf..471a8a7c049f6df7b377bbaa66a2040a987a403a 100644 (file)
@@ -68,6 +68,8 @@ Atom XA_SCREENSAVER_STATUS;
 
 extern saver_info *global_si_kludge;   /* I hate C so much... */
 
+static void maybe_transfer_grabs (saver_screen_info *ssi,
+                                  Window old_w, Window new_w);
 
 #define ALL_POINTER_EVENTS \
        (ButtonPressMask | ButtonReleaseMask | EnterWindowMask | \
@@ -957,6 +959,80 @@ get_screen_viewport (saver_screen_info *ssi,
 }
 
 
+static Bool error_handler_hit_p = False;
+
+static int
+ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error)
+{
+  error_handler_hit_p = True;
+  return 0;
+}
+
+
+/* Returns True if successful, False if an X error occurred.
+   We need this because other programs might have done things to
+   our window that will cause XChangeWindowAttributes() to fail:
+   if that happens, we give up, destroy the window, and re-create
+   it.
+ */
+static Bool
+safe_XChangeWindowAttributes (Display *dpy, Window window,
+                              unsigned long mask,
+                              XSetWindowAttributes *attrs)
+{
+  XErrorHandler old_handler;
+  XSync (dpy, False);
+  error_handler_hit_p = False;
+  old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
+
+  XChangeWindowAttributes (dpy, window, mask, attrs);
+
+  XSync (dpy, False);
+  XSetErrorHandler (old_handler);
+  XSync (dpy, False);
+
+  return (!error_handler_hit_p);
+}
+
+
+/* This might not be necessary, but just in case. */
+static Bool
+safe_XConfigureWindow (Display *dpy, Window window,
+                       unsigned long mask, XWindowChanges *changes)
+{
+  XErrorHandler old_handler;
+  XSync (dpy, False);
+  error_handler_hit_p = False;
+  old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
+
+  XConfigureWindow (dpy, window, mask, changes);
+
+  XSync (dpy, False);
+  XSetErrorHandler (old_handler);
+  XSync (dpy, False);
+
+  return (!error_handler_hit_p);
+}
+
+/* This might not be necessary, but just in case. */
+static Bool
+safe_XDestroyWindow (Display *dpy, Window window)
+{
+  XErrorHandler old_handler;
+  XSync (dpy, False);
+  error_handler_hit_p = False;
+  old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
+
+  XDestroyWindow (dpy, window);
+
+  XSync (dpy, False);
+  XSetErrorHandler (old_handler);
+  XSync (dpy, False);
+
+  return (!error_handler_hit_p);
+}
+
+
 static void
 initialize_screensaver_window_1 (saver_screen_info *ssi)
 {
@@ -974,6 +1050,7 @@ initialize_screensaver_window_1 (saver_screen_info *ssi)
   unsigned long attrmask;
   int x, y, width, height;
   static Bool printed_visual_info = False;  /* only print the message once. */
+  Window horked_window = 0;
 
   get_screen_viewport (ssi, &x, &y, &width, &height,
                        (p->verbose_p && !si->screen_blanked_p));
@@ -1113,12 +1190,17 @@ initialize_screensaver_window_1 (saver_screen_info *ssi)
       changes.height = height;
       changes.border_width = 0;
 
-      XConfigureWindow (si->dpy, ssi->screensaver_window,
-                       changesmask, &changes);
-      XChangeWindowAttributes (si->dpy, ssi->screensaver_window,
-                              attrmask, &attrs);
+      if (! (safe_XConfigureWindow (si->dpy, ssi->screensaver_window,
+                                  changesmask, &changes) &&
+             safe_XChangeWindowAttributes (si->dpy, ssi->screensaver_window,
+                                           attrmask, &attrs)))
+        {
+          horked_window = ssi->screensaver_window;
+          ssi->screensaver_window = 0;
+        }
     }
-  else
+
+  if (!ssi->screensaver_window)
     {
       ssi->screensaver_window =
        XCreateWindow (si->dpy, RootWindowOfScreen (ssi->screen),
@@ -1127,6 +1209,17 @@ initialize_screensaver_window_1 (saver_screen_info *ssi)
                       ssi->current_visual, attrmask, &attrs);
 
       reset_stderr (ssi);
+
+      if (horked_window)
+        {
+          fprintf (stderr,
+            "%s: someone horked our saver window (0x%lx)!  Recreating it...\n",
+                   blurb(), (unsigned long) horked_window);
+          maybe_transfer_grabs (ssi, horked_window, ssi->screensaver_window);
+          safe_XDestroyWindow (si->dpy, horked_window);
+          horked_window = 0;
+        }
+
       if (p->verbose_p)
        fprintf (stderr, "%s: saver window is 0x%lx.\n",
                 blurb(), (unsigned long) ssi->screensaver_window);
@@ -1450,6 +1543,47 @@ unblank_screen (saver_info *si)
 }
 
 
+/* Transfer any grabs from the old window to the new.
+   Actually I think none of this is necessary, since we always
+   hold our grabs on the root window, but I wrote this before
+   re-discovering that...
+ */
+static void
+maybe_transfer_grabs (saver_screen_info *ssi,
+                      Window old_w, Window new_w)
+{
+  saver_info *si = ssi->global;
+
+  /* If the old window held our mouse grab, transfer the grab to the new
+     window.  (Grab the server while so doing, to avoid a race condition.)
+   */
+  if (old_w == si->mouse_grab_window)
+    {
+      XGrabServer (si->dpy);           /* ############ DANGER! */
+      ungrab_mouse (si);
+      grab_mouse (si, ssi->screensaver_window,
+                  (si->demoing_p
+                   ? 0
+                   : ssi->cursor));
+      XUngrabServer (si->dpy);
+      XSync (si->dpy, False);          /* ###### (danger over) */
+    }
+
+  /* If the old window held our keyboard grab, transfer the grab to the new
+     window.  (Grab the server while so doing, to avoid a race condition.)
+   */
+  if (old_w == si->keyboard_grab_window)
+    {
+      XGrabServer (si->dpy);           /* ############ DANGER! */
+      ungrab_kbd(si);
+      grab_kbd(si, ssi->screensaver_window);
+      XUngrabServer (si->dpy);
+      XSync (si->dpy, False);          /* ###### (danger over) */
+    }
+}
+
+
+
 Bool
 select_visual (saver_screen_info *ssi, const char *visual_name)
 {
@@ -1538,45 +1672,10 @@ select_visual (saver_screen_info *ssi, const char *visual_name)
       store_vroot_property (si->dpy,
                            ssi->screensaver_window, ssi->screensaver_window);
 
+      /* Transfer any grabs from the old window to the new. */
+      maybe_transfer_grabs (ssi, old_w, ssi->screensaver_window);
 
-      /* Transfer the grabs from the old window to the new.
-        Actually I think none of this is necessary, since we always
-        hold our grabs on the root window, but I wrote this before
-        re-discovering that...
-       */
-
-
-      /* If we're destroying the window that holds our mouse grab,
-        transfer the grab to the new window.  (Grab the server while
-        so doing, to avoid a race condition.)
-       */
-      if (old_w == si->mouse_grab_window)
-       {
-         XGrabServer (si->dpy);                /* ############ DANGER! */
-         ungrab_mouse (si);
-         grab_mouse (si, ssi->screensaver_window,
-                     (si->demoing_p
-                      ? 0
-                      : ssi->cursor));
-         XUngrabServer (si->dpy);
-         XSync (si->dpy, False);               /* ###### (danger over) */
-       }
-
-      /* If we're destroying the window that holds our keyboard grab,
-        transfer the grab to the new window.  (Grab the server while
-        so doing, to avoid a race condition.)
-       */
-      if (old_w == si->keyboard_grab_window)
-       {
-         XGrabServer (si->dpy);                /* ############ DANGER! */
-         ungrab_kbd(si);
-         grab_kbd(si, ssi->screensaver_window);
-         XUngrabServer (si->dpy);
-         XSync (si->dpy, False);               /* ###### (danger over) */
-       }
-
-      /* Now we can destroy this window without horking our grabs. */
-
+      /* Now we can destroy the old window without horking our grabs. */
       XDestroyWindow (si->dpy, old_w);
 
       if (p->verbose_p)
index 25befb7e43d4ebccc7adcfb05eccc1a2d79c54e7..ae8535f9c8642c2d086dbcbc02f7d2fa6e1ef062 100644 (file)
@@ -11,7 +11,7 @@
 .if n .sp 1
 .if t .sp .5
 ..
-.TH XScreenSaver 1 "15-Apr-2001 (3.32)" "X Version 11"
+.TH XScreenSaver 1 "03-Jun-2001 (3.33)" "X Version 11"
 .SH NAME
 xscreensaver-command - control a running xscreensaver process
 .SH SYNOPSIS
index 01767bfbf8be746527eef42519e395f439185c70..b074e6288f9eb0be239f505aeaec2b00bef4e9ea 100644 (file)
@@ -11,7 +11,7 @@
 .if n .sp 1
 .if t .sp .5
 ..
-.TH XScreenSaver 1 "15-Apr-2001 (3.32)" "X Version 11"
+.TH XScreenSaver 1 "03-Jun-2001 (3.33)" "X Version 11"
 .SH NAME
 xscreensaver-demo - interactively control the background xscreensaver daemon
 .SH SYNOPSIS
index 0766d9ed91acedbe19fb7d9383b9b71f7e6586fd..402b1439dc413607c8dce4222e853efb2a222217 100755 (executable)
@@ -32,7 +32,7 @@ use Fcntl;
 
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my $version = q{ $Revision: 1.4 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
+my $version = q{ $Revision: 1.5 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
 
 my $verbose = 0;
 
@@ -133,7 +133,7 @@ sub find_random_file {
 
   @all_files = sort(@all_files);
 
-  my $n = int (rand ($#all_files));
+  my $n = int (rand ($#all_files + 1));
   my $file = $all_files[$n];
 
   print STDERR "$progname: chose file $n: $file\n" if ($verbose > 1);
index beaf7b1250361806e6e7e9be4524279ddd95716c..c4322793cd8ae072de1d06ba2380a2e29d149c03 100644 (file)
@@ -1,4 +1,4 @@
-.TH XScreenSaver 1 "15-Apr-2001 (3.32)" "X Version 11"
+.TH XScreenSaver 1 "03-Jun-2001 (3.33)" "X Version 11"
 .SH NAME
 xscreensaver-getimage-file - put a randomly-selected image on the root window
 .SH SYNOPSIS
index 8539b4d02125756853b5df5fd99d307b567dc81d..54ca89621f15ea320dc965d0130c7e878dffc10d 100644 (file)
@@ -1,4 +1,4 @@
-.TH XScreenSaver 1 "15-Apr-2001 (3.32)" "X Version 11"
+.TH XScreenSaver 1 "03-Jun-2001 (3.33)" "X Version 11"
 .SH NAME
 xscreensaver-getimage-video - put a video frame on the root window
 .SH SYNOPSIS
index 04232ee74939991fac3d683c8d195622049b75de..7e6c10033ab99e1e051b79ea7616c298ea7de1fa 100644 (file)
@@ -1,4 +1,4 @@
-.TH XScreenSaver 1 "15-Apr-2001 (3.32)" "X Version 11"
+.TH XScreenSaver 1 "03-Jun-2001 (3.33)" "X Version 11"
 .SH NAME
 xscreensaver-getimage - put some randomly-selected image on the root window
 .SH SYNOPSIS
index 08838dfa90d2b3c7b97677d1da02945635c3d413..63a63c83da2360cdc70ff06e59bb905210abeb57 100644 (file)
@@ -292,16 +292,27 @@ int
 saver_ehandler (Display *dpy, XErrorEvent *error)
 {
   saver_info *si = global_si_kludge;   /* I hate C so much... */
+  int i;
 
   if (!real_stderr) real_stderr = stderr;
 
   fprintf (real_stderr, "\n"
           "#######################################"
           "#######################################\n\n"
-          "%s: X Error!  PLEASE REPORT THIS BUG.\n\n"
-          "#######################################"
-          "#######################################\n\n",
+          "%s: X Error!  PLEASE REPORT THIS BUG.\n",
           blurb());
+
+  for (i = 0; i < si->nscreens; i++)
+    fprintf (real_stderr, "%s: screen %d: 0x%x, 0x%x, 0x%x\n",
+             blurb(), i,
+             RootWindowOfScreen (si->screens[i].screen),
+             si->screens[i].real_vroot,
+             si->screens[i].screensaver_window);
+
+  fprintf (real_stderr, "\n"
+          "#######################################"
+          "#######################################\n\n");
+
   if (XmuPrintDefaultErrorMessage (dpy, error, real_stderr))
     {
       fprintf (real_stderr, "\n");
@@ -1176,9 +1187,12 @@ main (int argc, char **argv)
  */
 
 
+static Bool error_handler_hit_p = False;
+
 static int
 ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error)
 {
+  error_handler_hit_p = True;
   return 0;
 }
 
@@ -1194,11 +1208,13 @@ XGetAtomName_safe (Display *dpy, Atom atom)
   if (!atom) return 0;
 
   XSync (dpy, False);
+  error_handler_hit_p = False;
   old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
   result = XGetAtomName (dpy, atom);
   XSync (dpy, False);
   XSetErrorHandler (old_handler);
   XSync (dpy, False);
+  if (error_handler_hit_p) result = 0;
 
   if (result)
     return result;
@@ -1219,6 +1235,8 @@ clientmessage_response (saver_info *si, Window w, Bool error,
   char *proto;
   int L;
   saver_preferences *p = &si->prefs;
+  XErrorHandler old_handler;
+
   if (error || p->verbose_p)
     fprintf (stderr, "%s: %s\n", blurb(), stderr_msg);
 
@@ -1228,9 +1246,23 @@ clientmessage_response (saver_info *si, Window w, Bool error,
   strcpy (proto+1, protocol_msg);
   L++;
 
+  /* Ignore all X errors while sending a response to a ClientMessage.
+     Pretty much the only way we could get an error here is if the
+     window we're trying to send the reply on has been deleted, in
+     which case, the sender of the ClientMessage won't see our response
+     anyway.
+   */
+  XSync (si->dpy, False);
+  error_handler_hit_p = False;
+  old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
+
   XChangeProperty (si->dpy, w, XA_SCREENSAVER_RESPONSE, XA_STRING, 8,
                   PropModeReplace, (unsigned char *) proto, L);
+
+  XSync (si->dpy, False);
+  XSetErrorHandler (old_handler);
   XSync (si->dpy, False);
+
   free (proto);
 }
 
index b6e27974160d3c92c86efa402f4e5308a7151b58..c5bef700536a8218e8d459de159767d85be8e97c 100644 (file)
@@ -366,6 +366,8 @@ extern void maybe_reload_init_file (saver_info *);
    subprocs
    ======================================================================= */
 
+extern void block_sigchld (void);
+extern void unblock_sigchld (void);
 extern void hack_environment (saver_info *si);
 extern void hack_subproc_environment (saver_screen_info *ssi);
 extern void init_sigchld (void);
index 9d33a72ec955d6a459ee4fb61faa3abe2cac482c..b2042e8cc838f30b97fed99dd3241e3b3298dcd3 100644 (file)
@@ -11,7 +11,7 @@
 .if n .sp 1
 .if t .sp .5
 ..
-.TH XScreenSaver 1 "15-Apr-2001 (3.32)" "X Version 11"
+.TH XScreenSaver 1 "03-Jun-2001 (3.33)" "X Version 11"
 .SH NAME
 xscreensaver - graphics hack and screen locker, launched when the user is idle
 .SH SYNOPSIS
@@ -283,6 +283,21 @@ system, and don't increase the load unnecessarily.  The default is 10.
 .BR nice (1)
 for details.)
 .TP 8
+.B memoryLimit\fP (class \fBMemoryLimit\fP)
+The sub-processes created by \fIxscreensaver\fP will not be allowed to
+allocate more than this much memory (more accurately, this is the maximum
+size their address space may become.)  If any sub-process tries to allocate
+more than this,
+.BR malloc (3)
+will fail, and the process will likely exit (or safely crash) rather than
+going forth and hogging memory.  
+
+The assumption here is that if one of the screenhacks is trying to use
+a lot of memory, then something has gone wrong, and it's better to kill
+that program than to overload the machine.
+
+Default: 50M.
+.TP 8
 .B fade\fP (class \fBBoolean\fP)
 If this is true, then when the screensaver activates, the current contents
 of the screen will fade to black instead of simply winking out.  This only
@@ -328,8 +343,21 @@ When the screensaver starts up, one of these is selected at random, and
 run.  After the \fIcycle\fP period expires, it is killed, and another
 is selected and run.
 
-If the value of this resource is empty, then no programs will be run; the
-screen will simply be made black.
+If a line begins with a dash (-) then that particular program is
+disabled: it won't be selected at random (though you can still select
+it explicitly using the
+.BR xscreensaver\-demo (1)
+program.)
+
+If all programs are disabled, then the screen will just be made blank.
+
+To disable a program, it's better to mark it as disabled with a dash
+than to remove it from the list.  This is because the system-wide
+(app-defaults) and per-user (.xscreensaver) settings are merged
+together, and if a user just \fIdeletes\fP an entry from their programs
+list, but that entry still exists in the system-wide list, then it will
+come back.  However, if the user \fIdisables\fP it, then their setting
+takes precedence.
 
 If the display has multiple screens, then a different program will be run
 for each screen.  (All screens are blanked and unblanked simultaniously.)
index e0586ed011604726701a634d002bc8e37e6144d4..eb00f72bf08620e4d2b4cef1ea7e44b8aea34348 100644 (file)
@@ -89,7 +89,7 @@ SRCS          = attraction.c blitspin.c bouboule.c braid.c bubbles.c \
                  phosphor.c xmatrix.c petri.c shadebobs.c xsublim.c ccurve.c \
                  blaster.c bumps.c ripples.c xteevee.c xspirograph.c \
                  nerverot.c xrayswarm.c hyperball.c zoom.c whirlwindwarp.c \
-                 rotzoomer.c
+                 rotzoomer.c whirlygig.c speedmine.c
 SCRIPTS                = vidwhacker webcollage
 
 OBJS           = attraction.o blitspin.o bouboule.o braid.o bubbles.o \
@@ -110,7 +110,7 @@ OBJS                = attraction.o blitspin.o bouboule.o braid.o bubbles.o \
                  phosphor.o xmatrix.o petri.o shadebobs.o xsublim.o ccurve.o \
                  blaster.o bumps.o ripples.o xteevee.o xspirograph.o \
                  nerverot.o xrayswarm.o hyperball.o zoom.o whirlwindwarp.o \
-                 rotzoomer.o
+                 rotzoomer.o whirlygig.o speedmine.o
 
 NEXES          = attraction blitspin bouboule braid bubbles decayscreen deco \
                  drift flag flame forest vines galaxy grav greynetic halo \
@@ -124,7 +124,8 @@ NEXES               = attraction blitspin bouboule braid bubbles decayscreen deco \
                  demon loop t3d penetrate deluxe compass squiral xflame \
                  wander spotlight critical phosphor xmatrix petri shadebobs \
                  xsublim ccurve blaster bumps ripples xteevee xspirograph \
-                 nerverot xrayswarm hyperball zoom whirlwindwarp rotzoomer
+                 nerverot xrayswarm hyperball zoom whirlwindwarp rotzoomer \
+                 whirlygig speedmine
 SEXES          = sonar
 EXES           = $(NEXES) $(SEXES)
 
@@ -154,7 +155,7 @@ MEN         = attraction.man blitspin.man bouboule.man braid.man \
                  vidwhacker.man webcollage.man xsublim.man distort.man \
                  phosphor.man xmatrix.man xteevee.man xflame.man petri.man \
                  nerverot.man zoom.man whirlwindwarp.man hyperball.man \
-                 rotzoomer.man
+                 rotzoomer.man whirlygig.man speedmine.man
 STAR           = *
 EXTRAS         = README Makefile.in xlock_23.h .gdbinit \
                  images/$(STAR).xbm \
@@ -602,6 +603,12 @@ whirlwindwarp:     whirlwindwarp.o $(HACK_OBJS) $(COL)
 rotzoomer:     rotzoomer.o     $(HACK_OBJS) $(GRAB) $(SHM)
        $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(GRAB) $(SHM) $(HACK_LIBS)
 
+whirlygig:     whirlygig.o     $(HACK_OBJS) $(COL)
+       $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(COL) $(HACK_LIBS)
+
+speedmine:     speedmine.o     $(HACK_OBJS) $(COL)
+       $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(COL) $(HACK_LIBS)
+
 
 # The rules for those hacks which follow the `xlockmore' API.
 #
@@ -1088,4 +1095,8 @@ whirlwindwarp.o: $(srcdir)/screenhack.h
 whirlwindwarp.o: ../config.h
 rotzoomer.o: $(srcdir)/screenhack.h
 rotzoomer.o: ../config.h
+whirlygig.o: $(srcdir)/screenhack.h
+whirlygig.o: ../config.h
+speedmine.o: $(srcdir)/screenhack.h
+speedmine.o: ../config.h
 
index 1a84833b80fb89a86becee326877b31260961108..397aae389b7956ec35eaf76a27779a5211bc6139 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1997, 1998
+/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1997, 1998, 2001
  *  Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
 
    John sez:
 
-   The simulation started out as a purely accurate gravitational simulation,
-   but, with constant simulation step size, I quickly realized the field being
-   simulated while grossly gravitational was, in fact, non-conservative.  It
-   also had the rather annoying behavior of dealing very badly with colliding
-   orbs.  Therefore, I implemented a negative-gravity region (with two
-   thresholds; as I read your code, you only implemented one) to prevent orbs
-   from every coming too close together, and added a viscosity factor if the
-   speed of any orb got too fast.  This provides a nice stable system with
-   interesting behavior.
-
-   I had experimented with a number of fields including the van der Waals
-   force (very interesting orbiting behavior) and 1/r^3 gravity (not as
-   interesting as 1/r^2).  An even normal viscosity (rather than the
-   thresholded version to bleed excess energy) is also not interesting.
-   The 1/r^2, -1/r^2, -10/r^2 thresholds proved not only robust but also
-   interesting -- the orbs never collided and the threshold viscosity fixed
-   the non-conservational problem.
+       The simulation started out as a purely accurate gravitational
+       simulation, but, with constant simulation step size, I quickly
+       realized the field being simulated while grossly gravitational
+       was, in fact, non-conservative.  It also had the rather annoying
+       behavior of dealing very badly with colliding orbs.  Therefore,
+       I implemented a negative-gravity region (with two thresholds; as
+       I read your code, you only implemented one) to prevent orbs from
+       every coming too close together, and added a viscosity factor if
+       the speed of any orb got too fast.  This provides a nice stable
+       system with interesting behavior.
+
+       I had experimented with a number of fields including the van der
+       Waals force (very interesting orbiting behavior) and 1/r^3
+       gravity (not as interesting as 1/r^2).  An even normal viscosity
+       (rather than the thresholded version to bleed excess energy) is
+       also not interesting.  The 1/r^2, -1/r^2, -10/r^2 thresholds
+       proved not only robust but also interesting -- the orbs never
+       collided and the threshold viscosity fixed the
+       non-conservational problem.
 
    Philip sez:
-   > An even normal viscosity (rather than the thresholded version to
-   > bleed excess energy) is also not interesting.
+       > An even normal viscosity (rather than the thresholded version to
+       > bleed excess energy) is also not interesting.
 
-   unless you make about 200 points.... set the viscosity to about .8
-   and drag the mouse through it.   it makes a nice wave which travels
-   through the field.
+       unless you make about 200 points.... set the viscosity to about .8
+       and drag the mouse through it.   it makes a nice wave which travels
+       through the field.
 
    And (always the troublemaker) Joe Keane <jgk@jgk.org> sez:
 
-   Despite what John sez, the field being simulated is always conservative.
-   The real problem is that it uses a simple hack, computing acceleration
-   *based only on the starting position*, instead of a real differential
-   equation solver.  Thus you'll always have energy coming out of nowhere,
-   although it's most blatant when balls get close together.  If it were
-   done right, you wouldn't need viscosity or artificial limits on how
-   close the balls can get.
- */
+       Despite what John sez, the field being simulated is always
+       conservative.  The real problem is that it uses a simple hack,
+       computing acceleration *based only on the starting position*,
+       instead of a real differential equation solver.  Thus you'll
+       always have energy coming out of nowhere, although it's most
+       blatant when balls get close together.  If it were done right,
+       you wouldn't need viscosity or artificial limits on how close
+       the balls can get.
+
+   Matt <straitm@carleton.edu> sez:
+
+       Added a switch to remove the walls.
+
+       Added a switch to make the threshold viscosity optional.  If
+       nomaxspeed is specified, then balls going really fast do not
+       recieve special treatment.
+
+       I've made tail mode prettier by eliminating the first erase line
+       that drew from the upper left corner to the starting position of
+       each point.
+
+       Made the balls in modes other than "balls" bounce exactly at the
+       walls.  (Because the graphics for different modes are drawn
+       differently with respect to the "actual" position of the point,
+       they used to be able to run somewhat past the walls, or bounce
+       before hitting them.)
+
+       Added an option to output each ball's speed in the form of a bar
+       graph drawn on the same window as the balls.  If only x or y is
+       selected, they will be represented on the appropriate axis down
+       the center of the window.  If both are selected, they will both
+       be displayed along the diagonal such that the x and y bars for
+       each point start at the same place.  If speed is selected, the
+       speed will be displayed down the left side.  */
 
 #include <stdio.h>
 #include <math.h>
@@ -70,6 +98,9 @@ struct ball {
 };
 
 static struct ball *balls;
+static double *x_vels;
+static double *y_vels;
+static double *speeds;
 static int npoints;
 static int threshold;
 static int delay;
@@ -77,12 +108,16 @@ static int global_size;
 static int segments;
 static Bool glow_p;
 static Bool orbit_p;
+static Bool walls_p;
+static Bool maxspeed_p;
+static Bool cbounce_p;
 static XPoint *point_stack;
 static int point_stack_size, point_stack_fp;
 static XColor *colors;
 static int ncolors;
 static int fg_index;
 static int color_shift;
+Bool no_erase_yet; /* for tail mode fix */
 
 /*flip mods for mouse interaction*/
 static Bool mouse_p;
@@ -94,10 +129,15 @@ static enum object_mode {
   tail_mode
 } mode;
 
+static enum graph_mode {
+  graph_none, graph_x, graph_y, graph_both, graph_speed
+} graph_mode;
+
 static GC draw_gc, erase_gc;
 
+/* The normal (and max) width for a graph bar */
+#define BAR_SIZE 11
 #define MAX_SIZE 16
-
 #define min(a,b) ((a)<(b)?(a):(b))
 #define max(a,b) ((a)>(b)?(a):(b))
 
@@ -110,32 +150,51 @@ init_balls (Display *dpy, Window window)
   int xlim, ylim, midx, midy, r, vx, vy;
   double th;
   Colormap cmap;
-  char *mode_str;
+  char *mode_str, *graph_mode_str;
+
   XGetWindowAttributes (dpy, window, &xgwa);
   xlim = xgwa.width;
   ylim = xgwa.height;
   cmap = xgwa.colormap;
   midx = xlim/2;
   midy = ylim/2;
+  walls_p = get_boolean_resource ("walls", "Boolean");
+
+  /* if there aren't walls, don't set a limit on the radius */
   r = get_integer_resource ("radius", "Integer");
-  if (r <= 0 || r > min (xlim/2, ylim/2))
+  if (r <= 0 || (r > min (xlim/2, ylim/2) && walls_p) )
     r = min (xlim/2, ylim/2) - 50;
+
   vx = get_integer_resource ("vx", "Integer");
   vy = get_integer_resource ("vy", "Integer");
+
   npoints = get_integer_resource ("points", "Integer");
   if (npoints < 1)
     npoints = 3 + (random () % 5);
   balls = (struct ball *) malloc (npoints * sizeof (struct ball));
+
+  no_erase_yet = 1; /* for tail mode fix */
+
   segments = get_integer_resource ("segments", "Integer");
   if (segments < 0) segments = 1;
+
   threshold = get_integer_resource ("threshold", "Integer");
   if (threshold < 0) threshold = 0;
+
   delay = get_integer_resource ("delay", "Integer");
-    if (delay < 0) delay = 0;
+  if (delay < 0) delay = 0;
+
   global_size = get_integer_resource ("size", "Integer");
   if (global_size < 0) global_size = 0;
+
   glow_p = get_boolean_resource ("glow", "Boolean");
+
   orbit_p = get_boolean_resource ("orbit", "Boolean");
+
+  maxspeed_p = get_boolean_resource ("maxspeed", "Boolean");
+
+  cbounce_p = get_boolean_resource ("cbounce", "Boolean");
+
   color_shift = get_integer_resource ("colorShift", "Integer");
   if (color_shift <= 0) color_shift = 5;
 
@@ -148,12 +207,12 @@ init_balls (Display *dpy, Window window)
 
   mode_str = get_string_resource ("mode", "Mode");
   if (! mode_str) mode = ball_mode;
-  else if (!strcmp (mode_str, "balls")) mode = ball_mode;
-  else if (!strcmp (mode_str, "lines")) mode = line_mode;
-  else if (!strcmp (mode_str, "polygons")) mode = polygon_mode;
-  else if (!strcmp (mode_str, "tails")) mode = tail_mode;
-  else if (!strcmp (mode_str, "splines")) mode = spline_mode;
-  else if (!strcmp (mode_str, "filled-splines")) mode = spline_filled_mode;
+  else if (!strcmp (mode_str, "balls"))        mode = ball_mode;
+  else if (!strcmp (mode_str, "lines"))        mode = line_mode;
+  else if (!strcmp (mode_str, "polygons"))     mode = polygon_mode;
+  else if (!strcmp (mode_str, "tails"))        mode = tail_mode;
+  else if (!strcmp (mode_str, "splines"))      mode = spline_mode;
+  else if (!strcmp (mode_str, "filled-splines"))mode = spline_filled_mode;
   else {
     fprintf (stderr,
             "%s: mode must be balls, lines, tails, polygons, splines, or\n\
@@ -162,6 +221,31 @@ init_balls (Display *dpy, Window window)
     exit (1);
   }
 
+  graph_mode_str = get_string_resource ("graphmode", "Mode");
+  if (! graph_mode_str) graph_mode = graph_none;
+  else if (!strcmp (graph_mode_str, "x"))      graph_mode = graph_x;
+  else if (!strcmp (graph_mode_str, "y"))      graph_mode = graph_y;
+  else if (!strcmp (graph_mode_str, "both"))   graph_mode = graph_both;
+  else if (!strcmp (graph_mode_str, "speed"))  graph_mode = graph_speed;
+  else if (!strcmp (graph_mode_str, "none"))   graph_mode = graph_none;
+  else {
+    fprintf (stderr,
+        "%s: graphmode must be speed, x, y, both, or none, not \"%s\"\n",
+        progname, graph_mode_str);
+    exit (1);
+  }
+
+  /* only allocate memory if it is needed */
+  if(graph_mode != graph_none)
+  {
+    if(graph_mode == graph_x || graph_mode == graph_both)
+      x_vels = (double *) malloc (npoints * sizeof (double));
+    if(graph_mode == graph_y || graph_mode == graph_both)
+      y_vels = (double *) malloc (npoints * sizeof (double));
+    if(graph_mode == graph_speed)
+      speeds = (double *) malloc (npoints * sizeof (double));
+  }
+
   if (mode != ball_mode && mode != tail_mode) glow_p = False;
   
   if (mode == polygon_mode && npoints < 3)
@@ -270,6 +354,20 @@ init_balls (Display *dpy, Window window)
        balls [i].pixel_index = random() % ncolors;
     }
 
+  /*  This lets modes where the points don't really have any size use the whole
+      window.  Otherwise, since the points still have a positive size
+      assigned to them, they will be bounced somewhat early.  Mass and size are
+      seperate, so this shouldn't cause problems.  It's a bit kludgy, tho.
+  */
+  if(mode == line_mode || mode == spline_mode || 
+     mode == spline_filled_mode || mode == polygon_mode)
+    {
+       for(i = 1; i < npoints; i++)
+         {
+               balls[i].size = 0;
+          }
+     }
+    
   if (orbit_p)
     {
       double a = 0;
@@ -306,6 +404,7 @@ init_balls (Display *dpy, Window window)
     }
 
   if (mono_p) glow_p = False;
+
   XClearWindow (dpy, window);
 }
 
@@ -362,17 +461,195 @@ compute_force (int i, double *dx_ret, double *dy_ret)
     }
 }
 
+
+/* Draws meters along the diagonal for the x velocity */
+static void 
+draw_meter_x(Display *dpy, Window window, GC draw_gc,
+             struct ball *balls, int i, int alone) 
+{
+  XWindowAttributes xgwa;
+  int x1,x2,y,w1,w2,h;
+  XGetWindowAttributes (dpy, window, &xgwa);
+
+  /* set the width of the bars to use */
+  if(xgwa.height < BAR_SIZE*npoints)
+    {
+      y = i*(xgwa.height/npoints);
+      h = (xgwa.height/npoints) - 2;
+    }
+  else
+    {
+      y = BAR_SIZE*i;
+      h = BAR_SIZE - 2;
+    }
+  
+  if(alone)
+    {
+      x1 = xgwa.width/2;
+      x2 = x1;
+    }
+  else
+    {
+      x1 = i*(h+2);
+      if(x1 < i) 
+        x1 = i;
+      x2 = x1;
+    }
+
+  if(y<1) y=i;  
+  if(h<1) h=1;
+
+  w1 = (int)(20*x_vels[i]);
+  w2 = (int)(20*balls[i].vx);
+  x_vels[i] = balls[i].vx; 
+
+  if (w1<0) {
+    w1=-w1;
+    x1=x1-w1;
+  }
+  if (w2<0) {
+    w2=-w2;
+    x2=x2-w2;
+  }
+  XDrawRectangle(dpy,window,erase_gc,x1+(h+2)/2,y,w1,h);
+  XDrawRectangle(dpy,window,draw_gc,x2+(h+2)/2,y,w2,h);
+}
+
+/* Draws meters along the diagonal for the y velocity.
+   Is there some way to make draw_meter_x and draw_meter_y 
+   one function instead of two without making them completely unreadable?
+*/
+static void 
+draw_meter_y (Display *dpy, Window window, GC draw_gc,
+              struct ball *balls, int i, int alone) 
+{
+  XWindowAttributes xgwa;
+  int y1,y2,x,h1,h2,w;
+  XGetWindowAttributes (dpy, window, &xgwa);
+
+  if(xgwa.height < BAR_SIZE*npoints){  /*needs to be height still */
+    x = i*(xgwa.height/npoints);
+    w = (xgwa.height/npoints) - 2;
+  }
+  else{
+    x = BAR_SIZE*i;
+    w = BAR_SIZE - 2;
+  }
+
+  if(alone)
+    {
+      y1 = xgwa.height/2;
+      y2 = y1;
+    }
+  else
+    {
+      y1 = i*(w+2);
+      if(y1 < i)
+        y1 = i;
+      y2 = y1;
+    }
+
+  if(x < 1) x = i;  
+  if(w < 1) w = 1;
+
+  h1 = (int)(20*y_vels[i]);
+  h2 = (int)(20*balls[i].vy);
+  y_vels[i] = balls[i].vy; 
+
+  if (h1<0) {
+    h1=-h1;
+    y1=y1-h1;
+  }
+  if (h2<0) {
+    h2=-h2;
+    y2=y2-h2;
+  }
+  XDrawRectangle(dpy,window,erase_gc,x,y1+(w+2)/2,w,h1);
+  XDrawRectangle(dpy,window,draw_gc,x,y2+(w+2)/2,w,h2);
+}
+
+
+/* Draws meters of the total speed of the balls */
+static void
+draw_meter_speed (Display *dpy, Window window, GC draw_gc, 
+                  struct ball *balls, int i) 
+{
+  XWindowAttributes xgwa;
+  int y,x1,x2,h,w1,w2;
+  XGetWindowAttributes (dpy, window, &xgwa);
+
+  if(xgwa.height < BAR_SIZE*npoints)
+    {
+      y = i*(xgwa.height/npoints);
+      h = (xgwa.height/npoints) - 2;
+    }
+  else{
+    y = BAR_SIZE*i;
+    h = BAR_SIZE - 2;
+  }
+
+  x1 = 0;
+  x2 = x1;
+
+  if(y < 1) y = i;  
+  if(h < 1) h = 1;
+
+  w1 = (int)(5*speeds[i]);
+  w2 = (int)(5*(balls[i].vy*balls[i].vy+balls[i].vx*balls[i].vx));
+  speeds[i] =    balls[i].vy*balls[i].vy+balls[i].vx*balls[i].vx;
+
+  XDrawRectangle(dpy,window,erase_gc,x1,y,w1,h);
+  XDrawRectangle(dpy,window,draw_gc, x2,y,w2,h);
+}
+
 static void
-run_balls (Display *dpy, Window window)
+run_balls (Display *dpy, Window window, int total_ticks)
 {
   int last_point_stack_fp = point_stack_fp;
   static int tick = 500, xlim, ylim;
   static Colormap cmap;
-  int i;
-
-  /*flip mods for mouse interaction*/
-  Window  root1, child1;
+  
+  Window root1, child1;  /*flip mods for mouse interaction*/
   unsigned int mask;
+
+  int i, radius = global_size/2;
+  if(global_size == 0)
+    radius = (MAX_SIZE / 3);
+
+  if(graph_mode != graph_none)
+    {
+      if(graph_mode == graph_both)
+       {
+          for(i = 0; i < npoints; i++)
+            {
+              draw_meter_x(dpy,window,draw_gc, balls, i, 0);
+              draw_meter_y(dpy,window,draw_gc, balls, i, 0);
+            }
+       }
+      else if(graph_mode == graph_x)
+       {
+          for(i = 0; i < npoints; i++)
+            {
+              draw_meter_x(dpy,window,draw_gc, balls, i, 1);
+            }
+       }
+      else if(graph_mode == graph_y)
+       {
+          for(i = 0; i < npoints; i++)
+            {
+              draw_meter_y(dpy,window,draw_gc, balls, i, 1);
+            }
+       }
+      else if(graph_mode == graph_speed)
+       {
+          for(i = 0; i < npoints; i++)
+            {
+              draw_meter_speed(dpy,window,draw_gc, balls, i);
+            }
+       }
+
+    }
+
   if (mouse_p)
     {
       XQueryPointer(dpy, window, &root1, &child1,
@@ -403,9 +680,13 @@ run_balls (Display *dpy, Window window)
       balls[i].vx += balls[i].dx;
       balls[i].vy += balls[i].dy;
 
-      /* don't let them get too fast: impose a terminal velocity
-         (actually, make the medium have friction) */
-      if (balls[i].vx > 10)
+      /* "don't let them get too fast: impose a terminal velocity
+         (actually, make the medium have friction)"
+        Well, what this first step really does is give the medium a 
+        viscosity of .9 for balls going over the speed limit.  Anyway, 
+        this is now optional
+      */
+      if (balls[i].vx > 10 && maxspeed_p)
        {
          balls[i].vx *= 0.9;
          balls[i].dx = 0;
@@ -415,7 +696,7 @@ run_balls (Display *dpy, Window window)
          balls[i].vx *= viscosity;
        }
 
-      if (balls[i].vy > 10)
+      if (balls[i].vy > 10 && maxspeed_p)
        {
          balls[i].vy *= 0.9;
          balls[i].dy = 0;
@@ -428,32 +709,70 @@ run_balls (Display *dpy, Window window)
       balls[i].x += balls[i].vx;
       balls[i].y += balls[i].vy;
 
-      /* bounce off the walls */
-      if (balls[i].x >= (xlim - balls[i].size))
-       {
-         balls[i].x = (xlim - balls[i].size - 1);
-         if (balls[i].vx > 0)
-           balls[i].vx = -balls[i].vx;
-       }
-      if (balls[i].y >= (ylim - balls[i].size))
-       {
-         balls[i].y = (ylim - balls[i].size - 1);
-         if (balls[i].vy > 0)
-           balls[i].vy = -balls[i].vy;
-       }
-      if (balls[i].x <= 0)
-       {
-         balls[i].x = 0;
-         if (balls[i].vx < 0)
-           balls[i].vx = -balls[i].vx;
-       }
-      if (balls[i].y <= 0)
-       {
-         balls[i].y = 0;
-         if (balls[i].vy < 0)
-           balls[i].vy = -balls[i].vy;
-       }
 
+      /* bounce off the walls if desired
+        note: a ball is actually its upper left corner */
+      if(walls_p)
+       {
+         if(cbounce_p)  /* with correct bouncing */
+           {
+              /* so long as it's out of range, keep bouncing */
+       
+              while( (balls[i].x >= (xlim - balls[i].size)) ||
+                     (balls[i].y >= (ylim - balls[i].size)) ||
+                     (balls[i].x <= 0) ||
+                     (balls[i].y <= 0) )
+                {
+                  if (balls[i].x >= (xlim - balls[i].size))
+                    {
+                      balls[i].x = (2*(xlim - balls[i].size) - balls[i].x);
+                      balls[i].vx = -balls[i].vx;
+                    }
+                  if (balls[i].y >= (ylim - balls[i].size))
+                    {
+                      balls[i].y = (2*(ylim - balls[i].size) - balls[i].y);
+                      balls[i].vy = -balls[i].vy;
+                    }
+                  if (balls[i].x <= 0)
+                    {
+                      balls[i].x = -balls[i].x;
+                     balls[i].vx = -balls[i].vx;
+                    }
+                  if (balls[i].y <= 0)
+                    {
+                      balls[i].y = -balls[i].y;
+                     balls[i].vy = -balls[i].vy;
+                    }
+                }
+            }
+          else  /* with old bouncing */
+            {
+              if (balls[i].x >= (xlim - balls[i].size))
+                {
+                  balls[i].x = (xlim - balls[i].size - 1);
+                  if (balls[i].vx > 0) /* why is this check here? */
+                    balls[i].vx = -balls[i].vx;
+                }
+              if (balls[i].y >= (ylim - balls[i].size))
+                {
+                  balls[i].y = (ylim - balls[i].size - 1);
+                  if (balls[i].vy > 0)
+                    balls[i].vy = -balls[i].vy;
+                }
+              if (balls[i].x <= 0)
+                {
+                  balls[i].x = 0;
+                  if (balls[i].vx < 0)
+                    balls[i].vx = -balls[i].vx;
+                }
+              if (balls[i].y <= 0)
+                {
+                  balls[i].y = 0;
+                  if (balls[i].vy < 0)
+                    balls[i].vy = -balls[i].vy;
+                }
+            }
+        }
       new_x = balls[i].x;
       new_y = balls[i].y;
 
@@ -545,12 +864,26 @@ run_balls (Display *dpy, Window window)
          {
            int index = point_stack_fp + i;
            int next_index = (index + (npoints + 1)) % point_stack_size;
-           XDrawLine (dpy, window, erase_gc,
-                      point_stack [index].x,
-                      point_stack [index].y,
-                      point_stack [next_index].x,
-                      point_stack [next_index].y);
-
+            if(no_erase_yet == 1)
+             {
+               if(total_ticks >= segments)
+                  {
+                    no_erase_yet = 0;
+                    XDrawLine (dpy, window, erase_gc,
+                              point_stack [index].x + radius,
+                              point_stack [index].y + radius,
+                              point_stack [next_index].x + radius,
+                              point_stack [next_index].y + radius);
+                  }
+             }
+           else
+             {
+               XDrawLine (dpy, window, erase_gc,
+                           point_stack [index].x + radius,
+                           point_stack [index].y + radius,
+                           point_stack [next_index].x + radius,
+                           point_stack [next_index].y + radius);
+             }
            index = last_point_stack_fp + i;
            next_index = (index - (npoints + 1)) % point_stack_size;
            if (next_index < 0) next_index += point_stack_size;
@@ -558,10 +891,10 @@ run_balls (Display *dpy, Window window)
                point_stack [next_index].y == 0)
              continue;
            XDrawLine (dpy, window, draw_gc,
-                      point_stack [index].x,
-                      point_stack [index].y,
-                      point_stack [next_index].x,
-                      point_stack [next_index].y);
+                      point_stack [index].x + radius,
+                      point_stack [index].y + radius,
+                      point_stack [next_index].x + radius,
+                      point_stack [next_index].y + radius);
          }
       }
       break;
@@ -615,6 +948,7 @@ char *defaults [] = {
   ".background:        black",
   ".foreground:        white",
   "*mode:      balls",
+  "*graphmode:  none",
   "*points:    0",
   "*size:      0",
   "*colors:    200",
@@ -622,6 +956,9 @@ char *defaults [] = {
   "*delay:     10000",
   "*glow:      false",
   "*mouseSize: 10",
+  "*walls:     true",
+  "*maxspeed:  true",
+  "*cbounce:   true",
   "*mouse:     false",
   "*viscosity: 1",
   "*orbit:     false",
@@ -633,6 +970,7 @@ char *defaults [] = {
 
 XrmOptionDescRec options [] = {
   { "-mode",           ".mode",        XrmoptionSepArg, 0 },
+  { "-graphmode",      ".graphmode",   XrmoptionSepArg, 0 },
   { "-colors",         ".colors",      XrmoptionSepArg, 0 },
   { "-points",         ".points",      XrmoptionSepArg, 0 },
   { "-color-shift",    ".colorShift",  XrmoptionSepArg, 0 },
@@ -645,23 +983,34 @@ XrmOptionDescRec options [] = {
   { "-vy",             ".vy",          XrmoptionSepArg, 0 },
   { "-vmult",          ".vMult",       XrmoptionSepArg, 0 },
   { "-mouse-size",     ".mouseSize",   XrmoptionSepArg, 0 },
+  { "-viscosity",      ".viscosity",   XrmoptionSepArg, 0 },
   { "-mouse",          ".mouse",       XrmoptionNoArg, "true" },
   { "-nomouse",                ".mouse",       XrmoptionNoArg, "false" },
-  { "-viscosity",      ".viscosity",   XrmoptionSepArg, 0 },
   { "-glow",           ".glow",        XrmoptionNoArg, "true" },
   { "-noglow",         ".glow",        XrmoptionNoArg, "false" },
   { "-orbit",          ".orbit",       XrmoptionNoArg, "true" },
+  { "-nowalls",                ".walls",       XrmoptionNoArg, "false" },
+  { "-walls",          ".walls",       XrmoptionNoArg, "true" },
+  { "-nomaxspeed",     ".maxspeed",    XrmoptionNoArg, "false" },
+  { "-maxspeed",       ".maxspeed",    XrmoptionNoArg, "true" },
+  { "-correct-bounce", ".cbounce",     XrmoptionNoArg, "false" },
+  { "-fast-bounce",    ".cbounce",     XrmoptionNoArg, "true" },
   { 0, 0, 0, 0 }
 };
 
 void
 screenhack (Display *dpy, Window window)
 {
+  /* for tail mode fix */
+  int total_ticks = 0;
+
   init_balls (dpy, window);
   while (1)
     {
-      run_balls (dpy, window);
+      total_ticks++;
+      run_balls (dpy, window, total_ticks);
       screenhack_handle_events (dpy);
-      if (delay) usleep (delay);
+      if (delay)
+        usleep (delay);
     }
 }
index fabdc8a3b2e1ef7b9be165c2e9b5738e5bddd2a9..f49257863d82ccb2b1e8881435993b7a9c8d6245 100644 (file)
 attraction - interactions of opposing forces
 .SH SYNOPSIS
 .B attraction
-[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-points \fIint\fP] [\-threshold \fIint\fP] [\-mode balls | lines | polygons | splines | filled-splines | tails ] [\-size \fIint\fP] [\-segments \fIint\fP] [\-delay \fIusecs\fP] [\-color-shift \fIint\fP] [\-radius \fIint\fP] [\-vx \fIint\fP] [\-vy \fIint\fP] [\-glow] [\-noglow] [\-orbit] [\-viscosity \fIfloat\fP] [\-mouse] [\-no-mouse] [\-mouse-size]
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP]
+[\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install]
+[\-visual \fIvisual\fP] [\-points \fIint\fP] [\-threshold \fIint\fP]
+[\-mode balls | lines | polygons | splines | filled-splines | tails ]
+[\-size \fIint\fP] [\-segments \fIint\fP] [\-delay \fIusecs\fP]
+[\-color-shift \fIint\fP] [\-radius \fIint\fP]
+[\-vx \fIint\fP] [\-vy \fIint\fP] [\-glow] [\-noglow]
+[\-orbit] [\-viscosity \fIfloat\fP] [\-mouse] [\-no-mouse] [\-mouse-size]
+[\-walls] [\-nowalls] [\-maxspeed] [\-nomaxspeed]
+[\-correct-bounce] [\-fast-bounce]
 .SH DESCRIPTION
 The \fIattraction\fP program has several visually different modes of 
 operation, all of which are based on the interactions of a set of control
@@ -152,9 +161,42 @@ Turns off \fB\-mouse\fP.
 .B \-mouse-size integer
 In \fB\-mouse\fP mode, this sets the mass of the mouse (analagously to the
 \fB\-size\fP parameter.)
-.SH ENVIRONMENT
-.PP
 .TP 8
+.B \-nowalls
+This will cause the balls to continue on past the edge of the
+screen or window.  They will still be kept track of and can come back.
+.TP 8
+.B \-walls
+This will cause the balls to bounce when they get
+to the edge of the screen or window.  This is the default behavior.
+.TP 8
+.B \-maxspeed
+Imposes a maximum speed (default).  If a ball ends up going faster than
+this, it will be treated as though there were .9  viscosity until it is
+under the limit. This stops the balls from continually accelerating (which
+they have a tendancy to do), but also causes balls moving very fast to
+tend to clump in the lower right corner.
+.TP 8
+.B \-nomaxspeed
+If this is specified, no maximum speed is set for the balls.
+.TP 8
+.B \-fast-bounce
+Uses the old, simple bouncing algorithm (default).  This simply moves any
+ball that is out of bounds back to a wall and reverses its velocity.
+This works fine for most cases, but under some circumstances, the
+simplification can lead to annoying effects.
+.TP 8
+.B \-correct-bounce
+Uses a more intelligent bouncing algorithm.  This method actually reflects
+the balls off the walls until they are within bounds.  This can be slow
+if balls are bouncing a whole lot, perhaps because of -nomaxspeed.
+.TP 8
+.B \-graphmode none | x | y | both | speed
+For "x", "y", and "both", displays the given velocities of each ball as a
+bar graph in the same window as the balls.  For "speed", displays the total
+speed of each ball.  Default is "none".
+.BR
+.SH ENVIRONMENT
 .B DISPLAY
 to get the default host and display number.
 .TP 8
@@ -176,3 +218,6 @@ made about the suitability of this software for any purpose.  It is provided
 Jamie Zawinski <jwz@jwz.org>, 13-aug-92.
 
 Viscosity and mouse support by Philip Edward Cutone, III.
+
+Walls, speed limit options, new bouncing, graphs, and tail mode fix by
+Matthew Strait. 31 March 2001
index bb30cbf124fc47c69b95efbd56f74171d7618b16..fb04fdc8f5ce4c2483bd246ee3c207f4842c4183 100644 (file)
@@ -1427,7 +1427,7 @@ sparc_solaris (Display* dpy, Window window, int delay)
 {
   const char *msg1 =
     "BAD TRAP: cpu=0 type=0x31 rp=0x2a10043b5e0 addr=0xf3880 mmu_fsr=0x0\n"
-    "BAD TRAP occurred in module \"unix\" due to an illegal access to a"
+    "BAD TRAP occured in module \"unix\" due to an illegal access to a"
     " user address.\n"
     "adb: trap type = 0x31\n"
     "addr=0xf3880\n"
index 56a1b0a5c646c39a86cde621e0b98f30bd50d284..ed765a987c0bdeba36373344e09cf2af7445d6c2 100644 (file)
@@ -801,7 +801,7 @@ char *defaults [] = {
   "*arrow1Foreground:  #FFF66A",
   "*arrow2Foreground:  #F7D64A",
   "*pointerForeground: #FF0000",
-  "*delay:             10000",
+  "*delay:             20000",
   "*doubleBuffer:      True",
 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
   "*useDBE:            True",
index 71d6cdae79b561dc2f24589ab059e63520dbf577..2440d0c25337eac4da224fa893c4af58d2650c38 100644 (file)
@@ -75,6 +75,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]) 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]) SPEEDMINE.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]) SPOTLIGHT.C
@@ -88,6 +89,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]) VINES.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) WANDER.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) WHIRLWINDWARP.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) WHIRLYGIG.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) WORM.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XFLAME.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XJACK.C
index 71d6cdae79b561dc2f24589ab059e63520dbf577..2440d0c25337eac4da224fa893c4af58d2650c38 100644 (file)
@@ -75,6 +75,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]) 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]) SPEEDMINE.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]) SPOTLIGHT.C
@@ -88,6 +89,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]) VINES.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) WANDER.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) WHIRLWINDWARP.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) WHIRLYGIG.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) WORM.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XFLAME.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XJACK.C
index 2ef9e1236410e4b921c37b9b35394566012310ae..188ab9df189c89a440ae313d7d851f537d1427ad 100644 (file)
@@ -3,7 +3,7 @@
 galaxy - draws spinning galaxies
 .SH SYNOPSIS
 .B galaxy
-[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-cycles \fIinteger\fP] [\-count \fIinteger\fP] [\-size \fIinteger\fP] [\-trail] [\-no\-trail]
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-cycles \fIinteger\fP] [\-count \fIinteger\fP] [\-size \fIinteger\fP] [\-tracks] [\-no\-tracks]
 
 .SH DESCRIPTION
 The \fIgalaxy\fP program draws spinning galaxies.
@@ -41,9 +41,9 @@ the color wheel.
 .B \-size \fIinteger\fP
 
 .TP 8
-.B \-trail
+.B \-tracks
 .TP 8
-.B \-no\-trail
+.B \-no\-tracks
 
 .SH ENVIRONMENT
 .PP
index 650894822935a922fa1db0bfcfa9367266164cb0..ba97c32963007ff0332a88d8d1ddd4faef3453ad 100644 (file)
@@ -93,15 +93,14 @@ OBJS                = xscreensaver-gl-helper.o \
                  stonerview-view.o starwars.o glut_stroke.o glut_swidth.o \
                  gltext.o molecule.o dangerball.o sphere.o tube.o
 
-GL_EXES_1      = cage gears moebius pipes sproingies stairs superquadrics \
+GL_EXES                = cage gears moebius pipes sproingies stairs superquadrics \
                  morph3d rubik atlantis lament bubble3d glplanet pulsar \
                  sierpinski3d gflux stonerview starwars gltext molecule \
                  dangerball
-UTIL_EXES      = xscreensaver-gl-helper
-GL_EXES                = $(UTIL_EXES) $(GL_EXES_1)
 GLE_EXES       = extrusion
+GL_UTIL_EXES   = xscreensaver-gl-helper
 HACK_EXES      = @GL_EXES@ @GLE_EXES@
-EXES           = $(HACK_EXES)
+EXES           = @GL_UTIL_EXES@ $(HACK_EXES)
 
 HACK_OBJS      = screenhack-gl.o xlock-gl.o fps.o $(HACK_BIN)/xlockmore.o \
                  $(UTILS_BIN)/resources.o $(UTILS_BIN)/visual.o \
@@ -130,68 +129,70 @@ install-strip:
        $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install
 
 # the hacks, in $HACKDIR
-install-program:: $(HACK_EXES)
-       @if [ ! -d $(install_prefix)$(HACKDIR) ]; then                  \
-         $(INSTALL_DIRS) $(install_prefix)$(HACKDIR) ;                 \
-        fi ;                                                           \
-       exes="$(HACK_EXES)" ;                                           \
-       for program in $$exes; do                                       \
-         echo $(INSTALL_PROGRAM) $$program                             \
-           $(install_prefix)$(HACKDIR)/$$program ;                     \
-         $(INSTALL_PROGRAM) $$program                                  \
-           $(install_prefix)$(HACKDIR)/$$program ;                     \
-       done
+install-program:: $(EXES)
+       @exes="$(HACK_EXES)" ;                                          \
+        idir="$(install_prefix)$(HACKDIR)" ;                           \
+        if [ "$$exes" != "" ]; then                                    \
+          if [ ! -d $$idir ]; then                                     \
+            $(INSTALL_DIRS) $$idir ;                                   \
+          fi ;                                                         \
+          for program in $$exes; do                                    \
+            echo $(INSTALL_PROGRAM) $$program $$idir/$$program ;       \
+                 $(INSTALL_PROGRAM) $$program $$idir/$$program ;       \
+          done ;                                                       \
+        fi
 
 # the xscreensaver-gl-helper program, in $bindir
-install-program:: $(HACK_EXES)
-       @if [ "$(HACK_EXES)" != "" ]; then                              \
-          if [ ! -d $(install_prefix)$(bindir) ]; then                 \
-            $(INSTALL_DIRS) $(install_prefix)$(bindir) ;               \
+install-program:: $(EXES)
+       @exes="$(GL_UTIL_EXES)" ;                                       \
+        idir="$(install_prefix)$(bindir)" ;                            \
+        if [ "$$exes" != "" ]; then                                    \
+          if [ ! -d $$idir ]; then                                     \
+            $(INSTALL_DIRS) $$idir ;                                   \
           fi ;                                                         \
-          exes="$(UTIL_EXES)" ;                                        \
           for program in $$exes; do                                    \
-            echo $(INSTALL_PROGRAM) $$program                          \
-              $(install_prefix)$(bindir)/$$program ;                   \
-            $(INSTALL_PROGRAM) $$program                               \
-              $(install_prefix)$(bindir)/$$program ;                   \
+            echo $(INSTALL_PROGRAM) $$program $$idir/$$program ;       \
+                 $(INSTALL_PROGRAM) $$program $$idir/$$program ;       \
           done ;                                                       \
         fi
 
 install-man: $(MEN)
        @men="$(MEN)" ;                                                 \
-       if [ ! -d $(install_prefix)$(man1dir) ]; then                   \
-         $(INSTALL_DIRS) $(install_prefix)$(man1dir) ;                 \
+        idir="$(install_prefix)$(man1dir)" ;                           \
+        if [ ! -d $$idir ]; then                                       \
+         $(INSTALL_DIRS) $$idir ;                                      \
         fi ;                                                           \
-       for man in $$men; do                                            \
-         instname=`echo $$man | sed 's/\.man$$/\.$(mansuffix)/'` ;     \
-         echo $(INSTALL_DATA) $(srcdir)/$$man                          \
-          $(install_prefix)$(man1dir)/$$instname ;                     \
-         $(INSTALL_DATA) $(srcdir)/$$man                               \
-           $(install_prefix)$(man1dir)/$$instname ;                    \
-       done
+        for man in $$men; do                                           \
+          instname=`echo $$man | sed 's/\.man$$/\.$(mansuffix)/'` ;    \
+          echo $(INSTALL_DATA) $(srcdir)/$$man $$idir/$$instname ;     \
+               $(INSTALL_DATA) $(srcdir)/$$man $$idir/$$instname ;     \
+        done
 
 # the hacks, in $HACKDIR
 uninstall-program::
-       @exes="$(GL_EXES_1) $(GLE_EXES)" ;                              \
-       for program in $$exes; do                                       \
-         echo rm -f $(install_prefix)$(HACKDIR)/$$program ;            \
-         rm -f $(install_prefix)$(HACKDIR)/$$program ;                 \
-       done
+       @exes="$(HACK_EXES)" ;                                          \
+        idir="$(install_prefix)$(HACKDIR)" ;                           \
+        for program in $$exes; do                                      \
+          echo rm -f $$idir/$$program ;                                \
+               rm -f $$idir/$$program ;                                \
+        done
 
 # the xscreensaver-gl-helper program, in $bindir
 uninstall-program::
-       @exes="$(UTIL_EXES)" ;                                          \
-       for program in $$exes; do                                       \
-         echo rm -f $(install_prefix)$(bindir)/$$program ;             \
-         rm -f $(install_prefix)$(bindir)/$$program ;                  \
+       @exes="$(GL_UTIL_EXES)" ;                                       \
+        idir="$(install_prefix)$(bindir)" ;                            \
+        for program in $$exes; do                                      \
+          echo rm -f $$idir/$$program ;                                \
+               rm -f $$idir/$$program ;                                \
        done
 
 uninstall-man:
-       @men="$(GL_MEN)" ;                                              \
-       for man in $$men; do                                            \
-         instname=`echo $$man | sed 's/\.man$$/\.$(mansuffix)/'` ;     \
-         echo rm -f $(install_prefix)$(man1dir)/$$instname ;           \
-         rm -f $(install_prefix)$(man1dir)/$$instname ;                \
+       @men="$(MEN)" ;                                                 \
+        idir="$(install_prefix)$(man1dir)" ;                           \
+        for man in $$men; do                                           \
+          instname=`echo $$man | sed 's/\.man$$/\.$(mansuffix)/'` ;    \
+          echo rm -f $$idir/$$instname ;                               \
+               rm -f $$idir/$$instname ;                               \
        done
 
 clean:
index f1844a5b212abb7b30c20288578c297a4fdb8abf..9f07ddbd17b9a5c0df25b241417a2e106cdee280 100644 (file)
@@ -103,19 +103,25 @@ static const char sccsid[] = "@(#)atlantis.c      1.3 98/06/18 xlockmore";
  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
  */
 
+#define DEF_TEXTURE "True"
+#define DEF_GRADIENT "False"
+#define DEF_WHALESPEED  "250"
+
 #ifdef STANDALONE
 # define PROGCLASS     "Atlantis"
 # define HACK_INIT     init_atlantis
 # define HACK_DRAW     draw_atlantis
 # define HACK_RESHAPE  reshape_atlantis
 # define atlantis_opts xlockmore_opts
-# define DEFAULTS      "*delay:       40000 \n" \
+# define DEFAULTS      "*delay:       25000 \n" \
                         "*count:          4 \n" \
                         "*showFPS:    False \n" \
                         "*cycles:       100 \n" \
                         "*size:        6000 \n" \
                         "*wireframe:  False \n" \
-                        "*whalespeed:   250 \n"
+                        "*texture:    " DEF_TEXTURE    " \n" \
+                        "*gradient:   " DEF_GRADIENT   " \n" \
+                        "*whalespeed: " DEF_WHALESPEED " \n"
 # include "xlockmore.h"                /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
 # include "xlock.h"            /* from the xlockmore distribution */
@@ -128,22 +134,23 @@ static const char sccsid[] = "@(#)atlantis.c      1.3 98/06/18 xlockmore";
 #include <GL/glu.h>
 
 
-#define DEF_TEXTURE "True"
-
-#define DEF_WHALESPEED  "250"
 static int  whalespeed;
 static int do_texture;
+static int do_gradient;
 static XrmOptionDescRec opts[] =
 {
      {"-whalespeed", ".atlantis.whalespeed", XrmoptionSepArg, (caddr_t) NULL},
      {"-texture",    ".atlantis.texture",    XrmoptionNoArg, (caddr_t)"true"},
      {"+texture",    ".atlantis.texture",    XrmoptionNoArg, (caddr_t)"false"},
+     {"-gradient",   ".atlantis.gradient",   XrmoptionNoArg, (caddr_t)"true"},
+     {"+gradient",   ".atlantis.gradient",   XrmoptionNoArg, (caddr_t)"false"},
 };
 
 static argtype vars[] =
 {
  {(caddr_t *) & whalespeed, "whalespeed", "WhaleSpeed", DEF_WHALESPEED, t_Int},
  {(caddr_t *) &do_texture,  "texture",    "Texture",    DEF_TEXTURE,   t_Bool},
+ {(caddr_t *) &do_gradient, "gradient",   "Gradient",   DEF_GRADIENT,  t_Bool},
 };
 
 static OptionStruct desc[] =
@@ -240,7 +247,6 @@ Init(ModeInfo *mi)
        {0.4, 0.4, 0.4, 1.0};
        static float lmodel_localviewer[] =
        {0.0};
-       float       fblue = 0.0, fgreen;
 
        glFrontFace(GL_CCW);
 
@@ -317,10 +323,7 @@ Init(ModeInfo *mi)
 
        InitFishs(ap);
 
-       /* Add a little randomness */
-       fblue = ((float) (NRAND(50)) / 100.0) + 0.50;
-       fgreen = fblue * 0.56;
-       glClearColor(0.0, fgreen, fblue, 0.0);
+       glClearColor(0.0, 0.39, 0.7, 0.0);
 }
 
 void
@@ -336,6 +339,95 @@ reshape_atlantis(ModeInfo * mi, int width, int height)
        glMatrixMode(GL_MODELVIEW);
 }
 
+
+static void
+clear_tank (atlantisstruct * ap)
+{
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  if (do_gradient && !ap->wire)
+    {
+      static GLint gradient_list = -1;
+      static GLint gradient_tex = -1;
+
+      if (gradient_list == -1)
+        {
+          unsigned char *pixels = 0;
+          int start = 64;
+          int end = start + 128;
+          int size = 4 * (end - start);
+          int i;
+
+          pixels = (unsigned char *) malloc (size);
+          i = 0;
+          while (i < size)
+            {
+              pixels[i++] = 0;
+              pixels[i++] = (start + (i>>2)) * 0.56;
+              pixels[i++] = (start + (i>>2));
+              pixels[i++] = 255;
+            }
+
+          clear_gl_error();
+
+          glGenTextures(1, &gradient_tex);
+          glBindTexture(GL_TEXTURE_1D, gradient_tex);
+
+          glTexImage1D(GL_TEXTURE_1D, 0, 4,
+                       (end - start), 0,
+                       GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+          check_gl_error ("gradient texture");
+          glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+          glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+
+          gradient_list = glGenLists(1);
+          glNewList(gradient_list, GL_COMPILE);
+
+          glDepthMask (False);
+          glDisable(GL_DEPTH_TEST);
+          glDisable(GL_LIGHTING);
+          glDisable(GL_TEXTURE_2D);
+          glEnable(GL_TEXTURE_1D);
+          glBindTexture(GL_TEXTURE_1D, gradient_tex);
+          glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); 
+          glTexParameterf(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+
+          glMatrixMode(GL_PROJECTION);
+          glPushMatrix();
+          glLoadIdentity();
+          glRotatef(90, 0, 0, 1);
+          glTranslatef(-1, -1, 0);
+          glScalef(2, 2, 1);
+
+          glBegin(GL_QUADS);
+          glTexCoord1i(1); glVertex3i(1, 0, 0);
+          glTexCoord1i(0); glVertex3i(0, 0, 0);
+          glTexCoord1i(0); glVertex3i(0, 1, 0);
+          glTexCoord1i(1); glVertex3i(1, 1, 0);
+          glEnd();
+
+          glPopMatrix();
+
+          glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 
+          glDisable(GL_TEXTURE_1D);
+
+          glDepthMask (True);
+          glEnable(GL_DEPTH_TEST);
+          glEnable(GL_CULL_FACE);
+          glEnable(GL_LIGHTING);
+          if (do_texture)
+            glEnable(GL_TEXTURE_2D);
+
+          glEndList();
+          check_gl_error ("gradient list");
+        }
+
+      glCallList(gradient_list);
+    }
+}
+
+
 static void
 Animate(atlantisstruct * ap)
 {
@@ -358,7 +450,7 @@ AllDisplay(atlantisstruct * ap)
 {
        int         i;
 
-       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+        clear_tank(ap);
 
        for (i = 0; i < ap->num_sharks; i++) {
                glPushMatrix();
index 16bcfcf0c5aa7f80715a4fc2e07f526ebe5c0cdd..e3641506dae448bc23b5632fffd60a0befddbada 100644 (file)
@@ -85,7 +85,7 @@ static const char sccsid[] = "@(#)cage.c      4.07 98/01/04 xlockmore";
 # define HACK_RESHAPE                  reshape_cage
 # define cage_opts                     xlockmore_opts
 # define DEFAULTS                      "*cycles:               1       \n"                     \
-                                                       "*delay:                20000   \n"                     \
+                                                       "*delay:                25000   \n"                     \
                                                        "*showFPS:      False   \n"                     \
                                                        "*wireframe:    False   \n"
 # include "xlockmore.h"                /* from the xscreensaver distribution */
index e7adec3dffa433213f2627d7c02838e95715973b..b254397eab2381c0a82a1996512e2b997d880334 100644 (file)
 #include <GL/glu.h>
 #include <GL/glx.h>
 
+#undef DEBUG  /* Defining this causes check_gl_error() to be called inside
+                 time-critical sections, which could slow things down (since
+                 it might result in a round-trip, and stall of the pipeline.)
+               */
+
 extern void clear_gl_error (void);
 extern void check_gl_error (const char *type);
 
@@ -75,9 +80,21 @@ fps_print_string (ModeInfo *mi, GLfloat x, GLfloat y, const char *string)
     y = mi->xgwa.height + y;
 
   clear_gl_error ();
-  glPushAttrib(GL_ALL_ATTRIB_BITS);
+
+  /* Sadly, this causes a stall of the graphics pipeline (as would the
+     equivalent calls to glGet*.)  But there's no way around this, short
+     of having each caller set up the specific display matrix we need
+     here, which would kind of defeat the purpose of centralizing this
+     code in one file.
+   */
+  glPushAttrib(GL_TRANSFORM_BIT |  /* for matrix contents */
+               GL_ENABLE_BIT |     /* for various glDisable calls */
+               GL_CURRENT_BIT |    /* for glColor3f() */
+               GL_LIST_BIT);       /* for glListBase() */
   {
+# ifdef DEBUG
     check_gl_error ("glPushAttrib");
+# endif
 
     /* disable lighting and texturing when drawing bitmaps!
        (glPopAttrib() restores these, I believe.)
@@ -93,7 +110,9 @@ fps_print_string (ModeInfo *mi, GLfloat x, GLfloat y, const char *string)
     glMatrixMode(GL_PROJECTION);
     glPushMatrix();
     {
+# ifdef DEBUG
       check_gl_error ("glPushMatrix");
+# endif
       glLoadIdentity();
 
       /* Each matrix mode has its own stack, so we need to push/pop
@@ -101,11 +120,15 @@ fps_print_string (ModeInfo *mi, GLfloat x, GLfloat y, const char *string)
       glMatrixMode(GL_MODELVIEW);
       glPushMatrix();
       {
+# ifdef DEBUG
         check_gl_error ("glPushMatrix");
+# endif
         glLoadIdentity();
 
         gluOrtho2D(0, mi->xgwa.width, 0, mi->xgwa.height);
+# ifdef DEBUG
         check_gl_error ("gluOrtho2D");
+# endif
 
         /* clear the background */
         if (fps_clear_p)
@@ -119,10 +142,12 @@ fps_print_string (ModeInfo *mi, GLfloat x, GLfloat y, const char *string)
         /* draw the text */
         glColor3f (1, 1, 1);
         glRasterPos2f (x, y);
-        for (i = 0; i < strlen(string); i++)
-          glCallList (font_dlist + (int)string[i]);
+        glListBase (font_dlist);
+        glCallLists (strlen(string), GL_UNSIGNED_BYTE, string);
 
+# ifdef DEBUG
         check_gl_error ("fps_print_string");
+# endif
       }
       glPopMatrix();
     }
@@ -132,7 +157,9 @@ fps_print_string (ModeInfo *mi, GLfloat x, GLfloat y, const char *string)
   }
   /* clean up after our state changes */
   glPopAttrib();
+# ifdef DEBUG
   check_gl_error ("glPopAttrib");
+# endif
 }
 
 
index db68a528393ee0569161ee6c734581fae716c1cf..d6c1cf01206cabd8a5ea6804eb680f36c0049c40 100644 (file)
@@ -36,7 +36,7 @@ Specifies the size of the grid in squares. default 19
 Specifies the wireframe detail of the squares. default 4
 .TP 8
 .B \-draw \fInum\fP\fP
-Specifies the draw method. 0 = wireframe (default), 1 = solid, 2 = light, 3 = checker texture mapped, 4 = PNM image is read from stdin and mapped to the surface
+Specifies the draw method. 0 = wireframe, 1 = solid, 2 = light (default), 3 = checker texture mapped, 4 = PNM image is read from stdin and mapped to the surface
 .TP 8
 .B \-flat \fInum\fP\fP
 0 for smooth shading 1 for flat. default 0
index d5d3de48adc166254e19b81f5d933149f9c96e7a..f1190281ba3b870dbdb35a0429cfa9c89adea4f9 100644 (file)
@@ -398,15 +398,13 @@ static void inline ParametricSphere(float theta, float rho, GLfloat *vector)
 /* lame way to generate some random stars */
 void generate_stars(int width, int height)
 {
-  int i;
-/*  GLfloat size_range[2], size;*/
-  GLfloat x, y;
+  int i, j;
+  int max_size = 3;
+  GLfloat inc = 0.5;
+  int steps = max_size / inc;
 
   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);
 
@@ -421,20 +419,27 @@ void generate_stars(int width, int height)
 
   /* 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 = ((random()%size_range[0])) * size_range[1]/2.; */
-/*    glPointSize(size); */
-         x = random() % width;
-         y = random() % height;
-         glVertex2f(x,y);
-       }
-  glEnd();
+  glColor3f(1,1,1);
+
+  glEnable(GL_POINT_SMOOTH);
+
+  for (j = 1; j <= steps; j++)
+    {
+      glPointSize(inc * j);
+      glBegin(GL_POINTS);
+      for(i = 0 ; i < NUM_STARS / steps; i++)
+        {
+          glColor3f (0.6 + frand(0.3),
+                     0.6 + frand(0.3),
+                     0.6 + frand(0.3));
+          glVertex2f ((GLfloat) (random() % width),
+                      (GLfloat) (random() % height));
+        }
+      glEnd();
+    }
 
   /* return to original PROJECT and MODELVIEW */
   glMatrixMode(GL_PROJECTION);
@@ -446,6 +451,20 @@ void generate_stars(int width, int height)
 
 }
 
+/* Set up lighting */
+static void
+init_sun (ModeInfo * mi)
+{
+  GLfloat light[4];
+  light[0] = -1;
+  light[1] = (int) (((random() % 3) & 0xFF) - 1);
+  light[2] = (int) (((random() % 3) & 0xFF) - 1);
+  light[3] = 0;
+
+  glLightfv(GL_LIGHT0, GL_POSITION, light);
+}
+
+
 /* Initialization function for screen saver */
 static void
 pinit(ModeInfo * mi)
@@ -478,7 +497,9 @@ pinit(ModeInfo * mi)
   unit_sphere (STACKS, SLICES, wire);
   glPopMatrix ();
   glEndList();
- }
+
+  init_sun (mi);
+}
 
 static void
 draw_sphere(ModeInfo * mi)
@@ -569,24 +590,16 @@ rotate_and_move (ModeInfo * mi)
 void
 reshape_planet(ModeInfo *mi, int width, int height)
 {
-  GLfloat light[4];
   GLfloat h = (GLfloat) height / (GLfloat) width;
 
-  light[0] = -1;
-  light[1] = (int) (((random() % 3) & 0xFF) - 1);
-  light[2] = (int) (((random() % 3) & 0xFF) - 1);
-  light[3] = 0;
-
   glViewport(0, 0, (GLint) width, (GLint) height);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   glFrustum(-1.0, 1.0, -h, h, 5.0, 100.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
-  glTranslatef(0.0, 0.0, -DIST);
-  glLightfv(GL_LIGHT0, GL_POSITION, light);
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
+  glTranslatef(0.0, 0.0, -DIST);
 }
 
 
@@ -664,15 +677,8 @@ draw_planet(ModeInfo * mi)
   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);
-
-       }
+    glCallList(gp->starlist);
        glPopMatrix();
-       glPopAttrib();
   }
 
   /* protect our modelview matrix and attributes */
index 8d5fe8c29b8300b97d0ebe14ca8367bf7ffe658a..3f5080c04d0b0b0650b988c7df94d29c732c7850 100644 (file)
@@ -140,8 +140,16 @@ typedef enum {
 
 } lament_type;
 
-static GLfloat exterior_color[] = { 0.70, 0.60, 0.00, 1.00 };
-static GLfloat interior_color[] = { 0.25, 0.25, 0.20, 1.00 };
+static GLfloat exterior_color[] = { 0.33, 0.22, 0.03, 1.00,  /* ambient    */
+                                    0.78, 0.57, 0.11, 1.00,  /* specular   */
+                                    0.99, 0.91, 0.81, 1.00,  /* diffuse    */
+                                   27.80                     /* shininess  */
+                                  };
+static GLfloat interior_color[] = { 0.20, 0.20, 0.15, 1.00,  /* ambient    */
+                                    0.40, 0.40, 0.32, 1.00,  /* specular   */
+                                    0.99, 0.99, 0.81, 1.00,  /* diffuse    */
+                                   50.80                     /* shininess  */
+                                  };
 
 
 typedef struct {
@@ -276,6 +284,15 @@ do_normal(GLfloat x1, GLfloat y1, GLfloat z1,
 /* Shorthand utilities for making faces, with proper normals.
  */
 
+static void
+set_colors (GLfloat *color)
+{
+  glMaterialfv(GL_FRONT, GL_AMBIENT, color+0);
+  glMaterialfv(GL_FRONT, GL_DIFFUSE, color+4);
+  glMaterialfv(GL_FRONT, GL_SPECULAR, color+8);
+  glMaterialfv(GL_FRONT, GL_SHININESS, color+12);
+}
+
 static void
 face3(GLint texture, GLfloat *color, Bool wire,
       GLfloat s1, GLfloat t1, GLfloat x1, GLfloat y1, GLfloat z1,
@@ -285,7 +302,8 @@ face3(GLint texture, GLfloat *color, Bool wire,
 #ifdef HAVE_GLBINDTEXTURE
   glBindTexture(GL_TEXTURE_2D, texture);
 #endif /* HAVE_GLBINDTEXTURE */
-  glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color);
+  set_colors(color);
+
   do_normal(x1, y1, z1,  x2, y2, z2,  x3, y3, z3);
   glBegin(wire ? GL_LINE_LOOP : GL_TRIANGLES);
   glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
@@ -304,7 +322,7 @@ face4(GLint texture, GLfloat *color, Bool wire,
 #ifdef HAVE_GLBINDTEXTURE
   glBindTexture(GL_TEXTURE_2D, texture);
 #endif /* HAVE_GLBINDTEXTURE */
-  glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color);
+  set_colors(color);
   do_normal(x1, y1, z1,  x2, y2, z2,  x3, y3, z3);
   glBegin(wire ? GL_LINE_LOOP : GL_QUADS);
   glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
@@ -325,7 +343,7 @@ face5(GLint texture, GLfloat *color, Bool wire,
 #ifdef HAVE_GLBINDTEXTURE
   glBindTexture(GL_TEXTURE_2D, texture);
 #endif /* HAVE_GLBINDTEXTURE */
-  glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, color);
+  set_colors(color);
   do_normal(x1, y1, z1,  x2, y2, z2,  x3, y3, z3);
   glBegin(wire ? GL_LINE_LOOP : GL_POLYGON);
   glTexCoord2f(s1, t1); glVertex3f(x1, y1, z1);
@@ -542,7 +560,7 @@ star(ModeInfo *mi, Bool top, Bool wire)
 #ifdef HAVE_GLBINDTEXTURE
   glBindTexture(GL_TEXTURE_2D, lc->texids[top ? FACE_U : FACE_D]);
 #endif /* HAVE_GLBINDTEXTURE */
-  glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, exterior_color);
+  set_colors(exterior_color);
 
   i = 1;
   do_normal(points[i+0][0], points[i+0][1], 0,
@@ -564,7 +582,7 @@ star(ModeInfo *mi, Bool top, Bool wire)
 #ifdef HAVE_GLBINDTEXTURE
   glBindTexture(GL_TEXTURE_2D, 0);
 #endif /* HAVE_GLBINDTEXTURE */
-  glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, interior_color);
+  set_colors(interior_color);
 
   i = countof(points) - 9;
   do_normal(points[i+0][0], points[i+0][1], 0,
@@ -1010,7 +1028,7 @@ taser(ModeInfo *mi, Bool wire)
 #ifdef HAVE_GLBINDTEXTURE
       glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
 #endif /* HAVE_GLBINDTEXTURE */
-      glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, exterior_color);
+      set_colors(exterior_color);
 
       do_normal(0, body_face_points[(i*5)+0][0], body_face_points[(i*5)+0][1],
                0, body_face_points[(i*5)+1][0], body_face_points[(i*5)+1][1],
@@ -1135,7 +1153,7 @@ taser(ModeInfo *mi, Bool wire)
 #ifdef HAVE_GLBINDTEXTURE
       glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
 #endif /* HAVE_GLBINDTEXTURE */
-      glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, exterior_color);
+      set_colors(exterior_color);
 
       do_normal(
          0, lifter_face_points[(i*5)+0][0], lifter_face_points[(i*5)+0][1],
@@ -1273,7 +1291,7 @@ taser(ModeInfo *mi, Bool wire)
 #ifdef HAVE_GLBINDTEXTURE
       glBindTexture(GL_TEXTURE_2D, lc->texids[FACE_E]);
 #endif /* HAVE_GLBINDTEXTURE */
-      glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, exterior_color);
+      set_colors(exterior_color);
 
       do_normal(
           0, slider_face_points[(i*5)+0][0], slider_face_points[(i*5)+0][1],
@@ -1302,7 +1320,7 @@ taser(ModeInfo *mi, Bool wire)
 #ifdef HAVE_GLBINDTEXTURE
       glBindTexture(GL_TEXTURE_2D, 0);
 #endif /* HAVE_GLBINDTEXTURE */
-      glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, interior_color);
+      set_colors(interior_color);
 
       do_normal(
           0, slider_face_points[(i*5)+2][0], slider_face_points[(i*5)+2][1],
@@ -1927,31 +1945,26 @@ gl_init(ModeInfo *mi)
 
   if (!wire)
     {
-      static GLfloat pos0[]  = { -4.0, 2.0, 5.0, 1.0 };
-      static GLfloat pos1[]  = { 12.0, 5.0, 1.0, 1.0 };
-      static GLfloat local[] = { 0.0 };
-      static GLfloat ambient[] = { 0.3, 0.3, 0.3, 1.0 };
-      static GLfloat spec[] = { 1.0, 1.0, 1.0, 1.0 };
-      static GLfloat shine[] = { 100.0 };
+      static GLfloat pos0[]  = { -4.0,  2.0, 5.0, 1.0 };
+      static GLfloat pos1[]  = {  6.0, -1.0, 3.0, 1.0 };
+
+      static GLfloat amb0[]  = { 0.7, 0.7, 0.7, 1.0 };
+/*    static GLfloat amb1[]  = { 0.7, 0.0, 0.0, 1.0 }; */
+      static GLfloat dif0[]  = { 1.0, 1.0, 1.0, 1.0 };
+      static GLfloat dif1[]  = { 0.3, 0.1, 0.1, 1.0 };
 
       glLightfv(GL_LIGHT0, GL_POSITION, pos0);
       glLightfv(GL_LIGHT1, GL_POSITION, pos1);
 
-      glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
-      glLightfv(GL_LIGHT1, GL_AMBIENT, ambient);
-
-      glLightfv(GL_LIGHT0, GL_SPECULAR, spec);
-      glLightfv(GL_LIGHT1, GL_SPECULAR, spec);
-
-      glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, local);
-      glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, exterior_color);
-      glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
-      glMaterialfv(GL_FRONT, GL_SHININESS, shine);
+      glLightfv(GL_LIGHT0, GL_AMBIENT,  amb0);
+/*    glLightfv(GL_LIGHT1, GL_AMBIENT,  amb1); */
+      glLightfv(GL_LIGHT0, GL_DIFFUSE,  dif0);
+      glLightfv(GL_LIGHT1, GL_DIFFUSE,  dif1);
+      set_colors(exterior_color);
 
       glEnable(GL_LIGHTING);
       glEnable(GL_LIGHT0);
-      glEnable(GL_LIGHT1);
-      glDisable(GL_LIGHT1);
+/*    glEnable(GL_LIGHT1); */
 
       glEnable(GL_DEPTH_TEST);
       glEnable(GL_TEXTURE_2D);
@@ -1975,7 +1988,7 @@ gl_init(ModeInfo *mi)
        {
          int height = lc->texture->width;      /* assume square */
          glBindTexture(GL_TEXTURE_2D, lc->texids[i]);
-         glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, exterior_color);
+         set_colors(exterior_color);
 
           clear_gl_error();
          glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
@@ -2040,14 +2053,13 @@ lament_signal_kludge (int sig)
            "\n"
            "%s: dying with signal %d (%s).\n"
            "\n"
-           "\tThis is almost certainly a bug in the MesaGL library,\n"
+           "\tThis is almost certainly a bug in the Mesa GL library,\n"
            "\tespecially if the stack trace in the core file mentions\n"
            "\t`lambda_textured_triangle' or `render_quad'.\n"
            "\n"
-           "\tI encourage you to report this to the Mesa maintainers\n"
-           "\tat <http://www.mesa3d.org/>.  I reported this bug more\n"
-           "\tthan a year ago, and it is trivially reproducible.\n"
-           "\tI do not know a workaround.\n"
+           "\tFirst make sure that you have the latest version of Mesa.\n"
+           "\tIf that doesn't fix it, then I encourage you to report this\n"
+           "\tbug to the Mesa maintainers at <http://www.mesa3d.org/>.\n"
            "\n",
            progname,
            sig,
index 954b98101dc03014adca815b485e016d06499597..e9cc9852c237b64833770540e7d54412c7f79c29 100644 (file)
@@ -552,7 +552,8 @@ print_title_string (ModeInfo *mi, const char *string,
   
   y -= line_height;
 
-  glPushAttrib (GL_LIGHTING | GL_DEPTH_TEST);
+  glPushAttrib (GL_TRANSFORM_BIT |  /* for matrix contents */
+                GL_ENABLE_BIT);     /* for various glDisable calls */
   glDisable (GL_LIGHTING);
   glDisable (GL_DEPTH_TEST);
   {
@@ -622,6 +623,7 @@ build_molecule (ModeInfo *mi)
       glEnable(GL_CULL_FACE);
     }
 
+#if 0
   if (do_labels && !wire)
     {
       /* This is so all polygons are drawn slightly farther back in the depth
@@ -634,6 +636,7 @@ build_molecule (ModeInfo *mi)
     {
       glDisable (GL_POLYGON_OFFSET_FILL);
     }
+#endif
 
   if (!wire)
     set_atom_color (mi, 0, False);
@@ -689,16 +692,20 @@ build_molecule (ModeInfo *mi)
         molecule_atom *a = &m->atoms[i];
         int j;
 
-        glPushAttrib (GL_LIGHTING | GL_DEPTH_TEST);
-        glDisable (GL_LIGHTING);
-/*        glDisable (GL_DEPTH_TEST);*/
+        if (!wire)
+          {
+            glDisable (GL_LIGHTING);
+#if 1
+            glDisable (GL_DEPTH_TEST);
+#endif
+          }
 
         if (!wire)
           set_atom_color (mi, a, True);
 
         glRasterPos3f (a->x, a->y, a->z);
 
-        /* Before drawing the string, shift the origin  to center
+        /* Before drawing the string, shift the origin to center
            the text over the origin of the sphere. */
         glBitmap (0, 0, 0, 0,
                   -string_width (mc->xfont1, a->label) / 2,
@@ -708,7 +715,17 @@ build_molecule (ModeInfo *mi)
         for (j = 0; j < strlen(a->label); j++)
           glCallList (mc->font1_dlist + (int)(a->label[j]));
 
-        glPopAttrib();
+        /* More efficient to always call glEnable() with correct values
+           than to call glPushAttrib()/glPopAttrib(), since reading
+           attributes from GL does a round-trip and  stalls the pipeline.
+         */
+        if (!wire)
+          {
+            glEnable(GL_LIGHTING);
+#if 1
+            glEnable(GL_DEPTH_TEST);
+#endif
+          }
       }
 
   if (do_bbox)
@@ -1098,7 +1115,7 @@ reshape_molecule (ModeInfo *mi, int width, int height)
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
 
-  gluPerspective( 30.0, 1/h, 1.0, 100.0 );
+  gluPerspective( 30.0, 1/h, 20.0, 40.0 );
   gluLookAt( 0.0, 0.0, 15.0,
              0.0, 0.0, 0.0,
              0.0, 1.0, 0.0);
index 7c67b83537991a979bb68885711e3f631ace43f6..a7695027e983fc84de1c834fcc352122f1bb26a0 100644 (file)
@@ -613,7 +613,7 @@ void drawQuads(void) {
 
 GLvoid drawScene(ModeInfo * mi) 
 {
-  check_gl_error ("drawScene");
+/*  check_gl_error ("drawScene"); */
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
   /* we have to do this here because the FPS meter turns these 3 features off!! */
@@ -647,7 +647,7 @@ GLvoid drawScene(ModeInfo * mi)
   /* increment frame-counter */
   frame++;
 
-  check_gl_error ("drawScene");
+/*  check_gl_error ("drawScene"); */
 }
 
 
index 517c22da966b4c99e78e6d60efc8d241feba0b4f..b8ec9c415edd3af009151f7856bbf99c033e5fae 100644 (file)
@@ -59,7 +59,7 @@ static const char sccsid[] = "@(#)sproingiewrap.c     4.07 97/11/24 xlockmore";
 # define HACK_DRAW                                     draw_sproingies
 # define HACK_RESHAPE                          reshape_sproingies
 # define sproingies_opts                       xlockmore_opts
-# define DEFAULTS      "*delay:                20000   \n"                     \
+# define DEFAULTS      "*delay:                25000   \n"                     \
                                        "*count:                5       \n"                     \
                                        "*cycles:               0       \n"                     \
                                        "*size:                 0       \n"                     \
index a6d5745caccce1c48704d5acb95cd1bef773cb81..cfb40f8c1e2262bf7844eb0fef14e80c04b67885 100644 (file)
@@ -43,7 +43,7 @@ extern XtAppContext app;
 #define HACK_RESHAPE   reshape_sws
 #define sws_opts       xlockmore_opts
 
-#define DEF_PROGRAM    ZIPPY_PROGRAM
+#define DEF_PROGRAM    "(default)"
 #define DEF_LINES      "125"
 #define DEF_STEPS      "35"
 #define DEF_SPIN       "0.03"
@@ -88,6 +88,7 @@ extern XtAppContext app;
 #ifdef USE_GL /* whole file */
 
 #include <GL/glu.h>
+#include <sys/stat.h>
 #include "glutstroke.h"
 #include "glut_roman.h"
 #define GLUT_FONT (&glutStrokeRoman)
@@ -253,8 +254,22 @@ static void
 launch_text_generator (sws_configuration *sc)
 {
   char *oprogram = get_string_resource ("program", "Program");
-  char *program = (char *) malloc (strlen (oprogram) + 10);
+  char *program;
 
+  if (!strcasecmp(oprogram, "(default)"))
+    {
+#ifdef __linux__
+      static int done_once = 0;
+      struct stat st;
+      char *cmd = "cat /usr/src/linux/README";
+      if (!(done_once++) && !stat (cmd+4, &st))
+        oprogram = cmd;
+      else
+#endif
+        oprogram = ZIPPY_PROGRAM;
+    }
+
+ program = (char *) malloc (strlen (oprogram) + 10);
   strcpy (program, "( ");
   strcat (program, oprogram);
   strcat (program, " ) 2>&1");
@@ -496,6 +511,41 @@ box (double width, double height, double depth)
 #endif /* DEBUG */
 
 
+/* Construct stars (number of stars is dependent on size of screen) */
+static void
+init_stars (ModeInfo *mi, int width, int height)
+{
+  sws_configuration *sc = &scs[MI_SCREEN(mi)];
+  int i, j;
+  int nstars = width * height / 320;
+  int max_size = 3;
+  GLfloat inc = 0.5;
+  int steps = max_size / inc;
+
+  glDeleteLists (sc->star_list, 1);
+  sc->star_list = glGenLists (1);
+  glNewList (sc->star_list, GL_COMPILE);
+
+  glEnable(GL_POINT_SMOOTH);
+
+  for (j = 1; j <= steps; j++)
+    {
+      glPointSize(inc * j);
+      glBegin (GL_POINTS);
+      for (i = 0; i < nstars / steps; i++)
+        {
+          glColor3f (0.6 + frand(0.3),
+                     0.6 + frand(0.3),
+                     0.6 + frand(0.3));
+          glVertex2f (2 * width  * (0.5 - frand(1.0)),
+                      2 * height * (0.5 - frand(1.0)));
+        }
+      glEnd ();
+    }
+  glEndList ();
+}
+
+
 /* Window management, etc
  */
 void
@@ -536,27 +586,6 @@ reshape_sws (ModeInfo *mi, int width, int height)
   }
 
 
-  /* Construct stars (number of stars is dependent on size of screen) */
-  {
-    int i;
-    int nstars = width * height / 320;
-    glDeleteLists (sc->star_list, 1);
-    sc->star_list = glGenLists (1);
-    glNewList (sc->star_list, GL_COMPILE);
-    glBegin (GL_POINTS);
-    for (i = 0; i < nstars; i++)
-      {
-        GLfloat c = 0.6 + 0.3 * random() / RAND_MAX;
-        glColor3f (c, c, c);
-        glVertex3f (2 * width  * (0.5 - 1.0 * random() / RAND_MAX),
-                    2 * height * (0.5 - 1.0 * random() / RAND_MAX),
-                    0.0);
-      }
-    glEnd ();
-    glEndList ();
-  }
-
-
   /* Compute the height in pixels of the line at the bottom of the screen. */
   {
     GLdouble mm[17], pm[17];
@@ -640,10 +669,10 @@ init_sws (ModeInfo *mi)
   if ((sc->glx_context = init_GL(mi)) != NULL) {
     gl_init(mi);
     reshape_sws (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+    init_stars (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
   }
 
 
-
   font_height = GLUT_FONT->top - GLUT_FONT->bottom;
   sc->font_scale = 1.0 / glutStrokeWidth (GLUT_FONT, 'z');   /* 'n' seems
                                                                 too wide */
@@ -666,7 +695,6 @@ init_sws (ModeInfo *mi)
 
   sc->subproc_relaunch_delay = 2 * 1000;
   sc->total_lines = max_lines-1;
-  launch_text_generator (sc);
 
   if (random() & 1)
     star_spin = -star_spin;
@@ -686,6 +714,8 @@ init_sws (ModeInfo *mi)
                progname, alignment_str);
       exit (1);
     }
+
+  launch_text_generator (sc);
 }
 
 
index 2788e2cd0b66e1e61a94684b56367ea900743b0f..a0606710deb322e1d7220ed0e6e8124a55044e24 100644 (file)
@@ -142,7 +142,6 @@ ATOM    140  C   ???     1      -1.422  -1.319   5.892
 ATOM    141  C   ???     1      -3.248  -0.795   4.314
 ATOM    142  P   ???     1      -9.378  -1.306   2.603
 ATOM    143  O   ???     1      -9.127  -2.221   3.726
-ATOM    144  O   ???     1     -10.818  -1.001   2.258
 ATOM    145  O   ???     1      -8.753  -2.007   1.349
 ATOM    146  C   ???     1      -8.460  -1.252   0.127
 ATOM    147  C   ???     1      -7.623  -2.192  -0.688
index 543af3e4f1f4807528f1a8f5685578b934e7930e..ea1a93bc74c1fd4531bb94e2af3bb7f167acbe26 100644 (file)
@@ -1,38 +1,46 @@
 #define nose_f1_width 64
 #define nose_f1_height 64
 static unsigned char nose_f1_bits[] = {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x40,0x00,
- 0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,
- 0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
- 0x40,0x00,0x00,0x04,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
- 0x08,0x00,0xc0,0x1f,0x00,0x20,0x00,0x00,0x08,0x00,0x30,0x60,0x00,0x20,0x00,
- 0x00,0xf8,0xff,0x0f,0x80,0xff,0x3f,0x00,0x00,0x00,0x02,0x02,0x00,0x82,0x00,
- 0x00,0x00,0x00,0x03,0x01,0x00,0x84,0x01,0x00,0x00,0x00,0x81,0x00,0x00,0x08,
- 0x01,0x00,0x00,0x80,0x80,0x00,0x00,0x08,0x02,0x00,0x00,0x80,0x40,0x00,0x00,
- 0x10,0x02,0x00,0x00,0x40,0x40,0x00,0x00,0x10,0x04,0x00,0x00,0x40,0x20,0x00,
- 0x00,0x20,0x04,0x00,0x00,0x60,0x20,0x00,0x00,0x20,0x0c,0x00,0x00,0x20,0x20,
- 0x00,0x00,0x20,0x08,0x00,0x00,0x20,0x20,0x00,0x00,0x20,0x08,0x00,0x00,0x10,
- 0x20,0x00,0x00,0x20,0x10,0x00,0x00,0x10,0x20,0x00,0x00,0x20,0x10,0x00,0x00,
- 0x10,0x20,0x00,0x00,0x20,0x10,0x00,0x00,0x10,0x40,0x00,0x00,0x10,0x10,0x00,
- 0x00,0x10,0x40,0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x80,0x00,0x00,0x08,0x10,
- 0x00,0x00,0x10,0x80,0x00,0x00,0x08,0x10,0x00,0x00,0x30,0x00,0x01,0x00,0x04,
- 0x18,0x00,0x00,0x20,0x00,0x02,0x00,0x02,0x08,0x00,0x00,0x20,0x00,0x0c,0x80,
- 0x01,0x08,0x00,0x00,0x60,0x00,0x30,0x60,0x00,0x0c,0x00,0x00,0x40,0x00,0xc0,
- 0x1f,0x00,0x04,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x01,
- 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x01,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0f,0xc0,0x0f,0x00,0x00,0x00,
- 0x00,0x40,0x10,0x20,0x10,0x00,0x00,0x00,0x00,0x20,0x60,0x30,0x20,0x00,0x00,
- 0x00,0x00,0x20,0xc0,0x18,0x20,0x00,0x00,0xc0,0x7f,0x10,0x80,0x0d,0x40,0xe0,
- 0x01,0x70,0xc0,0x18,0x00,0x05,0x40,0x1c,0x06,0x10,0x00,0x0f,0x00,0x05,0x80,
- 0x07,0x08,0x08,0x00,0x06,0x00,0x05,0x80,0x01,0x08,0x08,0x00,0x18,0x00,0x05,
- 0xc0,0x00,0x10,0x04,0x00,0x30,0x00,0x05,0x30,0x00,0x10,0x04,0x00,0x00,0x80,
- 0x08,0x18,0x00,0x20,0x04,0x00,0x00,0x80,0x08,0x00,0x00,0x20,0x04,0x00,0x00,
- 0x40,0x10,0x00,0x00,0x20,0x24,0x00,0x00,0x40,0x10,0x00,0x00,0x22,0x24,0x00,
- 0x00,0x40,0x10,0x00,0x00,0x22,0x44,0x00,0x00,0x40,0x10,0x00,0x00,0x11,0x84,
- 0x01,0x00,0xc0,0x18,0x00,0xc0,0x10,0x08,0x00,0x00,0x80,0x08,0x00,0x00,0x08,
- 0x30,0x00,0x00,0x80,0x08,0x00,0x00,0x04,0xe0,0xff,0xff,0xff,0xf8,0xff,0xff,
- 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00};
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00, 0x00,
+   0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+   0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00,
+   0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+   0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
+   0x00, 0x08, 0x00, 0xc0, 0x1f, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0x30,
+   0x60, 0x00, 0x20, 0x00, 0x00, 0xf8, 0xff, 0x0f, 0x80, 0xff, 0x3f, 0x00,
+   0x00, 0x00, 0x02, 0x02, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01,
+   0x00, 0x84, 0x01, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x08, 0x01, 0x00,
+   0x00, 0x80, 0x80, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x80, 0x40, 0x00,
+   0x00, 0x10, 0x02, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x10, 0x04, 0x00,
+   0x00, 0x40, 0x20, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x60, 0x20, 0x00,
+   0x00, 0x20, 0x0c, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x20, 0x08, 0x00,
+   0x00, 0x20, 0x20, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x10, 0x20, 0x00,
+   0x00, 0x20, 0x10, 0x00, 0x00, 0x10, 0x20, 0x00, 0x00, 0x20, 0x10, 0x00,
+   0x00, 0x10, 0x20, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x10, 0x40, 0x00,
+   0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x10, 0x10, 0x00,
+   0x00, 0x10, 0x80, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x10, 0x80, 0x00,
+   0x00, 0x08, 0x10, 0x00, 0x00, 0x30, 0x00, 0x01, 0x00, 0x04, 0x18, 0x00,
+   0x00, 0x20, 0x00, 0x02, 0x00, 0x02, 0x08, 0x00, 0x00, 0x20, 0x00, 0x0c,
+   0x80, 0x01, 0x08, 0x00, 0x00, 0x60, 0x00, 0x30, 0x60, 0x00, 0x0c, 0x00,
+   0x00, 0x40, 0x00, 0xc0, 0x1f, 0x00, 0x04, 0x00, 0x00, 0xc0, 0x00, 0x00,
+   0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
+   0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0xc0, 0x0f, 0x00, 0x00,
+   0x00, 0x00, 0x40, 0x10, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x20, 0x60,
+   0x30, 0x20, 0x00, 0x00, 0x00, 0x00, 0x20, 0xc0, 0x18, 0x20, 0x00, 0x00,
+   0xc0, 0x7f, 0x10, 0x80, 0x0d, 0x40, 0xe0, 0x01, 0x70, 0xc0, 0x18, 0x00,
+   0x05, 0x40, 0x1c, 0x06, 0x10, 0x00, 0x0f, 0x00, 0x05, 0x80, 0x07, 0x08,
+   0x08, 0x00, 0x06, 0x00, 0x05, 0x80, 0x01, 0x08, 0x08, 0x00, 0x18, 0x00,
+   0x05, 0xc0, 0x00, 0x10, 0x04, 0x00, 0x30, 0x00, 0x05, 0x30, 0x00, 0x10,
+   0x04, 0x00, 0x00, 0x80, 0x08, 0x18, 0x00, 0x20, 0x04, 0x00, 0x00, 0x80,
+   0x08, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x20,
+   0x24, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x22, 0x24, 0x00, 0x00, 0x40,
+   0x10, 0x00, 0x00, 0x22, 0x44, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x11,
+   0x84, 0x01, 0x00, 0xc0, 0x18, 0x00, 0xc0, 0x10, 0x08, 0x00, 0x00, 0x80,
+   0x08, 0x00, 0x00, 0x08, 0x30, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x04,
+   0xe0, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
index a6e03bfbbd27788ea4fff724e002ac9112c18886..fab867b517d654ccad527de1a7a0c9f6b01eaa36 100644 (file)
@@ -13,7 +13,6 @@ static char * nose_f1_xpm[] = {
 "                                                                ",
 "                                                                ",
 "                                                                ",
-"                                                                ",
 "                      .....................                     ",
 "                      .XXXXXXXXXXXXXXXXXXX.                     ",
 "                      .XXXXXXXXXXXXXXXXXXX.                     ",
@@ -71,4 +70,5 @@ static char * nose_f1_xpm[] = {
 "    ..@@@@@@@@@@@@@@@@@@@@@@@@@.   .@@@@@@@@@@@@@@@@@@@@@@.     ",
 "     ...........................   .......................      ",
 "                                                                ",
+"                                                                ",
 "                                                                "};
index 6851b201b53f4371c0a44025a782ddbd40ee3f4f..0e255768037e39522baf491281a5a6be112afe89 100644 (file)
@@ -1,38 +1,46 @@
 #define nose_f2_width 64
 #define nose_f2_height 64
 static unsigned char nose_f2_bits[] = {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x40,0x00,
- 0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,
- 0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
- 0x40,0x00,0x00,0x04,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
- 0x08,0x00,0xe0,0x0f,0x00,0x20,0x00,0x00,0x08,0x00,0x18,0x30,0x00,0x20,0x00,
- 0x00,0xf8,0xff,0x07,0xc0,0xff,0x3f,0x00,0x00,0x00,0x02,0x01,0x00,0x81,0x00,
- 0x00,0x00,0x00,0x83,0x00,0x00,0x82,0x01,0x00,0x00,0x00,0x41,0x00,0x00,0x04,
- 0x01,0x00,0x00,0x80,0x40,0x00,0x00,0x04,0x02,0x00,0x00,0x80,0x20,0x00,0x00,
- 0x08,0x02,0x00,0x00,0x40,0x20,0x00,0x00,0x08,0x04,0x00,0x00,0x40,0x10,0x00,
- 0x00,0x10,0x04,0x00,0x00,0x60,0x10,0x00,0x00,0x10,0x0c,0x00,0x00,0x20,0x10,
- 0x00,0x00,0x10,0x08,0x00,0x00,0x30,0x10,0x00,0x00,0x10,0x08,0x00,0x00,0x10,
- 0x10,0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x10,0x00,0x00,
- 0x10,0x10,0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x20,0x00,0x00,0x08,0x10,0x00,
- 0x00,0x10,0x20,0x00,0x00,0x08,0x10,0x00,0x00,0x10,0x40,0x00,0x00,0x04,0x10,
- 0x00,0x00,0x30,0x40,0x00,0x00,0x04,0x10,0x00,0x00,0x20,0x80,0x00,0x00,0x02,
- 0x18,0x00,0x00,0x20,0x00,0x01,0x00,0x01,0x08,0x00,0x00,0x60,0x00,0x06,0xc0,
- 0x00,0x08,0x00,0x00,0x80,0x00,0x18,0x30,0x00,0x0c,0x00,0x00,0x80,0x00,0xe0,
- 0x0f,0x00,0x04,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x01,
- 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x01,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x0f,0x00,0x00,0x00,
- 0x00,0xff,0x00,0x04,0x10,0x00,0x00,0x00,0xe0,0x00,0x07,0x02,0x10,0x00,0x00,
- 0x00,0x30,0x00,0x8c,0x01,0x20,0x00,0x00,0x00,0x0c,0x00,0x90,0x00,0x20,0x00,
- 0x00,0x00,0x04,0x03,0x60,0x00,0x20,0x00,0x00,0x00,0xc2,0x00,0xc0,0x00,0x20,
- 0x00,0x00,0x00,0x42,0x00,0x00,0x01,0x20,0x00,0x00,0x00,0x21,0x00,0x00,0x02,
- 0x20,0x00,0x00,0x00,0x21,0x00,0x00,0x06,0x20,0x00,0x00,0x00,0x21,0x00,0x00,
- 0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x03,0x00,
- 0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x02,
- 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x20,0x00,0x00,0x00,
- 0x18,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x10,0x00,0x00,
- 0x00,0xc0,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00};
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00, 0x00,
+   0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+   0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00,
+   0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+   0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
+   0x00, 0x08, 0x00, 0xe0, 0x0f, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0x18,
+   0x30, 0x00, 0x20, 0x00, 0x00, 0xf8, 0xff, 0x07, 0xc0, 0xff, 0x3f, 0x00,
+   0x00, 0x00, 0x02, 0x01, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00,
+   0x00, 0x82, 0x01, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x04, 0x01, 0x00,
+   0x00, 0x80, 0x40, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x80, 0x20, 0x00,
+   0x00, 0x08, 0x02, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00, 0x08, 0x04, 0x00,
+   0x00, 0x40, 0x10, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x60, 0x10, 0x00,
+   0x00, 0x10, 0x0c, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x10, 0x08, 0x00,
+   0x00, 0x30, 0x10, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x10, 0x10, 0x00,
+   0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00,
+   0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x20, 0x00,
+   0x00, 0x08, 0x10, 0x00, 0x00, 0x10, 0x20, 0x00, 0x00, 0x08, 0x10, 0x00,
+   0x00, 0x10, 0x40, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x30, 0x40, 0x00,
+   0x00, 0x04, 0x10, 0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x02, 0x18, 0x00,
+   0x00, 0x20, 0x00, 0x01, 0x00, 0x01, 0x08, 0x00, 0x00, 0x60, 0x00, 0x06,
+   0xc0, 0x00, 0x08, 0x00, 0x00, 0x80, 0x00, 0x18, 0x30, 0x00, 0x0c, 0x00,
+   0x00, 0x80, 0x00, 0xe0, 0x0f, 0x00, 0x04, 0x00, 0x00, 0x80, 0x01, 0x00,
+   0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
+   0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00,
+   0x00, 0x00, 0xff, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x07,
+   0x02, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x8c, 0x01, 0x20, 0x00, 0x00,
+   0x00, 0x0c, 0x00, 0x90, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x03, 0x60,
+   0x00, 0x20, 0x00, 0x00, 0x00, 0xc2, 0x00, 0xc0, 0x00, 0x20, 0x00, 0x00,
+   0x00, 0x42, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00,
+   0x02, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x06, 0x20, 0x00, 0x00,
+   0x00, 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+   0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+   0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+   0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+   0x00, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+   0x00, 0x10, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
index 3763b58df6960fadae6abe0734c43fb8d1c08f42..dd442acfb1ac9a20027218d76907ae90fd5ea196 100644 (file)
@@ -13,7 +13,6 @@ static char * nose_f2_xpm[] = {
 "                                                                ",
 "                                                                ",
 "                                                                ",
-"                                                                ",
 "                      .....................                     ",
 "                      .XXXXXXXXXXXXXXXXXXX.                     ",
 "                      .XXXXXXXXXXXXXXXXXXX.                     ",
@@ -71,4 +70,5 @@ static char * nose_f2_xpm[] = {
 "              ..............................                    ",
 "                                                                ",
 "                                                                ",
+"                                                                ",
 "                                                                "};
index e70f229338ab5941ed082fdb000b3a11e220ab5b..77a40ef02a49eb01d165960a10b2015faa53a891 100644 (file)
@@ -1,38 +1,46 @@
 #define nose_f3_width 64
 #define nose_f3_height 64
 static unsigned char nose_f3_bits[] = {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x20,0x00,
- 0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,
- 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,
- 0x20,0x00,0x00,0x02,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,
- 0x04,0x00,0xf0,0x07,0x00,0x10,0x00,0x00,0x04,0x00,0x0c,0x18,0x00,0x10,0x00,
- 0x00,0xfc,0xff,0x03,0xe0,0xff,0x1f,0x00,0x00,0x00,0x81,0x00,0x80,0x40,0x00,
- 0x00,0x00,0x80,0x41,0x00,0x00,0xc1,0x00,0x00,0x00,0x80,0x20,0x00,0x00,0x82,
- 0x00,0x00,0x00,0x40,0x20,0x00,0x00,0x02,0x01,0x00,0x00,0x40,0x10,0x00,0x00,
- 0x04,0x01,0x00,0x00,0x20,0x10,0x00,0x00,0x04,0x02,0x00,0x00,0x20,0x08,0x00,
- 0x00,0x08,0x02,0x00,0x00,0x30,0x08,0x00,0x00,0x08,0x06,0x00,0x00,0x10,0x08,
- 0x00,0x00,0x08,0x04,0x00,0x00,0x10,0x08,0x00,0x00,0x08,0x0c,0x00,0x00,0x08,
- 0x08,0x00,0x00,0x08,0x08,0x00,0x00,0x08,0x08,0x00,0x00,0x08,0x08,0x00,0x00,
- 0x08,0x08,0x00,0x00,0x08,0x08,0x00,0x00,0x08,0x10,0x00,0x00,0x04,0x08,0x00,
- 0x00,0x08,0x10,0x00,0x00,0x04,0x08,0x00,0x00,0x08,0x20,0x00,0x00,0x02,0x08,
- 0x00,0x00,0x08,0x20,0x00,0x00,0x02,0x0c,0x00,0x00,0x18,0x40,0x00,0x00,0x01,
- 0x04,0x00,0x00,0x10,0x80,0x00,0x80,0x00,0x04,0x00,0x00,0x10,0x00,0x03,0x60,
- 0x00,0x06,0x00,0x00,0x30,0x00,0x0c,0x18,0x00,0x01,0x00,0x00,0x20,0x00,0xf0,
- 0x07,0x00,0x01,0x00,0x00,0x60,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x40,0x00,
- 0x00,0x00,0x80,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x1f,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x08,0x20,0x00,0xff,0x00,0x00,0x00,0x00,0x08,0x40,0xe0,0x00,0x07,0x00,
- 0x00,0x00,0x04,0x80,0x31,0x00,0x0c,0x00,0x00,0x00,0x04,0x00,0x09,0x00,0x30,
- 0x00,0x00,0x00,0x04,0x00,0x06,0xc0,0x20,0x00,0x00,0x00,0x04,0x00,0x03,0x00,
- 0x43,0x00,0x00,0x00,0x04,0x80,0x00,0x00,0x42,0x00,0x00,0x00,0x04,0x40,0x00,
- 0x00,0x84,0x00,0x00,0x00,0x04,0x60,0x00,0x00,0x84,0x00,0x00,0x00,0x04,0x00,
- 0x00,0x00,0x84,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x02,
- 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,
- 0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x20,0x00,0x00,
- 0x00,0x04,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x0e,0x00,
- 0x00,0x00,0xf0,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00};
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x03, 0x00, 0x00,
+   0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+   0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00,
+   0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+   0x00, 0x02, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00,
+   0x00, 0x04, 0x00, 0xf0, 0x07, 0x00, 0x10, 0x00, 0x00, 0x04, 0x00, 0x0c,
+   0x18, 0x00, 0x10, 0x00, 0x00, 0xfc, 0xff, 0x03, 0xe0, 0xff, 0x1f, 0x00,
+   0x00, 0x00, 0x81, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0x80, 0x41, 0x00,
+   0x00, 0xc1, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0x82, 0x00, 0x00,
+   0x00, 0x40, 0x20, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x40, 0x10, 0x00,
+   0x00, 0x04, 0x01, 0x00, 0x00, 0x20, 0x10, 0x00, 0x00, 0x04, 0x02, 0x00,
+   0x00, 0x20, 0x08, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x30, 0x08, 0x00,
+   0x00, 0x08, 0x06, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x08, 0x04, 0x00,
+   0x00, 0x10, 0x08, 0x00, 0x00, 0x08, 0x0c, 0x00, 0x00, 0x08, 0x08, 0x00,
+   0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00,
+   0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x10, 0x00,
+   0x00, 0x04, 0x08, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x04, 0x08, 0x00,
+   0x00, 0x08, 0x20, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x08, 0x20, 0x00,
+   0x00, 0x02, 0x0c, 0x00, 0x00, 0x18, 0x40, 0x00, 0x00, 0x01, 0x04, 0x00,
+   0x00, 0x10, 0x80, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x10, 0x00, 0x03,
+   0x60, 0x00, 0x06, 0x00, 0x00, 0x30, 0x00, 0x0c, 0x18, 0x00, 0x01, 0x00,
+   0x00, 0x20, 0x00, 0xf0, 0x07, 0x00, 0x01, 0x00, 0x00, 0x60, 0x00, 0x00,
+   0x00, 0x80, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+   0x00, 0x80, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x08, 0x20, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40,
+   0xe0, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x80, 0x31, 0x00, 0x0c, 0x00,
+   0x00, 0x00, 0x04, 0x00, 0x09, 0x00, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00,
+   0x06, 0xc0, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x43, 0x00,
+   0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x04, 0x40,
+   0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x60, 0x00, 0x00, 0x84, 0x00,
+   0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x02, 0x00,
+   0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xc0, 0x00,
+   0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00,
+   0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00,
+   0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00,
+   0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x03, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
index c60c5f373ca92a90f49c14c6ae81f81d95f386ea..66ef3235af7376f2b798d06e09934800bc83da9f 100644 (file)
@@ -13,7 +13,6 @@ static char * nose_f3_xpm[] = {
 "                                                                ",
 "                                                                ",
 "                                                                ",
-"                                                                ",
 "                     .....................                      ",
 "                     .XXXXXXXXXXXXXXXXXXX.                      ",
 "                     .XXXXXXXXXXXXXXXXXXX.                      ",
@@ -71,4 +70,5 @@ static char * nose_f3_xpm[] = {
 "                    ..............................              ",
 "                                                                ",
 "                                                                ",
+"                                                                ",
 "                                                                "};
index 024eead8bdcb899ed78cc763ee22fbd7fa46c61b..03ff1dcc3927db8a4d9fd9d40d3af4f46b22bee4 100644 (file)
@@ -1,38 +1,46 @@
 #define nose_f4_width 64
 #define nose_f4_height 64
 static unsigned char nose_f4_bits[] = {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0xfc,0xff,0x01,0x00,0x00,0x00,0x00,0xc0,0x03,0x00,0x1e,0x00,
- 0x00,0x00,0x00,0x38,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,
- 0x03,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x40,0x00,0x00,0x00,
- 0x00,0x08,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x10,0x00,0x80,
- 0x1f,0x00,0x40,0x00,0x00,0x08,0x00,0x60,0x60,0x00,0x80,0x00,0x00,0x08,0x00,
- 0x10,0x80,0x00,0x80,0x00,0x00,0x04,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x04,
- 0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x18,0x80,0x01,0x00,0x02,0x00,
- 0x02,0x00,0x68,0x60,0x01,0x00,0x02,0x00,0x02,0x00,0x88,0x1f,0x01,0x00,0x02,
- 0x00,0x02,0x00,0x08,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x10,0x80,0x00,0x00,
- 0x03,0x00,0x06,0x00,0x60,0x60,0x00,0x80,0x02,0x00,0x0c,0x00,0x80,0x1f,0x00,
- 0x40,0x01,0x00,0x14,0x00,0x00,0x00,0x00,0x20,0x01,0x00,0x28,0x00,0x00,0x00,
- 0x00,0x90,0x00,0x00,0x50,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0xa0,0x01,0x00,
- 0x00,0x00,0x26,0x00,0x00,0x40,0x1e,0x00,0x00,0xc0,0x11,0x00,0x00,0x80,0xe1,
- 0x03,0x00,0x3c,0x0c,0x00,0x00,0x00,0x0e,0xfc,0xff,0x83,0x03,0x00,0x00,0x00,
- 0xf0,0x01,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x0f,0x00,0x00,0x00,
- 0x00,0x80,0x03,0x00,0x0c,0x00,0x00,0x00,0x00,0x80,0x02,0x00,0x14,0x00,0x00,
- 0x00,0x00,0x60,0x04,0x00,0x12,0x00,0x00,0xc0,0x7f,0x10,0x04,0x00,0x22,0xe0,
- 0x01,0x70,0xc0,0x18,0x08,0x00,0x61,0x1c,0x06,0x10,0x00,0x0f,0x30,0xc0,0x80,
- 0x07,0x08,0x08,0x00,0x06,0xc0,0x3f,0x80,0x01,0x08,0x08,0x00,0x18,0x00,0x02,
- 0xc0,0x00,0x10,0x04,0x00,0x30,0x00,0x05,0x30,0x00,0x10,0x04,0x00,0x00,0x80,
- 0x08,0x18,0x00,0x20,0x04,0x00,0x00,0x80,0x08,0x00,0x00,0x20,0x04,0x00,0x00,
- 0x40,0x10,0x00,0x00,0x20,0x24,0x00,0x00,0x40,0x10,0x00,0x00,0x22,0x24,0x00,
- 0x00,0x40,0x10,0x00,0x00,0x22,0x44,0x00,0x00,0x40,0x10,0x00,0x00,0x11,0x84,
- 0x01,0x00,0xc0,0x18,0x00,0xc0,0x10,0x08,0x00,0x00,0x80,0x08,0x00,0x00,0x08,
- 0x30,0x00,0x00,0x80,0x08,0x00,0x00,0x04,0xe0,0xff,0xff,0xff,0xf8,0xff,0xff,
- 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00};
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x01, 0x00, 0x00,
+   0x00, 0x00, 0xc0, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00,
+   0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03, 0x00,
+   0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x00, 0x00,
+   0x00, 0x00, 0x08, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00,
+   0x00, 0x10, 0x00, 0x80, 0x1f, 0x00, 0x40, 0x00, 0x00, 0x08, 0x00, 0x60,
+   0x60, 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x10, 0x80, 0x00, 0x80, 0x00,
+   0x00, 0x04, 0x00, 0x08, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x08,
+   0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x18, 0x80, 0x01, 0x00, 0x02,
+   0x00, 0x02, 0x00, 0x68, 0x60, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x88,
+   0x1f, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x08, 0x00, 0x01, 0x00, 0x02,
+   0x00, 0x02, 0x00, 0x10, 0x80, 0x00, 0x00, 0x03, 0x00, 0x06, 0x00, 0x60,
+   0x60, 0x00, 0x80, 0x02, 0x00, 0x0c, 0x00, 0x80, 0x1f, 0x00, 0x40, 0x01,
+   0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x28, 0x00, 0x00,
+   0x00, 0x00, 0x90, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00,
+   0x00, 0xa0, 0x01, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x40, 0x1e, 0x00,
+   0x00, 0xc0, 0x11, 0x00, 0x00, 0x80, 0xe1, 0x03, 0x00, 0x3c, 0x0c, 0x00,
+   0x00, 0x00, 0x0e, 0xfc, 0xff, 0x83, 0x03, 0x00, 0x00, 0x00, 0xf0, 0x01,
+   0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00,
+   0x00, 0x00, 0x80, 0x03, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02,
+   0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x60, 0x04, 0x00, 0x12, 0x00, 0x00,
+   0xc0, 0x7f, 0x10, 0x04, 0x00, 0x22, 0xe0, 0x01, 0x70, 0xc0, 0x18, 0x08,
+   0x00, 0x61, 0x1c, 0x06, 0x10, 0x00, 0x0f, 0x30, 0xc0, 0x80, 0x07, 0x08,
+   0x08, 0x00, 0x06, 0xc0, 0x3f, 0x80, 0x01, 0x08, 0x08, 0x00, 0x18, 0x00,
+   0x02, 0xc0, 0x00, 0x10, 0x04, 0x00, 0x30, 0x00, 0x05, 0x30, 0x00, 0x10,
+   0x04, 0x00, 0x00, 0x80, 0x08, 0x18, 0x00, 0x20, 0x04, 0x00, 0x00, 0x80,
+   0x08, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x20,
+   0x24, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x22, 0x24, 0x00, 0x00, 0x40,
+   0x10, 0x00, 0x00, 0x22, 0x44, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x11,
+   0x84, 0x01, 0x00, 0xc0, 0x18, 0x00, 0xc0, 0x10, 0x08, 0x00, 0x00, 0x80,
+   0x08, 0x00, 0x00, 0x08, 0x30, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x04,
+   0xe0, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
index faa52e0382c26451532b630a31ab3bc0b8c488be..d910e25a96b8fba6107bc8f3e4357b0cd29b2c7a 100644 (file)
@@ -21,7 +21,6 @@ static char * nose_f4_xpm[] = {
 "                                                                ",
 "                                                                ",
 "                                                                ",
-"                                                                ",
 "                          ...............                       ",
 "                      ....XXXXXXXXXXXXXXX....                   ",
 "                   ...XXXXXXXXXXXXXXXXXXXXXXX...                ",
@@ -70,4 +69,5 @@ static char * nose_f4_xpm[] = {
 "    ..@@@@@@@@@@@@@@@@@@@@@@@@@.   .@@@@@@@@@@@@@@@@@@@@@@.     ",
 "     ...........................   .......................      ",
 "                                                                ",
+"                                                                ",
 "                                                                "};
index e3cb70306a304e9f1e570937a966299fcf2455a3..bc38b02049af217b3c24fd839985cf9337f1ad1e 100644 (file)
@@ -1,38 +1,46 @@
 #define nose_l1_width 64
 #define nose_l1_height 64
 static unsigned char nose_l1_bits[] = {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x40,0x00,
- 0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,
- 0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
- 0x40,0x00,0x00,0x04,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
- 0x08,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x20,0x00,
- 0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0xf0,0x03,0x00,0x00,0x80,0x00,
- 0x00,0x00,0x0e,0x0c,0x00,0x00,0x80,0x01,0x00,0x00,0x03,0x30,0x00,0x00,0x00,
- 0x01,0x00,0x80,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x40,0x00,0xc0,0x00,0x00,
- 0x00,0x02,0x00,0x20,0x00,0x80,0x00,0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00,
- 0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x08,0x00,0x00,
- 0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,
- 0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,
- 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,
- 0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,
- 0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x01,0x00,0x00,
- 0x18,0x00,0x20,0x00,0x00,0x01,0x00,0x00,0x08,0x00,0x40,0x00,0x80,0x00,0x00,
- 0x00,0x08,0x00,0x80,0x00,0x40,0x00,0x00,0x00,0x0c,0x00,0x00,0x01,0x20,0x00,
- 0x00,0x00,0x04,0x00,0x00,0x06,0x18,0x00,0x00,0x00,0x06,0x00,0x00,0xf8,0x07,
- 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0x01,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x0f,0x00,0x00,0x00,
- 0x00,0xff,0x00,0x04,0x10,0x00,0x00,0x00,0xc0,0x00,0x03,0x03,0x10,0x00,0x00,
- 0x00,0x30,0x00,0x0c,0x01,0x20,0x00,0x00,0x00,0x08,0x00,0x98,0x00,0x20,0x00,
- 0x00,0x00,0x0c,0x03,0x60,0x00,0x20,0x00,0x00,0x00,0xc2,0x00,0xc0,0x00,0x20,
- 0x00,0x00,0x00,0x42,0x00,0x80,0x00,0x20,0x00,0x00,0x00,0x21,0x00,0x00,0x01,
- 0x20,0x00,0x00,0x00,0x21,0x00,0x00,0x01,0x20,0x00,0x00,0x00,0x21,0x00,0x00,
- 0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x01,0x00,
- 0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x02,
- 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x20,0x00,0x00,0x00,
- 0x18,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x10,0x00,0x00,
- 0x00,0xc0,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00};
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00, 0x00,
+   0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+   0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00,
+   0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+   0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
+   0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0x00,
+   0x00, 0x00, 0x20, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
+   0x00, 0xf0, 0x03, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x0e, 0x0c, 0x00,
+   0x00, 0x80, 0x01, 0x00, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00,
+   0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x40, 0x00, 0xc0, 0x00,
+   0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x00, 0x04, 0x00,
+   0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+   0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+   0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+   0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x18, 0x00,
+   0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x80, 0x00,
+   0x00, 0x00, 0x08, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0c, 0x00,
+   0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x18, 0x00,
+   0x00, 0x00, 0x06, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x02, 0x00,
+   0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00,
+   0x00, 0x00, 0xff, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x03,
+   0x03, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x0c, 0x01, 0x20, 0x00, 0x00,
+   0x00, 0x08, 0x00, 0x98, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0c, 0x03, 0x60,
+   0x00, 0x20, 0x00, 0x00, 0x00, 0xc2, 0x00, 0xc0, 0x00, 0x20, 0x00, 0x00,
+   0x00, 0x42, 0x00, 0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00,
+   0x01, 0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00,
+   0x00, 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+   0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+   0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+   0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+   0x00, 0x18, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+   0x00, 0x10, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
index 205d18be69820c22f44d4c264b50420374c21ef8..12bb2eb9a865e9cd068d967ec37e776b0991b7ed 100644 (file)
@@ -13,7 +13,6 @@ static char * nose_l1_xpm[] = {
 "                                                                ",
 "                                                                ",
 "                                                                ",
-"                                                                ",
 "                      .....................                     ",
 "                      .XXXXXXXXXXXXXXXXXXX.                     ",
 "                      .XXXXXXXXXXXXXXXXXXX.                     ",
@@ -71,4 +70,5 @@ static char * nose_l1_xpm[] = {
 "              ..............................                    ",
 "                                                                ",
 "                                                                ",
+"                                                                ",
 "                                                                "};
index fa39343beb9a473dacd10240d42e595430096212..1a2e77f10eda1a7ea625c34d9e2942a5f4877ca7 100644 (file)
@@ -1,38 +1,46 @@
 #define nose_l2_width 64
 #define nose_l2_height 64
 static unsigned char nose_l2_bits[] = {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x40,0x00,
- 0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,
- 0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
- 0x40,0x00,0x00,0x04,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
- 0x08,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x20,0x00,
- 0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0xf0,0x03,0x00,0x00,0x80,0x00,
- 0x00,0x00,0x0e,0x0c,0x00,0x00,0x80,0x01,0x00,0x00,0x03,0x30,0x00,0x00,0x00,
- 0x01,0x00,0x80,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x40,0x00,0xc0,0x00,0x00,
- 0x00,0x02,0x00,0x20,0x00,0x80,0x00,0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00,
- 0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x08,0x00,0x00,
- 0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,
- 0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,
- 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,
- 0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,
- 0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x01,0x00,0x00,
- 0x18,0x00,0x10,0x00,0x00,0x01,0x00,0x00,0x08,0x00,0x20,0x00,0x80,0x00,0x00,
- 0x00,0x08,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x0c,0x00,0x80,0x00,0x20,0x00,
- 0x00,0x00,0xe4,0x00,0x00,0x03,0x18,0x00,0x00,0x00,0x26,0x03,0x00,0xfc,0x07,
- 0x00,0x00,0x00,0x12,0x0c,0x00,0x00,0xf8,0xff,0xff,0xff,0x11,0x10,0x80,0x1f,
- 0x00,0x00,0x00,0x00,0x08,0x20,0x60,0x60,0xc0,0x07,0x00,0x00,0x04,0x40,0x10,
- 0xc0,0x20,0x08,0x00,0x1f,0x02,0x40,0x08,0x00,0x21,0x10,0xc0,0x60,0x02,0x40,
- 0x04,0x00,0x12,0x20,0x20,0x80,0x02,0x20,0xc2,0x00,0x14,0x40,0x18,0x00,0x03,
- 0x20,0x22,0x00,0x0c,0x80,0x04,0x03,0x02,0x10,0x12,0x00,0x08,0x80,0x86,0x00,
- 0x04,0x10,0x12,0x00,0x10,0x80,0x42,0x00,0x18,0x08,0x12,0x00,0x10,0x40,0x42,
- 0x00,0x00,0x04,0x02,0x00,0x20,0x40,0x42,0x00,0x00,0x04,0x02,0x00,0x00,0x20,
- 0x42,0x00,0x00,0x02,0x04,0x00,0x00,0x20,0x02,0x00,0x00,0x01,0x04,0x00,0x00,
- 0x20,0x02,0x00,0x00,0x01,0x08,0x00,0x00,0x20,0x04,0x00,0x80,0x00,0x10,0x00,
- 0x00,0x20,0x0c,0x00,0x80,0x00,0x60,0x00,0x00,0x10,0x08,0x00,0x40,0x00,0x80,
- 0xff,0xff,0x0f,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0x0f,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00};
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x07, 0x00, 0x00,
+   0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+   0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00,
+   0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+   0x00, 0x04, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
+   0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00, 0x00,
+   0x00, 0x00, 0x20, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
+   0x00, 0xf0, 0x03, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x0e, 0x0c, 0x00,
+   0x00, 0x80, 0x01, 0x00, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00,
+   0x80, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x40, 0x00, 0xc0, 0x00,
+   0x00, 0x00, 0x02, 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x00, 0x04, 0x00,
+   0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x0c, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+   0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+   0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+   0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x18, 0x00,
+   0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x00, 0x20, 0x00, 0x80, 0x00,
+   0x00, 0x00, 0x08, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0c, 0x00,
+   0x80, 0x00, 0x20, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x03, 0x18, 0x00,
+   0x00, 0x00, 0x26, 0x03, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x12, 0x0c,
+   0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x11, 0x10, 0x80, 0x1f, 0x00, 0x00,
+   0x00, 0x00, 0x08, 0x20, 0x60, 0x60, 0xc0, 0x07, 0x00, 0x00, 0x04, 0x40,
+   0x10, 0xc0, 0x20, 0x08, 0x00, 0x1f, 0x02, 0x40, 0x08, 0x00, 0x21, 0x10,
+   0xc0, 0x60, 0x02, 0x40, 0x04, 0x00, 0x12, 0x20, 0x20, 0x80, 0x02, 0x20,
+   0xc2, 0x00, 0x14, 0x40, 0x18, 0x00, 0x03, 0x20, 0x22, 0x00, 0x0c, 0x80,
+   0x04, 0x03, 0x02, 0x10, 0x12, 0x00, 0x08, 0x80, 0x86, 0x00, 0x04, 0x10,
+   0x12, 0x00, 0x10, 0x80, 0x42, 0x00, 0x18, 0x08, 0x12, 0x00, 0x10, 0x40,
+   0x42, 0x00, 0x00, 0x04, 0x02, 0x00, 0x20, 0x40, 0x42, 0x00, 0x00, 0x04,
+   0x02, 0x00, 0x00, 0x20, 0x42, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x20,
+   0x02, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x01,
+   0x08, 0x00, 0x00, 0x20, 0x04, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x20,
+   0x0c, 0x00, 0x80, 0x00, 0x60, 0x00, 0x00, 0x10, 0x08, 0x00, 0x40, 0x00,
+   0x80, 0xff, 0xff, 0x0f, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
index f08a72eb96723ca706539fa644d4f95167b0a2cb..37e40a655999f9bbc3edc2eb118269638da9d911 100644 (file)
@@ -13,7 +13,6 @@ static char * nose_l2_xpm[] = {
 "                                                                ",
 "                                                                ",
 "                                                                ",
-"                                                                ",
 "                      .....................                     ",
 "                      .XXXXXXXXXXXXXXXXXXX.                     ",
 "                      .XXXXXXXXXXXXXXXXXXX.                     ",
@@ -71,4 +70,5 @@ static char * nose_l2_xpm[] = {
 "                                                                ",
 "                                                                ",
 "                                                                ",
+"                                                                ",
 "                                                                "};
index 72df86c219fd80386e52f00c351aac17fa74eec2..3e4106345c0c24c112daa8fd7cd32c12b616dfe7 100644 (file)
@@ -1,38 +1,46 @@
 #define nose_r1_width 64
 #define nose_r1_height 64
 static unsigned char nose_r1_bits[] = {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x20,0x00,
- 0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,
- 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,
- 0x20,0x00,0x00,0x02,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,
- 0x04,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x10,0x00,
- 0x00,0xfc,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x01,0x00,0x00,0xc0,0x0f,
- 0x00,0x00,0x80,0x01,0x00,0x00,0x30,0x70,0x00,0x00,0x80,0x00,0x00,0x00,0x0c,
- 0xc0,0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x40,0x00,0x00,0x00,
- 0x03,0x00,0x02,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x20,0x00,0x00,
- 0x00,0x00,0x00,0x08,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x00,
- 0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,
- 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,
- 0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,
- 0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,
- 0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x18,0x00,0x00,0x80,0x00,
- 0x00,0x08,0x00,0x10,0x00,0x00,0x80,0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00,
- 0x01,0x00,0x02,0x00,0x30,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x20,0x00,0x00,
- 0x00,0x04,0x80,0x00,0x00,0x60,0x00,0x00,0x00,0x18,0x60,0x00,0x00,0x40,0x00,
- 0x00,0x00,0xe0,0x1f,0x00,0x00,0x80,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x1f,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x08,0x20,0x00,0xff,0x00,0x00,0x00,0x00,0x08,0xc0,0xc0,0x00,0x03,0x00,
- 0x00,0x00,0x04,0x80,0x30,0x00,0x0c,0x00,0x00,0x00,0x04,0x00,0x19,0x00,0x10,
- 0x00,0x00,0x00,0x04,0x00,0x06,0xc0,0x30,0x00,0x00,0x00,0x04,0x00,0x03,0x00,
- 0x43,0x00,0x00,0x00,0x04,0x00,0x01,0x00,0x42,0x00,0x00,0x00,0x04,0x80,0x00,
- 0x00,0x84,0x00,0x00,0x00,0x04,0x80,0x00,0x00,0x84,0x00,0x00,0x00,0x04,0x00,
- 0x00,0x00,0x84,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x02,
- 0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,
- 0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x20,0x00,0x00,
- 0x00,0x04,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x0e,0x00,
- 0x00,0x00,0xf0,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00};
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x03, 0x00, 0x00,
+   0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+   0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00,
+   0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+   0x00, 0x02, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00,
+   0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x04, 0x00, 0x00,
+   0x00, 0x00, 0x10, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00,
+   0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x80, 0x01, 0x00,
+   0x00, 0x30, 0x70, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x0c, 0xc0, 0x00,
+   0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00,
+   0x00, 0x03, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04,
+   0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x30, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+   0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+   0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+   0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x00, 0x80, 0x00, 0x00, 0x08,
+   0x00, 0x10, 0x00, 0x00, 0x80, 0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00,
+   0x00, 0x01, 0x00, 0x02, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01,
+   0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x60, 0x00, 0x00,
+   0x00, 0x18, 0x60, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00,
+   0x00, 0x80, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x08, 0x20, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0,
+   0xc0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x80, 0x30, 0x00, 0x0c, 0x00,
+   0x00, 0x00, 0x04, 0x00, 0x19, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00,
+   0x06, 0xc0, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x43, 0x00,
+   0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0x42, 0x00, 0x00, 0x00, 0x04, 0x80,
+   0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x84, 0x00,
+   0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x02, 0x00,
+   0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, 0x00,
+   0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00,
+   0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x20, 0x00,
+   0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00,
+   0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0x03, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
index 901dd428801e83761c536a56366da5ab42099eaa..58e8b0bfe918abc84d6e29bfcd7cf6c7fd73f132 100644 (file)
@@ -13,7 +13,6 @@ static char * nose_r1_xpm[] = {
 "                                                                ",
 "                                                                ",
 "                                                                ",
-"                                                                ",
 "                     .....................                      ",
 "                     .XXXXXXXXXXXXXXXXXXX.                      ",
 "                     .XXXXXXXXXXXXXXXXXXX.                      ",
@@ -71,4 +70,5 @@ static char * nose_r1_xpm[] = {
 "                    ..............................              ",
 "                                                                ",
 "                                                                ",
+"                                                                ",
 "                                                                "};
index eb750ca7a833413ca272b0ca3673881998a068be..1fdd6b49ada0b0003a9c9365204e42d947383920 100644 (file)
@@ -1,38 +1,46 @@
 #define nose_r2_width 64
 #define nose_r2_height 64
 static unsigned char nose_r2_bits[] = {
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x20,0x00,
- 0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,
- 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,
- 0x20,0x00,0x00,0x02,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,
- 0x04,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x10,0x00,
- 0x00,0xfc,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x01,0x00,0x00,0xc0,0x0f,
- 0x00,0x00,0x80,0x01,0x00,0x00,0x30,0x70,0x00,0x00,0x80,0x00,0x00,0x00,0x0c,
- 0xc0,0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x40,0x00,0x00,0x00,
- 0x03,0x00,0x02,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x20,0x00,0x00,
- 0x00,0x00,0x00,0x08,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x00,
- 0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,
- 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,
- 0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,
- 0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,
- 0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x18,0x00,0x00,0x80,0x00,
- 0x00,0x08,0x00,0x10,0x00,0x00,0x80,0x00,0x00,0x08,0x00,0x10,0x00,0x00,0x00,
- 0x01,0x00,0x04,0x00,0x30,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x27,0x00,0x00,
- 0x00,0x04,0x00,0x01,0xc0,0x64,0x00,0x00,0x00,0x18,0xc0,0x00,0x30,0x48,0x00,
- 0x00,0x00,0xe0,0x3f,0x00,0x08,0x88,0xff,0xff,0xff,0x1f,0x00,0x00,0x04,0x10,
- 0x00,0x00,0x00,0x00,0xf8,0x01,0x02,0x20,0x00,0x00,0xe0,0x03,0x06,0x06,0x02,
- 0x40,0xf8,0x00,0x10,0x04,0x03,0x08,0x02,0x40,0x06,0x03,0x08,0x84,0x00,0x10,
- 0x04,0x40,0x01,0x04,0x04,0x48,0x00,0x20,0x04,0xc0,0x00,0x18,0x02,0x28,0x00,
- 0x43,0x08,0x40,0xc0,0x20,0x01,0x30,0x00,0x44,0x08,0x20,0x00,0x61,0x01,0x10,
- 0x00,0x48,0x10,0x18,0x00,0x42,0x01,0x08,0x00,0x48,0x20,0x00,0x00,0x42,0x02,
- 0x08,0x00,0x48,0x20,0x00,0x00,0x42,0x02,0x04,0x00,0x40,0x40,0x00,0x00,0x42,
- 0x04,0x00,0x00,0x40,0x80,0x00,0x00,0x40,0x04,0x00,0x00,0x20,0x80,0x00,0x00,
- 0x40,0x04,0x00,0x00,0x20,0x00,0x01,0x00,0x20,0x04,0x00,0x00,0x10,0x00,0x01,
- 0x00,0x30,0x04,0x00,0x00,0x08,0x00,0x02,0x00,0x10,0x08,0x00,0x00,0x06,0x00,
- 0x0c,0x00,0x0c,0xf0,0xff,0xff,0x01,0x00,0xf0,0xff,0x03,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00};
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x03, 0x00, 0x00,
+   0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+   0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00,
+   0x00, 0x00, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+   0x00, 0x02, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00,
+   0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x04, 0x00, 0x00,
+   0x00, 0x00, 0x10, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00,
+   0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x80, 0x01, 0x00,
+   0x00, 0x30, 0x70, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x0c, 0xc0, 0x00,
+   0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x40, 0x00, 0x00,
+   0x00, 0x03, 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04,
+   0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x30, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+   0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+   0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+   0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x10, 0x00, 0x18, 0x00, 0x00, 0x80, 0x00, 0x00, 0x08,
+   0x00, 0x10, 0x00, 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00,
+   0x00, 0x01, 0x00, 0x04, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02,
+   0x00, 0x27, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0xc0, 0x64, 0x00, 0x00,
+   0x00, 0x18, 0xc0, 0x00, 0x30, 0x48, 0x00, 0x00, 0x00, 0xe0, 0x3f, 0x00,
+   0x08, 0x88, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00,
+   0x00, 0x00, 0xf8, 0x01, 0x02, 0x20, 0x00, 0x00, 0xe0, 0x03, 0x06, 0x06,
+   0x02, 0x40, 0xf8, 0x00, 0x10, 0x04, 0x03, 0x08, 0x02, 0x40, 0x06, 0x03,
+   0x08, 0x84, 0x00, 0x10, 0x04, 0x40, 0x01, 0x04, 0x04, 0x48, 0x00, 0x20,
+   0x04, 0xc0, 0x00, 0x18, 0x02, 0x28, 0x00, 0x43, 0x08, 0x40, 0xc0, 0x20,
+   0x01, 0x30, 0x00, 0x44, 0x08, 0x20, 0x00, 0x61, 0x01, 0x10, 0x00, 0x48,
+   0x10, 0x18, 0x00, 0x42, 0x01, 0x08, 0x00, 0x48, 0x20, 0x00, 0x00, 0x42,
+   0x02, 0x08, 0x00, 0x48, 0x20, 0x00, 0x00, 0x42, 0x02, 0x04, 0x00, 0x40,
+   0x40, 0x00, 0x00, 0x42, 0x04, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x40,
+   0x04, 0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x40, 0x04, 0x00, 0x00, 0x20,
+   0x00, 0x01, 0x00, 0x20, 0x04, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x30,
+   0x04, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x10, 0x08, 0x00, 0x00, 0x06,
+   0x00, 0x0c, 0x00, 0x0c, 0xf0, 0xff, 0xff, 0x01, 0x00, 0xf0, 0xff, 0x03,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
index ddf0edaf167d090cb0bafa7860494808ddb7f2c5..1a70e6949341f4d5c15cb0fa21c7290d9aecac8e 100644 (file)
@@ -13,7 +13,6 @@ static char * nose_r2_xpm[] = {
 "                                                                ",
 "                                                                ",
 "                                                                ",
-"                                                                ",
 "                     .....................                      ",
 "                     .XXXXXXXXXXXXXXXXXXX.                      ",
 "                     .XXXXXXXXXXXXXXXXXXX.                      ",
@@ -71,4 +70,5 @@ static char * nose_r2_xpm[] = {
 "                                                                ",
 "                                                                ",
 "                                                                ",
+"                                                                ",
 "                                                                "};
index f0fa57f4a0247115e555ec6d300cd31ca24e7614..fa3203cdeff135a263514bbea2ae71166cb19c43 100644 (file)
@@ -11,7 +11,8 @@
  */
 
 /* Make a little guy with a big nose and a hat wanter around the screen,
-   spewing out messages.  Derived from xnlock by Dan Heller <argv@sun.com>.
+   spewing out messages.  Derived from xnlock by 
+   Dan Heller <argv@danheller.com>.
  */
 
 #include "screenhack.h"
index f23746b51c20f8c1f9d514e5b125b0bef945a5f9..916b78fe3a917df7ba9243730f0d86175c41530a 100644 (file)
@@ -66,9 +66,9 @@ stored in the RESOURCE_MANAGER property.
 .BR xscreensaver (1),
 .BR xnlock (1)
 .SH COPYRIGHT
-Copyright 1985, 1990 by Dan Heller <argv@sun.com>.
+Copyright 1985, 1990 by Dan Heller <argv@danheller.com>.
 .SH AUTHOR
-Dan Heller <argv@sun.com>, 1985.
+Dan Heller <argv@danheller.com>, 1985.
 
 Ability to run standalone or with \fIxscreensaver\fP added by 
 Jamie Zawinski <jwz@jwz.org>, 13-aug-92.
index ddace3910fbeb3b942a2d5a321e4a4f472bb84af..e46e93fa97be4cb7247726d7eaafcc07c1c0b09c 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1992, 1994, 1996, 1998
+/* xscreensaver, Copyright (c) 1992, 1994, 1996, 1998, 2001
  *  Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -14,6 +14,7 @@
    John S. Pezaris <pz@hx.lcs.mit.edu>
  */
 
+#include <math.h>
 #include "screenhack.h"
 
 struct projectile {
@@ -29,6 +30,33 @@ struct projectile {
 };
 
 static struct projectile *projectiles, *free_projectiles;
+static struct projectile **sorted_projectiles;
+
+
+/* Slightly whacked, for better explosions
+ */
+#define PI_2000 6284
+
+static int sin_cache[PI_2000];
+static int cos_cache[PI_2000];
+
+static void
+cache(void)
+{               /*needs to be run once. Could easily be */
+  int i;        /*reimplemented to run and cache at compile-time,*/
+  double dA;    /*saving on init_pyro time */
+  for (i=0; i<PI_2000; i++)
+    {
+      dA=sin(((double) (random() % (PI_2000/2)))/1000.0);
+      /*Emulation of spherical distribution*/
+      dA+=asin(frand(1.0))/M_PI_2*0.1;
+      /*Approximating the integration of the binominal, for
+        well-distributed randomness*/
+      cos_cache[i]=(int) (cos(((double)i)/1000.0)*dA*2500.0);
+      sin_cache[i]=(int) (sin(((double)i)/1000.0)*dA*2500.0);
+    }
+}
+
 
 static struct projectile *
 get_projectile (void)
@@ -94,11 +122,13 @@ static struct projectile *
 shrapnel (struct projectile *parent, Display *dpy, Colormap cmap)
 {
   struct projectile *p = get_projectile ();
+  int v;
   if (! p) return 0;
   p->x = parent->x;
   p->y = parent->y;
-  p->dx = (random () % 5000) - 2500 + parent->dx;
-  p->dy = (random () % 5000) - 2500 + parent->dy;
+  v=random () % PI_2000;
+  p->dx =(sin_cache[v]) + parent->dx;
+  p->dy =(cos_cache[v]) + parent->dx;
   p->decay = (random () % 50) - 60;
   p->size = (parent->size * 2) / 3;
   p->fuse = 0;
@@ -134,43 +164,56 @@ init_pyro (Display *dpy, Window window)
   projectiles = 0;
   free_projectiles = 0;
   projectiles = (struct projectile *)
-    calloc (how_many, sizeof (struct projectile));
+    calloc (how_many, sizeof (*projectiles));
+  sorted_projectiles = (struct projectile **)
+    calloc (how_many, sizeof (*sorted_projectiles));
   for (i = 0; i < how_many; i++)
     free_projectile (&projectiles [i]);
+  for (i = 0; i < how_many; i++)
+    sorted_projectiles[i] = &projectiles[i];
   gcv.foreground = default_fg_pixel =
     get_pixel_resource ("foreground", "Foreground", dpy, cmap);
   draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
   gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
   erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
   XClearWindow (dpy, window);
+  cache();  
   return cmap;
 }
 
+
+static int
+projectile_pixel_sorter (const void *a, const void *b)
+{
+  struct projectile *pa = *(struct projectile **) a;
+  struct projectile *pb = *(struct projectile **) b;
+  if (pa->color.pixel == pb->color.pixel) return 0;
+  else if (pa->color.pixel < pb->color.pixel) return -1;
+  else return 1;
+}
+
+static void
+sort_by_pixel (int length)
+{
+  qsort ((void *) sorted_projectiles,
+         length,
+         sizeof(*sorted_projectiles),
+         projectile_pixel_sorter);
+}
+
+
 static void
 pyro (Display *dpy, Window window, Colormap cmap)
 {
   XWindowAttributes xgwa;
   static int xlim, ylim, real_xlim, real_ylim;
   int g = 100;
+  int resort = 0;
   int i;
-
-  if ((random () % frequency) == 0)
-    {
-      XGetWindowAttributes (dpy, window, &xgwa);
-      real_xlim = xgwa.width;
-      real_ylim = xgwa.height;
-      xlim = real_xlim * 1000;
-      ylim = real_ylim * 1000;
-      launch (xlim, ylim, g, dpy, cmap);
-    }
-
-  XSync (dpy, False);
-  screenhack_handle_events (dpy);
-  usleep (10000);
-
+  
   for (i = 0; i < how_many; i++)
     {
-      struct projectile *p = &projectiles [i];
+      struct projectile *p = sorted_projectiles [i];
       int old_x, old_y, old_size;
       int size, x, y;
       if (p->dead) continue;
@@ -184,8 +227,14 @@ pyro (Display *dpy, Window window, Colormap cmap)
       if (p->primary) p->fuse--;
 
       /* erase old one */
-      XFillRectangle (dpy, window, erase_gc, old_x, old_y,
-                     old_size, old_size);
+      if (old_size > 0)
+        {
+          if (old_size == 1)
+           XDrawPoint (dpy, window, erase_gc, old_x, old_y);
+          else
+            XFillRectangle (dpy, window, erase_gc, old_x, old_y,
+                            old_size, old_size);
+        }
 
       if ((p->primary ? (p->fuse > 0) : (p->size > 0)) &&
          x < real_xlim &&
@@ -193,16 +242,30 @@ pyro (Display *dpy, Window window, Colormap cmap)
          x > 0 &&
          y > 0)
        {
-         if (mono_p || p->primary)
-           XSetForeground (dpy, draw_gc, default_fg_pixel);
-         else
-           XSetForeground (dpy, draw_gc, p->color.pixel);
-
-         if /*(p->primary)*/ (size > 2)
-           XFillArc (dpy, window, draw_gc, x, y, size, size, 0, 360*64);
-         else
-           XFillRectangle (dpy, window, draw_gc, x, y, size, size);
-       }
+          if (size > 0)
+            {
+              static unsigned long last_pixel = ~0;
+              unsigned long pixel;
+
+              if (mono_p || p->primary)
+                pixel = default_fg_pixel;
+              else
+                pixel = p->color.pixel;
+
+              if (pixel != last_pixel)
+                {
+                  last_pixel = pixel;
+                  XSetForeground (dpy, draw_gc, pixel);
+                }
+
+              if (size == 1)
+                XDrawPoint (dpy, window, draw_gc, x, y);
+              else if (size < 4)
+                XFillRectangle (dpy, window, draw_gc, x, y, size, size);
+              else
+                XFillArc (dpy, window, draw_gc, x, y, size, size, 0, 360*64);
+            }
+        }
       else
        {
          free_projectile (p);
@@ -216,8 +279,24 @@ pyro (Display *dpy, Window window, Colormap cmap)
          int j = (random () % scatter) + (scatter/2);
          while (j--)
            shrapnel (p, dpy, cmap);
+          resort = 1;
        }
     }
+
+  if ((random () % frequency) == 0)
+    {
+      XGetWindowAttributes (dpy, window, &xgwa);
+      real_xlim = xgwa.width;
+      real_ylim = xgwa.height;
+      xlim = real_xlim * 1000;
+      ylim = real_ylim * 1000;
+      launch (xlim, ylim, g, dpy, cmap);
+      resort = 1;
+    }
+
+  /* being sorted lets us avoid changing the GC's foreground color as often. */
+  if (resort)
+    sort_by_pixel (how_many);
 }
 
 \f
@@ -226,14 +305,16 @@ char *progclass = "Pyro";
 char *defaults [] = {
   ".background:        black",
   ".foreground:        white",
-  "*count:     100",
+  "*count:     600",
+  "*delay:     5000",
   "*frequency: 30",
-  "*scatter:   20",
+  "*scatter:   100",
   "*geometry:  800x500",
   0
 };
 
 XrmOptionDescRec options [] = {
+  { "-delay",          ".delay",       XrmoptionSepArg, 0 },
   { "-count",          ".count",       XrmoptionSepArg, 0 },
   { "-frequency",      ".frequency",   XrmoptionSepArg, 0 },
   { "-scatter",                ".scatter",     XrmoptionSepArg, 0 },
@@ -244,6 +325,14 @@ void
 screenhack (Display *dpy, Window window)
 {
   Colormap cmap = init_pyro (dpy, window);
+  int delay = get_integer_resource ("delay", "Integer");
+
   while (1)
-    pyro (dpy, window, cmap);
+    {
+      pyro (dpy, window, cmap);
+
+      XSync (dpy, False);
+      screenhack_handle_events (dpy);
+      usleep (delay);
+    }
 }
index 1db5982abd20a6bf760a5f3e1a1f1214621119ce..5327c46d75be08195828b6ecb6d3ec40be8c468f 100644 (file)
@@ -160,7 +160,11 @@ See option \-teamACount, above.  Default value is 4.
 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.
+setuid root, so that it can create an ICMP socket.  Root privileges
+are disavowed shortly after startup (just after connecting to the
+X server and reading the resource database) so this is \fIbelieved\fP
+to be a safe thing to do, but it is usually recommended that you 
+have as few setuid programs around as possible, on general principles.
 .SH SEE ALSO
 .BR X (1),
 .BR xscreensaver (1),
diff --git a/hacks/speedmine.c b/hacks/speedmine.c
new file mode 100644 (file)
index 0000000..64f8578
--- /dev/null
@@ -0,0 +1,1589 @@
+/* -*- Mode: C; c-basic-offset: 4; tab-width: 4 -*-
+ * speedmine, Copyright (C) 2001 Conrad Parker <conrad@deephackmode.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ */
+
+/*
+ * Written mostly over the Easter holiday, 2001. Psychedelic option due to
+ * a night at Home nightclub, Sydney. Three all-nighters of solid partying
+ * were involved in the week this hack was written.
+ *
+ * Happy Birthday to WierdArms (17 April) and Pat (18 April)
+ */
+
+/*
+ * Hacking notes
+ *
+ * This program generates a rectangular terrain grid and maps this onto
+ * a semi-circular tunnel. The terrain has length TERRAIN_LENGTH, which
+ * corresponds to length along the tunnel, and breadth TERRAIN_BREADTH,
+ * which corresponds to circumference around the tunnel. For each frame,
+ * the tunnel is perspective mapped onto a set of X and Y screen values.
+ *
+ * Throughout this code the following temporary variable names are used:
+ *
+ *                     i       iterates along the tunnel in the direction of travel
+ *                     j       iterates around the tunnel clockwise
+ *                     t       iterates along the length of the perspective mapped values
+ *                             from the furthest to the nearest
+ *
+ * Thus, the buffers are used with these iterators:
+ *
+ *                     terrain[i][j]                                   terrain map
+ *                     worldx[i][j], worldy[i][j]              world coordinates (after wrapping)
+ *                     {x,y,z}curvature[i]                             tunnel curvature
+ *                     wideness[i]                                             tunnel wideness
+ *                     bonuses[i]                                              bonus values
+ *
+ *                     xvals[t][j], yvals[t][j]                screen coordinates
+ *                     {min,max}{x,y}[t]                               bounding boxes of screen coords
+ */
+
+/* Define or undefine NDEBUG to turn assert and abort debugging off or on */
+#define NDEBUG
+#include <assert.h>
+
+#include <math.h>
+
+#include "screenhack.h"
+#include "erase.h"
+
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#define MAX(a,b) ((a)>(b)?(a):(b))
+
+#define RAND(r) (int)(((r)>0)?(random() % (long)(r)): -(random() % (long)(-r)))
+
+#define SIGN3(a) ((a)>0?1:((a)<0?-1:0))
+
+#define MODULO(a,b) while ((a)<0) (a)+=(b); (a) %= (b);
+
+static Display * display;
+static Pixmap dbuf, stars_mask;
+static Colormap cmap;
+static unsigned int default_fg_pixel;
+static GC draw_gc, erase_gc, tunnelend_gc, stars_gc, stars_erase_gc;
+
+/* No. of shades of each color (ground, walls, bonuses) */
+#define MAX_COLORS 32
+static int ncolors, nr_ground_colors, nr_wall_colors, nr_bonus_colors;
+static XColor ground_colors[MAX_COLORS], wall_colors[MAX_COLORS];
+static XColor bonus_colors[MAX_COLORS];
+static GC ground_gcs[MAX_COLORS], wall_gcs[MAX_COLORS], bonus_gcs[MAX_COLORS];
+
+static int be_wormy;
+
+static int width, height;
+static int delay;
+
+static int smoothness;
+static int verbose_flag;
+static int wire_flag;
+static int terrain_flag;
+static int widening_flag;
+static int bumps_flag;
+static int bonuses_flag;
+static int crosshair_flag;
+static int psychedelic_flag;
+
+#ifdef NDEBUG
+#define DEBUG_FLAG 0
+#else
+#define DEBUG_FLAG 1
+#endif
+
+static double maxspeed;
+
+static double thrust, gravity;
+
+static double vertigo;
+static double curviness;
+static double twistiness;
+
+static double pos=0.0;
+static double speed=-1.1;
+static double accel=0.00000001;
+static double step=0.0;
+
+
+#define FORWARDS 1
+#define BACKWARDS -1
+static int direction = FORWARDS;
+
+static int pindex=0, nearest=0;
+static int flipped_at=0;
+static int xoffset=0, yoffset=0;
+
+static int bonus_bright = 0;
+static int wire_bonus=0;
+#define wireframe (wire_flag||wire_bonus>8||wire_bonus%2==1)
+
+static double speed_bonus=0.0;
+#define effective_speed (direction*(speed+speed_bonus))
+
+static int spin_bonus = 0;
+static int backwards_bonus = 0;
+
+/* No. of levels of interpolation, for perspective */
+#define INTERP 32
+
+/* These must be powers of 2 */
+#define TERRAIN_LENGTH 256
+#define TERRAIN_BREADTH 32
+
+/* total "perspective distance" of terrain */
+#define TERRAIN_PDIST (INTERP*TERRAIN_LENGTH)
+
+#define ROTS 1024
+#define TB_MUL (ROTS/TERRAIN_BREADTH)
+static double sintab[ROTS], costab[ROTS];
+
+static int orientation = (17*ROTS)/22;
+
+static int terrain[TERRAIN_LENGTH][TERRAIN_BREADTH];
+static double xcurvature[TERRAIN_LENGTH];
+static double ycurvature[TERRAIN_LENGTH];
+static double zcurvature[TERRAIN_LENGTH];
+static int wideness[TERRAIN_LENGTH];
+static int bonuses[TERRAIN_LENGTH];
+static int xvals[TERRAIN_LENGTH][TERRAIN_BREADTH];
+static int yvals[TERRAIN_LENGTH][TERRAIN_BREADTH];
+static double worldx[TERRAIN_LENGTH][TERRAIN_BREADTH];
+static double worldy[TERRAIN_LENGTH][TERRAIN_BREADTH];
+static int minx[TERRAIN_LENGTH], maxx[TERRAIN_LENGTH];
+static int miny[TERRAIN_LENGTH], maxy[TERRAIN_LENGTH];
+
+#define random_elevation() (terrain_flag?(random() % 200):0)
+#define random_curvature() (curviness>0.0?((double)(random() % 40)-20)*curviness:0.0)
+#define random_twist() (twistiness>0.0?((double)(random() % 40)-20)*twistiness:0.0)
+#define random_wideness() (widening_flag?(int)(random() % 1200):0)
+
+#define STEEL_ELEVATION 300
+
+/* a forward declaration ... */
+static void change_colors(void);
+
+#if HAVE_GETTIMEOFDAY
+static int total_nframes = 0;
+static int nframes = 0;
+static double fps = 0.0;
+static double fps_start, fps_end;
+static struct timeval start_time;
+
+/*
+ * get_time ()
+ *
+ * returns the total time elapsed since the beginning of the demo
+ */
+static double get_time(void) {
+  struct timeval t;
+  float f;
+#if GETTIMEOFDAY_TWO_ARGS
+  gettimeofday(&t, NULL);
+#else
+  gettimeofday(&t);
+#endif
+  t.tv_sec -= start_time.tv_sec;
+  f = ((double)t.tv_sec) + t.tv_usec*1e-6;
+  return f;
+}
+
+/*
+ * init_time ()
+ *
+ * initialises the timing structures
+ */
+static void init_time(void) {
+#if GETTIMEOFDAY_TWO_ARGS
+  gettimeofday(&start_time, NULL);
+#else
+  gettimeofday(&start_time);
+#endif
+  fps_start = get_time();
+}
+#endif
+
+/*
+ * perspective()
+ *
+ * perspective map the world coordinates worldx[i][j], worldy[i][j] onto
+ * screen coordinates xvals[t][j], yvals[t][j]
+ */
+static void
+perspective (void)
+{
+       static int rotation_offset=0;
+
+       int i, j, jj, t=0, depth, view_pos;
+       int rotation_bias, r;
+       double xc=0.0, yc=0.0, zc=0.0;
+       double xcc=0.0, ycc=0.0, zcc=0.0;
+       double xx, yy;
+       double zfactor, zf;
+
+       zf = 8.0*28.0 / (double)(width*TERRAIN_LENGTH);
+       if (be_wormy) zf *= 3.0;
+
+       depth = TERRAIN_PDIST - INTERP + pindex;
+
+       view_pos = (nearest+3*TERRAIN_LENGTH/4)%TERRAIN_LENGTH;
+       
+       xoffset += - xcurvature[view_pos]*curviness/8;
+       xoffset /= 2;
+
+       yoffset += - ycurvature[view_pos]*curviness/4;
+       yoffset /= 2;
+
+       rotation_offset += (int)((zcurvature[view_pos]-zcurvature[nearest])*ROTS/8);
+       rotation_offset /= 2;
+       rotation_bias = orientation + spin_bonus - rotation_offset;
+
+       if (bumps_flag) {
+               if (be_wormy) {
+                       yoffset -= ((terrain[view_pos][TERRAIN_BREADTH/4] * width /(8*1600)));
+                       rotation_bias += (terrain[view_pos][TERRAIN_BREADTH/4+2] -
+                                                        terrain[view_pos][TERRAIN_BREADTH/4-2])/8;
+               } else {
+                       yoffset -= ((terrain[view_pos][TERRAIN_BREADTH/4] * width /(2*1600)));
+                       rotation_bias += (terrain[view_pos][TERRAIN_BREADTH/4+2] -
+                                                        terrain[view_pos][TERRAIN_BREADTH/4-2])/16;
+               }
+       }
+
+       MODULO(rotation_bias, ROTS);
+
+       for (t=0; t < TERRAIN_LENGTH; t++) {
+               i = nearest + t; MODULO(i, TERRAIN_LENGTH);
+               xc += xcurvature[i]; yc += ycurvature[i]; zc += zcurvature[i];
+               xcc += xc; ycc += yc; zcc += zc;
+               maxx[i] = maxy[i] = 0;
+               minx[i] = width; miny[i] = height;
+       }
+
+       for (t=0; t < TERRAIN_LENGTH; t++) {
+               i = nearest - 1 - t; MODULO(i, TERRAIN_LENGTH);
+
+               zfactor = (double)depth* (12.0 - TERRAIN_LENGTH/8.0) * zf;
+               for (j=0; j < TERRAIN_BREADTH; j++) {
+                       jj = direction * j; MODULO(jj, TERRAIN_BREADTH);
+                       xx = (worldx[i][jj]-(vertigo*xcc))/zfactor; 
+                       yy = (worldy[i][j]-(vertigo*ycc))/zfactor;
+
+                       r = rotation_bias + (int)(vertigo*zcc); MODULO(r, ROTS);
+
+                       xvals[t][j] = xoffset + width/2 +
+                                         (int)(xx * costab[r] - yy * sintab[r]);
+                       maxx[t] = MAX(maxx[t], xvals[t][j]);
+                       minx[t] = MIN(minx[t], xvals[t][j]);
+
+                       yvals[t][j] = yoffset + height/2 +
+                                                 (int)(xx * sintab[r] + yy * costab[r]);
+                       maxy[t] = MAX(maxy[t], yvals[t][j]);
+                       miny[t] = MIN(miny[t], yvals[t][j]);
+               }
+               xcc -= xc; ycc -= yc; zcc -= zc;
+               xc -= xcurvature[i]; yc -= ycurvature[i]; zc -= zcurvature[i];
+               depth -= INTERP;
+       }
+}
+
+/*
+ * wrap_tunnel (start, end)
+ *
+ * wrap the terrain terrain[i][j] around the semi-circular tunnel function
+ * 
+ *                     x' = x/2 * cos(theta) - (y-k) * x * sin(theta)
+ *                     y' = x/4 * sin(theta) + y * cos(theta)
+ *
+ * between i=start and i=end inclusive, producing world coordinates
+ * worldx[i][j], worldy[i][j]
+ */
+static void
+wrap_tunnel (int start, int end)
+{
+       int i, j, v;
+       double x, y;
+
+       assert (start < end);
+
+       for (i=start; i <= end; i++) {
+               for (j=0; j < TERRAIN_BREADTH; j++) {
+                       x = j * (1.0/TERRAIN_BREADTH);
+                       v = terrain[i][j];
+                       y = (double)(v==STEEL_ELEVATION?200:v) - wideness[i] - 1200;
+
+                       /* lower road */
+                       if (j > TERRAIN_BREADTH/8 && j < 3*TERRAIN_BREADTH/8) y -= 300;
+
+                   worldx[i][j] = x/2 * costab[j*TB_MUL] -
+                                                       (y-height/4.0)*x*sintab[j*TB_MUL];
+                       worldy[i][j] = x/4 * sintab[j*TB_MUL] +
+                                                       y * costab[j*TB_MUL];
+               }
+       }
+}
+
+/*
+ * flip_direction()
+ *
+ * perform the state transitions and terrain transformation for the
+ * "look backwards/look forwards" bonus
+ */
+static void
+flip_direction (void)
+{
+       int i, ip, in, j, t;
+
+       direction = -direction;
+
+       bonus_bright = 20;
+
+       for (i=0; i < TERRAIN_LENGTH; i++) {
+               in = nearest + i; MODULO(in, TERRAIN_BREADTH);
+               ip = nearest - i; MODULO(ip, TERRAIN_BREADTH);
+               for (j=0; j < TERRAIN_BREADTH; j++) {
+                       t = terrain[ip][j];
+                       terrain[ip][j] = terrain[in][j];
+                       terrain[in][j] = t;
+               }
+       }
+}
+
+/*
+ * generate_smooth (start, end)
+ *
+ * generate smooth terrain between i=start and i=end inclusive
+ */
+static void
+generate_smooth (int start, int end)
+{
+       int i,j, ii;
+
+       assert (start < end);
+
+       for (i=start; i <= end; i++) {
+               ii = i; MODULO(ii, TERRAIN_LENGTH);
+               for (j=0; j < TERRAIN_BREADTH; j++) {
+                       terrain[i][j] = STEEL_ELEVATION;
+               }
+       }
+}
+
+/*
+ * generate_straight (start, end)
+ *
+ * zero the curvature and wideness between i=start and i=end inclusive
+ */
+static void
+generate_straight (int start, int end)
+{
+       int i,j, ii;
+
+       assert (start < end);
+
+       for (i=start; i <= end; i++) {
+               ii = i; MODULO(ii, TERRAIN_LENGTH);
+               for (j=0; j < TERRAIN_BREADTH; j++) {
+                       xcurvature[ii] = 0;
+                       ycurvature[ii] = 0;
+                       zcurvature[ii] = 0;
+                       wideness[ii] = 0;
+               }
+       }
+}
+
+/*
+ * int generate_terrain_value (v1, v2, v3, v4, w)
+ *
+ * generate terrain value near the average of v1, v2, v3, v4, with
+ * perturbation proportional to w
+ */
+static int
+generate_terrain_value (int v1, int v2, int v3, int v4, int w)
+{
+       int sum, ret;
+       int rval;
+
+       if (!terrain_flag) return 0;
+
+       sum = v1 + v2 + v3 + v4;
+
+       rval = w*sum/smoothness;
+       if (rval == 0) rval = 2;
+
+       ret = (sum/4 -(rval/2) + RAND(rval));
+
+       if (ret < -400 || ret > 400) {
+               ret = sum/4;
+       }
+
+       return ret;
+}
+
+/*
+ * generate_terrain (start, end, final)
+ *
+ * generate terrain[i][j] between i=start and i=end inclusive
+ *
+ * This is performed by successive subdivision of the terrain into
+ * rectangles of decreasing size. Subdivision continues until the
+ * the minimum width or height of these rectangles is 'final'; ie.
+ * final=1 indicates to subdivide as far as possible, final=2 indicates
+ * to stop one subdivision before that (leaving a checkerboard pattern
+ * uncalculated) etc.
+ */
+static void
+generate_terrain (int start, int end, int final)
+{
+       int i,j,w,l;
+       int ip, jp, in, jn; /* prev, next values */
+       int diff;
+
+       assert (start < end);
+       assert (start >= 0 && start < TERRAIN_LENGTH);
+       assert (end >= 0 && end < TERRAIN_LENGTH);
+
+       diff = end - start + 1;
+
+       terrain[end][0] = random_elevation();
+       terrain[end][TERRAIN_BREADTH/2] = random_elevation();
+
+       for (w= diff/2, l=TERRAIN_BREADTH/4;
+            w >= final || l >= final; w /= 2, l /= 2) {
+
+               if (w<1) w=1; if (l<1) l=1;
+
+               for (i=start+w-1; i < end; i += (w*2)) {
+                       ip = i-w; MODULO(ip, TERRAIN_LENGTH);
+                       in = i+w; MODULO(in, TERRAIN_LENGTH);
+                       for (j=l-1; j < TERRAIN_BREADTH; j += (l*2)) {
+                               jp = j-1; MODULO(jp, TERRAIN_BREADTH);
+                               jn = j+1; MODULO(jn, TERRAIN_BREADTH);
+                               terrain[i][j] =
+                                       generate_terrain_value (terrain[ip][jp], terrain[in][jp], 
+                                           terrain[ip][jn], terrain[in][jn], w);
+                       }
+               }
+
+               for (i=start+(w*2)-1; i < end; i += (w*2)) {
+                       ip = i-w; MODULO(ip, TERRAIN_LENGTH);
+                       in = i+w; MODULO(in, TERRAIN_LENGTH);
+                       for (j=l-1; j < TERRAIN_BREADTH; j += (l*2)) {
+                               jp = j-1; MODULO(jp, TERRAIN_BREADTH);
+                               jn = j+1; MODULO(jn, TERRAIN_BREADTH);
+                               terrain[i][j] =
+                                       generate_terrain_value (terrain[ip][j], terrain[in][j],
+                                           terrain[i][jp], terrain[i][jn], w);
+                       }
+               }
+
+               for (i=start+w-1; i < end; i += (w*2)) {
+                       ip = i-w; MODULO(ip, TERRAIN_LENGTH);
+                       in = i+w; MODULO(in, TERRAIN_LENGTH);
+                       for (j=2*l-1; j < TERRAIN_BREADTH; j += (l*2)) {
+                               jp = j-1; MODULO(jp, TERRAIN_BREADTH);
+                               jn = j+1; MODULO(jn, TERRAIN_BREADTH);
+                               terrain[i][j] =
+                                       generate_terrain_value (terrain[ip][j], terrain[in][j],
+                                           terrain[i][jp], terrain[i][jn], w);
+                       }
+               }
+       }
+}
+
+/*
+ * double generate_curvature_value (v1, v2, w)
+ *
+ * generate curvature value near the average of v1 and v2, with perturbation
+ * proportional to w
+ */
+static double
+generate_curvature_value (double v1, double v2, int w)
+{
+       double sum, avg, diff, ret;
+       int rval;
+
+       assert (!isnan(v1) && !isnan(v2));
+
+       sum = v1+v2;
+       avg = sum/2.0;
+
+       diff = MIN(v1 - avg, v2 - avg);
+
+       rval = (int)diff * w;
+       if (rval == 0.0) return avg;
+
+       ret = (avg -((double)rval)/500.0 + ((double)RAND(rval))/1000.0);
+
+       assert (!isnan(ret));
+
+       return ret;
+}
+
+/*
+ * generate_curves (start, end)
+ *
+ * generate xcurvature[i], ycurvature[i], zcurvature[i] and wideness[i]
+ * between start and end inclusive
+ */
+static void
+generate_curves (int start, int end)
+{
+       int i, diff, ii, in, ip, w;
+
+       assert (start < end);
+
+       diff = end - start + 1; MODULO (diff, TERRAIN_LENGTH);
+
+       if (random() % 100 == 0)
+         xcurvature[end] = 30 * random_curvature();
+       else if (random() % 10 == 0)
+         xcurvature[end] = 20 * random_curvature();
+       else
+         xcurvature[end] = 10 * random_curvature();
+
+       if (random() % 50 == 0)
+         ycurvature[end] = 20 * random_curvature();
+       else if (random() % 25 == 0)
+         ycurvature[end] = 30 * random_curvature();
+       else
+         ycurvature[end] = 10 * random_curvature();
+
+       if (random() % 3 == 0)
+         zcurvature[end] = random_twist();
+       else
+         zcurvature[end] =
+                         generate_curvature_value (zcurvature[end], random_twist(), 1);
+
+       if (be_wormy)
+                       wideness[end] = random_wideness();
+       else
+               wideness[end] =
+                       generate_curvature_value (wideness[end], random_wideness(), 1);
+
+    for (w=diff/2; w >= 1; w /= 2) {
+      for (i=start+w-1; i < end; i+=(w*2)) {
+        ii = i; MODULO (ii, TERRAIN_LENGTH);
+               ip = i-w; MODULO (ip, TERRAIN_LENGTH);
+           in = i+w; MODULO (in, TERRAIN_LENGTH);
+           xcurvature[ii] =
+                               generate_curvature_value (xcurvature[ip], xcurvature[in], w);
+           ycurvature[ii] =
+                               generate_curvature_value (ycurvature[ip], ycurvature[in], w);
+           zcurvature[ii] =
+                               generate_curvature_value (zcurvature[ip], zcurvature[in], w);
+           wideness[ii] =
+                               generate_curvature_value (wideness[ip], wideness[in], w);
+      }
+    }
+}
+
+/*
+ * do_bonus ()
+ *
+ * choose a random bonus and perform its state transition
+ */
+static void
+do_bonus (void)
+{
+       static int jamming=0;
+
+       bonus_bright = 20;
+
+       if (jamming > 0) {
+               jamming--;
+               nearest -= 2; MODULO(nearest, TERRAIN_LENGTH);
+               return;
+       }
+
+       if (psychedelic_flag) change_colors();
+
+       switch (random() % 7) {
+       case 0: /* switch to or from wireframe */
+               wire_bonus = (wire_bonus?0:300);
+               break;
+       case 1: /* speedup */
+               speed_bonus = 40.0;
+               break;
+       case 2:
+               spin_bonus += ROTS;
+               break;
+       case 3:
+               spin_bonus -= ROTS;
+               break;
+       case 4: /* look backwards / look forwards */
+               flipped_at = nearest;
+               flip_direction ();
+               backwards_bonus = (backwards_bonus?0:10);
+               break;
+       case 5:
+               change_colors();
+               break;
+       case 6: /* jam against the bonus a few times; deja vu! */
+               nearest -= 2; MODULO(nearest, TERRAIN_LENGTH);
+               jamming = 3;
+               break;
+       default:
+               assert(0);
+               break;
+       }
+}
+
+/*
+ * check_bonus ()
+ *
+ * check if a bonus has been passed in the last frame, and handle it
+ */
+static void
+check_bonuses (void)
+{
+       int i, ii, start, end;
+
+       if (!bonuses_flag) return;
+
+       if (step >= 0.0) {
+               start = nearest; end = nearest + (int)floor(step);
+       } else {
+               end = nearest; start = nearest + (int)floor(step);
+       }
+
+       if (be_wormy) {
+               start += TERRAIN_LENGTH/4;
+               end += TERRAIN_LENGTH/4;
+       }
+
+       for (i=start; i < end; i++) {
+               ii = i; MODULO(ii, TERRAIN_LENGTH);
+               if (bonuses[ii] == 1) do_bonus ();
+       }
+}
+
+/*
+ * decrement_bonuses (double time_per_frame)
+ *
+ * decrement timers associated with bonuses
+ */
+static void
+decrement_bonuses (double time_per_frame)
+{
+       if (!bonuses_flag) return;
+
+       if (bonus_bright > 0) bonus_bright-=4;
+       if (wire_bonus > 0) wire_bonus--;
+       if (speed_bonus > 0) speed_bonus -= 2.0;
+
+       if (spin_bonus > 10) spin_bonus -= (int)(step*13.7);
+       else if (spin_bonus < -10) spin_bonus += (int)(step*11.3);
+
+       if (backwards_bonus > 1) backwards_bonus--;
+       else if (backwards_bonus == 1) {
+               nearest += 2*(MAX(flipped_at, nearest) - MIN(flipped_at,nearest));
+               MODULO(nearest, TERRAIN_LENGTH);
+               flip_direction ();
+               backwards_bonus = 0;
+       }
+}
+
+/*
+ * set_bonuses (start, end)
+ *
+ * choose if to and where to set a bonus between i=start and i=end inclusive
+ */
+static void
+set_bonuses (int start, int end)
+{
+       int i, diff, ii;
+
+       if (!bonuses_flag) return;
+
+       assert (start < end);
+
+       diff = end - start;
+
+       for (i=start; i <= end; i++) {
+               ii = i; if (ii>=TERRAIN_LENGTH) ii -= TERRAIN_LENGTH;
+               bonuses[ii] = 0;
+       }
+       if (random() % 4 == 0) {
+               i = start + RAND(diff-3);
+               ii = i; if (ii>=TERRAIN_LENGTH) ii -= TERRAIN_LENGTH;
+               bonuses[ii] = 2; /* marker */
+               ii = i+3; if (ii>=TERRAIN_LENGTH) ii -= TERRAIN_LENGTH;
+               bonuses[ii] = 1; /* real thing */
+       }
+}
+
+/*
+ * regenerate_terrain ()
+ *
+ * regenerate a portion of the terrain map of length TERRAIN_LENGTH/4 iff
+ * we just passed between two quarters of the terrain.
+ *
+ * choose the kind of terrain to produce, produce it and wrap the tunnel
+ */
+static void
+regenerate_terrain (void)
+{
+       int start, end;
+       int passed;
+
+       passed = nearest % (TERRAIN_LENGTH/4);
+
+       if (speed == 0.0 ||
+               (speed > 0.0 && passed > (int)step) ||
+               (speed < 0.0 && (TERRAIN_LENGTH/4)-passed > (int)fabs(step))) {
+
+               return;
+       }
+
+       end = nearest - passed - 1; MODULO(end, TERRAIN_LENGTH);
+       start = end - TERRAIN_LENGTH/4 + 1; MODULO(start, TERRAIN_LENGTH);
+
+       if (DEBUG_FLAG) printf ("Regenerating [%d - %d]\n", start, end);
+
+       set_bonuses (start, end);
+
+       switch (random() % 64) {
+       case 0:
+       case 1:
+               generate_terrain (start, end, 1);
+               generate_smooth (start,
+                       start + TERRAIN_LENGTH/8 + (random() % TERRAIN_LENGTH/8));
+               break;
+       case 2:
+               generate_smooth (start, end);
+               generate_terrain (start, end, 4); break;
+       case 3:
+               generate_smooth (start, end);
+               generate_terrain (start, end, 2); break;
+       default:
+               generate_terrain (start, end, 1);
+       }
+
+       if (random() % 16 == 0) {
+               generate_straight (start, end);
+       } else {
+               generate_curves (start, end);
+       }
+
+       wrap_tunnel (start, end);
+}
+
+/*
+ * init_terrain ()
+ *
+ * initialise the terrain map for the beginning of the demo
+ */
+static void
+init_terrain (void)
+{
+       int i, j;
+
+       for (i=0; i < TERRAIN_LENGTH; i++) {
+               for (j=0; j < TERRAIN_BREADTH; j++) {
+                       terrain[i][j] = 0;
+               }
+       }
+
+       terrain[TERRAIN_LENGTH-1][0] =  - (random() % 300);
+       terrain[TERRAIN_LENGTH-1][TERRAIN_BREADTH/2] =  - (random() % 300);
+
+       generate_smooth (0, TERRAIN_LENGTH-1);
+       generate_terrain (0, TERRAIN_LENGTH/4 -1, 4);
+       generate_terrain (TERRAIN_LENGTH/4, TERRAIN_LENGTH/2 -1, 2);
+       generate_terrain (TERRAIN_LENGTH/2, 3*TERRAIN_LENGTH/4 -1, 1);
+       generate_smooth (3*TERRAIN_LENGTH/4, TERRAIN_LENGTH-1);
+}
+
+/*
+ * init_curves ()
+ *
+ * initialise the curvatures and wideness for the beginning of the demo.
+ */
+static void
+init_curves (void)
+{
+       int i;
+
+       for (i=0; i < TERRAIN_LENGTH-1; i++) {
+       xcurvature[i] = 0.0;
+           ycurvature[i] = 0.0;
+               zcurvature[i] = 0.0;
+       }
+
+    xcurvature[TERRAIN_LENGTH-1] = random_curvature();
+    ycurvature[TERRAIN_LENGTH-1] = random_curvature();
+    zcurvature[TERRAIN_LENGTH-1] = random_twist();
+
+       generate_straight (0, TERRAIN_LENGTH/4-1);
+       generate_curves (TERRAIN_LENGTH/4, TERRAIN_LENGTH/2-1);
+       generate_curves (TERRAIN_LENGTH/2, 3*TERRAIN_LENGTH/4-1);
+       generate_straight (3*TERRAIN_LENGTH/4, TERRAIN_LENGTH-1);
+
+}
+
+/*
+ * render_quads (dpy, d, t, dt, i)
+ *
+ * renders the quadrilaterals from perspective depth t to t+dt.
+ * i is passed as a hint, where i corresponds to t as asserted.
+ */
+static void
+render_quads (Display * dpy, Drawable d, int t, int dt, int i)
+{
+       int j, t2, j2, in;
+       int index;
+       XPoint points[4];
+       GC gc;
+
+       assert (i == (nearest - (t + dt) + TERRAIN_LENGTH) % TERRAIN_LENGTH);
+
+       in = i + 1; MODULO(in, TERRAIN_LENGTH);
+
+       for (j=0; j < TERRAIN_BREADTH; j+=dt) {
+               t2 = t+dt; if (t2 >= TERRAIN_LENGTH) t2 -= TERRAIN_LENGTH;
+               j2 = j+dt; if (j2 >= TERRAIN_BREADTH) j2 -= TERRAIN_BREADTH;
+               points[0].x = xvals[t][j]; points[0].y = yvals[t][j];
+               points[1].x = xvals[t2][j]; points[1].y = yvals[t2][j];
+               points[2].x = xvals[t2][j2]; points[2].y = yvals[t2][j2];
+               points[3].x = xvals[t][j2]; points[3].y = yvals[t][j2];
+
+           index = bonus_bright + ncolors/3 +
+                               t*(t*INTERP + pindex) * ncolors /
+                           (3*TERRAIN_LENGTH*TERRAIN_PDIST);
+               if (!wireframe) {
+                       index += (int)((points[0].y - points[3].y) / 8);
+                       index += (int)((worldx[i][j] - worldx[in][j]) / 40);
+                       index += (int)((terrain[in][j] - terrain[i][j]) / 100);
+               }
+               if (be_wormy && psychedelic_flag) index += ncolors/4;
+
+               index = MIN (index, ncolors-1);
+               index = MAX (index, 0);
+
+               if (bonuses[i]) {
+                       XSetClipMask (dpy, bonus_gcs[index], None);
+               }
+
+               if (wireframe) {
+                       if (bonuses[i]) gc = bonus_gcs[index];
+                       else gc = ground_gcs[index];
+                       XDrawLines (dpy, d, gc, points, 4, CoordModeOrigin);
+               } else {
+                       if (bonuses[i])
+                               gc = bonus_gcs[index];
+                       else if ((direction>0 && j < TERRAIN_BREADTH/8) ||
+                               (j > TERRAIN_BREADTH/8 && j < 3*TERRAIN_BREADTH/8-1) ||
+                               (direction < 0 && j > 3*TERRAIN_BREADTH/8-1 &&
+                                       j < TERRAIN_BREADTH/2) ||
+                               terrain[i][j] == STEEL_ELEVATION ||
+                               wideness[in] - wideness[i] > 200) 
+                               gc = ground_gcs[index];
+                       else
+                               gc = wall_gcs[index];
+
+                       XFillPolygon (dpy, d, gc, points, 4, Nonconvex, CoordModeOrigin);
+               }
+       }
+}
+
+/*
+ * render_pentagons (dpy, d, t, dt, i)
+ *
+ * renders the pentagons from perspective depth t to t+dt.
+ * i is passed as a hint, where i corresponds to t as asserted.
+ */
+static void
+render_pentagons (Display *dpy, Drawable d, int t, int dt, int i)
+{
+       int j, t2, j2, j3, in;
+       int index;
+       XPoint points[5];
+       GC gc;
+
+       assert (i == (nearest -t + TERRAIN_LENGTH) % TERRAIN_LENGTH);
+
+       in = i + 1; MODULO(in, TERRAIN_LENGTH);
+
+       for (j=0; j < TERRAIN_BREADTH; j+=dt*2) {
+               t2 = t+(dt*2); if (t2 >= TERRAIN_LENGTH) t2 -= TERRAIN_LENGTH;
+               j2 = j+dt; if (j2 >= TERRAIN_BREADTH) j2 -= TERRAIN_BREADTH;
+               j3 = j+dt+dt; if (j3 >= TERRAIN_BREADTH) j3 -= TERRAIN_BREADTH;
+               points[0].x = xvals[t][j]; points[0].y = yvals[t][j];
+               points[1].x = xvals[t2][j]; points[1].y = yvals[t2][j];
+               points[2].x = xvals[t2][j2]; points[2].y = yvals[t2][j2];
+               points[3].x = xvals[t2][j3]; points[3].y = yvals[t2][j3];
+               points[4].x = xvals[t][j3]; points[4].y = yvals[t][j3];
+
+           index = bonus_bright + ncolors/3 +
+                               t*(t*INTERP + pindex) * ncolors /
+                           (3*TERRAIN_LENGTH*TERRAIN_PDIST);
+               if (!wireframe) {
+                       index += (int)((points[0].y - points[3].y) / 8);
+                       index += (int)((worldx[i][j] - worldx[in][j]) / 40);
+                       index += (int)((terrain[in][j] - terrain[i][j]) / 100);
+               }
+               if (be_wormy && psychedelic_flag) index += ncolors/4;
+
+               index = MIN (index, ncolors-1);
+               index = MAX (index, 0);
+
+               if (bonuses[i]) {
+                       XSetClipMask (dpy, bonus_gcs[index], None);
+               }
+
+               if (wireframe) {
+                       if (bonuses[i]) gc = bonus_gcs[index];
+                       else gc = ground_gcs[index];
+                       XDrawLines (dpy, d, gc, points, 5, CoordModeOrigin);
+               } else {
+                       if (bonuses[i])
+                               gc = bonus_gcs[index];
+                       else if (j < TERRAIN_BREADTH/8 ||
+                               (j > TERRAIN_BREADTH/8 && j < 3*TERRAIN_BREADTH/8-1) ||
+                               terrain[i][j] == STEEL_ELEVATION ||
+                               wideness[in] - wideness[i] > 200) 
+                               gc = ground_gcs[index];
+                       else
+                               gc = wall_gcs[index];
+
+                       XFillPolygon (dpy, d, gc, points, 5, Complex, CoordModeOrigin);
+               }
+       }
+}
+
+/*
+ * render_block (dpy, d, gc, t)
+ *
+ * render a filled polygon at perspective depth t using the given GC
+ */
+static void
+render_block (Display * dpy, Drawable d, GC gc, int t)
+{
+       int i;
+
+       XPoint erase_points[TERRAIN_BREADTH/2];
+
+       for (i=0; i < TERRAIN_BREADTH/2; i++) {
+               erase_points[i].x = xvals[t][i*2];
+               erase_points[i].y = yvals[t][i*2];
+       }
+
+       XFillPolygon (dpy, d, gc, erase_points,
+                                 TERRAIN_BREADTH/2, Complex, CoordModeOrigin);
+}
+
+/*
+ * regenerate_stars_mask (dpy, t)
+ *
+ * regenerate the clip mask 'stars_mask' for drawing the bonus stars at
+ * random positions within the bounding box at depth t
+ */
+static void
+regenerate_stars_mask (Display * dpy, int t)
+{
+       int i, w, h, a, b, l1, l2;
+       const int lim = width*TERRAIN_LENGTH/(300*(TERRAIN_LENGTH-t));
+
+       w = maxx[t] - minx[t];
+       h = maxy[t] - miny[t];
+
+       if (w<6||h<6) return;
+
+       XFillRectangle (dpy, stars_mask, stars_erase_gc,
+                                       0, 0, width, height);
+
+       l1 = (t>3*TERRAIN_LENGTH/4?2:1);
+       l2 = (t>7*TERRAIN_LENGTH/8?2:1);
+
+       for (i=0; i < lim; i++) {
+               a = RAND(w); b = RAND(h);
+               XDrawLine (dpy, stars_mask, stars_gc,
+                                       minx[t]+a-l1, miny[t]+b, minx[t]+a+l1, miny[t]+b);
+               XDrawLine (dpy, stars_mask, stars_gc,
+                                       minx[t]+a, miny[t]+b-l1, minx[t]+a, miny[t]+b+l1);
+       }
+       for (i=0; i < lim; i++) {
+               a = RAND(w); b = RAND(h);
+               XDrawLine (dpy, stars_mask, stars_gc,
+                                       minx[t]+a-l2, miny[t]+b, minx[t]+a+l2, miny[t]+b);
+               XDrawLine (dpy, stars_mask, stars_gc,
+                                       minx[t]+a, miny[t]+b-l2, minx[t]+a, miny[t]+b+l2);
+       }
+}
+
+/*
+ * render_bonus_block (dpy, d, t, i)
+ *
+ * draw the bonus stars at depth t.
+ * i is passed as a hint, where i corresponds to t as asserted.
+ */
+static void
+render_bonus_block (Display * dpy, Drawable d, int t, int i)
+{
+       int bt;
+
+       assert (i == (nearest -t + TERRAIN_LENGTH) % TERRAIN_LENGTH);
+
+       if (!bonuses[i] || wireframe) return;
+
+       regenerate_stars_mask (dpy, t);
+
+       bt = t * nr_bonus_colors / (2*TERRAIN_LENGTH);
+
+       XSetClipMask (dpy, bonus_gcs[bt], stars_mask);
+
+       render_block (dpy, d, bonus_gcs[bt], t);
+}
+
+static int
+begin_at (void)
+{
+       int t;
+       int max_minx=0, min_maxx=width, max_miny=0, min_maxy=height;
+
+       for (t=TERRAIN_LENGTH-1; t > 0; t--) {
+               max_minx = MAX (max_minx, minx[t]);
+               min_maxx = MIN (min_maxx, maxx[t]);
+               max_miny = MAX (max_miny, miny[t]);
+               min_maxy = MIN (min_maxy, maxy[t]);
+
+               if (max_miny >= min_maxy || max_minx >= min_maxx) break;
+       }
+
+       return t;
+}
+
+/*
+ * render_speedmine (dpy, d)
+ *
+ * render the current frame.
+ */
+static void
+render_speedmine (Display * dpy, Drawable d)
+{
+       int t, i=nearest, dt=1;
+       GC gc;
+
+       assert (nearest >= 0 && nearest < TERRAIN_LENGTH);
+
+       if (be_wormy || wireframe) {
+               XFillRectangle (dpy, d, erase_gc, 0, 0, width, height);
+
+               dt=4;
+               for (t=0; t < TERRAIN_LENGTH/4; t+=dt) {
+                       render_bonus_block (dpy, d, t, i);
+                       i -= dt; MODULO(i, TERRAIN_LENGTH);
+                       render_quads (dpy, d, t, dt, i);
+               }
+
+               assert (t == TERRAIN_LENGTH/4);
+       } else {
+               t = MAX(begin_at(), TERRAIN_LENGTH/4);
+               /*t = TERRAIN_LENGTH/4; dt = 2; */
+               dt = (t >= 3*TERRAIN_LENGTH/4 ? 1 : 2);
+               i = (nearest -t + TERRAIN_LENGTH) % TERRAIN_LENGTH;
+               render_block (dpy, d, tunnelend_gc, t);
+       }
+
+       dt=2;
+
+       if (t == TERRAIN_LENGTH/4)
+               render_pentagons (dpy, d, t, dt, i);
+
+       for (; t < 3*TERRAIN_LENGTH/4; t+=dt) {
+               render_bonus_block (dpy, d, t, i);
+               i -= dt; MODULO(i, TERRAIN_LENGTH);
+               render_quads (dpy, d, t, dt, i);
+       }
+
+       dt=1;
+       if (be_wormy) {
+               for (; t < TERRAIN_LENGTH-(1+(pindex<INTERP/2)); t+=dt) {
+                       render_bonus_block (dpy, d, t, i);
+                       i -= dt; MODULO(i, TERRAIN_LENGTH);
+               }
+       } else {
+               if (wireframe) {assert (t == 3*TERRAIN_LENGTH/4);}
+
+               if (t == 3*TERRAIN_LENGTH/4)
+                       render_pentagons (dpy, d, t, dt, i);
+
+               for (; t < TERRAIN_LENGTH-(1+(pindex<INTERP/2)); t+=dt) {
+                       render_bonus_block (dpy, d, t, i);
+                       i -= dt; MODULO(i, TERRAIN_LENGTH);
+                       render_quads (dpy, d, t, dt, i);
+               }
+       }
+
+       /* Draw crosshair */
+       if (crosshair_flag) {
+               gc = (wireframe ? bonus_gcs[nr_bonus_colors/2] : erase_gc);
+               XFillRectangle (dpy, d, gc,
+                                               width/2+(xoffset)-8, height/2+(yoffset*2)-1, 16, 3);
+               XFillRectangle (dpy, d, gc,
+                                               width/2+(xoffset)-1, height/2+(yoffset*2)-8, 3, 16);
+       }
+
+}
+
+/*
+ * move (step)
+ *
+ * move to the position for the next frame, and modify the state variables
+ * nearest, pindex, pos, speed
+ */
+static void
+move (double step)
+{
+       double dpos;
+
+       pos += step;
+       dpos = SIGN3(pos) * floor(fabs(pos));
+
+       pindex += SIGN3(effective_speed) + INTERP;
+       while (pindex >= INTERP) {
+               nearest --;
+               pindex -= INTERP;
+       }
+       while (pindex < 0) {
+               nearest ++;
+               pindex += INTERP;
+       }
+
+    nearest += dpos; MODULO(nearest, TERRAIN_LENGTH);
+
+       pos -= dpos;
+
+       accel = thrust + ycurvature[nearest] * gravity;
+       speed += accel;
+       if (speed > maxspeed) speed = maxspeed;
+       if (speed < -maxspeed) speed = -maxspeed;
+}
+
+/*
+ * speedmine (dpy, window)
+ *
+ * do everything required for one frame of the demo
+ */
+static void
+speedmine (Display *dpy, Window window)
+{
+       double elapsed, time_per_frame = 0.04;
+
+       regenerate_terrain ();
+
+       perspective ();
+
+       render_speedmine (dpy, dbuf);
+       XCopyArea (dpy, dbuf, window, draw_gc, 0, 0, width, height, 0, 0);
+
+#if HAVE_GETTIMEOFDAY
+       fps_end = get_time();
+       nframes++;
+       total_nframes++;
+
+       if (fps_end > fps_start + 0.5) {
+               elapsed = fps_end - fps_start;
+               fps_start = get_time();
+
+               time_per_frame = elapsed / nframes - delay*1e-6;
+               fps = nframes / elapsed;
+               if (DEBUG_FLAG) {
+                       printf ("%f s elapsed\t%3f s/frame\t%.1f FPS\n", elapsed,
+                                       time_per_frame, fps);
+               }
+               step = effective_speed * elapsed;
+
+               nframes = 0;
+       }
+#else
+       time_per_frame = 0.04;
+       step = effective_speed;
+#endif
+
+       move (step);
+
+       decrement_bonuses (time_per_frame);
+
+       check_bonuses ();
+}
+
+/*
+ * speedmine_color_ramp (dpy, cmap, gcs, colors, ncolors, s1, s2, v1, v2)
+ *
+ * generate a color ramp of up to *ncolors between randomly chosen hues,
+ * varying from saturation s1 to s2 and value v1 to v2, placing the colors
+ * in 'colors' and creating corresponding GCs in 'gcs'.
+ *
+ * The number of colors actually allocated is returned in ncolors.
+ */
+static void
+speedmine_color_ramp (Display * dpy, Colormap cmap, GC *gcs, XColor * colors,
+                                        int *ncolors, double s1, double s2, double v1, double v2)
+{
+       XGCValues gcv;
+       int h1, h2;
+       unsigned long flags;
+       int i;
+
+       assert (*ncolors >= 0);
+       assert (s1 >= 0.0 && s1 <= 1.0 && v1 >= 0.0 && v2 <= 1.0);
+
+       if (psychedelic_flag) {
+               h1 = RAND(360); h2 = (h1 + 180) % 360;
+       } else {
+               h1 = h2 = RAND(360);
+       }
+
+       make_color_ramp (dpy, cmap, h1, s1, v1, h2, s2, v2,
+                                    colors, ncolors, False, True, False);
+
+       flags = GCForeground;
+       for (i=0; i < *ncolors; i++) {
+               gcv.foreground = colors[i].pixel;
+               gcs[i] = XCreateGC (dpy, dbuf, flags, &gcv);
+       }
+
+}
+
+/*
+ * change_colors ()
+ *
+ * perform the color changing bonus. New colors are allocated for the
+ * walls and bonuses, and if the 'psychedelic' option is set then new
+ * colors are also chosen for the ground.
+ */
+static void
+change_colors (void)
+{
+       double s1, s2;
+
+       if (psychedelic_flag) {
+               free_colors (display, cmap, bonus_colors, nr_bonus_colors);
+               free_colors (display, cmap, wall_colors, nr_wall_colors);
+               free_colors (display, cmap, ground_colors, nr_ground_colors);
+               ncolors = MAX_COLORS;
+
+               s1 = 0.4; s2 = 0.9;
+
+               speedmine_color_ramp (display, cmap, ground_gcs, ground_colors,
+                                                         &ncolors, 0.0, 0.8, 0.0, 0.9);
+               nr_ground_colors = ncolors;
+       } else {
+               free_colors (display, cmap, bonus_colors, nr_bonus_colors);
+               free_colors (display, cmap, wall_colors, nr_wall_colors);
+               ncolors = nr_ground_colors;
+
+               s1 = 0.0; s2 = 0.6;
+       }
+
+    speedmine_color_ramp (display, cmap, wall_gcs, wall_colors, &ncolors,
+                                                 s1, s2, 0.0, 0.9);
+    nr_wall_colors = ncolors;
+
+    speedmine_color_ramp (display, cmap, bonus_gcs, bonus_colors, &ncolors,
+                                                 0.6, 0.9, 0.4, 1.0);
+       nr_bonus_colors = ncolors;
+}
+
+/*
+ * init_psychedelic_colors (dpy, window, cmap)
+ *
+ * initialise a psychedelic colormap
+ */
+static void
+init_psychedelic_colors (Display * dpy, Window window, Colormap cmap)
+{
+  XGCValues gcv;
+
+  gcv.foreground = get_pixel_resource ("tunnelend", "TunnelEnd", dpy, cmap);
+  tunnelend_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+
+  ncolors = MAX_COLORS;
+
+  speedmine_color_ramp (dpy, cmap, ground_gcs, ground_colors, &ncolors,
+                                               0.0, 0.8, 0.0, 0.9);
+  nr_ground_colors = ncolors;
+
+  speedmine_color_ramp (dpy, cmap, wall_gcs, wall_colors, &ncolors,
+                                               0.0, 0.6, 0.0, 0.9);
+  nr_wall_colors = ncolors;
+
+  speedmine_color_ramp (dpy, cmap, bonus_gcs, bonus_colors, &ncolors,
+                                               0.6, 0.9, 0.4, 1.0);
+  nr_bonus_colors = ncolors;
+}
+
+/*
+ * init_colors (dpy, window, cmap)
+ *
+ * initialise a normal colormap
+ */
+static void
+init_colors (Display * dpy, Window window, Colormap cmap)
+{
+  XGCValues gcv;
+  XColor dark, light;
+  int h1, h2;
+  double s1, s2, v1, v2;
+  unsigned long flags;
+  int i;
+
+  gcv.foreground = get_pixel_resource ("tunnelend", "TunnelEnd", dpy, cmap);
+  tunnelend_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+
+  ncolors = MAX_COLORS;
+
+  dark.pixel = get_pixel_resource ("darkground", "DarkGround", dpy, cmap);
+  XQueryColor (dpy, cmap, &dark);
+
+  light.pixel = get_pixel_resource ("lightground", "LightGround", dpy, cmap);
+  XQueryColor (dpy, cmap, &light);
+
+  rgb_to_hsv (dark.red, dark.green, dark.blue, &h1, &s1, &v1);
+  rgb_to_hsv (light.red, light.green, light.blue, &h2, &s2, &v2);
+  make_color_ramp (dpy, cmap, h1, s1, v1, h2, s2, v2,
+                                 ground_colors, &ncolors, False, True, False);
+  nr_ground_colors = ncolors;
+
+  flags = GCForeground;
+  for (i=0; i < ncolors; i++) {
+       gcv.foreground = ground_colors[i].pixel;
+       ground_gcs[i] = XCreateGC (dpy, dbuf, flags, &gcv);
+  }
+
+  speedmine_color_ramp (dpy, cmap, wall_gcs, wall_colors, &ncolors,
+                                               0.0, 0.6, 0.0, 0.9);
+  nr_wall_colors = ncolors;
+
+  speedmine_color_ramp (dpy, cmap, bonus_gcs, bonus_colors, &ncolors,
+                                               0.6, 0.9, 0.4, 1.0);
+  nr_bonus_colors = ncolors;
+}
+
+/*
+ * print_stats ()
+ *
+ * print out average FPS stats for the demo
+ */
+static void
+print_stats (void)
+{
+       if (total_nframes >= 1)
+               printf ("Rendered %d frames averaging %f FPS\n", total_nframes,
+                               total_nframes / get_time());
+}
+
+/*
+ * init_speedmine (dpy, window)
+ *
+ * initialise the demo
+ */
+static void
+init_speedmine (Display *dpy, Window window)
+{
+  XGCValues gcv;
+  XWindowAttributes xgwa;
+  int i;
+  double th;
+  int wide;
+
+  display = dpy;
+
+  XGetWindowAttributes (dpy, window, &xgwa);
+  cmap = xgwa.colormap;
+  width = xgwa.width;
+  height = xgwa.height;
+
+  verbose_flag = get_boolean_resource ("verbose", "Boolean");
+
+  dbuf = XCreatePixmap (dpy, window, width, height, xgwa.depth);
+  stars_mask = XCreatePixmap (dpy, window, width, height, 1);
+
+  gcv.foreground = default_fg_pixel =
+    get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+  draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+  stars_gc = XCreateGC (dpy, stars_mask, GCForeground, &gcv);
+
+  gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
+  erase_gc = XCreateGC (dpy, dbuf, GCForeground, &gcv);
+  stars_erase_gc = XCreateGC (dpy, stars_mask, GCForeground, &gcv);
+
+  wire_flag = get_boolean_resource ("wire", "Boolean");
+
+  psychedelic_flag = get_boolean_resource ("psychedelic", "Boolean");
+
+  delay = get_integer_resource("delay", "Integer");
+
+  smoothness = get_integer_resource("smoothness", "Integer");
+  if (smoothness < 1) smoothness = 1;
+
+  maxspeed = get_float_resource("maxspeed", "Float");
+  maxspeed *= 0.01;
+  maxspeed = fabs(maxspeed);
+
+  thrust = get_float_resource("thrust", "Float");
+  thrust *= 0.2;
+
+  gravity = get_float_resource("gravity", "Float");
+  gravity *= 0.002/9.8;
+
+  vertigo = get_float_resource("vertigo", "Float");
+  vertigo *= 0.2;
+
+  curviness = get_float_resource("curviness", "Float");
+  curviness *= 0.25;
+
+  twistiness = get_float_resource("twistiness", "Float");
+  twistiness *= 0.125;
+
+  terrain_flag = get_boolean_resource ("terrain", "Boolean");
+  widening_flag = get_boolean_resource ("widening", "Boolean");
+  bumps_flag = get_boolean_resource ("bumps", "Boolean");
+  bonuses_flag = get_boolean_resource ("bonuses", "Boolean");
+  crosshair_flag = get_boolean_resource ("crosshair", "Boolean");
+
+  be_wormy = get_boolean_resource ("worm", "Boolean");
+  if (be_wormy) {
+      maxspeed   *= 1.43;
+      thrust     *= 10;
+      gravity    *= 3;
+      vertigo    *= 0.5;
+      smoothness *= 2;
+      curviness  *= 2;
+      twistiness *= 2;
+      psychedelic_flag = True;
+      crosshair_flag = False;
+  }
+
+  if (psychedelic_flag) init_psychedelic_colors (dpy, window, cmap);
+  else init_colors (dpy, window, cmap);
+
+  for (i=0; i<ROTS; i++) {
+       th = M_PI * 2.0 * i / ROTS;
+       costab[i] = cos(th);
+       sintab[i] = sin(th);
+  }
+
+  wide = random_wideness();
+
+  for (i=0; i < TERRAIN_LENGTH; i++) {
+       wideness[i] = wide;
+       bonuses[i] = 0;
+  }
+
+  init_terrain ();
+  init_curves ();
+  wrap_tunnel (0, TERRAIN_LENGTH-1);
+
+  if (DEBUG_FLAG || verbose_flag) atexit(print_stats);
+
+  step = effective_speed;
+
+#ifdef HAVE_GETTIMEOFDAY
+  init_time ();
+#endif
+
+}
+
+\f
+/*
+ * Down the speedmine, you'll find speed
+ * to satisfy your moving needs;
+ * So if you're looking for a blast
+ * then hit the speedmine, really fast.
+ */
+
+/*
+ * Speedworm likes to choke and spit
+ * and chase his tail, and dance a bit
+ * he really is a funky friend;
+ * he's made of speed from end to end.
+ */
+
+char *progclass = "Speedmine";
+
+char *defaults [] = {
+  ".verbose: False",
+  "*worm: False",
+  "*wire: False",
+  ".background:        black",
+  ".foreground:        white",
+  "*darkground: #101010",
+  "*lightground: #a0a0a0",
+  "*tunnelend: #000000",
+  "*delay:     30000",
+  "*maxspeed: 700",
+  "*thrust: 1.0",
+  "*gravity: 9.8",
+  "*vertigo: 1.0",
+  "*terrain: True",
+  "*smoothness: 6",
+  "*curviness: 1.0",
+  "*twistiness: 1.0",
+  "*widening: True",
+  "*bumps: True",
+  "*bonuses: True",
+  "*crosshair: True",
+  "*psychedelic: False",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-verbose",                        ".verbose",                             XrmoptionNoArg, "True"},
+  { "-worm",                   ".worm",                                XrmoptionNoArg, "True"},
+  { "-wire",                   ".wire",                                XrmoptionNoArg, "True"},
+  { "-nowire",                 ".wire",                                XrmoptionNoArg, "False"},
+  { "-darkground",             ".darkground",                  XrmoptionSepArg, 0 },
+  { "-lightground",            ".lightground",                 XrmoptionSepArg, 0 },
+  { "-tunnelend",              ".tunnelend",                   XrmoptionSepArg, 0 },
+  { "-delay",           ".delay",               XrmoptionSepArg, 0 },
+  { "-maxspeed",               ".maxspeed",                    XrmoptionSepArg, 0 },
+  { "-thrust",                 ".thrust",                              XrmoptionSepArg, 0 },
+  { "-gravity",                        ".gravity",                             XrmoptionSepArg, 0 },
+  { "-vertigo",                        ".vertigo",                             XrmoptionSepArg, 0 },
+  { "-terrain",                        ".terrain",                             XrmoptionNoArg, "True"},
+  { "-noterrain",              ".terrain",                             XrmoptionNoArg, "False"},
+  { "-smoothness",      ".smoothness",                 XrmoptionSepArg, 0 },
+  { "-curviness",              ".curviness",                   XrmoptionSepArg, 0 },
+  { "-twistiness",             ".twistiness",                  XrmoptionSepArg, 0 },
+  { "-widening",               ".widening",                    XrmoptionNoArg, "True"},
+  { "-nowidening",             ".widening",                    XrmoptionNoArg, "False"},
+  { "-bumps",                  ".bumps",                               XrmoptionNoArg, "True"},
+  { "-nobumps",                        ".bumps",                               XrmoptionNoArg, "False"},
+  { "-bonuses",                        ".bonuses",                             XrmoptionNoArg, "True"},
+  { "-nobonuses",              ".bonuses",                             XrmoptionNoArg, "False"},
+  { "-crosshair",              ".crosshair",                   XrmoptionNoArg, "True"},
+  { "-nocrosshair",            ".crosshair",                   XrmoptionNoArg, "False"},
+  { "-psychedelic",            ".psychedelic",                 XrmoptionNoArg, "True"},
+  { "-nopsychedelic",  ".psychedelic",                 XrmoptionNoArg, "False"},
+  { 0, 0, 0, 0 }
+};
+
+
+void
+screenhack (Display *dpy, Window window)
+{
+#ifndef NDEBUG
+       atexit (abort);
+#endif
+
+       init_speedmine (dpy, window);
+
+       while (1) {
+               speedmine (dpy, window);
+               XSync (dpy, False);
+               screenhack_handle_events (dpy);
+               if (delay) usleep(delay);
+       }
+}
+
+/* vim: ts=4
+ */
diff --git a/hacks/speedmine.man b/hacks/speedmine.man
new file mode 100644 (file)
index 0000000..88be0c2
--- /dev/null
@@ -0,0 +1,242 @@
+.de EX         \"Begin example
+.ne 5
+.if n .sp 1
+.if t .sp .5
+.nf
+.in +.5i
+..
+.de EE
+.fi
+.in -.5i
+.if n .sp 1
+.if t .sp .5
+..
+.TH XScreenSaver 1 "23-Apr-01" "X Version 11"
+.SH NAME
+speedmine - simulates speeding down a rocky mineshaft, or a funky dancing worm
+.SH SYNOPSIS
+.B speedmine 
+[\-display \fIhost:display.screen\fP] [\-root] [\-window]
+[\-install] [\-noinstall] [\-visual \fIvisual\fP] [\-wire] [\-nowire]
+[\-worm]
+[\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-darkground \fIcolor\fP] [\-lightground \fIcolor\fP] [\-tunnelend \fIcolor\fP] [\-delay \fImicroseconds\fP] [\-maxspeed \fInumber\fP] [\-thrust \fInumber\fP] [\-gravity \fInumber\fP] [\-vertigo \fInumber\fP] [\-terrain] [\-noterrain] [\-smoothness \fInumber\fP] [\-curviness \fInumber\fP] [\-twistiness \fInumber\fP] [\-widening] [\-nowidening] [\-bumps] [\-nobumps] [\-bonuses] [\-crosshair] [\-nocrosshair] [\-psychedelic] [\-nopsychedelic]
+.SH DESCRIPTION
+.TP 8
+Speedmine!
+Down the speedmine, you'll find speed
+
+to satisfy your moving needs;
+
+So if you're looking for a blast
+
+then hit the speedmine, really fast.
+.PP
+Speedworm loves you.
+Speedworm likes to bump and grind
+
+and chase her tail, and dance around
+
+she really is a funky friend;
+
+she's made of speed from end to end.
+.PP
+You can configure stuff
+either with command-line options or X resources.
+.SH OPTIONS
+.TP 8
+.B \-display \fIhost:display.screen\fP
+Specifies which X display we should use (see the section DISPLAY NAMES in
+.BR X (1)
+for more information about this option).
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-noinstall
+Don't install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual
+class, or the id number (decimal or hex) of a specific visual.
+Possible choices include
+
+.RS
+default, best, mono, monochrome, gray, grey, color, staticgray, staticcolor, 
+truecolor, grayscale, greyscale, pseudocolor, directcolor, \fInumber\fP
+
+If a decimal or hexadecimal number is used, 
+.BR XGetVisualInfo (3X)
+is consulted to obtain the required visual.
+.RE
+.TP 8
+.B \-worm
+Be a happy spastic worm instead of a tunnel.
+.TP 8
+.B \-wire
+Specifies that the tunnel/worm should always be rendered in wireframe style.
+.TP 8
+.B \-nowire
+Specifies that the tunnel/worm should be rendered normally. Note that 
+tunnel rendering may still temporarily switch to wireframe style when 
+a wireframe bonus is hit, if
+.B bonuses
+are enabled.
+.TP 8
+.B \-foreground \fIcolor\fP
+Specifies the default foreground color.
+.TP 8
+.B \-background \fIcolor\fP
+Specifies the default background color.
+.TP 8
+.B \-darkground \fIcolor\fP
+Specifies the color of the darkest portions of the ground (or the
+worm's belly.)  The ground/belly is colored by a gradient between
+.B darkground
+and
+.B lightground.
+.TP 8
+.B \-lightground \fIcolor\fP
+Specifies the color of the lightest portions of the ground/belly. 
+The ground/belly is colored by a gradient between
+.B darkground
+and
+.B lightground.
+.TP 8
+.B \-tunnelend \fIcolor\fP
+Specifies the color of the light at the end of the tunnel.
+.TP 8
+.B \-delay \fImicroseconds\fP
+Specifies the delay between drawing successive frames. If you do not specify 
+.BR -sync ,
+some X servers may batch up several drawing operations together,
+producing a less smooth effect.   This is more likely to happen 
+in monochrome mode (on monochrome servers or when 
+.B \-mono 
+is specified).
+.TP 8
+.B -maxspeed \fInumber\fP
+Specifies an upper bound on the speed of normal movement. This does not
+affect the speed that may be attained when hitting a speed bonus.
+.TP 8
+.B -thrust \fInumber\fP
+Specifies the thrust constantly applied. Positive numbers indicate a forwards
+thrust, negative numbers indicate a backwards thrust.
+.TP 8
+.B -gravity \fInumber\fP
+Specifies the effect of gravity. Larger numbers will increase acceleration
+downhill and decrease acceleration uphill.
+.TP 8
+.B -vertigo \fInumber\fP
+Specifies to what level the demo should accentuate the curvature and
+windiness of the tunnel or worm.
+.TP 8
+.B -terrain
+Continuously generate a fractal terrain to simulate the rockiness of the
+tunnel walls, or the texture of the worm's skin.
+.TP 8
+.B -noterrain
+Do not generate terrain. When this option is set, all surfaces are flat.
+.TP 8
+.B -smoothness \fInumber\fP
+When
+.BR -terrain
+is set, specifies how smooth the walls or skin are.
+.TP 8
+.B -curviness \fInumber\fP
+Controls how much the generated tunnel (or worm) should curve left 
+and right, and dip up and down.
+.TP 8
+.B -twistiness \fInumber\fP
+Controls how much the generated tunnel (or worm) twists around itself.
+.TP 8
+.B -widening
+Specifies that the generated tunnel (or worm) may vary in width.
+.TP 8
+.B -nowidening
+Specifies that the average width should be kept constant.
+.TP 8
+.B -bumps
+Indicates that the simulation should take the bumpiness of the ground into
+account and allow the animation to shake and rattle when travelling over
+rough ground.  Or that the worm should be allowed to bump around and 
+shake her booty.
+.TP 8
+.B -nobumps
+Indicates that the bumpiness of the ground should be ignored, such that the
+simulation will glide through the tunnel.  Or that the worm should calm
+down and behave herself.
+.TP 8
+.B -bonuses
+Indicates that the demo should include bonus events. These include speed
+bonuses, spins, and changes of viewpoint and rendering style.
+.TP 8
+.B -nobonuses
+Indicates that bonuses should not be included in the demo.
+.TP 8
+.B -crosshair
+Specifies that a gaming style crosshair be drawn on the simulation. This
+serves little purpose but may make hardcore gamers feel more comfortable.
+.TP 8
+.B -nocrosshair
+Specifies that no crosshair be drawn.
+.TP 8
+.B -psychedelic
+Specifies that a psychedelic colormap should be generated. When this is
+set, the walls and ground of the tunnel are drawn in an often changing
+rainbow of colours.
+.TP 8
+.B -nopsychedelic
+Specifies that a normal colormap should be used, with muted walls and a
+grey road.
+.SH RESOURCES
+.EX
+Option            Resource               Default Value
+------            --------               -------------
+-wire             .wire                  False
+-background       .background            black
+-foreground       .foreground            white
+-darkground       .darkground            #101010
+-lightground      .lightground           #a0a0a0
+-tunnelend        .tunnelend             #000000
+-delay            .delay                 30000
+-maxspeed         .maxspeed              700
+-thrust           .thrust                1.0
+-gravity          .gravity               9.8
+-vertigo          .vertigo               1.0
+-terrain          .terrain               True
+-smoothness       .smoothness            6
+-curviness        .curviness             1.0
+-twistiness       .twistiness            1.0
+-widening         .widening              True
+-bumps            .bumps                 True
+-bonuses          .bonuses               True
+-crosshair        .crosshair             False
+-psychedelic      .psychedelic           False
+.EE
+.SH WARNING
+Speedworm is a trained professional. Do not try this at home.
+
+Prolonged viewing of this demo with
+.B maxspeed
+and
+.B vertigo
+above the defaults may have short-term psychological side effects including
+hyperactivity and attention deficiency.
+.SH COPYRIGHT
+Copyright \(co 2001, Conrad Parker.  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 AUTHOR
+Conrad Parker <conrad@deephackmode.org>, April 2001.
index a1ffc1028e11d1c25e24a7ddd34bbbe80c5ddade..3c8a47051c3bf442043f62bdae84cd094b3ca2e7 100644 (file)
@@ -3,44 +3,52 @@
 vidwhacker - grab images and apply random filters to them
 .SH SYNOPSIS
 .B vidwhacker
-[\-display \fIhost:display.screen\fP] [\-root] [\-window] [\-verbose] [\-stdin] [\-stdout] [\-delay seconds]
+[\-display \fIhost:display.screen\fP] [\-root] [\-verbose]
+[\-stdin] [\-stdout] [\-delay seconds]
+[-directory \fIdirectory\fP]
 .SH DESCRIPTION
-The \fIvidwhacker\fP program grabs a image from the system's video input,
-applies random image filters to it, and displays the result.  
-The \fIvidwhacker\fP program does not terminate until killed.
-It depends heavily on
-.BR xv (1)
-and the various PBM tools
-(e.g.,
+The \fIvidwhacker\fP program grabs an image from disk, or  from the
+system's video input, then applies random image filters to it, and
+displays the result.  The \fIvidwhacker\fP program does not terminate
+until killed.  
+
+It depends heavily on the various PBM tools (e.g.,
 .BR ppmrelief (1).)
+
+Selection of random image files is done by running the
+.BR xscreensaver-getimage-file (1)
+program.  Capture of video frames (if requested) is done by running the
+.BR xscreensaver-getimage-video (1)
+program.  The options of whether to do video, and which directory to 
+search for images, are specified in the \fI~/.xscreensaver\fP file.
 .SH OPTIONS
 .I vidwhacker
 accepts the following options:
 .TP 8
 .B \-root
-Draw on the root window.
-.TP 8
-.B \-window
-Pop up a new window displaying the image.  When a new image has been fully
-processed, destroy that window and pop up a new one.  This is the default.
+Draw on the root window.  This is the default.
 .TP 8
 .B \-verbose
 Print diagnostics.
 .TP 8
 .B \-stdin
-Instead of grabbing an image from the system's video input, read an image
-to maniupulate from stdin.  This image must be in 
-.TP 8
-.B \-delay \fIseconds\fP
-How long to sleep between images.  Default 3 seconds (the actual
-elapsed time is significantly longer, due to processing time.)
+Instead of grabbing an image from disk or video, read an image
+to maniupulate from stdin.  This image must be in
 .BR ppm (5)
 format.  The program will still perform repeated random image 
 transformations, but it will always use this one image as its starting point.
 .TP 8
+.B \-delay \fIseconds\fP
+How long to sleep between images.  Default 5 seconds (the actual
+elapsed time is significantly longer, due to processing time.)
+.TP 8
 .B \-stdout
 Instead of displaying the image on a window or on the root, write the new
 image on stdout, and exit.
+.TP 8
+.B \-directory \fIdirectory\fP
+Use this directory instead of the \fBimageDirectory\fP specified in 
+the \fI~/.xscreensaver\fP file.
 .SH ENVIRONMENT
 .PP
 .TP 8
@@ -51,12 +59,6 @@ to get the default host and display number.
 to get the name of a resource file that overrides the global resources
 stored in the RESOURCE_MANAGER property.
 .SH BUGS
-Grabbing video images is, of course, very system-dependent.  It works
-on SGIs, and on Linux systems that have the
-.BR qcam (1)
-program.  If your system does things differently, you'll need to edit
-the vidwhacker script (look for the \fIgrab()\fP function.)
-
 It's slow.
 .SH TO DO
 It might be interesting to rewrite this to use
@@ -66,11 +68,13 @@ but there would be a wider variety of effects available.
 .SH SEE ALSO
 .BR X (1),
 .BR xscreensaver (1),
+.BR xscreensaver-getimage-file (1),
+.BR xscreensaver-getimage-video (1),
 .BR xv (1),
 .BR ppmtogif (1),
 .BR cjpeg (1)
 .SH COPYRIGHT
-Copyright \(co 1998, 1999 by Jamie Zawinski.  Permission to use, copy, modify, 
+Copyright \(co 1998-2001 by Jamie Zawinski.  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
index 5461ac318582609d279dca92e65b5feeb7b9c21e..f77c6153500a83fdfacf12671d7e118390083077 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/perl -w
 #
-# webcollage, Copyright (c) 1999, 2000 by Jamie Zawinski <jwz@jwz.org>
+# webcollage, Copyright (c) 1999-2001 by Jamie Zawinski <jwz@jwz.org>
 # This program decorates the screen with random images from the web.
 # One satisfied customer described it as "a nonstop pop culture brainbath."
 #
 
 # To run this as a display mode with xscreensaver, add this to `programs':
 #
-#   default-n:  webcollage -root                                       \n\
-#   default-n: webcollage -root -filter 'vidwhacker -stdin -stdout'    \n\
+#   default-n:  webcollage -root                                        \n\
+#   default-n:  webcollage -root -filter 'vidwhacker -stdin -stdout'    \n\
+
 
 require 5;
-#use diagnostics;
 use strict;
 
+# We can't "use diagnostics" here, because that library malfunctions if
+# you signal and catch alarms: it says "Uncaught exception from user code"
+# and exits, even though I damned well AM catching it!
+#use diagnostics;
+
+
 use Socket;
 require Time::Local;
 require POSIX;
@@ -28,88 +34,137 @@ use Fcntl ':flock'; # import LOCK_* constants
 use POSIX qw(strftime);
 
 
-my $version = q{ $Revision: 1.65 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
-my $copyright = "WebCollage $version, Copyright (c) 1999" .
+my $progname = $0; $progname =~ s@.*/@@g;
+my $version = q{ $Revision: 1.77 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
+my $copyright = "WebCollage $version, Copyright (c) 1999-2001" .
     " Jamie Zawinski <jwz\@jwz.org>\n" .
     "            http://www.jwz.org/xscreensaver/\n";
 
-my $argv0 = $0;
-my $progname = $argv0; $progname =~ s@.*/@@g;
-
-my $random_redirector = "http://random.yahoo.com/bin/ryl";
-my $image_randomizer_1 = "http://www.altavista.com/query" .
-                         "?mmdo=3" .
-                         "&nbq=12" .
-                         "&stype=simage" .
-                         "&iclr=1" .
-                         "&ibw=1" .
-                         "&iexc=1" .
-                         "&what=web" .
-                         "&q=";
-my $image_randomizer_2 = "http://www.hotbot.com/?clickSrc=search" .
-                         "&submit=SEARCH&SM=SC&LG=any" .
-                         "&AM0=MC&AT0=words&AW0=" .
-                         "&AM1=MN&AT1=words&AW1=" .
-                         "&savenummod=2&date=within" .
-                         "&DV=0&DR=newer&DM=1&DD=1&DY=99&FVI=1&FS=&RD=RG" .
-                         "&RG=all&Domain=&PS=A&PD=&STEM=1&DC=50&DE=0&_v=2" .
-                         "&OPs=MDRTP&NUMMOD=2" .
-                         "&MT=";
-my $image_randomizer_3 = "http://www.altavista.com/cgi-bin/query?pg=q" .
-                         "&text=yes&kl=XX&stype=stext&q=";
-my $image_randomizer_4 = "http://search.news.yahoo.com/search/news_photos?" .
-                         "&z=&n=100&o=o&2=&3=&p=";
-
-# I guess Photopoint got wise to me, because now they are doing error
-# checking on the user ("u=") and album ("a=") parameters.  Oh well.
+
+
+my @search_methods = (  35, "imagevista", \&pick_from_alta_vista_images,
+                        33, "altavista",  \&pick_from_alta_vista_text,
+                        20, "yahoorand",  \&pick_from_yahoo_random_link,
+                         2, "yahoonews",  \&pick_from_yahoo_news_text,
+                        10, "lycos",      \&pick_from_lycos_text,
+
+                     # Hotbot gives me "no matches" just about every time.
+                     # Then I try the same URL again, and it works.  I guess
+                     # it caches searches, and webcollage always busts its
+                     # cache and time out?  Or it just sucks.
+                     #   0, "hotbot",     \&pick_from_hotbot_text,
+                      );
+
+#@search_methods=(100, "lycos",     \&pick_from_lycos_text);
+
+# programs we can use to write to the root window (tried in ascending order.)
 #
-#my $photo_randomizer   = "http://albums.photopoint.com/j/View?u=1&a=1&p=";
-#my $photo_randomizer_lo = 10000001;
-#my $photo_randomizer_hi = 12400000;
+my @root_displayers = ( 
+  "xloadimage -quiet -onroot -center -border black",
+  "xli        -quiet -onroot -center -border black",
+  "xv         -root -quit -viewonly +noresetroot -rmode 5" .
+  "           -rfg black -rbg black",
+  "chbg       -once -xscreensaver",
 
-my $image_ppm   = ($ENV{TMPDIR} ? $ENV{TMPDIR} : "/tmp") . "/webcollage." . $$;
-my $image_tmp1  = $image_ppm . "-1";
-my $image_tmp2  = $image_ppm . "-2";
+# this lame program wasn't built with vroot.h:
+# "xsri       -scale -keep-aspect -center-horizontal -center-vertical",
+);
 
-my $img_width;           # size of the image being generated.
-my $img_height;
+
+# Some sites need cookies to work properly.   These are they.
+#
+my %cookies = (
+  "www.altavista.com"  =>  "AV_ALL=1",   # request uncensored searches
+  "web.altavista.com"  =>  "AV_ALL=1",
+
+                                         # log in as "cpunks"
+  "www.nytimes.com"    =>  "NYT-S=104nv1sChNnnWAvTLGx6eiDhzQcbSoN" .
+                                 "6zOMB7s0Qm8MlMaa8It.2/BlXTrpbBk" .
+                                 "jinV68IcqxOvAABDyKdciIJ8O000",
+);
+
+
+# Some sites have  managed to poison the search engines.  These are they.
+# (We auto-detect sites that have poisoned the search engines via excessive
+# keywords or dictionary words,  but these are ones that slip through
+# anyway.)
+#
+# This can contain full host names, or 2 or 3 component domains.
+#
+my %poisoners = (
+  "die.net"                 => 1,  # 'l33t h4ck3r d00dz.
+  "genforum.genealogy.com"  => 1,  # Cluttering altavista with human names.
+  "rootsweb.com"            => 1,  # Cluttering altavista with human names.
+  "akamai.net"              => 1,  # Lots of sites have their images on Akamai.
+                                   # But those are pretty much all banners.
+                                   # Since Akamai is super-expensive, let's
+                                   # go out on a limb and assume that all of
+                                   # their customers are rich-and-boring.
+);
+
+
+# When verbosity is turned on, we warn about sites that we seem to be hitting
+# a lot: usually this means some new poisoner has made it into the search
+# engines.  But sometimes, the warning is just because that site has a lot
+# of stuff on it.  So these are the sites that are immune to the "frequent
+# site" diagnostic message.
+#
+my %warningless_sites = (
+  "home.earthlink.net"      => 1,  # Lots of home pages here.
+  "www.geocities.com"       => 1,
+  "www.angelfire.com"       => 1,
+  "members.aol.com"         => 1,
+
+  "yimg.com"                => 1,  # This is where dailynews.yahoo.com stores
+  "eimg.com"                => 1,  # its images, so pick_from_yahoo_news_text()
+                                   # hits this every time.
+);
+
+
+##############################################################################
+#
+# Various global flags set by command line parameters, or computed
+#
+##############################################################################
+
+
+my $current_state = "???";      # for diagnostics
+my $load_method;
+my $last_search;
+my $image_succeeded = -1;
+my $suppress_audit = 0;
+
+my $verbose_imgmap = 0;         # print out rectangles and URLs only (stdout)
+my $verbose_warnings = 0;       # print out warnings when things go wrong
+my $verbose_load = 0;           # diagnostics about loading of URLs
+my $verbose_filter = 0;         # diagnostics about page selection/rejection
+my $verbose_net = 0;            # diagnostics about network I/O
+my $verbose_pbm = 0;            # diagnostics about PBM pipelines
+my $verbose_http = 0;           # diagnostics about all HTTP activity
+my $verbose_exec = 0;           # diagnostics about executing programs
+
+my $report_performance_interval = 60 * 15;  # print some stats every 15 minutes
 
 my $http_proxy = undef;
 my $http_timeout = 30;
 my $cvt_timeout = 10;
 
-# programs we can use to write to the root window (tried in ascending order.)
-my $ppm_to_root_window_cmd_1 = "xloadimage -onroot -quiet %%PPM%%";
-my $ppm_to_root_window_cmd_2 = "xli -quiet -onroot -center" .
-                               " -border black %%PPM%%";
-my $ppm_to_root_window_cmd_3 = "xv -root -rmode 5 -viewonly" .
-                               " +noresetroot %%PPM%% -quit";
-
-my $ppm_to_root_window_cmd = undef;     # initialized by x_output()
+my $min_width = 50;
+my $min_height = 50;
+my $min_ratio = 1/5;
 
-my $filter_cmd = undef;
-my $post_filter_cmd = undef;
-my $background = undef;
 my $no_output_p = 0;
 my $urls_only_p = 0;
-my $delay = 0;
 
 my $wordlist = "/usr/dict/words";
 
 if (!-r $wordlist) {
-    $wordlist = "/usr/share/dict/words";       # BSD
+  $wordlist = "/usr/share/dict/words";          # BSD
 }
 if (!-r $wordlist) {
-    $wordlist = "/usr/share/lib/dict/words";    # Irix
+  $wordlist = "/usr/share/lib/dict/words";      # Irix
 }
-die "$wordlist doesn't exist!\n" unless (-r $wordlist);
-
-
-my $min_width = 50;
-my $min_height = 50;
-my $min_ratio = 1/5;
-
-my $verbose = 0;
+die "$progname: $wordlist doesn't exist!\n" unless (-r $wordlist);
 
 my %rejected_urls;
 my @tripwire_words = ("aberrate", "abode", "amorphous", "antioch",
@@ -119,11 +174,6 @@ my @tripwire_words = ("aberrate", "abode", "amorphous", "antioch",
                       "eggplant");
 
 
-sub blurb {
-    return "$progname: " . strftime ("%H:%M:%S: ", localtime);
-}
-
-
 ##############################################################################
 #
 # Retrieving URLs
@@ -134,111 +184,141 @@ sub blurb {
 # and the document body.
 #
 sub get_document_1 {
-    my ( $url, $referer, $timeout ) = @_;
-
-    if (!defined($timeout)) { $timeout = $http_timeout; }
-    if ($timeout <= 0) { return (); }
-    if ($timeout > $http_timeout) { $timeout = $http_timeout; }
+  my ( $url, $referer, $timeout ) = @_;
 
-    if ( $verbose > 3 ) {
-       print STDERR blurb() . "get_document_1 $url " .
-            ($referer ? $referer : "") . "\n";
-    }
+  if (!defined($timeout)) { $timeout = $http_timeout; }
+  if ($timeout > $http_timeout) { $timeout = $http_timeout; }
 
-    my($url_proto, $dummy, $serverstring, $path) = split(/\//, $url, 4);
-    if (! ($url_proto && $url_proto =~ m/^http:$/i)) {
-        if ($verbose) { print STDERR blurb() . "not an HTTP URL: $url\n"; }
-        return ();
-    }
-
-    $path = "" unless $path;
+  if ($timeout <= 0) {
+    LOG (($verbose_net || $verbose_load), "timed out for $url");
+    return ();
+  }
 
-    my($them,$port) = split(/:/, $serverstring);
-    $port = 80 unless $port;
+  LOG ($verbose_net, "get_document_1 $url " . ($referer ? $referer : ""));
 
-    my $them2 = $them;
-    my $port2 = $port;
-    if ($http_proxy) {
-        $serverstring = $http_proxy if $http_proxy;
-        ($them2,$port2) = split(/:/, $serverstring);
-        $port2 = 80 unless $port2;
-    }
-
-    my ($remote, $iaddr, $paddr, $proto, $line);
-    $remote = $them2;
-    if ($port2 =~ /\D/) { $port2 = getservbyname($port2, 'tcp') }
-    return unless $port2;
-    $iaddr   = inet_aton($remote) || return;
-    $paddr   = sockaddr_in($port2, $iaddr);
+  if (! ($url =~ m@^http://@i)) {
+    LOG ($verbose_net, "not an HTTP URL: $url");
+    return ();
+  }
+
+  my ($url_proto, $dummy, $serverstring, $path) = split(/\//, $url, 4);
+  $path = "" unless $path;
+
+  my ($them,$port) = split(/:/, $serverstring);
+  $port = 80 unless $port;
+
+  my $them2 = $them;
+  my $port2 = $port;
+  if ($http_proxy) {
+    $serverstring = $http_proxy if $http_proxy;
+    ($them2,$port2) = split(/:/, $serverstring);
+    $port2 = 80 unless $port2;
+  }
+
+  my ($remote, $iaddr, $paddr, $proto, $line);
+  $remote = $them2;
+  if ($port2 =~ /\D/) { $port2 = getservbyname($port2, 'tcp') }
+  if (!$port2) {
+    LOG (($verbose_net || $verbose_load), "unrecognised port in $url");
+    return ();
+  }
+  $iaddr   = inet_aton($remote);
+  if (!$iaddr) {
+    LOG (($verbose_net || $verbose_load), "host not found: $remote");
+    return ();
+  }
+  $paddr   = sockaddr_in($port2, $iaddr);
 
 
-    my $head = "";
-    my $body = "";
+  my $head = "";
+  my $body = "";
 
-    @_ =
+  @_ =
     eval {
-        local $SIG{ALRM}  = sub {
-            if ($verbose > 0) {
-                print STDERR blurb() . "timed out ($timeout) for $url\n";
-            }
-            die "alarm\n"
-            };
-        alarm $timeout;
-
-        $proto   = getprotobyname('tcp');
-        if (!socket(S, PF_INET, SOCK_STREAM, $proto)) {
-            print STDERR blurb() . "socket: $!\n" if ($verbose);
-            return;
-        }
-        if (!connect(S, $paddr)) {
-            print STDERR blurb() . "connect($serverstring): $!\n"
-                if ($verbose);
-            return;
-        }
+      local $SIG{ALRM} = sub {
+        LOG (($verbose_net || $verbose_load), "timed out ($timeout) for $url");
+        die "alarm\n";
+      };
+      alarm $timeout;
+
+      $proto   = getprotobyname('tcp');
+      if (!socket(S, PF_INET, SOCK_STREAM, $proto)) {
+        LOG (($verbose_net || $verbose_load), "socket: $!");
+        return ();
+      }
+      if (!connect(S, $paddr)) {
+        LOG (($verbose_net || $verbose_load), "connect($serverstring): $!");
+        return ();
+      }
 
-        select(S); $| = 1; select(STDOUT);
+      select(S); $| = 1; select(STDOUT);
 
-        my $cookie;
-        if ($remote =~ m/\baltavista\.com$/i) {
-            # kludge to tell the various altavista sites to be uncensored.
-            $cookie = "AV_ALL=1";
-        }
+      my $cookie = $cookies{$them};
 
-        print S ("GET " . ($http_proxy ? $url : "/$path") . " HTTP/1.0\r\n" .
+      my $hdrs = "GET " . ($http_proxy ? $url : "/$path") . " HTTP/1.0\r\n" .
                  "Host: $them\r\n" .
-                 "User-Agent: $progname/$version\r\n" .
-                 ($referer ? "Referer: $referer\r\n" : "") .
-                 ($cookie ? "Cookie: $cookie\r\n" : "") .
-                 "\r\n");
-        my $http = <S>;
-
-        while (<S>) {
-            $head .= $_;
-            last if m@^[\r\n]@;
+                 "User-Agent: $progname/$version\r\n";
+      if ($referer) {
+        $hdrs .= "Referer: $referer\r\n";
+      }
+      if ($cookie) {
+        foreach (split(/\r?\n/, $cookie)) {
+          $hdrs .= "Cookie: $_\r\n";
         }
-        while (<S>) {
-            $body .= $_;
+      }
+      $hdrs .= "\r\n";
+
+      foreach (split('\r?\n', $hdrs)) {
+        LOG ($verbose_http, "  ==> $_");
+      }
+      print S $hdrs;
+      my $http = <S>;
+
+      $_  = $http;
+      s/[\r\n]+$//s;
+      LOG ($verbose_http, "  <== $_");
+
+      while (<S>) {
+        $head .= $_;
+        s/[\r\n]+$//s;
+        last if m@^$@;
+        LOG ($verbose_http, "  <== $_");
+
+        if (m@^Set-cookie:\s*([^;\r\n]+)@i) {
+          set_cookie($them, $1)
         }
+      }
 
-        close S;
+      my $lines = 0;
+      while (<S>) {
+        $body .= $_;
+        $lines++;
+      }
 
-        if ( $verbose > 3 ) {
-            print STDERR blurb() . "   ==> $http\n";
-        }
+      LOG ($verbose_http,
+           "  <== [ body ]: $lines lines, " . length($body) . " bytes");
 
-        return ( $http, $head, $body );
-    };
-    die if ($@ && $@ ne "alarm\n");       # propagate errors
-    if ($@) {
-        # timed out
-        $head = undef;
-        $body = undef;
+      close S;
+
+      if (!$http) {
+        LOG (($verbose_net || $verbose_load), "null response: $url");
         return ();
-    } else {
-        # didn't
-        alarm 0;
-        return @_;
-    }
+      }
+
+      return ( $http, $head, $body );
+    };
+  die if ($@ && $@ ne "alarm\n");       # propagate errors
+  if ($@) {
+    # timed out
+    $head = undef;
+    $body = undef;
+    $suppress_audit = 1;
+    return ();
+  } else {
+    # didn't
+    alarm 0;
+    return @_;
+  }
 }
 
 
@@ -246,324 +326,322 @@ sub get_document_1 {
 # if the given URL did a redirect, returns the redirected-to document.
 #
 sub get_document {
-    my ( $url, $referer, $timeout ) = @_;
-    my $start = time;
+  my ( $url, $referer, $timeout ) = @_;
+  my $start = time;
 
-    my $orig_url = $url;
-    my $loop_count = 0;
-    my $max_loop_count = 4;
+  my $orig_url = $url;
+  my $loop_count = 0;
+  my $max_loop_count = 4;
 
-    do {
-        if (defined($timeout) && $timeout <= 0) { return (); }
+  do {
+    if (defined($timeout) && $timeout <= 0) {
+      LOG (($verbose_net || $verbose_load), "timed out for $url");
+      $suppress_audit = 1;
+      return ();
+    }
 
-       my ( $http, $head, $body ) = get_document_1 ($url, $referer, $timeout);
+    my ( $http, $head, $body ) = get_document_1 ($url, $referer, $timeout);
 
-        if (defined ($timeout)) {
-            my $now = time;
-            my $elapsed = $now - $start;
-            $timeout -= $elapsed;
-            $start = $now;
+    if (defined ($timeout)) {
+      my $now = time;
+      my $elapsed = $now - $start;
+      $timeout -= $elapsed;
+      $start = $now;
+    }
+
+    return () unless $http; # error message already printed
+
+    $http =~ s/[\r\n]+$//s;
+
+    if ( $http =~ m@^HTTP/[0-9.]+ 30[123]@ ) {
+      $_ = $head;
+      my ( $location ) = m@^location:[ \t]*(.*)$@im;
+      if ( $location ) {
+        $location =~ s/[\r\n]$//;
+
+        LOG ($verbose_net, "redirect from $url to $location");
+        $referer = $url;
+        $url = $location;
+
+        if ($url =~ m@^/@) {
+          $referer =~ m@^(http://[^/]+)@i;
+          $url = $1 . $url;
+        } elsif (! ($url =~ m@^[a-z]+:@i)) {
+          $_ = $referer;
+          s@[^/]+$@@g if m@^http://[^/]+/@i;
+          $_ .= "/" if m@^http://[^/]+$@i;
+          $url = $_ . $url;
         }
 
-       return () if ( ! $body );
-
-       if ( $http =~ m@HTTP/[0-9.]+ 30[23]@ ) {
-           $_ = $head;
-           my ( $location ) = m@^location:[ \t]*(.*)$@im;
-           if ( $location ) {
-                $location =~ s/[\r\n]$//;
-
-               if ( $verbose > 3 ) {
-                   print STDERR blurb() . "redirect from " .
-                        "$url to $location\n";
-               }
-                $referer = $url;
-               $url = $location;
-
-                if ($url =~ m@^/@) {
-                    $referer =~ m@^(http://[^/]+)@i;
-                    $url = $1 . $url;
-                } elsif (! ($url =~ m@^[a-z]+:@i)) {
-                    $_ = $referer;
-                    s@[^/]+$@@g if m@^http://[^/]+/@i;
-                    $_ .= "/" if m@^http://[^/]+$@i;
-                    $url = $_ . $url;
-                }
-
-           } else {
-               return ( $url, $body );
-           }
-
-            if ($loop_count++ > $max_loop_count) {
-               if ( $verbose > 1 ) {
-                   print STDERR blurb() . "too many redirects " .
-                        "($max_loop_count) from $orig_url\n";
-               }
-                $body = undef;
-                return ();
-            }
-
-        } elsif ( $http =~ m@HTTP/[0-9.]+ [4-9][0-9][0-9]@ ) {
-            # http errors -- return nothing.
-            $body = undef;
-            return ();
-
-       } else {
-
-           return ( $url, $body );
-       }
-
-    } while (1);
-}
-
+      } else {
+        LOG ($verbose_net, "no Location with \"$http\"");
+        return ( $url, $body );
+      }
 
-# given a URL and the body text at that URL, selects and returns a random
-# image from it.  returns () if no suitable images found.
-#
-sub pick_image_from_body {
-    my ( $url, $body ) = @_;
+      if ($loop_count++ > $max_loop_count) {
+        LOG ($verbose_net,
+             "too many redirects ($max_loop_count) from $orig_url");
+        $body = undef;
+        return ();
+      }
 
-    my $base = $url;
-    $_ = $url;
+    } elsif ( $http =~ m@^HTTP/[0-9.]+ ([4-9][0-9][0-9].*)$@ ) {
 
-    # if there's at least one slash after the host, take off the last
-    # pathname component
-    if ( m@^http://[^/]+/@io ) {
-       $base =~ s@[^/]+$@@go;
-    }
+      LOG (($verbose_net || $verbose_load), "failed: $1 ($url)");
 
-    # if there are no slashes after the host at all, put one on the end.
-    if ( m@^http://[^/]+$@io ) {
-       $base .= "/";
-    }
-
-    if ( $verbose > 3 ) {
-       print STDERR blurb() . "base is $base\n";
-    }
+      # http errors -- return nothing.
+      $body = undef;
+      return ();
 
+    } elsif (!$body) {
 
-    $_ = $body;
+      LOG (($verbose_net || $verbose_load), "document contains no data: $url");
+      return ();
 
-    # strip out newlines, compress whitespace
-    s/[\r\n\t ]+/ /go;
+    } else {
 
-    # nuke comments
-    s/<!--.*?-->//go;
+      # ok!
+      return ( $url, $body );
+    }
 
+  } while (1);
+}
 
-    # There are certain web sites that list huge numbers of dictionary
-    # words in their bodies or in their <META NAME=KEYWORDS> tags (surprise!
-    # Porn sites tend not to be reputable!)
-    #
-    # I do not want webcollage to filter on content: I want it to select
-    # randomly from the set of images on the web.  All the logic here for
-    # rejecting some images is really a set of heuristics for rejecting
-    # images that are not really images: for rejecting *text* that is in
-    # GIF/JPEG form.  I don't want text, I want pictures, and I want the
-    # content of the pictures to be randomly selected from among all the
-    # available content.
-    #
-    # So, filtering out "dirty" pictures by looking for "dirty" keywords
-    # would be wrong: dirty pictures exist, like it or not, so webcollage
-    # should be able to select them.
-    #
-    # However, picking a random URL is a hard thing to do.  The mechanism I'm
-    # using is to search for a selection of random words.  This is not
-    # perfect, but works ok most of the time.  The way it breaks down is when
-    # some URLs get precedence because their pages list *every word* as
-    # related -- those URLs come up more often than others.
-    #
-    # So, after we've retrieved a URL, if it has too many keywords, reject
-    # it.  We reject it not on the basis of what those keywords are, but on
-    # the basis that by having so many, the page has gotten an unfair
-    # advantage against our randomizer.
-    #
-    my $trip_count = 0;
-    foreach my $trip (@tripwire_words) {
-        $trip_count++ if m/$trip/i;
-    }
-    if ($trip_count >= $#tripwire_words - 2) {
-        if ($verbose > 1) {
-            print STDERR blurb() . "there is probably a dictionary in" .
-                " \"$url\": rejecting.\n";
-        }
-        $rejected_urls{$url} = -1;
-        $body = undef;
-        $_ = undef;
-        return ();
-    }
+# If we already have a cookie defined for this site, and the site is trying
+# to overwrite that very same cookie, let it do so.  This is because nytimes
+# expires its cookies - it lets you upgrade to a new cookie without logging
+# in again, but you have to present the old cookie to get the new cookie.
+# So, by doing this, the built-in cypherpunks cookie will never go "stale".
+#
+sub set_cookie {
+  my ($host, $cookie) = @_;
+  my $oc = $cookies{$host};
+  return unless $oc;
+  $_ = $oc;
+  my ($oc_name, $oc_value) = m@^([^= \t\r\n]+)=(.*)$@;
+  $_ = $cookie;
+  my ($nc_name, $nc_value) = m@^([^= \t\r\n]+)=(.*)$@;
+
+  if ($oc_name eq $nc_name &&
+      $oc_value ne $nc_value) {
+    $cookies{$host} = $cookie;
+    LOG ($verbose_net, "overwrote ${host}'s $oc_name cookie");
+  }
+}
 
 
-    my @urls;
-    my %unique_urls;
-
-    foreach (split(/ *</)) {
-        if ( m/^meta /i ) {
-
-            # Likewise, reject any web pages that have a KEYWORDS meta tag
-            # that is too long.
-            #
-            if (m/name ?= ?\"?keywords\"?/i &&
-                m/content ?= ?\"([^\"]+)\"/) {
-                my $L = length($1);
-                if ($L > 1000) {
-                    if ($verbose > 1) {
-                        print STDERR blurb() . "keywords of" .
-                            " length $L in $url: rejecting.\n";
-                    }
-                    $rejected_urls{$url} = $L;
-                    $body = undef;
-                    $_ = undef;
-                    return ();
-                } elsif ( $verbose > 2 ) {
-                    print STDERR blurb() . "keywords of length $L" .
-                        " in $url (ok.)\n";
-                }
-            }
-
-        } elsif ( m/^(img|a) .*(src|href) ?= ?\"? ?(.*?)[ >\"]/io ) {
-
-           my $was_inline = ( "$1" eq "a" || "$1" eq "A" );
-           my $link = $3;
-           my ( $width )  = m/width ?=[ \"]*(\d+)/oi;
-           my ( $height ) = m/height ?=[ \"]*(\d+)/oi;
-           $_ = $link;
-
-           if ( m@^/@o ) {
-               my $site;
-               ( $site = $base ) =~ s@^(http://[^/]*).*@$1@gio;
-               $_ = "$site$link";
-           } elsif ( ! m@^[^/:?]+:@ ) {
-               $_ = "$base$link";
-                s@/\./@/@g;
-                while (s@/\.\./@/@g) {
-                }
-           }
-
-           # skip non-http
-           if ( ! m@^http://@io ) {
-               next;
-           }
-
-           # skip non-image
-           if ( ! m@[.](gif|jpg|jpeg|pjpg|pjpeg)$@io ) {
-               next;
-           }
-
-           # skip really short or really narrow images
-           if ( $width && $width < $min_width) {
-               if ( $verbose > 2 ) {
-                    if (!$height) { $height = "?"; }
-                   print STDERR blurb() . "skip narrow image " .
-                        "$_ (${width}x$height)\n";
-               }
-               next;
-           }
-
-           if ( $height && $height < $min_height) {
-               if ( $verbose > 2 ) {
-                    if (!$width) { $width = "?"; }
-                   print STDERR blurb() . "skip short image " .
-                        "$_ (${width}x$height)\n";
-               }
-               next;
-           }
-
-            # skip images with ratios that make them look like banners.
-           if ( $min_ratio && $width && $height &&
-                ($width * $min_ratio ) > $height ) {
-               if ( $verbose > 2 ) {
-                    if (!$height) { $height = "?"; }
-                   print STDERR blurb() . "skip bad ratio " .
-                        "$_ (${width}x$height)\n";
-               }
-               next;
-           }
-
-           my $url = $_;
-
-           if ( $unique_urls{$url} ) {
-               if ( $verbose > 2 ) {
-                    print STDERR blurb() . "skip duplicate image $_\n";
-                }
-               next;
-           }
-
-           if ( $verbose > 2 ) {
-               print STDERR blurb() . "got $url" . 
-                   ($width && $height ? " (${width}x${height})" : "") .
-                   ($was_inline ? " (inline)" : "") . "\n";
-           }
-
-           $urls[++$#urls] = $url;
-           $unique_urls{$url}++;
-
-           # jpegs are preferable to gifs.
-            $_ = $url;
-            if ( ! m@[.]gif$@io ) {
-               $urls[++$#urls] = $url;
-            }
-
-           # pointers to images are preferable to inlined images.
-           if ( ! $was_inline ) {
-               $urls[++$#urls] = $url;
-               $urls[++$#urls] = $url;
-           }
-       }
-    }
+############################################################################
+#
+# Extracting image URLs from HTML
+#
+############################################################################
 
-    $_ = undef;
+# given a URL and the body text at that URL, selects and returns a random
+# image from it.  returns () if no suitable images found.
+#
+sub pick_image_from_body {
+  my ( $url, $body ) = @_;
+
+  my $base = $url;
+  $_ = $url;
+
+  # if there's at least one slash after the host, take off the last
+  # pathname component
+  if ( m@^http://[^/]+/@io ) {
+    $base =~ s@[^/]+$@@go;
+  }
+
+  # if there are no slashes after the host at all, put one on the end.
+  if ( m@^http://[^/]+$@io ) {
+    $base .= "/";
+  }
+
+  $_ = $body;
+
+  # strip out newlines, compress whitespace
+  s/[\r\n\t ]+/ /go;
+
+  # nuke comments
+  s/<!--.*?-->//go;
+
+
+  # There are certain web sites that list huge numbers of dictionary
+  # words in their bodies or in their <META NAME=KEYWORDS> tags (surprise!
+  # Porn sites tend not to be reputable!)
+  #
+  # I do not want webcollage to filter on content: I want it to select
+  # randomly from the set of images on the web.  All the logic here for
+  # rejecting some images is really a set of heuristics for rejecting
+  # images that are not really images: for rejecting *text* that is in
+  # GIF/JPEG form.  I don't want text, I want pictures, and I want the
+  # content of the pictures to be randomly selected from among all the
+  # available content.
+  #
+  # So, filtering out "dirty" pictures by looking for "dirty" keywords
+  # would be wrong: dirty pictures exist, like it or not, so webcollage
+  # should be able to select them.
+  #
+  # However, picking a random URL is a hard thing to do.  The mechanism I'm
+  # using is to search for a selection of random words.  This is not
+  # perfect, but works ok most of the time.  The way it breaks down is when
+  # some URLs get precedence because their pages list *every word* as
+  # related -- those URLs come up more often than others.
+  #
+  # So, after we've retrieved a URL, if it has too many keywords, reject
+  # it.  We reject it not on the basis of what those keywords are, but on
+  # the basis that by having so many, the page has gotten an unfair
+  # advantage against our randomizer.
+  #
+  my $trip_count = 0;
+  foreach my $trip (@tripwire_words) {
+    $trip_count++ if m/$trip/i;
+  }
+
+  if ($trip_count >= $#tripwire_words - 2) {
+    LOG (($verbose_filter || $verbose_load),
+         "there is probably a dictionary in \"$url\": rejecting.");
+    $rejected_urls{$url} = -1;
     $body = undef;
+    $_ = undef;
+    return ();
+  }
+
+
+  my @urls;
+  my %unique_urls;
+
+  foreach (split(/ *</)) {
+    if ( m/^meta /i ) {
+
+      # Likewise, reject any web pages that have a KEYWORDS meta tag
+      # that is too long.
+      #
+      if (m/name ?= ?\"?keywords\"?/i &&
+          m/content ?= ?\"([^\"]+)\"/) {
+        my $L = length($1);
+        if ($L > 1000) {
+          LOG (($verbose_filter || $verbose_load),
+               "excessive keywords ($L bytes) in $url: rejecting.");
+          $rejected_urls{$url} = $L;
+          $body = undef;
+          $_ = undef;
+          return ();
+        } else {
+          LOG ($verbose_filter, "  keywords ($L bytes) in $url (ok)");
+        }
+      }
+
+    } elsif ( m/^(img|a) .*(src|href) ?= ?\"? ?(.*?)[ >\"]/io ) {
+
+      my $was_inline = ( "$1" eq "a" || "$1" eq "A" );
+      my $link = $3;
+      my ( $width )  = m/width ?=[ \"]*(\d+)/oi;
+      my ( $height ) = m/height ?=[ \"]*(\d+)/oi;
+      $_ = $link;
+
+      if ( m@^/@o ) {
+        my $site;
+        ( $site = $base ) =~ s@^(http://[^/]*).*@$1@gio;
+        $_ = "$site$link";
+      } elsif ( ! m@^[^/:?]+:@ ) {
+        $_ = "$base$link";
+        s@/\./@/@g;
+        while (s@/\.\./@/@g) {
+        }
+      }
+
+      # skip non-http
+      if ( ! m@^http://@io ) {
+        next;
+      }
+
+      # skip non-image
+      if ( ! m@[.](gif|jpg|jpeg|pjpg|pjpeg)$@io ) {
+        next;
+      }
+
+      # skip really short or really narrow images
+      if ( $width && $width < $min_width) {
+        if (!$height) { $height = "?"; }
+        LOG ($verbose_filter, "  skip narrow image $_ (${width}x$height)");
+        next;
+      }
+
+      if ( $height && $height < $min_height) {
+        if (!$width) { $width = "?"; }
+        LOG ($verbose_filter, "  skip short image $_ (${width}x$height)");
+        next;
+      }
+
+      # skip images with ratios that make them look like banners.
+      if ($min_ratio && $width && $height &&
+          ($width * $min_ratio ) > $height) {
+        if (!$height) { $height = "?"; }
+        LOG ($verbose_filter, "  skip bad ratio $_ (${width}x$height)");
+        next;
+      }
+
+      my $url = $_;
+
+      if ($unique_urls{$url}) {
+        LOG ($verbose_filter, "  skip duplicate image $_");
+        next;
+      }
+
+      LOG ($verbose_filter,
+           "  image $url" . 
+           ($width && $height ? " (${width}x${height})" : "") .
+           ($was_inline ? " (inline)" : ""));
+
+      $urls[++$#urls] = $url;
+      $unique_urls{$url}++;
+
+      # jpegs are preferable to gifs.
+      $_ = $url;
+      if ( ! m@[.]gif$@io ) {
+        $urls[++$#urls] = $url;
+      }
+
+      # pointers to images are preferable to inlined images.
+      if ( ! $was_inline ) {
+        $urls[++$#urls] = $url;
+        $urls[++$#urls] = $url;
+      }
+    }
+  }
+
+  my $fsp = ($body =~ m@<frameset@i);
+
+  $_ = undef;
+  $body = undef;
+
+  if ( $#urls < 0 ) {
+    LOG ($verbose_load, "no images on $base" . ($fsp ? " (frameset)" : ""));
+    return ();
+  }
 
-    if ( $#urls == 0 ) {
-       if ( $verbose > 2 ) {
-           print STDERR blurb() . "no images on $base\n";
-       }
-       return ();
-    }
+  @urls = depoison (@urls);
 
-    return () if ( $#urls < 1 );
+  # pick a random element of the table
+  my $i = int(rand($#urls+1));
+  $url = $urls[$i];
 
-    # pick a random element of the table
-    my $i = ((rand() * 99999) % $#urls);
-    $url = $urls[$i];
+  LOG ($verbose_load, "picked image " .($i+1) . "/" . ($#urls+1) . ": $url");
 
-    if ( $verbose > 2 ) {
-       print STDERR blurb() . "picked $url\n";
-    }
-
-    return $url;
+  return $url;
 }
 
 
-# Using the URL-randomizer, picks a random image on a random page, and
-# returns two URLs: the page containing the image, and the image.
-# Returns () if nothing found this time.
+\f
+############################################################################
 #
-sub pick_from_url_randomizer {
-    my ( $timeout ) = @_;
-
-    if ( $verbose > 3 ) {
-       print STDERR "\n\n$progname: picking from $random_redirector...\n\n";
-    }
-
-    my ( $base, $body ) = get_document ($random_redirector, undef, $timeout);
-
-    if (!$base || !$body) {
-        $body = undef;
-        return;
-    }
-    my $img = pick_image_from_body ($base, $body);
-    $body = undef;
-
-    if ($img) {
-        return ($base, $img, "yahoo");
-    } else {
-        return ();
-    }
-}
+# Subroutines for getting pages and images out of search engines
+#
+############################################################################
 
 
+# returns a random word from the dictionary
+#
 sub random_word {
     
     my $word = 0;
@@ -574,10 +652,10 @@ sub random_word {
             $word = <IN>;   # toss partial line
             $word = <IN>;   # keep next line
         }
-       if (!$word) {
+        if (!$word) {
           seek( IN, 0, 0 );
           $word = <IN>;
-       }
+        }
         close (IN);
     }
 
@@ -594,212 +672,469 @@ sub random_word {
     $word =~ tr/A-Z/a-z/;
 
     if ( $word =~ s/[ \t\n\r]/\+/g ) {  # convert intra-word spaces to "+".
-      $word = "\%22$word\%22";         # And put quotes (%22) around it.
+      $word = "\%22$word\%22";          # And put quotes (%22) around it.
     }
 
     return $word;
 }
 
+sub random_words {
+  return (random_word . "%20" .
+          random_word . "%20" .
+          random_word . "%20" .
+          random_word . "%20" .
+          random_word);
+}
 
 
-# Using the image-randomizer, picks a random image on a random page, and
-# returns two URLs: the page containing the image, and the image.
-# Returns () if nothing found this time.
+# Loads the given URL (a search on some search engine) and returns:
+# - the total number of hits the search engine claimed it had;
+# - a list of URLs from the page that the search engine returned;
+# Note that this list contains all kinds of internal search engine
+# junk URLs too -- caller must prune them.
 #
-sub pick_from_image_randomizer {
-    my ( $timeout, $which ) = @_;
-
-    my $words = random_word;
-    $words .= "%20" . random_word;
-    $words .= "%20" . random_word;
-    $words .= "%20" . random_word;
-    $words .= "%20" . random_word;
-
-    my $search_url = ($which == 0 ? $image_randomizer_1 :
-                      $which == 1 ? $image_randomizer_2 :
-                      $which == 2 ? $image_randomizer_3 :
-                      $image_randomizer_4) .
-        $words;
-
-    # Pick a random search-result page instead of always taking the first.
-    # This assumes there are at least 10 pages...
-    if ($which == 0) {
-        $search_url .= "&pgno=" . (int(rand(9)) + 1);
-    } elsif ($which == 2) {
-        $search_url .= "&stq=" . (10 * (int(rand(9)) + 1));
-    }
+sub pick_from_search_engine {
+  my ( $timeout, $search_url, $words ) = @_;
 
-    if ( $verbose > 3 ) {
-        $_ = $words; s/%20/ /g; print STDERR blurb() . "search words: $_\n";
-    }
+  $_ = $words;
+  s/%20/ /g;
 
-    if ( $verbose > 3 ) {
-       print STDERR "\n\n$progname: picking from $search_url\n";
-    }
+  print STDERR "\n\n" if ($verbose_load);
 
-    my $start = time;
-    my ( $base, $body ) = get_document ($search_url, undef, $timeout);
-    if (defined ($timeout)) {
-        $timeout -= (time - $start);
-        if ($timeout <= 0) {
-            $body = undef;
-            return ();
-        }
+  LOG ($verbose_load, "words: $_");
+  LOG ($verbose_load, "URL: $search_url");
+
+  $last_search = $search_url;   # for warnings
+
+  my $start = time;
+  my ( $base, $body ) = get_document ($search_url, undef, $timeout);
+  if (defined ($timeout)) {
+    $timeout -= (time - $start);
+    if ($timeout <= 0) {
+      $body = undef;
+      LOG (($verbose_net || $verbose_load),
+           "timed out (late) for $search_url");
+      $suppress_audit = 1;
+      return ();
     }
+  }
 
-    return () if (! $body);
+  return () if (! $body);
 
 
-    my @subpages;
-    my $skipped = 0;
+  my @subpages;
 
-    my $search_count = "?";
-    if ($which == 0 &&
-        $body =~ m@found (approximately |about )?(<B>)?(\d+)(</B>)? image@) {
-        $search_count = $3;
-    } elsif ($which == 1 && $body =~ m@<NOBR>((\d{1,3})(,\d{3})*)&nbsp;@i) {
-        $search_count = $1;
-    } elsif ($which == 2 && $body =~ m@found ((\d{1,3})(,\d{3})*|\d+) Web p@) {
-        $search_count = $1;
-    }
-    1 while ($search_count =~ s/^(\d+)(\d{3})/$1,$2/);
+  my $search_count = "?";
+  if ($body =~ m@found (approximately |about )?(<B>)?(\d+)(</B>)? image@) {
+    $search_count = $3;
+  } elsif ($body =~ m@<NOBR>((\d{1,3})(,\d{3})*)&nbsp;@i) {
+    $search_count = $1;
+  } elsif ($body =~ m@found ((\d{1,3})(,\d{3})*|\d+) Web p@) {
+    $search_count = $1;
+  } elsif ($body =~ m@found about ((\d{1,3})(,\d{3})*|\d+) results@) {
+    $search_count = $1;
+  } elsif ($body =~ m@\b\d+ - \d+ of (\d+)\b@i) { # imagevista
+    $search_count = $1;
+  } elsif ($body =~ m@About ((\d{1,3})(,\d{3})*) images@i) { # imagevista
+    $search_count = $1;
+  } elsif ($body =~ m@WEB.*?RESULTS.*?\b((\d{1,3})(,\d{3})*)\b.*?Matches@i) {
+    $search_count = $1;                          # hotbot
+  } elsif ($body =~ m@no photos were found containing@i) { # imagevista
+    $search_count = "0";
+  } elsif ($body =~ m@found no document matching@i) { # altavista
+    $search_count = "0";
+  }
+  1 while ($search_count =~ s/^(\d+)(\d{3})/$1,$2/);
 
-    my $length = length($body);
-    my $href_count = 0;
+#  if ($search_count eq "?" || $search_count eq "0") {
+#    local *OUT;
+#    my $file = "/tmp/wc.html";
+#    open(OUT, ">$file") || error ("writing $file: $!");
+#    print OUT $body;
+#    close OUT;
+#    print STDERR  blurb() . "###### wrote $file\n";
+#  }
 
-    $_ = $body;
 
-#    s/Result [Pp]ages:.*$//s;            # trim off page footer
-#    s/^.*?IMAGE RESULTS//s;              # trim off page header
+  my $length = length($body);
+  my $href_count = 0;
 
-    s/Have you tried these resources.*//s;  # let's try it again
+  $_ = $body;
 
-    s/[\r\n\t ]+/ /g;
+  s/[\r\n\t ]+/ /g;
 
-    s/(<A )/\n$1/gi;
-    foreach (split(/\n/)) {
-        $href_count++;
-        my ($u) = m@<A\s.*\bHREF\s*=\s*([^>]+)>@i;
-        next unless $u;
-        if ($u =~ m/^\"([^\"]*)\"/) { $u = $1; }   # quoted string
-        elsif ($u =~ m/^([^\s]*)\s/) { $u = $1; }  # or token
 
-        if ($which == 1) {
-            # Kludge to decode HotBot pages
-            next unless ($u =~ m@/director\.asp\?target=(http%3A[^&>]+)@);
-            $u = url_decode($1);
-        }
+  s/(<A )/\n$1/gi;
+  foreach (split(/\n/)) {
+    $href_count++;
+    my ($u) = m@<A\s.*\bHREF\s*=\s*([^>]+)>@i;
+    next unless $u;
 
-        next unless ($u =~ m@^http://@i);  # skip non-http and relative urls.
-
-        next if ($u =~ m@[/.]altavista\.com\b@i);     # skip altavista builtins
-        next if ($u =~ m@[/.]altavista\.[a-z]{2}\b@i); # altavista.fr, etc
-        next if ($u =~ m@[/.]av\.com\b@i);
-        next if ($u =~ m@[/.]virage\.com\b@i);
-        next if ($u =~ m@[/.]photoloft\.com\b@i);
-        next if ($u =~ m@[/.]shopping\.com\b@i);
-        next if ($u =~ m@[/.]thetrip\.com\b@i);
-        next if ($u =~ m@[/.]cmgi\.com\b@i);
-        next if ($u =~ m@[/.]intelihealth\.com\b@i);
-        next if ($u =~ m@[/.]wildweb\.com\b@i);
-        next if ($u =~ m@[/.]digital\.com\b@i);
-        next if ($u =~ m@[/.]doubleclick\.net\b@i);
-        next if ($u =~ m@[/.]freeim\.org\b@i);
-        next if ($u =~ m@[/.]clicktomarket\.com\b@i);  # you cretins
-        next if ($u =~ m@[/.]teragram\.com\b@i);
-
-        # must lose this one for altavista, even though it loses images of
-        # every single customer of akamai.  Oh well, those people have lots
-        # of money, and so their images are probably boring anyway.
-        next if ($u =~ m@[/.]akamai\.net@i);
-
-        if ($which == 0 && $u =~ m@[/.]corbis\.com@) {
-           $skipped = 1;
-            if ( $verbose > 3 ) {
-                print STDERR blurb() . "skipping corbis URL: $u\n";
-            }
-            next;
-
-        } elsif ($which == 3 &&
-                 ($u =~ m@^http://[^/]+$@ ||             # no slashes
-                  $u =~ m@/$@ ||                         # ends in /
-                  ! ($u =~ m@dailynews\.yahoo\.com@))) {  # not dailynews
-#            $skipped = 1;
-            if ( $verbose > 3 ) {
-                print STDERR blurb() . "skipping non-AP URL: $u\n";
-            }
-            next;
-
-        } elsif ( $rejected_urls{$u} ) {
-            if ( $verbose > 3 ) {
-                my $L = $rejected_urls{$u};
-                print STDERR blurb() . "pre-rejecting sub-page: $u\n";
-            }
-            next;
-
-        } elsif ( $verbose > 3 ) {
-            print STDERR blurb() . "sub-page: $u\n";
-        }
+    if ($u =~ m/^\"([^\"]*)\"/) { $u = $1; }   # quoted string
+    elsif ($u =~ m/^([^\s]*)\s/) { $u = $1; }  # or token
 
-        $subpages[++$#subpages] = $u;
+    if ( $rejected_urls{$u} ) {
+      LOG ($verbose_filter, "  pre-rejecting candidate: $u");
+      next;
     }
 
-    if ( $#subpages < 0 ) {
-        if (!$skipped && $verbose > 1) {
-            print STDERR blurb() . "found nothing on $base " .
-                "($length bytes, $href_count links).\n";
-        }
-        $body = undef;
-        $_ = undef;
-       return ();
-    }
+    LOG ($verbose_http, "    HREF: $u");
 
-    # pick a random element of the table
-    my $i = ((rand() * 99999) % ($#subpages + 1));
-    my $subpage = $subpages[$i];
+    $subpages[++$#subpages] = $u;
+  }
 
-    if ( $verbose > 3 ) {
-       print STDERR blurb() . "picked page $subpage\n";
-    }
+  if ( $#subpages < 0 ) {
+    LOG ($verbose_filter,
+         "found nothing on $base ($length bytes, $href_count links).");
+    return ();
+  }
 
+  LOG ($verbose_filter, "" . $#subpages+1 . " links on $search_url");
 
-    $body = undef;
-    $_ = undef;
+  return ($search_count, @subpages);
+}
 
-    my ( $base2, $body2 ) = get_document ($subpage, $base, $timeout);
 
-    if (!$base2 || !$body2) {
-        $body2 = undef;
-        return ();
+sub depoison {
+  my (@urls) = @_;
+  my @urls2 = ();
+  foreach (@urls) {
+    my ($h) = m@^http://([^/: \t\r\n]+)@i;
+
+    next unless defined($h);
+
+    if ($poisoners{$h}) {
+      LOG (($verbose_filter), "  rejecting poisoner: $_");
+      next;
+    }
+    if ($h =~ m@([^.]+\.[^.]+\.[^.]+)$@ &&
+        $poisoners{$1}) {
+      LOG (($verbose_filter), "  rejecting poisoner: $_");
+      next;
+    }
+    if ($h =~ m@([^.]+\.[^.]+)$@ &&
+        $poisoners{$1}) {
+      LOG (($verbose_filter), "  rejecting poisoner: $_");
+      next;
     }
 
-    my $img = pick_image_from_body ($base2, $body2);
+    push @urls2, $_;
+  }
+  return @urls2;
+}
+
+
+# given a list of URLs, picks one at random; loads it; and returns a
+# random image from it.
+# returns the url of the page loaded; the url of the image chosen;
+# and a debugging description string.
+#
+sub pick_image_from_pages {
+  my ($base, $total_hit_count, $unfiltered_link_count, $timeout, @pages) = @_;
+
+  $total_hit_count = "?" unless defined($total_hit_count);
+
+  @pages = depoison (@pages);
+  LOG ($verbose_load,
+       "" . ($#pages+1) . " candidates of $unfiltered_link_count links" .
+       " ($total_hit_count total)");
+
+  return () if ($#pages < 0);
+
+  my $i = int(rand($#pages+1));
+  my $page = $pages[$i];
+
+  LOG ($verbose_load, "picked page $page");
+
+  $suppress_audit = 1;
+
+  my ( $base2, $body2 ) = get_document ($page, $base, $timeout);
+
+  if (!$base2 || !$body2) {
     $body2 = undef;
+    return ();
+  }
 
-    if ($img) {
-        return ($base2, $img,
-                ($which == 0 ? "imagevista" :
-                 $which == 1 ? "hotbot" :
-                 $which == 2 ? "altavista" :
-                 "ap") .
-                "/$search_count");
-    } else {
-        return ();
-    }
+  my $img = pick_image_from_body ($base2, $body2);
+  $body2 = undef;
+
+  if ($img) {
+    return ($base2, $img);
+  } else {
+    return ();
+  }
 }
 
+\f
+############################################################################
+#
+# Pick images from random pages returned by the Yahoo Random Link
+#
+############################################################################
+
+# yahoorand
+my $yahoo_random_link = "http://random.yahoo.com/bin/ryl";
 
-# Using the photo site, generate a random URL that will hopefully point
-# to an image.  Returns two URLs, both of which are the URL of the image.
+
+# Picks a random page; picks a random image on that page;
+# returns two URLs: the page containing the image, and the image.
 # Returns () if nothing found this time.
 #
-#sub pick_from_photo_randomizer {
-#    my ( $timeout ) = @_;
-#    my $n = ($photo_randomizer_lo +
-#             int(rand() * ($photo_randomizer_hi - $photo_randomizer_lo)));
-#    my $url = $photo_randomizer . $n;
-#    return ( $url, $url, "photopoint" );
-#}
+sub pick_from_yahoo_random_link {
+  my ( $timeout ) = @_;
+
+  print STDERR "\n\n" if ($verbose_load);
+  LOG ($verbose_load, "URL: $yahoo_random_link");
+
+  $last_search = $yahoo_random_link;   # for warnings
+
+  $suppress_audit = 1;
+
+  my ( $base, $body ) = get_document ($yahoo_random_link, undef, $timeout);
+  if (!$base || !$body) {
+    $body = undef;
+    return;
+  }
+
+  LOG ($verbose_load, "redirected to: $base"); 
+
+  my $img = pick_image_from_body ($base, $body);
+  $body = undef;
+
+  if ($img) {
+    return ($base, $img);
+  } else {
+    return ();
+  }
+}
+
+\f
+############################################################################
+#
+# Pick images by feeding random words into Alta Vista Image Search
+#
+############################################################################
+
+
+my $alta_vista_images_url = "http://www.altavista.com/cgi-bin/query" .
+                            "?ipht=1" .       # photos
+                            "&igrph=1" .      # graphics
+                            "&iclr=1" .       # color
+                            "&ibw=1" .        # b&w
+                            "&micat=1" .      # no partner sites
+                            "&imgset=1" .     # no partner sites
+                            "&stype=simage" . # do image search
+                            "&mmW=1" .        # unknown, but required
+                            "&q=";
+
+
+# imagevista
+sub pick_from_alta_vista_images {
+  my ( $timeout ) = @_;
+
+  my $words = random_words;
+  my $page = (int(rand(9)) + 1);
+  my $search_url = $alta_vista_images_url . $words;
+
+  if ($page > 1) {
+    $search_url .= "&pgno=" . $page;           # page number
+    $search_url .= "&stq=" . (($page-1) * 12);  # first hit result on page
+  }
+
+  my ($search_hit_count, @subpages) =
+    pick_from_search_engine ($timeout, $search_url, $words);
+
+  my @candidates = ();
+  foreach my $u (@subpages) {
+    next unless ($u =~ m@^http://@i);    #  skip non-HTTP or relative URLs
+    next if ($u =~ m@[/.]altavista\.com\b@i);     # skip altavista builtins
+    next if ($u =~ m@[/.]doubleclick\.net\b@i);   # you cretins
+    next if ($u =~ m@[/.]clicktomarket\.com\b@i); # more cretins
+
+    next if ($u =~ m@[/.]viewimages\.com\b@i);    # stacked deck
+    next if ($u =~ m@[/.]gettyimages\.com\b@i);
+
+    LOG ($verbose_filter, "  candidate: $u");
+    push @candidates, $u;
+  }
+
+  return pick_image_from_pages ($search_url, $search_hit_count, $#subpages+1,
+                                $timeout, @candidates);
+}
+
+
+\f
+############################################################################
+#
+# Pick images by feeding random words into Alta Vista Text Search
+#
+############################################################################
+
+
+my $alta_vista_url = "http://www.altavista.com/cgi-bin/query?pg=q" .
+                     "&text=yes&kl=XX&stype=stext&q=";
+
+# altavista
+sub pick_from_alta_vista_text {
+  my ( $timeout ) = @_;
+
+  my $words = random_words;
+  my $page = (int(rand(9)) + 1);
+  my $search_url = $alta_vista_url . $words;
+
+  if ($page > 1) {
+    $search_url .= "&pgno=" . $page;
+    $search_url .= "&stq=" . (($page-1) * 10);
+  }
+
+  my ($search_hit_count, @subpages) =
+    pick_from_search_engine ($timeout, $search_url, $words);
+
+  my @candidates = ();
+  foreach my $u (@subpages) {
+
+    # Those altavista fuckers are playing really nasty redirection games
+    # these days: the filter your clicks through their site, but use
+    # onMouseOver to make it look like they're not!  Well, it makes it
+    # easier for us to identify search results...
+    #
+    next unless ($u =~ m@^/r\?ck_sm=[a-zA-Z0-9]+\&ref=[a-zA-Z0-9]+\&r=(.*)@);
+    $u = $1;
+
+    LOG ($verbose_filter, "  candidate: $u");
+    push @candidates, $u;
+  }
+
+  return pick_image_from_pages ($search_url, $search_hit_count, $#subpages+1,
+                                $timeout, @candidates);
+}
+
+
+\f
+############################################################################
+#
+# Pick images by feeding random words into Hotbot
+#
+############################################################################
+
+my $hotbot_search_url = "http://hotbot.lycos.com/" .
+                        "?SM=SC" .
+                        "&DV=0" .
+                        "&LG=any" .
+                        "&FVI=1" .
+                        "&DC=100" .
+                        "&DE=0" .
+                        "&SQ=1" .
+                        "&TR=13" .
+                        "&AM1=MC" .
+                        "&MT=";
+
+sub pick_from_hotbot_text {
+  my ( $timeout ) = @_;
+
+  my $words = random_words;
+  my $search_url = $hotbot_search_url . $words;
+
+  my ($search_hit_count, @subpages) =
+    pick_from_search_engine ($timeout, $search_url, $words);
+
+  my @candidates = ();
+  foreach my $u (@subpages) {
+
+    # Hotbot plays redirection games too
+    next unless ($u =~ m@^/director.asp\?target=([^&]+)@);
+    $u = url_decode($1);
+
+    LOG ($verbose_filter, "  candidate: $u");
+    push @candidates, $u;
+  }
+
+  return pick_image_from_pages ($search_url, $search_hit_count, $#subpages+1,
+                                $timeout, @candidates);
+}
+
+
+\f
+############################################################################
+#
+# Pick images by feeding random words into Lycos
+#
+############################################################################
+
+my $lycos_search_url = "http://lycospro.lycos.com/srchpro/" .
+                       "?lpv=1" .
+                       "&t=any" .
+                       "&query=";
+
+sub pick_from_lycos_text {
+  my ( $timeout ) = @_;
+
+  my $words = random_words;
+  my $start = int(rand(8)) * 10 + 1;
+  my $search_url = $lycos_search_url . $words . "&start=$start";
+
+  my ($search_hit_count, @subpages) =
+    pick_from_search_engine ($timeout, $search_url, $words);
+
+  my @candidates = ();
+  foreach my $u (@subpages) {
+
+    # Lycos plays exact the same redirection game as hotbot.
+    # Note that "id=0" is used for internal advertising links,
+    # and 1+ are used for  search results.
+    next unless ($u =~ m@^http://click.hotbot.com/director.asp\?id=[1-9]\d*&target=([^&]+)@);
+    $u = url_decode($1);
+
+    LOG ($verbose_filter, "  candidate: $u");
+    push @candidates, $u;
+  }
+
+  return pick_image_from_pages ($search_url, $search_hit_count, $#subpages+1,
+                                $timeout, @candidates);
+}
+
+
+\f
+############################################################################
+#
+# Pick images by feeding random words into news.yahoo.com
+#
+############################################################################
+
+my $yahoo_news_url = "http://search.news.yahoo.com/search/news_photos?" .
+                     "&z=&n=100&o=o&2=&3=&p=";
+
+# yahoonews
+sub pick_from_yahoo_news_text {
+  my ( $timeout ) = @_;
+
+  my $words = random_words;
+  my $search_url = $yahoo_news_url . $words;
+
+  my ($search_hit_count, @subpages) =
+    pick_from_search_engine ($timeout, $search_url, $words);
+
+  my @candidates = ();
+  foreach my $u (@subpages) {
+    # only accept URLs on Yahoo's news site
+    next unless ($u =~ m@^http://dailynews.yahoo.com/@i);
+
+    LOG ($verbose_filter, "  candidate: $u");
+    push @candidates, $u;
+  }
+
+  return pick_image_from_pages ($search_url, $search_hit_count, $#subpages+1,
+                                $timeout, @candidates);
+}
+
+
+
+\f
+############################################################################
+#
+# Pick a random image in a random way
+#
+############################################################################
 
 
 # Picks a random image on a random page, and returns two URLs:
@@ -807,165 +1142,374 @@ sub pick_from_image_randomizer {
 # Returns () if nothing found this time.
 # Uses the url-randomizer 1 time in 5, else the image randomizer.
 #
-my $total_0 = 0;
-my $total_1 = 0;
-my $total_2 = 0;
-my $total_3 = 0;
-my $total_4 = 0;
-my $count_0 = 0;
-my $count_1 = 0;
-my $count_2 = 0;
-my $count_3 = 0;
-my $count_4 = 0;
 
 sub pick_image {
-    my ( $timeout ) = @_;
-    my $r = int(rand(100));
-
-    my ($base, $img, $source, $total, $count);
-
-    if ($r < 20) {
-        ($base, $img, $source) = pick_from_url_randomizer ($timeout);
-        $total = ++$total_0;
-        $count = ++$count_0 if $img;
-
-    } elsif ($r < 60) {
-        ($base, $img, $source) = pick_from_image_randomizer ($timeout, 0);
-        $total = ++$total_1;
-        $count = ++$count_1 if $img;
-
-     } elsif ($r < 65) {
-         ($base, $img, $source) = pick_from_image_randomizer ($timeout, 3);
-         $total = ++$total_4;
-         $count = ++$count_4 if $img;
-
-#    } elsif ($r < 70) {
-#        ($base, $img, $source) = pick_from_photo_randomizer ($timeout);
-#        $total = ++$total_4;
-#        $count = ++$count_4 if $img;
-
-#    } elsif ($r < 80) {
-#        # HotBot sucks: 98% of the time, it says "no pages match your
-#        # search", and then if I load the URL again by hand, it works.
-#        # I don't understand what's going wrong here, but we're not getting
-#        # any good data back from them, so forget it for now.
+  my ( $timeout ) = @_;
+
+  $current_state = "select";
+  $load_method = "none";
+
+  my $n = int(rand(100));
+  my $fn = undef;
+  my $total = 0;
+  my @rest = @search_methods;
+
+  while (@rest) {
+    my $pct  = shift @rest;
+    my $name = shift @rest;
+    my $tfn  = shift @rest;
+    $total += $pct;
+    if ($total > $n && !defined($fn)) {
+      $fn = $tfn;
+      $current_state = $name;
+      $load_method = $current_state;
+    }
+  }
+
+  if ($total != 100) {
+    error ("internal error: \@search_methods totals to $total%!");
+  }
+
+  record_attempt ($current_state);
+  return $fn->($timeout);
+}
+
+
+\f
+############################################################################
+#
+# Statistics and logging
 #
-#        ($base, $img, $source) = pick_from_image_randomizer ($timeout, 1);
-#        $total = ++$total_2;
-#        $count = ++$count_2 if $img;
+############################################################################
 
-    } else {
-        ($base, $img, $source) = pick_from_image_randomizer ($timeout, 2);
-        $total = ++$total_3;
-        $count = ++$count_3 if $img;
-    }
+sub timestr {
+  return strftime ("%H:%M:%S: ", localtime);
+}
+
+sub blurb {
+  return "$progname: " . timestr() . "$current_state: ";
+}
 
-    if ($source && $total > 0) {
-        $source .= " " . int(($count / $total) * 100) . "%";
+sub error {
+  ($_) = @_;
+  print STDERR blurb() . "$_\n";
+  exit 1;
+}
+
+
+my $lastlog = "";
+
+sub clearlog {
+  $lastlog = "";
+}
+
+sub showlog {
+  my $head = "$progname: DEBUG: ";
+  foreach (split (/\n/, $lastlog)) {
+    print STDERR "$head$_\n";
+  }
+  $lastlog = "";
+}
+
+sub LOG {
+  my ($print, $msg) = @_;
+  my $blurb = timestr() . "$current_state: ";
+  $lastlog .= "$blurb$msg\n";
+  print STDERR "$progname: $blurb$msg\n" if $print;
+}
+
+
+my %stats_attempts;
+my %stats_successes;
+my %stats_elapsed;
+
+my $last_state = undef;
+sub record_attempt {
+  my ($name) = @_;
+
+  if ($last_state) {
+    record_failure($last_state) unless ($image_succeeded > 0);
+  }
+  $last_state = $name;
+
+  clearlog();
+  report_performance();
+
+  start_timer($name);
+  $image_succeeded = 0;
+  $suppress_audit = 0;
+}
+
+sub record_success {
+  my ($name, $url, $base) = @_;
+  if (defined($stats_successes{$name})) {
+    $stats_successes{$name}++;
+  } else {
+    $stats_successes{$name} = 1;
+  }
+
+  stop_timer ($name, 1);
+  my $o = $current_state;
+  $current_state = $name;
+  save_recent_url ($url, $base);
+  $current_state = $o;
+  $image_succeeded = 1;
+  clearlog();
+}
+
+
+sub record_failure {
+  my ($name) = @_;
+
+  return if $image_succeeded;
+
+  stop_timer ($name, 0);
+  if ($verbose_load && !$verbose_exec) {
+
+    if ($suppress_audit) {
+      print STDERR "$progname: " . timestr() . "(audit log suppressed)\n";
+      return;
     }
-    return ($base, $img, $source);
+
+    my $o = $current_state;
+    $current_state = "DEBUG";
+
+    my $line =  "#" x 78;
+    print STDERR "\n\n\n";
+    print STDERR ("#" x 78) . "\n";
+    print STDERR blurb() . "failed to get an image.  Full audit log:\n";
+    print STDERR "\n";
+    showlog();
+    print STDERR ("-" x 78) . "\n";
+    print STDERR "\n\n";
+
+    $current_state = $o;
+  }
+  $image_succeeded = 0;
 }
 
 
+
+sub stats_of {
+  my ($name) = @_;
+  my $i = $stats_successes{$name};
+  my $j = $stats_attempts{$name};
+  $i = 0 unless $i;
+  $j = 0 unless $j;
+  return "" . ($j ? int($i * 100 / $j) : "0") . "%";
+}
+
+
+my $current_start_time = 0;
+
+sub start_timer {
+  my ($name) = @_;
+  $current_start_time = time;
+
+  if (defined($stats_attempts{$name})) {
+    $stats_attempts{$name}++;
+  } else {
+    $stats_attempts{$name} = 1;
+  }
+  if (!defined($stats_elapsed{$name})) {
+    $stats_elapsed{$name} = 0;
+  }
+}
+
+sub stop_timer {
+  my ($name, $success) = @_;
+  $stats_elapsed{$name} += time - $current_start_time;
+}
+
+
+my $last_report_time = 0;
+sub report_performance {
+
+  return unless $verbose_warnings;
+
+  my $now = time;
+  return unless ($now >= $last_report_time + $report_performance_interval);
+  my $ot = $last_report_time;
+  $last_report_time = $now;
+
+  return if ($ot == 0);
+
+  my $blurb = "$progname: " . timestr();
+
+  print STDERR "\n";
+  print STDERR "${blurb}Current standings:\n";
+
+  foreach my $name (sort keys (%stats_attempts)) {
+    my $try = $stats_attempts{$name};
+    my $suc = $stats_successes{$name} || 0;
+    my $pct = int($suc * 100 / $try);
+    my $secs = $stats_elapsed{$name};
+    my $secs_link = int($secs / $try);
+    print STDERR sprintf ("$blurb   %-12s %4s (%d/%d);\t %2d secs/link\n",
+                          "$name:", "$pct%", $suc, $try, $secs_link);
+  }
+}
+
+
+
+my $max_recent_images = 400;
+my $max_recent_sites  = 20;
+my @recent_images = ();
+my @recent_sites = ();
+
+sub save_recent_url {
+  my ($url, $base) = @_;
+
+  return unless ($verbose_warnings);
+
+  $_ = $url;
+  my ($site) = m@^http://([^ \t\n\r/:]+)@;
+
+  my $done = 0;
+  foreach (@recent_images) {
+    if ($_ eq $url) {
+      print STDERR blurb() . "WARNING: recently-duplicated image: $url" .
+        " (on $base via $last_search)\n";
+      $done = 1;
+      last;
+    }
+  }
+
+  # suppress "duplicate site" warning via %warningless_sites.
+  #
+  if ($warningless_sites{$site}) {
+    $done = 1;
+  } elsif ($site =~ m@([^.]+\.[^.]+\.[^.]+)$@ &&
+           $warningless_sites{$1}) {
+    $done = 1;
+  } elsif ($site =~ m@([^.]+\.[^.]+)$@ &&
+           $warningless_sites{$1}) {
+    $done = 1;
+  }
+
+  if (!$done) {
+    foreach (@recent_sites) {
+      if ($_ eq $site) {
+        print STDERR blurb() . "WARNING: recently-duplicated site: $site" .
+        " ($url on $base via $last_search)\n";
+        last;
+      }
+    }
+  }
+
+  push @recent_images, $url;
+  push @recent_sites,  $site;
+  shift @recent_images if ($#recent_images >= $max_recent_images);
+  shift @recent_sites  if ($#recent_sites  >= $max_recent_sites);
+}
+
+
+\f
+##############################################################################
+#
+# other utilities
+#
+##############################################################################
+
 # Does %-decoding.
 #
 sub url_decode {
-    ($_) = @_;
-    tr/+/ /;
-    s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
-    return $_;
+  ($_) = @_;
+  tr/+/ /;
+  s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
+  return $_;
 }
 
 
 # Given the raw body of a GIF document, returns the dimensions of the image.
 #
 sub gif_size {
-    my ($body) = @_;
-    my $type = substr($body, 0, 6);
-    my $s;
-    return () unless ($type =~ /GIF8[7,9]a/);
-    $s = substr ($body, 6, 10);
-    my ($a,$b,$c,$d) = unpack ("C"x4, $s);
-    return (($b<<8|$a), ($d<<8|$c));
+  my ($body) = @_;
+  my $type = substr($body, 0, 6);
+  my $s;
+  return () unless ($type =~ /GIF8[7,9]a/);
+  $s = substr ($body, 6, 10);
+  my ($a,$b,$c,$d) = unpack ("C"x4, $s);
+  return (($b<<8|$a), ($d<<8|$c));
 }
 
 # Given the raw body of a JPEG document, returns the dimensions of the image.
 #
 sub jpeg_size {
-    my ($body) = @_;
-    my $i = 0;
-    my $L = length($body);
-    
-    my $c1 = substr($body, $i, 1); $i++;
-    my $c2 = substr($body, $i, 1); $i++;
-    return () unless (ord($c1) == 0xFF && ord($c2) == 0xD8);
-
-    my $ch = "0";
-    while (ord($ch) != 0xDA && $i < $L) {
-        # Find next marker, beginning with 0xFF.
-        while (ord($ch) != 0xFF) {
-            $ch = substr($body, $i, 1); $i++;
-        }
-        # markers can be padded with any number of 0xFF.
-        while (ord($ch) == 0xFF) {
-            $ch = substr($body, $i, 1); $i++;
-        }
-
-        # $ch contains the value of the marker.
-        my $marker = ord($ch);
+  my ($body) = @_;
+  my $i = 0;
+  my $L = length($body);
 
-        if (($marker >= 0xC0) &&
-            ($marker <= 0xCF) &&
-            ($marker != 0xC4) &&
-            ($marker != 0xCC)) {  # it's a SOFn marker
-            $i += 3;
-            my $s = substr($body, $i, 4); $i += 4;
-            my ($a,$b,$c,$d) = unpack("C"x4, $s);
-            return (($c<<8|$d), ($a<<8|$b));
+  my $c1 = substr($body, $i, 1); $i++;
+  my $c2 = substr($body, $i, 1); $i++;
+  return () unless (ord($c1) == 0xFF && ord($c2) == 0xD8);
 
-        } else {
-            # We must skip variables, since FFs in variable names aren't
-            # valid JPEG markers.
-            my $s = substr($body, $i, 2); $i += 2;
-            my ($c1, $c2) = unpack ("C"x2, $s); 
-            my $length = ($c1 << 8) | $c2;
-            return () if ($length < 2);
-            $i += $length-2;
-        }
+  my $ch = "0";
+  while (ord($ch) != 0xDA && $i < $L) {
+    # Find next marker, beginning with 0xFF.
+    while (ord($ch) != 0xFF) {
+      $ch = substr($body, $i, 1); $i++;
     }
-    return ();
+    # markers can be padded with any number of 0xFF.
+    while (ord($ch) == 0xFF) {
+      $ch = substr($body, $i, 1); $i++;
+    }
+
+    # $ch contains the value of the marker.
+    my $marker = ord($ch);
+
+    if (($marker >= 0xC0) &&
+        ($marker <= 0xCF) &&
+        ($marker != 0xC4) &&
+        ($marker != 0xCC)) {  # it's a SOFn marker
+      $i += 3;
+      my $s = substr($body, $i, 4); $i += 4;
+      my ($a,$b,$c,$d) = unpack("C"x4, $s);
+      return (($c<<8|$d), ($a<<8|$b));
+
+    } else {
+      # We must skip variables, since FFs in variable names aren't
+      # valid JPEG markers.
+      my $s = substr($body, $i, 2); $i += 2;
+      my ($c1, $c2) = unpack ("C"x2, $s); 
+      my $length = ($c1 << 8) | $c2;
+      return () if ($length < 2);
+      $i += $length-2;
+    }
+  }
+  return ();
 }
 
 # Given the raw body of a GIF or JPEG document, returns the dimensions of
 # the image.
 #
 sub image_size {
-    my ($body) = @_;
-    my ($w, $h) = gif_size ($body);
-    if ($w && $h) { return ($w, $h); }
-    return jpeg_size ($body);
+  my ($body) = @_;
+  my ($w, $h) = gif_size ($body);
+  if ($w && $h) { return ($w, $h); }
+  return jpeg_size ($body);
 }
 
 
 # returns the full path of the named program, or undef.
 #
 sub which {
-    my ($prog) = @_;
-    foreach (split (/:/, $ENV{PATH})) {
-        if (-x "$_/$prog") {
-            return $prog;
-        }
+  my ($prog) = @_;
+  foreach (split (/:/, $ENV{PATH})) {
+    if (-x "$_/$prog") {
+      return $prog;
     }
-    return undef;
+  }
+  return undef;
 }
 
 
 # Like rand(), but chooses numbers with a bell curve distribution.
 sub bellrand {
-    ($_) = @_;
-    $_ = 1.0 unless defined($_);
-    $_ /= 3.0;
-    return (rand($_) + rand($_) + rand($_));
+  ($_) = @_;
+  $_ = 1.0 unless defined($_);
+  $_ /= 3.0;
+  return (rand($_) + rand($_) + rand($_));
 }
 
 
@@ -976,14 +1520,14 @@ sub bellrand {
 ##############################################################################
 
 sub url_only_output {
-    do {
-        my ($base, $img) = pick_image;
-        if ($img) {
-            $base =~ s/ /%20/g;
-            $img  =~ s/ /%20/g;
-            print "$img $base\n";
-        }
-    } while (1);
+  do {
+    my ($base, $img) = pick_image;
+    if ($img) {
+      $base =~ s/ /%20/g;
+      $img  =~ s/ /%20/g;
+      print "$img $base\n";
+    }
+  } while (1);
 }
 
 ##############################################################################
@@ -992,11 +1536,25 @@ sub url_only_output {
 #
 ##############################################################################
 
+my $image_ppm   = ($ENV{TMPDIR} ? $ENV{TMPDIR} : "/tmp") . "/webcollage." . $$;
+my $image_tmp1  = $image_ppm . "-1";
+my $image_tmp2  = $image_ppm . "-2";
+
+my $filter_cmd = undef;
+my $post_filter_cmd = undef;
+my $background = undef;
+
+my $img_width;            # size of the image being generated.
+my $img_height;
+
+my $delay = 0;
+
+
 sub x_cleanup {
-    my ($sig) = @_;
-    if ($verbose > 0) { print STDERR blurb() . "caught signal $sig.\n"; }
-    unlink $image_ppm, $image_tmp1, $image_tmp2;
-    exit 1;
+  my ($sig) = @_;
+  print STDERR blurb() . "caught signal $sig.\n" if ($verbose_exec);
+  unlink $image_ppm, $image_tmp1, $image_tmp2;
+  exit 1;
 }
 
 
@@ -1004,40 +1562,31 @@ sub x_cleanup {
 # with whatever signal killed the sub-process, if any.
 #
 sub nontrapping_system {
-    $! = 0;
+  $! = 0;
     
-    if ($verbose > 1) {
-        $_ = join(" ", @_);
-        s/\"[^\"]+\"/\"...\"/g;
-        print STDERR blurb() . "executing \"$_\"\n";
-    }
+  $_ = join(" ", @_);
+  s/\"[^\"]+\"/\"...\"/g;
 
-    my $rc = system @_;
+  LOG ($verbose_exec, "executing \"$_\"");
 
-    if ($rc == 0) {
-        if ($verbose > 1) {
-            print STDERR blurb() . "subproc exited normally.\n";
-        }
-    } elsif (($rc & 0xff) == 0) {
-        $rc >>= 8;
-        if ($verbose) {
-            print blurb() . "subproc exited with status $rc.\n";
-        }
-    } else {
-        if ($rc & 0x80) {
-            if ($verbose) {
-                print blurb() . "subproc dumped core.\n";
-            }
-            $rc &= ~0x80;
-        }
-        if ($verbose) {
-            print blurb() . "subproc died with signal $rc.\n";
-        }
-        # die that way ourselves.
-        kill $rc, $$;
+  my $rc = system @_;
+
+  if ($rc == 0) {
+    LOG ($verbose_exec, "subproc exited normally.");
+  } elsif (($rc & 0xff) == 0) {
+    $rc >>= 8;
+    LOG ($verbose_exec, "subproc exited with status $rc.");
+  } else {
+    if ($rc & 0x80) {
+      LOG ($verbose_exec, "subproc dumped core.");
+      $rc &= ~0x80;
     }
+    LOG ($verbose_exec, "subproc died with signal $rc.");
+    # die that way ourselves.
+    kill $rc, $$;
+  }
 
-    return $rc;
+  return $rc;
 }
 
 
@@ -1046,552 +1595,617 @@ sub nontrapping_system {
 # successful.
 #
 sub image_to_pnm {
-    my ($url, $body, $output) = @_;
-    my ($cmd, $cmd2, $w, $h);
-
-    if ((@_ = gif_size ($body))) {
-        ($w, $h) = @_;
-        $cmd = "giftopnm";
-    } elsif ((@_ = jpeg_size ($body))) {
-        ($w, $h) = @_;
-        $cmd = "djpeg";
-    } else {
-        return ();
-    }
-
-    $cmd2 = "exec $cmd";        # yes, this really is necessary.  if we don't
-                                # do this, the process doesn't die properly.
-    if ($verbose <= 1) {
-        #
-        # We get a "giftopnm: got a 'Application Extension' extension"
-        # warning any time it's an animgif.
-        #
-        # Note that "giftopnm: EOF / read error on image data" is not
-        # always a fatal error -- sometimes the image looks fine anyway.
-        #
-        $cmd2 .= " 2>/dev/null";
-    }
+  my ($url, $body, $output) = @_;
+  my ($cmd, $cmd2, $w, $h);
+
+  if ((@_ = gif_size ($body))) {
+    ($w, $h) = @_;
+    $cmd = "giftopnm";
+  } elsif ((@_ = jpeg_size ($body))) {
+    ($w, $h) = @_;
+    $cmd = "djpeg";
+  } else {
+    LOG (($verbose_pbm || $verbose_load),
+         "not a GIF or JPG" .
+         (($body =~ m@<(base|html|head|body|script|table|a href)>@i)
+          ? " (looks like HTML)" : "") .
+         ": $url");
+    $suppress_audit = 1;
+    return ();
+  }
 
-    # There exist corrupted GIF and JPEG files that can make giftopnm and
-    # djpeg lose their minds and go into a loop.  So this gives those programs
-    # a small timeout -- if they don't complete in time, kill them.
+  $cmd2 = "exec $cmd";        # yes, this really is necessary.  if we don't
+                              # do this, the process doesn't die properly.
+  if (!$verbose_pbm) {
     #
-    my $pid;
-    @_ = eval {
-        my $timed_out;
-
-        local $SIG{ALRM}  = sub {
-            if ($verbose > 0) {
-                print STDERR blurb() . "timed out ($cvt_timeout) for " .
-                    "$cmd on \"$url\" in pid $pid\n";
-            }
-            kill ('TERM', $pid) if ($pid);
-            $timed_out = 1;
-            $body = undef;
-        };
-
-        if (($pid = open(PIPE, "| $cmd2 > $output"))) {
-            $timed_out = 0;
-            alarm $cvt_timeout;
-            print PIPE $body;
-            $body = undef;
-            close PIPE;
-
-            if ($verbose > 3) { print STDERR blurb() . "awaiting $pid\n"; }
-            waitpid ($pid, 0);
-            if ($verbose > 3) { print STDERR blurb() . "$pid completed\n"; }
-
-
-            my $size = (stat($output))[7];
-            if ($size < 5) {
-                if ($verbose) {
-                    print STDERR blurb() . "$cmd on ${w}x$h \"$url\" failed" .
-                        " ($size bytes)\n";
-                }
-                return ();
-            }
-
-            if ($verbose > 1) {
-                print STDERR blurb() . "created ${w}x$h $output ($cmd)\n";
-            }
-            return ($w, $h);
-        } else {
-            print STDERR blurb() . "$cmd failed: $!\n";
-            return ();
-        }
+    # We get a "giftopnm: got a 'Application Extension' extension"
+    # warning any time it's an animgif.
+    #
+    # Note that "giftopnm: EOF / read error on image data" is not
+    # always a fatal error -- sometimes the image looks fine anyway.
+    #
+    $cmd2 .= " 2>/dev/null";
+  }
+
+  # There exist corrupted GIF and JPEG files that can make giftopnm and
+  # djpeg lose their minds and go into a loop.  So this gives those programs
+  # a small timeout -- if they don't complete in time, kill them.
+  #
+  my $pid;
+  @_ = eval {
+    my $timed_out;
+
+    local $SIG{ALRM}  = sub {
+      LOG ($verbose_pbm,
+           "timed out ($cvt_timeout) for $cmd on \"$url\" in pid $pid");
+      kill ('TERM', $pid) if ($pid);
+      $timed_out = 1;
+      $body = undef;
     };
-    die if ($@ && $@ ne "alarm\n");       # propagate errors
-    if ($@) {
-        # timed out
-        $body = undef;
+
+    if (($pid = open(PIPE, "| $cmd2 > $output"))) {
+      $timed_out = 0;
+      alarm $cvt_timeout;
+      print PIPE $body;
+      $body = undef;
+      close PIPE;
+
+      LOG ($verbose_exec, "awaiting $pid");
+      waitpid ($pid, 0);
+      LOG ($verbose_exec, "$pid completed");
+
+      my $size = (stat($output))[7];
+      $size = -1 unless defined($size);
+      if ($size < 5) {
+        LOG ($verbose_pbm, "$cmd on ${w}x$h \"$url\" failed ($size bytes)");
         return ();
+      }
+
+      LOG ($verbose_pbm, "created ${w}x$h $output ($cmd)");
+      return ($w, $h);
     } else {
-        # didn't
-        alarm 0;
-        $body = undef;
-        return @_;
+      print STDERR blurb() . "$cmd failed: $!\n";
+      return ();
     }
+  };
+  die if ($@ && $@ ne "alarm\n");       # propagate errors
+  if ($@) {
+    # timed out
+    $body = undef;
+    return ();
+  } else {
+    # didn't
+    alarm 0;
+    $body = undef;
+    return @_;
+  }
 }
 
-sub x_output {
+sub pick_root_displayer {
+  my @names = ();
 
-    my $win_cmd_1 = $ppm_to_root_window_cmd_1;
-    my $win_cmd_2 = $ppm_to_root_window_cmd_2;
-    my $win_cmd_3 = $ppm_to_root_window_cmd_3;
-    $win_cmd_1 =~ s/^([^ \t\r\n]+).*$/$1/;
-    $win_cmd_2 =~ s/^([^ \t\r\n]+).*$/$1/;
-    $win_cmd_3 =~ s/^([^ \t\r\n]+).*$/$1/;
-
-    # make sure the various programs we execute exist, right up front.
-    foreach ("ppmmake", "giftopnm", "djpeg", "pnmpaste", "pnmscale",
-             "pnmcut") {
-        which ($_) || die blurb() . "$_ not found on \$PATH.\n";
+  foreach my $cmd (@root_displayers) {
+    $_ = $cmd;
+    my ($name) = m/^([^ ]+)/;
+    push @names, "\"$name\"";
+    LOG ($verbose_exec, "looking for $name...");
+    foreach my $dir (split (/:/, $ENV{PATH})) {
+      LOG ($verbose_exec, "  checking $dir/$name");
+      return $cmd if (-x "$dir/$name");
     }
+  }
 
-    if (which($win_cmd_1)) {
-        $ppm_to_root_window_cmd = $ppm_to_root_window_cmd_1;
-    } elsif (which($win_cmd_2)) {
-        $ppm_to_root_window_cmd = $ppm_to_root_window_cmd_2;
-    } elsif (which($win_cmd_3)) {
-        $ppm_to_root_window_cmd = $ppm_to_root_window_cmd_3;
-     } else {
-        die blurb() . "didn't find $win_cmd_1, $win_cmd_2, or $win_cmd_3 on \$PATH.\n";
-    }
+  $names[$#names] = "or " . $names[$#names];
+  error "none of: " . join (", ", @names) . " were found on \$PATH.";
+}
 
-    $SIG{HUP}  = \&x_cleanup;
-    $SIG{INT}  = \&x_cleanup;
-    $SIG{QUIT} = \&x_cleanup;
-    $SIG{ABRT} = \&x_cleanup;
-    $SIG{KILL} = \&x_cleanup;
-    $SIG{TERM} = \&x_cleanup;
-
-    # Need this so that if giftopnm dies, we don't die.
-    $SIG{PIPE} = 'IGNORE';
-
-    if (!$img_width || !$img_height) {
-        $_ = "xdpyinfo";
-        which ($_) || die blurb() . "$_ not found on \$PATH.\n";
-        $_ = `$_`;
-        ($img_width, $img_height) = m/dimensions: *(\d+)x(\d+) /;
-        if (!defined($img_height)) {
-            die blurb() . "xdpyinfo failed.\n";
-        }
-    }
 
-    my $bgcolor = "#000000";
-    my $bgimage = undef;
-
-    if ($background) {
-        if ($background =~ m/^\#[0-9a-f]+$/i) {
-            $bgcolor = $background;
-        } elsif (-r $background) {
-            $bgimage = $background;
-            
-        } elsif (! $background =~ m@^[-a-z0-9 ]+$@i) {
-            print STDERR blurb() . "not a color or readable file: " .
-                "$background\n";
-            exit 1;
-        } else {
-            # default to assuming it's a color
-            $bgcolor = $background;
-        }
-    }
+my $ppm_to_root_window_cmd = undef;
 
-    # Create the sold-colored base image.
-    #
-    $_ = "ppmmake '$bgcolor' $img_width $img_height";
-    if ($verbose > 1) {
-        print STDERR blurb() . "creating base image: $_\n";
-    }
-    nontrapping_system "$_ > $image_ppm";
 
-    # Paste the default background image in the middle of it.
-    #
-    if ($bgimage) {
-        my ($iw, $ih);
-
-        my $body = "";
-        local *IMG;
-        open(IMG, "<$bgimage") || die ("couldn't open $bgimage: $!\n");
-        my $cmd;
-        while (<IMG>) { $body .= $_; }
-        close (IMG);
-        if ((@_ = gif_size ($body))) {
-            ($iw, $ih) = @_;
-            $cmd = "giftopnm |";
-        } elsif ((@_ = jpeg_size ($body))) {
-            ($iw, $ih) = @_;
-            $cmd = "djpeg |";
-        } elsif ($body =~ m/^P\d\n(\d+) (\d+)\n/) {
-            $iw = $1;
-            $ih = $2;
-            $cmd = "";
-        } else {
-            die blurb() . "$bgimage is not a GIF, JPEG, or PPM.\n";
-        }
+sub x_or_pbm_output {
 
-        my $x = int (($img_width  - $iw) / 2);
-        my $y = int (($img_height - $ih) / 2);
-        if ($verbose > 1) {
-            print STDERR blurb() . "pasting $bgimage (${iw}x$ih) into base ".
-                "image at $x,$y\n";
-        }
+  # make sure the various programs we execute exist, right up front.
+  #
+  foreach ("ppmmake", "giftopnm", "djpeg", "pnmpaste", "pnmscale", "pnmcut") {
+    which ($_) || error "$_ not found on \$PATH.";
+  }
 
-        $cmd .= "pnmpaste - $x $y $image_ppm > $image_tmp1";
-        open (IMG, "| $cmd") || die ("running $cmd: $!\n");
-        print IMG $body;
-        $body = undef;
-        close (IMG);
-        if ($verbose > 1) {
-            print STDERR blurb() . "subproc exited normally.\n";
-        }
-        rename ($image_tmp1, $image_ppm) ||
-            die ("renaming $image_tmp1 to $image_ppm: $!\n");
-    }
+  # find a root-window displayer program.
+  #
+  $ppm_to_root_window_cmd = pick_root_displayer();
 
-    while (1) {
-        my ($base, $img, $source) = pick_image();
-        if ($img) {
-            my ($headers, $body) = get_document ($img, $base);
-            if ($body) {
-                handle_image ($base, $img, $body, $source);
-                $body = undef;
-            }
-        }
-        unlink $image_tmp1, $image_tmp2;
-        sleep $delay;
-    }
-}
 
-sub handle_image {
-    my ($base, $img, $body, $source) = @_;
+  $SIG{HUP}  = \&x_cleanup;
+  $SIG{INT}  = \&x_cleanup;
+  $SIG{QUIT} = \&x_cleanup;
+  $SIG{ABRT} = \&x_cleanup;
+  $SIG{KILL} = \&x_cleanup;
+  $SIG{TERM} = \&x_cleanup;
+
+  # Need this so that if giftopnm dies, we don't die.
+  $SIG{PIPE} = 'IGNORE';
 
-    if ($verbose > 1) {
-        print STDERR blurb() . "got $img (" . length($body) . ")\n";
+  if (!$img_width || !$img_height) {
+    $_ = "xdpyinfo";
+    which ($_) || error "$_ not found on \$PATH.";
+    $_ = `$_`;
+    ($img_width, $img_height) = m/dimensions: *(\d+)x(\d+) /;
+    if (!defined($img_height)) {
+      error "xdpyinfo failed.";
     }
+  }
 
-    my ($iw, $ih) = image_to_pnm ($img, $body, $image_tmp1);
-    $body = undef;
-    return 0 unless ($iw && $ih);
+  my $bgcolor = "#000000";
+  my $bgimage = undef;
 
-    my $ow = $iw;  # used only for error messages
-    my $oh = $ih;
+  if ($background) {
+    if ($background =~ m/^\#[0-9a-f]+$/i) {
+      $bgcolor = $background;
 
-    # don't just tack this onto the front of the pipeline -- we want it to
-    # be able to change the size of the input image.
-    #
-    if ($filter_cmd) {
-        if ($verbose > 1) {
-            print STDERR blurb() . "running $filter_cmd\n";
-        }
+    } elsif (-r $background) {
+      $bgimage = $background;
 
-        my $rc = nontrapping_system "($filter_cmd) < $image_tmp1 >$image_tmp2";
-        if ($rc != 0) {
-            if ($verbose) {
-                print STDERR blurb() . "failed command: \"$filter_cmd\"\n";
-                print STDERR blurb() . "failed url: \"$img\" (${ow}x$oh)\n";
-            }
-            return;
-        }
-        rename ($image_tmp2, $image_tmp1);
-
-        # re-get the width/height in case the filter resized it.
-        local *IMG;
-        open(IMG, "<$image_tmp1") || return 0;
-        $_ = <IMG>;
-        $_ = <IMG>;
-        ($iw, $ih) = m/^(\d+) (\d+)$/;
-        close (IMG);
-        return 0 unless ($iw && $ih);
+    } elsif (! $background =~ m@^[-a-z0-9 ]+$@i) {
+      error "not a color or readable file: $background";
+
+    } else {
+      # default to assuming it's a color
+      $bgcolor = $background;
     }
+  }
 
-    my $target_w = $img_width;
-    my $target_h = $img_height;
+  # Create the sold-colored base image.
+  #
+  $_ = "ppmmake '$bgcolor' $img_width $img_height";
+  LOG ($verbose_pbm, "creating base image: $_");
+  nontrapping_system "$_ > $image_ppm";
 
-    my $cmd = "";
+  # Paste the default background image in the middle of it.
+  #
+  if ($bgimage) {
+    my ($iw, $ih);
 
+    my $body = "";
+    local *IMG;
+    open(IMG, "<$bgimage") || error "couldn't open $bgimage: $!";
+    my $cmd;
+    while (<IMG>) { $body .= $_; }
+    close (IMG);
 
-    # Usually scale the image to fit on the screen -- but sometimes scale it
-    # to fit on half or a quarter of the screen.  Note that we don't merely
-    # scale it to fit, we instead cut it in half until it fits -- that should
-    # give a wider distribution of sizes.
-    #
-    if (rand() < 0.3) { $target_w /= 2; $target_h /= 2; }
-    if (rand() < 0.3) { $target_w /= 2; $target_h /= 2; }
-
-    if ($iw > $target_w || $ih > $target_h) {
-        while ($iw > $target_w ||
-               $ih > $target_h) {
-            $iw = int($iw / 2);
-            $ih = int($ih / 2);
-        }
-        if ($iw <= 10 || $ih <= 10) {
-            if ($verbose > 1) {
-                print STDERR blurb() . "scaling to ${iw}x$ih would " .
-                    "have been bogus.\n";
-            }
-            return 0;
-        }
+    if ((@_ = gif_size ($body))) {
+      ($iw, $ih) = @_;
+      $cmd = "giftopnm |";
 
-        if ($verbose > 1) {
-            print STDERR blurb() . "scaling to ${iw}x$ih\n";
-        }
+    } elsif ((@_ = jpeg_size ($body))) {
+      ($iw, $ih) = @_;
+      $cmd = "djpeg |";
 
-        $cmd .= " | pnmscale -xsize $iw -ysize $ih";
+    } elsif ($body =~ m/^P\d\n(\d+) (\d+)\n/) {
+      $iw = $1;
+      $ih = $2;
+      $cmd = "";
+
+    } else {
+      error "$bgimage is not a GIF, JPEG, or PPM.";
     }
 
+    my $x = int (($img_width  - $iw) / 2);
+    my $y = int (($img_height - $ih) / 2);
+    LOG ($verbose_pbm,
+         "pasting $bgimage (${iw}x$ih) into base image at $x,$y");
 
-    my $src = $image_tmp1;
+    $cmd .= "pnmpaste - $x $y $image_ppm > $image_tmp1";
+    open (IMG, "| $cmd") || error "running $cmd: $!";
+    print IMG $body;
+    $body = undef;
+    close (IMG);
+    LOG ($verbose_exec, "subproc exited normally.");
+    rename ($image_tmp1, $image_ppm) ||
+      error "renaming $image_tmp1 to $image_ppm: $!";
+  }
+
+  clearlog();
+
+  while (1) {
+    my ($base, $img) = pick_image();
+    my $source = $current_state;
+    $current_state = "loadimage";
+    if ($img) {
+      my ($headers, $body) = get_document ($img, $base);
+      if ($body) {
+        paste_image ($base, $img, $body, $source);
+        $body = undef;
+      }
+    }
+    $current_state = "idle";
+    $load_method = "none";
 
-    my $crop_x = 0;     # the sub-rectangle of the image
-    my $crop_y = 0;     # that we will actually paste.
-    my $crop_w = $iw;
-    my $crop_h = $ih;
+    unlink $image_tmp1, $image_tmp2;
+    sleep $delay;
+  }
+}
 
-    # The chance that we will randomly crop out a section of an image starts
-    # out fairly low, but goes up for images that are very large, or images
-    # that have ratios that make them look like banners (we try to avoid
-    # banner images entirely, but they slip through when the IMG tags didn't
-    # have WIDTH and HEIGHT specified.)
-    #
-    my $crop_chance = 0.2;
-    if ($iw > $img_width * 0.4 || $ih > $img_height * 0.4) {
-        $crop_chance += 0.2;
-    }
-    if ($iw > $img_width * 0.7 || $ih > $img_height * 0.7) {
-        $crop_chance += 0.2;
-    }
-    if ($min_ratio && ($iw * $min_ratio) > $ih) {
-        $crop_chance += 0.7;
-    }
+sub paste_image {
+  my ($base, $img, $body, $source) = @_;
 
-    if ($verbose > 2 && $crop_chance > 0.1) {
-        print STDERR blurb() . "crop chance: $crop_chance\n";
-    }
+  $current_state = "paste";
 
-    if (rand() < $crop_chance) {
+  $suppress_audit = 0;
 
-        my $ow = $crop_w;
-        my $oh = $crop_h;
+  LOG ($verbose_pbm, "got $img (" . length($body) . ")");
 
-        if ($crop_w > $min_width) {
-            # if it's a banner, select the width linearly.
-            # otherwise, select a bell.
-            my $r = (($min_ratio && ($iw * $min_ratio) > $ih)
-                     ? rand()
-                     : bellrand());
-            $crop_w = $min_width + int ($r * ($crop_w - $min_width));
-            $crop_x = int (rand() * ($ow - $crop_w));
-        }
-        if ($crop_h > $min_height) {
-            # height always selects as a bell.
-            $crop_h = $min_height + int (bellrand() * ($crop_h - $min_height));
-            $crop_y = int (rand() * ($oh - $crop_h));
-        }
+  my ($iw, $ih) = image_to_pnm ($img, $body, $image_tmp1);
+  $body = undef;
+  if (!$iw || !$ih) {
+    LOG ($verbose_pbm, "unable to make PBM from $img");
+    return 0;
+  }
 
-        if ($verbose > 1 &&
-            ($crop_x != 0   || $crop_y != 0 ||
-             $crop_w != $iw || $crop_h != $ih)) {
-            print STDERR blurb() . "randomly cropping to " .
-                "${crop_w}x$crop_h \@ $crop_x,$crop_y\n";
-        }
-    }
+  record_success ($load_method, $img, $base);
 
-    # Where the image should logically land -- this might be negative.
-    #
-    my $x = int((rand() * ($img_width  + $crop_w/2)) - $crop_w*3/4);
-    my $y = int((rand() * ($img_height + $crop_h/2)) - $crop_h*3/4);
 
-    # if we have chosen to paste the image outside of the rectangle of the
-    # screen, then we need to crop it.
-    #
-    if ($x < 0 ||
-        $y < 0 ||
-        $x + $crop_w > $img_width ||
-        $y + $crop_h > $img_height) {
-
-        if ($verbose > 1) {
-            print STDERR blurb() . "cropping for effective paste of " .
-                "${crop_w}x$crop_h \@ $x,$y\n";
-        }
+  my $ow = $iw;  # used only for error messages
+  my $oh = $ih;
 
-        if ($x < 0) { $crop_x -= $x; $crop_w += $x; $x = 0; }
-        if ($y < 0) { $crop_y -= $y; $crop_h += $y; $y = 0; }
+  # don't just tack this onto the front of the pipeline -- we want it to
+  # be able to change the size of the input image.
+  #
+  if ($filter_cmd) {
+    LOG ($verbose_pbm, "running $filter_cmd");
 
-        if ($x + $crop_w >= $img_width)  { $crop_w = $img_width  - $x - 1; }
-        if ($y + $crop_h >= $img_height) { $crop_h = $img_height - $y - 1; }
-    }
+    my $rc = nontrapping_system "($filter_cmd) < $image_tmp1 >$image_tmp2";
+    if ($rc != 0) {
+      LOG(($verbose_pbm || $verbose_load), "failed command: \"$filter_cmd\"");
+      LOG(($verbose_pbm || $verbose_load), "failed URL: \"$img\" (${ow}x$oh)");
+      return;
+    }
+    rename ($image_tmp2, $image_tmp1);
+
+    # re-get the width/height in case the filter resized it.
+    local *IMG;
+    open(IMG, "<$image_tmp1") || return 0;
+    $_ = <IMG>;
+    $_ = <IMG>;
+    ($iw, $ih) = m/^(\d+) (\d+)$/;
+    close (IMG);
+    return 0 unless ($iw && $ih);
+  }
 
-    # If any cropping needs to happen, add pnmcut.
-    #
-    if ($crop_x != 0   || $crop_y != 0 ||
-        $crop_w != $iw || $crop_h != $ih) {
-        $iw = $crop_w;
-        $ih = $crop_h;
-        $cmd .= " | pnmcut $crop_x $crop_y $iw $ih";
-        if ($verbose > 1) {
-            print STDERR blurb() . "cropping to ${crop_w}x$crop_h \@ " .
-                "$crop_x,$crop_y\n";
-        }
-    }
+  my $target_w = $img_width;
+  my $target_h = $img_height;
 
-    if ($verbose > 1) {
-        print STDERR blurb() . "pasting ${iw}x$ih \@ $x,$y in $image_ppm\n";
-    }
+  my $cmd = "";
 
-    $cmd .= " | pnmpaste - $x $y $image_ppm";
 
-    $cmd =~ s@^ *\| *@@;
-    my $rc = nontrapping_system "($cmd) < $image_tmp1 > $image_tmp2";
+  # Usually scale the image to fit on the screen -- but sometimes scale it
+  # to fit on half or a quarter of the screen.  Note that we don't merely
+  # scale it to fit, we instead cut it in half until it fits -- that should
+  # give a wider distribution of sizes.
+  #
+  if (rand() < 0.3) { $target_w /= 2; $target_h /= 2; }
+  if (rand() < 0.3) { $target_w /= 2; $target_h /= 2; }
 
-    if ($rc != 0) {
-        if ($verbose) {
-            print STDERR blurb() . "failed command: \"$cmd\"\n";
-            print STDERR blurb() . "failed url: \"$img\" (${ow}x$oh)\n";
-        }
-        return;
+  if ($iw > $target_w || $ih > $target_h) {
+    while ($iw > $target_w ||
+           $ih > $target_h) {
+      $iw = int($iw / 2);
+      $ih = int($ih / 2);
+    }
+    if ($iw <= 10 || $ih <= 10) {
+      LOG ($verbose_pbm, "scaling to ${iw}x$ih would have been bogus.");
+      return 0;
     }
 
-    rename ($image_tmp2, $image_ppm) || return;
+    LOG ($verbose_pbm, "scaling to ${iw}x$ih");
 
-    my $target = "$image_ppm";
+    $cmd .= " | pnmscale -xsize $iw -ysize $ih";
+  }
 
-    # don't just tack this onto the end of the pipeline -- we don't want it
-    # to end up in $image_ppm, because we don't want the results to be
-    # cumulative.
-    #
-    if ($post_filter_cmd) {
-        $target = $image_tmp1;
-        $rc = nontrapping_system "($post_filter_cmd) < $image_ppm > $target";
-        if ($rc != 0) {
-            if ($verbose) {
-                print STDERR blurb() . "filter failed: " .
-                    "\"$post_filter_cmd\"\n";
-            }
-            return;
-        }
-    }
 
-    if (!$no_output_p) {
-        my $tsize = (stat($target))[7];
-        if ($tsize > 200) {
-            $cmd = $ppm_to_root_window_cmd;
-            $cmd =~ s/%%PPM%%/$target/;
-
-            # xv seems to hate being killed.  it tends to forget to clean
-            # up after itself, and leaves windows around and colors allocated.
-            # I had this same problem with vidwhacker, and I'm not entirely
-            # sure what I did to fix it.  But, let's try this: launch xv
-            # in the background, so that killing this process doesn't kill it.
-            # it will die of its own accord soon enough.  So this means we
-            # start pumping bits to the root window in parallel with starting
-            # the next network retrieval, which is probably a better thing
-            # to do anyway.
-            #
-            $cmd .= "&";
-
-            $rc = nontrapping_system ($cmd);
-
-            if ($rc != 0) {
-                if ($verbose) {
-                    print STDERR blurb() . "display failed: \"$cmd\"\n";
-                }
-                return;
-            }
-
-        } elsif ($verbose > 1) {
-            print STDERR blurb() . "$target size is $tsize\n";
-        }
-    }
+  my $src = $image_tmp1;
 
-    if ($verbose > 0) {
-        print STDOUT "image: ${iw}x${ih} @ $x,$y $base $source\n";
-    }
+  my $crop_x = 0;     # the sub-rectangle of the image
+  my $crop_y = 0;     # that we will actually paste.
+  my $crop_w = $iw;
+  my $crop_h = $ih;
 
-    return 1;
-}
+  # The chance that we will randomly crop out a section of an image starts
+  # out fairly low, but goes up for images that are very large, or images
+  # that have ratios that make them look like banners (we try to avoid
+  # banner images entirely, but they slip through when the IMG tags didn't
+  # have WIDTH and HEIGHT specified.)
+  #
+  my $crop_chance = 0.2;
+  if ($iw > $img_width * 0.4 || $ih > $img_height * 0.4) {
+    $crop_chance += 0.2;
+  }
+  if ($iw > $img_width * 0.7 || $ih > $img_height * 0.7) {
+    $crop_chance += 0.2;
+  }
+  if ($min_ratio && ($iw * $min_ratio) > $ih) {
+    $crop_chance += 0.7;
+  }
 
+  if ($crop_chance > 0.1) {
+    LOG ($verbose_pbm, "crop chance: $crop_chance");
+  }
 
-sub main {
-    $| = 1;
-    srand(time ^ $$);
-
-    my $root_p = 0;
-
-    # historical suckage: the environment variable name is lower case.
-    $http_proxy = $ENV{http_proxy} || $ENV{HTTP_PROXY};
-
-    while ($_ = $ARGV[0]) {
-        shift @ARGV;
-        if ($_ eq "-display" ||
-            $_ eq "-displ" ||
-            $_ eq "-disp" ||
-            $_ eq "-dis" ||
-            $_ eq "-dpy" ||
-            $_ eq "-d") {
-            $ENV{DISPLAY} = shift @ARGV;
-        } elsif ($_ eq "-root") {
-            $root_p = 1;
-        } elsif ($_ eq "-no-output") {
-            $no_output_p = 1;
-        } elsif ($_ eq "-urls-only") {
-            $urls_only_p = 1;
-            $no_output_p = 1;
-        } elsif ($_ eq "-verbose") {
-            $verbose++;
-        } elsif (m/^-v+$/) {
-            $verbose += length($_)-1;
-        } elsif ($_ eq "-delay") {
-            $delay = shift @ARGV;
-        } elsif ($_ eq "-timeout") {
-            $http_timeout = shift @ARGV;
-        } elsif ($_ eq "-filter") {
-            $filter_cmd = shift @ARGV;
-        } elsif ($_ eq "-filter2") {
-            $post_filter_cmd = shift @ARGV;
-        } elsif ($_ eq "-background" || $_ eq "-bg") {
-            $background = shift @ARGV;
-        } elsif ($_ eq "-size") {
-            $_ = shift @ARGV;
-            if (m@^(\d+)x(\d+)$@) {
-                $img_width = $1;
-                $img_height = $2;
-            } else {
-                die blurb() . "argument to \"-size\" must be" .
-                    " of the form \"640x400\"\n";
-            }
-        } elsif ($_ eq "-proxy" || $_ eq "-http-proxy") {
-            $http_proxy = shift @ARGV;
-        } else {
-            die "$copyright\nusage: $progname [-root]" .
-                " [-display dpy] [-root] [-verbose] [-timeout secs]\n" .
-                "\t\t  [-delay secs] [-filter cmd] [-filter2 cmd]\n" .
-                "\t\t  [-http-proxy host[:port]]\n";
-        }
+  if (rand() < $crop_chance) {
+    
+    my $ow = $crop_w;
+    my $oh = $crop_h;
+    
+    if ($crop_w > $min_width) {
+      # if it's a banner, select the width linearly.
+      # otherwise, select a bell.
+      my $r = (($min_ratio && ($iw * $min_ratio) > $ih)
+               ? rand()
+               : bellrand());
+      $crop_w = $min_width + int ($r * ($crop_w - $min_width));
+      $crop_x = int (rand() * ($ow - $crop_w));
+    }
+    if ($crop_h > $min_height) {
+      # height always selects as a bell.
+      $crop_h = $min_height + int (bellrand() * ($crop_h - $min_height));
+      $crop_y = int (rand() * ($oh - $crop_h));
     }
+    
+    if ($crop_x != 0   || $crop_y != 0 ||
+        $crop_w != $iw || $crop_h != $ih) {
+      LOG ($verbose_pbm,
+           "randomly cropping to ${crop_w}x$crop_h \@ $crop_x,$crop_y");
+    }
+  }
+
+  # Where the image should logically land -- this might be negative.
+  #
+  my $x = int((rand() * ($img_width  + $crop_w/2)) - $crop_w*3/4);
+  my $y = int((rand() * ($img_height + $crop_h/2)) - $crop_h*3/4);
+
+  # if we have chosen to paste the image outside of the rectangle of the
+  # screen, then we need to crop it.
+  #
+  if ($x < 0 ||
+      $y < 0 ||
+      $x + $crop_w > $img_width ||
+      $y + $crop_h > $img_height) {
+    
+    LOG ($verbose_pbm,
+         "cropping for effective paste of ${crop_w}x$crop_h \@ $x,$y");
+    
+    if ($x < 0) { $crop_x -= $x; $crop_w += $x; $x = 0; }
+    if ($y < 0) { $crop_y -= $y; $crop_h += $y; $y = 0; }
+    
+    if ($x + $crop_w >= $img_width)  { $crop_w = $img_width  - $x - 1; }
+    if ($y + $crop_h >= $img_height) { $crop_h = $img_height - $y - 1; }
+  }
 
-    if ($http_proxy && $http_proxy eq "") {
-        $http_proxy = undef;
-    }
-    if ($http_proxy && $http_proxy =~ m@^http://([^/]*)/?$@ ) {
-        # historical suckage: allow "http://host:port" as well as "host:port".
-        $http_proxy = $1;
-    }
+  # If any cropping needs to happen, add pnmcut.
+  #
+  if ($crop_x != 0   || $crop_y != 0 ||
+        $crop_w != $iw || $crop_h != $ih) {
+    $iw = $crop_w;
+    $ih = $crop_h;
+    $cmd .= " | pnmcut $crop_x $crop_y $iw $ih";
+    LOG ($verbose_pbm, "cropping to ${crop_w}x$crop_h \@ $crop_x,$crop_y");
+  }
 
-    if (!$root_p && !$no_output_p) {
-        die "$copyright" .
-            blurb() . "the -root argument is mandatory (for now.)\n";
-    }
+  LOG ($verbose_pbm, "pasting ${iw}x$ih \@ $x,$y in $image_ppm");
 
-    if (!$no_output_p && !$ENV{DISPLAY}) {
-        die blurb() . "\$DISPLAY is not set.\n";
-    }
+  $cmd .= " | pnmpaste - $x $y $image_ppm";
+
+  $cmd =~ s@^ *\| *@@;
 
-    if ($urls_only_p) {
-        url_only_output;
+  $_ = "($cmd)";
+  $_ .= " < $image_tmp1 > $image_tmp2";
+
+  if ($verbose_pbm) {
+    $_ = "($_) 2>&1 | sed s'/^/" . blurb() . "/'";
+  } else {
+    $_ .= " 2> /dev/null";
+  }
+  my $rc = nontrapping_system ($_);
+
+  if ($rc != 0) {
+    LOG (($verbose_pbm || $verbose_load), "failed command: \"$cmd\"");
+    LOG (($verbose_pbm || $verbose_load), "failed URL: \"$img\" (${ow}x$oh)");
+    return;
+  }
+
+  rename ($image_tmp2, $image_ppm) || return;
+
+  my $target = "$image_ppm";
+
+  # don't just tack this onto the end of the pipeline -- we don't want it
+  # to end up in $image_ppm, because we don't want the results to be
+  # cumulative.
+  #
+  if ($post_filter_cmd) {
+    $target = $image_tmp1;
+    $rc = nontrapping_system "($post_filter_cmd) < $image_ppm > $target";
+    if ($rc != 0) {
+      LOG ($verbose_pbm, "filter failed: \"$post_filter_cmd\"\n");
+      return;
+    }
+  }
+
+  if (!$no_output_p) {
+    my $tsize = (stat($target))[7];
+    if ($tsize > 200) {
+      $cmd = "$ppm_to_root_window_cmd $target";
+      
+      # xv seems to hate being killed.  it tends to forget to clean
+      # up after itself, and leaves windows around and colors allocated.
+      # I had this same problem with vidwhacker, and I'm not entirely
+      # sure what I did to fix it.  But, let's try this: launch xv
+      # in the background, so that killing this process doesn't kill it.
+      # it will die of its own accord soon enough.  So this means we
+      # start pumping bits to the root window in parallel with starting
+      # the next network retrieval, which is probably a better thing
+      # to do anyway.
+      #
+      $cmd .= " &";
+      
+      $rc = nontrapping_system ($cmd);
+      
+      if ($rc != 0) {
+        LOG (($verbose_pbm || $verbose_load), "display failed: \"$cmd\"");
+        return;
+      }
+      
     } else {
-        x_output;
+      LOG ($verbose_pbm, "$target size is $tsize");
     }
+  }
+
+  $source .= "-" . stats_of($source);
+  print STDOUT "image: ${iw}x${ih} @ $x,$y $base $source\n"
+    if ($verbose_imgmap);
+
+  clearlog();
+
+  return 1;
+}
+
+
+sub main {
+  $| = 1;
+  srand(time ^ $$);
+
+  my $verbose = 0;
+
+  $current_state = "init";
+  $load_method = "none";
+
+  my $root_p = 0;
+
+  # historical suckage: the environment variable name is lower case.
+  $http_proxy = $ENV{http_proxy} || $ENV{HTTP_PROXY};
+
+  while ($_ = $ARGV[0]) {
+    shift @ARGV;
+    if ($_ eq "-display" ||
+        $_ eq "-displ" ||
+        $_ eq "-disp" ||
+        $_ eq "-dis" ||
+        $_ eq "-dpy" ||
+        $_ eq "-d") {
+      $ENV{DISPLAY} = shift @ARGV;
+    } elsif ($_ eq "-root") {
+      $root_p = 1;
+    } elsif ($_ eq "-no-output") {
+      $no_output_p = 1;
+    } elsif ($_ eq "-urls-only") {
+      $urls_only_p = 1;
+      $no_output_p = 1;
+    } elsif ($_ eq "-verbose") {
+      $verbose++;
+    } elsif (m/^-v+$/) {
+      $verbose += length($_)-1;
+    } elsif ($_ eq "-delay") {
+      $delay = shift @ARGV;
+    } elsif ($_ eq "-timeout") {
+      $http_timeout = shift @ARGV;
+    } elsif ($_ eq "-filter") {
+      $filter_cmd = shift @ARGV;
+    } elsif ($_ eq "-filter2") {
+      $post_filter_cmd = shift @ARGV;
+    } elsif ($_ eq "-background" || $_ eq "-bg") {
+      $background = shift @ARGV;
+    } elsif ($_ eq "-size") {
+      $_ = shift @ARGV;
+      if (m@^(\d+)x(\d+)$@) {
+        $img_width = $1;
+        $img_height = $2;
+      } else {
+        error "argument to \"-size\" must be of the form \"640x400\"";
+      }
+    } elsif ($_ eq "-proxy" || $_ eq "-http-proxy") {
+      $http_proxy = shift @ARGV;
+    } else {
+      print STDERR "$copyright\nusage: $progname [-root]" .
+                 " [-display dpy] [-root] [-verbose] [-timeout secs]\n" .
+                 "\t\t  [-delay secs] [-filter cmd] [-filter2 cmd]\n" .
+                 "\t\t  [-http-proxy host[:port]]\n";
+      exit 1;
+    }
+  }
+
+  if ($http_proxy && $http_proxy eq "") {
+    $http_proxy = undef;
+  }
+  if ($http_proxy && $http_proxy =~ m@^http://([^/]*)/?$@ ) {
+    # historical suckage: allow "http://host:port" as well as "host:port".
+    $http_proxy = $1;
+  }
+
+  if (!$root_p && !$no_output_p) {
+    print STDERR $copyright;
+    error "the -root argument is mandatory (for now.)";
+  }
+
+  if (!$no_output_p && !$ENV{DISPLAY}) {
+    error "\$DISPLAY is not set.";
+  }
+
+
+  if ($verbose == 1) {
+    $verbose_imgmap   = 1;
+    $verbose_warnings = 1;
+
+  } elsif ($verbose == 2) {
+    $verbose_imgmap   = 1;
+    $verbose_warnings = 1;
+    $verbose_load     = 1;
+
+  } elsif ($verbose == 3) {
+    $verbose_imgmap   = 1;
+    $verbose_warnings = 1;
+    $verbose_load     = 1;
+    $verbose_filter   = 1;
+
+  } elsif ($verbose == 4) {
+    $verbose_imgmap   = 1;
+    $verbose_warnings = 1;
+    $verbose_load     = 1;
+    $verbose_filter   = 1;
+    $verbose_net      = 1;
+
+  } elsif ($verbose == 5) {
+    $verbose_imgmap   = 1;
+    $verbose_warnings = 1;
+    $verbose_load     = 1;
+    $verbose_filter   = 1;
+    $verbose_net      = 1;
+    $verbose_pbm      = 1;
+
+  } elsif ($verbose == 6) {
+    $verbose_imgmap   = 1;
+    $verbose_warnings = 1;
+    $verbose_load     = 1;
+    $verbose_filter   = 1;
+    $verbose_net      = 1;
+    $verbose_pbm      = 1;
+    $verbose_http     = 1;
+
+  } elsif ($verbose >= 7) {
+    $verbose_imgmap   = 1;
+    $verbose_warnings = 1;
+    $verbose_load     = 1;
+    $verbose_filter   = 1;
+    $verbose_net      = 1;
+    $verbose_pbm      = 1;
+    $verbose_http     = 1;
+    $verbose_exec     = 1;
+  }
+
+
+  if ($urls_only_p) {
+    url_only_output;
+  } else {
+    x_or_pbm_output;
+  }
 }
 
 main;
diff --git a/hacks/whirlygig.c b/hacks/whirlygig.c
new file mode 100644 (file)
index 0000000..0f26bbc
--- /dev/null
@@ -0,0 +1,171 @@
+/*  Whirlygig -- an experiment in X programming
+ *
+ * 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.
+ *
+ *  When I was in trigonometry class as a kid, I remember being fascinated
+ *  by the beauty of the shapes one receives when playing with sine waves
+ *  Here is a little experiment to show that beauty is simple
+ */
+#include <math.h>
+#include "screenhack.h"
+#include <stdio.h>
+
+static XColor colors[1000];
+static int ncolors = 1000;
+static int current_color = 0;
+
+int 
+draw_dot(Display *dpy, 
+         Window window, 
+         Colormap cmap, 
+         GC fgc, GC bgc,
+         int current_time,
+         int origin_x, int origin_y,
+         int screen_num, double xspeed, double yspeed,
+         int whirlies, int nlines) 
+{
+    int size, last_size;  /* The size of my dot */
+    int start_arc = 0;  /* Start my circle at 0 degrees */
+    int end_arc = 23040;  /*  The number of degrees in a X circle (360 * 64) */
+    int horiz, vert;    /*  These will contain the new x,y coordinates to put my dot */
+    int last_horiz ,last_vert;  /*  These contain the positions to black out */
+    int last_time;
+    int count, line_count;
+    int line_offset, last_line_offset;
+    int color_offset;
+    XWindowAttributes xgwa;
+    XGetWindowAttributes (dpy, window, &xgwa);
+    if (++current_color >= ncolors)
+        current_color = 0;
+    for (count = 0; count < whirlies; count++) { 
+        color_offset = (current_color + (10 * count )) % ncolors;
+        if (current_time == count) { 
+            last_time = current_time; 
+        }
+        else {
+            current_time = current_time + count;
+            last_time = current_time - 1;
+        }
+        last_horiz = compute_x(last_time, origin_x, xspeed);
+        last_vert = compute_y(last_time, origin_y, yspeed);
+        horiz = compute_x(current_time, origin_x, xspeed);
+        vert = compute_y(current_time, origin_y, yspeed);
+        for (line_count = 0; line_count < nlines; line_count++) { 
+            last_line_offset = (int)(80.0 * line_count * sin((double)last_time / 90));
+            line_offset = (int)(80.0 * line_count * sin((double)current_time / 90));
+            last_size = (int)(15.0 + 5.0 * sin((double)last_time / 180.0));
+            size = (int)(15.0 + 5.0 * sin((double)current_time / 180.0));
+                /* Get rid of the old circle */
+            XSetForeground(dpy, bgc, BlackPixel(dpy, screen_num));
+            XFillArc(dpy, window, bgc, last_horiz, last_line_offset+last_vert, last_size, last_size, start_arc, end_arc);
+                /* Draw in the new circle */
+            XSetForeground(dpy, bgc, colors[color_offset].pixel);
+            XFillArc(dpy, window, bgc, horiz, line_offset+vert, size, size, start_arc, end_arc);
+        } 
+    }
+    XSync (dpy, False); 
+    if (current_time == 23040)
+    { 
+        return(1);
+    }
+    else 
+    {
+        return(0);
+    }
+}
+
+int compute_x(int the_time, int origin, double xspeed) 
+{
+    double funky = (((the_time % 360) * 1.0) / 180.0) * M_PI;
+    double the_cosine = cos((double)the_time / (180.0 * xspeed));
+    double dist_mod_x = cos((double)funky) * (origin - 50);
+    int horiz_pos = origin + (the_cosine * dist_mod_x);
+    return(horiz_pos);
+}
+
+int compute_y(int the_time, int origin, double yspeed)
+{
+    double funky = (((the_time % 360) * 1.0) / 180.0) * M_PI;
+    double the_sine = sin((double)the_time / (180.0 * yspeed));
+    double dist_mod_y = sin((double)funky) * (origin - 50);
+    int vert_pos = origin + (the_sine * dist_mod_y);
+    return(vert_pos);
+}
+
+char *progclass = "Whirlygig";
+
+char *defaults [] = {
+  ".background:                black",
+  ".foreground:                white",
+  "*xspeed:             1.0",
+  "*yspeed:             1.0",
+  "*whirlies:           10",
+  "*nlines:             1",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-xspeed",          ".xspeed", XrmoptionSepArg, 0 },
+  { "-yspeed",          ".yspeed", XrmoptionSepArg, 0 },
+  { "-whirlies",         ".whirlies",XrmoptionSepArg, 0 },
+  { "-nlines",         ".nlines",XrmoptionSepArg, 0 },
+  { 0, 0, 0, 0 }
+};
+
+void screenhack (Display *dpy, Window window)
+{
+    GC fgc, bgc;  /* the foreground and background graphics contexts */
+    XGCValues gcv;      /* The structure to hold the GC data */
+    XWindowAttributes xgwa;       /*  A structure to hold window data */
+    Bool writable = get_boolean_resource ("cycle", "Boolean");
+    double xspeed = get_float_resource( "xspeed", "Float");
+    double yspeed = get_float_resource( "yspeed", "Float");
+    int whirlies = get_integer_resource( "whirlies", "Integer");
+    int nlines = get_integer_resource( "nlines", "Integer");
+    int time_counter = 0;  /* This will be incremented in my while loop so that I can move my circle */
+    int screen_num = DefaultScreen(dpy);
+    int half_width, half_height;
+    XGetWindowAttributes (dpy, window, &xgwa);
+
+    half_width = xgwa.width / 2;
+    half_height = xgwa.height / 2;
+
+    gcv.foreground = get_pixel_resource("foreground", "Foreground", dpy, xgwa.colormap);
+    fgc = XCreateGC (dpy, window, GCForeground, &gcv);
+    gcv.foreground = get_pixel_resource("background", "Background", dpy, xgwa.colormap);
+    bgc = XCreateGC (dpy, window, GCForeground, &gcv);
+    make_uniform_colormap (dpy, xgwa.visual, xgwa.colormap, 
+                           colors, &ncolors, 
+                           True, &writable, True);
+    mono_p = True;
+    if (!mono_p)
+    {
+        GC tmp = fgc;
+        fgc = bgc;
+        bgc = tmp;
+    }
+
+    while (1)
+    {
+            /* draw_dot will return an interger.  If this interger is 0, then continue incrementing 
+               time_counter, if it is 1, then reset it to zero...  It should only become 1 with the sine
+               is 0 and the cosine is 1 */
+        if (draw_dot(dpy, window, xgwa.colormap, fgc, bgc, time_counter, half_width, half_height, screen_num, xspeed , yspeed, whirlies, nlines) == 1) {
+            time_counter = 1;
+        }
+        else {
+            time_counter++;
+        }
+        screenhack_handle_events (dpy);
+
+        if (!writable)
+            usleep(10);
+    }
+}
+
diff --git a/hacks/whirlygig.man b/hacks/whirlygig.man
new file mode 100644 (file)
index 0000000..c42edc1
--- /dev/null
@@ -0,0 +1,58 @@
+.TH XScreenSaver 1 "31-Mar-01" "X Version 11"
+.SH NAME
+whirlygig -- zooming chains of sinusoidal spots
+.SH SYNOPSIS
+.B whirlygig
+[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-background] [\-foreground] [\-xspeed] [\-yspeed] [\-whirlies] [\-nlines]
+.SH DESCRIPTION
+The \flwhirlygig\fP program draws a series of circles on your screen.
+They then move about in a cyclic pattern
+.SH OPTIONS
+.I whirlygig
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-xspeed \flspeed\fP
+Specify how fast the dots should cycle horizontally.
+Try out values from .01 to 4000
+.TP 8
+.B \-yspeed \flspeed\fP
+Specify how fast the dots should cycle vertically.
+Try out values from .01 to 4000
+.TP 8
+.B \-whirlies \fla number\fP
+Specify how many whilrlies you want
+.TP 8
+.B \-nlines \flnumber of lines\fP
+Specify how many lines of whirlies you want
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 2001 by Ashton Trey Belew.  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 AUTHOR
+Ashton Trey Belew <trey@veggie.wesleyan.edu>, 31-Mar-01
index 574f1883deeb8b88e51389ce09be0ddad248aaf7..857cb2103fcb83737002a3ab8591c8abd1712c6f 100644 (file)
--- a/setup.com
+++ b/setup.com
@@ -78,6 +78,7 @@ $ sierpinski  :== $'mydir'sierpinski
 $ slidescreen  :== $'mydir'slidescreen
 $ slip         :== $'mydir'slip
 $ sonar                :== $'mydir'sonar
+$ speedmine    :== $'mydir'speedmine
 $ sphere       :== $'mydir'sphere
 $ spiral       :== $'mydir'spiral
 $ spotlight    :== $'mydir'spotlight
@@ -91,6 +92,7 @@ $ truchet     :== $'mydir'truchet
 $ vines                :== $'mydir'vines
 $ wander       :== $'mydir'wander
 $ whirlwindwarp        :== $'mydir'whirlwindwarp
+$ whirlygig    :== $'mydir'whirlygig
 $ worm         :== $'mydir'worm
 $ xflame       :== $'mydir'xflame
 $ xjack                :== $'mydir'xjack
index f3d6de8b49ebc8942972838a40b5fb846f8c7fe2..bd7a345d1d74cec162d9431286d73d17cf615778 100644 (file)
@@ -1,8 +1,18 @@
 /* erase.c: Erase the screen in various more or less interesting ways.
- * (c) 1997 by Johannes Keukelaar <johannes@nada.kth.se>
- * Permission to use in any way granted. Provided "as is" without expressed
- * or implied warranty. NO WARRANTY, NO EXPRESSION OF SUITABILITY FOR ANY
- * PURPOSE. (I.e.: Use in any way, but at your own risk!)
+ * Copyright (c) 1997-2001 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ *
+ * Portions (c) 1997 by Johannes Keukelaar <johannes@nada.kth.se>:
+ *   Permission to use in any way granted. Provided "as is" without expressed
+ *   or implied warranty. NO WARRANTY, NO EXPRESSION OF SUITABILITY FOR ANY
+ *   PURPOSE. (I.e.: Use in any way, but at your own risk!)
  */
 
 #include "utils.h"
 #include "usleep.h"
 #include "resources.h"
 
+extern char *progname;
+
 #undef countof
 #define countof(x) (sizeof(x)/sizeof(*(x)))
 
+#define LITTLE_NAP 5000   /* 1/200th sec */
+
 typedef void (*Eraser) (Display *dpy, Window window, GC gc,
-                       int width, int height, int delay, int granularity);
+                       int width, int height, int total_msecs);
+
+
+static unsigned long
+millitime (void)
+{
+  struct timeval tt;
+# ifdef GETTIMEOFDAY_TWO_ARGS
+  struct timezone tz;
+  gettimeofday (&tt, &tz);
+# else
+  gettimeofday (&tt);
+# endif
+  return (tt.tv_sec * 1000) + (tt.tv_usec / 1000);
+}
 
 
 static void
 random_lines (Display *dpy, Window window, GC gc,
-             int width, int height, int delay, int granularity)
+             int width, int height, int total_msecs)
 {
+  int granularity = 50;
+
   Bool horiz_p = (random() & 1);
   int max = (horiz_p ? height : width);
   int *lines = (int *) calloc(max, sizeof(*lines));
+  int oi = -1;
   int i;
+  unsigned long start_tick = millitime();
+  unsigned long end_tick = start_tick + total_msecs;
+  unsigned long tick = start_tick;
+  int hits = 0;
+  int nonhits = 0;
 
   for (i = 0; i < max; i++)
     lines[i] = i;
@@ -38,32 +74,57 @@ random_lines (Display *dpy, Window window, GC gc,
       lines[r] = t;
     }
 
-  for (i = 0; i < max; i++)
-    { 
-      if (horiz_p)
-       XDrawLine (dpy, window, gc, 0, lines[i], width, lines[i]);
+  while (tick < end_tick)
+    {
+      int i = (max * (tick - start_tick)) / (end_tick - start_tick);
+
+      i /= granularity;
+
+      if (i == oi)
+        {
+          usleep (LITTLE_NAP);
+          nonhits++;
+        }
       else
-       XDrawLine (dpy, window, gc, lines[i], 0, lines[i], height);
+        {
+          int j;
+          for (j = 0; j < granularity; j++)
+            {
+              int ii = i * granularity + j;
+              if (horiz_p)
+                XDrawLine (dpy, window, gc, 0, lines[ii], width, lines[ii]);
+              else
+                XDrawLine (dpy, window, gc, lines[ii], 0, lines[ii], height);
+              hits++;
+            }
+          XSync (dpy, False);
+        }
 
-      XSync (dpy, False);
-      if (delay > 0 && ((i % granularity) == 0))
-       usleep (delay * granularity);
+      oi = i;
+      tick = millitime();
     }
+
   free(lines);
 }
 
 
 static void
 venetian (Display *dpy, Window window, GC gc,
-         int width, int height, int delay, int granularity)
+         int width, int height, int total_msecs)
 {
   Bool horiz_p = (random() & 1);
   Bool flip_p = (random() & 1);
   int max = (horiz_p ? height : width);
   int *lines = (int *) calloc(max, sizeof(*lines));
   int i, j;
+  int oi = -1;
 
-  granularity /= 6;
+  unsigned long start_tick = millitime();
+  unsigned long end_tick = (start_tick +
+                            (1.5 * total_msecs));  /* this one needs more */
+  unsigned long tick = start_tick;
+  int hits = 0;
+  int nonhits = 0;
 
   j = 0;
   for (i = 0; i < max*2; i++)
@@ -73,16 +134,31 @@ venetian (Display *dpy, Window window, GC gc,
        lines[j++] = (flip_p ? max - line : line);
     }
 
-  for (i = 0; i < max; i++)
-    { 
-      if (horiz_p)
-       XDrawLine (dpy, window, gc, 0, lines[i], width, lines[i]);
+  while (tick < end_tick)
+    {
+      int i = (max * (tick - start_tick)) / (end_tick - start_tick);
+
+      if (i == oi)
+        {
+          usleep (LITTLE_NAP);
+          nonhits++;
+        }
       else
-       XDrawLine (dpy, window, gc, lines[i], 0, lines[i], height);
+        {
+          int k;
+          for (k = oi; k <= i; k++)
+            {
+              if (horiz_p)
+                XDrawLine(dpy,window, gc, 0, lines[k], width, lines[k]);
+              else
+                XDrawLine(dpy,window, gc, lines[k], 0, lines[k], height);
+              hits++;
+            }
+          XSync (dpy, False);
+        }
 
-      XSync (dpy, False);
-      if (delay > 0 && ((i % granularity) == 0))
-       usleep (delay * granularity);
+      oi = i;
+      tick = millitime();
     }
   free(lines);
 }
@@ -90,13 +166,20 @@ venetian (Display *dpy, Window window, GC gc,
 
 static void
 triple_wipe (Display *dpy, Window window, GC gc,
-            int width, int height, int delay, int granularity)
+            int width, int height, int total_msecs)
 {
   Bool flip_x = random() & 1;
   Bool flip_y = random() & 1;
   int max = width + (height / 2);
   int *lines = (int *)calloc(max, sizeof(int));
   int i;
+  int oi = -1;
+
+  unsigned long start_tick = millitime();
+  unsigned long end_tick = start_tick + total_msecs;
+  unsigned long tick = start_tick;
+  int hits = 0;
+  int nonhits = 0;
 
   for(i = 0; i < width/2; i++)
     lines[i] = i*2+height;
@@ -105,25 +188,39 @@ triple_wipe (Display *dpy, Window window, GC gc,
   for(i = 0; i < width/2; i++)
     lines[i+width/2+height/2] = width-i*2-(width%2?0:1)+height;
 
-  granularity /= 6;
-
-  for (i = 0; i < max; i++)
-    { 
+  while (tick < end_tick)
+    {
+      int i = (max * (tick - start_tick)) / (end_tick - start_tick);
       int x, y, x2, y2;
-      if (lines[i] < height)
-       x = 0, y = lines[i], x2 = width, y2 = y;
-      else
-       x = lines[i]-height, y = 0, x2 = x, y2 = height;
 
-      if (flip_x)
-       x = width-x, x2 = width-x2;
-      if (flip_y)
-       y = height-y, y2 = height-y2;
+      if (i == oi)
+        {
+          usleep (LITTLE_NAP);
+          nonhits++;
+        }
+      else
+        {
+          int k;
+          for (k = oi; k <= i; k++)
+            {
+              if (lines[k] < height)
+                x = 0, y = lines[k], x2 = width, y2 = y;
+              else
+                x = lines[k]-height, y = 0, x2 = x, y2 = height;
+
+              if (flip_x)
+                x = width-x, x2 = width-x2;
+              if (flip_y)
+                y = height-y, y2 = height-y2;
+
+              XDrawLine (dpy, window, gc, x, y, x2, y2);
+              hits++;
+            }
+          XSync (dpy, False);
+        }
 
-      XDrawLine (dpy, window, gc, x, y, x2, y2);
-      XSync (dpy, False);
-      if (delay > 0 && ((i % granularity) == 0))
-       usleep (delay*granularity);
+      oi = i;
+      tick = millitime();
     }
   free(lines);
 }
@@ -131,15 +228,20 @@ triple_wipe (Display *dpy, Window window, GC gc,
 
 static void
 quad_wipe (Display *dpy, Window window, GC gc,
-          int width, int height, int delay, int granularity)
+          int width, int height, int total_msecs)
 {
   Bool flip_x = random() & 1;
   Bool flip_y = random() & 1;
   int max = width + height;
   int *lines = (int *)calloc(max, sizeof(int));
   int i;
+  int oi = -1;
 
-  granularity /= 3;
+  unsigned long start_tick = millitime();
+  unsigned long end_tick = start_tick + total_msecs;
+  unsigned long tick = start_tick;
+  int hits = 0;
+  int nonhits = 0;
 
   for (i = 0; i < max/4; i++)
     {
@@ -149,24 +251,41 @@ quad_wipe (Display *dpy, Window window, GC gc,
       lines[i*4+3] = height+width-i*2-(width%2?0:1);
     }
 
-  for (i = 0; i < max; i++)
-    { 
-      int x, y, x2, y2;
-      if (lines[i] < height)
-       x = 0, y = lines[i], x2 = width, y2 = y;
-      else
-       x = lines[i]-height, y = 0, x2 = x, y2 = height;
+  while (tick < end_tick)
+    {
+      int i = (max * (tick - start_tick)) / (end_tick - start_tick);
 
-      if (flip_x)
-       x = width-x, x2 = width-x2;
-      if (flip_y)
-       y = height-y, y2 = height-y2;
+      if (i == oi)
+        {
+          usleep (LITTLE_NAP);
+          nonhits++;
+        }
+      else
+        {
+          int k;
+          for (k = oi; k <= i; k++)
+            {
+              int x, y, x2, y2;
+              if (lines[k] < height)
+                x = 0, y = lines[k], x2 = width, y2 = y;
+              else
+                x = lines[k]-height, y = 0, x2 = x, y2 = height;
+
+              if (flip_x)
+                x = width-x, x2 = width-x2;
+              if (flip_y)
+                y = height-y, y2 = height-y2;
+
+              XDrawLine (dpy, window, gc, x, y, x2, y2);
+              hits++;
+            }
+          XSync (dpy, False);
+        }
 
-      XDrawLine (dpy, window, gc, x, y, x2, y2);
-      XSync (dpy, False);
-      if (delay > 0 && ((i % granularity) == 0))
-       usleep (delay*granularity);
+      oi = i;
+      tick = millitime();
     }
+
   free(lines);
 }
 
@@ -174,71 +293,131 @@ quad_wipe (Display *dpy, Window window, GC gc,
 
 static void
 circle_wipe (Display *dpy, Window window, GC gc,
-            int width, int height, int delay, int granularity)
+            int width, int height, int total_msecs)
 {
-  int full = 360 * 64;
-  int inc = full / 64;
-  int start = random() % full;
+  int max = 360 * 64;
+  int start = random() % max;
   int rad = (width > height ? width : height);
-  int i;
-  if (random() & 1)
-    inc = -inc;
-  for (i = (inc > 0 ? 0 : full);
-       (inc > 0 ? i < full : i > 0);
-       i += inc)
+  int flip_p = random() & 1;
+  int oth;
+
+  unsigned long start_tick = millitime();
+  unsigned long end_tick = start_tick + total_msecs;
+  unsigned long tick = start_tick;
+
+  int hits = 0;
+  int nonhits = 0;
+
+  oth = (flip_p ? max : 0);
+  while (tick < end_tick)
     {
-      XFillArc(dpy, window, gc,
-              (width/2)-rad, (height/2)-rad, rad*2, rad*2,
-              (i+start) % full, inc);
-      XFlush (dpy);
-      usleep (delay*granularity);
+      int th = (max * (tick - start_tick)) / (end_tick - start_tick);
+      if (flip_p)
+        th = (360 * 64) - th;
+
+      if (th == oth)
+        {
+          usleep (LITTLE_NAP);
+          nonhits++;
+        }
+      else
+        {
+          XFillArc(dpy, window, gc,
+                   (width/2)-rad, (height/2)-rad, rad*2, rad*2,
+                   (start+oth)%(360*64),
+                   (th-oth));
+          hits++;
+          XSync (dpy, False);
+        }
+
+      oth = th;
+      tick = millitime();
     }
 }
 
 
 static void
 three_circle_wipe (Display *dpy, Window window, GC gc,
-                  int width, int height, int delay, int granularity)
+                  int width, int height, int total_msecs)
 {
-  int i;
-  int full = 360 * 64;
-  int q = full / 6;
-  int q2 = q * 2;
-  int inc = full / 240;
-  int start = random() % q;
+  int max = (360 * 64) / 6;
+  int start = random() % max;
   int rad = (width > height ? width : height);
+  int oth;
 
-  for (i = 0; i < q; i += inc)
-    {
-      XFillArc(dpy, window, gc, (width/2)-rad, (height/2)-rad, rad*2, rad*2,
-              (start+i) % full, inc);
-      XFillArc(dpy, window, gc, (width/2)-rad, (height/2)-rad, rad*2, rad*2,
-              (start-i) % full, -inc);
+  unsigned long start_tick = millitime();
+  unsigned long end_tick = start_tick + total_msecs;
+  unsigned long tick = start_tick;
+
+  int hits = 0;
+  int nonhits = 0;
 
-      XFillArc(dpy, window, gc, (width/2)-rad, (height/2)-rad, rad*2, rad*2,
-              (start+q2+i) % full, inc);
-      XFillArc(dpy, window, gc, (width/2)-rad, (height/2)-rad, rad*2, rad*2,
-              (start+q2-i) % full, -inc);
+  oth = 0;
+  while (tick < end_tick)
+    {
+      int th = (max * (tick - start_tick)) / (end_tick - start_tick);
 
-      XFillArc(dpy, window, gc, (width/2)-rad, (height/2)-rad, rad*2, rad*2,
-              (start+q2+q2+i) % full, inc);
-      XFillArc(dpy, window, gc, (width/2)-rad, (height/2)-rad, rad*2, rad*2,
-              (start+q2+q2-i) % full, -inc);
+      if (th == oth)
+        {
+          usleep (LITTLE_NAP);
+          nonhits++;
+        }
+      else
+        {
+          int off = 0;
+          XFillArc(dpy, window, gc,
+                   (width/2)-rad, (height/2)-rad, rad*2, rad*2,
+                   (start+off+oth)%(360*64),
+                   (th-oth));
+          XFillArc(dpy, window, gc,
+                   (width/2)-rad, (height/2)-rad, rad*2, rad*2,
+                   ((start+off-oth))%(360*64),
+                   -(th-oth));
+
+          off += max + max;
+          XFillArc(dpy, window, gc,
+                   (width/2)-rad, (height/2)-rad, rad*2, rad*2,
+                   (start+off+oth)%(360*64),
+                   (th-oth));
+          XFillArc(dpy, window, gc,
+                   (width/2)-rad, (height/2)-rad, rad*2, rad*2,
+                   ((start+off-oth))%(360*64),
+                   -(th-oth));
+
+          off += max + max;
+          XFillArc(dpy, window, gc,
+                   (width/2)-rad, (height/2)-rad, rad*2, rad*2,
+                   (start+off+oth)%(360*64),
+                   (th-oth));
+          XFillArc(dpy, window, gc,
+                   (width/2)-rad, (height/2)-rad, rad*2, rad*2,
+                   ((start+off-oth))%(360*64),
+                   -(th-oth));
+
+          hits++;
+          XSync (dpy, False);
+        }
 
-      XSync (dpy, False);
-      usleep (delay*granularity);
+      oth = th;
+      tick = millitime();
     }
 }
 
 
 static void
 squaretate (Display *dpy, Window window, GC gc,
-           int width, int height, int delay, int granularity)
+           int width, int height, int total_msecs)
 {
-  int steps = (((width > height ? width : width) * 2) / granularity);
-  int i;
+  int max = ((width > height ? width : width) * 2);
+  int oi = -1;
   Bool flip = random() & 1;
 
+  unsigned long start_tick = millitime();
+  unsigned long end_tick = start_tick + total_msecs;
+  unsigned long tick = start_tick;
+  int hits = 0;
+  int nonhits = 0;
+
 #define DRAW() \
       if (flip) { \
        points[0].x = width-points[0].x; \
@@ -246,45 +425,56 @@ squaretate (Display *dpy, Window window, GC gc,
         points[2].x = width-points[2].x; } \
       XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin)
 
-  for (i = 0; i < steps; i++)
+  while (tick < end_tick)
     {
-      XPoint points [3];
-      points[0].x = 0;
-      points[0].y = 0;
-      points[1].x = width;
-      points[1].y = 0;
-      points[2].x = 0;
-      points[2].y = points[0].y + ((i * height) / steps);
-      DRAW();
-
-      points[0].x = 0;
-      points[0].y = 0;
-      points[1].x = 0;
-      points[1].y = height;
-      points[2].x = ((i * width) / steps);
-      points[2].y = height;
-      DRAW();
-
-      points[0].x = width;
-      points[0].y = height;
-      points[1].x = 0;
-      points[1].y = height;
-      points[2].x = width;
-      points[2].y = height - ((i * height) / steps);
-      DRAW();
-
-      points[0].x = width;
-      points[0].y = height;
-      points[1].x = width;
-      points[1].y = 0;
-      points[2].x = width - ((i * width) / steps);
-      points[2].y = 0;
-      DRAW();
-
-      XSync (dpy, True);
-      if (delay > 0)
-       usleep (delay * granularity);
-   }
+      int i = (max * (tick - start_tick)) / (end_tick - start_tick);
+
+      if (i == oi)
+        {
+          usleep (LITTLE_NAP);
+          nonhits++;
+        }
+      else
+        {
+          XPoint points [3];
+          points[0].x = 0;
+          points[0].y = 0;
+          points[1].x = width;
+          points[1].y = 0;
+          points[2].x = 0;
+          points[2].y = points[0].y + ((i * height) / max);
+          DRAW();
+
+          points[0].x = 0;
+          points[0].y = 0;
+          points[1].x = 0;
+          points[1].y = height;
+          points[2].x = ((i * width) / max);
+          points[2].y = height;
+          DRAW();
+
+          points[0].x = width;
+          points[0].y = height;
+          points[1].x = 0;
+          points[1].y = height;
+          points[2].x = width;
+          points[2].y = height - ((i * height) / max);
+          DRAW();
+
+          points[0].x = width;
+          points[0].y = height;
+          points[1].x = width;
+          points[1].y = 0;
+          points[2].x = width - ((i * width) / max);
+          points[2].y = 0;
+          DRAW();
+          hits++;
+          XSync (dpy, True);
+        }
+
+      oi = i;
+      tick = millitime();
+    }
 #undef DRAW
 }
 
@@ -292,19 +482,29 @@ squaretate (Display *dpy, Window window, GC gc,
 /* from Frederick Roeber <roeber@netscape.com> */
 static void
 fizzle (Display *dpy, Window window, GC gc,
-           int width, int height, int delay, int granularity)
+        int width, int height, int total_msecs)
 {
   /* These dimensions must be prime numbers.  They should be roughly the
      square root of the width and height. */
-# define BX 31
+# define BX 41
 # define BY 31
 # define SIZE (BX*BY)
 
   int array[SIZE];
   int i, j;
+  int oi = -1;
   XPoint *skews;
+  XPoint points[250];
+  int npoints = 0;
   int nx, ny;
 
+  unsigned long start_tick = millitime();
+  unsigned long end_tick = (start_tick +
+                            (2.5 * total_msecs));  /* this one needs more */
+  unsigned long tick = start_tick;
+  int hits = 0;
+  int nonhits = 0;
+
   /* Distribute the numbers [0,SIZE) randomly in the array */
   {
     int indices[SIZE];
@@ -337,66 +537,91 @@ fizzle (Display *dpy, Window window, GC gc,
 # define SKEWX(cx, cy) (((XPoint *)0 == skews)?0:skews[cy*nx + cx].x)
 # define SKEWY(cx, cy) (((XPoint *)0 == skews)?0:skews[cy*nx + cx].y)
 
-  for( i = 0; i < SIZE; i++ ) {
-    int x = array[i] % BX;
-    int y = array[i] / BX;
-
+  while (tick < end_tick)
     {
-      int iy, cy;
-      for( iy = 0, cy = 0; iy < height; iy += BY, cy++ ) {
-        int ix, cx;
-        for( ix = 0, cx = 0; ix < width; ix += BX, cx++ ) {
-          int xx = ix + (SKEWX(cx, cy) + x*((cx%(BX-1))+1))%BX;
-          int yy = iy + (SKEWY(cx, cy) + y*((cy%(BY-1))+1))%BY;
-          if (xx < width && yy < height)
-            XDrawPoint(dpy, window, gc, xx, yy);
+      int i = (SIZE * (tick - start_tick)) / (end_tick - start_tick);
+
+      if (i == oi)
+        {
+          usleep (LITTLE_NAP);
+          nonhits++;
         }
-      }
+      else
+        {
+          int j;
+          for (j = oi; j < i; j++)
+            {
+              int x = array[j] % BX;
+              int y = array[j] / BX;
+              int iy, cy;
+              for (iy = 0, cy = 0; iy < height; iy += BY, cy++)
+                {
+                  int ix, cx;
+                  for( ix = 0, cx = 0; ix < width; ix += BX, cx++ ) {
+                    int xx = ix + (SKEWX(cx, cy) + x*((cx%(BX-1))+1))%BX;
+                    int yy = iy + (SKEWY(cx, cy) + y*((cy%(BY-1))+1))%BY;
+                    if (xx < width && yy < height)
+                      {
+                        points[npoints].x = xx;
+                        points[npoints].y = yy;
+                        if (++npoints == countof(points))
+                          {
+                            XDrawPoints(dpy, window, gc, points, npoints,
+                                        CoordModeOrigin);
+                            XSync (dpy, False);
+                            npoints = 0;
+                          }
+                      }
+                  }
+                }
+            }
+          hits++;
+        }
+
+      oi = i;
+      tick = millitime();
     }
 
-    if( (BX-1) == (i%BX) ) {
+  if (npoints > 100)
+    {
+      XDrawPoints(dpy, window, gc, points, npoints, CoordModeOrigin);
       XSync (dpy, False);
-      usleep (delay*granularity);
+      usleep (10000);
     }
-  }
 
 # undef SKEWX
 # undef SKEWY
-
-  if( (XPoint *)0 != skews ) {
-    free(skews);
-  }
-
 # undef BX
 # undef BY
 # undef SIZE
+
+  if (skews) free(skews);
 }
 
 
 /* from Rick Campbell <rick@campbellcentral.org> */
 static void
-spiral (Display *display, Window window, GC context,
-        int width, int height, int delay, int granularity)
+spiral (Display *dpy, Window window, GC context,
+        int width, int height, int total_msecs)
 {
-# define SPIRAL_ERASE_PI_2 (M_PI + M_PI)
-# define SPIRAL_ERASE_LOOP_COUNT (10)
-# define SPIRAL_ERASE_ARC_COUNT (360.0)
-# define SPIRAL_ERASE_ANGLE_INCREMENT (SPIRAL_ERASE_PI_2 /     \
-SPIRAL_ERASE_ARC_COUNT)
-# define SPIRAL_ERASE_DELAY (0)
+  int granularity = 1; /* #### */
 
+  double pi2 = (M_PI + M_PI);
+  int loop_count = 10;
+  int angle_step = 1000 / 8;  /* disc granularity is 8 degrees */
+  int max = pi2 * angle_step;
   double angle;
   int arc_limit;
   int arc_max_limit;
   int length_step;
   XPoint points [3];
 
+  total_msecs *= 2.5;  /* this one needs more */
+
   angle = 0.0;
   arc_limit = 1;
-  arc_max_limit = (int) (ceil (sqrt ((width * width) + (height * height)))
-                         / 2.0);
-  length_step = ((arc_max_limit + SPIRAL_ERASE_LOOP_COUNT - 1) /
-                 SPIRAL_ERASE_LOOP_COUNT);
+  arc_max_limit = (ceil (sqrt ((width * width) + (height * height))) / 2.0);
+  length_step = ((arc_max_limit + loop_count - 1) / loop_count);
   arc_max_limit += length_step;
   points [0].x = width / 2;
   points [0].y = height / 2;
@@ -411,27 +636,65 @@ SPIRAL_ERASE_ARC_COUNT)
     {
       int arc_length = length_step;
       int length_base = arc_limit;
-      for (angle = 0.0; angle < SPIRAL_ERASE_PI_2;
-           angle += SPIRAL_ERASE_ANGLE_INCREMENT)
+
+      unsigned long start_tick = millitime();
+      unsigned long end_tick = start_tick + (total_msecs /
+                                             (arc_max_limit / length_step));
+      unsigned long tick = start_tick;
+      int hits = 0;
+      int nonhits = 0;
+      int i = 0;
+      int oi = -1;
+
+#if 0
+      int max2 = max / granularity;
+      while (i < max2)
+#else
+      while (tick < end_tick)
+#endif
         {
-          arc_length = length_base + ((length_step * angle) /
-                                      SPIRAL_ERASE_PI_2);
-          points [1].x = points [2].x;
-          points [1].y = points [2].y;
-          points [2].x = points [0].x + (int)(cos (angle) * arc_length);
-          points [2].y = points [0].y + (int)(sin (angle) * arc_length);
-          XFillPolygon (display, window, context, points, 3, Convex,
-                        CoordModeOrigin);
-# if (SPIRAL_ERASE_DELAY != 0)
-          usleep (SPIRAL_ERASE_DELAY);
-# endif /* (SPIRAL_ERASE_DELAY != 0) */
+          i = (max * (tick - start_tick)) / (end_tick - start_tick);
+          if (i > max) i = max;
+
+          i /= granularity;
+
+          if (i == oi)
+            {
+              usleep (LITTLE_NAP);
+              nonhits++;
+            }
+          else
+            {
+              int j, k;
+#if 0
+              for (k = oi; k <= i; k++)
+#else
+              k = i;
+#endif
+                {
+                  for (j = 0; j < granularity; j++)
+                    {
+                      int ii = k * granularity + j;
+                      angle = ii / (double) angle_step;
+                      arc_length = length_base + ((length_step * angle) / pi2);
+                      points [1].x = points [2].x;
+                      points [1].y = points [2].y;
+                      points [2].x = points [0].x +
+                        (int)(cos(angle) * arc_length);
+                      points [2].y = points [0].y +
+                        (int)(sin(angle) * arc_length);
+                      XFillPolygon (dpy, window, context, points, 3, Convex,
+                                    CoordModeOrigin);
+                      hits++;
+                    }
+                }
+              XSync (dpy, False);
+            }
+
+          oi = i;
+          tick = millitime();
         }
     }
-# undef SPIRAL_ERASE_DELAY
-# undef SPIRAL_ERASE_ANGLE_INCREMENT
-# undef SPIRAL_ERASE_ARC_COUNT
-# undef SPIRAL_ERASE_LOOP_COUNT
-# undef SPIRAL_ERASE_PI_2
 }
 
 
@@ -443,14 +706,23 @@ SPIRAL_ERASE_ARC_COUNT)
 /* from David Bagley <bagleyd@tux.org> */
 static void
 random_squares(Display * dpy, Window window, GC gc,
-               int width, int height, int delay, int granularity)
+               int width, int height, int total_msecs)
 {
+  int granularity = 20;
+
   int randsize = MAX(1, MIN(width, height) / (16 + (random() % 32)));
   int max = (height / randsize + 1) * (width / randsize + 1);
   int *squares = (int *) calloc(max, sizeof (*squares));
   int i;
   int columns = width / randsize + 1;  /* Add an extra for roundoff */
 
+  int oi = -1;
+  unsigned long start_tick = millitime();
+  unsigned long end_tick = start_tick + total_msecs;
+  unsigned long tick = start_tick;
+  int hits = 0;
+  int nonhits = 0;
+
   for (i = 0; i < max; i++)
     squares[i] = i;
 
@@ -463,16 +735,35 @@ random_squares(Display * dpy, Window window, GC gc,
       squares[r] = t;
     }
 
-  for (i = 0; i < max; i++)
+  while (tick < end_tick)
     {
-      XFillRectangle(dpy, window, gc,
-                    (squares[i] % columns) * randsize,
-                    (squares[i] / columns) * randsize,
-                    randsize, randsize);
-
-      XSync(dpy, False);
-      if (delay > 0 && ((i % granularity) == 0))
-      usleep(delay * granularity);
+      int i = (max * (tick - start_tick)) / (end_tick - start_tick);
+
+      i /= granularity;
+
+      if (i == oi)
+        {
+          usleep (LITTLE_NAP);
+          nonhits++;
+        }
+      else
+        {
+          int j;
+          for (j = 0; j < granularity; j++)
+            {
+              int ii = i * granularity + j;
+
+              XFillRectangle(dpy, window, gc,
+                             (squares[ii] % columns) * randsize,
+                             (squares[ii] / columns) * randsize,
+                             randsize, randsize);
+              hits++;
+            }
+        }
+      XSync (dpy, False);
+
+      oi = i;
+      tick = millitime();
     }
   free(squares);
 }
@@ -481,51 +772,281 @@ random_squares(Display * dpy, Window window, GC gc,
    implementation for the Mac.
     -- Torbjörn Andersson <torbjorn@dev.eurotime.se>
  */
+static void
+slide_lines (Display *dpy, Window window, GC gc,
+             int width, int height, int total_msecs)
+{
+  int max = width;
+  int dy = MAX (10, height/40);
+
+  int oi = 0;
+  unsigned long start_tick = millitime();
+  unsigned long end_tick = start_tick + total_msecs;
+  unsigned long tick = start_tick;
+  int hits = 0;
+  int nonhits = 0;
+
+  while (tick < end_tick)
+    {
+      int i = (max * (tick - start_tick)) / (end_tick - start_tick);
 
+      if (i == oi)
+        {
+          usleep (LITTLE_NAP);
+          nonhits++;
+        }
+      else
+        {
+          int y;
+          int tick = 0;
+          int from1 = oi;
+          int to1 = i;
+          int w = width-to1;
+          int from2 = width - oi - w;
+          int to2 = width - i - w;
+
+          for (y = 0; y < height; y += dy)
+            {
+              if (++tick & 1)
+                {
+                  XCopyArea (dpy, window, window, gc, from1, y, w, dy, to1, y);
+                  XFillRectangle (dpy, window, gc, from1, y, to1-from1, dy);
+                }
+              else
+                {
+                  XCopyArea (dpy, window, window, gc, from2, y, w, dy, to2, y);
+                  XFillRectangle (dpy, window, gc, from2+w, y, to2-from2, dy);
+                }
+            }
+
+          hits++;
+          XSync (dpy, False);
+        }
+
+      oi = i;
+      tick = millitime();
+    }
+}
+
+
+/* from Frederick Roeber <roeber@xigo.com> */
 static void
-slide_lines (Display * dpy, Window window, GC gc, int width, int height,
-             int delay, int granularity)
+losira (Display * dpy, Window window, GC gc,
+        int width, int height, int total_msecs)
 {
-  int slide_old_x, slide_new_x, clear_x;
-  int x, y, dx, dy;
+  XGCValues gcv;
+  XWindowAttributes wa;
+  XColor white;
+  GC white_gc; 
+  XArc arc[2][8];
+  double xx[8], yy[8], dx[8], dy[8];
+
+  int i;
+  int oi = 0;
+
+  int max = width/2;
+  int max_off = MAX(1, max / 12);
+
+  int msecs1 = (0.55 * total_msecs);
+  int msecs2 = (0.30 * total_msecs);
+  int msecs3 = (0.15 * total_msecs);
+
+  unsigned long start_tick = millitime();
+  unsigned long end_tick = start_tick + msecs1;
+  unsigned long tick = start_tick;
+  int hits = 0;
+  int nonhits = 0;
+
+  XGetWindowAttributes(dpy, window, &wa);
+  white.flags = DoRed|DoGreen|DoBlue;
+  white.red = white.green = white.blue = 65535;
+  XAllocColor(dpy, wa.colormap, &white);
+  gcv.foreground = white.pixel;
+  white_gc = XCreateGC(dpy, window, GCForeground, &gcv);
+
+  /* Squeeze in from the sides */
+  while (tick < end_tick)
+    {
+      int i = (max * (tick - start_tick)) / (end_tick - start_tick);
+
+      if (i == oi)
+        {
+          usleep (LITTLE_NAP);
+          nonhits++;
+        }
+      else
+        {
+          int off = (max_off * (tick - start_tick)) / (end_tick - start_tick);
+
+          int from1 = oi;
+          int to1 = i;
+          int w = max - to1 - off/2 + 1;
+          int from2 = max+(to1-from1)+off/2;
+          int to2 = max+off/2;
+
+          if (w < 0)
+            break;
+
+          XCopyArea (dpy, window, window, gc, from1, 0, w, height, to1, 0);
+          XCopyArea (dpy, window, window, gc, from2, 0, w, height, to2, 0);
+          XFillRectangle (dpy, window, gc, from1, 0, (to1-from1), height);
+          XFillRectangle (dpy, window, gc, to2+w, 0, from2+w,     height);
+          XFillRectangle (dpy, window, white_gc, max-off/2, 0, off, height);
+          hits++;
+          XSync(dpy, False);
+        }
+
+      oi = i;
+      tick = millitime();
+    }
+
+
+  XFillRectangle(dpy, window, white_gc, max-max_off/2, 0, max_off, height);
+
+  /* Cap the top and bottom of the line */
+  XFillRectangle(dpy, window, gc, max-max_off/2, 0, max_off, max_off/2);
+  XFillRectangle(dpy, window, gc, max-max_off/2, height-max_off/2,
+                 max_off, max_off/2);
+  XFillArc(dpy, window, white_gc, max-max_off/2-1, 0,
+           max_off-1, max_off-1, 0, 180*64);
+  XFillArc(dpy, window, white_gc, max-max_off/2-1, height-max_off,
+           max_off-1, max_off-1,
+           180*64, 360*64);
+
+  XFillRectangle(dpy, window, gc, 0,               0, max-max_off/2, height);
+  XFillRectangle(dpy, window, gc, max+max_off/2-1, 0, max-max_off/2, height);
+  XSync(dpy, False);
+
+  /* Collapse vertically */
+  start_tick = millitime();
+  end_tick = start_tick + msecs2;
+  tick = start_tick;
+
+  max = height/2;
+  oi = 0;
+  while (tick < end_tick)
+    {
+      int i = (max * (tick - start_tick)) / (end_tick - start_tick);
+      int x = (width-max_off)/2;
+      int w = max_off;
+
+      if (i == oi)
+        {
+          usleep (LITTLE_NAP);
+          nonhits++;
+        }
+      else
+        {
+          int off = (max_off * (tick - start_tick)) / (end_tick - start_tick);
+
+          int from1 = oi;
+          int to1 = i;
+          int h = max - to1 - off/2;
+          int from2 = max+(to1-from1)+off/2;
+          int to2 = max+off/2;
+
+          if (h < max_off/2)
+            break;
+
+          XCopyArea (dpy, window, window, gc, x, from1, w, h, x, to1);
+          XCopyArea (dpy, window, window, gc, x, from2, w, h, x, to2);
+          XFillRectangle(dpy, window, gc, x, from1, w, (to1 - from1));
+          XFillRectangle(dpy, window, gc, x, to2+h, w, (to2 - from2));
+          hits++;
+          XSync(dpy, False);
+        }
+
+      oi = i;
+      tick = millitime();
+    }
+
+  /* "This is Sci-Fi" */
+  for( i = 0; i < 8; i++ ) {
+    arc[0][i].width = arc[0][i].height = max_off;
+    arc[1][i].width = arc[1][i].height = max_off;
+    arc[0][i].x = arc[1][i].x = width/2;
+    arc[0][i].y = arc[1][i].y = height/2;
+    xx[i] = (double)(width/2)  - max_off/2;
+    yy[i] = (double)(height/2) - max_off/2;
+  }
+
+  arc[0][0].angle1 = arc[1][0].angle1 =   0*64; arc[0][0].angle2 = arc[1][0].angle2 =  45*64;
+  arc[0][1].angle1 = arc[1][1].angle1 =  45*64; arc[0][1].angle2 = arc[1][1].angle2 =  45*64;
+  arc[0][2].angle1 = arc[1][2].angle1 =  90*64; arc[0][2].angle2 = arc[1][2].angle2 =  45*64;
+  arc[0][3].angle1 = arc[1][3].angle1 = 135*64; arc[0][3].angle2 = arc[1][3].angle2 =  45*64;
+  arc[0][4].angle1 = arc[1][4].angle1 = 180*64; arc[0][4].angle2 = arc[1][4].angle2 =  45*64;
+  arc[0][5].angle1 = arc[1][5].angle1 = 225*64; arc[0][5].angle2 = arc[1][5].angle2 =  45*64;
+  arc[0][6].angle1 = arc[1][6].angle1 = 270*64; arc[0][6].angle2 = arc[1][6].angle2 =  45*64;
+  arc[0][7].angle1 = arc[1][7].angle1 = 315*64; arc[0][7].angle2 = arc[1][7].angle2 =  45*64;
+  
+  for( i = 0; i < 8; i++ ) {
+    dx[i] =  cos((i*45 + 22.5)/360 * 2*M_PI);
+    dy[i] = -sin((i*45 + 22.5)/360 * 2*M_PI);
+  }
 
-  /* This might need some tuning. The idea is to get sensible values no
-     matter what the size of the window.
+  gcv.line_width = 3;  
+  XChangeGC(dpy, gc, GCLineWidth, &gcv);
 
-     Everything moves at constant speed. Should it accelerate instead? */
+  XClearWindow (dpy, window);
+  XFillArc(dpy, window, white_gc,
+           width/2-max_off/2-1, height/2-max_off/2-1,
+           max_off-1, max_off-1,
+           0, 360*64);
+  XDrawLine(dpy, window, gc, 0, height/2-1, width, height/2-1);
+  XDrawLine(dpy, window, gc, width/2-1, 0, width/2-1, height);
+  XDrawLine(dpy, window, gc, width/2-1-max_off, height/2-1-max_off,
+            width/2+max_off, height/2+max_off);
+  XDrawLine(dpy, window, gc, width/2+max_off, height/2-1-max_off,
+            width/2-1-max_off, height/2+max_off);
 
-  granularity *= 2;
+  XSync(dpy, False);
 
-  dy = MAX (1, height / granularity);
-  dx = MAX (1, width / 100);
 
-  for (x = 0; x < width; x += dx)
+  /* Fan out */
+  start_tick = millitime();
+  end_tick = start_tick + msecs3;
+  tick = start_tick;
+  oi = 0;
+  while (tick < end_tick)
     {
-      for (y = 0; y < height; y += dy)
-       {
-         if ((y / dy) & 1)
-           {
-             slide_old_x = x;
-             slide_new_x = x + dx;
-             clear_x = x;
-           }
-         else
-           {
-             slide_old_x = dx;
-             slide_new_x = 0;
-             clear_x = width - x - dx;
-           }
-
-         XCopyArea (dpy, window, window, gc, slide_old_x, y, width - x - dx,
-                    dy, slide_new_x, y);
-         XClearArea (dpy, window, clear_x, y, dx, dy, False);
-       }
-
-      XSync(dpy, False);
-      usleep(delay * 3);
+      int i = (max_off * (tick - start_tick)) / (end_tick - start_tick);
+
+      if (i == oi)
+        {
+          usleep (LITTLE_NAP);
+          nonhits++;
+        }
+      else
+        {
+          int j;
+          for (j = 0; j < 8; j++)
+            {
+              xx[j] += 2*dx[j];
+              yy[j] += 2*dy[j];
+              arc[(i+1)%2][j].x = xx[j];
+              arc[(i+1)%2][j].y = yy[j];
+            }
+
+          XFillRectangle (dpy, window, gc,
+                          (width-max_off*5)/2, (height-max_off*5)/2,
+                          max_off*5, max_off*5);
+          XFillArcs(dpy, window, white_gc, arc[(i+1)%2], 8);
+          XSync(dpy, False);
+          hits++;
+        }
+
+      oi = i;
+      tick = millitime();
     }
+  
+  XSync (dpy, False);
+
+  /*XFreeColors(dpy, wa.colormap, &white.pixel, 1, 0);*/
+  XFreeGC(dpy, white_gc);
 }
 
+
+
 static Eraser erasers[] = {
   random_lines,
   venetian,
@@ -535,23 +1056,32 @@ static Eraser erasers[] = {
   three_circle_wipe,
   squaretate,
   fizzle,
-  random_squares,
   spiral,
+  random_squares,
   slide_lines,
+  losira,
 };
 
 
-void
-erase_window(Display *dpy, Window window, GC gc,
-            int width, int height, int mode, int delay)
+static void
+erase_window (Display *dpy, Window window, GC gc,
+              int width, int height, int mode, int total_msecs)
 {
-  int granularity = 25;
+  Bool verbose_p = False;
+  unsigned long start = millitime();
 
   if (mode < 0 || mode >= countof(erasers))
     mode = random() % countof(erasers);
-  (*(erasers[mode])) (dpy, window, gc, width, height, delay, granularity);
+
+  (*(erasers[mode])) (dpy, window, gc, width, height, total_msecs);
+
+  if (verbose_p)
+    fprintf(stderr, "%s: eraser %d time: %4.2f sec\n",
+            progname, mode, (millitime() - start) / 1000.0);
+
   XClearWindow (dpy, window);
   XSync(dpy, False);
+  usleep (333333);  /* 1/3 sec */
 }
 
 
@@ -562,14 +1092,18 @@ erase_full_window(Display *dpy, Window window)
   XGCValues gcv;
   GC erase_gc;
   XColor black;
-  int erase_speed, erase_mode;
+  int erase_msecs, erase_mode;
   char *s;
 
-  s = get_string_resource("eraseSpeed", "Integer");
+  s = get_string_resource("eraseSeconds", "Integer");
   if (s && *s)
-    erase_speed = get_integer_resource("eraseSpeed", "Integer");
+    erase_msecs = 1000 * get_float_resource("eraseSeconds", "Float");
   else
-    erase_speed = 400;
+    erase_msecs = 1000;
+
+  if (erase_msecs < 10 || erase_msecs > 10000)
+    erase_msecs = 1000;
+
   if (s) free(s);
 
   s = get_string_resource("eraseMode", "Integer");
@@ -586,51 +1120,7 @@ erase_full_window(Display *dpy, Window window)
   gcv.foreground = black.pixel;
   erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
   erase_window (dpy, window, erase_gc, xgwa.width, xgwa.height,
-               erase_mode, erase_speed);
+               erase_mode, erase_msecs);
   XFreeColors(dpy, xgwa.colormap, &black.pixel, 1, 0);
   XFreeGC(dpy, erase_gc);
 }
-
-
-\f
-#if 0
-#include "screenhack.h"
-
-char *progclass = "Erase";
-char *defaults [] = {
-  0
-};
-
-XrmOptionDescRec options [] = {{0}};
-int options_size = 0;
-
-void
-screenhack (dpy, window)
-     Display *dpy;
-     Window window;
-{
-  int delay = 500000;
-  XGCValues gcv;
-  GC gc;
-  XColor white;
-  XWindowAttributes xgwa;
-  XGetWindowAttributes (dpy, window, &xgwa);
-  white.flags = DoRed|DoGreen|DoBlue;
-  white.red = white.green = white.blue = 0xFFFF;
-  XAllocColor(dpy, xgwa.colormap, &white);
-  gcv.foreground = white.pixel;
-  gc = XCreateGC (dpy, window, GCForeground, &gcv);
-
-  while (1)
-    {
-      XFillRectangle(dpy, window, gc, 0, 0, 1280, 1024);
-      XSync (dpy, False);
-      usleep (delay);
-      erase_full_window(dpy, window);
-      XSync (dpy, False);
-      usleep (delay);
-
-    }
-}
-
-#endif
index 2f00d3e1ae3caf6aa8f4a49c459da550cffd7070..d161d2ebfeedf4b84219b429243c10561102483a 100644 (file)
@@ -1,15 +1,18 @@
 /* erase.c: Erase the screen in various more or less interesting ways.
- * (c) 1997 by Johannes Keukelaar <johannes@nada.kth.se>
- * Permission to use in any way granted. Provided "as is" without expressed
- * or implied warranty. NO WARRANTY, NO EXPRESSION OF SUITABILITY FOR ANY
- * PURPOSE. (I.e.: Use in any way, but at your own risk!)
+ * Copyright (c) 1997-2001 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
  */
 
 #ifndef __XSCREENSAVER_ERASE_H__
 #define __XSCREENSAVER_ERASE_H__
 
-extern void erase_window(Display *dpy, Window window, GC gc,
-                        int width, int height, int mode, int delay);
 extern void erase_full_window(Display *dpy, Window window);
 
 #endif /* __XSCREENSAVER_ERASE_H__ */
index 7277fd03b87fa09ceccdee98b8b0cc92bf15a3b5..8569903846d9b5d123e373eef07f0d47eb143377 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1997 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1997, 2001 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
 /* If the server's root window contains a SERVER_OVERLAY_VISUALS property,
    then that identifies the visuals which correspond to the video hardware's
    overlay planes.  Windows created in these kinds of visuals have the
-   property that one particular pixel value is transparent.
+   property that one or more particular pixel values is transparent.
+
+   Vendor support:
+
+    SGI:  - Supported on all systems since IRIX 4.0.
+          - Their version of the Motif toolkit renders menus into the overlay
+            visual, so that they don't cause exposure events on occluded
+            windows.
+          - 2 bit overlay plane with Indigo Entry graphics (e.g., Indy).
+          - 8 bit overlay on O2 with Indigo 24 graphics or better (e.g., O2).
+
+    HP:   - Supported on workstations with CRX24 and CRX48Z graphics hardware.
+          - 8 bit or 24 bit overlay plane.
+          - The default visual is the overlay visual, with a transparent pixel.
+            That way, all Xlib programs draw into the overlay plane, and no
+            Xlib program causes exposures on occluded OpenGL windows.
+
+    IBM:  - Supported on some graphics hardware (which?)
+
+    DEC:  - Supported on some graphics hardware (which?)
+
+    SUN:  - Some systems apparently implement it VERRRRRRY SLOWLY, so drawing
+            into the overlay plane is a performance killer (about as bad as
+            using the SHAPE extension.)
+
 
    On my Indy, there are two transparent visuals, one of which is at layer 1,
    and one of which is at layer 2.  This is apparently the ordering in which
    they are overlayed (1 being topmost.)  The other difference between them
    is that the topmost one only has 2 planes, while the next one has 8.
 
-   Rumor has it that SGI, HP, DEC, and IBM all use the same mechanism.
-   Does Sun?
-
    This code selects the topmost one, regardless of depth.  Maybe that's not
    the right thing.  Well, in XScreenSaver, we only need to allocate two
    colors from it (it's only used to display the stderr output, so that the
@@ -31,7 +52,6 @@
 
      http://www.hp.com/xwindow/sharedInfo/Whitepapers/Visuals/server_overlay_visuals.html
     http://www.xig.com/Pages/Ed-Overlays.html
-
  */
 
 
 struct overlay_data
 {
   CARD32 visual_id;
-  CARD32 transparency; /* 0: none; 1: pixel; 2: mask (?) */
-  CARD32 value;                /* the transparent pixel */
+  CARD32 transparency; /* 0: none; 1: pixel; 2: mask
+                           ("mask" means "any pixel with these bits set
+                           is a transparent pixel")
+                         */
+  CARD32 value;                /* the transparent pixel or mask */
   CARD32 layer;                /* -1: underlay; 0: normal; 1: popup; 2: overlay */
 };
 
@@ -101,8 +124,9 @@ get_overlay_visual (Screen *screen, unsigned long *transparent_pixel_ret)
   if (data)
     for (i = 0; i < n_visuals; i++)
 
-      /* Only accept ones that have a transparent pixel. */
-      if (data[i].transparency == 1)
+      /* Only accept ones that have a transparent pixel or mask. */
+      if (data[i].transparency == 1 ||
+          data[i].transparency == 2)
        {
          XVisualInfo vi_in, *vi_out;
          int out_count;
index 4de0984d902af17bc877c23ba7459d70f46544a7..3889f5f5f25fc8d461f5d286d2deea76cf4bc5ec 100644 (file)
@@ -1,2 +1,2 @@
 static const char screensaver_id[] =
-       "@(#)xscreensaver 3.32 (14-Apr-2001), by Jamie Zawinski (jwz@jwz.org)";
+       "@(#)xscreensaver 3.33 (19-May-2001), by Jamie Zawinski (jwz@jwz.org)";
index debc1baee77211cabf76edfe4ad7048d55f8b944..1b02f7b012da6b6ae2bb183b1918d8234efb7c9d 100644 (file)
@@ -1,30 +1,30 @@
 Begin3
 Title:          xscreensaver
-Version:        3.32
-Entered-date:   15APR01
+Version:        3.33
+Entered-date:   03JUN01
 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.
-                Comes with more than 100 display modes.
+                More than 120 display modes are included in this package.
 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/
-                1602K xscreensaver-3.32.tar.gz
-                47K  xscreensaver.README
-                1K   xscreensaver.lsm
+                1630K xscreensaver-3.33.tar.gz
+                49K   xscreensaver.README
+                1K    xscreensaver.lsm
 Alternate-site: sunsite.unc.edu /pub/Linux/X11/screensavers/
-                1602K xscreensaver-3.32.tar.gz
-                47K  xscreensaver.README
-                1K   xscreensaver.lsm
+                1630K xscreensaver-3.33.tar.gz
+                49K   xscreensaver.README
+                1K    xscreensaver.lsm
 Alternate-site: ftp.x.org /contrib/applications/
-                1602K xscreensaver-3.32.tar.gz
-                47K  xscreensaver.README
-                1K   xscreensaver.lsm
+                1630K xscreensaver-3.33.tar.gz
+                49K   xscreensaver.README
+                1K    xscreensaver.lsm
 Platforms:      Linux, Irix, SunOS, Solaris, HPUX, AIX, FreeBSD, NetBSD,
                 BSDI, SCO, OSF1, Ultrix, VMS.
                 Requires X11 and ANSI C.
-                Works with Motif or Athena.
+                Works with GTK+, GNOME, and/or Motif.
                 Shadow passwords, Kerberos, and OpenGL optionally supported.
                 Multi-headed machines supported.
 Copying-policy: BSD
index b3126f0a1b2fe32609a4e9ea9e8e7839bfb18ddc..fc1103f9b399de23d339f6a4df701e9d84ee51f9 100755 (executable)
@@ -11,15 +11,14 @@ size() {
     sed 's/[0-9][0-9][0-9]$/K/'
 }
 
-TAR_SIZE=`size xscreensaver-*.gz`
-README_SIZE=`size README`
-#LSM_SIZE=`size xscreensaver.lsm`
-LSM_SIZE="1K"
-
 VERSION=`sed -n 's/.*\([0-9][0-9]*\.[0-9]*\).*/\1/p' < utils/version.h`
 DATE=`date '+%d%b%y' | tr a-z A-Z`
 
-#URL=`sed -n 's/\(http:[^ ]*\)/\1/p' < README | sed 's/[^a-zA-Z/]$//'`
+ADIR=archive/
+TAR_SIZE=`size ${ADIR}xscreensaver-$VERSION.tar.gz`
+README_SIZE=`size README`
+#LSM_SIZE=`size xscreensaver.lsm`
+LSM_SIZE="1K"
 
 echo "Begin3
 Title:          xscreensaver
@@ -28,26 +27,26 @@ Entered-date:   $DATE
 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.
-                Comes with more than 100 display modes.
+                More than 120 display modes are included in this package.
 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/
                 $TAR_SIZE xscreensaver-$VERSION.tar.gz
-                $README_SIZE  xscreensaver.README
-                $LSM_SIZE   xscreensaver.lsm
+                $README_SIZE   xscreensaver.README
+                $LSM_SIZE    xscreensaver.lsm
 Alternate-site: sunsite.unc.edu /pub/Linux/X11/screensavers/
                 $TAR_SIZE xscreensaver-$VERSION.tar.gz
-                $README_SIZE  xscreensaver.README
-                $LSM_SIZE   xscreensaver.lsm
+                $README_SIZE   xscreensaver.README
+                $LSM_SIZE    xscreensaver.lsm
 Alternate-site: ftp.x.org /contrib/applications/
                 $TAR_SIZE xscreensaver-$VERSION.tar.gz
-                $README_SIZE  xscreensaver.README
-                $LSM_SIZE   xscreensaver.lsm
+                $README_SIZE   xscreensaver.README
+                $LSM_SIZE    xscreensaver.lsm
 Platforms:      Linux, Irix, SunOS, Solaris, HPUX, AIX, FreeBSD, NetBSD,
                 BSDI, SCO, OSF1, Ultrix, VMS.
                 Requires X11 and ANSI C.
-                Works with Motif or Athena.
+                Works with GTK+, GNOME, and/or Motif.
                 Shadow passwords, Kerberos, and OpenGL optionally supported.
                 Multi-headed machines supported.
 Copying-policy: BSD
index fd75dbe02199977a82aec41f5584694685644704..8933255dfeaba43ae48457f9fee634e5b09812fb 100644 (file)
@@ -1,5 +1,5 @@
 %define        name            xscreensaver
-%define        version         3.32
+%define        version         3.33
 %define        release         1
 %define        serial          1
 %define        x11_prefix      /usr/X11R6
@@ -76,6 +76,7 @@ RPMOPTS=""
 CFLAGS="$RPM_OPT_FLAGS" \
  ./configure --prefix=%{x11_prefix} \
              --enable-subdir=../lib/xscreensaver \
+             --with-zippy=/usr/games/fortune \
              --without-setuid-hacks \
              $RPMOPTS
 
@@ -122,7 +123,7 @@ list_files() {
 }
 
 ( cd hacks ; list_files install ; \
-  cd ../driver; list_files install-program ) \
+  cd ../driver; list_files install-program install-scripts ) \
    > $RPM_BUILD_DIR/xscreensaver-%{version}/exes-non-gl
 ( cd hacks/glx ; list_files install ) \
    > $RPM_BUILD_DIR/xscreensaver-%{version}/exes-gl