http://ftp.x.org/contrib/applications/xscreensaver-3.18.tar.gz
authorZygo Blaxell <zblaxell@hungrycats.org>
Mon, 2 Mar 2009 05:42:38 +0000 (00:42 -0500)
committerZygo Blaxell <zblaxell@hungrycats.org>
Mon, 2 Mar 2009 05:42:38 +0000 (00:42 -0500)
-rw-r--r-- 1 zblaxell zblaxell 1163033 Oct 12  1999 xscreensaver-3.18.tar.gz
533787dcdc7ba24561b6afb6084ef84901d0b2b6  xscreensaver-3.18.tar.gz

42 files changed:
README
configure
configure.in
driver/Makefile.in
driver/XScreenSaver.ad.in
driver/XScreenSaver_ad.h
driver/lock.c
driver/windows.c
driver/xscreensaver-command.man
driver/xscreensaver-demo.man
driver/xscreensaver.c
driver/xscreensaver.h
driver/xscreensaver.kss [new file with mode: 0755]
driver/xscreensaver.man
hacks/Makefile.in
hacks/blaster.c [new file with mode: 0644]
hacks/bsod.c
hacks/bumps.c [new file with mode: 0644]
hacks/bumps.h [new file with mode: 0644]
hacks/ccurve.c [new file with mode: 0644]
hacks/compile_axp.com
hacks/compile_decc.com
hacks/distort.c
hacks/forest.c
hacks/galaxy.c
hacks/glx/sproingies.c
hacks/glx/sproingiewrap.c
hacks/lmorph.c
hacks/lmorph.man
hacks/screenhack.c
hacks/shadebobs.c
hacks/vidwhacker
hacks/webcollage
hacks/xflame.c
hacks/xsublim.c
hacks/xsublim.man [new file with mode: 0644]
setup.com
utils/colors.c
utils/version.h
utils/visual.c
xscreensaver.lsm
xscreensaver.spec

diff --git a/README b/README
index 860debe27410203b8d4975fd9d20b9614ed20cfe..9fe342bd2c8365e3e2274bb3b32ceab874531beb 100644 (file)
--- a/README
+++ b/README
@@ -77,6 +77,22 @@ http://www.jwz.org/xscreensaver/.
 
                               ============
 
+Changes since 3.17:   * New versions of `shadebobs', `lmorph', and `distort'.
+                      * Added `ccurve', `blaster', and `bumps' hacks.
+                      * Replaced `forest' hack with a rewritten version.
+                      * Worked around a Xinerama server bug.
+                      * Fixed a bug I introduced in 3.10 that caused some
+                        hacks to print out superfluous warnings about not
+                        having gotten enough colors.
+                      * Made `sproingies' obey the `-delay' option.
+                      * Fixed a portability bug in `shadebobs'.
+                      * Made `webcollage' and `vidwhacker' use `xli' in
+                        preference to `xv', if it is available.
+                      * Added a new source of images to `webcollage'.
+                      * If running under KDE, xscreensaver will add itself to
+                        KDE's list of screensavers (via xscreensaver.kss.)
+                      * Improved detection of GL libraries.
+                      * Made the password dialog include the date and time.
 Changes since 3.16:   * New version of `webcollage' -- deals better with
                         corrupted images, and can use an http proxy.
                       * New hack, `xsublim' (run it in the background,
index 74d889e6e61d4faab625cb8a08dfcaafe937f66e..a1d4d6a97abd75bcf75dc822d1de5d9fd3aa715e 100755 (executable)
--- a/configure
+++ b/configure
@@ -7011,16 +7011,11 @@ fi
   #
   if test "$have_gl" = yes ; then
 
-    cat >> confdefs.h <<\EOF
-#define HAVE_GL 1
-EOF
-
-
     # We need to know whether it's MesaGL so that we know which libraries
     # to link against.
     #
     echo $ac_n "checking whether GL is really MesaGL""... $ac_c" 1>&6
-echo "configure:7035: checking whether GL is really MesaGL" >&5
+echo "configure:7030: 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
@@ -7032,7 +7027,7 @@ else
   fi
   CPPFLAGS="$CPPFLAGS $X_CFLAGS"
   cat > conftest.$ac_ext <<EOF
-#line 7047 "configure"
+#line 7042 "configure"
 #include "confdefs.h"
 #include <GL/glx.h>
 EOF
 echo "$ac_t""$ac_cv_have_mesa_gl" 1>&6
     ac_have_mesa_gl=$ac_cv_have_mesa_gl
  
-    if test "$ac_have_mesa_gl" = no ; then
-      gl_lib_1="GL"
-      GL_LIBS="-lGL -lGLU"
+
+    # If we have Mesa headers, check to see if we can link against -lMesaGL.
+    # If we don't have Mesa headers, or we don't have -lMesaGL, try -lGL.
+    # Else, warn that GL is busted.  (We have the headers, but no libs.)
+    #
+    gl_lib_1=""
+    GL_LIBS=""
+
+    if test "$ac_have_mesa_gl" = yes ; then
+      
+  ac_save_CPPFLAGS="$CPPFLAGS"
+  ac_save_LDFLAGS="$LDFLAGS"
+#  ac_save_LIBS="$LIBS"
+
+  if test \! -z "$includedir" ; then 
+    CPPFLAGS="$CPPFLAGS -I$includedir"
+  fi
+  # note: $X_CFLAGS includes $x_includes
+  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+
+  if test \! -z "$libdir" ; then
+    LDFLAGS="$LDFLAGS -L$libdir"
+  fi
+  # note: $X_LIBS includes $x_libraries
+  LDFLAGS="$LDFLAGS $X_LIBS"
+
+  echo $ac_n "checking for glXCreateContext in -lMesaGL""... $ac_c" 1>&6
+echo "configure:7087: 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
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lMesaGL -lMesaGLU -lX11 -lXext -lm $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 7095 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char glXCreateContext();
+
+int main() {
+glXCreateContext()
+; return 0; }
+EOF
+if { (eval echo configure:7106: \"$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
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  gl_lib_1="MesaGL"
+                      GL_LIBS="-lMesaGL -lMesaGLU"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+  CPPFLAGS="$ac_save_CPPFLAGS"
+  LDFLAGS="$ac_save_LDFLAGS"
+#  LIBS="$ac_save_LIBS"
+  
+    fi
+
+    if test "$gl_lib_1" = "" ; then
+      
+  ac_save_CPPFLAGS="$CPPFLAGS"
+  ac_save_LDFLAGS="$LDFLAGS"
+#  ac_save_LIBS="$LIBS"
+
+  if test \! -z "$includedir" ; then 
+    CPPFLAGS="$CPPFLAGS -I$includedir"
+  fi
+  # note: $X_CFLAGS includes $x_includes
+  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+
+  if test \! -z "$libdir" ; then
+    LDFLAGS="$LDFLAGS -L$libdir"
+  fi
+  # note: $X_LIBS includes $x_libraries
+  LDFLAGS="$LDFLAGS $X_LIBS"
+
+  echo $ac_n "checking for glXCreateContext in -lGL""... $ac_c" 1>&6
+echo "configure:7152: 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
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lGL -lGLU -lX11 -lXext -lm $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 7160 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char glXCreateContext();
+
+int main() {
+glXCreateContext()
+; return 0; }
+EOF
+if { (eval echo configure:7171: \"$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
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  gl_lib_1="GL"
+                      GL_LIBS="-lGL -lGLU"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+  CPPFLAGS="$ac_save_CPPFLAGS"
+  LDFLAGS="$ac_save_LDFLAGS"
+#  LIBS="$ac_save_LIBS"
+  
+    fi
+
+    if test "$gl_lib_1" = "" ; then
+      # we have headers, but no libs -- bail.
+      have_gl=no
+      ac_have_mesa_gl=no
     else
+      # linking works -- we can build the GL hacks.
       cat >> confdefs.h <<\EOF
+#define HAVE_GL 1
+EOF
+
+      if test "$ac_have_mesa_gl" = yes ; then
+        cat >> confdefs.h <<\EOF
 #define HAVE_MESA_GL 1
 EOF
 
-      gl_lib_1="MesaGL"
-      GL_LIBS="-lMesaGL -lMesaGLU"
+      fi
     fi
+  fi
 
 
+  # Now that we know we have GL headers and libs, do some more GL testing.
+  #
+
+  if test "$have_gl" = yes ; then
     # If it's MesaGL, we'd like to issue a warning if the version number
     # is less than or equal to 2.6, because that version had a security bug.
     #
     if test "$ac_have_mesa_gl" = yes; then
 
       echo $ac_n "checking MesaGL version number""... $ac_c" 1>&6
-echo "configure:7084: checking MesaGL version number" >&5
+echo "configure:7228: checking MesaGL version number" >&5
 if eval "test \"`echo '$''{'ac_cv_mesagl_version_string'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7089 "configure"
+#line 7233 "configure"
 #include "confdefs.h"
 #include <GL/gl.h>
 configure: MESA_MAJOR_VERSION MESA_MINOR_VERSION
@@ -7127,7 +7271,7 @@ echo "$ac_t""$ac_cv_mesagl_version_string" 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:7142: checking for pthread_create in -lpthread" >&5
+echo "configure:7286: 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
@@ -7135,7 +7279,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lpthread  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 7150 "configure"
+#line 7294 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -7146,7 +7290,7 @@ int main() {
 pthread_create()
 ; return 0; }
 EOF
