From 3c58fb6311db49c46f1670922933b27c6ea0c065 Mon Sep 17 00:00:00 2001 From: Zygo Blaxell Date: Mon, 2 Mar 2009 00:42:47 -0500 Subject: [PATCH] ftp://updates.redhat.com/enterprise/2.1AS/en/os/SRPMS/xscreensaver-3.33-4.rhel21.5.src.rpm -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 --- Makefile.in | 25 +- README | 26 + config.h.in | 3 + configure | 272 ++- configure.in | 41 +- driver/Makefile.in | 6 + driver/XScreenSaver.ad.in | 66 +- driver/XScreenSaver_ad.h | 43 +- driver/demo-Gtk.c | 2 +- driver/passwd-pam.c | 26 +- driver/prefs.c | 67 +- driver/prefs.h | 1 + driver/subprocs.c | 70 +- driver/timers.c | 25 +- driver/windows.c | 185 +- driver/xscreensaver-command.man | 2 +- driver/xscreensaver-demo.man | 2 +- driver/xscreensaver-getimage-file | 4 +- driver/xscreensaver-getimage-file.man | 2 +- driver/xscreensaver-getimage-video.man | 2 +- driver/xscreensaver-getimage.man | 2 +- driver/xscreensaver.c | 38 +- driver/xscreensaver.h | 2 + driver/xscreensaver.man | 34 +- hacks/Makefile.in | 19 +- hacks/attraction.c | 525 +++- hacks/attraction.man | 51 +- hacks/bsod.c | 2 +- hacks/compass.c | 2 +- hacks/compile_axp.com | 2 + hacks/compile_decc.com | 2 + hacks/galaxy.man | 6 +- hacks/glx/Makefile.in | 95 +- hacks/glx/atlantis.c | 114 +- hacks/glx/cage.c | 2 +- hacks/glx/fps.c | 33 +- hacks/glx/gflux.man | 2 +- hacks/glx/glplanet.c | 76 +- hacks/glx/lament.c | 82 +- hacks/glx/molecule.c | 31 +- hacks/glx/pulsar.c | 4 +- hacks/glx/sproingiewrap.c | 2 +- hacks/glx/starwars.c | 80 +- hacks/images/molecules/dna.pdb | 1 - hacks/images/noseguy/nose-f1.xbm | 78 +- hacks/images/noseguy/nose-f1.xpm | 2 +- hacks/images/noseguy/nose-f2.xbm | 78 +- hacks/images/noseguy/nose-f2.xpm | 2 +- hacks/images/noseguy/nose-f3.xbm | 78 +- hacks/images/noseguy/nose-f3.xpm | 2 +- hacks/images/noseguy/nose-f4.xbm | 78 +- hacks/images/noseguy/nose-f4.xpm | 2 +- hacks/images/noseguy/nose-l1.xbm | 78 +- hacks/images/noseguy/nose-l1.xpm | 2 +- hacks/images/noseguy/nose-l2.xbm | 78 +- hacks/images/noseguy/nose-l2.xpm | 2 +- hacks/images/noseguy/nose-r1.xbm | 78 +- hacks/images/noseguy/nose-r1.xpm | 2 +- hacks/images/noseguy/nose-r2.xbm | 78 +- hacks/images/noseguy/nose-r2.xpm | 2 +- hacks/noseguy.c | 3 +- hacks/noseguy.man | 4 +- hacks/pyro.c | 159 +- hacks/sonar.man | 6 +- hacks/speedmine.c | 1589 ++++++++++++ hacks/speedmine.man | 242 ++ hacks/vidwhacker.man | 56 +- hacks/webcollage | 3106 ++++++++++++++---------- hacks/whirlygig.c | 171 ++ hacks/whirlygig.man | 58 + setup.com | 2 + utils/erase.c | 1066 +++++--- utils/erase.h | 15 +- utils/overlay.c | 44 +- utils/version.h | 2 +- xscreensaver.lsm | 26 +- xscreensaver.lsm.sh | 27 +- xscreensaver.spec | 5 +- 78 files changed, 6842 insertions(+), 2456 deletions(-) create mode 100644 hacks/speedmine.c create mode 100644 hacks/speedmine.man create mode 100644 hacks/whirlygig.c create mode 100644 hacks/whirlygig.man diff --git a/Makefile.in b/Makefile.in index 6fe2ba0e..b7ed67e4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 cedca8ea..f66639b2 100644 --- 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, diff --git a/config.h.in b/config.h.in index ed31807e..e3d4afc2 100644 --- a/config.h.in +++ b/config.h.in @@ -341,6 +341,9 @@ /* 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 header file. */ #undef HAVE_UNISTD_H diff --git a/configure b/configure index 24e782b9..1eb09070 100755 --- 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 < 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 < #include @@ -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 < #include @@ -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 <&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 <&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 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 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 @@ -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 <&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 <&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 <&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 < #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 <&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 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 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 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 <&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 <&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 <&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 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 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 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 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 <&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 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 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 @@ -10009,17 +10066,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 diff --git a/configure.in b/configure.in index 9fbdfe30..82fbc0a6 100644 --- a/configure.in +++ b/configure.in @@ -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 diff --git a/driver/Makefile.in b/driver/Makefile.in index c7160142..060966aa 100644 --- a/driver/Makefile.in +++ b/driver/Makefile.in @@ -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 diff --git a/driver/XScreenSaver.ad.in b/driver/XScreenSaver.ad.in index e2d79ebd..5796f021 100644 --- a/driver/XScreenSaver.ad.in +++ b/driver/XScreenSaver.ad.in @@ -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 @@ -79,10 +80,10 @@ *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 @@ -267,6 +268,10 @@ - "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)" \ @@ -324,16 +329,8 @@ ! 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. + !============================================================================= ! diff --git a/driver/XScreenSaver_ad.h b/driver/XScreenSaver_ad.h index f45b5c87..b4ca0b27 100644 --- a/driver/XScreenSaver_ad.h +++ b/driver/XScreenSaver_ad.h @@ -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: \ @@ -171,6 +171,10 @@ - \"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 \ diff --git a/driver/demo-Gtk.c b/driver/demo-Gtk.c index 2f04b6f0..d4052b62 100644 --- a/driver/demo-Gtk.c +++ b/driver/demo-Gtk.c @@ -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 */ diff --git a/driver/passwd-pam.c b/driver/passwd-pam.c index 9e6a7194..43f2cbc2 100644 --- a/driver/passwd-pam.c +++ b/driver/passwd-pam.c @@ -1,7 +1,7 @@ /* passwd-pam.c --- verifying typed passwords with PAM * (Pluggable Authentication Modules.) * written by Bill Nottingham (and jwz) for - * xscreensaver, Copyright (c) 1993-1998, 2000 Jamie Zawinski + * xscreensaver, Copyright (c) 1993-2001 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 @@ -55,6 +55,8 @@ extern char *blurb(void); #include +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)); diff --git a/driver/prefs.c b/driver/prefs.c index 629b1b31..55b4653c 100644 --- a/driver/prefs.c +++ b/driver/prefs.c @@ -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. diff --git a/driver/prefs.h b/driver/prefs.h index 0ff0ff82..fb4cd1bd 100644 --- a/driver/prefs.h +++ b/driver/prefs.h @@ -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 */ diff --git a/driver/subprocs.c b/driver/subprocs.c index fd4cef83..465b03fd 100644 --- a/driver/subprocs.c +++ b/driver/subprocs.c @@ -1,6 +1,5 @@ /* subprocs.c --- choosing, spawning, and killing screenhacks. - * xscreensaver, Copyright (c) 1991, 1992, 1993, 1995, 1997, 1998, 1999, 2000 - * Jamie Zawinski + * xscreensaver, Copyright (c) 1991-2001 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 @@ -31,8 +30,10 @@ # include /* for waitpid() and associated macros */ #endif -#if defined(HAVE_SETPRIORITY) && defined(PRIO_PROCESS) +#if (defined(HAVE_SETPRIORITY) && defined(PRIO_PROCESS)) || \ + defined(HAVE_SETRLIMIT) # include /* 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(); diff --git a/driver/timers.c b/driver/timers.c index d810b492..f2fdb24b 100644 --- a/driver/timers.c +++ b/driver/timers.c @@ -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 */ } diff --git a/driver/windows.c b/driver/windows.c index 29e04619..471a8a7c 100644 --- a/driver/windows.c +++ b/driver/windows.c @@ -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) diff --git a/driver/xscreensaver-command.man b/driver/xscreensaver-command.man index 25befb7e..ae8535f9 100644 --- a/driver/xscreensaver-command.man +++ b/driver/xscreensaver-command.man @@ -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 diff --git a/driver/xscreensaver-demo.man b/driver/xscreensaver-demo.man index 01767bfb..b074e628 100644 --- a/driver/xscreensaver-demo.man +++ b/driver/xscreensaver-demo.man @@ -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 diff --git a/driver/xscreensaver-getimage-file b/driver/xscreensaver-getimage-file index 0766d9ed..402b1439 100755 --- a/driver/xscreensaver-getimage-file +++ b/driver/xscreensaver-getimage-file @@ -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); diff --git a/driver/xscreensaver-getimage-file.man b/driver/xscreensaver-getimage-file.man index beaf7b12..c4322793 100644 --- a/driver/xscreensaver-getimage-file.man +++ b/driver/xscreensaver-getimage-file.man @@ -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 diff --git a/driver/xscreensaver-getimage-video.man b/driver/xscreensaver-getimage-video.man index 8539b4d0..54ca8962 100644 --- a/driver/xscreensaver-getimage-video.man +++ b/driver/xscreensaver-getimage-video.man @@ -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 diff --git a/driver/xscreensaver-getimage.man b/driver/xscreensaver-getimage.man index 04232ee7..7e6c1003 100644 --- a/driver/xscreensaver-getimage.man +++ b/driver/xscreensaver-getimage.man @@ -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 diff --git a/driver/xscreensaver.c b/driver/xscreensaver.c index 08838dfa..63a63c83 100644 --- a/driver/xscreensaver.c +++ b/driver/xscreensaver.c @@ -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); } diff --git a/driver/xscreensaver.h b/driver/xscreensaver.h index b6e27974..c5bef700 100644 --- a/driver/xscreensaver.h +++ b/driver/xscreensaver.h @@ -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); diff --git a/driver/xscreensaver.man b/driver/xscreensaver.man index 9d33a72e..b2042e8c 100644 --- a/driver/xscreensaver.man +++ b/driver/xscreensaver.man @@ -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.) diff --git a/hacks/Makefile.in b/hacks/Makefile.in index e0586ed0..eb00f72b 100644 --- a/hacks/Makefile.in +++ b/hacks/Makefile.in @@ -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 diff --git a/hacks/attraction.c b/hacks/attraction.c index 1a84833b..397aae38 100644 --- a/hacks/attraction.c +++ b/hacks/attraction.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1997, 1998 +/* xscreensaver, Copyright (c) 1992, 1995, 1996, 1997, 1998, 2001 * Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its @@ -17,42 +17,70 @@ 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 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 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 #include @@ -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); } } diff --git a/hacks/attraction.man b/hacks/attraction.man index fabdc8a3..f4925786 100644 --- a/hacks/attraction.man +++ b/hacks/attraction.man @@ -16,7 +16,16 @@ 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 , 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 diff --git a/hacks/bsod.c b/hacks/bsod.c index bb30cbf1..fb04fdc8 100644 --- a/hacks/bsod.c +++ b/hacks/bsod.c @@ -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" diff --git a/hacks/compass.c b/hacks/compass.c index 56a1b0a5..ed765a98 100644 --- a/hacks/compass.c +++ b/hacks/compass.c @@ -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", diff --git a/hacks/compile_axp.com b/hacks/compile_axp.com index 71d6cdae..2440d0c2 100644 --- a/hacks/compile_axp.com +++ b/hacks/compile_axp.com @@ -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 diff --git a/hacks/compile_decc.com b/hacks/compile_decc.com index 71d6cdae..2440d0c2 100644 --- a/hacks/compile_decc.com +++ b/hacks/compile_decc.com @@ -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 diff --git a/hacks/galaxy.man b/hacks/galaxy.man index 2ef9e123..188ab9df 100644 --- a/hacks/galaxy.man +++ b/hacks/galaxy.man @@ -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 diff --git a/hacks/glx/Makefile.in b/hacks/glx/Makefile.in index 65089482..ba97c329 100644 --- a/hacks/glx/Makefile.in +++ b/hacks/glx/Makefile.in @@ -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: diff --git a/hacks/glx/atlantis.c b/hacks/glx/atlantis.c index f1844a5b..9f07ddbd 100644 --- a/hacks/glx/atlantis.c +++ b/hacks/glx/atlantis.c @@ -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 -#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(); diff --git a/hacks/glx/cage.c b/hacks/glx/cage.c index 16bcfcf0..e3641506 100644 --- a/hacks/glx/cage.c +++ b/hacks/glx/cage.c @@ -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 */ diff --git a/hacks/glx/fps.c b/hacks/glx/fps.c index e7adec3d..b254397e 100644 --- a/hacks/glx/fps.c +++ b/hacks/glx/fps.c @@ -21,6 +21,11 @@ #include #include +#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 } diff --git a/hacks/glx/gflux.man b/hacks/glx/gflux.man index db68a528..d6c1cf01 100644 --- a/hacks/glx/gflux.man +++ b/hacks/glx/gflux.man @@ -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 diff --git a/hacks/glx/glplanet.c b/hacks/glx/glplanet.c index d5d3de48..f1190281 100644 --- a/hacks/glx/glplanet.c +++ b/hacks/glx/glplanet.c @@ -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 */ diff --git a/hacks/glx/lament.c b/hacks/glx/lament.c index 8d5fe8c2..3f5080c0 100644 --- a/hacks/glx/lament.c +++ b/hacks/glx/lament.c @@ -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 . 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 .\n" "\n", progname, sig, diff --git a/hacks/glx/molecule.c b/hacks/glx/molecule.c index 954b9810..e9cc9852 100644 --- a/hacks/glx/molecule.c +++ b/hacks/glx/molecule.c @@ -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); diff --git a/hacks/glx/pulsar.c b/hacks/glx/pulsar.c index 7c67b835..a7695027 100644 --- a/hacks/glx/pulsar.c +++ b/hacks/glx/pulsar.c @@ -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"); */ } diff --git a/hacks/glx/sproingiewrap.c b/hacks/glx/sproingiewrap.c index 517c22da..b8ec9c41 100644 --- a/hacks/glx/sproingiewrap.c +++ b/hacks/glx/sproingiewrap.c @@ -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" \ diff --git a/hacks/glx/starwars.c b/hacks/glx/starwars.c index a6d5745c..cfb40f8c 100644 --- a/hacks/glx/starwars.c +++ b/hacks/glx/starwars.c @@ -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 +#include #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); } diff --git a/hacks/images/molecules/dna.pdb b/hacks/images/molecules/dna.pdb index 2788e2cd..a0606710 100644 --- a/hacks/images/molecules/dna.pdb +++ b/hacks/images/molecules/dna.pdb @@ -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 diff --git a/hacks/images/noseguy/nose-f1.xbm b/hacks/images/noseguy/nose-f1.xbm index 543af3e4..ea1a93bc 100644 --- a/hacks/images/noseguy/nose-f1.xbm +++ b/hacks/images/noseguy/nose-f1.xbm @@ -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}; diff --git a/hacks/images/noseguy/nose-f1.xpm b/hacks/images/noseguy/nose-f1.xpm index a6e03bfb..fab867b5 100644 --- a/hacks/images/noseguy/nose-f1.xpm +++ b/hacks/images/noseguy/nose-f1.xpm @@ -13,7 +13,6 @@ static char * nose_f1_xpm[] = { " ", " ", " ", -" ", " ..................... ", " .XXXXXXXXXXXXXXXXXXX. ", " .XXXXXXXXXXXXXXXXXXX. ", @@ -71,4 +70,5 @@ static char * nose_f1_xpm[] = { " ..@@@@@@@@@@@@@@@@@@@@@@@@@. .@@@@@@@@@@@@@@@@@@@@@@. ", " ........................... ....................... ", " ", +" ", " "}; diff --git a/hacks/images/noseguy/nose-f2.xbm b/hacks/images/noseguy/nose-f2.xbm index 6851b201..0e255768 100644 --- a/hacks/images/noseguy/nose-f2.xbm +++ b/hacks/images/noseguy/nose-f2.xbm @@ -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}; diff --git a/hacks/images/noseguy/nose-f2.xpm b/hacks/images/noseguy/nose-f2.xpm index 3763b58d..dd442acf 100644 --- a/hacks/images/noseguy/nose-f2.xpm +++ b/hacks/images/noseguy/nose-f2.xpm @@ -13,7 +13,6 @@ static char * nose_f2_xpm[] = { " ", " ", " ", -" ", " ..................... ", " .XXXXXXXXXXXXXXXXXXX. ", " .XXXXXXXXXXXXXXXXXXX. ", @@ -71,4 +70,5 @@ static char * nose_f2_xpm[] = { " .............................. ", " ", " ", +" ", " "}; diff --git a/hacks/images/noseguy/nose-f3.xbm b/hacks/images/noseguy/nose-f3.xbm index e70f2293..77a40ef0 100644 --- a/hacks/images/noseguy/nose-f3.xbm +++ b/hacks/images/noseguy/nose-f3.xbm @@ -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}; diff --git a/hacks/images/noseguy/nose-f3.xpm b/hacks/images/noseguy/nose-f3.xpm index c60c5f37..66ef3235 100644 --- a/hacks/images/noseguy/nose-f3.xpm +++ b/hacks/images/noseguy/nose-f3.xpm @@ -13,7 +13,6 @@ static char * nose_f3_xpm[] = { " ", " ", " ", -" ", " ..................... ", " .XXXXXXXXXXXXXXXXXXX. ", " .XXXXXXXXXXXXXXXXXXX. ", @@ -71,4 +70,5 @@ static char * nose_f3_xpm[] = { " .............................. ", " ", " ", +" ", " "}; diff --git a/hacks/images/noseguy/nose-f4.xbm b/hacks/images/noseguy/nose-f4.xbm index 024eead8..03ff1dcc 100644 --- a/hacks/images/noseguy/nose-f4.xbm +++ b/hacks/images/noseguy/nose-f4.xbm @@ -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}; diff --git a/hacks/images/noseguy/nose-f4.xpm b/hacks/images/noseguy/nose-f4.xpm index faa52e03..d910e25a 100644 --- a/hacks/images/noseguy/nose-f4.xpm +++ b/hacks/images/noseguy/nose-f4.xpm @@ -21,7 +21,6 @@ static char * nose_f4_xpm[] = { " ", " ", " ", -" ", " ............... ", " ....XXXXXXXXXXXXXXX.... ", " ...XXXXXXXXXXXXXXXXXXXXXXX... ", @@ -70,4 +69,5 @@ static char * nose_f4_xpm[] = { " ..@@@@@@@@@@@@@@@@@@@@@@@@@. .@@@@@@@@@@@@@@@@@@@@@@. ", " ........................... ....................... ", " ", +" ", " "}; diff --git a/hacks/images/noseguy/nose-l1.xbm b/hacks/images/noseguy/nose-l1.xbm index e3cb7030..bc38b020 100644 --- a/hacks/images/noseguy/nose-l1.xbm +++ b/hacks/images/noseguy/nose-l1.xbm @@ -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}; diff --git a/hacks/images/noseguy/nose-l1.xpm b/hacks/images/noseguy/nose-l1.xpm index 205d18be..12bb2eb9 100644 --- a/hacks/images/noseguy/nose-l1.xpm +++ b/hacks/images/noseguy/nose-l1.xpm @@ -13,7 +13,6 @@ static char * nose_l1_xpm[] = { " ", " ", " ", -" ", " ..................... ", " .XXXXXXXXXXXXXXXXXXX. ", " .XXXXXXXXXXXXXXXXXXX. ", @@ -71,4 +70,5 @@ static char * nose_l1_xpm[] = { " .............................. ", " ", " ", +" ", " "}; diff --git a/hacks/images/noseguy/nose-l2.xbm b/hacks/images/noseguy/nose-l2.xbm index fa39343b..1a2e77f1 100644 --- a/hacks/images/noseguy/nose-l2.xbm +++ b/hacks/images/noseguy/nose-l2.xbm @@ -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}; diff --git a/hacks/images/noseguy/nose-l2.xpm b/hacks/images/noseguy/nose-l2.xpm index f08a72eb..37e40a65 100644 --- a/hacks/images/noseguy/nose-l2.xpm +++ b/hacks/images/noseguy/nose-l2.xpm @@ -13,7 +13,6 @@ static char * nose_l2_xpm[] = { " ", " ", " ", -" ", " ..................... ", " .XXXXXXXXXXXXXXXXXXX. ", " .XXXXXXXXXXXXXXXXXXX. ", @@ -71,4 +70,5 @@ static char * nose_l2_xpm[] = { " ", " ", " ", +" ", " "}; diff --git a/hacks/images/noseguy/nose-r1.xbm b/hacks/images/noseguy/nose-r1.xbm index 72df86c2..3e410634 100644 --- a/hacks/images/noseguy/nose-r1.xbm +++ b/hacks/images/noseguy/nose-r1.xbm @@ -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}; diff --git a/hacks/images/noseguy/nose-r1.xpm b/hacks/images/noseguy/nose-r1.xpm index 901dd428..58e8b0bf 100644 --- a/hacks/images/noseguy/nose-r1.xpm +++ b/hacks/images/noseguy/nose-r1.xpm @@ -13,7 +13,6 @@ static char * nose_r1_xpm[] = { " ", " ", " ", -" ", " ..................... ", " .XXXXXXXXXXXXXXXXXXX. ", " .XXXXXXXXXXXXXXXXXXX. ", @@ -71,4 +70,5 @@ static char * nose_r1_xpm[] = { " .............................. ", " ", " ", +" ", " "}; diff --git a/hacks/images/noseguy/nose-r2.xbm b/hacks/images/noseguy/nose-r2.xbm index eb750ca7..1fdd6b49 100644 --- a/hacks/images/noseguy/nose-r2.xbm +++ b/hacks/images/noseguy/nose-r2.xbm @@ -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}; diff --git a/hacks/images/noseguy/nose-r2.xpm b/hacks/images/noseguy/nose-r2.xpm index ddf0edaf..1a70e694 100644 --- a/hacks/images/noseguy/nose-r2.xpm +++ b/hacks/images/noseguy/nose-r2.xpm @@ -13,7 +13,6 @@ static char * nose_r2_xpm[] = { " ", " ", " ", -" ", " ..................... ", " .XXXXXXXXXXXXXXXXXXX. ", " .XXXXXXXXXXXXXXXXXXX. ", @@ -71,4 +70,5 @@ static char * nose_r2_xpm[] = { " ", " ", " ", +" ", " "}; diff --git a/hacks/noseguy.c b/hacks/noseguy.c index f0fa57f4..fa3203cd 100644 --- a/hacks/noseguy.c +++ b/hacks/noseguy.c @@ -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 . + spewing out messages. Derived from xnlock by + Dan Heller . */ #include "screenhack.h" diff --git a/hacks/noseguy.man b/hacks/noseguy.man index f23746b5..916b78fe 100644 --- a/hacks/noseguy.man +++ b/hacks/noseguy.man @@ -66,9 +66,9 @@ stored in the RESOURCE_MANAGER property. .BR xscreensaver (1), .BR xnlock (1) .SH COPYRIGHT -Copyright 1985, 1990 by Dan Heller . +Copyright 1985, 1990 by Dan Heller . .SH AUTHOR -Dan Heller , 1985. +Dan Heller , 1985. Ability to run standalone or with \fIxscreensaver\fP added by Jamie Zawinski , 13-aug-92. diff --git a/hacks/pyro.c b/hacks/pyro.c index ddace391..e46e93fa 100644 --- a/hacks/pyro.c +++ b/hacks/pyro.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1992, 1994, 1996, 1998 +/* xscreensaver, Copyright (c) 1992, 1994, 1996, 1998, 2001 * Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its @@ -14,6 +14,7 @@ John S. Pezaris */ +#include #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; ix = 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); } @@ -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); + } } diff --git a/hacks/sonar.man b/hacks/sonar.man index 1db5982a..5327c46d 100644 --- a/hacks/sonar.man +++ b/hacks/sonar.man @@ -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 index 00000000..64f8578a --- /dev/null +++ b/hacks/speedmine.c @@ -0,0 +1,1589 @@ +/* -*- Mode: C; c-basic-offset: 4; tab-width: 4 -*- + * speedmine, Copyright (C) 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. + */ + +/* + * 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 + +#include + +#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) { + 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, April 2001. diff --git a/hacks/vidwhacker.man b/hacks/vidwhacker.man index a1ffc102..3c8a4705 100644 --- a/hacks/vidwhacker.man +++ b/hacks/vidwhacker.man @@ -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 diff --git a/hacks/webcollage b/hacks/webcollage index 5461ac31..f77c6153 100755 --- a/hacks/webcollage +++ b/hacks/webcollage @@ -1,6 +1,6 @@ #!/usr/bin/perl -w # -# webcollage, Copyright (c) 1999, 2000 by Jamie Zawinski +# webcollage, Copyright (c) 1999-2001 by Jamie Zawinski # This program decorates the screen with random images from the web. # One satisfied customer described it as "a nonstop pop culture brainbath." # @@ -14,13 +14,19 @@ # 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 \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 = ; - - while () { - $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 () { - $body .= $_; + } + $hdrs .= "\r\n"; + + foreach (split('\r?\n', $hdrs)) { + LOG ($verbose_http, " ==> $_"); + } + print S $hdrs; + my $http = ; + + $_ = $http; + s/[\r\n]+$//s; + LOG ($verbose_http, " <== $_"); + + while () { + $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 () { + $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 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(/ * 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 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(/ * 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@ 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. + +############################################################################ # -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 = ; # toss partial line $word = ; # keep next line } - if (!$word) { + if (!$word) { seek( IN, 0, 0 ); $word = ; - } + } 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 )?()?(\d+)()? image@) { - $search_count = $3; - } elsif ($which == 1 && $body =~ m@((\d{1,3})(,\d{3})*) @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 )?()?(\d+)()? image@) { + $search_count = $3; + } elsif ($body =~ m@((\d{1,3})(,\d{3})*) @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/(]+)>@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/(]+)>@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 (); + } } + +############################################################################ +# +# 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 (); + } +} + + +############################################################################ +# +# 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); +} + + + +############################################################################ +# +# 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); +} + + + +############################################################################ +# +# 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); +} + + + +############################################################################ +# +# 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); +} + + + +############################################################################ +# +# 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); +} + + + + +############################################################################ +# +# 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); +} + + + +############################################################################ +# +# 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); +} + + + +############################################################################## +# +# 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 () { $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; - $_ = ; - $_ = ; - ($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 () { $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; + $_ = ; + $_ = ; + ($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 index 00000000..0f26bbcd --- /dev/null +++ b/hacks/whirlygig.c @@ -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 +#include "screenhack.h" +#include + +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 index 00000000..c42edc14 --- /dev/null +++ b/hacks/whirlygig.man @@ -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 , 31-Mar-01 diff --git a/setup.com b/setup.com index 574f1883..857cb210 100644 --- 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 diff --git a/utils/erase.c b/utils/erase.c index f3d6de8b..bd7a345d 100644 --- a/utils/erase.c +++ b/utils/erase.c @@ -1,8 +1,18 @@ /* erase.c: Erase the screen in various more or less interesting ways. - * (c) 1997 by Johannes Keukelaar - * 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 + * + * 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 : + * 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" @@ -10,21 +20,47 @@ #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 */ 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 */ 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 */ 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 */ +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 */ 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); } - - - -#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 diff --git a/utils/erase.h b/utils/erase.h index 2f00d3e1..d161d2eb 100644 --- a/utils/erase.h +++ b/utils/erase.h @@ -1,15 +1,18 @@ /* erase.c: Erase the screen in various more or less interesting ways. - * (c) 1997 by Johannes Keukelaar - * 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 + * + * 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__ */ diff --git a/utils/overlay.c b/utils/overlay.c index 7277fd03..85699038 100644 --- a/utils/overlay.c +++ b/utils/overlay.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1997 Jamie Zawinski +/* xscreensaver, Copyright (c) 1997, 2001 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 @@ -12,16 +12,37 @@ /* 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 - */ @@ -46,8 +66,11 @@ 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; diff --git a/utils/version.h b/utils/version.h index 4de0984d..3889f5f5 100644 --- a/utils/version.h +++ b/utils/version.h @@ -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)"; diff --git a/xscreensaver.lsm b/xscreensaver.lsm index debc1bae..1b02f7b0 100644 --- a/xscreensaver.lsm +++ b/xscreensaver.lsm @@ -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 diff --git a/xscreensaver.lsm.sh b/xscreensaver.lsm.sh index b3126f0a..fc1103f9 100755 --- a/xscreensaver.lsm.sh +++ b/xscreensaver.lsm.sh @@ -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 diff --git a/xscreensaver.spec b/xscreensaver.spec index fd75dbe0..8933255d 100644 --- a/xscreensaver.spec +++ b/xscreensaver.spec @@ -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 -- 2.30.2