-if { (eval echo configure:7161: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7305: \"$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
@@ -7185,7 +7329,7 @@ fi
   LDFLAGS="$LDFLAGS $X_LIBS"
 
   echo $ac_n "checking for gl_get_thread_context in -l$gl_lib_1""... $ac_c" 1>&6
-echo "configure:7200: checking for gl_get_thread_context in -l$gl_lib_1" >&5
+echo "configure:7344: checking for gl_get_thread_context in -l$gl_lib_1" >&5
 ac_lib_var=`echo $gl_lib_1'_'gl_get_thread_context | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -7193,7 +7337,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-l$gl_lib_1 $GL_LIBS -lpthread -lX11 -lXext -lm $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 7208 "configure"
+#line 7352 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -7204,7 +7348,7 @@ int main() {
 gl_get_thread_context()
 ; return 0; }
 EOF
-if { (eval echo configure:7219: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7363: \"$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
@@ -7256,7 +7400,7 @@ fi
   LDFLAGS="$LDFLAGS $X_LIBS"
 
   echo $ac_n "checking for glBindTexture in -l$gl_lib_1""... $ac_c" 1>&6
-echo "configure:7271: checking for glBindTexture in -l$gl_lib_1" >&5
+echo "configure:7415: 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
@@ -7264,7 +7408,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-l$gl_lib_1 $GL_LIBS -lX11 -lXext -lm $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 7279 "configure"
+#line 7423 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -7275,7 +7419,7 @@ int main() {
 glBindTexture()
 ; return 0; }
 EOF
-if { (eval echo configure:7290: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7434: \"$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
@@ -7309,7 +7453,7 @@ fi
     # See comments in utils/visual-gl.c for why this is sometimes necessary.
     #
     echo $ac_n "checking whether drastic GL measures must be taken""... $ac_c" 1>&6
-echo "configure:7324: checking whether drastic GL measures must be taken" >&5
+echo "configure:7468: checking whether drastic GL measures must be taken" >&5
     case "$host" in
       *-sgi*)
         echo "$ac_t""yes -- hello, SGI." 1>&6
@@ -7361,7 +7505,7 @@ fi
 
     /*)
      echo $ac_n "checking for XPM headers""... $ac_c" 1>&6
-echo "configure:7376: checking for XPM headers" >&5
+echo "configure:7520: checking for XPM headers" >&5
      d=$with_xpm/include
      if test -d $d; then
        X_CFLAGS="-I$d $X_CFLAGS"
@@ -7371,7 +7515,7 @@ echo "configure:7376: checking for XPM headers" >&5
      fi
 
      echo $ac_n "checking for XPM libs""... $ac_c" 1>&6
-echo "configure:7386: checking for XPM libs" >&5
+echo "configure:7530: checking for XPM libs" >&5
      d=$with_xpm/lib
      if test -d $d; then
        X_LIBS="-L$d $X_LIBS"
@@ -7404,17 +7548,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:7419: checking for X11/xpm.h" >&5
+echo "configure:7563: checking for X11/xpm.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7424 "configure"
+#line 7568 "configure"
 #include "confdefs.h"
 #include <X11/xpm.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7429: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:7573: \"$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*
@@ -7480,7 +7624,7 @@ fi
 
     /*)
      echo $ac_n "checking for XSHM headers""... $ac_c" 1>&6
-echo "configure:7495: checking for XSHM headers" >&5
+echo "configure:7639: checking for XSHM headers" >&5
      d=$with_xshm/include
      if test -d $d; then
        X_CFLAGS="-I$d $X_CFLAGS"
@@ -7490,7 +7634,7 @@ echo "configure:7495: checking for XSHM headers" >&5
      fi
 
      echo $ac_n "checking for XSHM libs""... $ac_c" 1>&6
-echo "configure:7505: checking for XSHM libs" >&5
+echo "configure:7649: checking for XSHM libs" >&5
      d=$with_xshm/lib
      if test -d $d; then
        X_LIBS="-L$d $X_LIBS"
@@ -7525,17 +7669,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:7540: checking for X11/extensions/XShm.h" >&5
+echo "configure:7684: checking for X11/extensions/XShm.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7545 "configure"
+#line 7689 "configure"
 #include "confdefs.h"
 #include <X11/extensions/XShm.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7550: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:7694: \"$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*
@@ -7569,17 +7713,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:7584: checking for sys/ipc.h" >&5
+echo "configure:7728: checking for sys/ipc.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7589 "configure"
+#line 7733 "configure"
 #include "confdefs.h"
 #include <sys/ipc.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7594: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:7738: \"$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*
@@ -7614,17 +7758,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:7629: checking for sys/shm.h" >&5
+echo "configure:7773: checking for sys/shm.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7634 "configure"
+#line 7778 "configure"
 #include "confdefs.h"
 #include <sys/shm.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7639: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:7783: \"$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*
@@ -7675,7 +7819,7 @@ fi
   LDFLAGS="$LDFLAGS $X_LIBS"
 
   echo $ac_n "checking for XShmQueryExtension in -lXextSam""... $ac_c" 1>&6
-echo "configure:7690: checking for XShmQueryExtension in -lXextSam" >&5
+echo "configure:7834: 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
@@ -7683,7 +7827,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lXextSam -lX11 -lXext -lm $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 7698 "configure"
+#line 7842 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -7694,7 +7838,7 @@ int main() {
 XShmQueryExtension()
 ; return 0; }
 EOF
-if { (eval echo configure:7709: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7853: \"$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
@@ -7760,7 +7904,7 @@ fi
 
     /*)
      echo $ac_n "checking for DOUBLE-BUFFER headers""... $ac_c" 1>&6
-echo "configure:7775: checking for DOUBLE-BUFFER headers" >&5
+echo "configure:7919: checking for DOUBLE-BUFFER headers" >&5
      d=$with_xdbe/include
      if test -d $d; then
        X_CFLAGS="-I$d $X_CFLAGS"
@@ -7770,7 +7914,7 @@ echo "configure:7775: checking for DOUBLE-BUFFER headers" >&5
      fi
 
      echo $ac_n "checking for DOUBLE-BUFFER libs""... $ac_c" 1>&6
-echo "configure:7785: checking for DOUBLE-BUFFER libs" >&5
+echo "configure:7929: checking for DOUBLE-BUFFER libs" >&5
      d=$with_xdbe/lib
      if test -d $d; then
        X_LIBS="-L$d $X_LIBS"
@@ -7804,17 +7948,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:7819: checking for X11/extensions/Xdbe.h" >&5
+echo "configure:7963: checking for X11/extensions/Xdbe.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7824 "configure"
+#line 7968 "configure"
 #include "confdefs.h"
 #include <X11/extensions/Xdbe.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7829: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:7973: \"$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*
@@ -7877,7 +8021,7 @@ fi
 
     /*)
      echo $ac_n "checking for XReadDisplay headers""... $ac_c" 1>&6
-echo "configure:7892: checking for XReadDisplay headers" >&5
+echo "configure:8036: checking for XReadDisplay headers" >&5
      d=$with_readdisplay/include
      if test -d $d; then
        X_CFLAGS="-I$d $X_CFLAGS"
@@ -7887,7 +8031,7 @@ echo "configure:7892: checking for XReadDisplay headers" >&5
      fi
 
      echo $ac_n "checking for XReadDisplay libs""... $ac_c" 1>&6
-echo "configure:7902: checking for XReadDisplay libs" >&5
+echo "configure:8046: checking for XReadDisplay libs" >&5
      d=$with_readdisplay/lib
      if test -d $d; then
        X_LIBS="-L$d $X_LIBS"
@@ -7920,17 +8064,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:7935: checking for X11/extensions/readdisplay.h" >&5
+echo "configure:8079: checking for X11/extensions/readdisplay.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7940 "configure"
+#line 8084 "configure"
 #include "confdefs.h"
 #include <X11/extensions/readdisplay.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:7945: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:8089: \"$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*
@@ -7985,7 +8129,7 @@ fi
 
     /*)
      echo $ac_n "checking for Iris Video headers""... $ac_c" 1>&6
-echo "configure:8000: checking for Iris Video headers" >&5
+echo "configure:8144: checking for Iris Video headers" >&5
      d=$with_sgivideo/include
      if test -d $d; then
        X_CFLAGS="-I$d $X_CFLAGS"
@@ -7995,7 +8139,7 @@ echo "configure:8000: checking for Iris Video headers" >&5
      fi
 
      echo $ac_n "checking for Iris Video libs""... $ac_c" 1>&6
-echo "configure:8010: checking for Iris Video libs" >&5
+echo "configure:8154: checking for Iris Video libs" >&5
      d=$with_sgivideo/lib
      if test -d $d; then
        X_LIBS="-L$d $X_LIBS"
@@ -8028,17 +8172,17 @@ if test "$with_sgivideo" = yes; then
   CPPFLAGS="$CPPFLAGS $X_CFLAGS"
   ac_safe=`echo "dmedia/vl.h" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for dmedia/vl.h""... $ac_c" 1>&6
-echo "configure:8043: checking for dmedia/vl.h" >&5
+echo "configure:8187: checking for dmedia/vl.h" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 8048 "configure"
+#line 8192 "configure"
 #include "confdefs.h"
 #include <dmedia/vl.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:8053: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:8197: \"$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*
@@ -8063,7 +8207,7 @@ fi
   if test "$have_sgivideo" = yes; then
     have_sgivideo=no
     echo $ac_n "checking for vlOpenVideo in -lvl""... $ac_c" 1>&6
-echo "configure:8078: checking for vlOpenVideo in -lvl" >&5
+echo "configure:8222: checking for vlOpenVideo in -lvl" >&5
 ac_lib_var=`echo vl'_'vlOpenVideo | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -8071,7 +8215,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lvl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 8086 "configure"
+#line 8230 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -8082,7 +8226,7 @@ int main() {
 vlOpenVideo()
 ; return 0; }
 EOF
-if { (eval echo configure:8097: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8241: \"$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
@@ -8153,7 +8297,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:8168: checking for $with_zippy_req" >&5
+echo "configure:8312: checking for $with_zippy_req" >&5
       if test -x "$with_zippy_req" ; then
         echo "$ac_t""yes" 1>&6
       else
@@ -8167,7 +8311,7 @@ echo "configure:8168: 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:8182: checking for $ac_word" >&5
+echo "configure:8326: 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
@@ -8217,7 +8361,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:8232: checking for $ac_word" >&5
+echo "configure:8376: 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
@@ -8251,7 +8395,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:8266: checking for $ac_word" >&5
+echo "configure:8410: 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
@@ -8286,7 +8430,7 @@ done
 
   if test -n "$emacs_exe" ; then
     echo $ac_n "checking for emacs yow""... $ac_c" 1>&6
-echo "configure:8301: checking for emacs yow" >&5
+echo "configure:8445: checking for emacs yow" >&5
     #
     # get emacs to tell us where the libexec directory is.
     #
@@ -8308,7 +8452,7 @@ echo "configure:8301: 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:8323: checking for xemacs yow" >&5
+echo "configure:8467: checking for xemacs yow" >&5
     if test -n "$xemacs_exe" ; then
       #
       # get xemacs to tell us where the libexec directory is.
@@ -8367,7 +8511,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:8382: checking for $ac_word" >&5
+echo "configure:8526: 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
@@ -8403,7 +8547,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:8418: checking for $ac_word" >&5
+echo "configure:8562: 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
@@ -9346,7 +9490,7 @@ if test "$do_dir_warning" = yes; then
   echo '      "xscreensaver-demo", and "xscreensaver-command" executables'
   echo "      will be installed in ${bindir}."
   echo ""
-  echo "      The various graphics demos (90+ different executables) will"
+  echo "      The various graphics demos (100+ different executables) will"
   echo "      also be installed in ${HACKDIR}."
   echo ""
   echo "      If you would prefer the demos to be installed elsewhere"
index 07fb76e98386a52397f77d74e19dbd82837f5870..6c9c4d0d3fe8589fd50084698a8a687c8a8ee84f 100644 (file)
@@ -1809,8 +1809,6 @@ if test "$with_gl" = yes; then
   #
   if test "$have_gl" = yes ; then
 
-    AC_DEFINE(HAVE_GL)
-
     # We need to know whether it's MesaGL so that we know which libraries
     # to link against.
     #
@@ -1820,16 +1818,46 @@ if test "$with_gl" = yes; then
       ])
     ac_have_mesa_gl=$ac_cv_have_mesa_gl
  
-    if test "$ac_have_mesa_gl" = no ; then
-      gl_lib_1="GL"
-      GL_LIBS="-lGL -lGLU"
+
+    # If we have Mesa headers, check to see if we can link against -lMesaGL.
+    # If we don't have Mesa headers, or we don't have -lMesaGL, try -lGL.
+    # Else, warn that GL is busted.  (We have the headers, but no libs.)
+    #
+    gl_lib_1=""
+    GL_LIBS=""
+
+    if test "$ac_have_mesa_gl" = yes ; then
+      AC_CHECK_X_LIB(MesaGL, glXCreateContext, 
+                     [gl_lib_1="MesaGL"
+                      GL_LIBS="-lMesaGL -lMesaGLU"],
+                     [], -lMesaGLU -lX11 -lXext -lm)
+    fi
+
+    if test "$gl_lib_1" = "" ; then
+      AC_CHECK_X_LIB(GL, glXCreateContext, 
+                     [gl_lib_1="GL"
+                      GL_LIBS="-lGL -lGLU"],
+                     [], -lGLU -lX11 -lXext -lm)
+    fi
+
+    if test "$gl_lib_1" = "" ; then
+      # we have headers, but no libs -- bail.
+      have_gl=no
+      ac_have_mesa_gl=no
     else
-      AC_DEFINE(HAVE_MESA_GL)
-      gl_lib_1="MesaGL"
-      GL_LIBS="-lMesaGL -lMesaGLU"
+      # linking works -- we can build the GL hacks.
+      AC_DEFINE(HAVE_GL)
+      if test "$ac_have_mesa_gl" = yes ; then
+        AC_DEFINE(HAVE_MESA_GL)
+      fi
     fi
+  fi
 
 
+  # Now that we know we have GL headers and libs, do some more GL testing.
+  #
+
+  if test "$have_gl" = yes ; then
     # If it's MesaGL, we'd like to issue a warning if the version number
     # is less than or equal to 2.6, because that version had a security bug.
     #
@@ -2749,7 +2777,7 @@ if test "$do_dir_warning" = yes; then
   echo '      "xscreensaver-demo", and "xscreensaver-command" executables'
   echo "      will be installed in ${bindir}."
   echo ""
-  echo "      The various graphics demos (90+ different executables) will"
+  echo "      The various graphics demos (100+ different executables) will"
   echo "      also be installed in ${HACKDIR}."
   echo ""
   echo "      If you would prefer the demos to be installed elsewhere"
index 318ec69eb572b0a87f220eefe2c6d0ffdb9731c2..6d0da08412f479a8eb12dc55b10a7c3b9b0abc2e 100644 (file)
@@ -152,7 +152,7 @@ HDRS                = XScreenSaver_ad.h xscreensaver.h prefs.h remote.h
 MEN            = xscreensaver.man xscreensaver-demo.man \
                  xscreensaver-command.man
 EXTRAS         = README Makefile.in XScreenSaver.ad.in xscreensaver.pam \
-                 .gdbinit
+                 xscreensaver.kss .gdbinit
 VMSFILES       = compile_axp.com compile_decc.com link_axp.com link_decc.com \
                  vms-getpwnam.c vms-pwd.h vms-hpwd.c vms-validate.c \
                  vms_axp.opt vms_axp_12.opt vms_decc.opt vms_decc_12.opt
@@ -166,8 +166,8 @@ TARFILES    = $(EXTRAS) $(VMSFILES) $(SAVER_SRCS_1) \
 default: $(EXES)
 all: $(EXES) $(EXES2)
 
-install:   install-program   install-ad   install-man   @INSTALL_PAM@
-uninstall: uninstall-program uninstall-ad uninstall-man
+install:   install-program   install-ad   install-kde   install-man   @INSTALL_PAM@
+uninstall: uninstall-program uninstall-ad uninstall-kde uninstall-man
 
 install-strip:
        $(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' \
@@ -302,6 +302,40 @@ install-pam:
          fi ;                                                          \
        fi
 
+install-kde:
+       @src="$(srcdir)/xscreensaver.kss" ;                                   \
+       if [ "$$KDEDIR" != "" ]; then                                         \
+         dir="$$KDEDIR/bin" ;                                                \
+         dest="$$dir/xscreensaver.kss" ;                                     \
+         echo $(INSTALL_PROGRAM) $$src $$dest ;                              \
+         if $(INSTALL_PROGRAM) $$src $$dest ; then                           \
+           true ;                                                            \
+         else                                                                \
+           e=echo ;                                                          \
+ $$e ""                                                                             ;\
+ $$e "  ####################################################################";\
+ $$e "  Warning: unable to install $$dest"                                  ;\
+           if [ ! -d $$KDEDIR ]; then                                        \
+ $$e "           $$KDEDIR (\$$KDEDIR) does not exist."                      ;\
+           elif [ ! -d $$KDEDIR/bin ]; then                                  \
+ $$e "           $$KDEDIR/bin (\$$KDEDIR/bin) does not exist."              ;\
+           elif [ -f $$dest ]; then                                          \
+ $$e "           That file exists, and is unwritable."                      ;\
+           else                                                              \
+ $$e "           The directory is unwritable."                              ;\
+           fi                                                               ;\
+ $$e "  ####################################################################";\
+ $$e ""                                                                             ;\
+           exit 1 ;                                                          \
+         fi ;                                                                \
+       fi
+
+uninstall-kde:
+       @if [ "$$KDEDIR" != "" ]; then                                  \
+         dest="$$KDEDIR/bin/xscreensaver.kss" ;                        \
+         echo rm -f $$dest ;                                           \
+         rm -f $$dest ;                                                \
+       fi
 
 clean:
        -rm -f *.o a.out core $(EXES) $(EXES2) XScreenSaver_ad.h
index ca7285b98a8e2cc65516acdcd4ebc2fa135a723c..076cd748564fea97e30da479a893405924abad21 100644 (file)
@@ -4,8 +4,8 @@
 !            a screen saver and locker for the X window system
 !                            by Jamie Zawinski
 !
-!                              version 3.17
-!                                15-Jul-99
+!                              version 3.18
+!                                13-Oct-99
 !
 ! See "man xscreensaver" for more info.  The latest version is always
 ! available at http://www.jwz.org/xscreensaver/
 *loadURL: netscape -remote 'openURL(%s)' || netscape '%s'
 
 
+! The format used for printing the date and time in the password dialog box
+! (see the strftime(3) manual page for details.)
+*dateFormat:           %d-%b-%y (%a); %I:%M %p
+! To show the time only:
+! *dateFormat:         %I:%M %p
+! For 24 hour time:
+! *dateFormat:         %H:%M
+
+
 ! Turning on "installColormap" interacts erratically with twm and tvtwm,
 ! but seems to work fine with mwm and olwm.  Try it and see.  If your
 ! screen turns some color other than black, the window manager is buggy,
                   -minlifespan 1 -maxlifespan 1 -instantdeathchan 0      \
                   -minorchan 0 -anychan 0.3                            \n\
                shadebobs -root                                         \n\
+               ccurve -root                                            \n\
+               blaster -root                                           \n\
+               bumps -root                                             \n\
     default-n:  webcollage -root                                       \n\
  -  default-n: webcollage -root -filter 'vidwhacker -stdin -stdout'    \n\
  -  default-n: vidwhacker -root                                        \n\
 !     default-n:  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\
+!
 ! 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
 ! specifying the command-line arguments "-visual default -no-install".
-! This is necessary because, when XV is running in "-root" mode, it always
-! assumes that the default visual and colormap are being used, rather than 
-! examining the window it is drawing on to see what visual and colormap it
-! has.  If we didn't force the default visual to be used, xv would get an
+! This is necessary because, when XV or XLI arerunning in "-root" mode, they
+! always assume that the default visual and colormap are being used, rather
+! than  examining the window it is drawing on to see what visual and colormap
+! it has.  If we didn't force the default visual to be used, we would get an
 ! X error.  If we didn't force the default colormap to be installed, the
 ! colors would be all wrong.  "default-i" may also be used as a visual name
 ! (meaning, "-visual default -install") but you probably won't ever need
@@ -327,6 +350,7 @@ XScreenSaver.bourneShell:           /bin/sh
 *Dialog.bodyFont:              *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1
 *Dialog.labelFont:             *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1
 *Dialog.buttonFont:            *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1
+*Dialog.dateFont:              *-courier-medium-r-*-*-*-80-*-*-*-iso8859-1
 *Dialog.foreground:            #000000
 *Dialog.background:            #BFBFBF
 *Dialog.Button.foreground:     #000000
index 104a5161dea39ea3c260c64b849ff1cd571402e5..73e756f43bc52504e184fc675f6dd7113237eba6 100644 (file)
@@ -27,6 +27,7 @@
 "*prefsCommand: xscreensaver-demo -prefs",
 "*helpURL: http://www.jwz.org/xscreensaver/man.html",
 "*loadURL: netscape -remote 'openURL(%s)' || netscape '%s'",
+"*dateFormat:          %d-%b-%y (%a); %I:%M %p",
 "*installColormap:     True",
 "*programs:    qix -root -solid -delay 0 -segments 100                 \\n\
                qix -root -count 4 -solid -transparent                  \\n\
                   -minlifespan 1 -maxlifespan 1 -instantdeathchan 0      \
                   -minorchan 0 -anychan 0.3                            \\n\
                shadebobs -root                                         \\n\
+               ccurve -root                                            \\n\
+               blaster -root                                           \\n\
+               bumps -root                                             \\n\
     default-n:  webcollage -root                                       \\n\
  -  default-n: webcollage -root -filter 'vidwhacker -stdin -stdout'    \\n\
  -  default-n: vidwhacker -root                                        \\n\
 "*Dialog.bodyFont:             *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1",
 "*Dialog.labelFont:            *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1",
 "*Dialog.buttonFont:           *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1",
+"*Dialog.dateFont:             *-courier-medium-r-*-*-*-80-*-*-*-iso8859-1",
 "*Dialog.foreground:           #000000",
 "*Dialog.background:           #BFBFBF",
 "*Dialog.Button.foreground:    #000000",
index 31d9138fc98aacd87a8173f42d1a5a5d3b6efe6c..6d498b199fdf835ff38172ca05c0a1ac33edfe3c 100644 (file)
@@ -20,6 +20,7 @@
 #ifndef NO_LOCKING   /* whole file */
 
 #include <X11/Intrinsic.h>
+#include <X11/Xos.h>           /* for time() */
 #include "xscreensaver.h"
 #include "resources.h"
 
@@ -89,6 +90,7 @@ struct passwd_dialog_data {
   char *body_label;
   char *user_label;
   char *passwd_label;
+  char *date_label;
   char *user_string;
   char *passwd_string;
 
@@ -96,6 +98,7 @@ struct passwd_dialog_data {
   XFontStruct *body_font;
   XFontStruct *label_font;
   XFontStruct *passwd_font;
+  XFontStruct *date_font;
 
   Pixel foreground;
   Pixel background;
@@ -149,6 +152,7 @@ make_passwd_window (saver_info *si)
                                        "Dialog.Label.Label");
   pw->passwd_label = get_string_resource ("passwd.passwd.label",
                                          "Dialog.Label.Label");
+  pw->date_label = get_string_resource ("dateFormat", "DateFormat");
 
   if (!pw->heading_label)
     pw->heading_label = strdup("ERROR: REESOURCES NOT INSTALLED CORRECTLY");
@@ -156,6 +160,7 @@ make_passwd_window (saver_info *si)
     pw->body_label = strdup("ERROR: REESOURCES NOT INSTALLED CORRECTLY");
   if (!pw->user_label) pw->user_label = strdup("ERROR");
   if (!pw->passwd_label) pw->passwd_label = strdup("ERROR");
+  if (!pw->date_label) pw->date_label = strdup("ERROR");
 
   /* Put the version number in the label. */
   {
@@ -188,6 +193,11 @@ make_passwd_window (saver_info *si)
   if (!pw->passwd_font) pw->passwd_font = XLoadQueryFont (si->dpy, "fixed");
   if (f) free (f);
 
+  f = get_string_resource("passwd.dateFont", "Dialog.Font");
+  pw->date_font = XLoadQueryFont (si->dpy, (f ? f : "fixed"));
+  if (!pw->date_font) pw->date_font = XLoadQueryFont (si->dpy, "fixed");
+  if (f) free (f);
+
   pw->foreground = get_pixel_resource ("passwd.foreground",
                                       "Dialog.Foreground",
                                       si->dpy, cmap);
@@ -396,7 +406,9 @@ draw_passwd_window (saver_info *si)
            pw->body_font->ascent + pw->body_font->descent +
            (2 * MAX ((pw->label_font->ascent + pw->label_font->descent),
                      (pw->passwd_font->ascent + pw->passwd_font->descent +
-                      (pw->shadow_width * 4)))));
+                      (pw->shadow_width * 4)))) +
+            pw->date_font->ascent + pw->date_font->descent
+            );
   spacing = ((pw->height - (2 * pw->shadow_width) -
              pw->internal_border - height)) / 8;
   if (spacing < 0) spacing = 0;
@@ -504,6 +516,26 @@ draw_passwd_window (saver_info *si)
                         pw->shadow_width,
                         pw->shadow_bottom, pw->shadow_top);
 
+
+  /* The date, below the text fields
+   */
+  {
+    char buf[100];
+    time_t now = time ((time_t *) 0);
+    struct tm *tm = localtime (&now);
+    memset (buf, 0, sizeof(buf));
+    strftime (buf, sizeof(buf)-1, pw->date_label, tm);
+
+    XSetFont (si->dpy, gc1, pw->date_font->fid);
+    y1 += pw->shadow_width;
+    y1 += (spacing + tb_height);
+    y1 += spacing/2;
+    sw = string_width (pw->date_font, buf);
+    x2 = x1 + x2 - sw;
+    XDrawString (si->dpy, si->passwd_dialog, gc1, x2, y1, buf, strlen(buf));
+  }
+
+
   /* the logo
    */
   XSetForeground (si->dpy, gc1, pw->logo_foreground);
index ded26972a547d1b1241ff25f43605b45bb88e01b..205e43bdfe3d6df570542e58c35aa38beee5303a 100644 (file)
@@ -803,12 +803,17 @@ get_screen_viewport (saver_screen_info *ssi,
 #ifdef HAVE_XF86VMODE
   saver_info *si = ssi->global;
   int screen_no = screen_number (ssi->screen);
-  int event, error;
+  int op, event, error;
   int dot;
   XF86VidModeModeLine ml;
   int x, y;
 
-  if (XF86VidModeQueryExtension (si->dpy, &event, &error) &&
+  /* Check for Xinerama first, because the VidModeExtension is broken
+     when Xinerama is present.  Wheee!
+   */
+
+  if (!XQueryExtension (si->dpy, "XINERAMA", &op, &event, &error) &&
+      XF86VidModeQueryExtension (si->dpy, &event, &error) &&
       XF86VidModeGetModeLine (si->dpy, screen_no, &dot, &ml) &&
       XF86VidModeGetViewPort (si->dpy, screen_no, &x, &y))
     {
@@ -822,6 +827,35 @@ get_screen_viewport (saver_screen_info *ssi,
         /* There is no viewport -- the screen does not scroll. */
         return;
 
+
+      /* Apparently some versions of XFree86 return nonsense here!
+         I've had reports of 1024x768 viewports at -1936862040, -1953705044.
+         So, sanity-check the values and give up if they are out of range.
+       */
+      if (*x_ret <  0 || *x_ret >= w ||
+          *y_ret <  0 || *y_ret >= h ||
+          *w_ret <= 0 || *w_ret >  w ||
+          *h_ret <= 0 || *h_ret >  h)
+        {
+          static int warned_once = 0;
+          if (!warned_once)
+            {
+              fprintf (stderr, "\n"
+                  "%s: X SERVER BUG: %dx%d viewport at %d,%d is impossible.\n"
+                  "%s: The XVidMode server extension is returning nonsense.\n"
+                  "%s: Please report this bug to your X server vendor.\n\n",
+                       blurb(), *w_ret, *h_ret, *x_ret, *y_ret,
+                       blurb(), blurb());
+              warned_once = 1;
+            }
+          *x_ret = 0;
+          *y_ret = 0;
+          *w_ret = w;
+          *h_ret = h;
+          return;
+        }
+          
+
       sprintf (msg, "%s: vp is %dx%d+%d+%d",
                blurb(), *w_ret, *h_ret, *x_ret, *y_ret);
 
index 9b5ed9a2dd7dc9a59bb27d89909768a405cb5ec8..7d1802a1f33643cb5ce7c98c779fb9dd14b3faad 100644 (file)
@@ -11,7 +11,7 @@
 .if n .sp 1
 .if t .sp .5
 ..
-.TH XScreenSaver 1 "15-Jul-99 (3.17)" "X Version 11"
+.TH XScreenSaver 1 "13-Oct-99 (3.18)" "X Version 11"
 .SH NAME
 xscreensaver-command - control a running xscreensaver process
 .SH SYNOPSIS
index c54c23e638623753d9fec9acec2439daca9d0746..cb555b1b3a7a5b1b65b85b73f6e27083f990b6e0 100644 (file)
@@ -11,7 +11,7 @@
 .if n .sp 1
 .if t .sp .5
 ..
-.TH XScreenSaver 1 "15-Jul-99 (3.17)" "X Version 11"
+.TH XScreenSaver 1 "13-Oct-99 (3.18)" "X Version 11"
 .SH NAME
 xscreensaver-demo - interactively control the background xscreensaver daemon
 .SH SYNOPSIS
index c88f36cc9fed32fbc009d333a6f6cc7ab2a13d39..dead85d6c3ec90bed0d501acef5a42781010acb5 100644 (file)
@@ -1523,7 +1523,8 @@ analyze_display (saver_info *si)
     { "DOUBLE-BUFFER",           "Double-Buffering" },
     { "DPMS",                    "Power Management" },
     { "GLX",                     "GLX" },
-    { "XFree86-VidModeExtension", "XF86 Video-Mode" }
+    { "XFree86-VidModeExtension", "XF86 Video-Mode" },
+    { "XINERAMA",                "Xinerama" }
   };
 
   fprintf (stderr, "%s: running on display \"%s\"\n", blurb(),
index 9e75c783097ac814d6f76a1b5407cadd95e11a18..f54ebcf0368f4d5e871c5ff6cea8d8ac841df397 100644 (file)
@@ -304,9 +304,9 @@ extern Bool unlock_p (saver_info *si);
 extern Bool lock_priv_init (int argc, char **argv, Bool verbose_p);
 extern Bool lock_init (int argc, char **argv, Bool verbose_p);
 extern Bool passwd_valid_p (const char *typed_passwd, Bool verbose_p);
-extern void set_locked_p (saver_info *si, Bool locked_p);
 #endif /* NO_LOCKING */
 
+extern void set_locked_p (saver_info *si, Bool locked_p);
 extern int move_mouse_grab (saver_info *si, Window to, Cursor cursor);
 
 
diff --git a/driver/xscreensaver.kss b/driver/xscreensaver.kss
new file mode 100755 (executable)
index 0000000..98ad08e
--- /dev/null
@@ -0,0 +1,146 @@
+#!/bin/bash -
+
+# script - "xscreensaver.kss"
+#
+# Author: Shane Smit <shane_smit@calderasystems.com>
+#
+# Modification History:
+#  [08/23/1999] - Shane Smit: Creation
+#
+# Description:
+#  This script file enables users to use XScreenSaver via the
+#  KDE Display Properties. 
+
+# 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.
+
+
+# Locking is turned off by default.
+lockmode="-no-lock-mode"
+
+while [ -n "$1" ]; do
+  case "$1" in
+
+    -desc) 
+      # This is the name in the list box.
+      echo "XScreenSaver"
+      exit
+      ;;
+
+    -preview)
+      # This simply runs xroger in the preview window.  For this to be "real",
+      # it needs to run xscreensaver with a -window-id parameter for each hack.
+      # There are two ways to do this:
+      # 1) Hack xscreensaver to allow global parameters.
+      # 2) Hack xscreensaver to accept alternate setup files, and create one on
+      #    the fly here.
+      shift
+      /usr/X11R6/lib/xscreensaver/xroger -delay 1 -window-id $1 &    # Start new preview 
+      echo "$!" > $HOME/.kss-preview$1.pid.`hostname`                # Write PID 
+      wait $!                                                       # Wait for it to get killed
+      exit
+      ;;
+
+    -setup)
+      /usr/X11R6/bin/xscreensaver -no-splash &     # daemon must be started
+      /usr/X11R6/bin/xscreensaver-demo             # or the setup will produce
+      kill $!                                      # a warning.
+      exit
+      ;;
+
+    -test)
+      # I was unable to grep stdout because xscreensaver nabs it. But I was able
+      # to output it to a file, and grep the file.
+      TEMP_FILE=/tmp/xsc.$RANDOM
+      /usr/X11R6/bin/xscreensaver -no-splash -verbose -no-capture-stderr 2> $TEMP_FILE &
+      /usr/X11R6/bin/xscreensaver-command -activate
+      while true; do
+        ExitNow=$(grep -E -c unblanking\|already $TEMP_FILE)
+        if [ $ExitNow != 0 ]; then
+          kill $!
+          rm $TEMP_FILE
+          exit
+        fi
+        sleep 1
+      done
+      exit     # It should never get this far.
+      ;;
+
+#    -corners)
+#      echo "Not yet supported"
+#      ;;
+    -delay)
+      shift
+      timeout="-timeout $1"
+      ;;
+    -install)
+      Install="TRUE"
+      ;;
+    -lock)
+      if [ ! -f "/etc/shadow" ]; then      
+        lockmode="-lock-mode"
+      fi
+      ;;
+#    -allow-root)
+#      echo "Not yet supported"
+#      ;;
+    -nice)
+      shift
+      Nice="-nice $1"
+      ;;
+#    -inroot)
+#      echo "Not yet supported"
+#      ;;
+    *)
+      echo "Unknown parameter: $1"
+      ;;
+  esac
+  shift
+done
+
+if [ -n "$Install" ] ; then
+  rm $HOME/.kss-preview*                                # Remove old preview files
+  PID_FILE=$HOME/.kss-install.pid.`hostname`
+  kill `cat $PID_FILE`                                  # Kill old screensaver 
+  echo "$$" > $PID_FILE                                 # Write PID of this script
+  /usr/X11R6/bin/xscreensaver -no-splash $timeout $lockmode $Nice &    # Start XScreenSaver daemon
+  trap "kill $!" SIGTERM                                # Set these to kill the daemon
+  trap "kill $!" SIGKILL
+
+  if [ -f "/etc/shadow" ]; then
+    # xscreensaver is run as the user, which has no access to the /etc/shadow file.  Other
+    # .kss screensavers use kcheckpass, which would have to be hacked into xscreensaver to
+    # work correctly. This just activates the screensaver with no password lock.
+    trap "/usr/X11R6/bin/xscreensaver-command -activate" SIGUSR1
+  else
+    # xscreensaver can be locked, because it can read the /etc/passwd file.
+    trap "/usr/X11R6/bin/xscreensaver-command -lock" SIGUSR1
+  fi
+
+  wait $!                                               # Do not exit, just wait for signals.
+
+else
+  echo "Usage: ./xscreensaver.kss -install|-setup|-test|-desc [-delay num] [-lock] [-nice num]"
+#  echo "  -corners xxxx     Placing cursor in corner performs action:"
+#  echo "                     x = i  no action (ignore)"
+#  echo "                     x = s  save screen"
+#  echo "                     x = l  lock screen"
+#  echo "                    order: top-left, top-right, bottom-left, bottom-right"
+  echo "  -delay num        Amount of idle time before screen saver starts  (default 10min)"
+  echo "  -desc             Print the screen saver's description to stdout"
+  echo "  -install          Install screen saver"
+  echo "  -lock             Require password to stop screen saver"
+#  echo "  -allow-root       Accept root password to unlock"
+  echo "  -nice num         Run with specified nice value"
+  echo "  -preview wid      Run in the specified XWindow"
+#  echo "  -inroot           Run in the root window"
+  echo "  -setup            Setup screen saver"
+  echo "  -test             Invoke the screen saver immediately"
+fi
+
+# End of script - "xscreensaver.kss"
index e974833f7ef91afd8aa9e2508c368d00103130a5..8b2a70b73366e7d7dc7be0691dcead563f66d4bc 100644 (file)
@@ -11,7 +11,7 @@
 .if n .sp 1
 .if t .sp .5
 ..
-.TH XScreenSaver 1 "15-Jul-99 (3.17)" "X Version 11"
+.TH XScreenSaver 1 "13-Oct-99 (3.18)" "X Version 11"
 .SH NAME
 xscreensaver - graphics hack and screen locker, launched when the user is idle
 .SH SYNOPSIS
index 4f186cf38268714134c62b2af432dd9f6d5fbc4d..cd1921ac41a95379dc7d83bfc31bb8dc3aa04107 100644 (file)
@@ -84,7 +84,8 @@ SRCS          = attraction.c blitspin.c bouboule.c braid.c bubbles.c \
                  truchet.c bsod.c crystal.c discrete.c distort.c kumppa.c \
                  sonar.c demon.c loop.c t3d.c penetrate.c deluxe.c compass.c \
                  squiral.c xflame.c wander.c spotlight.c critical.c \
-                 phosphor.c xmatrix.c petri.c shadebobs.c xsublim.c
+                 phosphor.c xmatrix.c petri.c shadebobs.c xsublim.c ccurve.c \
+                 blaster.c bumps.c
 SCRIPTS                = vidwhacker webcollage
 
 OBJS           = attraction.o blitspin.o bouboule.o braid.o bubbles.o \
@@ -102,7 +103,8 @@ OBJS                = attraction.o blitspin.o bouboule.o braid.o bubbles.o \
                  truchet.o bsod.o crystal.o discrete.o distort.o kumppa.o \
                  sonar.o demon.o loop.o t3d.o penetrate.o deluxe.o compass.o \
                  squiral.o xflame.o wander.o spotlight.o critical.o \
-                 phosphor.o xmatrix.o petri.o shadebobs.o xsublim.o
+                 phosphor.o xmatrix.o petri.o shadebobs.o xsublim.o ccurve.o \
+                 blaster.o bumps.o
 
 EXES           = attraction blitspin bouboule braid bubbles decayscreen deco \
                  drift flag flame forest vines galaxy grav greynetic halo \
@@ -115,7 +117,7 @@ EXES                = attraction blitspin bouboule braid bubbles decayscreen deco \
                  interference truchet bsod crystal discrete distort kumppa \
                  sonar demon loop t3d penetrate deluxe compass squiral \
                  xflame wander spotlight critical phosphor xmatrix petri \
-                 shadebobs xsublim
+                 shadebobs xsublim ccurve blaster bumps
 
 HACK_OBJS_1    = $(UTILS_BIN)/resources.o $(UTILS_BIN)/visual.o \
                  $(UTILS_BIN)/usleep.o $(UTILS_BIN)/yarandom.o @XMU_OBJS@
@@ -128,7 +130,8 @@ XSHM_OBJS   = $(UTILS_BIN)/xshm.o
 XDBE_OBJS      = $(UTILS_BIN)/xdbe.o
 GRAB_LIBS      = $(SGI_VIDEO_LIBS)
 
-HDRS           = bubbles.h screenhack.h xlockmore.h xlockmoreI.h automata.h
+HDRS           = bubbles.h screenhack.h xlockmore.h xlockmoreI.h automata.h \
+                 bumps.h
 MEN            = attraction.man blitspin.man bouboule.man braid.man \
                  bubbles.man decayscreen.man deco.man drift.man flag.man \
                  flame.man forest.man vines.man galaxy.man grav.man \
@@ -141,7 +144,7 @@ MEN         = attraction.man blitspin.man bouboule.man braid.man \
                  xroger.man goop.man starfish.man munch.man rd-bomb.man \
                  xjack.man xlyap.man jigsaw.man epicycle.man bsod.man \
                  sonar.man t3d.man squiral.man spotlight.man critical.man \
-                 vidwhacker.man webcollage.man
+                 vidwhacker.man webcollage.man xsublim.man
 STAR           = *
 EXTRAS         = README Makefile.in xlock_23.h .gdbinit \
                  images/$(STAR).xbm \
@@ -534,6 +537,15 @@ petri:             petri.o         $(HACK_OBJS) $(COL) $(SPL)
 shadebobs:     shadebobs.o     $(HACK_OBJS) $(COL) $(SPL)
        $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(COL) $(SPL) $(HACK_LIBS)
 
+ccurve:                ccurve.o        $(HACK_OBJS) $(COL) $(SPL)
+       $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(COL) $(ERASE) $(HACK_LIBS)
+
+blaster:       blaster.o       $(HACK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(HACK_LIBS)
+
+bumps: bumps.o                 $(HACK_OBJS) $(GRAB)
+       $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(GRAB) $(HACK_LIBS) $(GRAB_LIBS)
+
 
 # The rules for those hacks which follow the `xlockmore' API.
 #
@@ -805,8 +817,8 @@ flame.o: $(UTILS_SRC)/hsv.h
 flame.o: $(UTILS_SRC)/colors.h
 flame.o: $(UTILS_SRC)/grabscreen.h
 flame.o: $(UTILS_SRC)/visual.h
-forest.o: $(srcdir)/xlockmore.h
 forest.o: ../config.h
+forest.o: $(srcdir)/xlockmore.h
 forest.o: $(srcdir)/xlockmoreI.h
 forest.o: $(srcdir)/screenhack.h
 forest.o: $(UTILS_SRC)/yarandom.h
@@ -817,7 +829,6 @@ forest.o: $(UTILS_SRC)/colors.h
 forest.o: $(UTILS_SRC)/grabscreen.h
 forest.o: $(UTILS_SRC)/visual.h
 forest.o: $(UTILS_SRC)/xshm.h
-forest.o: $(UTILS_SRC)/erase.h
 vines.o: $(srcdir)/xlockmore.h
 vines.o: ../config.h
 vines.o: $(srcdir)/xlockmoreI.h
@@ -1685,4 +1696,33 @@ shadebobs.o: $(UTILS_SRC)/grabscreen.h
 shadebobs.o: $(UTILS_SRC)/visual.h
 xsublim.o: $(UTILS_SRC)/usleep.h
 xsublim.o: $(UTILS_SRC)/resources.h
+ccurve.o: $(srcdir)/screenhack.h
+ccurve.o: ../config.h
+ccurve.o: $(UTILS_SRC)/yarandom.h
+ccurve.o: $(UTILS_SRC)/usleep.h
+ccurve.o: $(UTILS_SRC)/resources.h
+ccurve.o: $(UTILS_SRC)/hsv.h
+ccurve.o: $(UTILS_SRC)/colors.h
+ccurve.o: $(UTILS_SRC)/grabscreen.h
+ccurve.o: $(UTILS_SRC)/visual.h
+ccurve.o: $(UTILS_SRC)/erase.h
+blaster.o: $(srcdir)/screenhack.h
+blaster.o: ../config.h
+blaster.o: $(UTILS_SRC)/yarandom.h
+blaster.o: $(UTILS_SRC)/usleep.h
+blaster.o: $(UTILS_SRC)/resources.h
+blaster.o: $(UTILS_SRC)/hsv.h
+blaster.o: $(UTILS_SRC)/colors.h
+blaster.o: $(UTILS_SRC)/grabscreen.h
+blaster.o: $(UTILS_SRC)/visual.h
+bumps.o: $(srcdir)/bumps.h
+bumps.o: $(srcdir)/screenhack.h
+bumps.o: ../config.h
+bumps.o: $(UTILS_SRC)/yarandom.h
+bumps.o: $(UTILS_SRC)/usleep.h
+bumps.o: $(UTILS_SRC)/resources.h
+bumps.o: $(UTILS_SRC)/hsv.h
+bumps.o: $(UTILS_SRC)/colors.h
+bumps.o: $(UTILS_SRC)/grabscreen.h
+bumps.o: $(UTILS_SRC)/visual.h
 
diff --git a/hacks/blaster.c b/hacks/blaster.c
new file mode 100644 (file)
index 0000000..c7cbd54
--- /dev/null
@@ -0,0 +1,1109 @@
+/* -*- mode: C; tab-width: 2 -*-
+ * blaster, Copyright (c) 1999 Jonathan H. Lin <jonlin@tesuji.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ *
+ *  Robots that move randomly and shoot lasers at each other. If the
+ *  mothership is active, it will fly back and forth horizontally, 
+ *  firing 8 lasers in the 8 cardinal directions. The explosions are
+ *  a 20 frame animation. Robots regenerate after the explosion is finished
+ *  and all of its lasers have left the screen.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include "screenhack.h"
+
+static Display *dpy;
+static Window window;
+static GC r_color0, r_color1, r_color2, r_color3, r_color4, r_color5, l_color0, l_color1;
+static GC s_color;
+static GC black;
+
+static int delay;
+
+static int NUM_ROBOTS=5;
+static int NUM_LASERS=3;
+
+static int MOTHER_SHIP=0;
+static int MOTHER_SHIP_WIDTH=25;
+static int MOTHER_SHIP_HEIGHT=7;
+static int MOTHER_SHIP_LASER=15;
+static int MOTHER_SHIP_PERIOD=150;
+static int MOTHER_SHIP_HITS=10;
+
+static int LINE_MOVE_STYLE=0;
+static int RANDOM_MOVE_STYLE=1;
+static int NUM_MOVE_STYLES=2;
+
+static int EXPLODE_SIZE_1=27;
+static int EXPLODE_SIZE_2=19;
+static int EXPLODE_SIZE_3=7;
+static GC EXPLODE_COLOR_1;
+static GC EXPLODE_COLOR_2;
+
+struct laser_state {
+       int active;
+       int start_x,start_y;
+       int end_x, end_y;
+};
+
+struct robot_state {
+       int alive;
+       int death;
+
+       int move_style;
+       int target;
+
+       int old_x, old_y;
+       int new_x, new_y;
+
+       int radius;
+       GC robot_color;
+       GC laser_color;
+       struct laser_state *lasers;
+};
+
+struct mother_ship_state {
+       int active;
+       int death;
+       int old_x,new_x;
+       int y;
+       GC ship_color;
+       GC laser_color;
+       struct laser_state *lasers;
+};
+
+static XArc *stars;
+static int NUM_STARS;
+static int MOVE_STARS;
+static int MOVE_STARS_X;
+static int MOVE_STARS_Y;
+static int MOVE_STARS_RANDOM;
+
+static struct mother_ship_state *mother;
+
+static struct robot_state *robots;
+
+XWindowAttributes xgwa;
+
+
+
+
+/* creates a new robot. It starts out on one of the edges somewhere and
+       has no initial velocity. A target is randomly picked. */
+static void make_new_robot(int index)
+{
+       int laser_check = 0;
+       int x=0;
+
+       for(x=0;x<NUM_LASERS;x++) {
+               if(robots[index].lasers[x].active) {
+                       x=NUM_LASERS;
+                       laser_check = 1;
+               }
+       }
+       if(laser_check==0) {
+               robots[index].alive=1;
+
+               robots[index].radius = 7+(random()%7);
+
+               robots[index].move_style = random()%NUM_MOVE_STYLES;
+               if(random()%2==0) {
+                       robots[index].new_x=random()%(xgwa.width-robots[index].radius);
+                       robots[index].old_x=robots[index].new_x;
+                       if(random()%2==0) {
+                               robots[index].new_y=0;
+                               robots[index].old_y=0;
+                       }
+                       else {
+                               robots[index].new_y=xgwa.height-robots[index].radius;
+                               robots[index].old_y = robots[index].new_y;
+                       }
+               }
+               else {
+                       robots[index].new_y=random()%(xgwa.height-robots[index].radius);
+                       robots[index].old_y = robots[index].new_y;
+                       if(random()%2) {
+                               robots[index].new_x=0;
+                               robots[index].old_x=0;
+                       }
+                       else {
+                               robots[index].new_x=xgwa.width-robots[index].radius;
+                               robots[index].old_x=robots[index].new_x;
+                       }
+               }
+                       
+               x=random()%6;
+               if(x==0) {
+                       robots[index].robot_color = r_color0;
+               }
+               else if(x==1) {
+                       robots[index].robot_color = r_color1;
+               }
+               else if(x==2) {
+                       robots[index].robot_color = r_color2;
+               }
+               else if(x==3) {
+                       robots[index].robot_color = r_color3;
+               }
+               else if(x==4) {
+                       robots[index].robot_color = r_color4;
+               }
+               else if(x==5) {
+                       robots[index].robot_color = r_color5;
+               }
+
+               if(random()%2==0) {
+                       robots[index].laser_color = l_color0;
+               }
+               else {
+                       robots[index].laser_color = l_color1;
+               }
+
+               if(NUM_ROBOTS>1) {
+                       robots[index].target = random()%NUM_ROBOTS;
+                       while(robots[index].target==index) {
+                               robots[index].target = random()%NUM_ROBOTS;
+                       }       
+               }
+       }
+}
+
+/* moves each robot, randomly changing its direction and velocity.
+       At random a laser is shot toward that robot's target. Also at random
+       the target can change. */
+static void move_robots(void)
+{
+       int x=0;
+       int y=0;
+       int dx=0;
+       int dy=0;
+       int target_x = 0;
+       int target_y = 0;
+       double slope = 0;
+
+       for(x=0;x<NUM_ROBOTS;x++) {
+               if(robots[x].alive) {
+                       if((robots[x].new_x == robots[x].old_x) && (robots[x].new_y == robots[x].old_y)) {
+                               if(robots[x].new_x==0) {
+                                       robots[x].old_x = -((random()%3)+1);
+                               }
+                               else {
+                                       robots[x].old_x = robots[x].old_x + (random()%3)+1;
+                               }
+                               if(robots[x].new_y==0) {
+                                       robots[x].old_y = -((random()%3)+1);
+                               }
+                               else {
+                                       robots[x].old_y = robots[x].old_y + (random()%3)+1;
+                               }
+                       }
+                       if(robots[x].move_style==LINE_MOVE_STYLE) {
+                               dx = robots[x].new_x - robots[x].old_x;
+                               dy = robots[x].new_y - robots[x].old_y;
+                               if(dx > 3) {
+                                       dx = 3;
+                               }
+                               else if(dx < -3) {
+                                       dx = -3;
+                               }
+                               if(dy > 3) {
+                                       dy = 3;
+                               }
+                               else if(dy < -3) {
+                                       dy = -3;
+                               }
+                               robots[x].old_x = robots[x].new_x;
+                               robots[x].old_y = robots[x].new_y;
+
+                               robots[x].new_x = robots[x].new_x + dx;
+                               robots[x].new_y = robots[x].new_y + dy;
+                       }
+                       else if(robots[x].move_style==RANDOM_MOVE_STYLE) {
+                               dx = robots[x].new_x - robots[x].old_x;
+                               dy = robots[x].new_y - robots[x].old_y;
+                               y=random()%3;
+                               if(y==0) {
+                                       dx = dx - ((random()%7)+1);
+                               }
+                               else if(y==1){
+                                       dx = dx + ((random()%7)+1);
+                               }
+                               else {
+                                       dx = (-1)*dx;
+                               }
+                               if(dx > 3) {
+                                       dx = 3;
+                               }
+                               else if(dx < -3) {
+                                       dx = -3;
+                               }
+
+                               y = random()%3;
+                               if(y==0) {
+                                       dy = dy - ((random()%7)+1);
+                               }
+                               else if(y==1){
+                                       dy = dy + ((random()%7)+1);
+                               }
+                               else {
+                                       dx = (-1)*dx;
+                               }
+                               if(dy > 3) {
+                                       dy = 3;
+                               }
+                               else if(dy < -3) {
+                                       dy = -3;
+                               }
+                               robots[x].old_x = robots[x].new_x;
+                               robots[x].old_y = robots[x].new_y;
+
+                               robots[x].new_x = robots[x].new_x + dx;
+                               robots[x].new_y = robots[x].new_y + dy;
+                       }
+
+                       /* bounds corrections */
+                       if(robots[x].new_x >= xgwa.width-robots[x].radius) {
+                               robots[x].new_x = xgwa.width - robots[x].radius;
+                       }
+                       else if(robots[x].new_x < 0) {
+                               robots[x].new_x = 0;
+                       }
+                       if(robots[x].new_y >= xgwa.height-robots[x].radius) {
+                               robots[x].new_y = xgwa.height - robots[x].radius;
+                       }
+                       else if(robots[x].new_y < 0) {
+                               robots[x].new_y = 0;
+                       }
+               
+                       if(random()%10==0) {
+                               robots[x].move_style = 1;
+                       }
+                       else {
+                               robots[x].move_style = 0;
+                       }
+
+                       if(NUM_ROBOTS>1) {
+                               if(random()%2==0) {
+                                       if(random()%200==0) {
+                                               robots[x].target = random()%NUM_ROBOTS;
+                                               while(robots[x].target==x) {
+                                                       robots[x].target = random()%NUM_ROBOTS;
+                                               }       
+                                               for(y=0;y<NUM_LASERS;y++) {
+                                                       if(robots[x].lasers[y].active == 0) {
+                                                               robots[x].lasers[y].active = 1;
+                                                               if(random()%2==0) {
+                                                                       if(random()%2==0) {
+                                                                               robots[x].lasers[y].start_x = robots[x].new_x+robots[x].radius;
+                                                                               robots[x].lasers[y].start_y = robots[x].new_y+robots[x].radius;
+                                                                               robots[x].lasers[y].end_x = robots[x].lasers[y].start_x+7;
+                                                                               robots[x].lasers[y].end_y = robots[x].lasers[y].start_y+7;
+                                                                       }
+                                                                       else {
+                                                                               robots[x].lasers[y].start_x = robots[x].new_x-robots[x].radius;
+                                                                               robots[x].lasers[y].start_y = robots[x].new_y+robots[x].radius;
+                                                                               robots[x].lasers[y].end_x = robots[x].lasers[y].start_x-7;
+                                                                               robots[x].lasers[y].end_y = robots[x].lasers[y].start_y+7;
+                                                                       }
+                                                               }
+                                                               else {
+                                                                       if(random()%2==0) {
+                                                                               robots[x].lasers[y].start_x = robots[x].new_x-robots[x].radius;
+                                                                               robots[x].lasers[y].start_y = robots[x].new_y-robots[x].radius;
+                                                                               robots[x].lasers[y].end_x = robots[x].lasers[y].start_x-7;
+                                                                               robots[x].lasers[y].end_y = robots[x].lasers[y].start_y-7;
+                                                                       }
+                                                                       else {
+                                                                               robots[x].lasers[y].start_x = robots[x].new_x+robots[x].radius;
+                                                                               robots[x].lasers[y].start_y = robots[x].new_y-robots[x].radius;
+                                                                               robots[x].lasers[y].end_x = robots[x].lasers[y].start_x+7;
+                                                                               robots[x].lasers[y].end_y = robots[x].lasers[y].start_y-7;
+                                                                       }
+                                                               }
+                                                               y = NUM_LASERS;
+                                                       }
+                                               }
+                                       }
+                                       else {
+                                               for(y=0;y<NUM_LASERS;y++) {
+                                                       if(robots[x].lasers[y].active==0) {
+                                                               target_x = robots[robots[x].target].new_x;
+                                                               target_y = robots[robots[x].target].new_y;
+                                                               if((target_x-robots[x].new_x)!=0) {
+                                                                       slope = ((double)target_y-robots[x].new_y)/((double)(target_x-robots[x].new_x));
+
+                                                                       if((slope<1) && (slope>-1)) {
+                                                                               if(target_x>robots[x].new_x) {
+                                                                                       robots[x].lasers[y].start_x = robots[x].radius;
+                                                                                       robots[x].lasers[y].end_x = robots[x].lasers[y].start_x + 7;
+                                                                               }
+                                                                               else {
+                                                                                       robots[x].lasers[y].start_x = -robots[x].radius;
+                                                                                       robots[x].lasers[y].end_x = robots[x].lasers[y].start_x - 7;
+                                                                               }
+                                                                               robots[x].lasers[y].start_y = (int)(robots[x].lasers[y].start_x * slope);
+                                                                               robots[x].lasers[y].end_y = (int)(robots[x].lasers[y].end_x * slope);
+                                                                       }
+                                                                       else {
+                                                                               slope = (target_x-robots[x].new_x)/(target_y-robots[x].new_y);
+                                                                               if(target_y>robots[x].new_y) {
+                                                                                       robots[x].lasers[y].start_y = robots[x].radius;
+                                                                                       robots[x].lasers[y].end_y = robots[x].lasers[y].start_y + 7;
+                                                                               }
+                                                                               else {
+                                                                                       robots[x].lasers[y].start_y = -robots[x].radius;
+                                                                                       robots[x].lasers[y].end_y = robots[x].lasers[y].start_y + 7;
+                                                                               }
+                                                                               robots[x].lasers[y].start_x = (int)(robots[x].lasers[y].start_y * slope);;
+                                                                               robots[x].lasers[y].start_x = (int)(robots[x].lasers[y].end_y * slope);
+                                                                       }
+                                                                       robots[x].lasers[y].start_x = robots[x].lasers[y].start_x + robots[x].new_x;
+                                                                       robots[x].lasers[y].start_y = robots[x].lasers[y].start_y + robots[x].new_y;
+                                                                       robots[x].lasers[y].end_x = robots[x].lasers[y].end_x + robots[x].new_x;
+                                                                       robots[x].lasers[y].end_y = robots[x].lasers[y].end_y + robots[x].new_y;
+                                                               }
+                                                               else {
+                                                                       if(target_y > robots[x].new_y) {
+                                                                               robots[x].lasers[y].start_x = robots[x].new_x;
+                                                                               robots[x].lasers[y].start_y = robots[x].new_y+robots[x].radius;
+                                                                               robots[x].lasers[y].end_x = robots[x].new_x;
+                                                                               robots[x].lasers[y].end_y = robots[x].lasers[y].start_y+7;
+                                                                       }
+                                                                       else {
+                                                                               robots[x].lasers[y].start_x = robots[x].new_x;
+                                                                               robots[x].lasers[y].start_y = robots[x].new_y-robots[x].radius;
+                                                                               robots[x].lasers[y].end_x = robots[x].new_x;
+                                                                               robots[x].lasers[y].end_y = robots[x].lasers[y].start_y-7;
+                                                                       }
+                                                               }
+                                                       
+                                                               if((((robots[x].lasers[y].start_x - robots[x].lasers[y].end_x) > 7) || 
+                                                                        ((robots[x].lasers[y].end_x - robots[x].lasers[y].start_x) > 7)) &&  
+                                                                       (((robots[x].lasers[y].start_y - robots[x].lasers[y].end_y) > 7) || 
+                                                                        ((robots[x].lasers[y].end_y - robots[x].lasers[y].start_y) > 7))) {
+                                                               }
+                                                               else {
+                                                                       robots[x].lasers[y].active = 1;
+                                                                       y = NUM_LASERS;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+               else {
+                       if(robots[x].death==0) {
+                               make_new_robot(x);
+                       }
+               }
+       }
+
+}
+
+/* This moves a single laser one frame. collisions with other robots or
+       the mothership is checked. */
+static void move_laser(int rindex, int index)
+{
+       int x=0;
+       int y=0;
+       int z=0;
+       int dx=0;
+       int dy=0;
+       struct laser_state *laser;
+       if(rindex>=0) {
+               laser = robots[rindex].lasers;
+       }
+       else {
+               laser = mother->lasers;
+       }
+       if(laser[index].active) {
+               /* collision with other robots are checked here */
+               for(x=0;x<NUM_ROBOTS;x++) {
+                       if(x!=rindex) {
+                               if(robots[x].alive) {
+                                       y = laser[index].start_x-robots[x].new_x;
+                                       if(y<0) {
+                                               y = robots[x].new_x-laser[index].start_x;
+                                       }
+                                       z = laser[index].start_y-robots[x].new_y;
+                                       if(z<0) {
+                                               z = robots[x].new_y-laser[index].start_y;
+                                       }
+                                       if((z<robots[x].radius-1)&&(y<robots[x].radius-1)) {
+                                               robots[x].alive = 0;
+                                               robots[x].death = 20;
+                                               XFillArc(dpy, window, black, robots[x].old_x, robots[x].old_y, robots[x].radius, robots[x].radius, 0, 360*64);
+                                               XFillArc(dpy, window, black, robots[x].new_x, robots[x].new_y, robots[x].radius, robots[x].radius, 0, 360*64);
+                                               laser[index].active = 0;
+                                               x = NUM_ROBOTS;
+                                       }
+                                       else {
+                                               y = laser[index].end_x-robots[x].new_x;
+                                               if(y<0) {
+                                                       y = robots[x].new_x-laser[index].end_x;
+                                               }
+                                               z = laser[index].end_y-robots[x].new_y;
+                                               if(z<0) {
+                                                       z = robots[x].new_y-laser[index].end_y;
+                                               }
+                                               if((z<robots[x].radius-1)&&(y<robots[x].radius-1)) {
+                                                       robots[x].alive = 0;
+                                                       robots[x].death = 20;
+                                                       XFillArc(dpy, window, black, robots[x].old_x, robots[x].old_y, robots[x].radius, robots[x].radius, 0, 360*64);
+                                                       XFillArc(dpy, window, black, robots[x].new_x, robots[x].new_y, robots[x].radius, robots[x].radius, 0, 360*64);
+                                                       laser[index].active = 0;
+                                                       x = NUM_ROBOTS;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               if((MOTHER_SHIP)&&(rindex!=-1)) {
+                       if(laser[index].active) {
+                               if(mother->active) {
+                                       y = laser[index].start_x-mother->new_x;
+                                       if(y<0) {
+                                               y = mother->new_x-laser[index].start_x;
+                                       }
+                                       z = laser[index].start_y-mother->y;
+                                       if(z<0) {
+                                               z = mother->y-laser[index].start_y;
+                                       }
+                                       if((z<MOTHER_SHIP_HEIGHT-1)&&(y<MOTHER_SHIP_WIDTH-1)) {
+                                               laser[index].active = 0;
+                                               mother->active--;
+                                       }
+                                       else {
+                                               y = laser[index].end_x-mother->new_x;
+                                               if(y<0) {
+                                                       y = mother->new_x-laser[index].end_x;
+                                               }
+                                               z = laser[index].end_y-mother->y;
+                                               if(z<0) {
+                                                       z = mother->y-laser[index].end_y;
+                                               }
+                                               if((z<MOTHER_SHIP_HEIGHT-1)&&(y<MOTHER_SHIP_WIDTH-1)) {
+                                                       laser[index].active = 0;
+                                                       mother->active--;
+                                               }
+                                       }
+
+                                       if(mother->active==0) {
+                                               mother->death=20;
+                                       }
+                               }
+                       }
+               }
+
+               if(laser[index].active) {
+                       dx = laser[index].start_x - laser[index].end_x;
+                       dy = laser[index].start_y - laser[index].end_y;
+               
+                       laser[index].start_x = laser[index].end_x;
+                       laser[index].start_y = laser[index].end_y;
+                       laser[index].end_x = laser[index].end_x-dx;
+                       laser[index].end_y = laser[index].end_y-dy;
+                       
+                       if((laser[index].end_x < 0) || (laser[index].end_x >= xgwa.width) ||
+                               (laser[index].end_y < 0) || (laser[index].end_y >= xgwa.height)) {
+                               laser[index].active = 0;
+                       }                               
+               }
+       }
+}
+
+/* All the robots are drawn, including the mother ship and the explosions.
+       After all the robots have been drawn, their laser banks are check and
+       the active lasers are drawn. */
+static void draw_robots(void)
+{
+       int x=0;
+       int y=0;
+
+       for(x=0;x<NUM_ROBOTS;x++) {
+               if(robots[x].alive) {
+                       XFillArc(dpy, window, black, robots[x].old_x, robots[x].old_y, robots[x].radius, robots[x].radius, 0, 360*64);
+                       XFillArc(dpy, window, robots[x].robot_color, robots[x].new_x, robots[x].new_y, robots[x].radius, robots[x].radius, 0, 360*64);
+               }
+               else {
+                       XFillArc(dpy, window, black, robots[x].old_x, robots[x].old_y, robots[x].radius, robots[x].radius, 0, 360*64);
+                       if(robots[x].death) {
+                               if(robots[x].death==20) {
+                                       XFillArc(dpy, window, EXPLODE_COLOR_1, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(robots[x].death==18) {
+                                       XFillArc(dpy, window, EXPLODE_COLOR_2, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(robots[x].death==17) {
+                                       XFillArc(dpy, window, EXPLODE_COLOR_1, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(robots[x].death==15) {
+                                       XFillArc(dpy, window, black, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(robots[x].death==14) {
+                                       XFillArc(dpy, window, EXPLODE_COLOR_2, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(robots[x].death==13) {
+                                       XFillArc(dpy, window, black, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(robots[x].death==12) {
+                                       XFillArc(dpy, window, EXPLODE_COLOR_1, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(robots[x].death==11) {
+                                       XFillArc(dpy, window, black, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(robots[x].death==10) {
+                                       XFillArc(dpy, window, EXPLODE_COLOR_2, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(robots[x].death==9) {
+                                       XFillArc(dpy, window, black, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(robots[x].death==8) {
+                                       XFillArc(dpy, window, EXPLODE_COLOR_1, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(robots[x].death==7) {
+                                       XFillArc(dpy, window, black, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(robots[x].death==6) {
+                                       XFillArc(dpy, window, EXPLODE_COLOR_2, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_2, EXPLODE_SIZE_2, 0, 360*64);
+                               }
+                               else if(robots[x].death==4) {
+                                       XFillArc(dpy, window, black, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_2, EXPLODE_SIZE_2, 0, 360*64);
+                               }
+                               else if(robots[x].death==3) {
+                                       XFillArc(dpy, window, EXPLODE_COLOR_1, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_2, EXPLODE_SIZE_2, 0, 360*64);
+                               }
+                               else if(robots[x].death==2) {
+                                       XFillArc(dpy, window, black, robots[x].new_x+(robots[x].radius/3), robots[x].new_y+(robots[x].radius/3), EXPLODE_SIZE_2, EXPLODE_SIZE_2, 0, 360*64);
+                                       XFillArc(dpy, window, EXPLODE_COLOR_2, robots[x].new_x+(1.7*robots[x].radius/2), robots[x].new_y+(1.7*robots[x].radius/2), EXPLODE_SIZE_3, EXPLODE_SIZE_3, 0, 360*64);
+                               }
+                               else if(robots[x].death==1) {
+                                       XFillArc(dpy, window, black, robots[x].new_x+(1.7*robots[x].radius/2), robots[x].new_y+(1.7*robots[x].radius/2), EXPLODE_SIZE_3, EXPLODE_SIZE_3, 0, 360*64);
+                               }
+                               robots[x].death--;
+                       }
+               }
+       }
+
+       for(x=0;x<NUM_ROBOTS;x++) {
+               for(y=0;y<NUM_LASERS;y++) {
+                       if(robots[x].lasers[y].active) {
+                               XDrawLine(dpy, window, black, robots[x].lasers[y].start_x,
+                                                        robots[x].lasers[y].start_y,
+                                                        robots[x].lasers[y].end_x,
+                                                        robots[x].lasers[y].end_y);
+                               move_laser(x, y);
+                               if(robots[x].lasers[y].active) {
+                                       XDrawLine(dpy, window, robots[x].laser_color, robots[x].lasers[y].start_x,
+                                                                robots[x].lasers[y].start_y,
+                                                                robots[x].lasers[y].end_x,
+                                                                robots[x].lasers[y].end_y);
+                               }
+                               else {
+                                       XDrawLine(dpy, window, black, robots[x].lasers[y].start_x,
+                                                                robots[x].lasers[y].start_y,
+                                                                robots[x].lasers[y].end_x,
+                                                                robots[x].lasers[y].end_y);
+                               }                                       
+                       }
+               }
+       }
+
+       if(MOTHER_SHIP) {
+               if(mother->active) {
+                       XFillArc(dpy, window, black, mother->old_x, mother->y, MOTHER_SHIP_WIDTH, MOTHER_SHIP_HEIGHT, 0 , 360*64);
+                       XFillArc(dpy, window, mother->ship_color, mother->new_x, mother->y, MOTHER_SHIP_WIDTH, MOTHER_SHIP_HEIGHT, 0 , 360*64);
+               }
+               else {
+                       if(mother->death) {
+                               XFillArc(dpy, window, black, mother->old_x, mother->y, MOTHER_SHIP_WIDTH, MOTHER_SHIP_HEIGHT, 0 , 360*64);
+                               if(mother->death==20) {
+                                       XFillArc(dpy, window, EXPLODE_COLOR_1, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(mother->death==18) {
+                                       XFillArc(dpy, window, EXPLODE_COLOR_2, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(mother->death==17) {
+                                       XFillArc(dpy, window, EXPLODE_COLOR_1, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(mother->death==15) {
+                                       XFillArc(dpy, window, black, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(mother->death==14) {
+                                       XFillArc(dpy, window, EXPLODE_COLOR_2, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(mother->death==13) {
+                                       XFillArc(dpy, window, black, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(mother->death==12) {
+                                       XFillArc(dpy, window, EXPLODE_COLOR_1, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(mother->death==11) {
+                                       XFillArc(dpy, window, black, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(mother->death==10) {
+                                       XFillArc(dpy, window, EXPLODE_COLOR_2, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(mother->death==9) {
+                                       XFillArc(dpy, window, black, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(mother->death==8) {
+                                       XFillArc(dpy, window, EXPLODE_COLOR_1, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(mother->death==7) {
+                                       XFillArc(dpy, window, black, mother->new_x+1, mother->y+1, EXPLODE_SIZE_1, EXPLODE_SIZE_1, 0, 360*64);
+                               }
+                               else if(mother->death==6) {
+                                       XFillArc(dpy, window, EXPLODE_COLOR_2, mother->new_x+1, mother->y+1, EXPLODE_SIZE_2, EXPLODE_SIZE_2, 0, 360*64);
+                               }
+                               else if(mother->death==4) {
+                                       XFillArc(dpy, window, black, mother->new_x+1, mother->y+1, EXPLODE_SIZE_2, EXPLODE_SIZE_2, 0, 360*64);
+                               }
+                               else if(mother->death==3) {
+                                       XFillArc(dpy, window, EXPLODE_COLOR_1, mother->new_x+1, mother->y+1, EXPLODE_SIZE_2, EXPLODE_SIZE_2, 0, 360*64);
+                               }
+                               else if(mother->death==2) {
+                                       XFillArc(dpy, window, black, mother->new_x+1, mother->y+1, EXPLODE_SIZE_2, EXPLODE_SIZE_2, 0, 360*64);
+                                       XFillArc(dpy, window, EXPLODE_COLOR_2, mother->new_x+(1.7*MOTHER_SHIP_WIDTH/2), mother->y+(1.7*MOTHER_SHIP_HEIGHT/2), EXPLODE_SIZE_3, EXPLODE_SIZE_3, 0, 360*64);
+                               }
+                               else if(mother->death==1) {
+                                       XFillArc(dpy, window, black, mother->new_x+(1.7*MOTHER_SHIP_WIDTH/2), mother->y+(1.7*MOTHER_SHIP_HEIGHT/2), EXPLODE_SIZE_3, EXPLODE_SIZE_3, 0, 360*64);
+                               }
+                               mother->death--;
+                       }
+               }
+               for(y=0;y<8;y++) {
+                       if(mother->lasers[y].active) {
+                               XDrawLine(dpy, window, black, mother->lasers[y].start_x,
+                                                        mother->lasers[y].start_y,
+                                                        mother->lasers[y].end_x,
+                                                        mother->lasers[y].end_y);
+                               move_laser(-1,y);
+                               if(mother->lasers[y].active) {
+                               XDrawLine(dpy, window, mother->laser_color, mother->lasers[y].start_x,
+                                                        mother->lasers[y].start_y,
+                                                        mother->lasers[y].end_x,
+                                                        mother->lasers[y].end_y);
+                               }
+                               else {
+                                       XDrawLine(dpy, window, black, mother->lasers[y].start_x,
+                                                                mother->lasers[y].start_y,
+                                                                mother->lasers[y].end_x,
+                                                                mother->lasers[y].end_y);
+                               }
+                       }
+               }
+       }
+}
+
+/* This is the main loop. The mothership movement and laser firing happens inside
+       this loop. */
+static void 
+start_blaster(void)
+{
+       int x=0;
+       int y=0;
+       int z=0;
+       robots = (struct robot_state *) malloc(NUM_ROBOTS * sizeof (struct robot_state));
+       for(x=0;x<NUM_ROBOTS;x++) {
+               robots[x].alive = 0;
+               robots[x].death = 0;
+               robots[x].lasers = (struct laser_state *) malloc (NUM_LASERS * sizeof(struct laser_state));
+               for(y=0;y<NUM_LASERS;y++) {
+                       robots[x].lasers[y].active = 0;
+               }
+       }
+
+       if(NUM_STARS) {
+               stars = (XArc *) malloc (NUM_STARS * sizeof(XArc));
+               for(x=0;x<NUM_STARS;x++) {
+                       stars[x].x = random()%xgwa.width;
+                       stars[x].y = random()%xgwa.height;
+                       stars[x].width = random()%4 + 1;
+                       stars[x].height = stars[x].width;
+                       stars[x].angle1 = 0;
+                       stars[x].angle2 = 360 * 64;
+               }
+       }
+
+       while(1) {
+               if(NUM_STARS) {
+                       if(MOVE_STARS) {
+                               XFillArcs(dpy,window,black,stars,NUM_STARS);
+                               if(MOVE_STARS_RANDOM) {
+                                       y = MOVE_STARS_X;
+                                       z = MOVE_STARS_Y;
+                                       if(random()%167==0) {
+                                               y = (-1)*y;
+                                       }
+                                       if(random()%173==0) {
+                                               z = (-1)*z;
+                                       }
+                                       if(random()%50==0) {
+                                               if(random()%2) {
+                                                       y++;
+                                                       if(y>MOVE_STARS_RANDOM) {
+                                                               y = MOVE_STARS_RANDOM;
+                                                       }
+                                               }
+                                               else {
+                                                       y--;
+                                                       if(y < -(MOVE_STARS_RANDOM)) {
+                                                               y = -(MOVE_STARS_RANDOM);
+                                                       }
+                                               }
+                                       }
+                                       if(random()%50==0) {
+                                               if(random()%2) {
+                                                       z++;
+                                                       if(z>MOVE_STARS_RANDOM) {
+                                                               z = MOVE_STARS_RANDOM;
+                                                       }
+                                               }
+                                               else {
+                                                       z--;
+                                                       if(z < -MOVE_STARS_RANDOM) {
+                                                               z = -MOVE_STARS_RANDOM;
+                                                       }
+                                               }
+                                       }
+                                       MOVE_STARS_X = y;
+                                       MOVE_STARS_Y = z;
+                                       for(x=0;x<NUM_STARS;x++) {
+                                               stars[x].x = stars[x].x + y;
+                                               stars[x].y = stars[x].y + z;
+                                               if(stars[x].x<0) {
+                                                       stars[x].x = stars[x].x + xgwa.width;
+                                               }
+                                               else if(stars[x].x>xgwa.width) {
+                                                       stars[x].x = stars[x].x - xgwa.width;
+                                               }
+                                               if(stars[x].y<0) {
+                                                       stars[x].y = stars[x].y + xgwa.height;
+                                               }
+                                               else if(stars[x].y>xgwa.height) {
+                                                       stars[x].y = stars[x].y - xgwa.height;
+                                               }
+                                       }
+                               }
+                               else {
+                                       for(x=0;x<NUM_STARS;x++) {
+                                               stars[x].x = stars[x].x + MOVE_STARS_X;
+                                               stars[x].y = stars[x].y + MOVE_STARS_Y;
+                                               if(stars[x].x<0) {
+                                                       stars[x].x = stars[x].x + xgwa.width;
+                                               }
+                                               else if(stars[x].x>xgwa.width) {
+                                                       stars[x].x = stars[x].x - xgwa.width;
+                                               }
+                                               if(stars[x].y<0) {
+                                                       stars[x].y = stars[x].y + xgwa.height;
+                                               }
+                                               else if(stars[x].y>xgwa.height) {
+                                                       stars[x].y = stars[x].y - xgwa.height;
+                                               }
+                                       }
+                               }
+                               XFillArcs(dpy,window,s_color,stars,NUM_STARS);
+                       }
+                       else {
+                               XFillArcs(dpy,window,s_color,stars,NUM_STARS);
+                       }
+               }
+
+               if(MOTHER_SHIP) {
+                       if(random()%MOTHER_SHIP_PERIOD==0) {
+                               if((mother->active==0)&&(mother->death==0)) {
+                                       mother->active = MOTHER_SHIP_HITS;
+                                       mother->y = random()%(xgwa.height-7);
+                                       if(random()%2==0) {
+                                               mother->old_x=0;
+                                               mother->new_x=0;
+                                       }
+                                       else {
+                                               mother->old_x=xgwa.width-25;
+                                               mother->new_x=xgwa.width-25;
+                                       }
+                               }
+                       }
+               }
+               move_robots();
+               if(MOTHER_SHIP) {
+                       if(mother->active) {
+                               if(mother->old_x==mother->new_x) {
+                                       if(mother->old_x==0) {
+                                               mother->new_x=3;
+                                       }
+                                       else {
+                                               mother->new_x=mother->new_x-3;
+                                       }
+                               }
+                               else {
+                                       if(mother->old_x>mother->new_x) {
+                                               mother->old_x = mother->new_x;
+                                               mother->new_x = mother->new_x-3;
+                                               if(mother->new_x<0) {
+                                                       mother->active=0;
+                                                       XFillArc(dpy, window, black, mother->old_x, mother->y, MOTHER_SHIP_WIDTH, MOTHER_SHIP_HEIGHT, 0 , 360*64);
+                                                       XFillArc(dpy, window, black, mother->new_x, mother->y, MOTHER_SHIP_WIDTH, MOTHER_SHIP_HEIGHT, 0 , 360*64);
+                                               }
+                                       }
+                                       else {
+                                               mother->old_x = mother->new_x;
+                                               mother->new_x = mother->new_x+3;
+                                               if(mother->new_x>xgwa.width) {
+                                                       mother->active=0;
+                                                       XFillArc(dpy, window, black, mother->old_x, mother->y, MOTHER_SHIP_WIDTH, MOTHER_SHIP_HEIGHT, 0 , 360*64);
+                                                       XFillArc(dpy, window, black, mother->new_x, mother->y, MOTHER_SHIP_WIDTH, MOTHER_SHIP_HEIGHT, 0 , 360*64);
+                                               }
+                                       }
+                               }
+                               y=0;
+                               for(x=0;x<8;x++) {
+                                       if(mother->lasers[x].active) {
+                                               y=1;
+                                               x=8;
+                                       }
+                               }
+                               if(y==0) {
+                                       for(x=0;x<8;x++) {
+                                               mother->lasers[x].active = 1;
+                                               mother->lasers[x].start_x=mother->new_x+(MOTHER_SHIP_WIDTH/2);
+                                               mother->lasers[x].start_y=mother->y+(MOTHER_SHIP_HEIGHT/2);
+                                       }
+                                       y = (int)(MOTHER_SHIP_LASER/1.5);
+                                       mother->lasers[0].end_x=mother->lasers[0].start_x-MOTHER_SHIP_LASER;
+                                       mother->lasers[0].end_y=mother->lasers[0].start_y;
+                                       mother->lasers[1].end_x=mother->lasers[1].start_x-y;
+                                       mother->lasers[1].end_y=mother->lasers[1].start_y-y;
+                                       mother->lasers[2].end_x=mother->lasers[2].start_x;
+                                       mother->lasers[2].end_y=mother->lasers[2].start_y-MOTHER_SHIP_LASER;
+                                       mother->lasers[3].end_x=mother->lasers[3].start_x+y;
+                                       mother->lasers[3].end_y=mother->lasers[3].start_y-y;
+                                       mother->lasers[4].end_x=mother->lasers[4].start_x+MOTHER_SHIP_LASER;
+                                       mother->lasers[4].end_y=mother->lasers[4].start_y;
+                                       mother->lasers[5].end_x=mother->lasers[5].start_x+y;
+                                       mother->lasers[5].end_y=mother->lasers[5].start_y+y;
+                                       mother->lasers[6].end_x=mother->lasers[6].start_x;
+                                       mother->lasers[6].end_y=mother->lasers[6].start_y+MOTHER_SHIP_LASER;
+                                       mother->lasers[7].end_x=mother->lasers[7].start_x-y;
+                                       mother->lasers[7].end_y=mother->lasers[7].start_y+y;
+                               }
+                       }
+               }
+               draw_robots();
+
+               XSync(dpy, False);
+               screenhack_handle_events(dpy);
+               if(delay) usleep(delay);
+       }
+}
+
+
+
+
+
+
+
+
+char *progclass = "Blaster";
+
+char *defaults [] = {
+  ".background:        black",
+  ".foreground:        white",
+  "*r_color0:  magenta",
+  "*r_color1:  orange",
+  "*r_color2:  yellow",
+  "*r_color3:  white",
+  "*r_color4:  blue",
+  "*r_color5:  cyan",
+  "*l_color0:  green",
+  "*l_color1:  red",
+  "*mother_ship_color0:        darkblue",
+  "*mother_ship_color1:        white",
+  "*explode_color_1: yellow",
+  "*explode_color_2: orange",
+  "*delay: 10000",
+  "*num_robots: 5",
+  "*num_lasers: 3",
+  "*mother_ship: false",
+  "*mother_ship_width: 25",
+  "*mother_ship_height: 7",
+  "*mother_ship_laser: 15",
+  "*mother_ship_period: 150",
+  "*mother_ship_hits: 10",  
+  "*explode_size_1: 27",
+  "*explode_size_2: 19",
+  "*explode_size_3: 7",
+  "*num_stars: 50",
+  "*star_color: white",
+  "*move_stars: true",
+  "*move_stars_x: 2",
+  "*move_stars_y: 1",
+  "*move_stars_random: 0",
+  0
+};
+
+XrmOptionDescRec options [] = {
+       /* These are the 6 robot colors */
+  { "-r_color0",               ".r_color0",    XrmoptionSepArg, 0 },
+  { "-r_color1",               ".r_color1",    XrmoptionSepArg, 0 },
+  { "-r_color2",               ".r_color2",    XrmoptionSepArg, 0 },
+  { "-r_color3",               ".r_color3",    XrmoptionSepArg, 0 },
+  { "-r_color4",               ".r_color4",    XrmoptionSepArg, 0 },
+  { "-r_color5",               ".r_color5",    XrmoptionSepArg, 0 },
+  /* These are the 2 laser colors that robots have */
+  { "-l_color0",               ".l_color0",    XrmoptionSepArg, 0 },
+  { "-l_color1",               ".l_color1",    XrmoptionSepArg, 0 },
+  /* These are the colors for the mothership and the mothership lasers */
+  { "-mother_ship_color0",   ".mother_ship_color0",  XrmoptionSepArg, 0},
+  { "-mother_ship_color1",   ".mother_ship_color1",  XrmoptionSepArg, 0},
+  /* These are the two colors of the animated explosion */
+  { "-explode_color_1",  ".explode_color_1",   XrmoptionSepArg, 0 },
+  { "-explode_color_2",  ".explode_color_2",   XrmoptionSepArg, 0 },
+  /* This is the delay in the main loop */
+  { "-delay",          ".delay",       XrmoptionSepArg, 0 },
+  /* The number of robots and the number of lasers each robot has */
+  { "-num_robots",   ".num_robots",  XrmoptionSepArg, 0},
+  { "-num_lasers",   ".num_lasers",  XrmoptionSepArg, 0},
+  /* If this is set, a mothership will appear, otherwise no mothership */
+  { "-mother_ship",   ".mother_ship",  XrmoptionNoArg, "true"},
+  { "-no_mother_ship",   ".mother_ship",  XrmoptionNoArg, "false"},
+  /* This is the width, height, and laser length of the mothership */
+  { "-mother_ship_width",   ".mother_ship_width",  XrmoptionSepArg, 0},
+  { "-mother_ship_height",   ".mother_ship_height",  XrmoptionSepArg, 0},
+  { "-mother_ship_laser",   ".mother_ship_laser",  XrmoptionSepArg, 0},
+  /* This is the period which the mothership comes out, higher period==less often */
+  { "-mother_ship_period",   ".mother_ship_period",  XrmoptionSepArg, 0},
+  /* This is the number of hits it takes to destroy the mothership */
+  { "-mother_ship_hits",   ".mother_ship_hits",  XrmoptionSepArg, 0},
+  /* These are the size of the radius of the animated explosions */
+  { "-explode_size_1", ".explode_size_1",   XrmoptionSepArg, 0},
+  { "-explode_size_2", ".explode_size_2",   XrmoptionSepArg, 0},
+  { "-explode_size_3", ".explode_size_3",   XrmoptionSepArg, 0},
+  /* This sets the number of stars in the star field, if this is set to 0, there will be no stars */
+  { "-num_stars", ".num_stars", XrmoptionSepArg, 0},
+  /* This is the color of the stars */
+  { "-star_color", ".star_color", XrmoptionSepArg, 0},
+  /* If this is true, the stars will move */
+  { "-move_stars", ".move_stars", XrmoptionNoArg, "true"},
+  /* This is the amount the stars will move in the x and y direction */
+  { "-move_stars_x", ".move_stars_x", XrmoptionSepArg, 0},
+  { "-move_stars_y", ".move_stars_y", XrmoptionSepArg, 0},
+  /* If this is non-zero, the stars will move randomly, but will not move more than this number in 
+         either the x or y direction */
+  { "-move_stars_random", ".move_stars_random", XrmoptionSepArg, 0},
+  { 0, 0, 0, 0 }
+};
+
+
+
+void screenhack(Display *d, Window w)
+{
+       XGCValues gcv;
+       Colormap cmap;
+       unsigned long bg;
+
+       dpy = d;
+       window = w;
+       XGetWindowAttributes(dpy, window, &xgwa);
+       cmap = xgwa.colormap;
+
+       delay = get_integer_resource("delay", "Integer");
+       if(delay==0) {
+               delay=10000;
+       }
+       NUM_ROBOTS = get_integer_resource("num_robots","Integer");
+       if(NUM_ROBOTS==0) {
+               NUM_ROBOTS=5;
+       }
+       NUM_LASERS = get_integer_resource("num_lasers","Integer");
+       EXPLODE_SIZE_1 = get_integer_resource("explode_size_1","Integer");
+       EXPLODE_SIZE_2 = get_integer_resource("explode_size_2","Integer");
+       EXPLODE_SIZE_3 = get_integer_resource("explode_size_3","Integer");
+
+       NUM_STARS = get_integer_resource("num_stars","Integer");
+       if(get_boolean_resource("move_stars","Boolean")) {
+               MOVE_STARS = 1;
+               MOVE_STARS_X = get_integer_resource("move_stars_x","Integer");
+               MOVE_STARS_Y = get_integer_resource("move_stars_y","Integer");
+               MOVE_STARS_RANDOM = get_integer_resource("move_stars_random","Integer");
+       }
+       else {
+               MOVE_STARS = 0;
+       }
+
+
+       bg = get_pixel_resource("background","Background", dpy, cmap);
+       gcv.function = GXcopy;
+
+#define make_gc(color,name) \
+       gcv.foreground = bg ^ get_pixel_resource ((name), "Foreground", \
+                                                 dpy, cmap);           \
+       color = XCreateGC (dpy, window, GCForeground|GCFunction, &gcv)
+
+       if(mono_p) {
+               gcv.foreground = bg;
+               black = XCreateGC(dpy, window, GCForeground|GCFunction, &gcv);
+               gcv.foreground = get_pixel_resource("foreground", "Foreground", dpy, cmap);
+               r_color0 = r_color1 = r_color2 = r_color3 = r_color4 = r_color5 = l_color0 = l_color1 = s_color=
+                       XCreateGC(dpy, window, GCForeground|GCFunction, &gcv);
+               if(get_boolean_resource("mother_ship","Boolean")) {
+                       MOTHER_SHIP_WIDTH=get_integer_resource("mother_ship_width","Integer");
+                       MOTHER_SHIP_HEIGHT=get_integer_resource("mother_ship_height","Integer");
+                       MOTHER_SHIP_LASER=get_integer_resource("mother_ship_laser","Integer");
+                       MOTHER_SHIP_PERIOD=get_integer_resource("mother_ship_period","Integer");
+                       MOTHER_SHIP_HITS=get_integer_resource("mother_ship_hits","Integer");
+                       MOTHER_SHIP=1;
+                       mother = (struct mother_ship_state *) malloc(sizeof(struct mother_ship_state));
+                       mother->lasers = (struct laser_state *) malloc(8*sizeof(struct laser_state));
+                       mother->active = 0;
+                       mother->death = 0;
+                       mother->ship_color = r_color0;
+                       mother->laser_color = r_color0;
+               }
+       }
+       else {
+               if(get_boolean_resource("mother_ship","Boolean")) {
+                       MOTHER_SHIP_WIDTH=get_integer_resource("mother_ship_width","Integer");
+                       MOTHER_SHIP_HEIGHT=get_integer_resource("mother_ship_height","Integer");
+                       MOTHER_SHIP_LASER=get_integer_resource("mother_ship_laser","Integer");
+                       MOTHER_SHIP_PERIOD=get_integer_resource("mother_ship_period","Integer");
+                       MOTHER_SHIP_HITS=get_integer_resource("mother_ship_hits","Integer");
+                       MOTHER_SHIP=1;
+                       mother = (struct mother_ship_state *) malloc(sizeof(struct mother_ship_state));
+                       mother->lasers = (struct laser_state *) malloc(8*sizeof(struct laser_state));
+                       mother->active = 0;
+                       mother->death = 0;
+                       make_gc(mother->ship_color,"mother_ship_color0");
+                       make_gc(mother->laser_color,"mother_ship_color1");              
+               }
+
+               make_gc (s_color,"star_color");
+               
+               make_gc (EXPLODE_COLOR_1,"explode_color_1");
+               make_gc (EXPLODE_COLOR_2,"explode_color_2");
+               
+      make_gc (r_color0,"r_color0");
+      make_gc (r_color1,"r_color1");
+      make_gc (r_color2,"r_color2");
+      make_gc (r_color3,"r_color3");
+      make_gc (r_color4,"r_color4");
+      make_gc (r_color5,"r_color5");
+      make_gc (l_color0,"l_color0");
+      make_gc (l_color1,"l_color1");
+               make_gc (black,"background");
+       }
+
+       start_blaster();
+}
index bbbc2ca29b011d4ac3b1fb2b22d88822b6e9d8c7..faffc0f4e821a120c3baa8324d7a005821ee1452 100644 (file)
@@ -217,7 +217,7 @@ windows (Display *dpy, Window window, int delay, Bool w95p)
      "\n"
      "_Press any key to continue");
 
-  const char *wnt =
+  const char *wnt = /* from Jim Niemira <urmane@urmane.org> */
     ("*** STOP: 0x0000001E (0x80000003,0x80106fc0,0x8025ea21,0xfd6829e8)\n"
    "Unhandled Kernel exception c0000047 from fa8418b4 (8025ea21,fd6829e8)\n"
    "\n"
diff --git a/hacks/bumps.c b/hacks/bumps.c
new file mode 100644 (file)
index 0000000..b1dda08
--- /dev/null
@@ -0,0 +1,396 @@
+/* Bumps, Copyright (c) 1999 Shane Smit <blackend@inconnect.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or
+ * implied warranty.
+ *
+ * Module: "Bumps.cpp"
+ * Tab Size: 4
+ *
+ * Description:
+ *  This is typical bump-mapping.  The actual bump map is generated by a screen
+ *  grab.  The light source is represented by a spotlight of random color. This
+ *  spotlight randomly traverses the bump map in a sinus pattern.
+ *
+ *  Essentially, it 3D-izes your desktop, based on color intensity.
+ *
+ * Modification History:
+ *  [10/01/99] - Shane Smit: Creation
+ *  [10/08/99] - Shane Smit: Port to C. (Ick)
+ */
+
+
+#include "bumps.h"
+
+
+void CreateSpotLight( SSpotLight *pSpotLight, uint16_ iWinWidth, uint16_ nColorCount )
+{
+       double nDelta;
+       int16_ iHeight, iWidth;
+       
+       pSpotLight->nDiameter = iWinWidth / 3;
+#ifdef VERBOSE
+       printf( "%s: Light Diameter: %d\n", progclass, pSpotLight->nDiameter );
+#endif
+
+       pSpotLight->aLightMap = calloc( pSpotLight->nDiameter * pSpotLight->nDiameter, sizeof(uint8_) );
+       memset( pSpotLight->aLightMap, 0, pSpotLight->nDiameter * pSpotLight->nDiameter );
+
+       /* The falloff max values... 3/4 of the entire lightmap. */
+       pSpotLight->nRadius = (uint16_)(pSpotLight->nDiameter / 2.5F);
+       
+       for( iHeight=-pSpotLight->nRadius; iHeight<pSpotLight->nRadius; iHeight++ )
+               for( iWidth=-pSpotLight->nRadius; iWidth<pSpotLight->nRadius; iWidth++ )
+               {
+                       nDelta = ( nColorCount * 2.5F ) - ( ( sqrt( pow( iWidth+0.5F, 2 ) + pow( iHeight+0.5F, 2 ) ) / pSpotLight->nRadius ) * ( nColorCount * 2.5F ) );
+                       nDelta += nColorCount;
+                       if( nDelta >= ( nColorCount * 2 ) ) nDelta = ( nColorCount * 2 ) - 1;
+                       if( nDelta >= nColorCount )
+                               pSpotLight->aLightMap[ ( ( iHeight + (pSpotLight->nDiameter/2) ) * pSpotLight->nDiameter ) + iWidth + (pSpotLight->nDiameter/2) ] = (uint8_)nDelta;
+               }
+
+       /* The actual lightmap... 1/2 of the entire lightmap. */
+       pSpotLight->nRadius = pSpotLight->nDiameter / 4;
+
+       for( iHeight=-pSpotLight->nRadius; iHeight<pSpotLight->nRadius; iHeight++ )
+               for( iWidth=-pSpotLight->nRadius; iWidth<pSpotLight->nRadius; iWidth++ )
+               {
+                       nDelta = nColorCount - ( ( sqrt( pow( iWidth+0.5F, 2 ) + pow( iHeight+0.5F, 2 ) ) / pSpotLight->nRadius ) * ( nColorCount - 1 ) );
+                       if( nDelta >= 1 )
+                               pSpotLight->aLightMap[ ( ( iHeight + (pSpotLight->nDiameter/2) ) * pSpotLight->nDiameter ) + iWidth + (pSpotLight->nDiameter/2) ] = (uint8_)nDelta;
+               }
+               
+       CreateTables( pSpotLight );
+
+       pSpotLight->nRadius = pSpotLight->nDiameter / 2;        /* Now set the radius back to what it should be. */
+       pSpotLight->nAngleX = RANDOM() % pSpotLight->nDegreeCount;
+       pSpotLight->nAngleY = RANDOM() % pSpotLight->nDegreeCount;
+       pSpotLight->nVelocityX = ( RANDOM() % 3 ) + 1;
+       pSpotLight->nVelocityY = ( RANDOM() % 3 ) + 1;
+}
+
+
+void CreateTables( SSpotLight *pSpotLight )
+{
+       long double nUnit;
+       uint16_ iDegree;
+       
+       pSpotLight->nDegreeCount = get_integer_resource( "degrees", "Integer" );
+       if( pSpotLight->nDegreeCount < 180 ) pSpotLight->nDegreeCount = 180;    /* Less than 180 will show trails in higher resolutions. */
+#ifdef VERBOSE
+       printf( "%s: Using a %d degree circle.\n", progclass, pSpotLight->nDegreeCount );
+#endif
+
+       pSpotLight->aSinTable = calloc( pSpotLight->nDegreeCount, sizeof(double) );
+
+       /* This funtion builds the Sine Lookup Tables. */
+       nUnit = (long double)( PI * 2.0F ) / (long double)( pSpotLight->nDegreeCount );
+
+       for( iDegree=0; iDegree<pSpotLight->nDegreeCount; iDegree++)
+               pSpotLight->aSinTable[ iDegree ] = sin( nUnit * (long double)iDegree );
+}
+
+
+void CalcLightPos( SSpotLight *pSpotLight, uint16_ *pXPos, uint16_ *pYPos )
+{
+       pSpotLight->nVelocityX += ( RANDOM() % 2 ) ? 0.05F : -0.05F;
+       if( pSpotLight->nVelocityX < 1 )                pSpotLight->nVelocityX = 1;
+       else if( pSpotLight->nVelocityX > 3 )   pSpotLight->nVelocityX = 3;
+
+       pSpotLight->nVelocityX += ( RANDOM() % 2 ) ? 0.05F : -0.05F;
+       if( pSpotLight->nVelocityY < 1 )                pSpotLight->nVelocityX = 1;
+       else if( pSpotLight->nVelocityY > 3 )   pSpotLight->nVelocityX = 3;
+       
+    pSpotLight->nAngleX += pSpotLight->nVelocityX;
+    if( pSpotLight->nAngleX >= pSpotLight->nDegreeCount )      pSpotLight->nAngleX -= pSpotLight->nDegreeCount;
+
+    pSpotLight->nAngleY += pSpotLight->nVelocityY;
+    if( pSpotLight->nAngleY >= pSpotLight->nDegreeCount )      pSpotLight->nAngleY -= pSpotLight->nDegreeCount;
+
+    *pXPos = (uint16_)( ( pSpotLight->iWinXCenter - pSpotLight->nRadius ) * pSpotLight->aSinTable[ (uint16_)pSpotLight->nAngleX ] ) + pSpotLight->iWinXCenter;
+    *pYPos = (uint16_)( ( pSpotLight->iWinYCenter - pSpotLight->nRadius ) * pSpotLight->aSinTable[ (uint16_)pSpotLight->nAngleY ] ) + pSpotLight->iWinYCenter;
+
+       /* Offset to upper left hand corner. */
+       *pXPos -= pSpotLight->nRadius;
+       *pYPos -= pSpotLight->nRadius;
+}
+
+
+void CreateBumps( SBumps *pBumps, Display *pNewDisplay, Window NewWin )
+{
+       XWindowAttributes XWinAttribs;
+       XGCValues GCValues;
+       int32_ nGCFlags;
+       uint16_ iWidth, iHeight;
+
+       XGetWindowAttributes( pNewDisplay, NewWin, &XWinAttribs );
+       pBumps->iWinWidth = XWinAttribs.width;
+       pBumps->iWinHeight = XWinAttribs.height;
+       pBumps->SpotLight.iWinXCenter = XWinAttribs.width / 2;
+       pBumps->SpotLight.iWinYCenter = XWinAttribs.height / 2;
+       pBumps->pDisplay = pNewDisplay;
+       pBumps->Win = NewWin;
+
+       pBumps->pXImage = XCreateImage( pBumps->pDisplay, XWinAttribs.visual, XWinAttribs.depth, ZPixmap, 0, NULL,
+               pBumps->iWinWidth, pBumps->iWinHeight, BitmapPad( pBumps->pDisplay ), 0 );
+       pBumps->pXImage->data = calloc( pBumps->pXImage->bytes_per_line * pBumps->pXImage->height, sizeof(int8_) );
+
+       GCValues.function = GXcopy;
+       GCValues.subwindow_mode = IncludeInferiors;
+       nGCFlags = GCForeground | GCFunction;
+       if( use_subwindow_mode_p( XWinAttribs.screen, pBumps->Win ) ) /* See grabscreen.c */
+               nGCFlags |= GCSubwindowMode;
+       pBumps->GraphicsContext = XCreateGC( pBumps->pDisplay, pBumps->Win, nGCFlags, &GCValues );
+       
+       SetPalette( pBumps, &XWinAttribs );
+       CreateSpotLight( &pBumps->SpotLight, pBumps->iWinWidth, pBumps->nColorCount );
+       InitBumpMap( pBumps, &XWinAttribs );
+
+       /* Clear the image. */
+  if (pBumps->aXColors[ 0 ].pixel == 0)
+    memset (pBumps->pXImage->data, 0,
+            pBumps->pXImage->bytes_per_line * pBumps->pXImage->height);
+  else
+    for( iHeight=0; iHeight<pBumps->iWinHeight; iHeight++ )
+      for( iWidth=0; iWidth<pBumps->iWinWidth; iWidth++ )
+        XPutPixel( pBumps->pXImage, iWidth, iHeight,
+                   pBumps->aXColors[ 0 ].pixel );
+  XSetWindowBackground( pBumps->pDisplay, pBumps->Win,
+                        pBumps->aXColors[ 0 ].pixel );
+  XClearWindow (pBumps->pDisplay, pBumps->Win);
+}
+
+
+void SetPalette( SBumps *pBumps, XWindowAttributes *pXWinAttribs )
+{
+       XColor Color;
+       char *sColor;                   /* Spotlight Color */
+       int16_ iColor;
+       uint32_ *aPixels;
+       
+       sColor = get_string_resource( "color", "Color" );
+
+       Color.red = RANDOM() % 0xFFFF; 
+       Color.green = RANDOM() % 0xFFFF;
+       Color.blue = RANDOM() % 0xFFFF;
+
+       if( strcasecmp( sColor, "random" ) && !XParseColor( pBumps->pDisplay, pXWinAttribs->colormap, sColor, &Color ) )
+               fprintf( stderr, "%s: color %s not found in database. Choosing random...\n", progname, sColor );
+
+#ifdef VERBOSE
+       printf( "%s: Spotlight color is <%d,%d,%d> RGB.\n", progclass, Color.red, Color.green, Color.blue );
+#endif  /*  VERBOSE */
+
+       pBumps->nColorCount = get_integer_resource( "colorcount", "Integer" );
+       if( pBumps->nColorCount < 2 )   pBumps->nColorCount = 2;
+       if( pBumps->nColorCount > 128 ) pBumps->nColorCount = 128;
+
+       pBumps->aXColors = calloc( pBumps->nColorCount, sizeof(XColor ) );
+               aPixels  = calloc( pBumps->nColorCount, sizeof(uint32_) );
+
+       /* Creates a phong shade:                 / SpotColor  \                               Index/ColorCount 
+        *                                                      PhongShade = | ------------ | Index + ( 65535 - SpotColor )^ 
+        *                                                                                \ ColorCount /                                                                                                */
+       pBumps->nColorCount--;
+       for( iColor=0; iColor<=pBumps->nColorCount; iColor++ )
+       {
+               pBumps->aXColors[ iColor ].red   = (uint16_)( ( ( Color.red   / (double)pBumps->nColorCount ) * iColor ) + pow( 0xFFFF - Color.red,   iColor/(double)pBumps->nColorCount ) );
+               pBumps->aXColors[ iColor ].green = (uint16_)( ( ( Color.green / (double)pBumps->nColorCount ) * iColor ) + pow( 0xFFFF - Color.green, iColor/(double)pBumps->nColorCount ) );
+               pBumps->aXColors[ iColor ].blue  = (uint16_)( ( ( Color.blue  / (double)pBumps->nColorCount ) * iColor ) + pow( 0xFFFF - Color.blue,  iColor/(double)pBumps->nColorCount ) );
+
+               if( !XAllocColor( pBumps->pDisplay, pXWinAttribs->colormap, &pBumps->aXColors[ iColor ] ) )
+               {
+                       XFreeColors( pBumps->pDisplay, pXWinAttribs->colormap, aPixels, iColor, 0 );
+                       free( pBumps->aXColors );
+                       free(         aPixels );
+                       pBumps->nColorCount--;
+                       pBumps->aXColors = calloc( pBumps->nColorCount, sizeof(XColor) );
+                       aPixels  = calloc( pBumps->nColorCount, sizeof(uint32_) );
+                       iColor = -1;
+               }
+               else
+                       aPixels[ iColor ] = pBumps->aXColors[ iColor ].pixel;
+       }
+       pBumps->nColorCount++;
+
+#ifdef VERBOSE
+       printf( "%s: Allocated %d colors.\n", progclass, pBumps->nColorCount );
+#endif  /*  VERBOSE */
+
+       XSetWindowBackground( pBumps->pDisplay, pBumps->Win, pBumps->aXColors[ 0 ].pixel );
+}
+
+
+void InitBumpMap( SBumps *pBumps, XWindowAttributes *pXWinAttribs )
+{
+       XImage *pScreenImage;
+       XColor aColors[ pBumps->iWinWidth ];
+       uint8_ nSoften;
+       uint16_ iWidth, iHeight;
+       BOOL bInvert = (BOOL)get_boolean_resource( "invert", "Boolean" );
+       
+       grab_screen_image( pXWinAttribs->screen, pBumps->Win );
+       pScreenImage = XGetImage( pBumps->pDisplay, pBumps->Win, 0, 0, pBumps->iWinWidth, pBumps->iWinHeight, ~0L, ZPixmap );
+
+        /* jwz: get the grabbed bits off the screen fast */
+        XClearWindow (pBumps->pDisplay, pBumps->Win);
+        XSync (pBumps->pDisplay, 0);
+
+       pBumps->aBumpMap = calloc( pBumps->iWinWidth * pBumps->iWinHeight, sizeof(uint16_) );
+       for( iHeight=0; iHeight<pBumps->iWinHeight; iHeight++ )
+       {
+               for( iWidth=0; iWidth<pBumps->iWinWidth; iWidth++ )
+                       aColors[ iWidth ].pixel = XGetPixel( pScreenImage, iWidth, iHeight );
+
+               XQueryColors( pBumps->pDisplay, pXWinAttribs->colormap, aColors, pBumps->iWinWidth );
+       
+               if( bInvert )
+                       for( iWidth=0; iWidth<pBumps->iWinWidth; iWidth++ )
+                               pBumps->aBumpMap[ ( iHeight * pBumps->iWinWidth ) + iWidth ] = (uint16_)
+                                       ( ( aColors[ iWidth ].red + aColors[ iWidth ].green + aColors[ iWidth ].blue ) / ( 0x2FFFD / (double)pBumps->SpotLight.nDiameter ) );
+               else
+                       for( iWidth=0; iWidth<pBumps->iWinWidth; iWidth++ )
+                               pBumps->aBumpMap[ ( iHeight * pBumps->iWinWidth ) + iWidth ] = (uint16_)
+                                       ( pBumps->SpotLight.nDiameter - ( ( aColors[ iWidth ].red + aColors[ iWidth ].green + aColors[ iWidth ].blue ) / ( 0x2FFFD / (double)pBumps->SpotLight.nDiameter ) ) );
+       }
+
+       XDestroyImage( pScreenImage );
+
+       nSoften = get_integer_resource( "soften", "Integer" );
+#ifdef VERBOSE
+       if( nSoften )   printf( "%s: Softening Bump Map %d time(s)...\n", progclass, nSoften );
+#endif
+       while( nSoften-- )
+               SoftenBumpMap( pBumps );
+}
+
+
+void SoftenBumpMap( SBumps *pBumps )
+{
+       uint16_ *pOffset;
+       uint16_ nHeight;
+       uint16_ iWidth, iHeight;
+       uint16_ *pTempBuffer = calloc( pBumps->iWinWidth * pBumps->iWinHeight, sizeof(uint16_) );
+
+       for( iHeight=1; iHeight<pBumps->iWinHeight-1; iHeight++ )
+       {
+               pOffset = pBumps->aBumpMap + ( iHeight * pBumps->iWinWidth );
+               for( iWidth=1; iWidth<pBumps->iWinWidth-1; iWidth++ )
+               {       
+                       nHeight = 0;
+                       nHeight += pOffset[ iWidth ];
+                       nHeight += pOffset[ iWidth - pBumps->iWinWidth ];
+                       nHeight += pOffset[ iWidth + 1 ];
+                       nHeight += pOffset[ iWidth + pBumps->iWinWidth ];
+                       nHeight += pOffset[ iWidth - 1 ];
+                       nHeight /= 5;
+                       pTempBuffer[ ( iHeight * pBumps->iWinWidth ) + iWidth ] = nHeight;
+               }
+       }                                               
+       
+       memcpy( pBumps->aBumpMap, pTempBuffer, pBumps->iWinWidth * pBumps->iWinHeight * 2 );
+       free( pTempBuffer );
+}
+
+
+void Execute( SBumps *pBumps )
+{
+       uint16_ nLightXPos, nLightYPos;
+       uint16_ iWidth, iHeight;
+       uint16_ iLightWidth, iLightHeight;
+       uint16_ *pBOffset;
+       uint8_ *pLOffset;
+       int16_ nX, nY;
+       uint16_ nColor;
+       CalcLightPos( &pBumps->SpotLight, &nLightXPos, &nLightYPos );
+
+       for( iHeight=nLightYPos, iLightHeight=0; iLightHeight<pBumps->SpotLight.nDiameter; iHeight++, iLightHeight++ )
+       {
+               pBOffset = pBumps->aBumpMap + ( iHeight * pBumps->iWinWidth );
+               pLOffset = pBumps->SpotLight.aLightMap + ( iLightHeight * pBumps->SpotLight.nDiameter );
+               for( iWidth=nLightXPos, iLightWidth=0; iLightWidth<pBumps->SpotLight.nDiameter; iWidth++, iLightWidth++ )
+               {
+                       if( pLOffset[ iLightWidth ] )
+                       {                               
+                               nX = pBOffset[ iWidth + 1                 ] - pBOffset[ iWidth ] + iLightWidth;
+                               nY = pBOffset[ iWidth + pBumps->iWinWidth ] - pBOffset[ iWidth ] + iLightHeight;
+
+                               if( nX < 0 )                                    nX = 0;
+                               else if( nX >= pBumps->SpotLight.nDiameter )    nX = pBumps->SpotLight.nDiameter - 1;
+
+                               if( nY < 0 )                                    nY = 0;
+                               else if( nY >= pBumps->SpotLight.nDiameter )    nY = pBumps->SpotLight.nDiameter - 1;
+
+                               nColor = pBumps->SpotLight.aLightMap[ ( nY * pBumps->SpotLight.nDiameter ) + nX ];
+                               if( nColor >= pBumps->nColorCount )
+                                       nColor = 1;
+
+                               if( pLOffset[ iLightWidth ] >= pBumps->nColorCount )
+                                       if( nColor > pLOffset[ iLightWidth ] - pBumps->nColorCount )
+                                               nColor = pLOffset[ iLightWidth ] - pBumps->nColorCount;
+                                               
+                               XPutPixel( pBumps->pXImage, iWidth, iHeight, pBumps->aXColors[ nColor ].pixel );
+                       }
+                       else
+                               XPutPixel( pBumps->pXImage, iWidth, iHeight, pBumps->aXColors[ 0 ].pixel );
+               }
+       }       
+
+       XPutImage( pBumps->pDisplay, pBumps->Win, pBumps->GraphicsContext, pBumps->pXImage, nLightXPos, nLightYPos, nLightXPos, nLightYPos, pBumps->SpotLight.nDiameter, pBumps->SpotLight.nDiameter );
+       XSync( pBumps->pDisplay, False );
+}
+
+
+void DestroyBumps( SBumps *pBumps )
+{
+       DestroySpotLight( &pBumps->SpotLight );
+       free( pBumps->aXColors );
+       free( pBumps->aBumpMap );
+       XDestroyImage( pBumps->pXImage );
+}
+
+
+/* All messages to the screensaver are processed here. */
+void screenhack( Display *pDisplay, Window Win )
+{
+       SBumps Bumps;
+       uint32_ iDelay;
+#ifdef VERBOSE
+       time_t Time = time( NULL );
+       uint16_ iFrame = 0;
+#endif  /*  VERBOSE */
+       
+       CreateBumps( &Bumps, pDisplay, Win );
+       iDelay = get_integer_resource( "delay", "Integer" );
+
+       while( 1 )
+       {
+               screenhack_handle_events( pDisplay );
+               Execute( &Bumps );
+               usleep( iDelay );
+
+#ifdef VERBOSE
+               iFrame++;
+               if( Time - time( NULL ) )
+               {
+                       printf( "FPS: %d\n", iFrame );
+                       Time = time( NULL );
+                       iFrame = 0;
+               }
+#endif  /*  VERBOSE */
+       }
+
+       DestroyBumps( &Bumps );
+}
+
+/*
+ * End of Module: "Bumps.cpp"
+ */
+
+/* vim: ts=4
+ */
diff --git a/hacks/bumps.h b/hacks/bumps.h
new file mode 100644 (file)
index 0000000..08d56a5
--- /dev/null
@@ -0,0 +1,124 @@
+/* Bumps, Copyright (c) 1999 Shane Smit <blackend@inconnect.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or
+ * implied warranty.
+ *
+ * Module: "Bumps.h"
+ * Tab Size: 4
+ *
+ * Description:
+ *  Header file for module "Bumps.cpp"
+ *
+ * Modification History:
+ *  [10/01/99] - Shane Smit: Creation
+ *  [10/08/99] - Shane Smit: Port to C. (Ick)
+ */
+
+
+#ifndef _BUMPS_H
+#define _BUMPS_H
+
+
+#include <math.h>
+#include "screenhack.h"
+#include <X11/Xutil.h>
+
+
+/* Defines: */
+/* #define VERBOSE */
+#define PI             3.141592654
+#define RANDOM() ((int) (random() & 0X7FFFFFFFL))
+
+typedef char                   int8_;
+typedef unsigned char  uint8_;
+typedef short                  int16_;
+typedef unsigned short uint16_;
+typedef long                   int32_;
+typedef unsigned long  uint32_;
+typedef unsigned char  BOOL;
+
+
+// Globals:
+char *progclass = "Bumps";
+
+char *defaults [] = {
+  "*degrees:   360",
+  "*color:             random",
+  "*colorcount:        64",
+  "*delay:             50000",
+  "*soften:            1",
+  "*invert:            FALSE",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-degrees",                ".degrees",             XrmoptionSepArg, 0 },
+  { "-color",          ".color",               XrmoptionSepArg, 0 },
+  { "-colorcount",     ".colorcount",  XrmoptionSepArg, 0 },
+  { "-delay",          ".delay",               XrmoptionSepArg, 0 },
+  { "-soften",         ".soften",              XrmoptionSepArg, 0 },
+  { "-invert",         ".invert",              XrmoptionNoArg, "TRUE" },
+  { 0, 0, 0, 0 }
+};
+
+
+/* This structure handles everything to do with the spotlight, and is designed to be
+ * a member of TBumps. */
+typedef struct
+{
+       uint16_ nDegreeCount;
+       double *aSinTable;
+
+       uint8_ *aLightMap;
+       uint16_ nDiameter, nRadius;
+       float nAngleX, nAngleY;         /* Spotlight's movement direction. */
+       float nVelocityX, nVelocityY;
+       uint16_ iWinXCenter, iWinYCenter;
+} SSpotLight;
+
+void CreateSpotLight( SSpotLight *, uint16_, uint16_ );
+void CreateTables( SSpotLight * );
+void CalcLightPos( SSpotLight *, uint16_ *, uint16_ * );
+void DestroySpotLight( SSpotLight *pSpotLight ) { free( pSpotLight->aLightMap ); free( pSpotLight->aSinTable ); }
+
+
+/* The entire program's operation is contained within this structure. */
+typedef struct
+{
+       /* XWindows specific variables. */
+       Display *pDisplay;
+       Window Win;
+       GC GraphicsContext;
+       XColor *aXColors;
+       XImage *pXImage;
+
+       uint8_ nColorCount;                             /* Number of colors used. */
+       uint16_ iWinWidth, iWinHeight;
+       uint16_ *aBumpMap;                              /* The actual bump map. */
+
+       SSpotLight SpotLight;
+} SBumps;
+
+void CreateBumps( SBumps *, Display *, Window );
+void Execute( SBumps * );
+void DestroyBumps( SBumps * );
+
+void SetPalette( SBumps *, XWindowAttributes * );
+void InitBumpMap( SBumps *, XWindowAttributes * );
+void SoftenBumpMap( SBumps * );
+
+
+#endif /* _BUMPS_H */
+
+
+/*
+ * End of Module: "Bumps.h"
+ */
+
+/* vim: ts=4
+ */
diff --git a/hacks/ccurve.c b/hacks/ccurve.c
new file mode 100644 (file)
index 0000000..6dbe0ac
--- /dev/null
@@ -0,0 +1,790 @@
+/* ccurve, Copyright (c) 1998, 1999
+ *  Rick Campbell <rick@campbellcentral.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or
+ * implied warranty.
+ *
+ */
+
+/* Draw self-similar linear fractals including the classic ``C Curve''
+ * 
+ * 16 Aug 1999  Rick Campbell <rick@campbellcentral.org>
+ *      Eliminated sub-windows-with-backing-store-double-buffering crap in
+ *      favor of drawing the new image in a pixmap and then splatting that on
+ *      the window.
+ *
+ * 19 Dec 1998  Rick Campbell <rick@campbellcentral.org>
+ *      Original version.
+ */
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "screenhack.h"
+#include "colors.h"
+#include "erase.h"
+
+#define SQRT3 (1.73205080756887729353)
+#define MAXIMUM_COLOR_COUNT (256)
+#define EPSILON (1e-5)
+
+typedef struct Position_struct
+{
+    double x;
+    double y;
+}
+Position;
+
+typedef struct Segment_struct
+{
+    double angle;
+    double length;
+}
+Segment;
+
+static int                  color_count = 0;
+static int                  color_index = 0;
+static Colormap             color_map = (Colormap)NULL;
+static XColor               colors [MAXIMUM_COLOR_COUNT];
+static int                  line_count = 0;
+static int                  maximum_lines = 0;
+static double               plot_maximum_x = -1000.00;
+static double               plot_maximum_y = -1000.00;
+static double               plot_minimum_x =  1000.00;
+static double               plot_minimum_y =  1000.00;
+static int                  total_lines = 0;
+
+/* normalize alters the sequence to go from (0,0) to (1,0) */
+static
+void
+normalized_plot (int       segment_count,
+                Segment*  segments,
+                Position* points)
+{
+    double   angle = 0.0;
+    double   cosine = 0.0;
+    int      index = 0;
+    double   length = 0.0;
+    double   sine = 0.0;
+    double   x = 0.0;
+    double   y = 0.0;
+
+    for (index = 0; index < segment_count; ++index)
+    {
+       Segment* segment = segments + index;
+       double length = segment->length;
+       double angle = segment->angle;
+
+       x += length * cos (angle);
+       y += length * sin (angle);
+       points [index].x = x;
+       points [index].y = y;
+    }
+    angle = -(atan2 (y, x));
+    cosine = cos (angle);
+    sine = sin (angle);
+    length = sqrt ((x * x) + (y * y));
+    /* rotate and scale */
+    for (index = 0; index < segment_count; ++index)
+    {
+       double temp_x = points [index].x;
+       double temp_y = points [index].y;
+       points [index].x = ((temp_x * cosine) + (temp_y * (-sine))) / length;
+       points [index].y = ((temp_x * sine) + (temp_y * cosine)) / length;
+    }
+}
+
+static
+void
+copy_points (int       segment_count,
+            Position* source,
+            Position* target)
+{
+    int      index = 0;
+
+    for (index = 0; index < segment_count; ++index)
+    {
+       target [index] = source [index];
+    }
+}
+
+static
+void
+realign (double    x1,
+        double    y1,
+        double    x2,
+        double    y2,
+        int       segment_count,
+        Position* points)
+{
+    double angle = 0.0;
+    double cosine = 0.0;
+    double delta_x = 0.0;
+    double delta_y = 0.0;
+    int    index = 0;
+    double length = 0.0;
+    double sine = 0.0;
+
+    delta_x = x2 - x1;
+    delta_y = y2 - y1;
+    angle = atan2 (delta_y, delta_x);
+    cosine = cos (angle);
+    sine = sin (angle);
+    length = sqrt ((delta_x * delta_x) + (delta_y * delta_y));
+    /* rotate, scale, then shift */
+    for (index = 0; index < segment_count; ++index)
+    {
+       double temp_x = points [index].x;
+       double temp_y = points [index].y;
+       points [index].x
+           = (length * ((temp_x * cosine) + (temp_y * (-sine)))) + x1;
+       points [index].y
+           = (length * ((temp_x * sine) + (temp_y * cosine))) + y1;
+    }
+}
+
+static
+void
+self_similar_normalized (Display*  display,
+                        Pixmap    pixmap,
+                        GC        context,
+                        int       width,
+                        int       height,
+                        int       iterations,
+                        double    x1,
+                        double    y1,
+                        double    x2,
+                        double    y2,
+                        double    maximum_x,
+                        double    maximum_y,
+                        double    minimum_x,
+                        double    minimum_y,
+                        int       segment_count,
+                        Position* points)
+{
+    if (iterations == 0)
+    {
+       double delta_x = maximum_x - minimum_x;
+       double delta_y = maximum_y - minimum_y;
+       color_index = (int)(((double)(line_count * color_count))
+                           / ((double)total_lines));
+       ++line_count;
+       XSetForeground (display, context, colors [color_index].pixel);
+       if (plot_maximum_x < x1) plot_maximum_x = x1;
+       if (plot_maximum_x < x2) plot_maximum_x = x2;
+       if (plot_maximum_y < y1) plot_maximum_y = y1;
+       if (plot_maximum_y < y2) plot_maximum_y = y2;
+       if (plot_minimum_x > x1) plot_minimum_x = x1;
+       if (plot_minimum_x > x2) plot_minimum_x = x2;
+       if (plot_minimum_y > y1) plot_minimum_y = y1;
+       if (plot_minimum_y > y2) plot_minimum_y = y2;
+       XDrawLine (display, pixmap, context,
+                  (int)(((x1 - minimum_x) / delta_x) * width),
+                  (int)(((maximum_y - y1) / delta_y) * height),
+                  (int)(((x2 - minimum_x) / delta_x) * width),
+                  (int)(((maximum_y - y2) / delta_y) * height));
+    }
+    else
+    {
+       int       index = 0;
+       double    next_x = 0.0;
+       double    next_y = 0.0;
+       Position* replacement = (Position*)NULL;
+       double    x = 0.0;
+       double    y = 0.0;
+
+       replacement = (Position*)(alloca (segment_count * sizeof (Segment)));
+       copy_points (segment_count, points, replacement);
+       assert (fabs ((replacement [segment_count - 1].x) - 1.0) < EPSILON);
+       assert (fabs (replacement [segment_count - 1].y) < EPSILON);
+       realign (x1, y1, x2, y2, segment_count, replacement);
+       assert (fabs (x2 - (replacement [segment_count - 1].x)) < EPSILON);
+       assert (fabs (y2 - (replacement [segment_count - 1].y)) < EPSILON);
+       x = x1;
+       y = y1;
+       for (index = 0; index < segment_count; ++index)
+       {
+           next_x = replacement [index].x;
+           next_y = replacement [index].y;
+           self_similar_normalized (display, pixmap, context, width, height,
+                                    iterations - 1, x, y, next_x, next_y,
+                                    maximum_x, maximum_y,
+                                    minimum_x, minimum_y,
+                                    segment_count, points);
+           x = next_x;
+           y = next_y;
+       }
+    }
+}
+
+static
+void
+self_similar (Display* display,
+             Pixmap   pixmap,
+             GC       context,
+             int      width,
+             int      height,
+             int      iterations,
+             double   x1,
+             double   y1,
+             double   x2,
+             double   y2,
+             double   maximum_x,
+             double   maximum_y,
+             double   minimum_x,
+             double   minimum_y,
+             int      segment_count,
+             Segment* segments)
+{
+    Position* points = (Position*)NULL;
+
+    points = (Position*)(alloca (segment_count * sizeof (Position)));
+    normalized_plot (segment_count, segments, points);
+    assert (fabs ((points [segment_count - 1].x) - 1.0) < EPSILON);
+    assert (fabs (points [segment_count - 1].y) < EPSILON);
+    self_similar_normalized (display, pixmap, context,
+                            width, height, iterations,
+                            x1, y1, x2, y2,
+                            maximum_x, maximum_y,
+                            minimum_x, minimum_y,
+                            segment_count, points);
+}
+
+static
+double
+random_double (double base,
+              double limit,
+              double epsilon)
+{
+    double       range = 0.0;
+    unsigned int steps = 0;
+
+    assert (base < limit);
+    assert (epsilon > 0.0);
+    range = limit - base;
+    steps = (unsigned int)(floor (range / epsilon));
+    return base + ((random () % steps) * epsilon);
+}
+
+static
+void
+select_2_pattern (Segment* segments)
+{
+    if ((random () % 2) == 0)
+    {
+       if ((random () % 2) == 0)
+       {
+           segments [0].angle  = -M_PI_4;
+           segments [0].length = M_SQRT2;
+           segments [1].angle  = M_PI_4;
+           segments [1].length = M_SQRT2;
+       }
+       else
+       {
+           segments [0].angle  = M_PI_4;
+           segments [0].length = M_SQRT2;
+           segments [1].angle  = -M_PI_4;
+           segments [1].length = M_SQRT2;
+       }
+    }
+    else
+    {
+       segments [0].angle
+           = random_double (M_PI / 6.0, M_PI / 3.0, M_PI / 180.0);
+       segments [0].length = random_double (0.25, 0.67, 0.001);
+       if ((random () % 2) == 0)
+       {
+           segments [1].angle = -(segments [0].angle);
+           segments [1].length = segments [0].length;
+       }
+       else
+       {
+           segments [1].angle = random_double ((-M_PI) / 3.0,
+                                               (-M_PI) / 6.0,
+                                               M_PI / 180.0);
+           segments [1].length = random_double (0.25, 0.67, 0.001);
+       }       
+    }
+}
+
+static
+void
+select_3_pattern (Segment* segments)
+{
+    switch (random () % 5)
+    {
+     case 0:
+       if ((random () % 2) == 0)
+       {
+           segments [0].angle  = M_PI_4;
+           segments [0].length = M_SQRT2 / 4.0;
+           segments [1].angle  = -M_PI_4;
+           segments [1].length = M_SQRT2 / 2.0;
+           segments [2].angle  = M_PI_4;
+           segments [2].length = M_SQRT2 / 4.0;
+       }
+       else
+       {
+           segments [0].angle  = -M_PI_4;
+           segments [0].length = M_SQRT2 / 4.0;
+           segments [1].angle  = M_PI_4;
+           segments [1].length = M_SQRT2 / 2.0;
+           segments [2].angle  = -M_PI_4;
+           segments [2].length = M_SQRT2 / 4.0;
+       }
+       break;
+     case 1:
+       if ((random () % 2) == 0)
+       {
+           segments [0].angle  = M_PI / 6.0;
+           segments [0].length = 1.0;
+           segments [1].angle  = -M_PI_2;
+           segments [1].length = 1.0;
+           segments [2].angle  = M_PI / 6.0;
+           segments [2].length = 1.0;
+       }
+       else
+       {
+           segments [0].angle  = -M_PI / 6.0;
+           segments [0].length = 1.0;
+           segments [1].angle  = M_PI_2;
+           segments [1].length = 1.0;
+           segments [2].angle  = -M_PI / 6.0;
+           segments [2].length = 1.0;
+       }
+       break;
+     case 2:
+     case 3:
+     case 4:
+       segments [0].angle
+           = random_double (M_PI / 6.0, M_PI / 3.0, M_PI / 180.0);
+       segments [0].length = random_double (0.25, 0.67, 0.001);
+       segments [1].angle
+           = random_double (-M_PI / 3.0, -M_PI / 6.0, M_PI / 180.0);
+       segments [1].length = random_double (0.25, 0.67, 0.001);
+       if ((random () % 3) == 0)
+       {
+           if ((random () % 2) == 0)
+           {
+               segments [2].angle = segments [0].angle;
+           }
+           else
+           {
+               segments [2].angle = -(segments [0].angle);
+           }
+           segments [2].length = segments [0].length;
+       }
+       else
+       {
+           segments [2].angle
+               = random_double (-M_PI / 3.0, -M_PI / 6.0, M_PI / 180.0);
+           segments [2].length = random_double (0.25, 0.67, 0.001);
+       }
+       break;
+    }
+}
+
+static
+void
+select_4_pattern (Segment* segments)
+{
+    switch (random () % 9)
+    {
+     case 0:
+       if ((random () % 2) == 0)
+       {
+           double length = random_double (0.25, 0.50, 0.001);
+
+           segments [0].angle  = 0.0;
+           segments [0].length = 0.5;
+           segments [1].angle  = M_PI_2;
+           segments [1].length = length;
+           segments [2].angle  = -M_PI_2;
+           segments [2].length = length;
+           segments [3].angle  = 0.0;
+           segments [3].length = 0.5;
+       }
+       else
+       {
+           double length = random_double (0.25, 0.50, 0.001);
+
+           segments [0].angle  = 0.0;
+           segments [0].length = 0.5;
+           segments [1].angle  = -M_PI_2;
+           segments [1].length = length;
+           segments [2].angle  = M_PI_2;
+           segments [2].length = length;
+           segments [3].angle  = 0.0;
+           segments [3].length = 0.5;
+       }
+       break;
+     case 1:
+       if ((random () % 2) == 0)
+       {
+           segments [0].angle  = 0.0;
+           segments [0].length = 0.5;
+           segments [1].angle  = M_PI_2;
+           segments [1].length = 0.45;
+           segments [2].angle  = -M_PI_2;
+           segments [2].length = 0.45;
+           segments [3].angle  = 0.0;
+           segments [3].length = 0.5;
+       }
+       else
+       {
+           segments [0].angle  = 0.0;
+           segments [0].length = 0.5;
+           segments [1].angle  = -M_PI_2;
+           segments [1].length = 0.45;
+           segments [2].angle  = M_PI_2;
+           segments [2].length = 0.45;
+           segments [3].angle  = 0.0;
+           segments [3].length = 0.5;
+       }
+       break;
+     case 2:
+       if ((random () % 2) == 0)
+       {
+           segments [0].angle  = 0.0;
+           segments [0].length = 1.0;
+           segments [1].angle  = (5.0 * M_PI) / 12.0;
+           segments [1].length = 1.2;
+           segments [2].angle  = (-5.0 * M_PI) / 12.0;
+           segments [2].length = 1.2;
+           segments [3].angle  = 0.0;
+           segments [3].length = 1.0;
+       }
+       else
+       {
+           segments [0].angle  = 0.0;
+           segments [0].length = 1.0;
+           segments [1].angle  = (-5.0 * M_PI) / 12.0;
+           segments [1].length = 1.2;
+           segments [2].angle  = (5.0 * M_PI) / 12.0;
+           segments [2].length = 1.2;
+           segments [3].angle  = 0.0;
+           segments [3].length = 1.0;
+       }
+       break;
+     case 3:
+       if ((random () % 2) == 0)
+       {
+           double angle
+               = random_double (M_PI / 4.0,
+                                M_PI_2,
+                                M_PI / 180.0);
+
+           segments [0].angle  = 0.0;
+           segments [0].length = 1.0;
+           segments [1].angle  = angle;
+           segments [1].length = 1.2;
+           segments [2].angle  = (-angle);
+           segments [2].length = 1.2;
+           segments [3].angle  = 0.0;
+           segments [3].length = 1.0;
+       }
+       else
+       {
+           double angle
+               = random_double (M_PI / 4.0,
+                                M_PI_2,
+                                M_PI / 180.0);
+
+           segments [0].angle  = 0.0;
+           segments [0].length = 1.0;
+           segments [1].angle  = (-angle);
+           segments [1].length = 1.2;
+           segments [2].angle  = angle;
+           segments [2].length = 1.2;
+           segments [3].angle  = 0.0;
+           segments [3].length = 1.0;
+       }
+       break;
+     case 4:
+       if ((random () % 2) == 0)
+       {
+           double angle
+               = random_double (M_PI / 4.0,
+                                M_PI_2,
+                                M_PI / 180.0);
+
+           segments [0].angle  = 0.0;
+           segments [0].length = 1.0;
+           segments [1].angle  = angle;
+           segments [1].length = 1.2;
+           segments [2].angle  = (-angle);
+           segments [2].length = 1.2;
+           segments [3].angle  = 0.0;
+           segments [3].length = 1.0;
+       }
+       else
+       {
+           double angle
+               = random_double (M_PI / 4.0,
+                                M_PI_2,
+                                M_PI / 180.0);
+
+           segments [0].angle  = 0.0;
+           segments [0].length = 1.0;
+           segments [1].angle  = (-angle);
+           segments [1].length = 1.2;
+           segments [2].angle  = angle;
+           segments [2].length = 1.2;
+           segments [3].angle  = 0.0;
+           segments [3].length = 1.0;
+       }
+       break;
+     case 5:
+       if ((random () % 2) == 0)
+       {
+           double angle
+               = random_double (M_PI / 4.0,
+                                M_PI_2,
+                                M_PI / 180.0);
+           double length = random_double (0.25, 0.50, 0.001);
+
+           segments [0].angle  = 0.0;
+           segments [0].length = 1.0;
+           segments [1].angle  = angle;
+           segments [1].length = length;
+           segments [2].angle  = (-angle);
+           segments [2].length = length;
+           segments [3].angle  = 0.0;
+           segments [3].length = 1.0;
+       }
+       else
+       {
+           double angle
+               = random_double (M_PI / 4.0,
+                                M_PI_2,
+                                M_PI / 180.0);
+           double length = random_double (0.25, 0.50, 0.001);
+
+           segments [0].angle  = 0.0;
+           segments [0].length = 1.0;
+           segments [1].angle  = (-angle);
+           segments [1].length = length;
+           segments [2].angle  = angle;
+           segments [2].length = length;
+           segments [3].angle  = 0.0;
+           segments [3].length = 1.0;
+       }
+       break;
+     case 6:
+     case 7:
+     case 8:
+       segments [0].angle
+           = random_double (M_PI / 12.0, (11.0 * M_PI) / 12.0, 0.001);
+       segments [0].length = random_double (0.25, 0.50, 0.001);
+       segments [1].angle
+           = random_double (M_PI / 12.0, (11.0 * M_PI) / 12.0, 0.001);
+       segments [1].length = random_double (0.25, 0.50, 0.001);
+       if ((random () % 3) == 0)
+       {
+           segments [2].angle
+               = random_double (M_PI / 12.0, (11.0 * M_PI) / 12.0, 0.001);
+           segments [2].length = random_double (0.25, 0.50, 0.001);
+           segments [3].angle
+               = random_double (M_PI / 12.0, (11.0 * M_PI) / 12.0, 0.001);
+           segments [3].length = random_double (0.25, 0.50, 0.001);
+       }
+       else
+       {
+           if ((random () % 2) == 0)
+           {
+               segments [2].angle = -(segments [1].angle);
+               segments [2].length = segments [1].length;
+               segments [3].angle = -(segments [0].angle);
+               segments [3].length = segments [0].length;
+           }
+           else
+           {
+               segments [2].angle = segments [1].angle;
+               segments [2].length = segments [1].length;
+               segments [3].angle = segments [0].angle;
+               segments [3].length = segments [0].length;
+           }
+       }
+       break;
+    }
+}
+
+static void
+select_pattern (int      segment_count,
+               Segment* segments)
+{
+    switch (segment_count)
+    {
+     case 2:
+       select_2_pattern (segments);
+       break;
+     case 3:
+       select_3_pattern (segments);
+       break;
+     case 4:
+       select_4_pattern (segments);
+       break;
+     default:
+       fprintf (stderr, "\nBad segment count, must be 2, 3, or 4.\n");
+       exit (1);
+    }
+}
+
+char *progclass = "Ccurve";
+
+char *defaults [] =
+{
+    ".delay:      1",
+    ".pause:      3",
+    ".limit: 200000",
+    0
+};
+
+XrmOptionDescRec options [] =
+{
+    { "-delay", ".delay", XrmoptionSepArg, 0 },
+    { "-pause", ".pause", XrmoptionSepArg, 0 },
+    { "-limit", ".limit", XrmoptionSepArg, 0 },
+    { 0, 0, 0, 0 }
+};
+
+#define Y_START (0.5)
+
+void
+screenhack (Display* display,
+           Window   window)
+{
+    unsigned long int    background      = 0;
+    unsigned long int    black           = 0;
+    GC                   context;
+    int                  delay           = 0;
+    int                  depth           = 0;
+    Pixmap               pixmap           = (Pixmap)NULL;
+    XWindowAttributes    hack_attributes;
+    int                  height          = 0;
+    int                  iterations      = 0;
+    int                  pause           = 0;
+    XGCValues            values;
+    unsigned long int    white           = 0;
+    int                  width           = 0;
+
+    delay = get_integer_resource ("delay", "Integer");
+    pause = get_integer_resource ("pause", "Integer");
+    maximum_lines = get_integer_resource ("limit", "Integer");
+    black = BlackPixel (display, DefaultScreen (display));
+    white = WhitePixel (display, DefaultScreen (display));
+    background = black;
+    XGetWindowAttributes (display, window, &hack_attributes);
+    width = hack_attributes.width;
+    height = hack_attributes.height;
+    depth = hack_attributes.depth;
+    color_map = hack_attributes.colormap;
+    pixmap = XCreatePixmap (display, window, width, height, depth);
+    values.foreground = white;
+    values.background = black;
+    context = XCreateGC (display, window, GCForeground | GCBackground,
+                        &values);
+    color_count = MAXIMUM_COLOR_COUNT;
+    make_color_loop (display, color_map,
+                    0,   1, 1,
+                    120, 1, 1,
+                    240, 1, 1,
+                    colors, &color_count, True, False);
+    if (color_count <= 0)
+    {
+        color_count = 1;
+        colors [0].red = colors [0].green = colors [0].blue = 0xFFFF;
+        XAllocColor (display, color_map, &colors [0]);
+    }
+
+    while (1)
+    {
+       int    index = 0;
+       double maximum_x =  1.20;
+       double maximum_y =  0.525;
+       double minimum_x = -0.20;
+       double minimum_y = -0.525;
+       static int lengths [] = { 4, 4, 4, 4, 4, 3, 3, 3, 2 };
+       int segment_count = 0;
+       Segment* segments = (Segment*)NULL;
+       double x1 = 0.0;
+       double y1 = 0.0;
+       double x2 = 1.0;
+       double y2 = 0.0;
+
+       segment_count
+           = lengths [random () % (sizeof (lengths) / sizeof (int))];
+       segments
+           = (Segment*)(alloca ((segment_count) * sizeof (Segment)));
+       select_pattern (segment_count, segments);
+       iterations = floor (log (maximum_lines)
+                               / log (((double)(segment_count))));
+       if ((random () % 3) != 0)
+       {
+           double factor = 0.45;
+           x1 += random_double (-factor, factor, 0.001);
+           y1 += random_double (-factor, factor, 0.001);
+           x2 += random_double (-factor, factor, 0.001);
+           y2 += random_double (-factor, factor, 0.001);
+       }
+/*     background = (random () % 2) ? black : white; */
+       for (index = 0; index < iterations; ++index)
+       {
+           double delta_x = 0.0;
+           double delta_y = 0.0;
+
+           XSetForeground (display, context, background);
+           XFillRectangle (display, pixmap, context, 0, 0, width, height);
+           line_count = 0;
+           total_lines = (int)(pow ((double)(segment_count),
+                                    (double)index));
+           plot_maximum_x = -1000.00;
+           plot_maximum_y = -1000.00;
+           plot_minimum_x =  1000.00;
+           plot_minimum_y =  1000.00;
+           self_similar (display, pixmap, context, width, height, index,
+                         x1, y1, x2, y2,
+                         maximum_x,
+                         maximum_y,
+                         minimum_x,
+                         minimum_y,
+                         segment_count, segments);
+           delta_x = plot_maximum_x - plot_minimum_x;
+           delta_y = plot_maximum_y - plot_minimum_y;
+           maximum_x = plot_maximum_x + (delta_x * 0.2);
+           maximum_y = plot_maximum_y + (delta_y * 0.2);
+           minimum_x = plot_minimum_x - (delta_x * 0.2);
+           minimum_y = plot_minimum_y - (delta_y * 0.2);
+           delta_x = maximum_x - minimum_x;
+           delta_y = maximum_y - minimum_y;
+           if ((delta_y / delta_x) > (((double)height) / ((double)width)))
+           {
+               double new_delta_x
+                   = (delta_y * ((double)width)) / ((double)height);
+               minimum_x -= (new_delta_x - delta_x) / 2.0;
+               maximum_x += (new_delta_x - delta_x) / 2.0;
+           }
+           else
+           {
+               double new_delta_y
+                   = (delta_x * ((double)height)) / ((double)width);
+               minimum_y -= (new_delta_y - delta_y) / 2.0;
+               maximum_y += (new_delta_y - delta_y) / 2.0;
+           }
+           XCopyArea (display, pixmap, window, context, 0, 0, width, height,
+                      0, 0);
+           if (delay) sleep (delay);
+           screenhack_handle_events (display);
+       }
+       if (pause) sleep (pause);
+       erase_full_window (display, window);
+    }
+}
index 69a496d4f1025d5c22ff9c307a4f5d5bd9fed417..462220e980995bb6808fa3f0627256024ab8be21 100644 (file)
@@ -1,11 +1,14 @@
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) ANT.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) ATTRACTION.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) BLASTER.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) BLITSPIN.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) BOUBOULE.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) BRAID.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) BSOD.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) BUBBLES-DEFAULT.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) BUBBLES.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) BUMPS.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) CCURVE.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) COMPASS.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) CORAL.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) CRITICAL.C
index 69a496d4f1025d5c22ff9c307a4f5d5bd9fed417..462220e980995bb6808fa3f0627256024ab8be21 100644 (file)
@@ -1,11 +1,14 @@
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) ANT.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) ATTRACTION.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) BLASTER.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) BLITSPIN.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) BOUBOULE.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) BRAID.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) BSOD.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) BUBBLES-DEFAULT.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) BUBBLES.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) BUMPS.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) CCURVE.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) COMPASS.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) CORAL.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) CRITICAL.C
index 74bcf4585cc3e04dd1b4024248b2dbef97123c7d..4218418f201628b8b54c2969a506736196883d0e 100644 (file)
  *     -more distortion matrices (fortunately, I'm out of ideas :)
  * Stuff that would be cool but probably too much of a resource hog:
  *     -some kind of interpolation to avoid jaggies
+ *    -large speed values leaves the image distorted
  * program idea borrowed from a screensaver on a non-*NIX OS,
+ *
+ * 28 Sep 1999 Jonas Munsin (jmunsin@iki.fi)
+ *    Added about 10x faster algortim for 8, 16 and 32 bpp (modifies pixels
+ *    directly avoiding costly XPutPixle(XGetPixel()) calls, inspired by
+ *    xwhirl made by horvai@clipper.ens.fr (Peter Horvai) and the XFree86
+ *    Xlib sources.
+ *    This piece of code is really horrible, but it works, and at the moment
+ *    I don't have time or inspiration to fix something that works (knock
+ *    on wood).
+ * 08 Oct 1999 Jonas Munsin (jmunsin@iki.fi)
+ *     Corrected several bugs causing references beyond allocated memory.
  */
 
 #include <math.h>
 #include "screenhack.h"
 #include <X11/Xutil.h>
+#include <X11/Xmd.h>
 
 #ifdef HAVE_XSHM_EXTENSION
 # include "xshm.h"
-static Bool use_shm;
+static Bool use_shm = False;
 static XShmSegmentInfo shm_info;
 #endif /* HAVE_XSHM_EXTENSION */
 
@@ -41,7 +54,7 @@ struct coo {
 };
 static struct coo xy_coo[10];
 
-static int delay, radius, speed, number, blackhole, vortex, magnify, reflect;
+static int delay, radius, speed, number, blackhole, vortex, magnify, reflect, slow;
 static XWindowAttributes xgwa;
 static GC gc;
 static Window g_window;
@@ -49,9 +62,11 @@ static Display *g_dpy;
 static unsigned long black_pixel;
 
 static XImage *orig_map, *buffer_map;
+static unsigned long *buffer_map_cache;
 
 static int ***from;
 static int ****from_array;
+static int *fast_from = NULL;
 static void (*effect) (int) = NULL;
 static void move_lense(int);
 static void swamp_thing(int);
@@ -61,6 +76,14 @@ static void (*draw) (int) = NULL;
 static void reflect_draw(int);
 static void plain_draw(int);
 
+static void (*draw_routine)(XImage *, XImage *, int, int, int *) = NULL;
+static void fast_draw_8(XImage *, XImage *, int, int, int *);
+static void fast_draw_16(XImage *, XImage *, int, int, int *);
+static void fast_draw_32(XImage *, XImage *, int, int, int *);
+static void generic_draw(XImage *, XImage *, int, int, int *);
+static int bpp_size = 0;
+
+
 static void init_distort(Display *dpy, Window window) 
 {
        XGCValues gcv;
@@ -83,6 +106,7 @@ static void init_distort(Display *dpy, Window window)
        vortex = get_boolean_resource("vortex", "Boolean");
        magnify = get_boolean_resource("magnify", "Boolean");
        reflect = get_boolean_resource("reflect", "Boolean");
+       slow = get_boolean_resource("slow", "Boolean");
        
        if (get_boolean_resource("swamp", "Boolean"))
                effect = &swamp_thing;
@@ -102,16 +126,17 @@ static void init_distort(Display *dpy, Window window)
  * -radius 100 -number 1 -speed 2 -vortex
  * -radius 100 -number 1 -speed 2 -vortex -magnify
  * -radius 100 -number 1 -speed 2 -vortex -magnify -blackhole
- * -radius 50 -number 4 -speed 2 -swamp
- * -radius 50 -number 4 -speed 2 -swamp -blackhole
- * -radius 50 -number 4 -speed 2 -swamp -vortex
- * -radius 50 -number 4 -speed 2 -swamp -vortex -magnify
- * -radius 50 -number 4 -speed 2 -swamp -vortex -magnify -blackhole
  * -radius 80 -number 1 -speed 2 -reflect
  * -radius 50 -number 3 -speed 2 -reflect
+ * jwz: not these
+ *   -radius 50 -number 4 -speed 2 -swamp
+ *   -radius 50 -number 4 -speed 2 -swamp -blackhole
+ *   -radius 50 -number 4 -speed 2 -swamp -vortex
+ *   -radius 50 -number 4 -speed 2 -swamp -vortex -magnify
+ *   -radius 50 -number 4 -speed 2 -swamp -vortex -magnify -blackhole
  */
                
-               i = (random() % 17);
+               i = (random() % 12 /* 17 */);
 
                draw = &plain_draw;
 
@@ -146,27 +171,34 @@ static void init_distort(Display *dpy, Window window)
                        case 9:
                                radius=100;number=1;speed=2;vortex=1;magnify=1;blackhole=1;
                                effect=&move_lense;break;
+
                        case 10:
+                               radius=80;number=1;speed=2;reflect=1;
+                               draw = &reflect_draw;effect = &move_lense;break;
+                       case 11:
+                               radius=50;number=4;speed=2;reflect=1;
+                               draw = &reflect_draw;effect = &move_lense;break;
+
+#if 0 /* jwz: not these */
+                       case 12:
                                radius=50;number=4;speed=2;
                                effect=&swamp_thing;break;
-                       case 11:
+                       case 13:
                                radius=50;number=4;speed=2;blackhole=1;
                                effect=&swamp_thing;break;
-                       case 12:
+                       case 14:
                                radius=50;number=4;speed=2;vortex=1;
                                effect=&swamp_thing;break;
-                       case 13:
+                       case 15:
                                radius=50;number=4;speed=2;vortex=1;magnify=1;
                                effect=&swamp_thing;break;
-                       case 14:
+                       case 16:
                                radius=50;number=4;speed=2;vortex=1;magnify=1;blackhole=1;
                                effect=&swamp_thing;break;
-                       case 15:
-                               radius=80;number=1;speed=2;reflect=1;
-                               draw = &reflect_draw;effect = &move_lense;break;
-                       case 16: default:
-                               radius=50;number=4;speed=2;reflect=1;
-                               draw = &reflect_draw;effect = &move_lense;break;
+#endif
+
+            default:
+                abort(); break;
                }
 
        }
@@ -205,6 +237,12 @@ static void init_distort(Display *dpy, Window window)
        buffer_map = 0;
        orig_map = XGetImage(dpy, window, 0, 0, xgwa.width, xgwa.height,
                                                 ~0L, ZPixmap);
+       buffer_map_cache = malloc(sizeof(unsigned long)*(2*radius+speed+2)*(2*radius+speed+2));
+
+       if (buffer_map_cache == NULL) {
+               perror("distort");
+               exit(EXIT_FAILURE);
+       }
 
 # ifdef HAVE_XSHM_EXTENSION
 
@@ -229,6 +267,31 @@ static void init_distort(Display *dpy, Window window)
                  calloc(buffer_map->height, buffer_map->bytes_per_line);
        }
 
+       if ((buffer_map->byte_order == orig_map->byte_order)
+                       && (buffer_map->depth == orig_map->depth)
+                       && (buffer_map->format == ZPixmap)
+                       && (orig_map->format == ZPixmap)
+                       && !slow) {
+               switch (orig_map->bits_per_pixel) {
+                       case 32:
+                               draw_routine = &fast_draw_32;
+                               bpp_size = sizeof(CARD32);
+                               break;
+                       case 16:
+                               draw_routine = &fast_draw_16;
+                               bpp_size = sizeof(CARD16);
+                               break;
+                       case 8:
+                               draw_routine = &fast_draw_8;
+                               bpp_size = sizeof(CARD8);
+                               break;
+                       default:
+                               draw_routine = &generic_draw;
+                               break;
+               }
+       } else {
+               draw_routine = &generic_draw;
+       }
        init_round_lense();
 
        for (i = 0; i < number; i++) {
@@ -241,6 +304,7 @@ static void init_distort(Display *dpy, Window window)
                xy_coo[i].xmove = speed + (i%2)*2*(-speed);
                xy_coo[i].ymove = speed + (i%2)*2*(-speed);
        }
+
 }
 
 /* example: initializes a "see-trough" matrix */
@@ -255,6 +319,26 @@ static void init_distort(Display *dpy, Window window)
        } 
 }
 */
+static void convert(void) {
+       int *p;
+       int i, j;
+       fast_from = calloc(1, sizeof(int)*((buffer_map->bytes_per_line/bpp_size)*(2*radius+speed+2) + 2*radius+speed+2));
+       if (fast_from == NULL) {
+               perror("distort");
+               exit(EXIT_FAILURE);
+       }
+       p = fast_from;
+       for (i = 0; i < 2*radius+speed+2; i++) {
+               for (j = 0; j < 2*radius+speed+2; j++) {
+                       *(p + i + j*buffer_map->bytes_per_line/bpp_size)
+                               = from[i][j][0] + xgwa.width*from[i][j][1];
+                       if (*(p + i + j*buffer_map->bytes_per_line/bpp_size) < 0
+                                       || *(p + i + j*buffer_map->bytes_per_line/bpp_size) >= orig_map->height*orig_map->width) {
+                               *(p + i + j*buffer_map->bytes_per_line/bpp_size) = 0;
+                       }
+               }
+       }
+}
 
 /* makes a lense with the Radius=loop and centred in
  * the point (radius, radius)
@@ -264,7 +348,7 @@ static void make_round_lense(int radius, int loop)
        int i, j;
 
        for (i = 0; i < 2*radius+speed+2; i++) {
-               for(j = 0; j < 2*radius+speed+2; j++) {
+               for(j = 0; j < ((0 == bpp_size) ? (2*radius+speed+2) : (buffer_map->bytes_per_line/bpp_size)); j++) {
                        double r, d;
                        r = sqrt ((i-radius)*(i-radius)+(j-radius)*(j-radius));
                        if (loop == 0)
@@ -280,18 +364,18 @@ static void make_round_lense(int radius, int loop)
                 * (with permission) from the whirl plugin for gimp,
                 * Copyright (C) 1996 Federico Mena Quintero
                 */
-               /* 2.5 is just a constant used because it looks good :) */
-                                       angle = 2.5*(1-d)*(1-d);
+               /* 5 is just a constant used because it looks good :) */
+                                       angle = 5*(1-d)*(1-d);
 
         /* Avoid atan2: DOMAIN error message */
                                        if ((radius-j) == 0.0 && (radius-i) == 0.0) {
                                                from[i][j][0] = radius + cos(angle)*r;
                                                from[i][j][1] = radius + sin(angle)*r;
                                        } else {
-                                       from[i][j][0] = radius +
-                                                                       cos(angle - atan2(radius-j, -(radius-i)))*r;
-                                       from[i][j][1] = radius +
-                                                                       sin(angle - atan2(radius-j, -(radius-i)))*r;
+                                               from[i][j][0] = radius +
+                                                       cos(angle - atan2(radius-j, -(radius-i)))*r;
+                                               from[i][j][1] = radius +
+                                                       sin(angle - atan2(radius-j, -(radius-i)))*r;
                                        }
                                        if (magnify) {
                                                r = sin(d*M_PI_2);
@@ -319,6 +403,12 @@ static void make_round_lense(int radius, int loop)
                        }
                }
        }
+
+       /* this is really just a quick hack to keep both the compability mode with all depths and still
+        * allow the custom optimized draw routines with the minimum amount of work */
+       if (0 != bpp_size) {
+               convert();
+       }
 }
 
 #ifndef EXIT_FAILURE
@@ -328,23 +418,23 @@ static void make_round_lense(int radius, int loop)
 static void allocate_lense(void)
 {
        int i, j;
+       int s = ((0 != bpp_size) ? (buffer_map->bytes_per_line/bpp_size) : (2*radius+speed+2));
        /* maybe this should be redone so that from[][][] is in one block;
         * then pointers could be used instead of arrays in some places (and
         * maybe give a speedup - maybe also consume less memory)
         */
-
-       from = (int ***)malloc((2*radius+speed+2) * sizeof(int **));
+       from = (int ***)malloc(s*sizeof(int **));
        if (from == NULL) {
                perror("distort");
                exit(EXIT_FAILURE);
        }
-       for (i = 0; i < 2*radius+speed+2; i++) {
+       for (i = 0; i < s; i++) {
                from[i] = (int **)malloc((2*radius+speed+2) * sizeof(int *));
                if (from[i] == NULL) {
                        perror("distort");
                        exit(EXIT_FAILURE);
                }
-               for (j = 0; j < 2*radius+speed+2; j++) {
+               for (j = 0; j < s; j++) {
                        from[i][j] = (int *)malloc(2 * sizeof(int));
                        if (from[i][j] == NULL) {
                                perror("distort");
@@ -375,28 +465,83 @@ static void init_round_lense(void)
        }
 }
 
+/* If fast_draw_8, fast_draw_16 or fast_draw_32 are to be used, the following properties
+ * of the src and dest XImages must hold (otherwise the generic, slooow, method provided
+ * by X is to be used):
+ *     src->byte_order == dest->byte_order
+ *     src->format == ZPixmap && dest->format == ZPixmap
+ *     src->depth == dest->depth == the depth the function in question asumes
+ * x and y is the coordinates in src from where to cut out the image from,
+ * distort_matrix is a precalculated array of how to distort the matrix
+ */
+
+static void fast_draw_8(XImage *src, XImage *dest, int x, int y, int *distort_matrix) {
+       CARD8 *u = (CARD8 *)dest->data;
+       CARD8 *t = (CARD8 *)src->data + x + y*src->bytes_per_line/sizeof(CARD8);
+
+       while (u < (CARD8 *)(dest->data + sizeof(CARD8)*dest->height
+                               *dest->bytes_per_line/sizeof(CARD8))) {
+               *u++ = t[*distort_matrix++];
+       }
+}
+
+static void fast_draw_16(XImage *src, XImage *dest, int x, int y, int *distort_matrix) {
+       CARD16 *u = (CARD16 *)dest->data;
+       CARD16 *t = (CARD16 *)src->data + x + y*src->bytes_per_line/sizeof(CARD16);
+
+       while (u < (CARD16 *)(dest->data + sizeof(CARD16)*dest->height
+                               *dest->bytes_per_line/sizeof(CARD16))) {
+               *u++ = t[*distort_matrix++];
+       }
+}
+
+static void fast_draw_32(XImage *src, XImage *dest, int x, int y, int *distort_matrix) {
+       CARD32 *u = (CARD32 *)dest->data;
+       CARD32 *t = (CARD32 *)src->data + x + y*src->bytes_per_line/sizeof(CARD32);
+
+       while (u < (CARD32 *)(dest->data + sizeof(CARD32)*dest->height
+                               *dest->bytes_per_line/sizeof(CARD32))) {
+               *u++ = t[*distort_matrix++];
+       }
+}
+
+static void generic_draw(XImage *src, XImage *dest, int x, int y, int *distort_matrix) {
+       int i, j;
+       for (i = 0; i < dest->width; i++)
+               for (j = 0; j < dest->height; j++)
+                       if (from[i][j][0] + x >= 0 &&
+                                       from[i][j][0] + x < src->width &&
+                                       from[i][j][1] + y >= 0 &&
+                                       from[i][j][1] + y < src->height)
+                               XPutPixel(dest, i, j,
+                                               XGetPixel(src,
+                                                       from[i][j][0] + x,
+                                                       from[i][j][1] + y));
+}
 
 /* generate an XImage of from[][][] and draw it on the screen */
 static void plain_draw(int k)
 {
-       int i, j;
-       for(i = 0 ; i < 2*radius+speed+2; i++) {
-               for(j = 0 ; j < 2*radius+speed+2 ; j++) {
-                       if (xy_coo[k].x+from[i][j][0] >= 0 &&
-                                       xy_coo[k].x+from[i][j][0] < xgwa.width &&
-                                       xy_coo[k].y+from[i][j][1] >= 0 &&
-                                       xy_coo[k].y+from[i][j][1] < xgwa.height)
-                               XPutPixel(buffer_map, i, j,
-                                               XGetPixel(orig_map,
-                                                       xy_coo[k].x+from[i][j][0],
-                                                       xy_coo[k].y+from[i][j][1]));
-               }
-       }
+       if (xy_coo[k].x+2*radius+speed+2 > orig_map->width ||
+                       xy_coo[k].y+2*radius+speed+2 > orig_map->height)
+               return;
+
+       draw_routine(orig_map, buffer_map, xy_coo[k].x, xy_coo[k].y, fast_from);
+
+# ifdef HAVE_XSHM_EXTENSION
+       if (use_shm)
+               XShmPutImage(g_dpy, g_window, gc, buffer_map, 0, 0, xy_coo[k].x, xy_coo[k].y,
+                               2*radius+speed+2, 2*radius+speed+2, False);
+       else
+# endif
+
+       if (!use_shm)
+               XPutImage(g_dpy, g_window, gc, buffer_map, 0, 0, xy_coo[k].x, xy_coo[k].y,
+                               2*radius+speed+2, 2*radius+speed+2);
 
-       XPutImage(g_dpy, g_window, gc, buffer_map, 0, 0, xy_coo[k].x, xy_coo[k].y,
-                       2*radius+speed+2, 2*radius+speed+2);
 }
 
+
 /* generate an XImage from the reflect algoritm submitted by
  * Randy Zack <randy@acucorp.com>
  * draw really got too big and ugly so I split it up
@@ -486,6 +631,7 @@ static void move_lense(int k)
        xy_coo[k].x = xy_coo[k].x + xy_coo[k].xmove;
        xy_coo[k].y = xy_coo[k].y + xy_coo[k].ymove;
 
+       /* bounce against othe lenses */
        for (i = 0; i < number; i++) {
                if ((i != k)
                
@@ -546,7 +692,7 @@ char *defaults [] = {
        "*visualID:                     Best",
 #endif
 
-       "*delay:                        10000",
+       "*delay:                        1000",
        "*radius:                       0",
        "*speed:                        0",
        "*number:                       0",
@@ -573,6 +719,7 @@ XrmOptionDescRec options [] = {
        { "-vortex",    ".vortex",      XrmoptionNoArg, "True" },
        { "-magnify",   ".magnify",     XrmoptionNoArg, "True" },
        { "-blackhole", ".blackhole",   XrmoptionNoArg, "True" },
+       { "-slow",      ".slow",        XrmoptionNoArg, "True" },
 #ifdef HAVE_XSHM_EXTENSION
        { "-shm",               ".useSHM",      XrmoptionNoArg, "True" },
        { "-no-shm",    ".useSHM",      XrmoptionNoArg, "False" },
index 54fe80739b9e4f62c8b3f83e614bbea1558c42eb..0a64c0609a11087f58db86dba8ac4d83a6d7b86e 100644 (file)
-/* -*- Mode: C; tab-width: 4 -*-
- * forest.c --- draw a fractal forest.
- */
-#if !defined( lint ) && !defined( SABER )
-static const char sccsid[] = "@(#)forest.c     4.03 97/05/10 xlockmore";
-#endif
-
-/* Copyright (c) 1995 Pascal Pensa <pensa@aurora.unice.fr>
- *
- * Original idea : Guillaume Ramey <ramey@aurora.unice.fr>
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation.
+/* forest.c (aka xtree.c), Copyright (c) 1999
+ *  Peter Baumung <unn6@rz.uni-karlsruhe.de>
  *
- * This file is provided AS IS with no warranties of any kind.  The author
- * shall have no liability with respect to the infringement of copyrights,
- * trade secrets or any patents by this file or any part thereof.  In no
- * event will the author be liable for any lost revenue or profits or
- * other special, indirect and consequential damages.
+ * Most code taken from
+ *  xscreensaver, Copyright (c) 1992, 1995, 1997 
+ *  Jamie Zawinski <jwz@netscape.com>
  *
- * Revision History:
- * 10-May-97: Compatible with xscreensaver
+ * 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.
  */
 
+#include "config.h"
+
 #ifdef STANDALONE
-# define PROGCLASS                                     "Forest"
-# define HACK_INIT                                     init_forest
-# define HACK_DRAW                                     draw_forest
-# define forest_opts                           xlockmore_opts
-# define DEFAULTS      "*count:                100     \n"                     \
-                                       "*cycles:               200     \n"                     \
-                                       "*delay:                400000  \n"                     \
-                                       "*ncolors:              100     \n"
-# define UNIFORM_COLORS
-# include "xlockmore.h"                                /* from the xscreensaver distribution */
-# include "erase.h"
+# define PROGCLASS          "Forest" /*"XTree"*/
+# define HACK_INIT          init_trees
+# define HACK_DRAW          draw_trees
+# define trees_opts         xlockmore_opts 
+# define DEFAULTS   "*delay:            500000 \n"  \
+                    "*ncolors:          20     \n"  \
+                    "*eraseSpeed:       400    \n"  \
+                    "*eraseMode:        -1     \n"  \
+                    "*installColormap   False"
+# include "xlockmore.h"     /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
 # include "xlock.h"                                    /* from the xlockmore distribution */
 #endif /* !STANDALONE */
 
-ModeSpecOpt forest_opts = {
-  0, NULL, 0, NULL, NULL };
-
-
-#define MINTREES   1
-
-#define MINHEIGHT  20          /* Tree height range */
-#define MAXHEIGHT  40
-
-#define MINANGLE   15          /* (degree) angle between soon */
-#define MAXANGLE   35
-#define RANDANGLE  15          /* (degree) Max random angle from default */
-
-#define REDUCE     90          /* Height % from father */
-
-#define ITERLEVEL  10          /* Tree iteration */
-
-#define COLORSPEED  2          /* Color increment */
-
-/* degree to radian */
-#define DEGTORAD(x) (((float)(x)) * M_PI / 180.0)
-
-#define RANGE_RAND(min,max) ((min) + NRAND((max) - (min)))
+ModeSpecOpt trees_opts = {0, NULL, 0, NULL, NULL};
 
 typedef struct {
-       int         width;
-       int         height;
-       int         time;       /* up time */
-       int         ntrees;
-} foreststruct;
-
-static foreststruct *forests = NULL;
-
-static void
-draw_tree(ModeInfo * mi,
-         short int x, short int y, short int len,
-         float a, float as, short int c, short int level)
-                               /* Father's end */
-                               /* Length */
-                               /* color */
-                               /* Height level */
-                               /* Father's angle */
-                               /* Father's angle step */
-{
-       Display    *display = MI_DISPLAY(mi);
-       Window      window = MI_WINDOW(mi);
-       GC          gc = MI_GC(mi);
-       short       x_1, y_1, x_2, y_2;
-       float       a1, a2;
-
-       /* left */
-
-       a1 = a + as + DEGTORAD(NRAND(2 * RANDANGLE) - RANDANGLE);
-
-       x_1 = x + (short) (COSF(a1) * ((float) len));
-       y_1 = y + (short) (SINF(a1) * ((float) len));
-
-       /* right */
-
-       a2 = a - as + DEGTORAD(NRAND(2 * RANDANGLE) - RANDANGLE);
-
-       x_2 = x + (short) (COSF(a2) * ((float) len));
-       y_2 = y + (short) (SINF(a2) * ((float) len));
-
-       if (MI_NPIXELS(mi) > 2) {
-               XSetForeground(display, gc, MI_PIXEL(mi, c));
-               c = (c + COLORSPEED) % MI_NPIXELS(mi);
-       } else
-               XSetForeground(display, gc, MI_WIN_WHITE_PIXEL(mi));
-
-       XDrawLine(display, window, gc, x, y, x_1, y_1);
-       XDrawLine(display, window, gc, x, y, x_2, y_2);
-
-       if (level < 2) {
-               XDrawLine(display, window, gc, x + 1, y, x_1 + 1, y_1);
-               XDrawLine(display, window, gc, x + 1, y, x_2 + 1, y_2);
-       }
-       len = (len * REDUCE * 10) / 1000;
-
-       if (level < ITERLEVEL) {
-               draw_tree(mi, x_1, y_1, len, a1, as, c, level + 1);
-               draw_tree(mi, x_2, y_2, len, a2, as, c, level + 1);
-       }
+  int     x;
+  int     y;
+  int     thick;
+  double  size;
+  long    color;
+  int     toDo;
+  int     season;
+} treestruct;
+
+static treestruct *trees = NULL;
+
+XColor colors[20];
+int color;
+
+static long colorM[12] = {0xff0000, 0xff8000, 0xffff00, 0x80ff00,
+                          0x00ff00, 0x00ff80, 0x00ffff, 0x0080ff,
+                          0x0000ff, 0x8000ff, 0xff00ff, 0xff0080};
+
+static long colorV[12] = {0x0a0000, 0x0a0500, 0x0a0a00, 0x050a00,
+                          0x000a00, 0x000a05, 0x000a0a, 0x00050a,
+                          0x00000a, 0x05000a, 0x0a000a, 0x0a0005};
+
+void init_trees(ModeInfo * mi) {
+       unsigned long                   pixels[20];
+  treestruct       *tree;
+  Display          *display = MI_DISPLAY(mi);
+  GC                gc = MI_GC(mi);
+  int               i;
+
+  if (trees == NULL) {
+    trees = (treestruct *) calloc(MI_NUM_SCREENS(mi), sizeof (treestruct));
+    if (trees == NULL) {
+      return;
+    }
+               
+    if (mi->npixels > 20) {
+                       printf("%d colors selected. Setting limit to 20...\n", mi->npixels);
+                       mi->npixels = 20;
+               }
+                       
+               if (mi->npixels < 4) {
+      for (i = 0; i < mi->npixels; i++) {
+        colors[i].red   = 65535 * (i & 1);
+        colors[i].green = 65535 * (i & 1);
+        colors[i].blue  = 65535 * (i & 1);
+        colors[i].flags = DoRed | DoGreen | DoBlue;
+      }
+    } else {
+      if (mi->npixels < 8) {
+        for (i = 0; i < mi->npixels; i++) {
+          colors[i].red   = 32768 + 4096 * (i % 4);
+          colors[i].green = 32768 + 4096 * (i % 4);
+          colors[i].blue  = 32768 + 4096 * (i % 4);
+          colors[i].flags = DoRed | DoGreen | DoBlue;
+        }
+      } else {
+        for (i = 0; i < mi->npixels; i++) {
+          colors[i].red   = 24576 + 4096 * (i % 4);
+          colors[i].green = 10240 + 2048 * (i % 4);
+          colors[i].blue  =  0;
+          colors[i].flags = DoRed | DoGreen | DoBlue;
+        }
+      }
+    }
+
+    for (i = 0; i < mi->npixels; i++)
+      if (!XAllocColor(display, mi->xgwa.colormap, &colors[i])) break;
+    color = i;
+
+    XSetForeground(display, gc, colors[1].pixel);
+  }
+
+  XClearWindow(display, MI_WINDOW(mi));
+  XSetLineAttributes(display, gc, 2, LineSolid, CapButt, JoinMiter);
+  tree = &trees[MI_SCREEN(mi)];
+  tree->toDo   = 25;
+       tree->season = NRAND(12);
+
+  for (i = 4; i < mi->npixels; i++) {
+    int sIndex = (tree->season + (i-4) / 4) % 12;
+    long color = colorM[sIndex] - 2 * colorV[sIndex] * (i % 4);
+    colors[i].red = (color & 0xff0000) / 256;
+    colors[i].green = (color & 0x00ff00);
+    colors[i].blue = (color & 0x0000ff) * 256;
+    colors[i].flags = DoRed | DoGreen | DoBlue;
+  }
+
+       for (i = 0; i < color; i++)
+               pixels[i] = colors[i].pixel;
+                       
+  XFreeColors(display, mi->xgwa.colormap, pixels, mi->npixels, 0L);
+
+       for (i = 0; i < mi->npixels; i++)
+    if (!XAllocColor(display, mi->xgwa.colormap, &colors[i])) break;
+
+  color = i;
 }
 
-void
-init_forest(ModeInfo * mi)
-{
-       foreststruct *fp;
-
-       if (forests == NULL) {
-               if ((forests = (foreststruct *) calloc(MI_NUM_SCREENS(mi),
-                                            sizeof (foreststruct))) == NULL)
-                       return;
-       }
-       fp = &forests[MI_SCREEN(mi)];
-
-       fp->width = MI_WIN_WIDTH(mi);
-       fp->height = MI_WIN_HEIGHT(mi);
-       fp->time = 0;
-
-       fp->ntrees = MI_BATCHCOUNT(mi);
-       if (fp->ntrees < -MINTREES)
-               fp->ntrees = NRAND(-fp->ntrees - MINTREES + 1) + MINTREES;
-       else if (fp->ntrees < MINTREES)
-               fp->ntrees = MINTREES;
-       XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi));
+double rRand(double a, double b) {
+  return (a+(b-a)*NRAND(10001)/10000.0);
 }
 
-void
-draw_forest(ModeInfo * mi)
-{
-       Display    *display = MI_DISPLAY(mi);
-       GC          gc = MI_GC(mi);
-       foreststruct *fp = &forests[MI_SCREEN(mi)];
-       short       x, y, x_2, y_2, len, c = 0;
-       float       a, as;
-
-       if (fp->time < fp->ntrees) {
-
-               x = RANGE_RAND(0, fp->width);
-               y = RANGE_RAND(0, fp->height + MAXHEIGHT);
-               a = -M_PI / 2.0 + DEGTORAD(NRAND(2 * RANDANGLE) - RANDANGLE);
-               as = DEGTORAD(RANGE_RAND(MINANGLE, MAXANGLE));
-               len = ((RANGE_RAND(MINHEIGHT, MAXHEIGHT) * (fp->width / 20)) / 50) + 2;
-
-               if (MI_NPIXELS(mi) > 2) {
-                       c = NRAND(MI_NPIXELS(mi));
-                       XSetForeground(display, gc, MI_PIXEL(mi, c));
-                       c = (c + COLORSPEED) % MI_NPIXELS(mi);
-               } else
-                       XSetForeground(display, gc, MI_WIN_WHITE_PIXEL(mi));
-
-               x_2 = x + (short) (COSF(a) * ((float) len));
-               y_2 = y + (short) (SINF(a) * ((float) len));
-
-               XDrawLine(display, MI_WINDOW(mi), gc, x, y, x_2, y_2);
-               XDrawLine(display, MI_WINDOW(mi), gc, x + 1, y, x_2 + 1, y_2);
-
-               draw_tree(mi, x_2, y_2, (len * REDUCE) / 100, a, as, c, 1);
-       }
-       if (++fp->time > MI_CYCLES(mi)) {
-#ifdef STANDALONE
-         erase_full_window(MI_DISPLAY(mi), MI_WINDOW(mi));
-#endif /* STANDALONE */
-         init_forest(mi);
-       }
+void draw_line(ModeInfo * mi,
+               int x1, int y1, int x2, int y2,
+               double angle, int widths, int widthe) {
+
+  Display    *display = MI_DISPLAY(mi);
+  GC          gc = MI_GC(mi);
+  double      sns = 0.5*widths*sin(angle + M_PI_2);
+  double      css = 0.5*widths*cos(angle + M_PI_2);
+  double      sne = 0.5*widthe*sin(angle + M_PI_2);
+  double      cse = 0.5*widthe*cos(angle + M_PI_2);
+
+  int         xs1 = (int) (x1-sns);
+  int         xs2 = (int) (x1+sns);
+  int         ys1 = (int) (y1-css);
+  int         ys2 = (int) (y1+css);
+  int         xe1 = (int) (x2-sne);
+  int         xe2 = (int) (x2+sne);
+  int         ye1 = (int) (y2-cse);
+  int         ye2 = (int) (y2+cse);
+  int         i;
+
+  for (i = 0; i < widths; i++) {
+    if (color >= 4)
+      XSetForeground(display, gc, colors[i*4/widths].pixel);
+    XDrawLine(display, MI_WINDOW(mi), gc,
+      xs1+(xs2-xs1)*i/widths, ys1+(ys2-ys1)*i/widths,
+      xe1+(xe2-xe1)*i/widths, ye1+(ye2-ye1)*i/widths);
+  }
 }
 
-void
-release_forest(ModeInfo * mi)
-{
-       if (forests != NULL) {
-               (void) free((void *) forests);
-               forests = NULL;
-       }
+void draw_tree_rec(ModeInfo * mi, double thick, int x, int y, double angle) {
+  treestruct *tree = &trees[MI_SCREEN(mi)];
+  Display    *display = MI_DISPLAY(mi);
+  GC          gc = MI_GC(mi);
+  int         length = (24+NRAND(12))*tree->size;
+  int         a = (int) (x - length*sin(angle));
+  int         b = (int) (y - length*cos(angle));
+  int         i;
+
+  draw_line(mi, x, y, a, b, angle, thick*tree->size, 0.68*thick*tree->size);
+
+  if (thick > 2) {
+    draw_tree_rec(mi, 0.68*thick, a, b, 0.8*angle+rRand(-0.2, 0.2));
+    if (thick < tree->thick-1) {
+      draw_tree_rec(mi, 0.68*thick, a, b, angle+rRand(0.2, 0.9));
+      draw_tree_rec(mi, 0.68*thick, (a+x)/2, (b+y)/2, angle-rRand(0.2, 0.9));
+    }
+  }
+
+  if (thick < 0.5*tree->thick) {
+       int     nleaf = 12 + NRAND(4);
+         XArc    leaf[16];
+    for (i = 0; i < nleaf; i++) {
+      leaf[i].x = a + (int) (tree->size * rRand(-12, 12));
+      leaf[i].y = b + (int) (tree->size * rRand(-12, 12));
+      leaf[i].width = (int) (tree->size * rRand(2, 6));
+      leaf[i].height = leaf[i].width;
+      leaf[i].angle1 = 0;
+      leaf[i].angle2 = 360 * 64;
+    }
+    if (mi->npixels >= 4)
+      XSetForeground(display, gc, colors[tree->color+NRAND(4)].pixel);
+    XFillArcs(display, MI_WINDOW(mi), gc, leaf, nleaf);
+  }
 }
 
-void
-refresh_forest(ModeInfo * mi)
-{
-       foreststruct *fp = &forests[MI_SCREEN(mi)];
+void draw_trees(ModeInfo * mi) {
+  treestruct *tree = &trees[MI_SCREEN(mi)];
+       int                                     width = MI_WIN_WIDTH(mi);
+       int                                     height = MI_WIN_HEIGHT(mi);
+
+  if (--(tree->toDo) == 0) {
+    usleep(3000000);
+    init_trees(mi);
+  }
+
+  tree->x        = NRAND(width);
+  tree->y        = (int) (1.25 * height * (1 - tree->toDo / 23.0));
+  tree->thick    = rRand(7, 12);
+  tree->size     = height / 480.0;
+  if (color < 8) {
+    tree->color = 0;
+  } else {
+    tree->color    = 4 * (1 + NRAND(color / 4 - 1));
+  }
+
+  draw_tree_rec(mi, tree->thick, tree->x, tree->y, rRand(-0.1, 0.1));
+}
 
-       if (fp->time < fp->ntrees)
-               XClearWindow(MI_DISPLAY(mi), MI_WINDOW(mi));
-       else
-               init_forest(mi);
+void release_trees(ModeInfo * mi) {
+  if (trees != NULL) {
+    (void) free((void *) trees);
+    trees = NULL;
+  }
 }
index b75ff03e3eae35587c2fd8fe131ce1dd4a163681..ed44d8c2a3cfa213ec20e783a94aeb0adcac0705 100644 (file)
@@ -27,14 +27,14 @@ static const char sccsid[] = "@(#)galaxy.c  4.04 97/07/28 xlockmore";
  * 10-May-97: jwz@jwz.org: turned into a standalone program.
  * 18-Apr-97: Memory leak fixed by Tom Schmidt <tschmidt@micron.com>
  * 07-Apr-97: Modified by Dave Mitchell <davem@magnet.com>
- * 23-Oct-94: Modified by David Bagley <bagleyd@bigfoot.com>
- *             random star sizes
- *             colors change depending on velocity
+ *            random star sizes
+ *            colors change depending on velocity
+ * 23-Oct-94: Modified by David Bagley <bagleyd@tux.org>
  * 10-Oct-94: Add colors by Hubert Feyer
  * 30-Sep-94: Initial port by Hubert Feyer
  * 09-Mar-94: VMS can generate a random number 0.0 which results in a
  *            division by zero, corrected by Jouk Jansen
- *            <joukj@crys.chem.uva.nl>
+ *            <joukj@hrem.stm.tudelft.nl>
  */
 
 #ifdef STANDALONE
index aa7904562159210b7b65c49e8f8e9e399c974457..31852987bcd1239c538ee2fd50a5ec6bf23cc6ab 100644 (file)
@@ -596,7 +596,7 @@ ComputeGround(sp_instance * si)
 }
 
 void
-DisplaySproingies(int screen)
+DisplaySproingies(int screen,int pause)
 {
        sp_instance *si = &si_list[screen];
        int         t;
@@ -651,10 +651,11 @@ DisplaySproingies(int screen)
 }
 
 void
-NextSproingieDisplay(int screen)
+NextSproingieDisplay(int screen,int pause)
 {
        NextSproingie(screen);
-       DisplaySproingies(screen);
+        if (pause) usleep(pause);
+       DisplaySproingies(screen,pause);
 }
 
 #if 0
index dff236b08cef160a6b87e0718d133d429b0e5246..8ca7c9f8a2af210d3e7b054825abc6e7efcb7f46 100644 (file)
@@ -58,7 +58,7 @@ static const char sccsid[] = "@(#)sproingiewrap.c     4.07 97/11/24 xlockmore";
 # define HACK_INIT                                     init_sproingies
 # define HACK_DRAW                                     draw_sproingies
 # define sproingies_opts                       xlockmore_opts
-# define DEFAULTS      "*delay:                100     \n"                     \
+# define DEFAULTS      "*delay:                0     \n"                       \
                                        "*count:                5       \n"                     \
                                        "*cycles:               0       \n"                     \
                                        "*size:                 0       \n"                     \
@@ -88,8 +88,8 @@ ModStruct   sproingies_description =
 #include <time.h>
 
 void        NextSproingie(int screen);
-void        NextSproingieDisplay(int screen);
-void        DisplaySproingies(int screen);
+void        NextSproingieDisplay(int screen,int pause);
+void        DisplaySproingies(int screen,int pause);
 
 #if 0
 void        ReshapeSproingies(int w, int h);
@@ -181,7 +181,7 @@ init_sproingies(ModeInfo * mi)
 
                swap_display = display;
                swap_window = window;
-               DisplaySproingies(MI_SCREEN(mi));
+               DisplaySproingies(MI_SCREEN(mi),mi->pause);
        } else {
                MI_CLEARWINDOW(mi);
        }
@@ -204,7 +204,7 @@ draw_sproingies(ModeInfo * mi)
        swap_display = display;
        swap_window = window;
 
-       NextSproingieDisplay(MI_SCREEN(mi));    /* It will swap. */
+       NextSproingieDisplay(MI_SCREEN(mi),mi->pause);  /* It will swap. */
 }
 
 void
index 11099d26bcb58ced25ff3b344f8f44ba9705ae95..1d6bee2b00bb8cf413a1d518dc764df3689b5c3e 100644 (file)
@@ -1,46 +1,66 @@
-
-/**************************************************************************
- *
- *  FILE            lmorph.c
- *  MODULE OF       xscreensaver
- *
- *  DESCRIPTION     Bilinear interpolation for morphing line shapes.
- *
- *  WRITTEN BY      Sverre H. Huseby                Glenn T. Lines
- *                  Kurvn. 30                       Ã˜stgaardsgt. 5
- *                  N-0495 Oslo                     N-0474 Oslo
- *                  Norway                          Norway
- *
- *                  Phone:  +47 901 63 579          Phone:  +47 22 04 67 28
- *                  E-mail: sverrehu@online.no      E-mail: gtl@si.sintef.no
- *                  URL:    http://home.sol.no/~sverrehu/
- *
- *                  The original idea, and the bilinear interpolation
- *                  mathematics used, emerged in the head of the wise
- *                  Glenn T. Lines.
- *
- *  MODIFICATIONS   june 1998 (shh)
- *                    * Minor code cleanup.
- *
- *                  march 1997 (shh)
- *                    * Added -mailfile option to allow checking for
- *                      new mail while the screensaver is active.
- *
- *                  january 1997 (shh)
- *                    * Some code reformatting.
- *                    * Added possibility to use float arithmetic.
- *                    * Added -figtype option.
- *                    * Made color blue default.
+/* lmorph, Copyright (c) 1993-1999 Sverre H. Huseby and Glenn T. Lines
  *
- *                  december 1995 (jwz)
- *                    * Function headers converted from ANSI to K&R.
- *                    * Added posibility for random number of steps, and
- *                      made this the default.
- *
- *                  march 1995 (shh)
- *                    * Converted from an MS-Windows program to X Window.
- *
- **************************************************************************/
+ * 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.
+ */
+
+/*------------------------------------------------------------------------
+ |
+ |  FILE            lmorph.c
+ |  MODULE OF       xscreensaver
+ |
+ |  DESCRIPTION     Smooth and non-linear morphing between 1D curves.
+ |
+ |  WRITTEN BY      Sverre H. Huseby                Glenn T. Lines
+ |                  Kurvn. 30                       Ã˜stgaardsgt. 5
+ |                  N-0495 Oslo                     N-0474 Oslo
+ |                  Norway                          Norway
+ |
+ |                  Phone:  +47 901 63 579          Phone:  +47 22 04 67 28
+ |                  E-mail: sverrehu@online.no      E-mail: glennli@ifi.uio.no
+ |                  URL:    http://home.sol.no/~sverrehu/
+ |
+ |                  The original idea, and the bilinear interpolation
+ |                  mathematics used, emerged in the head of the wise
+ |                  Glenn T. Lines.
+ |
+ |  MODIFICATIONS   october 1999 (shh)
+ |                    * Removed option to use integer arithmetic.
+ |                    * Increased default number of points, and brightened
+ |                      the foreground color a little bit.
+ |                    * Minor code cleanup (very minor, that is).
+ |                    * Default number of steps is no longer random.
+ |                    * Added -linewidth option (and resource).
+ |
+ |                  october 1999 (gtl)
+ |                   * Added cubic interpolation between shapes 
+ |                   * Added non-linear transformation speed  
+ |
+ |                  june 1998 (shh)
+ |                    * Minor code cleanup.
+ |
+ |                  january 1997 (shh)
+ |                    * Some code reformatting.
+ |                    * Added possibility to use float arithmetic.
+ |                    * Added -figtype option.
+ |                    * Made color blue default.
+ |
+ |                  december 1995 (jwz)
+ |                    * Function headers converted from ANSI to K&R.
+ |                    * Added posibility for random number of steps, and
+ |                      made this the default.
+ |
+ |                  march 1995 (shh)
+ |                    * Converted from an MS-Windows program to X Window.
+ |
+ |                  november 1993 (gtl, shh, lots of beer)
+ |                    * Original Windows version (we didn't know better).
+ +----------------------------------------------------------------------*/
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 #include "screenhack.h"
 
-/**************************************************************************
- *                                                                        *
- *                       P R I V A T E    D A T A                         *
- *                                                                        *
- **************************************************************************/
+/*-----------------------------------------------------------------------+
+|  PRIVATE DATA                                                          |
++-----------------------------------------------------------------------*/
 
 /* define MARGINS to make some space around the figure. */
 #define MARGINS
 
-/* define USE_FLOAT to avoid using integer calculations in
-   createPoints. integer calculation is supposed to be faster, but it
-   won't work for displays larger than 2048x2048 or so pixels. */
-#undef USE_FLOAT
-
 #define MAXFIGS    20
 #define TWO_PI     (2.0 * M_PI)
 #define RND(x)     (random() % (x))
@@ -76,6 +89,8 @@ static int
     nWork,                      /* current work array number. */
     nFrom,                      /* current from array number. */
     nTo,                        /* current to array number. */
+    nNext,                      /* current next array number (after to).*/
+    shift,                      /* shifts the starting point of a figure */
     figType;
 static long delay;              /* usecs to wait between updates. */
 static XPoint
@@ -85,49 +100,46 @@ static XPoint
     *aPrev,                     /* previous points displayed. */
     *aCurr,                     /* the current points displayed. */  
     *aFrom,                     /* figure converting from. */
-    *aTo;                       /* figure converting to. */
+    *aTo,                       /* figure converting to. */
+    *aNext,                     /* figure converting to next time. */
+    *aSlopeFrom,                /* slope at start of morph */ 
+    *aSlopeTo;                  /* slope at end of morph */ 
 static int         scrWidth, scrHeight;
 static double      currGamma, maxGamma = 1.0, deltaGamma;
 static GC          gcDraw, gcClear;
 static Display     *dpy;
 static Window      window;
 
-
-
-/**************************************************************************
- *                                                                        *
- *                        P U B L I C    D A T A                          *
- *                                                                        *
- **************************************************************************/
+/*-----------------------------------------------------------------------+
+|  PUBLIC DATA                                                           |
++-----------------------------------------------------------------------*/
 
 char *progclass = "LMorph";
 
 char *defaults [] = {
     ".background: black",
-    ".foreground: blue",
-    "*points: 150",
-    "*steps: 0",
-    "*delay: 50000",
+    ".foreground: #4444FF",
+    "*points: 200",
+    "*steps: 150",
+    "*delay: 70000",
     "*figtype: all",
+    "*linewidth: 5",
     0
 };
 
 XrmOptionDescRec options [] = {
-  { "-points",      ".points",      XrmoptionSepArg, 0 },
-  { "-steps",       ".steps",       XrmoptionSepArg, 0 },
-  { "-delay",       ".delay",       XrmoptionSepArg, 0 },
-  { "-figtype",     ".figtype",     XrmoptionSepArg, 0 },
-  { 0, 0, 0, 0 }
+    { "-points",      ".points",      XrmoptionSepArg, 0 },
+    { "-steps",       ".steps",       XrmoptionSepArg, 0 },
+    { "-delay",       ".delay",       XrmoptionSepArg, 0 },
+    { "-figtype",     ".figtype",     XrmoptionSepArg, 0 },
+    { "-linewidth",   ".linewidth",   XrmoptionSepArg, 0 },
+    { 0, 0, 0, 0 }
 };
 int options_size = (sizeof (options) / sizeof (options[0]));
 
-
-
-/**************************************************************************
- *                                                                        *
- *                   P R I V A T E    F U N C T I O N S                   *
- *                                                                        *
- **************************************************************************/
+/*-----------------------------------------------------------------------+
+|  PRIVATE FUNCTIONS                                                     |
++-----------------------------------------------------------------------*/
 
 static void *
 xmalloc(size_t size)
@@ -144,11 +156,11 @@ xmalloc(size_t size)
 static void
 initPointArrays(void)
 {
-    int q, w,
-        mx, my,                 /* max screen coordinates. */
-        mp,                     /* max point number. */
-        s, rx, ry,
-        marginx, marginy;
+    int    q, w;
+    int    mx, my;            /* max screen coordinates. */
+    int    mp;                /* max point number. */
+    int    s, rx, ry;
+    int    marginx, marginy;
     double scalex, scaley;
 
     mx = scrWidth - 1;
@@ -219,7 +231,8 @@ initPointArrays(void)
        a[numFigs][mp].y = a[numFigs][0].y;
        ++numFigs;
 
-       /*  */
+
+       /* */
        a[numFigs] = (XPoint *) xmalloc(numPoints * sizeof(XPoint));
        rx = mx / 2;
        ry = my / 2;
@@ -231,6 +244,7 @@ initPointArrays(void)
        a[numFigs][mp].y = a[numFigs][0].y;
        ++numFigs;
 
+
        /*  */
        a[numFigs] = (XPoint *) xmalloc(numPoints * sizeof(XPoint));
        rx = mx / 2;
@@ -331,7 +345,8 @@ initLMorph(void)
     XWindowAttributes wa;
     Colormap          cmap;
     char              *ft;
-    
+    int               i;
+
     numPoints = get_integer_resource("points", "Integer");
     steps = get_integer_resource("steps", "Integer");
     delay = get_integer_resource("delay", "Integer");
@@ -369,15 +384,29 @@ initLMorph(void)
     aPrev = NULL;
     currGamma = maxGamma + 1.0;  /* force creation of new figure at startup */
     nTo = RND(numFigs);
+    do {
+        nNext = RND(numFigs);
+    } while (nNext == nTo);
+
+    aSlopeTo = (XPoint *) xmalloc(numPoints * sizeof(XPoint)); 
+    aSlopeFrom = (XPoint *) xmalloc(numPoints * sizeof(XPoint)); 
+    aNext = (XPoint *) xmalloc(numPoints * sizeof(XPoint)); 
+
+    for (i = 0; i < numPoints ; i++) {
+        aSlopeTo[i].x = 0.0;
+        aSlopeTo[i].y = 0.0; 
+    }
 
-    { /* jwz for version 2.11 */
-      int width = random() % 10;
-      int style = LineSolid;
-      int cap   = (width > 1 ? CapRound  : CapButt);
-      int join  = (width > 1 ? JoinRound : JoinBevel);
-      if (width == 1) width = 0;
-      XSetLineAttributes(dpy, gcDraw,  width, style, cap, join);
-      XSetLineAttributes(dpy, gcClear, width, style, cap, join);
+    {   /* jwz for version 2.11 */
+        /*      int width = random() % 10;*/
+        int width = get_integer_resource("linewidth", "Integer");
+        int style = LineSolid;
+        int cap   = (width > 1 ? CapRound  : CapButt);
+        int join  = (width > 1 ? JoinRound : JoinBevel);
+        if (width == 1)
+            width = 0;
+        XSetLineAttributes(dpy, gcDraw,  width, style, cap, join);
+        XSetLineAttributes(dpy, gcClear, width, style, cap, join);
     }
 }
 
@@ -385,32 +414,33 @@ initLMorph(void)
 static void
 createPoints(void)
 {
-    int             q;
+    int    q;
     XPoint *pa = aCurr, *pa1 = aFrom, *pa2 = aTo;
-#ifdef USE_FLOAT
-    float           fg, f1g;
-#else
-    long            lg, l1g;
-#endif
+    XPoint *qa1 = aSlopeFrom, *qa2 = aSlopeTo; 
+    float  fg, f1g;
+    float  speed;
 
-#ifdef USE_FLOAT
     fg  = currGamma;
     f1g = 1.0 - currGamma;
-#else
-    lg  = 8192L * currGamma;
-    l1g = 8192L * (1.0 - currGamma);
-#endif
     for (q = numPoints; q; q--) {
-#ifdef USE_FLOAT
-        pa->x = (short) (f1g * pa1->x + fg * pa2->x);
-        pa->y = (short) (f1g * pa1->y + fg * pa2->y);
-#else
-        pa->x = (short) ((l1g * pa1->x + lg * pa2->x) / 8192L);
-        pa->y = (short) ((l1g * pa1->y + lg * pa2->y) / 8192L);
-#endif
+        speed = 0.45 * sin(TWO_PI * (double) (q + shift) / (numPoints - 1));
+        fg = currGamma + 1.67 * speed
+            * exp(-200.0 * (currGamma - 0.5 + 0.7 * speed)
+                  * (currGamma - 0.5 + 0.7 * speed));
+
+        f1g = 1.0 - fg;
+        pa->x = (short) (f1g * f1g * f1g * pa1->x + f1g * f1g * fg
+                         * (3 * pa1->x + qa1->x) + f1g * fg * fg
+                         * (3 * pa2->x - qa2->x) + fg * fg * fg * pa2->x);
+        pa->y = (short) (f1g * f1g * f1g * pa1->y + f1g * f1g * fg
+                         * (3 * pa1->y + qa1->y) + f1g * fg * fg
+                         * (3 * pa2->y - qa2->y) + fg * fg * fg * pa2->y);
+
         ++pa;
         ++pa1;
         ++pa2;
+       ++qa1;
+       ++qa2;
     }
 }
 
@@ -418,13 +448,13 @@ createPoints(void)
 static void
 drawImage(void)
 {
-    int             q;
+    int    q;
     XPoint *old0, *old1, *new0, *new1;
 
     /* Problem: update the window without too much flickering. I do
      * this by handling each linesegment separately. First remove a
      * line, then draw the new line. The problem is that this leaves
-     * small black pixels on the figure. To fix this, I draw the
+     * small black pixels on the figure. To fix this, we draw the
      * entire figure using XDrawLines() afterwards. */
     if (aPrev) {
        old0 = aPrev;
@@ -432,8 +462,8 @@ drawImage(void)
        new0 = aCurr;
        new1 = aCurr + 1;
        for (q = numPoints - 1; q; q--) {
-           XDrawLine(dpy, window, gcClear,
-                     old0->x, old0->y, old1->x, old1->y);
+          XDrawLine(dpy, window, gcClear,
+            old0->x, old0->y, old1->x, old1->y); 
            XDrawLine(dpy, window, gcDraw,
                      new0->x, new0->y, new1->x, new1->y);
            ++old0;
@@ -451,36 +481,38 @@ drawImage(void)
 static void
 animateLMorph(void)
 {
+    int i;
     if (currGamma > maxGamma) {
         currGamma = 0.0;
-        if (maxGamma == 1.0) {
-            nFrom = nTo;
-            aFrom = a[nFrom];
-        } else {
-            memcpy(aTmp, aCurr, numPoints * sizeof(XPoint));
-            aFrom = aTmp;
-            nFrom = -1;
-        }
+        nFrom = nTo;
+        nTo = nNext;
+        aFrom = a[nFrom];
+       aTo = a[nTo];
         do {
-            nTo = RND(numFigs);
-        } while (nTo == nFrom);
-        aTo = a[nTo];
+            nNext = RND(numFigs);
+        } while (nNext == nTo);
+       aNext = a[nNext];
+
+       shift = RND(numPoints);
         if (RND(2)) {
             /* reverse the array to get more variation. */
             int    i1, i2;
             XPoint p;
             
             for (i1 = 0, i2 = numPoints - 1; i1 < numPoints / 2; i1++, i2--) {
-                p = aTo[i1];
-                aTo[i1] = aTo[i2];
-                aTo[i2] = p;
+                p = aNext[i1];
+                aNext[i1] = aNext[i2];
+                aNext[i2] = p;
             }
         }
-        /* occationally interrupt the next run. */
-        if (RND(4) == 0)
-            maxGamma = 0.1 + 0.7 * (RND(1001) / 1000.0); /* partial run */
-        else
-            maxGamma = 1.0;                              /* full run */
+
+       /* calculate the slopes */
+       for (i = 0; i < numPoints ; i++) {
+            aSlopeFrom[i].x = aSlopeTo[i].x;
+            aSlopeFrom[i].y = aSlopeTo[i].y;
+            aSlopeTo[i].x = aNext[i].x - aTo[i].x;
+            aSlopeTo[i].y = (aNext[i].y - aTo[i].y);
+       }
     }
 
     createPoints();
@@ -491,13 +523,9 @@ animateLMorph(void)
     currGamma += deltaGamma;
 }
 
-
-
-/**************************************************************************
- *                                                                        *
- *                    P U B L I C    F U N C T I O N S                    *
- *                                                                        *
- **************************************************************************/
+/*-----------------------------------------------------------------------+
+|  PUBLIC FUNCTIONS                                                      |
++-----------------------------------------------------------------------*/
 
 void
 screenhack(Display *disp, Window win)
@@ -506,8 +534,9 @@ screenhack(Display *disp, Window win)
     window = win;
     initLMorph();
     for (;;) {
-       animateLMorph();
+       animateLMorph();
         screenhack_handle_events (dpy);
        usleep(delay);
-    }
+       }
+
 }
index 50cf8d21976322965947952e93dd0b5cd537f907..6b488f35a346ab775954472452a209421d508220 100644 (file)
@@ -5,8 +5,8 @@ lmorph \- morphing lines
 .B lmorph
 [\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-points \fIint\fP] [\-steps \fIint\fP] [\-delay \fIusecs\fP] [\-figtype \fItype\fP]
 .SH DESCRIPTION
-The \fIlmorph\fP program morphs between simple linedrawings using bilinear
-interpolation.
+The \fIlmorph\fP program shows smooth and non-linear morphing between
+1D curves.
 .SH OPTIONS
 .I lmorph
 accepts the following options:
@@ -28,19 +28,22 @@ 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 \-points \fIinteger\fP
-Number of points in each line drawing. Default is 150 points.
+Number of points in each line drawing. Default is 200 points.
 .TP 8
 .B \-steps \fIinteger\fP
-Interpolation steps from one drawing to the next. Default is 0, which
-means a random number between 100 and 500.
+Interpolation steps from one drawing to the next. Default is 150. You
+may specify 0, to get a random number between 100 and 500.
 .TP 8
 .B \-delay \fImicroseconds\fP
 How much of a delay should be introduced between steps of the animation.
-Default 50000.
+Default 70000.
 .TP 8
 .B \-figtype \fItype\fP
 Limit the figures to only open or closed figures. Possible types are
 "all" (default), "open" and "closed".
+.TP 8
+.B \-linewidth \fIinteger\fP
+Width of lines. Default is 5 pixels.
 .SH ENVIRONMENT
 .PP
 .TP 8
@@ -54,5 +57,5 @@ stored in the RESOURCE_MANAGER property.
 .BR X (1),
 .BR xscreensaver (1)
 .SH AUTHOR
-Sverre H. Huseby <sverrehu@online.no> and Glenn T. Lines <gtl@si.sintef.no>,
+Sverre H. Huseby <sverrehu@online.no> and Glenn T. Lines <glennli@ifi.uio.no>,
 built on top of the screen saver routines by Jamie Zawinski <jwz@jwz.org>.
index 8a882fcd7b4ddd41426d673f79d387822241abc2..5a70760d53d81e99ae3e3bf71b21a9d0ba9f190d 100644 (file)
@@ -299,6 +299,10 @@ main (int argc, char **argv)
   dpy = XtDisplay (toplevel);
   db = XtDatabase (dpy);
   XtGetApplicationNameAndClass (dpy, &progname, &progclass);
+
+  /* half-assed way of avoiding buffer-overrun attacks. */
+  if (strlen (progname) >= 100) progname[100] = 0;
+
   XSetErrorHandler (screenhack_ehandler);
 
   XA_WM_PROTOCOLS = XInternAtom (dpy, "WM_PROTOCOLS", False);
index 34965dfc465303ffdec3764ef6c43d7d3d6b332e..cca0654ead0ecabf12411b96c779506b01852c9a 100644 (file)
@@ -28,6 +28,9 @@
  *                on cycle, and the extents of the sinus pattern change in
  *                real-time.
  * [06/22/99] - Shane Smit: Fixed delay to be fast and use little CPU :).
+ * [09/17/99] - Shane Smit: Made all calculations based on the size of the
+ *                window. Thus, it'll look the same at 100x100 as it does at
+ *                1600x1200 ( Only smaller :).
  */
 
 #include <math.h>
 char *progclass = "ShadeBobs";
 
 char *defaults [] = {
-  "*degrees:  512",
+  "*degrees:  0",      /* default: Automatic degree calculation */
   "*color:    random",
-  "*count:    2",
-  "*cycles:   50",
+  "*count:    4",
+  "*cycles:   10",
   "*ncolors:  64",    /* changing this doesn't work particularly well */
   "*delay:    5000",
   0
@@ -63,6 +66,8 @@ static unsigned short nMaxExtentX, nMaxExtentY;
 static unsigned short nMinExtentX, nMinExtentY;
 static unsigned short nHalfWidth, nHalfHeight;
 static char *sColor;
+static unsigned char nBobRadius, nBobDiameter; 
+static float nExtentDelta; 
 
 #define RANDOM() ((int) (random() & 0X7FFFFFFFL))
 
@@ -70,14 +75,12 @@ static char *sColor;
 /* Ahem. Chocolate is a flavor; not a food. Thank you */
 
 
-#define MAPSIZE 32
-
 typedef struct
 {
-  char anDeltaMap[ MAPSIZE * MAPSIZE ];  /* 32 x 32 Delta Map */
+  char *anDeltaMap;
   double nVelocityX, nVelocityY;
   double nAngleX, nAngleY;
-  short nExtentX, nExtentY;
+  float nExtentX, nExtentY;
 } SShadeBob;
 
 
@@ -96,17 +99,23 @@ static void InitShadeBob( SShadeBob *pShadeBob, Bool bDark )
   double nDelta;
   char iWidth, iHeight;
 
-  for( iHeight=-16; iHeight<16; iHeight++ )
-    for( iWidth=-16; iWidth<16; iWidth++ )
+  if( ( pShadeBob->anDeltaMap = calloc( nBobDiameter * nBobDiameter, sizeof(char) ) ) == NULL )
+  {
+    fprintf( stderr, "Could not allocate Delta Map!\n" );
+    return;
+  }
+
+  for( iHeight=-nBobRadius; iHeight<nBobRadius; iHeight++ )
+    for( iWidth=-nBobRadius; iWidth<nBobRadius; iWidth++ )
     {
-      nDelta = 9 - (sqrt( pow( iWidth+0.5, 2 ) + pow( iHeight+0.5, 2 ) ) / 2 );
+      nDelta = 9 - ( ( sqrt( pow( iWidth+0.5, 2 ) + pow( iHeight+0.5, 2 ) ) / nBobRadius ) * 8 );
       if( nDelta < 0 )  nDelta = 0;
       if( bDark ) nDelta = -nDelta;
-      pShadeBob->anDeltaMap[ (iWidth+(MAPSIZE/2))*MAPSIZE
-                           + iHeight+(MAPSIZE/2) ] = (char)nDelta;
+      pShadeBob->anDeltaMap[ ( iWidth + nBobRadius ) * nBobDiameter
+                           + iHeight + nBobRadius ] = (char)nDelta;
     }
-
-       ResetShadeBob( pShadeBob );
+  
+  ResetShadeBob( pShadeBob );
 }
 
 
@@ -131,15 +140,13 @@ static void Execute( SShadeBob *pShadeBob, Display *pDisplay,
   pShadeBob->nAngleX += pShadeBob->nVelocityX;
   pShadeBob->nAngleY += pShadeBob->nVelocityY;
 
-  if(      pShadeBob->nAngleX >= nDegreeCount ) pShadeBob->nAngleX -= nDegreeCount;
-  else if( pShadeBob->nAngleX < 0 )             pShadeBob->nAngleX += nDegreeCount;
-  if(      pShadeBob->nAngleY >= nDegreeCount ) pShadeBob->nAngleY -= nDegreeCount;
-  else if( pShadeBob->nAngleY < 0 )             pShadeBob->nAngleY += nDegreeCount;
+  if( pShadeBob->nAngleX >= nDegreeCount ) pShadeBob->nAngleX -= nDegreeCount;
+  if( pShadeBob->nAngleY >= nDegreeCount ) pShadeBob->nAngleY -= nDegreeCount;
 
-  pShadeBob->nExtentX += ( RANDOM() % 5 ) - 2;
+  pShadeBob->nExtentX += ( ( ( RANDOM() % 5 ) - 2 ) / 2.0F ) * nExtentDelta;
   if( pShadeBob->nExtentX > nMaxExtentX ) pShadeBob->nExtentX = nMaxExtentX;
   if( pShadeBob->nExtentX < nMinExtentX ) pShadeBob->nExtentX = nMinExtentX;
-  pShadeBob->nExtentY += ( RANDOM() % 5 ) - 2;
+  pShadeBob->nExtentY += ( ( ( RANDOM() % 5 ) - 2 ) / 2.0F ) * nExtentDelta;
   if( pShadeBob->nExtentY > nMaxExtentY ) pShadeBob->nExtentY = nMaxExtentY;
   if( pShadeBob->nExtentY < nMinExtentY ) pShadeBob->nExtentY = nMinExtentY;
 
@@ -149,9 +156,9 @@ static void Execute( SShadeBob *pShadeBob, Display *pDisplay,
   nYPos = (unsigned int)(( anSinTable[ (int)pShadeBob->nAngleY ] * pShadeBob->nExtentY )
                          + nHalfHeight);
 
-  for( iHeight=0; iHeight < MAPSIZE; iHeight++ )
+  for( iHeight=0; iHeight<nBobDiameter; iHeight++ )
   {
-    for( iWidth=0; iWidth < MAPSIZE; iWidth++ )
+    for( iWidth=0; iWidth<nBobDiameter; iWidth++ )
     {
       nColor = XGetPixel( pXImage, nXPos + iWidth, nYPos + iHeight );
 
@@ -160,7 +167,7 @@ static void Execute( SShadeBob *pShadeBob, Display *pDisplay,
         if( aXColors[ nIndex ].pixel == nColor )
           break;
 
-      nIndex += pShadeBob->anDeltaMap[ iWidth * MAPSIZE + iHeight ];
+      nIndex += pShadeBob->anDeltaMap[ iWidth * nBobDiameter + iHeight ];
       if( nIndex >= ncolors ) nIndex = ncolors-1;
       if( nIndex < 0 )  nIndex = 0;
 
@@ -168,9 +175,9 @@ static void Execute( SShadeBob *pShadeBob, Display *pDisplay,
                  aXColors[ nIndex ].pixel );
     }
   }
-  /* Place graphics in window */
+
   XPutImage( pDisplay, MainWindow, *pGC, pXImage,
-             nXPos, nYPos, nXPos, nYPos, MAPSIZE, MAPSIZE );
+             nXPos, nYPos, nXPos, nYPos, nBobDiameter, nBobDiameter );
   XSync (pDisplay, False);
 }
 
@@ -242,6 +249,8 @@ static void SetPalette(Display *pDisplay, Window Win, char *sColor,
                      False, True, False );
     *ncolorsP = n1 + n2;
   }
+
+  XSetWindowBackground( pDisplay, Win, aXColors[ 0 ].pixel );
 }
 
 
@@ -282,19 +291,30 @@ static void Initialize( Display *pDisplay, Window Win,
                            (*pXImage)->height);
 
   /*  These are precalculations used in Execute(). */
-  nMaxExtentX = ( XWinAttribs.width / 2 ) - 20;
-  nMaxExtentY = ( XWinAttribs.height / 2 ) - 20;
+  nBobDiameter = XWinAttribs.width / 25;
+  nBobRadius = nBobDiameter / 2;
+  nExtentDelta = nBobRadius / 5.0F;
+#ifdef VERBOSE
+  printf( "Bob Diameter = %d\n", nBobDiameter );
+#endif
+
+  nHalfWidth = ( XWinAttribs.width / 2 ) - nBobRadius;
+  nHalfHeight = ( XWinAttribs.height / 2 ) - nBobRadius;
+  nMaxExtentX = nHalfWidth - nBobRadius;
+  nMaxExtentY = nHalfHeight - nBobRadius;
   nMinExtentX = nMaxExtentX / 3;
   nMinExtentY = nMaxExtentY / 3;
-  nHalfWidth = ( XWinAttribs.width / 2 ) - 16;
-  nHalfHeight = ( XWinAttribs.height / 2 ) - 16;
-
+  
   /*  Create the Sin and Cosine lookup tables. */
   nDegreeCount = get_integer_resource( "degrees", "Integer" );
-  if( nDegreeCount < 90 ) nDegreeCount = 90;
-  if( nDegreeCount > 5400 ) nDegreeCount = 5400;
+  if(      nDegreeCount == 0   ) nDegreeCount = ( XWinAttribs.width / 6 ) + 400;
+  else if( nDegreeCount < 90   ) nDegreeCount = 90;
+  else if( nDegreeCount > 5400 ) nDegreeCount = 5400;
   CreateTables( nDegreeCount );
-
+#ifdef VERBOSE
+  printf( "Using a %d degree circle.\n", nDegreeCount );
+#endif /* VERBOSE */
+  
   /*  Get the colors. */
   sColor = get_string_resource( "color", "Color" );
   if( sColor == NULL)
@@ -337,18 +357,18 @@ void screenhack(Display *pDisplay, Window Win )
     InitShadeBob( &aShadeBobs[ iShadeBob ], iShadeBob % 2 );
 
   delay = get_integer_resource( "delay", "Integer" );
-  cycles = get_integer_resource( "cycles", "Integer" ) * (nDegreeCount / 3);
+  cycles = get_integer_resource( "cycles", "Integer" ) * nDegreeCount;
   i = cycles;
 
-  while (1)
+  while( 1 )
   {
     screenhack_handle_events( pDisplay );
 
     if (i++ >= cycles)
     {
       i = 0;
-      XClearWindow (pDisplay, Win);
-      memset (pImage->data, 0, pImage->bytes_per_line * pImage->height);
+      XClearWindow( pDisplay, Win );
+      memset( pImage->data, 0, pImage->bytes_per_line * pImage->height );
       for( iShadeBob=0; iShadeBob<nShadeBobCount; iShadeBob++ )
         ResetShadeBob( &aShadeBobs[ iShadeBob ] );
       SetPalette( pDisplay, Win, sColor, &ncolors, aXColors );
@@ -375,6 +395,8 @@ void screenhack(Display *pDisplay, Window Win )
   free( anSinTable );
   free( pImage->data );
   XDestroyImage( pImage );
+  for( iShadeBob=0; iShadeBob<nShadeBobCount; iShadeBob++ )
+    free( aShadeBobs[ iShadeBob ].anDeltaMap );
   free( aShadeBobs );
 }
 
index a27e0c2b3e1db152626be23c60f6fdf0dcca1e5e..45175a921ba88c96f36e7e753dad6d2073dcff19 100755 (executable)
@@ -12,8 +12,8 @@
 #
 #
 # This script grabs a frame of video, then uses various pbm filters to
-# munge the image in random nefarious ways, then uses xv to put it on
-# the root window.  This works out really nicely if you just feed some
+# munge the image in random nefarious ways, then uses xli or xv to put it
+# on the root window.  This works out really nicely if you just feed some
 # random TV station into it...
 #
 # The video grabbing part is SGI-specific -- if you want to use this on
@@ -42,6 +42,32 @@ tmp_ppm4=$tmp-4.ppm
 tmp_ppmS=$tmp-S.ppm
 
 
+# Figure out whether to use xli or xv.
+pick_displayer() {
+  IFS=:
+  for p in $PATH; do
+    if [ "$p" = "" ]; then p=. ; fi
+    if [ -x $p/xli ]; then
+      displayer=$p/xli
+      displayer_args="-quiet"
+      displayer_win_args=""
+      displayer_root_args="-onroot -center -border black"
+      return
+    elif [ -x $p/xv ]; then
+      displayer=$p/xv
+      displayer_args="-quick24"
+      displayer_win_args="-geom +0+0"
+      displayer_root_args="-root -rmode 5 -noresetroot -rfg black -rbg black -viewonly"
+
+      return
+    fi
+  done
+  IFS=
+
+  echo "$0: neither xli nor xv found on \$PATH"
+  exit -1
+}
+
 # Process command-line args
 getargs() {
 
@@ -83,12 +109,12 @@ getargs() {
     shift
   done
 
-  xvargs="-quick24"
+  pick_displayer
 
   if [ "$onroot" = true ]; then
-    xvargs="$xvargs -root -rmode 5 -noresetroot -rfg black -rbg black -viewonly"
+    displayer_args="$displayer_args $displayer_root_args"
   else
-    xvargs="$xvargs -geom +0+0"
+    displayer_args="$displayer_args $displayer_win_args"
   fi
 
 
@@ -300,7 +326,7 @@ whack() {
 }
 
 
-# Kill off the xv subprocess, if it's running
+# Kill off the xli or xv subprocess, if it's running
 #
 kill_pid() {
   if [ "$pid" != "" ]; then
@@ -345,11 +371,12 @@ main() {
 
     # Loop grabbing and frobbing images.
     #
-    # If we're running on the root, run xv in the foreground (with -exit)
-    # and then wait.
+    # If we're running on the root, run xv or xli in the foreground
+    # (with -exit, if xv) and then wait.
     #
-    # If we're running in a window, spawn xv in the background; then when
-    # it's time to put up the new image, kill off the currently-running xv.
+    # If we're running in a window, spawn xv or xli in the background; then
+    # when it's time to put up the new image, kill off the currently-running
+    # xv or xli.
 
     if [ "$verbose" = true ]; then
       whack
@@ -370,23 +397,24 @@ main() {
 
     else
 
-      pnmtosgi < $tmp_ppm3 > $tmp_ppm2
-      rm -f $tmp_ppm3
+#      pnmtosgi < $tmp_ppm3 > $tmp_ppm2
+#      rm -f $tmp_ppm3
+       mv $tmp_ppm3 $tmp_ppm2
 
       if [ -s $tmp_ppm2 ]; then
         if [ "$verbose" = true ]; then
-          echo "launching xv $xvargs $tmp_ppm2" >&2
+          echo "launching $displayer $displayer_args $tmp_ppm2" >&2
          ls -lF $tmp_ppm2
         fi
 
        mv $tmp_ppm2 $tmp_ppm0
-        xv $xvargs $tmp_ppm0 &
+        eval "$displayer $displayer_args $tmp_ppm0 &"
 
 # this doesn't work -- leaves xv processes around, instead of stray xset
 # data.  Sigh.
 #
 #      # cat the file so that we can nuke it without racing against xv.
-#        cat $tmp_ppm2 | xv $xvargs - &
+#        cat $tmp_ppm2 | $displayer $displayer_args - &
 
         pid=$!
       fi
index 9f767edaabb6abb61ea93d1e6b27db06312d6740..2a727006d90446729e39e1df73dfb05972e322b4 100755 (executable)
@@ -27,7 +27,7 @@ require POSIX;
 use Fcntl ':flock'; # import LOCK_* constants
 
 
-my $version = q{ $Revision: 1.32 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
+my $version = q{ $Revision: 1.36 $ }; $version =~ s/^[^0-9]+([0-9.]+).*$/$1/;
 my $copyright = "WebCollage $version, Copyright (c) 1999" .
     " Jamie Zawinski <jwz\@jwz.org>\n" .
     "            http://www.jwz.org/xscreensaver/\n";
@@ -56,6 +56,9 @@ my $image_randomizer_2 = "http://www.hotbot.com/?clickSrc=search" .
                          "&MT=";
 my $image_randomizer_3 = "http://www.altavista.com/cgi-bin/query?pg=q" .
                          "&text=yes&kl=XX&stype=stext&q=";
+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 $image_ppm   = ($ENV{TMPDIR} ? $ENV{TMPDIR} : "/tmp") . "/webcollage." . $$;
 my $image_tmp1  = $image_ppm . "-1";
@@ -67,8 +70,15 @@ my $img_height;
 my $http_proxy = undef;
 my $http_timeout = 30;
 my $cvt_timeout = 10;
-my $ppm_to_root_window_cmd = "xv -root -rmode 5 -viewonly" .
-                             " +noresetroot %%PPM%% -quit";
+
+# if we have xli, use it to write to the root window.  else use xv.
+my $ppm_to_root_window_cmd_1 = "xli -quiet -onroot -center" .
+                               " -border black %%PPM%%";
+my $ppm_to_root_window_cmd_2 = "xv -root -rmode 5 -viewonly" .
+                               " +noresetroot %%PPM%% -quit";
+
+my $ppm_to_root_window_cmd = undef;     # initialized by x_output()
+
 my $filter_cmd = undef;
 my $post_filter_cmd = undef;
 my $background = undef;
@@ -640,7 +650,7 @@ sub pick_from_image_randomizer {
         next if ($u =~ m@[/.]digital\.com@i);
         next if ($u =~ m@[/.]doubleclick\.net@i);
 
-        if ($which == 0 && $u =~ m@[/.]corbis\.com/@) {
+        if ($which == 0 && $u =~ m@[/.]corbis\.com@) {
             $skipped = 1;
             if ( $verbose > 3 ) {
                 print STDERR "$progname: skipping corbis URL: $u\n";
@@ -696,6 +706,19 @@ sub pick_from_image_randomizer {
 }
 
 
+# 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.
+# 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" );
+}
+
+
 # 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.
@@ -705,10 +728,12 @@ 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 ) = @_;
@@ -726,6 +751,11 @@ sub pick_image {
         $total = ++$total_1;
         $count = ++$count_1 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.
@@ -1006,15 +1036,25 @@ sub image_to_pnm {
 
 sub x_output {
 
-    my $win_cmd = $ppm_to_root_window_cmd;
-    $win_cmd =~ s/^([^ \t\r\n]+).*$/$1/;
+    my $win_cmd_1 = $ppm_to_root_window_cmd_1;
+    my $win_cmd_2 = $ppm_to_root_window_cmd_2;
+    $win_cmd_1 =~ s/^([^ \t\r\n]+).*$/$1/;
+    $win_cmd_2 =~ s/^([^ \t\r\n]+).*$/$1/;
 
     # make sure the various programs we execute exist, right up front.
     foreach ("ppmmake", "giftopnm", "djpeg", "pnmpaste", "pnmscale",
-             "pnmcut", $win_cmd) {
+             "pnmcut") {
         which ($_) || die "$progname: $_ not found on \$PATH.\n";
     }
 
+    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;
+    } else {
+        die "$progname: neither $win_cmd_1 nor $win_cmd_2 found on \$PATH.\n";
+    }
+
     $SIG{HUP}  = \&x_cleanup;
     $SIG{INT}  = \&x_cleanup;
     $SIG{QUIT} = \&x_cleanup;
index c32e6a5f0103cf47ca947f9f4116c777537a4f7b..9d0883c50167cdc8fff486fa0c0939bc7eeac013 100644 (file)
@@ -38,6 +38,9 @@
          behavioral constants.
 
        - General cleanup and portability tweaks.
+
+   * 4-Oct-99, jwz: added support for packed-24bpp (versus 32bpp.)
+
  */
 
 
@@ -319,6 +322,55 @@ Flame2Image32(void)
     }
 }
 
+static void
+Flame2Image24(void)
+{
+  int x,y;
+  unsigned char *ptr;
+  unsigned char *ptr1;
+  int v1,v2,v3,v4;
+
+  ptr  = (unsigned char *)xim->data;
+  ptr += (top << 1) * xim->bytes_per_line;
+  ptr1 = flame + 1 + (top * (fwidth + 2));
+
+  for( y = top; y < fheight; y++)
+    {
+      unsigned char *last_ptr = ptr;
+      for( x = 0; x < fwidth; x++)
+        {
+          v1 = (int)*ptr1;
+          v2 = (int)*(ptr1 + 1);
+          v3 = (int)*(ptr1 + fwidth + 2);
+          v4 = (int)*(ptr1 + fwidth + 2 + 1);
+          ptr1++;
+
+          ptr[2] = ((unsigned int)ctab[v1] & 0x00FF0000) >> 16;
+          ptr[1] = ((unsigned int)ctab[v1] & 0x0000FF00) >> 8;
+          ptr[0] = ((unsigned int)ctab[v1] & 0x000000FF);
+          ptr += 3;
+
+          ptr[2] = ((unsigned int)ctab[(v1 + v2) >> 1] & 0x00FF0000) >> 16;
+          ptr[1] = ((unsigned int)ctab[(v1 + v2) >> 1] & 0x0000FF00) >> 8;
+          ptr[0] = ((unsigned int)ctab[(v1 + v2) >> 1] & 0x000000FF);
+          ptr += ((width - 1) * 3);
+
+          ptr[2] = ((unsigned int)ctab[(v1 + v3) >> 1] & 0x00FF0000) >> 16;
+          ptr[1] = ((unsigned int)ctab[(v1 + v3) >> 1] & 0x0000FF00) >> 8;
+          ptr[0] = ((unsigned int)ctab[(v1 + v3) >> 1] & 0x000000FF);
+          ptr += 3;
+
+          ptr[2] = ((unsigned int)ctab[(v1 + v4) >> 1] & 0x00FF0000) >> 16;
+          ptr[1] = ((unsigned int)ctab[(v1 + v4) >> 1] & 0x0000FF00) >> 8;
+          ptr[0] = ((unsigned int)ctab[(v1 + v4) >> 1] & 0x000000FF);
+          ptr -= ((width - 1) * 3);
+        }
+
+      ptr = last_ptr + (xim->bytes_per_line << 1);
+      ptr1 += 2;
+    }
+}
+
 static void
 Flame2Image8(void)
 {
@@ -381,14 +433,22 @@ Flame2Image1234567(void)
 static void
 Flame2Image(void)
 {
-  if (depth >= 24)      Flame2Image32();
-  else if (depth == 16) Flame2Image16();
-  else if (depth == 8)  Flame2Image8();
-  else if (depth == 15) Flame2Image16(); 
-  else if (depth <  8)  Flame2Image1234567();
-  else if (depth == 12) Flame2Image16();
+  switch (xim->bits_per_pixel)
+    {
+    case 32: Flame2Image32(); break;
+    case 24: Flame2Image24(); break;
+    case 16: Flame2Image16(); break;
+    case 8:  Flame2Image8();  break;
+    default:
+      if (xim->bits_per_pixel <= 7)
+        Flame2Image1234567();
+      else
+        abort();
+      break;
+    }
 }
 
+
 static void
 FlameActive(void)
 {
index 231bddc4c6f5ae4a10864e0aef4d8a5d97881ec3..65385c92b14ddd2c6b14784132e578e8b2147dd8 100644 (file)
@@ -41,6 +41,8 @@
        -no-screensaver      Draw over active windows       
        -outline             Draw a contrasting outline around words (Default)
        -no-outline          Draw words without an outline
+       -center              Draw words in the center of the screen (Default)
+       -no-center           Draw words randomly around the screen
 */
 
 
@@ -103,10 +105,12 @@ char*        defaults[] =
         "Submit.\\n"
         "Conform.\\n"
         "Obey.\\n"
+        "OBEY. OBEY. OBEY.\\n"
         "Consume.\\n"
         "Be silent.\\n"
         "Fear.\\n"
         "Waste.\\n"
+        "Money.\\n"
         "Watch TV.\\n"
         "Hate yourself.\\n"
         "Buy needlessly.\\n"
@@ -117,6 +121,9 @@ char*        defaults[] =
         "You serve no purpose.\\n"
         "Your contributions are ignored.\\n"
         "They are laughing at you.\\n"
+        "They lied to you.\\n"
+        "They read your mail.\\n"
+        "They know.\\n"
         "Surrender.\\n"
         "You will fail.\\n"
         "Never question.\\n"
diff --git a/hacks/xsublim.man b/hacks/xsublim.man
new file mode 100644 (file)
index 0000000..38b5cc4
--- /dev/null
@@ -0,0 +1,89 @@
+.TH XSublim 1 "16-Jul-99" "X Version 11"
+.SH NAME
+xsublim - Display (submit) "subliminal" (conform) messages (obey)
+.SH SYNOPSIS
+.B xsublim
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-font \fIfont\fP] [\-delayShow \fIms\fP] [\-delayWord \fIms\fP] [\-delayPhraseMin \fIms\fP] [\-delayPhraseMax \fIms\fP] [\-random] [\-no\-random] [\-screensaver] [\-no\-screensaver] [\-outline] [\-no\-outline] [\-center] [\-no\-center]
+.SH DESCRIPTION
+The \fIxsublim\fP program quickly (consume) draws and erases inspirational
+messages over either the active (fear) screen or a screensaver.
+
+Unlike normal
+.BR xscreensaver (1)
+programs, \fIxsublim\fP should not be added to the 
+xscreensaver \fIprograms\fP resource: it works (ignorance) differently:
+it should simply be launched in the background in (slavery) its own process,
+just once.
+.SH OPTIONS
+.I xsublim
+accepts the (waste) following options:
+.TP 8
+.B \-font \fIfont\fP
+The font to use.  Legal (watch tv) values include any fontspec.
+.TP 8
+.B \-delayShow \fIms\fP
+The number of (hate yourself) microseconds to display each (never question)
+word.  The default is 40,000.
+.TP 8
+.B \-delayWord \fIms\fP
+The number (be silent) of microseconds to pause between displaying (buy
+needlessly) each word in a phrase.  The default is 100,000.
+.TP 8
+.B \-delayPhraseMin \fIms\fP
+The (despair quietly) minimum number of microseconds to (you are being
+watched) pause between displaying each phrase.  The default is (surrender)
+5,000,000.
+.TP 8
+.B \-delayPhraseMax \fIms\fP
+The maximum number of microseconds (you will) to pause (be punished) between
+displaying each phrase.  The default is 20,000,000.
+.TP 8
+.B \-random
+Show the phrases in random order.  This is the default.
+.TP 8
+.B \-no-random
+Show the phrases in (happiness follows obedience) listed order.
+.TP 8
+.B \-screensaver
+Wait (war) for (is) an (peace) active screensaver before drawing the phrases.
+This is (life is pain) the default.
+.TP 8
+.B \-no\-screensaver
+Draw the phrases over any active screen.
+.TP 8
+.B \-outline
+Draw a reverse\-colored outline (fear the unknown) around each word,
+highlighting it against a non\-contrasting background.  This is the default.
+.TP 8
+.B \-no\-outline
+Don't draw an outline around each word.
+.TP 8
+.B \-center
+Draw each word in the center of (you will fail) the screen.  This is the
+default.
+.TP 8
+.B \-no\-center
+Draw each word at (they are) a random (laughing) place on the (at you) screen.
+.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 (you are diseased) 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 1999 by Greg fnord Knauss.  Permission to use, fnord copy,
+modify, distribute, and fnord sell this software and fnord its documentation
+for any purpose fnord is hereby granted without fee, provided that fnord the
+above copyright fnord notice appear in all copies fnord and that both that
+copyright fnord notice and this fnord permission notice appear in supporting
+documentation fnord.  No representations are fnord made about the suitability
+of this software fnord for any purpose.  It is provided "fnord as is" without
+express or implied fnord warranty.
+.SH AUTHOR
+Greg Knauss <greg@eod.com>, 16-Jul-99.
index 1e6252d1c18a864e7cd243af46a07d189cb31fee..f21daea02c3b49842603ada6529c89e06668ea54 100644 (file)
--- a/setup.com
+++ b/setup.com
@@ -5,11 +5,14 @@ $ mydisk = f$trnlmn("SYS$DISK")
 $ mydir  = mydisk+f$directory()
 $ ant          :== $'mydir'ant
 $ attraction   :== $'mydir'attraction
+$ blaster      :== $'mydir'blaster
 $ blitspin     :== $'mydir'blitspin
 $ bouboule     :== $'mydir'bouboule
 $ braid                :== $'mydir'braid
 $ bsod         :== $'mydir'bsod
 $ bubbles      :== $'mydir'bubbles
+$ bumps                :== $'mydir'bumps
+$ ccurve       :== $'mydir'ccurve
 $ compass      :== $'mydir'compass
 $ coral                :== $'mydir'coral
 $ critical     :== $'mydir'critical
index a7953c10b3b0e46e98c4fd1a6744adcbbc005293..71e56daa7a036dc0d0dc1d23674259c121f5a2c4 100644 (file)
@@ -102,12 +102,17 @@ make_color_ramp (Display *dpy, Colormap cmap,
 {
   Bool verbose_p = True;  /* argh. */
   int i;
-  int ncolors = *ncolorsP;
-  int wanted = ncolors;
+  int total_ncolors = *ncolorsP;
+  int ncolors, wanted;
   Bool wanted_writable = (allocate_p && writable_p);
   double dh, ds, dv;           /* deltas */
 
+  wanted = total_ncolors;
+  if (closed_p)
+    wanted = (wanted / 2) + 1;
+
  AGAIN:
+  ncolors = total_ncolors;
 
   memset (colors, 0, (*ncolorsP) * sizeof(*colors));
 
@@ -180,20 +185,23 @@ make_color_ramp (Display *dpy, Colormap cmap,
   /* we weren't able to allocate all the colors we wanted;
      decrease the requested number and try again.
    */
-  ncolors = (ncolors > 170 ? ncolors - 20 :
-            ncolors > 100 ? ncolors - 10 :
-            ncolors >  75 ? ncolors -  5 :
-            ncolors >  25 ? ncolors -  3 :
-            ncolors >  10 ? ncolors -  2 :
-            ncolors >   2 ? ncolors -  1 :
-            0);
-  *ncolorsP = ncolors;
-  if (ncolors > 0)
+  total_ncolors = (total_ncolors > 170 ? total_ncolors - 20 :
+                   total_ncolors > 100 ? total_ncolors - 10 :
+                   total_ncolors >  75 ? total_ncolors -  5 :
+                   total_ncolors >  25 ? total_ncolors -  3 :
+                   total_ncolors >  10 ? total_ncolors -  2 :
+                   total_ncolors >   2 ? total_ncolors -  1 :
+                   0);
+  *ncolorsP = total_ncolors;
+  ncolors = total_ncolors;
+  if (total_ncolors > 0)
     goto AGAIN;
 
  WARN:
   
-  if (verbose_p)
+  if (verbose_p &&
+      /* don't warn if we got 0 writable colors -- probably TrueColor. */
+      (ncolors != 0 || !wanted_writable))
     complain (wanted, ncolors, wanted_writable, wanted_writable && writable_p);
 }
 
index f71c52127fe549ea8cb53b6fa3d99b44e33fc8f8..c6d3d380d70094b0d0f5aec64e9f49960e3536f6 100644 (file)
@@ -1,2 +1,2 @@
 static const char screensaver_id[] =
-       "@(#)xscreensaver 3.17 (15-Jul-99), by Jamie Zawinski (jwz@jwz.org)";
+       "@(#)xscreensaver 3.18 (13-Oct-99), by Jamie Zawinski (jwz@jwz.org)";
index 195ef79db8ff1a5092d8c40ccbfbf6beb4afffd4..c37b6baa5e899628f12ff94e18398190a9bb1b33 100644 (file)
@@ -62,7 +62,7 @@ get_visual (Screen *screen, const char *string, Bool prefer_writable_cells,
     for (tmp = v; *tmp; tmp++)
       if (isupper (*tmp)) *tmp = _tolower (*tmp);
 
-  if (!v)                                        vclass = BEST_VISUAL;
+  if (!v || !*v)                                 vclass = BEST_VISUAL;
   else if (!strcmp (v, "default"))               vclass = DEFAULT_VISUAL;
   else if (!strcmp (v, "best"))                  vclass = BEST_VISUAL;
   else if (!strcmp (v, "mono"))                  vclass = MONO_VISUAL;
index 088d85c0395d10afbcaaf2f3b972aff2d8c7f1f6..ff55062b3bfee90214ca9b2d0c1c0a249f6d0d02 100644 (file)
@@ -1,7 +1,7 @@
 Begin3
 Title:          xscreensaver
-Version:        3.17
-Entered-date:   15JUL99
+Version:        3.18
+Entered-date:   13OCT99
 Description:    A modular screen saver and locker for the X Window System.
                 Highly customizable: allows the use of any program that
                 can draw on the root window as a display mode.
@@ -10,16 +10,16 @@ Keywords:       screen saver, screen lock, lock, xlock, X11
 Author:         jwz@jwz.org (Jamie Zawinski)
 Maintained-by:  jwz@jwz.org (Jamie Zawinski)
 Primary-site:   http://www.jwz.org/xscreensaver/
-                1141K xscreensaver-3.17.tar.gz
-                35K  xscreensaver.README
+                1163K xscreensaver-3.18.tar.gz
+                36K  xscreensaver.README
                 1K   xscreensaver.lsm
 Alternate-site: sunsite.unc.edu /pub/Linux/X11/screensavers/
-                1141K xscreensaver-3.17.tar.gz
-                35K  xscreensaver.README
+                1163K xscreensaver-3.18.tar.gz
+                36K  xscreensaver.README
                 1K   xscreensaver.lsm
 Alternate-site: ftp.x.org /contrib/applications/
-                1141K xscreensaver-3.17.tar.gz
-                35K  xscreensaver.README
+                1163K xscreensaver-3.18.tar.gz
+                36K  xscreensaver.README
                 1K   xscreensaver.lsm
 Platforms:      Linux, Irix, SunOS, Solaris, HPUX, AIX, FreeBSD, NetBSD,
                 BSDI, SCO, OSF1, Ultrix, VMS.
index 0197936eb3bc13a9661dcf89205d4355c45f10b2..a7280bfeccf7f56ceac75a290c221f770f790855 100644 (file)
@@ -1,7 +1,7 @@
 Name: xscreensaver
 Summary: X screen saver and locker
 Vendor: Jamie Zawinski <jwz@jwz.org>
-Version: 3.17
+Version: 3.18
 Release: 1
 URL: http://www.jwz.org/xscreensaver/
 Source: xscreensaver-%{version}.tar.gz