]> git.hungrycats.org Git - xscreensaver/commitdiff
http://www.ibiblio.org/pub/historic-linux/ftp-archives/sunsite.unc.edu/Sep-29-1996... xscreensaver-1.26 github/xscreensaver-1.26
authorZygo Blaxell <zblaxell@hungrycats.org>
Fri, 27 Feb 2009 19:40:52 +0000 (14:40 -0500)
committerZygo Blaxell <zblaxell@hungrycats.org>
Fri, 27 Feb 2009 19:40:52 +0000 (14:40 -0500)
-rw-r--r-- 1 zblaxell zblaxell 148692 May 24  2002 xscreensaver-1.26.tar.gz
e06b9602a89be6f08963e6a0f933b1edeae68eb4  xscreensaver-1.26.tar.gz

94 files changed:
Imakefile [new file with mode: 0644]
README [new file with mode: 0644]
config.h [new file with mode: 0644]
driver/.gdbinit [new file with mode: 0644]
driver/Imakefile [new file with mode: 0644]
driver/README [new file with mode: 0644]
driver/XScreenSaver.ad [new file with mode: 0644]
driver/demo.c [new file with mode: 0644]
driver/dialogs.c [new file with mode: 0644]
driver/dialogs.xd [new file with mode: 0644]
driver/lock.c [new file with mode: 0644]
driver/stderr.c [new file with mode: 0644]
driver/subprocs.c [new file with mode: 0644]
driver/timers.c [new file with mode: 0644]
driver/windows.c [new file with mode: 0644]
driver/xscreensaver-command.c [new file with mode: 0644]
driver/xscreensaver-command.man [new file with mode: 0644]
driver/xscreensaver.c [new file with mode: 0644]
driver/xscreensaver.h [new file with mode: 0644]
driver/xscreensaver.man [new file with mode: 0644]
hacks/.gdbinit [new file with mode: 0644]
hacks/Imakefile [new file with mode: 0644]
hacks/README [new file with mode: 0644]
hacks/attraction.c [new file with mode: 0644]
hacks/attraction.man [new file with mode: 0644]
hacks/blitspin.c [new file with mode: 0644]
hacks/blitspin.man [new file with mode: 0644]
hacks/decayscreen.c [new file with mode: 0644]
hacks/decayscreen.man [new file with mode: 0644]
hacks/default.xbm [new file with mode: 0644]
hacks/flame.c [new file with mode: 0644]
hacks/flame.man [new file with mode: 0644]
hacks/greynetic.c [new file with mode: 0644]
hacks/greynetic.man [new file with mode: 0644]
hacks/halo.c [new file with mode: 0644]
hacks/halo.man [new file with mode: 0644]
hacks/helix.c [new file with mode: 0644]
hacks/helix.man [new file with mode: 0644]
hacks/hopalong.c [new file with mode: 0644]
hacks/hopalong.man [new file with mode: 0644]
hacks/hypercube.c [new file with mode: 0644]
hacks/hypercube.man [new file with mode: 0644]
hacks/imsmap.c [new file with mode: 0644]
hacks/imsmap.man [new file with mode: 0644]
hacks/lmorph.c [new file with mode: 0644]
hacks/lmorph.man [new file with mode: 0644]
hacks/maze.c [new file with mode: 0644]
hacks/maze.man [new file with mode: 0644]
hacks/noseguy.c [new file with mode: 0644]
hacks/noseguy.man [new file with mode: 0644]
hacks/noses/CVS/Entries [new file with mode: 0644]
hacks/noses/CVS/Repository [new file with mode: 0644]
hacks/noses/nose.0.left [new file with mode: 0644]
hacks/noses/nose.0.right [new file with mode: 0644]
hacks/noses/nose.1.left [new file with mode: 0644]
hacks/noses/nose.1.right [new file with mode: 0644]
hacks/noses/nose.down [new file with mode: 0644]
hacks/noses/nose.front [new file with mode: 0644]
hacks/noses/nose.left.front [new file with mode: 0644]
hacks/noses/nose.right.front [new file with mode: 0644]
hacks/pedal.c [new file with mode: 0644]
hacks/pedal.man [new file with mode: 0644]
hacks/pyro.c [new file with mode: 0644]
hacks/pyro.man [new file with mode: 0644]
hacks/qix.c [new file with mode: 0644]
hacks/qix.man [new file with mode: 0644]
hacks/rocks.c [new file with mode: 0644]
hacks/rocks.man [new file with mode: 0644]
hacks/rorschach.c [new file with mode: 0644]
hacks/rorschach.man [new file with mode: 0644]
hacks/screenhack.c [new file with mode: 0644]
hacks/screenhack.h [new file with mode: 0644]
hacks/slidescreen.c [new file with mode: 0644]
hacks/slidescreen.man [new file with mode: 0644]
hacks/vroot.h [new file with mode: 0644]
hacks/xlock.h [new file with mode: 0644]
hacks/xroger-hack.c [new file with mode: 0644]
hacks/xroger.man [new file with mode: 0644]
screenblank.txt [new file with mode: 0644]
utils/Imakefile [new file with mode: 0644]
utils/README [new file with mode: 0644]
utils/ad2c [new file with mode: 0755]
utils/fade.c [new file with mode: 0644]
utils/grabscreen.c [new file with mode: 0644]
utils/hsv.c [new file with mode: 0644]
utils/resources.c [new file with mode: 0644]
utils/spline.c [new file with mode: 0644]
utils/spline.h [new file with mode: 0644]
utils/usleep.c [new file with mode: 0644]
utils/version.h [new file with mode: 0644]
utils/visual.c [new file with mode: 0644]
utils/xroger.c [new file with mode: 0644]
utils/yarandom.c [new file with mode: 0644]
utils/yarandom.h [new file with mode: 0644]

diff --git a/Imakefile b/Imakefile
new file mode 100644 (file)
index 0000000..d7ec7c6
--- /dev/null
+++ b/Imakefile
@@ -0,0 +1,53 @@
+/*
+ * Imakefile file for xscreensaver, Copyright (c) 1991-1994 Jamie Zawinski.
+ *
+ * You should not need to edit this file; edit config.h instead.
+ *
+ */
+
+#include "config.h"
+
+       TARFILES = README Imakefile config.h screenblank.txt
+            TAR = tar
+       COMPRESS = compress
+   COMPRESS_EXT = Z
+/**/#      COMPRESS = gzip --verbose --best
+/**/#  COMPRESS_EXT = gz
+
+all:: utils/Makefile driver/Makefile hacks/Makefile
+       cd utils  ; $(MAKE) $@ CC="$(CC)" CCOPTIONS="$(CCOPTIONS)" CDEBUGFLAGS="$(CDEBUGFLAGS)"
+       cd driver ; $(MAKE) $@ CC="$(CC)" CCOPTIONS="$(CCOPTIONS)" CDEBUGFLAGS="$(CDEBUGFLAGS)"
+       cd hacks  ; $(MAKE) $@ CC="$(CC)" CCOPTIONS="$(CCOPTIONS)" CDEBUGFLAGS="$(CDEBUGFLAGS)"
+
+clean install install.man:: utils/Makefile driver/Makefile hacks/Makefile
+       cd utils  ; $(MAKE) $@ BINDIR=$(BINDIR) XAPPLOADDIR=$(XAPPLOADDIR)
+       cd driver ; $(MAKE) $@ BINDIR=$(BINDIR) XAPPLOADDIR=$(XAPPLOADDIR)
+       cd hacks  ; $(MAKE) $@ BINDIR=$(BINDIR) XAPPLOADDIR=$(XAPPLOADDIR)
+
+Makefiles:: utils/Makefile driver/Makefile hacks/Makefile
+
+utils/Makefile: utils/Imakefile config.h
+       cd utils  ; $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)/utils
+driver/Makefile: driver/Imakefile config.h
+       cd driver ; $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)/driver
+hacks/Makefile: hacks/Imakefile config.h
+       cd hacks  ; $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)/hacks
+
+/* This really makes me sick... */
+tar: utils/Makefile driver/Makefile hacks/Makefile
+       @NAME=`sed -n                                                       \
+  's/[^0-9]*\([0-9]\.[0-9][0-9]*\).*/xscreensaver-\1/p' utils/version.h` ;  \
+  rm -f $$NAME ; ln -s . $$NAME ;                                          \
+  FILES= ;                                                                 \
+  for subdir in driver utils hacks ; do                                            \
+    cd $$subdir ;                                                          \
+    FILES="$$FILES `make echo_tarfiles                                     \
+      | grep -v '^make\['                                                  \
+      | sed \"s|^|$$subdir/|g;s| | $$subdir/|g\"                           \
+      ` ";                                                                 \
+    cd .. ; done ;                                                         \
+  echo creating tar file $${NAME}.tar.$(COMPRESS_EXT)... ;                 \
+  $(TAR) -vchf -                                                           \
+    `echo $(TARFILES) $$FILES | sed "s|^|$$NAME/|g; s| | $$NAME/|g" `      \
+   | $(COMPRESS) > $${NAME}.tar.$(COMPRESS_EXT) ;                          \
+  rm $$NAME
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..55b1ae2
--- /dev/null
+++ b/README
@@ -0,0 +1,133 @@
+
+To build:
+
+  -  read the comments in `config.h' and edit it as appropriate
+  -  xmkmf ; make
+  -  make install install.man
+
+The xscreensaver program waits until the keyboard and mouse have been idle
+for a period, and then runs a graphics demo chosen at random.  It turns off
+as soon as there is any mouse or keyboard activity.
+
+The purpose of xscreensaver is to display pretty pictures on your screen 
+when it is not in use, in keeping with the philosophy that unattended 
+monitors should always be doing something interesting, just like they do 
+in the movies.
+
+However, xscreensaver can also be used as a screen locker, to prevent
+others from using your terminal while your are away.
+
+The benefit that this program has over the combination of the xlock and
+xautolock programs is the ease with which new graphics hacks can be
+installed: you don't need to recompile this program to add a new display
+mode, you just change some resource settings.  Any program which can be
+invoked in such a way that it draws on the root window of the screen can
+now be used as a screensaver without modification.  The programs that
+are being run as screensavers don't need to have any special knowledge
+about what it means to be a screensaver.
+
+The XIDLE or MIT-SCREEN-SAVER server extensions will be used if you have them.
+
+Unfortunately, locking doesn't work if you don't have Motif.
+
+Also included are several graphics hacks for use as screensavers.  There's
+nothing magic about these: they're just programs that draw on the root
+window, which are pointed at by the screensaver's default resource settings.
+
+   qix         - My own implementation of this, with many more options
+                 than you would have thought qix could have.
+   helix       - Generates spirally "stringart" patterns.
+   pedal       - Draws a different kind of spirally pattern.
+   rorschach   - Random inkblot patterns.
+   attraction  - A bouncing ball demo, or a qix-like demo, or a wild
+                 color-cycling thing, with some odd rules.
+   greynetic   - Random colored/stippled rectangles.
+   rocks       - Flying through an asteroid field.
+   blitspin    - Rotate a bitmap using bitblts.
+   imsmap      - Generates random maps or cloud formations.
+   hypercube   - 2d projection of a hypercube rotating on all four axes.
+   slidescreen - Divides the screen into a grid and plays a 16-puzzle on it.
+   decayscreen - A melting effect.
+   halo                - Random circular patterns.
+   pyro                - Fireworks.  Looks a lot like the version in xlock.
+   hopalong    - Fractals.  I snarfed this code from xlock.
+   flame       - Fractals.  Also from xlock.
+   noseguy     - A guy with a big nose wanders around the screen saying
+                 things.  I snarfed this code from xnlock.
+   maze                - This is the X maze demo modified to take a -root option
+                 so that it works with xscreensaver.
+   lmorph      - morphing line drawings.
+
+All of these will pop up their own window unless given that -root option.
+See their man pages for more details.
+
+Other reasonable things to use as screensavers, if you have them, are
+
+  xdaliclock -root -builtin2   - melting digital clock
+  xswarm -r 2>&-               - swimming sperm
+  xwave -root                  - random 3d graphs
+  xbouncebits                  - bounce arbitrary bitmaps around
+  ico -r                       - it's dull, but it's there
+  xv -root file.gif -quit      - they don't all have to animate!
+  xsplinefun                   - bouncing splines
+  kaleid -root                 - qix-like kaleidescope patterns
+  xfishtank -c black -d -r 1   - fish (use version 2.0 or later)
+
+You can get all of these from the contrib directory on ftp.x.org.  If you
+know of (or write) any other interesting programs that can be used as
+screensavers, please let me know!
+
+The latest version of xscreensaver is always ftpable from ftp.x.org.  You can
+also get it from my web page at http://www.netscape.com/people/jwz/.
+
+       -- Jamie Zawinski <jwz@netscape.com>
+
+\f
+Changes since 1.25:    Added `lmorph' hack.
+                       Added viscosity and mouse-control to attraction.
+                       Fixed possible bad color choices in qix and attraction.
+                       Added ramp-mode to halo.
+                       Added a new RNG, which is faster and more portable
+                       than using the RNG in libc.
+                       Made locking work on SCO.
+                       Various other minor tweaks that I don't remember.
+Changes since 1.24:    Made it capture the stdout/stderr of its subprocesses
+                       and present them on the screensaver window itself.
+                       Made demo mode work correctly with non-default visuals
+                       and color maps, instead of always using the defaults.
+                       Added -visual argument to all included screenhacks.
+                       Support for the R6 MIT-SCREEN-SAVER server extension.
+                       Made the demo mode list scroll properly.
+                       Added `pedal' hack.
+Changes since 1.23:    Fixed some private-colormap oddities in slidescreen,
+                       decayscreen, and xroger.  Fixed apparent conservation-
+                       of-mass problem in pyro; made the shrapnel round.
+Changes since 1.22:    Minor tweaks for IRIX5; fixed locking race condition.
+Changes since 1.21:    Minor tweaks for X11R6.
+                       Fixes for non-default visuals.
+Changes since 1.20:    Fixed bug in color blitspin; added default image.
+                       Added diagnostics to noseguy.  Fixed off-by-one
+                       error in flame.  Added some missing casts.
+Changes since 1.18:    Added `flame' hack.
+                       Fixed a minor Motif dialog text field bug.
+                       Fixed yet another XPointer-not-defined-in-R4 bug.
+Changes since 1.17:    Added support for shadow password files.
+                       Fixed some Motif-related locking bugs.
+                       Added diagnostics when locking is disabled.
+                       Made blitspin able to use the XPM library.
+                       Added `decayscreen' hack.
+Changes since 1.16:    Added `halo' hack.
+Changes since 1.15:    Portability fixes.
+Changes since 1.14:    Broke the driver up into more source files.
+                       Moved the hacks into their own directory.
+                       Made all `time' parameters accept the 00:00:00 syntax,
+                       so that even the parameters which are normally read as
+                       `minutes' can be specified in seconds.
+                       Added colormap cycling to `imsmap'.
+                       Made hyper work with K&R compilers.
+Changes since 1.13:    Added `orbit' option to `attraction' hack.
+                       Added `lock-timeout' option.
+                       Cleaned up options of `maze' hack.
+Changes since 1.8:     Added demo mode, and locking.
+                       Added `maze' hack.
+                       Added `norotate' option to `rocks' hack.
diff --git a/config.h b/config.h
new file mode 100644 (file)
index 0000000..17517dc
--- /dev/null
+++ b/config.h
@@ -0,0 +1,121 @@
+/*
+ * Config file for xscreensaver, Copyright (c) 1991-1995 Jamie Zawinski.
+ * This file is included by the various Imakefiles.
+ */
+
+/*  Uncomment the following line if you have the XIDLE extension installed.
+ *  This extension resides in .../contrib/extensions/xidle/ on the X11R5
+ *  contrib tape.  (Turning on this flag lets XScreenSaver work better with
+ *  servers which support this extension; but it will still work with servers
+ *  which do not suport this extension, so it's a good idea to compile in
+ *  support for it if you can.)
+ */
+/* #define HAVE_XIDLE_EXTENSION */
+
+/*  Uncomment the following line if you have the MIT-SCREEN-SAVER extension
+ *  installed.  This extension resides in .../contrib/extensions/screensaver/
+ *  on the X11R6 contrib tape.
+ *
+ *  This extension does basically the same thing that the XIDLE extension does,
+ *  but there are two things wrong with it: first, because of the way the 
+ *  extension was designed, the `fade' option to XScreenSaver will be uglier:
+ *  just before the screen fades out, there will be an unattractive flicker to
+ *  black, because this extension blanks the screen *before* telling us that it
+ *  is time to do so.  Second, this extension is known to be buggy; on the
+ *  systems I use, it works, but some people have reported X server crashes as
+ *  a result of using it.  XScreenSaver uses this extension rather
+ *  conservatively, because when I tried to use any of its more complicated
+ *  features, I could get it to crash the server at the drop of a hat.
+ *
+ *  I wish someone would port the XIDLE extension to R6.  Or I wish someone
+ *  would make the MIT-SCREEN-SAVER extension not be such a piece of junk.
+ *
+ *  Note that the SGI X server also has an extension called SCREEN_SAVER.
+ *  That is a completely different extension, and XScreenSaver contains no
+ *  support for it (though it probably wouldn't be hard.)
+ */
+/* #define HAVE_SAVER_EXTENSION */
+
+/*  Uncomment the following line if you have the XPM library installed.
+ *  Some of the demos can make use of this if it is available.
+ */
+#define HAVE_XPM
+
+/*  Uncomment the following line if you don't have Motif.  If you don't have
+ *  Motif, then the screensaver won't have any dialog boxes, which means
+ *  that it won't be compiled with support for demo-mode or display-locking.
+ *  But other than that, it will work fine.
+ */
+/* #define NO_MOTIF */
+
+/*  Uncomment the following line if for some reason the locking code doesn't
+ *  work (for example, if you don't have the crypt() system call, or if you
+ *  don't use standard passwd files.)  If you need to do this, please let me
+ *  know.
+ */
+/* #define NO_LOCKING */
+
+/*  Uncomment the following line if your system doesn't have the select()
+ *  system call.  If you need to do this, please let me know.
+ */
+/* #define NO_SELECT */
+
+/*  Uncomment the following line if your system doesn't have the setuid(),
+ *  setregid(), and getpwnam() library routines.
+ *
+ *  WARNING: if you do this, it will be unsafe to run xscreensaver as root
+ *  (which probably means you can't have it be started by xdm.)  If you are
+ *  on such a system, please try to find the corresponding way to do this,
+ *  and then tell me what it is.
+ */
+/* #define NO_SETUID */
+
+/*  Uncomment the following line if your system uses `shadow' passwords,
+ *  that is, the passwords live in /etc/shadow instead of /etc/passwd,
+ *  and one reads them with getspnam() instead of getpwnam().
+ */
+/* #define HAVE_SHADOW */
+
+/*  You may need to edit these to correspond to where Motif is installed.
+ */
+#ifndef NO_MOTIF
+  MOTIFINCLUDES = -I/usr/local/include/
+ MOTIFLDOPTIONS = -L/usr/local/lib/
+      MOTIFLIBS = -lXm
+#endif
+
+/*  On some systems, only programs running as root can use the getpwent()
+    library routine.  This means that, in order for locking to work, the
+    screensaver must be installed as setuid to root.  Define this to make
+    that happen.  (You must run "make install" as root for it to work.)
+    (What systems other than HP and AIX need this?  Let me know.)
+ */
+#if defined(HPArchitecture) || defined(AIXArchitecture) || defined(HAVE_SHADOW)
+# define INSTALL_SETUID
+#endif
+
+#ifdef HPArchitecture
+      CCOPTIONS = -Aa -D_HPUX_SOURCE   /* eat me */
+# if (ProjectX <= 4)
+  MOTIFINCLUDES = -I/usr/include/Motif1.1
+ MOTIFLDOPTIONS = -L/usr/lib/Motif1.1
+# else /* R5 */
+  MOTIFINCLUDES = -I/usr/include/Motif1.2
+ MOTIFLDOPTIONS = -L/usr/lib/Motif1.2
+# endif /* R5 */
+#endif /* HPArchitecture */
+
+#ifdef MacIIArchitecture
+      CCOPTIONS = -D_POSIX_SOURCE
+#endif /* MacIIArchitecture */
+
+#if (ProjectX <= 4)
+# define R5ISMS -DXPointer="char*"
+#else /* r5 or better */
+# define R5ISMS
+#endif
+
+/* It seems that some versions of Sun's dynamic X libraries are broken; if
+   you get link errors about _get_wmShellWidgetClass being undefined, try
+   adding -Bstatic to the link command.
+ */
diff --git a/driver/.gdbinit b/driver/.gdbinit
new file mode 100644 (file)
index 0000000..e04c492
--- /dev/null
@@ -0,0 +1,25 @@
+# If you're debugging xscreensaver and you are running a virtual root window
+# manager, you'd better let the process handle these signals: it remaps the
+# virtual root window when they arrive.  If you don't do this, your window
+# manager will be hosed.
+#
+# Also, gdb copes badly with breakpoints in functions that are called on the
+# other side of a fork().  The Trace/BPT traps cause the spawned process to
+# die.
+#
+#handle 1 pass nostop
+#handle 3 pass nostop
+#handle 4 pass nostop
+#handle 6 pass nostop
+#handle 7 pass nostop
+#handle 8 pass nostop
+#handle 9 pass nostop
+#handle 10 pass nostop
+#handle 11 pass nostop
+#handle 12 pass nostop
+#handle 13 pass nostop
+#handle 15 pass nostop
+#handle 19 pass nostop
+b exit
+set args -verbose -idelay 0
+#b purify_stop_here
diff --git a/driver/Imakefile b/driver/Imakefile
new file mode 100644 (file)
index 0000000..5444939
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Imakefile file for xscreensaver, Copyright (c) 1993-1995 Jamie Zawinski.
+ *
+ * You should not need to edit this file; edit ../config.h instead.
+ *
+ */
+
+#include "../config.h"
+
+/* #### If anyone ever finishes the Athena locking code, remove this. */
+#if defined(NO_MOTIF) && !defined(NO_LOCKING)
+# define NO_LOCKING
+#endif
+
+#ifdef NO_LOCKING
+# undef INSTALL_SETUID
+#endif
+
+#ifdef HAVE_XIDLE_EXTENSION
+# define XIDLE_DEF -DHAVE_XIDLE_EXTENSION
+#else
+# define XIDLE_DEF
+#endif
+
+#ifdef HAVE_SAVER_EXTENSION
+# define SAVER_DEF -DHAVE_SAVER_EXTENSION
+#else
+# define SAVER_DEF
+#endif
+
+#ifdef NO_LOCKING
+# define LOCKING_DEF -DNO_LOCKING
+#else
+# define LOCKING_DEF
+#endif
+
+#ifdef NO_SETUID
+# define SETUID_DEF -DNO_SETUID
+#else
+# define SETUID_DEF
+#endif
+
+#ifdef HAVE_SHADOW
+# define SHADOW_DEF -DHAVE_SHADOW
+#else
+# define SHADOW_DEF
+#endif
+
+#ifdef NO_MOTIF
+# define MOTIF_DEF -DNO_MOTIF
+# define MOTIF_SRC
+# define MOTIF_OBJ
+# define MOTIF_LIB
+# define MOTIF_INC
+#else
+# define MOTIF_DEF
+# define MOTIF_SRC $(DBOX_SRCS) $(UTILS)/xroger.c
+# define MOTIF_OBJ $(DBOX_OBJS) $(UTILS)/xroger.o
+# define MOTIF_LIB $(MOTIFLDOPTIONS) $(MOTIFLIBS)
+# define MOTIF_INC $(MOTIFINCLUDES)
+#endif
+
+         UTILS = ../utils
+      INCLUDES = -I$(UTILS) MOTIF_INC
+       DEFINES = SETUID_DEF XIDLE_DEF SAVER_DEF MOTIF_DEF LOCKING_DEF SHADOW_DEF R5ISMS
+     SAVERLIBS = $(XMULIB) $(XTOOLLIB) $(EXTENSIONLIB) $(XLIB) -lm
+      COMMLIBS = $(XLIB) -lm
+     UTIL_SRCS = $(UTILS)/resources.c $(UTILS)/fade.c $(UTILS)/visual.c $(UTILS)/usleep.c $(UTILS)/yarandom.c
+     UTIL_OBJS = $(UTILS)/resources.o $(UTILS)/fade.o $(UTILS)/visual.o $(UTILS)/usleep.o $(UTILS)/yarandom.o
+     DBOX_SRCS = dialogs.c demo.c
+     DBOX_OBJS = dialogs.o demo.o
+     LOCK_SRCS = lock.c
+     LOCK_OBJS = lock.o
+     SAVERSRCS = xscreensaver.c timers.c subprocs.c windows.c stderr.c
+     SAVEROBJS = xscreensaver.o timers.o subprocs.o windows.o stderr.o
+         SRCS1 = $(SAVERSRCS) MOTIF_SRC $(LOCK_SRCS) $(UTIL_SRCS)
+         OBJS1 = $(SAVEROBJS) MOTIF_OBJ $(LOCK_OBJS) $(UTIL_OBJS)
+      COMMSRCS = xscreensaver-command.c
+      COMMOBJS = xscreensaver-command.o
+         SRCS2 = $(COMMSRCS)
+         OBJS2 = $(COMMOBJS)
+           MEN = xscreensaver.man xscreensaver-command.man
+      TARFILES = README Imakefile $(SAVERSRCS) $(DBOX_SRCS) $(LOCK_SRCS) \
+                 $(COMMSRCS) xscreensaver.h XScreenSaver.ad dialogs.xd \
+                 $(MEN) .gdbinit
+
+#if defined(HPArchitecture) && !defined(NO_LOCKING)
+EXTRA_LIBRARIES = -lXhp11      /* for XHPDisableReset() */
+#endif
+
+#if defined(i386ScoArchitecture)
+        SCOLIBS = -lintl -lprot -lx -lcrypt_i
+#endif
+
+all:: xscreensaver xscreensaver-command
+
+echo_tarfiles:
+       @echo $(TARFILES)
+
+PROGRAMS = xscreensaver xscreensaver-command
+
+#ifdef INSTALL_SETUID
+#undef  InstallProgram
+#define InstallProgram(p,d) InstallProgramWithFlags(p,d,$(INSTUIDFLAGS))
+#endif
+
+ComplexProgramTarget_1(xscreensaver,MOTIF_LIB $(SAVERLIBS),$(SCOLIBS) $(HP_NULL_STR))
+
+#ifdef INSTALL_SETUID
+#undef  InstallProgram
+#define InstallProgram(p,d) InstallProgramWithFlags(p,d,$(HP_NULL_STR))
+#endif
+
+ComplexProgramTarget_2(xscreensaver-command,$(COMMLIBS),$(HP_NULL_STR))
+
+InstallAppDefaults(XScreenSaver)
+
+xscreensaver.o: XScreenSaver.ad.h $(UTILS)/version.h
+xscreensaver-command.o: $(UTILS)/version.h
+
+demo.o: $(UTILS)/version.h
+lock.o: $(UTILS)/version.h
+
+/* build this before calling makedepend */
+depend:: XScreenSaver.ad.h
+
+XScreenSaver.ad.h: XScreenSaver.ad
+       $(UTILS)/ad2c XScreenSaver.ad > XScreenSaver.ad.h
+
+clean::
+       $(RM) XScreenSaver.ad.h
+
+
+#if defined(SparcArchitecture) || defined(SGIArchitecture)
+# undef  UsePurify
+# define UsePurify
+#endif
+
+#ifdef UsePurify
+        PURIFY = purify
+ PURIFYOPTIONS = 
+
+# undef  PurifyProgramTarget
+# define PurifyProgramTarget(program,deplist,linklist)                 @@\
+program.pure: deplist                                                  @@\
+       RemoveTargetProgram($@)                                         @@\
+       $(CCENVSETUP) $(PURIFY) $(PURIFYOPTIONS) $(CC)                    \
+         -o $@ $(LDOPTIONS) linklist $(EXTRA_LOAD_FLAGS)
+
+PurifyProgramTarget(xscreensaver,$(OBJS1),$(OBJS1) MOTIF_LIB $(SAVERLIBS))
+
+#endif /* Purify */
diff --git a/driver/README b/driver/README
new file mode 100644 (file)
index 0000000..df64793
--- /dev/null
@@ -0,0 +1,6 @@
+
+This directory contains the source for xscreensaver and xscreensaver-command,
+the screensaver driver, and the program for externally controlling it.  Some
+stuff from the ../utils/ directory is used here as well.
+
+If you have compilation problems, check the parameters in ../config.h.
diff --git a/driver/XScreenSaver.ad b/driver/XScreenSaver.ad
new file mode 100644 (file)
index 0000000..da72eff
--- /dev/null
@@ -0,0 +1,160 @@
+! app-defaults file for XScreenSaver by Jamie Zawinski.
+
+*timeout:      10
+*cycle:                10
+*lockTimeout:  0
+*passwdTimeout:        30
+*nice:         10
+*lock:         False
+*verbose:      False
+*fade:         True
+*unfade:       False
+*fadeSeconds:  1
+*fadeTicks:    75
+
+*captureStderr:        True
+*captureStdout:        True
+*textForeground:       Yellow
+*textBackground:       Black
+*font:                 *-medium-r-*-140-*-m-*
+
+! Turning on "installColormap" interacts erratically with twm and tvtwm,
+! but seems to work fine with mwm and olwm.  Try it and see.
+!
+*installColormap: False
+
+! Programs on this list apply all the time.
+*programs:     qix -root                                               \n\
+               qix -root -solid -delay 0 -segments 100                 \n\
+               qix -root -linear -count 10 -size 100 -segments 200     \n\
+               attraction -root -mode balls                            \n\
+               attraction -root -mode lines -points 3 -segments 200    \n\
+               attraction -root -mode splines -segments 300            \n\
+               attraction -root -mode lines -radius 300                \
+                       -orbit -vmult 0.5                               \n\
+               pyro -root                                              \n\
+               helix -root                                             \n\
+               pedal -root                                             \n\
+               rorschach -root -offset 7                               \n\
+               hopalong -root                                          \n\
+               greynetic -root                                         \n\
+               xroger -root                                            \n\
+               imsmap -root                                            \n\
+               slidescreen -root                                       \n\
+               decayscreen -root                                       \n\
+               hypercube -root                                         \n\
+               halo -root                                              \n\
+               maze -root                                              \n\
+               flame -root                                             \n\
+               lmorph -root                                            \n
+
+! Programs on this list are run only for monochrome screens.
+*monoPrograms: qix -root -linear -count 5 -size 200 -spread 30         \
+                       -segments 75 -solid -xor                        \n\
+               rocks -root                                             \n\
+               noseguy -root                                           \n
+
+! Programs on this list are run only for color (really, non-mono) screens.
+*colorPrograms:        qix -root -count 4 -solid -transparent                  \n\
+               qix -root -count 5 -solid -transparent -linear          \
+                       -segments 250 -size 100                         \n\
+               attraction -root -mode polygons                         \n\
+               attraction -root -mode filled-splines -segments 0       \n\
+               attraction -root -glow -points 10                       \n\
+               rocks -root -fg darksalmon                              \n\
+               noseguy -root -fg yellow -bg gray30                     \n
+
+
+! Some other screenhacks that you might want to track down:
+!
+!              xdaliclock -root -builtin2                              \n\
+!              xswarm -r 2>&-                                          \n\
+!              xwave -root                                             \n\
+!              xbouncebits ...                                         \n\
+!              ico -r                                                  \n\
+!              xsplinefun                                              \n\
+!              kaleid -root                                            \n\
+!              xfishtank -c black -d -r 2                              \n\
+
+
+! Resources for the dialog boxes:
+! 
+*fontList:                       *-helvetica-medium-r-*-*-*-120-*-*-*-iso8859-1
+*demoDialog*label1.fontList:     *-helvetica-medium-r-*-*-*-140-*-*-*-iso8859-1
+*passwdDialog*fontList:          *-helvetica-medium-r-*-*-*-140-*-*-*-iso8859-1
+*XmList.fontList:                  *-courier-medium-r-*-*-*-120-*-*-*-iso8859-1
+*XmTextField.fontList:             *-courier-medium-r-*-*-*-120-*-*-*-iso8859-1
+*passwdDialog.passwdText.fontList: *-courier-medium-r-*-*-*-120-*-*-*-iso8859-1
+
+*XmDialogShell*foreground:             black
+*XmDialogShell*background:             gray90
+*XmDialogShell*XmTextField.foreground: black
+*XmDialogShell*XmTextField.background: white
+*XmDialogShell*demoList.foreground:    black
+*XmDialogShell*demoList.background:    white
+*XmDialogShell*rogerLabel.foreground:  red3
+*XmDialogShell*rogerLabel.background:  white
+
+*XmDialogShell.title:          XScreenSaver
+*allowShellResize:             True
+*autoUnmanage:                 False
+
+! This doesn't work.  Motif ignores it if there is a scroll-list!
+*demoDialog.maxWidth:          600
+
+*label1.labelString:           XScreenSaver %s
+*label2.labelString: Copyright Â© 1991-1995 by Jamie Zawinski <jwz@netscape.com>
+*demoList.visibleItemCount:    10
+*demoList.automaticSelection:  True
+*next.labelString:             Run Next
+*prev.labelString:             Run Previous
+*edit.labelString:             Edit Parameters
+*done.labelString:             Exit Demo Mode
+*restart.labelString:          Reinitialize
+
+*resourcesLabel.labelString:   XScreenSaver Parameters
+
+! *timeoutLabel.labelString:   Timeout Minutes
+! *cycleLabel.labelString:     Cycle Seconds
+! *fadeSecondsLabel.labelString:Fade Seconds
+! *fadeTicksLabel.labelString: Fade Ticks
+! *lockLabel.labelString:      Lock Timeout
+! *passwdLabel.labelString:    Password Timeout
+! *resourcesForm*XmTextField.columns:  5
+
+*timeoutLabel.labelString:     Saver Timeout
+*cycleLabel.labelString:       Cycle Timeout
+*fadeSecondsLabel.labelString: Fade Duration
+*fadeTicksLabel.labelString:   Fade Ticks
+*lockLabel.labelString:                Lock Timeout
+*passwdLabel.labelString:      Password Timeout
+*resourcesForm*XmTextField.columns:    8
+
+*verboseToggle.labelString:    Verbose
+*cmapToggle.labelString:       Install Colormap
+*fadeToggle.labelString:       Fade Colormap
+*unfadeToggle.labelString:     Unfade Colormap
+*lockToggle.labelString:       Require Password
+*resourcesDone.labelString:    Done
+*resourcesCancel.labelString:  Cancel
+
+*passwdDialog.title:           Password
+*passwdLabel1.labelString:     XScreenSaver %s
+*passwdLabel2.labelString:     This display is locked.
+*passwdLabel3.labelString:     Please type %s's password to unlock it.
+*passwdDone.labelString:       Done
+*passwdCancel.labelString:     Cancel
+
+*passwdLabel1.alignment:       ALIGNMENT_BEGINNING
+*passwdLabel2.alignment:       ALIGNMENT_BEGINNING
+*passwdLabel3.alignment:       ALIGNMENT_BEGINNING
+*rogerLabel.width:             150
+
+! You probably won't need to change these.  They aren't consulted if the
+! XIdle extension is being used.
+!
+*pointerPollTime:      5
+*initialDelay:         30
+*windowCreationTimeout:        30
+
+*bourneShell:          /bin/sh
diff --git a/driver/demo.c b/driver/demo.c
new file mode 100644 (file)
index 0000000..b782340
--- /dev/null
@@ -0,0 +1,657 @@
+/* xscreensaver, Copyright (c) 1993-1995 Jamie Zawinski <jwz@netscape.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.
+ */
+
+#include <X11/Intrinsic.h>
+
+#if !__STDC__
+# define _NO_PROTO
+#endif
+
+#include <Xm/Xm.h>
+#include <Xm/Text.h>
+#include <Xm/List.h>
+#include <Xm/ToggleB.h>
+
+#include "xscreensaver.h"
+#include <stdio.h>
+
+#ifdef HAVE_SAVER_EXTENSION
+extern int saver_ext_event_number;
+extern Window server_saver_window;
+#endif /* HAVE_SAVER_EXTENSION */
+
+extern Time timeout, cycle, lock_timeout;
+#ifndef NO_LOCKING
+extern Time passwd_timeout;
+#endif
+extern int fade_seconds, fade_ticks;
+extern Bool verbose_p, install_cmap_p, fade_p, unfade_p;
+extern Bool lock_p, locking_disabled_p;
+
+static void demo_mode_hack P((char *));
+static void demo_mode_done P((void));
+
+static void focus_fuckus P((Widget dialog));
+static void text_cb P((Widget button, XtPointer, XtPointer));
+
+extern void demo_mode_restart_process ();
+
+extern Widget demo_dialog;
+extern Widget label1;
+extern Widget text_line;
+extern Widget demo_form;
+extern Widget demo_list;
+extern Widget next, prev, done, restart, edit;
+
+extern Widget resources_dialog;
+extern Widget resources_form;
+extern Widget res_done, res_cancel;
+extern Widget timeout_text, cycle_text, fade_text, ticks_text;
+extern Widget lock_time_text, passwd_time_text;
+extern Widget verbose_toggle, cmap_toggle, fade_toggle, unfade_toggle,
+  lock_toggle;
+
+extern create_demo_dialog ();
+extern create_resources_dialog ();
+
+static void
+focus_fuckus (dialog)
+     Widget dialog;
+{
+  XSetInputFocus (XtDisplay (dialog), XtWindow (dialog),
+                 RevertToParent, CurrentTime);
+}
+
+static void
+raise_screenhack_dialog ()
+{
+  XMapRaised (XtDisplay (demo_dialog), XtWindow (demo_dialog));
+  if (resources_dialog)
+    XMapRaised (XtDisplay (resources_dialog), XtWindow (resources_dialog));
+  focus_fuckus (resources_dialog ? resources_dialog : demo_dialog);
+}
+
+static void
+destroy_screenhack_dialogs ()
+{
+  if (demo_dialog) XtDestroyWidget (demo_dialog);
+  if (resources_dialog) XtDestroyWidget (resources_dialog);
+  demo_dialog = resources_dialog = 0;
+}
+
+static void
+text_cb (button, client_data, call_data)
+     Widget button;
+     XtPointer client_data, call_data;
+{
+  char *line = XmTextGetString (button);
+  demo_mode_hack (line);
+}
+
+
+static void
+select_cb (button, client_data, call_data)
+     Widget button;
+     XtPointer client_data, call_data;
+{
+  char **hacks = (char **) client_data;
+  XmListCallbackStruct *lcb = (XmListCallbackStruct *) call_data;
+  XmTextSetString (text_line, hacks [lcb->item_position - 1]);
+  if (lcb->reason == XmCR_DEFAULT_ACTION)
+    text_cb (text_line, 0, 0);
+  focus_fuckus (demo_dialog);
+}
+
+static void
+ensure_selected_item_visible (list)
+     Widget list;
+{
+  int *pos_list = 0;
+  int pos_count = 0;
+  if (XmListGetSelectedPos (list, &pos_list, &pos_count) && pos_count > 0)
+    {
+      int top = -2;
+      int visible = 0;
+      XtVaGetValues (list,
+                    XmNtopItemPosition, &top,
+                    XmNvisibleItemCount, &visible,
+                    0);
+      if (pos_list[0] >= top + visible)
+       {
+         int pos = pos_list[0] - visible + 1;
+         if (pos < 0) pos = 0;
+         XmListSetPos (list, pos);
+       }
+      else if (pos_list[0] < top)
+       {
+         XmListSetPos (list, pos_list[0]);
+       }
+    }
+  if (pos_list)
+    XtFree ((char *) pos_list);
+}
+
+static void
+next_cb (button, client_data, call_data)
+     Widget button;
+     XtPointer client_data, call_data;
+{
+  int *pos_list;
+  int pos_count;
+  if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
+    XmListSelectPos (demo_list, 1, True);
+  else
+    {
+      int pos = pos_list [0];
+      XmListSelectPos (demo_list, pos + 1, True);
+      XtFree ((char *) pos_list);
+      if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
+       abort ();
+      if (pos_list [0] == pos)
+       XmListSelectPos (demo_list, 1, True);
+      XtFree ((char *) pos_list);
+    }
+  ensure_selected_item_visible (demo_list);
+  text_cb (text_line, 0, 0);
+}
+
+static void
+prev_cb (button, client_data, call_data)
+     Widget button;
+     XtPointer client_data, call_data;
+{
+  int *pos_list;
+  int pos_count;
+  if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
+    XmListSelectPos (demo_list, 0, True);
+  else
+    {
+      XmListSelectPos (demo_list, pos_list [0] - 1, True);
+      XtFree ((char *) pos_list);
+    }
+  ensure_selected_item_visible (demo_list);
+  text_cb (text_line, 0, 0);
+}
+
+
+static void pop_resources_dialog ();
+static void make_resources_dialog ();
+
+static void
+edit_cb (button, client_data, call_data)
+     Widget button;
+     XtPointer client_data, call_data;
+{
+  Widget parent = (Widget) client_data;
+  if (! resources_dialog)
+    make_resources_dialog (parent);
+  pop_resources_dialog ();
+}
+
+static void
+done_cb (button, client_data, call_data)
+     Widget button;
+     XtPointer client_data, call_data;
+{
+  demo_mode_done ();
+}
+
+
+static void
+restart_cb (button, client_data, call_data)
+     Widget button;
+     XtPointer client_data, call_data;
+{
+  demo_mode_restart_process ();
+}
+
+void
+pop_up_dialog_box (dialog, form, where)
+     Widget dialog, form;
+     int where;
+{
+  /* I'm sure this is the wrong way to pop up a dialog box, but I can't
+     figure out how else to do it.
+
+     It's important that the screensaver dialogs not get decorated or
+     otherwise reparented by the window manager, because they need to be
+     children of the *real* root window, not the WM's virtual root, in
+     order for us to guarentee that they are visible above the screensaver
+     window itself.
+   */
+  Arg av [100];
+  int ac = 0;
+  Dimension sw, sh, x, y, w, h;
+  XtRealizeWidget (form);
+  sw = WidthOfScreen (XtScreen (dialog));
+  sh = HeightOfScreen (XtScreen (dialog));
+  ac = 0;
+  XtSetArg (av [ac], XmNwidth, &w); ac++;
+  XtSetArg (av [ac], XmNheight, &h); ac++;
+  XtGetValues (form, av, ac);
+  switch (where)
+    {
+    case 0:    /* center it in the top-right quadrant */
+      x = (sw/2 + w) / 2 + (sw/2) - w;
+      y = (sh/2 + h) / 2 - h;
+      break;
+    case 1:    /* center it in the bottom-right quadrant */
+      x = (sw/2 + w) / 2 + (sw/2) - w;
+      y = (sh/2 + h) / 2 + (sh/2) - h;
+      break;
+    case 2:    /* center it on the screen */
+      x = (sw + w) / 2 - w;
+      y = (sh + h) / 2 - h;
+      break;
+    default:
+      abort ();
+    }
+  if (x + w > sw) x = sw - w;
+  if (y + h > sh) y = sh - h;
+  ac = 0;
+  XtSetArg (av [ac], XmNx, x); ac++;
+  XtSetArg (av [ac], XmNy, y); ac++;
+  XtSetArg (av [ac], XtNoverrideRedirect, True); ac++;
+  XtSetArg (av [ac], XmNdefaultPosition, False); ac++;
+  /* I wonder whether this does anything useful? */
+  /*  XtSetArg (av [ac], XmNdialogStyle, XmDIALOG_SYSTEM_MODAL); ac++; */
+  XtSetValues (dialog, av, ac);
+  XtSetValues (form, av, ac);
+  XtManageChild (form);
+
+  focus_fuckus (dialog);
+}
+
+
+static void
+make_screenhack_dialog (parent, hacks)
+     Widget parent;
+     char **hacks;
+{
+  char buf [255];
+  Arg av[10];
+  int ac;
+  char *label;
+  XmString xm_label = 0;
+  XmString new_xm_label;
+
+  create_demo_dialog (parent);
+  ac = 0;
+  XtSetArg (av [ac], XmNlabelString, &xm_label); ac++;
+  XtGetValues (label1, av, ac);
+  XmStringGetLtoR (xm_label, XmSTRING_DEFAULT_CHARSET, &label);
+  if (!strcmp (label, XtName (label1)))
+    strcpy (buf, "ERROR: RESOURCES ARE NOT INSTALLED CORRECTLY");
+  else
+    sprintf (buf, label, screensaver_version);
+  new_xm_label = XmStringCreate (buf, XmSTRING_DEFAULT_CHARSET);
+  ac = 0;
+  XtSetArg (av [ac], XmNlabelString, new_xm_label); ac++;
+  XtSetValues (label1, av, ac);
+  XmStringFree (new_xm_label);
+  XtFree (label);
+
+  XtAddCallback (demo_list, XmNbrowseSelectionCallback, select_cb,
+                (XtPointer) hacks);
+  XtAddCallback (demo_list, XmNdefaultActionCallback, select_cb,
+                (XtPointer) hacks);
+
+  XtAddCallback (text_line, XmNactivateCallback, text_cb, 0);
+  XtAddCallback (next, XmNactivateCallback, next_cb, 0);
+  XtAddCallback (prev, XmNactivateCallback, prev_cb, 0);
+  XtAddCallback (done, XmNactivateCallback, done_cb, 0);
+  XtAddCallback (restart, XmNactivateCallback, restart_cb, 0);
+  XtAddCallback (edit, XmNactivateCallback, edit_cb, (XtPointer) parent);
+
+  for (; *hacks; hacks++)
+    {
+      XmString xmstr = XmStringCreate (*hacks, XmSTRING_DEFAULT_CHARSET);
+      XmListAddItem (demo_list, xmstr, 0);
+      /* XmListSelectPos (widget, i, False); */
+      XmStringFree (xmstr);
+    }
+
+#if 0
+  /* Dialogs that have scroll-lists don't obey maxWidth!  Fuck!!  Hack it. */
+  ac = 0;
+  XtSetArg (av [ac], XmNmaxWidth, &max_w); ac++;
+  XtGetValues (demo_dialog, av, ac); /* great, this SEGVs */
+#endif
+
+  pop_up_dialog_box (demo_dialog, demo_form, 0);
+}
+
+\f
+/* the Screensaver Parameters dialog */
+
+static struct resources {
+  int timeout, cycle, secs, ticks, lock_time, passwd_time;
+  int verb, cmap, fade, unfade, lock_p;
+} res;
+
+
+extern int parse_time ();
+
+static void 
+hack_time_cb (dpy, line, store, sec_p)
+     Display *dpy;
+     char *line;
+     int *store;
+     Bool sec_p;
+{
+  if (*line)
+    {
+      int value;
+      value = parse_time (line, sec_p, True);
+      if (value < 0)
+       /*XBell (dpy, 0)*/;
+      else
+       *store = value;
+    }
+}
+
+static void
+res_sec_cb (button, client_data, call_data)
+     Widget button;
+     XtPointer client_data, call_data;
+{
+  hack_time_cb (XtDisplay (button), XmTextGetString (button),
+               (int *) client_data, True);
+}
+
+static void
+res_min_cb (button, client_data, call_data)
+     Widget button;
+     XtPointer client_data, call_data;
+{
+  hack_time_cb (XtDisplay (button), XmTextGetString (button),
+               (int *) client_data, False);
+}
+
+static void
+res_int_cb (button, client_data, call_data)
+     Widget button;
+     XtPointer client_data, call_data;
+{
+  char *line = XmTextGetString (button);
+  int *store = (int *) client_data;
+  unsigned int value;
+  char c;
+  if (! *line)
+    ;
+  else if (sscanf (line, "%u%c", &value, &c) != 1)
+    XBell (XtDisplay (button), 0);
+  else
+    *store = value;
+}
+
+static void
+res_bool_cb (button, client_data, call_data)
+     Widget button;
+     XtPointer client_data, call_data;
+{
+  int *store = (int *) client_data;
+  *store = ((XmToggleButtonCallbackStruct *) call_data)->set;
+}
+
+static void
+res_cancel_cb (button, client_data, call_data)
+     Widget button;
+     XtPointer client_data, call_data;
+{
+  XtDestroyWidget (resources_dialog);
+  resources_dialog = 0;
+  raise_screenhack_dialog ();
+}
+
+
+static void
+res_done_cb (button, client_data, call_data)
+     Widget button;
+     XtPointer client_data, call_data;
+{
+  res_cancel_cb (button, client_data, call_data);
+
+  if (res.timeout < 10) res.timeout = 10;
+  if (res.cycle < 2) res.cycle = 2;
+  if (res.passwd_time < 2) res.passwd_time = 30;
+
+  timeout = res.timeout * 1000;
+  cycle = res.cycle * 1000;
+  lock_timeout = res.lock_time * 1000;
+#ifndef NO_LOCKING
+  passwd_timeout = res.passwd_time * 1000;
+#endif
+  fade_seconds = res.secs;
+  fade_ticks = res.ticks;
+  verbose_p = res.verb;
+  install_cmap_p = res.cmap;
+  fade_p = res.fade;
+  unfade_p = res.unfade;
+  lock_p = res.lock_p;
+}
+
+
+static void
+make_resources_dialog (parent)
+     Widget parent;
+{
+  Arg av[10];
+  int ac;
+
+  create_resources_dialog (parent);
+
+  XtAddCallback (res_done, XmNactivateCallback, res_done_cb, 0);
+  XtAddCallback (res_cancel, XmNactivateCallback, res_cancel_cb, 0);
+
+#define CB(widget,type,slot) \
+       XtAddCallback ((widget), XmNvalueChangedCallback, (type), \
+                      (XtPointer) (slot))
+  CB (timeout_text,    res_min_cb,  &res.timeout);
+  CB (cycle_text,      res_min_cb,  &res.cycle);
+  CB (fade_text,       res_sec_cb,  &res.secs);
+  CB (ticks_text,      res_int_cb,  &res.ticks);
+  CB (lock_time_text,  res_min_cb,  &res.lock_time);
+  CB (passwd_time_text,        res_sec_cb,  &res.passwd_time);
+  CB (verbose_toggle,  res_bool_cb, &res.verb);
+  CB (cmap_toggle,     res_bool_cb, &res.cmap);
+  CB (fade_toggle,     res_bool_cb, &res.fade);
+  CB (unfade_toggle,   res_bool_cb, &res.unfade);
+  CB (lock_toggle,     res_bool_cb, &res.lock_p);
+#undef CB
+  ac = 0;
+  XtSetArg (av[ac], XmNsensitive, False); ac++;
+
+  if (locking_disabled_p)
+    {
+      XtSetValues (passwd_time_text, av, ac);
+      XtSetValues (lock_time_text, av, ac);
+      XtSetValues (lock_toggle, av, ac);
+    }
+  if (CellsOfScreen (XtScreen (parent)) <= 2)
+    {
+      XtSetValues (fade_text, av, ac);
+      XtSetValues (ticks_text, av, ac);
+      XtSetValues (cmap_toggle, av, ac);
+      XtSetValues (fade_toggle, av, ac);
+      XtSetValues (unfade_toggle, av, ac);
+    }
+}
+
+
+static void
+fmt_time (buf, s, min_p)
+     char *buf;
+     unsigned int s;
+     int min_p;
+{
+  unsigned int h = 0, m = 0;
+  if (s >= 60)
+    {
+      m += (s / 60);
+      s %= 60;
+    }
+  if (m >= 60)
+    {
+      h += (m / 60);
+      m %= 60;
+    }
+/*
+  if (min_p && h == 0 && s == 0)
+    sprintf (buf, "%u", m);
+  else if (!min_p && h == 0 && m == 0)
+    sprintf (buf, "%u", s);
+  else
+  if (h == 0)
+    sprintf (buf, "%u:%02u", m, s);
+  else
+*/
+    sprintf (buf, "%u:%02u:%02u", h, m, s);
+}
+
+static void
+pop_resources_dialog ()
+{
+  char buf [100];
+
+  res.timeout = timeout / 1000;
+  res.cycle = cycle / 1000;
+  res.lock_time = lock_timeout / 1000;
+#ifndef NO_LOCKING
+  res.passwd_time = passwd_timeout / 1000;
+#endif
+  res.secs = fade_seconds;
+  res.ticks = fade_ticks;
+  res.verb = verbose_p;
+  res.cmap = install_cmap_p;
+  res.fade = fade_p;
+  res.unfade = unfade_p;
+  res.lock_p = (lock_p && !locking_disabled_p);
+
+  fmt_time (buf, res.timeout, 1);     XmTextSetString (timeout_text, buf);
+  fmt_time (buf, res.cycle, 1);       XmTextSetString (cycle_text, buf);
+  fmt_time (buf, res.lock_time, 1);   XmTextSetString (lock_time_text, buf);
+  fmt_time (buf, res.passwd_time, 0); XmTextSetString (passwd_time_text, buf);
+  fmt_time (buf, res.secs, 0);        XmTextSetString (fade_text, buf);
+  sprintf (buf, "%u", res.ticks);     XmTextSetString (ticks_text, buf);
+
+  XmToggleButtonSetState (verbose_toggle, res.verb, True);
+  XmToggleButtonSetState (cmap_toggle, res.cmap, True);
+  XmToggleButtonSetState (fade_toggle, res.fade, True);
+  XmToggleButtonSetState (unfade_toggle, res.unfade, True);
+  XmToggleButtonSetState (lock_toggle, res.lock_p, True);
+
+  pop_up_dialog_box (resources_dialog, resources_form, 1);
+}
+
+\f
+/* The code on this page isn't actually Motif-specific */
+
+Bool dbox_up_p = False;
+Bool demo_mode_p = False;
+
+extern XtAppContext app;
+extern Widget toplevel_shell;
+extern Bool use_xidle_extension;
+extern Bool use_saver_extension;
+extern Time notice_events_timeout;
+
+extern char **screenhacks;
+extern char *demo_hack;
+
+extern void notice_events_timer P((XtPointer closure, XtIntervalId *timer));
+extern Bool handle_clientmessage P((/*XEvent *, Bool*/));
+
+void
+demo_mode ()
+{
+  dbox_up_p = True;
+  initialize_screensaver_window ();
+  raise_window (True, False);
+  make_screenhack_dialog (toplevel_shell, screenhacks);
+  while (demo_mode_p)
+    {
+      XEvent event;
+      XtAppNextEvent (app, &event);
+      switch (event.xany.type)
+       {
+       case 0:         /* synthetic "timeout" event */
+         break;
+
+       case ClientMessage:
+         handle_clientmessage (&event, False);
+         break;
+
+       case CreateNotify:
+         if (!use_xidle_extension && !use_saver_extension)
+           {
+             XtAppAddTimeOut (app, notice_events_timeout, notice_events_timer,
+                              (XtPointer) event.xcreatewindow.window);
+#ifdef DEBUG_TIMERS
+             if (verbose_p)
+               printf ("%s: starting notice_events_timer for 0x%X (%lu)\n",
+                       progname,
+                       (unsigned int) event.xcreatewindow.window,
+                       notice_events_timeout);
+#endif /* DEBUG_TIMERS */
+           }
+         break;
+
+       case ButtonPress:
+       case ButtonRelease:
+         if (!XtWindowToWidget (dpy, event.xbutton.window))
+           raise_screenhack_dialog ();
+         /* fall through */
+
+       default:
+#ifdef HAVE_SAVER_EXTENSION
+         if (event.type == saver_ext_event_number)
+           {
+             /* Get the "real" server window out of the way as soon
+                as possible. */
+             if (server_saver_window &&
+                 window_exists_p (dpy, server_saver_window))
+               XUnmapWindow (dpy, server_saver_window);
+           }
+         else
+#endif /* HAVE_SAVER_EXTENSION */
+
+         XtDispatchEvent (&event);
+         break;
+       }
+    }
+  destroy_screenhack_dialogs ();
+  initialize_screensaver_window ();
+  unblank_screen ();
+}
+
+static void
+demo_mode_hack (hack)
+     char *hack;
+{
+  if (! demo_mode_p) abort ();
+  kill_screenhack ();
+  if (! demo_hack)
+    blank_screen ();
+  demo_hack = hack;
+  spawn_screenhack (False);
+}
+
+static void
+demo_mode_done ()
+{
+  kill_screenhack ();
+  if (demo_hack)
+    unblank_screen ();
+  demo_mode_p = False;
+  dbox_up_p = False;
+  demo_hack = 0;
+}
diff --git a/driver/dialogs.c b/driver/dialogs.c
new file mode 100644 (file)
index 0000000..a403c1b
--- /dev/null
@@ -0,0 +1,765 @@
+
+/*
+** Generated by X-Designer 
+*/
+/*
+**LIBS: -lXm -lXt -lX11
+*/
+
+#if !__STDC__
+# define _NO_PROTO
+#endif
+
+#include <X11/Xatom.h>
+#include <X11/Intrinsic.h>
+#include <X11/Shell.h>
+
+#include <Xm/Xm.h>
+#include <Xm/DialogS.h>
+#include <Xm/DrawnB.h>
+#include <Xm/Form.h>
+#include <Xm/Label.h>
+#include <Xm/List.h>
+#include <Xm/PushB.h>
+#include <Xm/ScrollBar.h>
+#include <Xm/Separator.h>
+#include <Xm/TextF.h>
+#include <Xm/ToggleB.h>
+
+/* #### Hacked by hand, not generated by XDesigner */
+extern Visual *visual;
+extern int visual_depth;
+extern Colormap cmap;
+
+
+Widget passwd_dialog;
+Widget passwd_form;
+Widget roger_label;
+Widget passwd_label1;
+Widget passwd_label3;
+Widget passwd_text;
+Widget passwd_done;
+Widget passwd_cancel;
+
+Widget resources_dialog;
+Widget resources_form;
+Widget timeout_text;
+Widget cycle_text;
+Widget fade_text;
+Widget ticks_text;
+Widget lock_time_text;
+Widget passwd_time_text;
+Widget verbose_toggle;
+Widget cmap_toggle;
+Widget fade_toggle;
+Widget unfade_toggle;
+Widget lock_toggle;
+Widget res_done;
+Widget res_cancel;
+
+Widget demo_dialog;
+Widget demo_form;
+Widget label1;
+Widget label2;
+Widget text_area;
+Widget demo_list;
+Widget text_line;
+Widget vline;
+Widget next;
+Widget prev;
+Widget edit;
+Widget done;
+Widget restart;
+Widget spacer;
+
+
+void
+create_passwd_dialog( parent )
+Widget parent;
+{
+       Widget children[8];      /* Children to manage */
+       Arg al[64];           /* Arg List */
+       register int ac = 0;      /* Arg Count */
+       Widget widget4;
+       Widget widget7;
+
+
+       /* #### Hacked by hand, not generated by XDesigner */
+       ac = 0;
+       XtSetArg (al[ac], XmNvisual, visual); ac++;
+       XtSetArg (al[ac], XmNcolormap, cmap); ac++;
+       XtSetArg (al[ac], XmNdepth, visual_depth); ac++;
+
+
+       passwd_dialog = XmCreateDialogShell ( parent, "passwdDialog", al, ac );
+       passwd_form = XmCreateForm ( passwd_dialog, "passwdForm", al, ac );
+       roger_label = XmCreateDrawnButton ( passwd_form, "rogerLabel", al, ac );
+       passwd_label1 = XmCreateLabel ( passwd_form, "passwdLabel1", al, ac );
+       widget4 = XmCreateLabel ( passwd_form, "passwdLabel2", al, ac );
+       passwd_label3 = XmCreateLabel ( passwd_form, "passwdLabel3", al, ac );
+       passwd_text = XmCreateTextField ( passwd_form, "passwdText", al, ac );
+       widget7 = XmCreateSeparator ( passwd_form, "widget7", al, ac );
+       passwd_done = XmCreatePushButton ( passwd_form, "passwdDone", al, ac );
+       passwd_cancel = XmCreatePushButton ( passwd_form, "passwdCancel", al, ac );
+
+       /* #### Hacked by hand, not generated by XDesigner */
+       ac = 0;
+
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 4); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+        XtSetValues ( roger_label,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 4); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+       XtSetArg(al[ac], XmNbottomWidget, widget4); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftWidget, roger_label); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+        XtSetValues ( passwd_label1,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+       XtSetArg(al[ac], XmNbottomWidget, passwd_label3); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftWidget, roger_label); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+        XtSetValues ( widget4,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+       XtSetArg(al[ac], XmNbottomWidget, passwd_text); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftWidget, roger_label); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 30); ac++;
+        XtSetValues ( passwd_label3,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+       XtSetArg(al[ac], XmNbottomWidget, widget7); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftWidget, roger_label); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+        XtSetValues ( passwd_text,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+       XtSetArg(al[ac], XmNbottomWidget, passwd_done); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+       XtSetArg(al[ac], XmNleftWidget, roger_label); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 0); ac++;
+        XtSetValues ( widget7,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftWidget, roger_label); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+        XtSetValues ( passwd_done,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftWidget, passwd_done); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+        XtSetValues ( passwd_cancel,al, ac );
+       ac = 0;
+       children[ac++] = roger_label;
+       children[ac++] = passwd_label1;
+       children[ac++] = widget4;
+       children[ac++] = passwd_label3;
+       children[ac++] = passwd_text;
+       children[ac++] = widget7;
+       children[ac++] = passwd_done;
+       children[ac++] = passwd_cancel;
+       XtManageChildren(children, ac);
+       ac = 0;
+}
+
+
+
+void
+create_resources_dialog( parent )
+Widget parent;
+{
+       Widget children[22];      /* Children to manage */
+       Arg al[64];           /* Arg List */
+       register int ac = 0;      /* Arg Count */
+       Widget widget12;
+       Widget widget13;
+       Widget widget14;
+       Widget widget15;
+       Widget widget16;
+       Widget widget17;
+       Widget widget18;
+       Widget widget48;
+       Widget widget29;
+
+
+       /* #### Hacked by hand, not generated by XDesigner */
+       ac = 0;
+       XtSetArg (al[ac], XmNvisual, visual); ac++;
+       XtSetArg (al[ac], XmNcolormap, cmap); ac++;
+       XtSetArg (al[ac], XmNdepth, visual_depth); ac++;
+
+
+       resources_dialog = XmCreateDialogShell ( parent, "resourcesDialog", al, ac );
+       resources_form = XmCreateForm ( resources_dialog, "resourcesForm", al, ac );
+
+       /* #### Hacked by hand, not generated by XDesigner */
+       ac = 0;
+
+       widget12 = XmCreateLabel ( resources_form, "resourcesLabel", al, ac );
+       widget13 = XmCreateSeparator ( resources_form, "widget13", al, ac );
+       XtSetArg(al[ac], XmNalignment, XmALIGNMENT_END); ac++;
+       widget14 = XmCreateLabel ( resources_form, "timeoutLabel", al, ac );
+       ac = 0;
+       XtSetArg(al[ac], XmNalignment, XmALIGNMENT_END); ac++;
+       widget15 = XmCreateLabel ( resources_form, "cycleLabel", al, ac );
+       ac = 0;
+       XtSetArg(al[ac], XmNalignment, XmALIGNMENT_END); ac++;
+       widget16 = XmCreateLabel ( resources_form, "fadeSecondsLabel", al, ac );
+       ac = 0;
+       XtSetArg(al[ac], XmNalignment, XmALIGNMENT_END); ac++;
+       widget17 = XmCreateLabel ( resources_form, "fadeTicksLabel", al, ac );
+       ac = 0;
+       XtSetArg(al[ac], XmNalignment, XmALIGNMENT_END); ac++;
+       widget18 = XmCreateLabel ( resources_form, "lockLabel", al, ac );
+       ac = 0;
+       XtSetArg(al[ac], XmNalignment, XmALIGNMENT_END); ac++;
+       widget48 = XmCreateLabel ( resources_form, "passwdLabel", al, ac );
+       ac = 0;
+       timeout_text = XmCreateTextField ( resources_form, "timeoutText", al, ac );
+       cycle_text = XmCreateTextField ( resources_form, "cycleText", al, ac );
+       fade_text = XmCreateTextField ( resources_form, "fadeSecondsText", al, ac );
+       ticks_text = XmCreateTextField ( resources_form, "fadeTicksText", al, ac );
+       lock_time_text = XmCreateTextField ( resources_form, "passwdText", al, ac );
+       passwd_time_text = XmCreateTextField ( resources_form, "lockText", al, ac );
+       XtSetArg(al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
+       verbose_toggle = XmCreateToggleButton ( resources_form, "verboseToggle", al, ac );
+       ac = 0;
+       XtSetArg(al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
+       cmap_toggle = XmCreateToggleButton ( resources_form, "cmapToggle", al, ac );
+       ac = 0;
+       XtSetArg(al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
+       fade_toggle = XmCreateToggleButton ( resources_form, "fadeToggle", al, ac );
+       ac = 0;
+       XtSetArg(al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
+       unfade_toggle = XmCreateToggleButton ( resources_form, "unfadeToggle", al, ac );
+       ac = 0;
+       XtSetArg(al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
+       lock_toggle = XmCreateToggleButton ( resources_form, "lockToggle", al, ac );
+       ac = 0;
+       widget29 = XmCreateSeparator ( resources_form, "widget29", al, ac );
+       res_done = XmCreatePushButton ( resources_form, "resourcesDone", al, ac );
+       res_cancel = XmCreatePushButton ( resources_form, "resourcesCancel", al, ac );
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+        XtSetValues ( widget12,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 4); ac++;
+       XtSetArg(al[ac], XmNtopWidget, widget12); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 0); ac++;
+        XtSetValues ( widget13,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 4); ac++;
+       XtSetArg(al[ac], XmNtopWidget, widget13); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNbottomWidget, timeout_text); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 20); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+       XtSetArg(al[ac], XmNrightWidget, timeout_text); ac++;
+        XtSetValues ( widget14,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+       XtSetArg(al[ac], XmNtopWidget, cycle_text); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 0); ac++;
+       XtSetArg(al[ac], XmNbottomWidget, cycle_text); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 20); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+       XtSetArg(al[ac], XmNrightWidget, cycle_text); ac++;
+        XtSetValues ( widget15,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+       XtSetArg(al[ac], XmNtopWidget, fade_text); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 0); ac++;
+       XtSetArg(al[ac], XmNbottomWidget, fade_text); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 20); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+       XtSetArg(al[ac], XmNrightWidget, fade_text); ac++;
+        XtSetValues ( widget16,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+       XtSetArg(al[ac], XmNtopWidget, ticks_text); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 0); ac++;
+       XtSetArg(al[ac], XmNbottomWidget, ticks_text); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 20); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+       XtSetArg(al[ac], XmNrightWidget, ticks_text); ac++;
+        XtSetValues ( widget17,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+       XtSetArg(al[ac], XmNtopWidget, lock_time_text); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 0); ac++;
+       XtSetArg(al[ac], XmNbottomWidget, lock_time_text); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 19); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+       XtSetArg(al[ac], XmNrightWidget, lock_time_text); ac++;
+        XtSetValues ( widget18,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+       XtSetArg(al[ac], XmNtopWidget, passwd_time_text); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 0); ac++;
+       XtSetArg(al[ac], XmNbottomWidget, passwd_time_text); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 14); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+       XtSetArg(al[ac], XmNrightWidget, passwd_time_text); ac++;
+        XtSetValues ( widget48,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 4); ac++;
+       XtSetArg(al[ac], XmNtopWidget, widget13); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 141); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+        XtSetValues ( timeout_text,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 2); ac++;
+       XtSetArg(al[ac], XmNtopWidget, timeout_text); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+       XtSetArg(al[ac], XmNleftWidget, timeout_text); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+        XtSetValues ( cycle_text,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 2); ac++;
+       XtSetArg(al[ac], XmNtopWidget, cycle_text); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+       XtSetArg(al[ac], XmNleftWidget, cycle_text); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+        XtSetValues ( fade_text,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 2); ac++;
+       XtSetArg(al[ac], XmNtopWidget, fade_text); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+       XtSetArg(al[ac], XmNleftWidget, fade_text); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+        XtSetValues ( ticks_text,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 2); ac++;
+       XtSetArg(al[ac], XmNtopWidget, ticks_text); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+       XtSetArg(al[ac], XmNleftWidget, ticks_text); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+        XtSetValues ( lock_time_text,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 4); ac++;
+       XtSetArg(al[ac], XmNtopWidget, lock_time_text); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+       XtSetArg(al[ac], XmNleftWidget, lock_time_text); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+        XtSetValues ( passwd_time_text,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 4); ac++;
+       XtSetArg(al[ac], XmNtopWidget, widget13); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 0); ac++;
+       XtSetArg(al[ac], XmNbottomWidget, timeout_text); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 20); ac++;
+       XtSetArg(al[ac], XmNleftWidget, timeout_text); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 20); ac++;
+        XtSetValues ( verbose_toggle,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+       XtSetArg(al[ac], XmNtopWidget, cycle_text); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 0); ac++;
+       XtSetArg(al[ac], XmNbottomWidget, cycle_text); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+       XtSetArg(al[ac], XmNleftWidget, verbose_toggle); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 20); ac++;
+        XtSetValues ( cmap_toggle,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+       XtSetArg(al[ac], XmNtopWidget, fade_text); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 0); ac++;
+       XtSetArg(al[ac], XmNbottomWidget, fade_text); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+       XtSetArg(al[ac], XmNleftWidget, cmap_toggle); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 20); ac++;
+        XtSetValues ( fade_toggle,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+       XtSetArg(al[ac], XmNtopWidget, ticks_text); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 0); ac++;
+       XtSetArg(al[ac], XmNbottomWidget, ticks_text); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+       XtSetArg(al[ac], XmNleftWidget, fade_toggle); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 20); ac++;
+        XtSetValues ( unfade_toggle,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+       XtSetArg(al[ac], XmNtopWidget, lock_time_text); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 0); ac++;
+       XtSetArg(al[ac], XmNbottomWidget, lock_time_text); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+       XtSetArg(al[ac], XmNleftWidget, unfade_toggle); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 20); ac++;
+        XtSetValues ( lock_toggle,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+       XtSetArg(al[ac], XmNtopWidget, passwd_time_text); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+       XtSetArg(al[ac], XmNbottomWidget, res_done); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+        XtSetValues ( widget29,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+        XtSetValues ( res_done,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftWidget, res_done); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+        XtSetValues ( res_cancel,al, ac );
+       ac = 0;
+       children[ac++] = widget12;
+       children[ac++] = widget13;
+       children[ac++] = widget14;
+       children[ac++] = widget15;
+       children[ac++] = widget16;
+       children[ac++] = widget17;
+       children[ac++] = widget18;
+       children[ac++] = widget48;
+       children[ac++] = timeout_text;
+       children[ac++] = cycle_text;
+       children[ac++] = fade_text;
+       children[ac++] = ticks_text;
+       children[ac++] = lock_time_text;
+       children[ac++] = passwd_time_text;
+       children[ac++] = verbose_toggle;
+       children[ac++] = cmap_toggle;
+       children[ac++] = fade_toggle;
+       children[ac++] = unfade_toggle;
+       children[ac++] = lock_toggle;
+       children[ac++] = widget29;
+       children[ac++] = res_done;
+       children[ac++] = res_cancel;
+       XtManageChildren(children, ac);
+       ac = 0;
+}
+
+
+
+void
+create_demo_dialog( parent )
+Widget parent;
+{
+       Widget children[11];      /* Children to manage */
+       Arg al[64];           /* Arg List */
+       register int ac = 0;      /* Arg Count */
+       XmString xmstrings[15];    /* temporary storage for XmStrings */
+
+
+       /* #### Hacked by hand, not generated by XDesigner */
+       ac = 0;
+       XtSetArg (al[ac], XmNvisual, visual); ac++;
+       XtSetArg (al[ac], XmNcolormap, cmap); ac++;
+       XtSetArg (al[ac], XmNdepth, visual_depth); ac++;
+
+
+       demo_dialog = XmCreateDialogShell ( parent, "demoDialog", al, ac );
+       demo_form = XmCreateForm ( demo_dialog, "demoForm", al, ac );
+       label1 = XmCreateLabel ( demo_form, "label1", al, ac );
+       label2 = XmCreateLabel ( demo_form, "label2", al, ac );
+       demo_list = XmCreateScrolledList ( demo_form, "demoList", al, ac );
+       text_area = XtParent ( demo_list );
+
+       /* #### Hacked by hand, not generated by XDesigner */
+       ac = 0;
+
+
+       text_line = XmCreateTextField ( demo_form, "textLine", al, ac );
+       vline = XmCreateSeparator ( demo_form, "vline", al, ac );
+       next = XmCreatePushButton ( demo_form, "next", al, ac );
+       prev = XmCreatePushButton ( demo_form, "prev", al, ac );
+       edit = XmCreatePushButton ( demo_form, "edit", al, ac );
+       done = XmCreatePushButton ( demo_form, "done", al, ac );
+       restart = XmCreatePushButton ( demo_form, "restart", al, ac );
+       xmstrings[0] = XmStringCreateLtoR(" ", (XmStringCharSet)XmSTRING_DEFAULT_CHARSET);
+       XtSetArg(al[ac], XmNlabelString, xmstrings[0]); ac++;
+       spacer = XmCreateLabel ( demo_form, "spacer", al, ac );
+       ac = 0;
+       XmStringFree ( xmstrings [ 0 ] );
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 5); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+        XtSetValues ( label1,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 4); ac++;
+       XtSetArg(al[ac], XmNtopWidget, label1); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+        XtSetValues ( label2,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 4); ac++;
+       XtSetArg(al[ac], XmNtopWidget, label2); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+       XtSetArg(al[ac], XmNbottomWidget, text_line); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+        XtSetValues ( text_area,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+       XtSetArg(al[ac], XmNbottomWidget, vline); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+        XtSetValues ( text_line,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+       XtSetArg(al[ac], XmNbottomWidget, next); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+        XtSetValues ( vline,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 3); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+        XtSetValues ( next,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+       XtSetArg(al[ac], XmNtopWidget, next); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftWidget, next); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+        XtSetValues ( prev,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+       XtSetArg(al[ac], XmNtopWidget, prev); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftWidget, prev); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+        XtSetValues ( edit,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+       XtSetArg(al[ac], XmNtopWidget, edit); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftWidget, edit); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+        XtSetValues ( done,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+       XtSetArg(al[ac], XmNtopWidget, done); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftWidget, done); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+        XtSetValues ( restart,al, ac );
+       ac = 0;
+
+       XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+       XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+       XtSetArg(al[ac], XmNtopWidget, restart); ac++;
+       XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+       XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+       XtSetArg(al[ac], XmNleftWidget, restart); ac++;
+       XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+       XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+        XtSetValues ( spacer,al, ac );
+       ac = 0;
+       XtManageChild(demo_list);
+       children[ac++] = label1;
+       children[ac++] = label2;
+       children[ac++] = text_line;
+       children[ac++] = vline;
+       children[ac++] = next;
+       children[ac++] = prev;
+       children[ac++] = edit;
+       children[ac++] = done;
+       children[ac++] = restart;
+       children[ac++] = spacer;
+       XtManageChildren(children, ac);
+       ac = 0;
+}
+
+
diff --git a/driver/dialogs.xd b/driver/dialogs.xd
new file mode 100644 (file)
index 0000000..ad1f6da
--- /dev/null
@@ -0,0 +1,569 @@
+module 'XScreenSaver'
+applicationName = 'XScreenSaver';
+generateNameC = 'dialogs.c';
+generateNameUIL = '';
+generateNameResDB = 'dialogs.ad';
+generateUidFile = '';
+generateMask = 1507557;
+useMask = 1;
+value
+object 'passwd_dialog' : XmDialogShell {
+       arguments {
+       name = 'passwdDialog';
+       XmNtitle= 'XScreenSaver';
+       XmNallowShellResize= true;
+       };
+object 'passwd_form' : XmForm {
+       arguments {
+       name = 'passwdForm';
+       XmNautoUnmanage= false;
+       };
+object 'roger_label' : XmDrawnButton {
+       arguments {
+       name = 'rogerLabel';
+       XmNwidth= 150;
+       };
+};
+object 'passwd_label1' : XmLabel {
+       arguments {
+       name = 'passwdLabel1';
+       XmNlabelString= 'XScreenSaver %s';
+       XmNalignment= 0;
+       };
+};
+object '' : XmLabel {
+       arguments {
+       name = 'passwdLabel2';
+       XmNlabelString= 'This display is locked.';
+       XmNalignment= 0;
+       };
+};
+object 'passwd_label3' : XmLabel {
+       arguments {
+       name = 'passwdLabel3';
+       XmNlabelString= 'Please type %s\'s password to unlock it.';
+       XmNalignment= 0;
+       };
+};
+object 'passwd_text' : XmTextField {
+       arguments {
+       name = 'passwdText';
+       };
+};
+object '' : XmSeparator {
+       arguments {
+       };
+};
+object 'passwd_done' : XmPushButton {
+       arguments {
+       name = 'passwdDone';
+       XmNlabelString= 'Done';
+       };
+};
+object 'passwd_cancel' : XmPushButton {
+       arguments {
+       name = 'passwdCancel';
+       XmNlabelString= 'Cancel';
+       };
+};
+    attachments {
+    attachment {
+       XmNrightAttachment = 0 0 0;
+       XmNleftAttachment = 1 0 4;
+       XmNbottomAttachment = 1 0 4;
+       XmNtopAttachment = 1 0 4;
+    };
+    attachment {
+       XmNrightAttachment = 1 0 4;
+       XmNleftAttachment = 3 1 4;
+       XmNbottomAttachment = 3 3 4;
+       XmNtopAttachment = 1 0 4;
+    };
+    attachment {
+       XmNrightAttachment = 1 0 4;
+       XmNleftAttachment = 3 1 4;
+       XmNbottomAttachment = 3 4 4;
+       XmNtopAttachment = 0 0 0;
+    };
+    attachment {
+       XmNrightAttachment = 1 0 30;
+       XmNleftAttachment = 3 1 4;
+       XmNbottomAttachment = 3 5 4;
+       XmNtopAttachment = 0 0 0;
+    };
+    attachment {
+       XmNrightAttachment = 1 0 4;
+       XmNleftAttachment = 3 1 4;
+       XmNbottomAttachment = 3 6 4;
+       XmNtopAttachment = 0 0 0;
+    };
+    attachment {
+       XmNrightAttachment = 1 0 0;
+       XmNleftAttachment = 3 1 0;
+       XmNbottomAttachment = 3 7 4;
+       XmNtopAttachment = 0 0 0;
+    };
+    attachment {
+       XmNrightAttachment = 0 0 0;
+       XmNleftAttachment = 3 1 4;
+       XmNbottomAttachment = 1 0 4;
+       XmNtopAttachment = 0 0 0;
+    };
+    attachment {
+       XmNrightAttachment = 0 0 0;
+       XmNleftAttachment = 3 7 4;
+       XmNbottomAttachment = 1 0 4;
+       XmNtopAttachment = 0 0 0;
+    };
+    };
+};
+};
+object 'resources_dialog' : XmDialogShell {
+       arguments {
+       name = 'resourcesDialog';
+       XmNtitle= 'XScreenSaver';
+       XmNallowShellResize= true;
+       };
+object 'resources_form' : XmForm {
+       arguments {
+       name = 'resourcesForm';
+       XmNautoUnmanage= false;
+       };
+object '' : XmLabel {
+       arguments {
+       name = 'resourcesLabel';
+       XmNlabelString= 'XScreenSaver Parameters';
+       };
+};
+object '' : XmSeparator {
+       arguments {
+       };
+};
+object '' : XmLabel {
+       arguments {
+       name = 'timeoutLabel';
+       XmNlabelString= 'Timeout Minutes';
+       XmNalignment= * 2;
+       };
+};
+object '' : XmLabel {
+       arguments {
+       name = 'cycleLabel';
+       XmNlabelString= 'Cycle Seconds';
+       XmNalignment= * 2;
+       };
+};
+object '' : XmLabel {
+       arguments {
+       name = 'fadeSecondsLabel';
+       XmNlabelString= 'Fade Seconds';
+       XmNalignment= * 2;
+       };
+};
+object '' : XmLabel {
+       arguments {
+       name = 'fadeTicksLabel';
+       XmNlabelString= 'Fade Ticks';
+       XmNalignment= * 2;
+       };
+};
+object '' : XmLabel {
+       arguments {
+       name = 'lockLabel';
+       XmNlabelString= 'Lock Timeout';
+       XmNalignment= * 2;
+       };
+};
+object '' : XmLabel {
+       arguments {
+       name = 'passwdLabel';
+       XmNlabelString= 'Password Timeout';
+       XmNalignment= * 2;
+       };
+};
+object 'timeout_text' : XmTextField {
+       arguments {
+       name = 'timeoutText';
+       XmNcolumns= 5;
+       };
+};
+object 'cycle_text' : XmTextField {
+       arguments {
+       name = 'cycleText';
+       XmNcolumns= 5;
+       };
+};
+object 'fade_text' : XmTextField {
+       arguments {
+       name = 'fadeSecondsText';
+       XmNcolumns= 5;
+       };
+};
+object 'ticks_text' : XmTextField {
+       arguments {
+       name = 'fadeTicksText';
+       XmNcolumns= 5;
+       };
+};
+object 'lock_time_text' : XmTextField {
+       arguments {
+       name = 'passwdText';
+       XmNcolumns= 5;
+       };
+};
+object 'passwd_time_text' : XmTextField {
+       arguments {
+       name = 'lockText';
+       XmNcolumns= 5;
+       };
+};
+object 'verbose_toggle' : XmToggleButton {
+       arguments {
+       name = 'verboseToggle';
+       XmNlabelString= 'Verbose';
+       XmNalignment= * 0;
+       };
+};
+object 'cmap_toggle' : XmToggleButton {
+       arguments {
+       name = 'cmapToggle';
+       XmNlabelString= 'Install Colormap';
+       XmNalignment= * 0;
+       };
+};
+object 'fade_toggle' : XmToggleButton {
+       arguments {
+       name = 'fadeToggle';
+       XmNlabelString= 'Fade Colormap';
+       XmNalignment= * 0;
+       };
+};
+object 'unfade_toggle' : XmToggleButton {
+       arguments {
+       name = 'unfadeToggle';
+       XmNlabelString= 'Unfade Colormap';
+       XmNalignment= * 0;
+       };
+};
+object 'lock_toggle' : XmToggleButton {
+       arguments {
+       name = 'lockToggle';
+       XmNlabelString= 'Require Password';
+       XmNalignment= * 0;
+       };
+};
+object '' : XmSeparator {
+       arguments {
+       };
+};
+object 'res_done' : XmPushButton {
+       arguments {
+       name = 'resourcesDone';
+       XmNlabelString= 'Done';
+       };
+};
+object 'res_cancel' : XmPushButton {
+       arguments {
+       name = 'resourcesCancel';
+       XmNlabelString= 'Cancel';
+       };
+};
+    attachments {
+    attachment {
+       XmNrightAttachment = 1 0 4;
+       XmNleftAttachment = 1 0 4;
+       XmNtopAttachment = 1 0 4;
+    };
+    attachment {
+       XmNrightAttachment = 1 0 0;
+       XmNleftAttachment = 1 0 0;
+       XmNbottomAttachment = 0 0 0;
+       XmNtopAttachment = 3 1 4;
+    };
+    attachment {
+       XmNrightAttachment = 3 9 4;
+       XmNleftAttachment = 1 0 20;
+       XmNbottomAttachment = 4 9;
+       XmNtopAttachment = 3 2 4;
+    };
+    attachment {
+       XmNrightAttachment = 3 10 4;
+       XmNleftAttachment = 1 0 20;
+       XmNbottomAttachment = 4 10 0;
+       XmNtopAttachment = 4 10 0;
+    };
+    attachment {
+       XmNrightAttachment = 3 11 4;
+       XmNleftAttachment = 1 0 20;
+       XmNbottomAttachment = 4 11 0;
+       XmNtopAttachment = 4 11 0;
+    };
+    attachment {
+       XmNrightAttachment = 3 12 4;
+       XmNleftAttachment = 1 0 20;
+       XmNbottomAttachment = 4 12 0;
+       XmNtopAttachment = 4 12 0;
+    };
+    attachment {
+       XmNrightAttachment = 3 13 4;
+       XmNleftAttachment = 1 0 19;
+       XmNbottomAttachment = 4 13 0;
+       XmNtopAttachment = 4 13 0;
+    };
+    attachment {
+       XmNrightAttachment = 3 14 4;
+       XmNleftAttachment = 1 0 14;
+       XmNbottomAttachment = 4 14 0;
+       XmNtopAttachment = 4 14 0;
+    };
+    attachment {
+       XmNrightAttachment = 0 0 0;
+       XmNleftAttachment = 1 0 141;
+       XmNbottomAttachment = 0 0 0;
+       XmNtopAttachment = 3 2 4;
+    };
+    attachment {
+       XmNrightAttachment = 0 0 0;
+       XmNleftAttachment = 4 9 0;
+       XmNbottomAttachment = 0 0 0;
+       XmNtopAttachment = 3 9 2;
+    };
+    attachment {
+       XmNrightAttachment = 0 0 0;
+       XmNleftAttachment = 4 10 0;
+       XmNbottomAttachment = 0 0 0;
+       XmNtopAttachment = 3 10 2;
+    };
+    attachment {
+       XmNrightAttachment = 0 0 0;
+       XmNleftAttachment = 4 11 0;
+       XmNbottomAttachment = 0 0 0;
+       XmNtopAttachment = 3 11 2;
+    };
+    attachment {
+       XmNrightAttachment = 0 0 0;
+       XmNleftAttachment = 4 12 0;
+       XmNbottomAttachment = 0 0 0;
+       XmNtopAttachment = 3 12 2;
+    };
+    attachment {
+       XmNrightAttachment = 0 0 0;
+       XmNleftAttachment = 4 13 0;
+       XmNbottomAttachment = 0 0 0;
+       XmNtopAttachment = 3 13 4;
+    };
+    attachment {
+       XmNrightAttachment = 1 0 20;
+       XmNleftAttachment = 3 9 20;
+       XmNbottomAttachment = 4 9 0;
+       XmNtopAttachment = 3 2 4;
+    };
+    attachment {
+       XmNrightAttachment = 1 0 20;
+       XmNleftAttachment = 4 15 0;
+       XmNbottomAttachment = 4 10 0;
+       XmNtopAttachment = 4 10 0;
+    };
+    attachment {
+       XmNrightAttachment = 1 0 20;
+       XmNleftAttachment = 4 16 0;
+       XmNbottomAttachment = 4 11 0;
+       XmNtopAttachment = 4 11 0;
+    };
+    attachment {
+       XmNrightAttachment = 1 0 20;
+       XmNleftAttachment = 4 17 0;
+       XmNbottomAttachment = 4 12 0;
+       XmNtopAttachment = 4 12 0;
+    };
+    attachment {
+       XmNrightAttachment = 1 0 20;
+       XmNleftAttachment = 4 18 0;
+       XmNbottomAttachment = 4 13 0;
+       XmNtopAttachment = 4 13 0;
+    };
+    attachment {
+       XmNrightAttachment = 1 0;
+       XmNleftAttachment = 1 0;
+       XmNbottomAttachment = 3 21 4;
+       XmNtopAttachment = 3 14 0;
+    };
+    attachment {
+       XmNrightAttachment = 0 0 0;
+       XmNleftAttachment = 1 0 4;
+       XmNbottomAttachment = 1 0 4;
+       XmNtopAttachment = 0 0 0;
+    };
+    attachment {
+       XmNrightAttachment = 0 0 0;
+       XmNleftAttachment = 3 21 4;
+       XmNbottomAttachment = 1 0 4;
+       XmNtopAttachment = 0 0 0;
+    };
+    };
+};
+};
+object 'demo_dialog' : XmDialogShell {
+       arguments {
+       name = 'demoDialog';
+       XmNtitle= 'XScreenSaver';
+       XmNmaxWidth= 500;
+       XmNallowShellResize= true;
+       };
+object 'demo_form' : XmForm {
+       arguments {
+       name = 'demoForm';
+       XmNautoUnmanage= false;
+       };
+object 'label1' : XmLabel {
+       arguments {
+       name = 'label1';
+       XmNlabelString= 'XScreenSaver %s';
+       };
+};
+object 'label2' : XmLabel {
+       arguments {
+       name = 'label2';
+       XmNlabelString= 'Copyright Â© 1991-1994 by Jamie Zawinski <jwz@netscape.com>';
+       };
+};
+object 'text_area' : XmScrolledList {
+       arguments {
+       name = 'textArea';
+       };
+object '' : XmScrollBar {
+       arguments {
+       name = 'ListhScrollBar';
+       };
+};
+object '' : XmScrollBar {
+       arguments {
+       name = 'ListvScrollBar';
+       };
+};
+object 'demo_list' : XmList {
+       arguments {
+       name = 'demoList';
+       XmNvisibleItemCount= 10;
+       XmNautomaticSelection= true;
+       XmNlistSizePolicy= 2;
+       };
+};
+};
+object 'text_line' : XmTextField {
+       arguments {
+       name = 'textLine';
+       };
+};
+object 'vline' : XmSeparator {
+       arguments {
+       name = 'vline';
+       };
+};
+object 'next' : XmPushButton {
+       arguments {
+       name = 'next';
+       XmNlabelString= 'Run Next';
+       };
+};
+object 'prev' : XmPushButton {
+       arguments {
+       name = 'prev';
+       XmNlabelString= 'Run Previous';
+       };
+};
+object 'edit' : XmPushButton {
+       arguments {
+       name = 'edit';
+       XmNlabelString= 'Edit Parameters';
+       };
+};
+object 'done' : XmPushButton {
+       arguments {
+       name = 'done';
+       XmNlabelString= 'Exit Demo Mode';
+       };
+};
+object 'restart' : XmPushButton {
+       arguments {
+       name = 'restart';
+       XmNlabelString= 'Restart Screen Saver';
+       };
+};
+object 'spacer' : XmLabel {
+       arguments {
+       name = 'spacer';
+       XmNlabelString= * ' ';
+       };
+};
+    attachments {
+    attachment {
+       XmNrightAttachment = 1 0 4;
+       XmNleftAttachment = 1 0 4;
+       XmNbottomAttachment = 0 0 0;
+       XmNtopAttachment = 1 0 5;
+    };
+    attachment {
+       XmNrightAttachment = 1 0 4;
+       XmNleftAttachment = 1 0 4;
+       XmNbottomAttachment = 0 0 0;
+       XmNtopAttachment = 3 1 4;
+    };
+    attachment {
+       XmNrightAttachment = 1 0 4;
+       XmNleftAttachment = 1 0 4;
+       XmNbottomAttachment = 3 4 4;
+       XmNtopAttachment = 3 2 4;
+    };
+    attachment {
+       XmNrightAttachment = 1 0 4;
+       XmNleftAttachment = 1 0 4;
+       XmNbottomAttachment = 3 5 4;
+       XmNtopAttachment = 0 0 0;
+    };
+    attachment {
+       XmNrightAttachment = 1 0 4;
+       XmNleftAttachment = 1 0 4;
+       XmNbottomAttachment = 3 6 4;
+       XmNtopAttachment = 0 0 0;
+    };
+    attachment {
+       XmNrightAttachment = 0 0 0;
+       XmNleftAttachment = 1 0 3;
+       XmNbottomAttachment = 1 0 4;
+       XmNtopAttachment = 0 0 0;
+    };
+    attachment {
+       XmNrightAttachment = 0 0 0;
+       XmNleftAttachment = 3 6 4;
+       XmNbottomAttachment = 1 0 4;
+       XmNtopAttachment = 4 6 0;
+    };
+    attachment {
+       XmNrightAttachment = 0 0 0;
+       XmNleftAttachment = 3 7 4;
+       XmNbottomAttachment = 1 0 4;
+       XmNtopAttachment = 4 7 0;
+    };
+    attachment {
+       XmNrightAttachment = 0 0 0;
+       XmNleftAttachment = 3 8 4;
+       XmNbottomAttachment = 1 0 4;
+       XmNtopAttachment = 4 8 0;
+    };
+    attachment {
+       XmNrightAttachment = 0 0 0;
+       XmNleftAttachment = 3 9 4;
+       XmNbottomAttachment = 1 0 4;
+       XmNtopAttachment = 4 9 0;
+    };
+    attachment {
+       XmNrightAttachment = 1 0 4;
+       XmNleftAttachment = 3 10 4;
+       XmNbottomAttachment = 1 0 4;
+       XmNtopAttachment = 4 10 0;
+    };
+    };
+};
+};
+end module;
diff --git a/driver/lock.c b/driver/lock.c
new file mode 100644 (file)
index 0000000..e4ef982
--- /dev/null
@@ -0,0 +1,676 @@
+/*    xscreensaver, Copyright (c) 1993-1995 Jamie Zawinski <jwz@netscape.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.
+ */
+
+/* #### If anyone ever finishes the Athena locking code, remove this.
+   But until then, locking requires Motif.
+ */
+#if defined(NO_MOTIF) && !defined(NO_LOCKING)
+# define NO_LOCKING
+#endif
+
+
+#ifndef NO_LOCKING
+
+#if __STDC__
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#endif
+
+#ifdef  HAVE_SHADOW
+#include <shadow.h>
+#endif
+
+#include <pwd.h>
+#include <stdio.h>
+
+#include <X11/Intrinsic.h>
+
+#include "xscreensaver.h"
+
+extern char *screensaver_version;
+extern char *progname;
+extern XtAppContext app;
+extern Bool verbose_p;
+
+#ifdef SCO
+/* SCO has some kind of goofy, nonstandard security crap.  This stuff was
+   donated by one of their victims, I mean users, Didier Poirot <dp@chorus.fr>.
+ */
+# include <sys/security.h>
+# include <sys/audit.h>
+# include <prot.h>
+#endif
+
+#if !__STDC__
+# define _NO_PROTO
+#endif
+
+#ifdef NO_MOTIF
+
+# include <X11/StringDefs.h>
+# include <X11/Xaw/Text.h>
+# include <X11/Xaw/Label.h>
+
+#else /* Motif */
+
+# include <Xm/Xm.h>
+# include <Xm/List.h>
+# include <Xm/TextF.h>
+
+#endif /* Motif */
+
+Time passwd_timeout;
+
+extern Widget passwd_dialog;
+extern Widget passwd_form;
+extern Widget roger_label;
+extern Widget passwd_label1;
+extern Widget passwd_label3;
+extern Widget passwd_text;
+extern Widget passwd_done;
+extern Widget passwd_cancel;
+
+extern create_passwd_dialog P((Widget));
+extern void ungrab_keyboard_and_mouse P((void));
+
+static enum { pw_read, pw_ok, pw_fail, pw_cancel, pw_time } passwd_state;
+static char typed_passwd [1024];
+
+static char root_passwd [255];
+static char user_passwd [255];
+
+#ifdef HAVE_SHADOW
+# define PWTYPE struct spwd *
+# define PWSLOT sp_pwdp
+# define GETPW  getspnam
+#else
+# define PWTYPE struct passwd *
+# define PWSLOT pw_passwd
+# define GETPW  getpwnam
+#endif
+
+#ifdef SCO
+# define PRPWTYPE struct pr_passwd *
+# define GETPRPW getprpwnam
+#endif
+
+Bool
+lock_init ()
+{
+  Bool ok = True;
+  char *u;
+  PWTYPE p = GETPW ("root");
+
+#ifdef SCO
+  PRPWTYPE prpwd = GETPRPW ("root");
+  if (prpwd && *prpwd->ufld.fd_encrypt)
+    strcpy (root_passwd, prpwd->ufld.fd_encrypt);
+#else /* !SCO */
+  if (p && p->PWSLOT && p->PWSLOT[0] != '*')
+    strcpy (root_passwd, p->PWSLOT);
+#endif /* !SCO */
+  else
+    {
+      fprintf (stderr, "%s: couldn't get root's password\n", progname);
+      strcpy (root_passwd, "*");
+    }
+
+  /* It has been reported that getlogin() returns the wrong user id on some
+     very old SGI systems... */
+  u = (char *) getlogin ();
+  if (u)
+    {
+#ifdef SCO
+      prpwd = GETPRPW (u);
+#endif /* SCO */
+      p = GETPW (u);
+    }
+  else
+    {
+      /* getlogin() fails if not attached to a terminal;
+        in that case, use getpwuid(). */
+      struct passwd *p2 = getpwuid (getuid ());
+      u = p2->pw_name;
+#ifdef HAVE_SHADOW
+      p = GETPW (u);
+#else
+      p = p2;
+#endif
+    }
+
+#ifdef SCO
+  if (prpwd && *prpwd->ufld.fd_encrypt)
+    strcpy (user_passwd, prpwd->ufld.fd_encrypt);
+#else /* !SCO */
+  if (p && p->PWSLOT &&
+      /* p->PWSLOT[0] != '*' */                /* sensible */
+      (strlen (p->PWSLOT) > 4)         /* solaris */
+      )
+    strcpy (user_passwd, p->PWSLOT);
+#endif /* !SCO */
+  else
+    {
+      fprintf (stderr, "%s: couldn't get password of \"%s\"\n", progname, u);
+      strcpy (user_passwd, "*");
+      ok = False;
+    }
+  return ok;
+}
+
+
+\f
+#if defined(NO_MOTIF) || (XmVersion >= 1002)
+   /* The `destroy' bug apears to be fixed as of Motif 1.2.1, but
+      the `verify-callback' bug is still present. */
+# define DESTROY_WORKS
+#endif
+
+static void
+passwd_cancel_cb (button, client_data, call_data)
+     Widget button;
+     XtPointer client_data, call_data;
+{
+  passwd_state = pw_cancel;
+}
+
+static void
+passwd_done_cb (button, client_data, call_data)
+     Widget button;
+     XtPointer client_data, call_data;
+{
+  if (passwd_state != pw_read) return; /* already done */
+  if (!strcmp ((char *) crypt (typed_passwd, user_passwd), user_passwd))
+    passwd_state = pw_ok;
+  /* do not allow root to have empty passwd */
+  else if (typed_passwd [0] &&
+          !strcmp ((char *) crypt (typed_passwd, root_passwd), root_passwd))
+    passwd_state = pw_ok;
+  else
+    passwd_state = pw_fail;
+}
+
+#if !defined(NO_MOTIF) && defined(VERIFY_CALLBACK_WORKS)
+
+  /* ####  It looks to me like adding any modifyVerify callback causes
+     ####  Motif 1.1.4 to free the the TextF_Value() twice.  I can't see
+     ####  the bug in the Motif source, but Purify complains, even if
+     ####  check_passwd_cb() is a no-op.
+
+     ####  Update: Motif 1.2.1 also loses, but in a different way: it
+     ####  writes beyond the end of a malloc'ed block in ModifyVerify().
+     ####  Probably this block is the text field's text.
+   */
+
+static void 
+check_passwd_cb (button, client_data, call_data)
+     Widget button;
+     XtPointer client_data, call_data;
+{
+  XmTextVerifyCallbackStruct *vcb = (XmTextVerifyCallbackStruct *) call_data;
+
+  if (passwd_state != pw_read)
+    return;
+  else if (vcb->reason == XmCR_ACTIVATE)
+    {
+      passwd_done_cb (0, 0, 0);
+    }
+  else if (vcb->text->length > 1)      /* don't allow "paste" operations */
+    {
+      vcb->doit = False;
+    }
+  else if (vcb->text->ptr != 0)
+    {
+      int i;
+      strncat (typed_passwd, vcb->text->ptr, vcb->text->length);
+      typed_passwd [vcb->endPos + vcb->text->length] = 0;
+      for (i = 0; i < vcb->text->length; i++)
+       vcb->text->ptr [i] = '*';
+    }
+}
+
+#else /* !VERIFY_CALLBACK_WORKS */
+
+static void keypress();
+static void backspace();
+static void kill_line();
+static void done();
+
+static XtActionsRec actions[] = {{"keypress",  keypress},
+                                {"backspace", backspace},
+                                {"kill_line", kill_line},
+                                {"done",      done}
+                               };
+
+#if 0 /* oh fuck, why doesn't this work? */
+static char translations[] = "\
+<Key>BackSpace:                backspace()\n\
+<Key>Delete:           backspace()\n\
+Ctrl<Key>H:            backspace()\n\
+Ctrl<Key>U:            kill_line()\n\
+Ctrl<Key>X:            kill_line()\n\
+Ctrl<Key>J:            done()\n\
+Ctrl<Key>M:            done()\n\
+<Key>:                 keypress()\n\
+";
+#else
+static char translations[] = "<Key>:keypress()";
+#endif
+
+static void
+text_field_set_string (widget, text, position)
+     Widget widget;
+     char *text;
+     int position;
+{
+#ifdef NO_MOTIF
+  XawTextBlock block;
+  block.firstPos = 0;
+  block.length = strlen (text);
+  block.ptr = text;
+  block.format = 0;
+  XawTextReplace (widget, 0, -1, &block);
+  XawTextSetInsertionPoint (widget, position);
+#else  /* !NO_MOTIF */
+  XmTextFieldSetString (widget, text);
+  XmTextFieldSetInsertionPosition (widget, position);
+#endif /* !NO_MOTIF */
+}
+
+
+static void
+keypress (w, event, argv, argc)
+     Widget w;
+     XEvent *event;
+     String *argv;
+     Cardinal *argc;
+{
+  int i, j;
+  char s [sizeof (typed_passwd)];
+  int size = XLookupString ((XKeyEvent *) event, s, sizeof (s), 0, 0);
+  if (size != 1) return;
+
+  /* hack because I can't get translations to dance to my tune... */
+  if (*s == '\010') { backspace (w, event, argv, argc); return; }
+  if (*s == '\177') { backspace (w, event, argv, argc); return; }
+  if (*s == '\025') { kill_line (w, event, argv, argc); return; }
+  if (*s == '\030') { kill_line (w, event, argv, argc); return; }
+  if (*s == '\012') { done (w, event, argv, argc); return; }
+  if (*s == '\015') { done (w, event, argv, argc); return; }
+
+  i = j = strlen (typed_passwd);
+  typed_passwd [i] = *s;
+  s [++i] = 0;
+  while (i--)
+    s [i] = '*';
+
+  text_field_set_string (passwd_text, s, j + 1);
+}
+
+static void
+backspace (w, event, argv, argc)
+     Widget w;
+     XEvent *event;
+     String *argv;
+     Cardinal *argc;
+{
+  char s [sizeof (typed_passwd)];
+  int i = strlen (typed_passwd);
+  int j = i;
+  if (i == 0)
+    return;
+  typed_passwd [--i] = 0;
+  s [i] = 0;
+  while (i--)
+    s [i] = '*';
+
+  text_field_set_string (passwd_text, s, j + 1);
+}
+
+static void
+kill_line (w, event, argv, argc)
+     Widget w;
+     XEvent *event;
+     String *argv;
+     Cardinal *argc;
+{
+  memset (typed_passwd, 0, sizeof (typed_passwd));
+  text_field_set_string (passwd_text, "", 0);
+}
+
+static void
+done (w, event, argv, argc)
+     Widget w;
+     XEvent *event;
+     String *argv;
+     Cardinal *argc;
+{
+  passwd_done_cb (w, 0, 0);
+}
+
+#endif /* !VERIFY_CALLBACK_WORKS || NO_MOTIF */
+
+static void
+format_into_label (widget, string)
+     Widget widget;
+     char *string;
+{
+  char *label;
+  char buf [255];
+  Arg av[10];
+  int ac = 0;
+
+#ifdef NO_MOTIF
+  XtSetArg (av [ac], XtNlabel, &label); ac++;
+  XtGetValues (widget, av, ac);
+#else  /* Motif */
+  XmString xm_label = 0;
+  XmString new_xm_label;
+  XtSetArg (av [ac], XmNlabelString, &xm_label); ac++;
+  XtGetValues (widget, av, ac);
+  XmStringGetLtoR (xm_label, XmSTRING_DEFAULT_CHARSET, &label);
+#endif /* Motif */
+
+  if (!label || !strcmp (label, XtName (widget)))
+    strcpy (buf, "ERROR: RESOURCES ARE NOT INSTALLED CORRECTLY");
+  else
+    sprintf (buf, label, string);
+
+  ac = 0;
+
+#ifdef NO_MOTIF
+  XtSetArg (av [ac], XtNlabel, buf); ac++;
+#else  /* Motif */
+  new_xm_label = XmStringCreate (buf, XmSTRING_DEFAULT_CHARSET);
+  XtSetArg (av [ac], XmNlabelString, new_xm_label); ac++;
+#endif /* Motif */
+
+  XtSetValues (widget, av, ac);
+#ifndef NO_MOTIF
+  XmStringFree (new_xm_label);
+#endif
+  XtFree (label);
+}
+
+#if __STDC__
+extern void skull (Display *, Window, GC, GC, int, int, int, int);
+#endif
+
+static void
+roger (button, client_data, call_data)
+     Widget button;
+     XtPointer client_data, call_data;
+{
+  Display *dpy = XtDisplay (button);
+  Screen *screen = XtScreen (button);
+  Window window = XtWindow (button);
+  Arg av [10];
+  int ac = 0;
+  XGCValues gcv;
+  Colormap cmap;
+  GC draw_gc, erase_gc;
+  unsigned int fg, bg;
+  int x, y, size;
+  XWindowAttributes xgwa;
+  XGetWindowAttributes (dpy, window, &xgwa);
+  cmap = xgwa.colormap;
+  if (xgwa.width > xgwa.height) size = xgwa.height;
+  else size = xgwa.width;
+  if (size > 40) size -= 30;
+  x = (xgwa.width - size) / 2;
+  y = (xgwa.height - size) / 2;
+  XtSetArg (av [ac], XtNforeground, &fg); ac++;
+  XtSetArg (av [ac], XtNbackground, &bg); ac++;
+  XtGetValues (button, av, ac);
+  /* if it's black on white, swap it cause it looks better (hack hack) */
+  if (fg == BlackPixelOfScreen (screen) && bg == WhitePixelOfScreen (screen))
+    fg = WhitePixelOfScreen (screen), bg = BlackPixelOfScreen (screen);
+  gcv.foreground = bg;
+  erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+  gcv.foreground = fg;
+  draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+  XFillRectangle (dpy, window, erase_gc, 0, 0, xgwa.width, xgwa.height);
+  skull (dpy, window, draw_gc, erase_gc, x, y, size, size);
+  XFreeGC (dpy, draw_gc);
+  XFreeGC (dpy, erase_gc);
+}
+
+#ifdef NO_MOTIF
+
+static void
+make_passwd_dialog (parent)
+     Widget parent;
+{
+  abort (); /* #### */
+}
+
+#else  /* Motif */
+
+static void
+make_passwd_dialog (parent)
+     Widget parent;
+{
+  struct passwd *pw;
+  create_passwd_dialog (parent);
+
+  XtAddCallback (passwd_done, XmNactivateCallback, passwd_done_cb, 0);
+  XtAddCallback (passwd_cancel, XmNactivateCallback, passwd_cancel_cb, 0);
+  XtAddCallback (roger_label, XmNexposeCallback, roger, 0);
+
+#ifdef VERIFY_CALLBACK_WORKS
+  XtAddCallback (passwd_text, XmNmodifyVerifyCallback, check_passwd_cb, 0);
+  XtAddCallback (passwd_text, XmNactivateCallback, check_passwd_cb, 0);
+#else
+  XtAddCallback (passwd_text, XmNactivateCallback, passwd_done_cb, 0);
+  XtOverrideTranslations (passwd_text, XtParseTranslationTable (translations));
+#endif
+
+#if !defined(NO_MOTIF) && (XmVersion >= 1002)
+  /* The focus stuff changed around; this didn't exist in 1.1.5. */
+  XtVaSetValues (passwd_form, XmNinitialFocus, passwd_text, 0);
+#endif
+
+  /* Another random thing necessary in 1.2.1 but not 1.1.5... */
+  XtVaSetValues (roger_label, XmNborderWidth, 2, 0);
+
+  pw = getpwuid (getuid ());
+  format_into_label (passwd_label3, (pw->pw_name ? pw->pw_name : "???"));
+  format_into_label (passwd_label1, screensaver_version);
+}
+
+#endif /* Motif */
+
+extern void idle_timer ();
+
+static int passwd_idle_timer_tick;
+static XtIntervalId id;
+
+static void
+passwd_idle_timer (junk1, junk2)
+     void *junk1;
+     XtPointer junk2;
+{
+  Display *dpy = XtDisplay (passwd_form);
+  Window window = XtWindow (passwd_form);
+  static Dimension x, y, d, s, ss;
+  static GC gc = 0;
+  int max = passwd_timeout / 1000;
+
+  idle_timer (junk1, junk2);
+
+  if (passwd_idle_timer_tick == max)  /* first time */
+    {
+      Arg av [10];
+      int ac = 0;
+      XGCValues gcv;
+      unsigned long fg, bg;
+      XtSetArg (av [ac], XtNheight, &d); ac++;
+      XtGetValues (passwd_done, av, ac);
+      ac = 0;
+      XtSetArg (av [ac], XtNwidth, &x); ac++;
+      XtSetArg (av [ac], XtNheight, &y); ac++;
+      XtSetArg (av [ac], XtNforeground, &fg); ac++;
+      XtSetArg (av [ac], XtNbackground, &bg); ac++;
+      XtGetValues (passwd_form, av, ac);
+      x -= d;
+      y -= d;
+      d -= 4;
+      gcv.foreground = fg;
+      if (gc) XFreeGC (dpy, gc);
+      gc = XCreateGC (dpy, window, GCForeground, &gcv);
+      s = 360*64 / (passwd_idle_timer_tick - 1);
+      ss = 90*64;
+      XFillArc (dpy, window, gc, x, y, d, d, 0, 360*64);
+      XSetForeground (dpy, gc, bg);
+      x += 1;
+      y += 1;
+      d -= 2;
+    }
+
+  if (--passwd_idle_timer_tick)
+    {
+      id = XtAppAddTimeOut (app, 1000, passwd_idle_timer, 0);
+      XFillArc (dpy, window, gc, x, y, d, d, ss, s);
+      ss += s;
+    }
+}
+
+extern void pop_up_dialog_box ();
+extern int BadWindow_ehandler ();
+
+static Bool
+pop_passwd_dialog (parent)
+     Widget parent;
+{
+  Display *dpy = XtDisplay (passwd_dialog);
+  Window focus;
+  int revert_to;
+  typed_passwd [0] = 0;
+  passwd_state = pw_read;
+  text_field_set_string (passwd_text, "", 0);
+
+  XGetInputFocus (dpy, &focus, &revert_to);
+#ifndef DESTROY_WORKS
+  /* This fucker blows up if we destroy the widget.  I can't figure
+     out why.  The second destroy phase dereferences freed memory...
+     So we just keep it around; but unrealizing or unmanaging it
+     doesn't work right either, so we hack the window directly. FMH.
+   */
+  if (XtWindow (passwd_form))
+    XMapRaised (dpy, XtWindow (passwd_dialog));
+#endif
+
+  pop_up_dialog_box (passwd_dialog, passwd_form, 2);
+  XtManageChild (passwd_form);
+
+#if !defined(NO_MOTIF) && (XmVersion < 1002)
+  /* The focus stuff changed around; this causes problems in 1.2.1
+     but is necessary in 1.1.5. */
+  XmProcessTraversal (passwd_text, XmTRAVERSE_CURRENT);
+#endif
+
+  passwd_idle_timer_tick = passwd_timeout / 1000;
+  id = XtAppAddTimeOut (app, 1000, passwd_idle_timer, 0);
+
+
+  XGrabServer (dpy);                           /* ############ DANGER! */
+
+  /* this call to ungrab used to be in main_loop() - see comment in
+      xscreensaver.c around line 696. */
+  ungrab_keyboard_and_mouse ();
+
+  while (passwd_state == pw_read)
+    {
+      XEvent event;
+      XtAppNextEvent (app, &event);
+      /* wait for timer event */
+      if (event.xany.type == 0 && passwd_idle_timer_tick == 0)
+       passwd_state = pw_time;
+      XtDispatchEvent (&event);
+    }
+  XUngrabServer (dpy);
+  XSync (dpy, False);                          /* ###### (danger over) */
+
+  if (passwd_state != pw_time)
+    XtRemoveTimeOut (id);
+
+  if (passwd_state != pw_ok)
+    {
+      char *lose;
+      switch (passwd_state)
+       {
+       case pw_time: lose = "Timed out!"; break;
+       case pw_fail: lose = "Sorry!"; break;
+       case pw_cancel: lose = 0; break;
+       default: abort ();
+       }
+#ifndef NO_MOTIF
+      XmProcessTraversal (passwd_cancel, 0); /* turn off I-beam */
+#endif
+      if (lose)
+       {
+         text_field_set_string (passwd_text, lose, strlen (lose) + 1);
+         passwd_idle_timer_tick = 1;
+         id = XtAppAddTimeOut (app, 3000, passwd_idle_timer, 0);
+         while (1)
+           {
+             XEvent event;
+             XtAppNextEvent (app, &event);
+             if (event.xany.type == 0 &&       /* wait for timer event */
+                 passwd_idle_timer_tick == 0)
+               break;
+             XtDispatchEvent (&event);
+           }
+       }
+    }
+  memset (typed_passwd, 0, sizeof (typed_passwd));
+  text_field_set_string (passwd_text, "", 0);
+  XtSetKeyboardFocus (parent, None);
+
+#ifdef DESTROY_WORKS
+  XtDestroyWidget (passwd_dialog);
+  passwd_dialog = 0;
+#else
+  XUnmapWindow (XtDisplay (passwd_dialog), XtWindow (passwd_dialog));
+#endif
+  {
+    int (*old_handler) ();
+    old_handler = XSetErrorHandler (BadWindow_ehandler);
+    /* I don't understand why this doesn't refocus on the old selected
+       window when MWM is running in click-to-type mode.  The value of
+       `focus' seems to be correct. */
+    XSetInputFocus (dpy, focus, revert_to, CurrentTime);
+    XSync (dpy, False);
+    XSetErrorHandler (old_handler);
+  }
+
+  return (passwd_state == pw_ok ? True : False);
+}
+
+Bool
+unlock_p (parent)
+     Widget parent;
+{
+  static Bool initted = False;
+  if (! initted)
+    {
+#ifndef VERIFY_CALLBACK_WORKS
+      XtAppAddActions (app, actions, XtNumber (actions));
+#endif
+      passwd_dialog = 0;
+      initted = True;
+    }
+  if (! passwd_dialog)
+    make_passwd_dialog (parent);
+  return pop_passwd_dialog (parent);
+}
+
+#endif /* !NO_LOCKING */
diff --git a/driver/stderr.c b/driver/stderr.c
new file mode 100644 (file)
index 0000000..7d5fc13
--- /dev/null
@@ -0,0 +1,328 @@
+/* xscreensaver, Copyright (c) 1991-1995 Jamie Zawinski <jwz@netscape.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.
+ */
+
+/* stderr hackery - Why Unix Sucks, reason number 32767.
+ */
+
+#if __STDC__
+#include <stdlib.h>
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <time.h>
+
+#include <X11/Intrinsic.h>
+
+#include "xscreensaver.h"
+
+extern XtAppContext app;
+extern Colormap cmap;
+extern Window screensaver_window;
+
+extern char *get_string_resource P((char *, char *));
+extern Bool get_boolean_resource P((char *, char *));
+extern unsigned int get_pixel_resource P((char *, char *,
+                                         Display *, Colormap));
+
+static char stderr_buffer [1024];
+static char *stderr_tail = 0;
+static time_t stderr_last_read = 0;
+static XtIntervalId stderr_popup_timer = 0;
+
+FILE *real_stderr = 0;
+FILE *real_stdout = 0;
+
+static int text_x = 0;
+static int text_y = 0;
+
+void
+reset_stderr ()
+{
+  text_x = text_y = 0;
+}
+
+static void
+print_stderr (string)
+     char *string;
+{
+  int h_border = 20;
+  int v_border = 20;
+  static int line_height;
+  static XFontStruct *font = 0;
+  static GC gc = 0;
+  char *head = string;
+  char *tail;
+
+  /* In verbose mode, copy it to stderr as well. */
+  if (verbose_p)
+    fprintf (real_stderr, "%s", string);
+
+  if (! gc)
+    {
+      XGCValues gcv;
+      Pixel fg, bg;
+      char *font_name = get_string_resource ("font", "Font");
+      if (!font_name) font_name = "fixed";
+      font = XLoadQueryFont (dpy, font_name);
+      if (! font) font = XLoadQueryFont (dpy, "fixed");
+      line_height = font->ascent + font->descent;
+      fg = get_pixel_resource ("textForeground", "Foreground", dpy, cmap);
+      bg = get_pixel_resource ("textBackground", "Background", dpy, cmap);
+      gcv.font = font->fid;
+      gcv.foreground = fg;
+      gcv.background = bg;
+      gc = XCreateGC (dpy, screensaver_window,
+                     (GCFont | GCForeground | GCBackground), &gcv);
+    }
+
+  for (tail = string; *tail; tail++)
+    {
+      if (*tail == '\n' || *tail == '\r')
+       {
+         int maxy = HeightOfScreen (screen) - v_border - v_border;
+         if (tail != head)
+           XDrawImageString (dpy, screensaver_window, gc,
+                             text_x + h_border,
+                             text_y + v_border + font->ascent,
+                             head, tail - head);
+         text_x = 0;
+         text_y += line_height;
+         head = tail + 1;
+         if (*tail == '\r' && *head == '\n')
+           head++, tail++;
+
+         if (text_y > maxy - line_height)
+           {
+#if 0
+             text_y = 0;
+#else
+             int offset = line_height * 5;
+             XCopyArea (dpy, screensaver_window, screensaver_window, gc,
+                        0, v_border + offset,
+                        WidthOfScreen (screen),
+                        (HeightOfScreen (screen) - v_border - v_border
+                         - offset),
+                        0, v_border);
+             XClearArea (dpy, screensaver_window,
+                         0, HeightOfScreen (screen) - v_border - offset,
+                         WidthOfScreen (screen), offset, False);
+             text_y -= offset;
+#endif
+           }
+       }
+    }
+  if (tail != head)
+    {
+      int direction, ascent, descent;
+      XCharStruct overall;
+      XDrawImageString (dpy, screensaver_window, gc,
+                       text_x + h_border, text_y + v_border + font->ascent,
+                       head, tail - head);
+      XTextExtents (font, tail, tail - head,
+                   &direction, &ascent, &descent, &overall);
+      text_x += overall.width;
+    }
+}
+
+
+static void
+stderr_popup_timer_fn (closure, id)
+     XtPointer closure;
+     XtIntervalId *id;
+{
+  char *s = stderr_buffer;
+  if (*s)
+    {
+      /* If too much data was printed, then something has gone haywire,
+        so truncate it. */
+      char *trailer = "\n\n<< stderr diagnostics have been truncated >>\n\n";
+      int max = sizeof (stderr_buffer) - strlen (trailer) - 5;
+      if (strlen (s) > max)
+       strcpy (s + max, trailer);
+      /* Now show the user. */
+      print_stderr (s);
+    }
+
+  stderr_tail = stderr_buffer;
+  stderr_popup_timer = 0;
+}
+
+
+static void
+stderr_callback (closure, fd, id)
+     XtPointer closure;
+     int *fd;
+     XtIntervalId *id;
+{
+  char *s;
+  int left;
+  int size;
+  int read_this_time = 0;
+
+  if (stderr_tail == 0)
+    stderr_tail = stderr_buffer;
+
+  left = ((sizeof (stderr_buffer) - 2) - (stderr_tail - stderr_buffer));
+
+  s = stderr_tail;
+  *s = 0;
+
+  /* Read as much data from the fd as we can, up to our buffer size. */
+  if (left > 0)
+    {
+      while ((size = read (*fd, (void *) s, left)) > 0)
+       {
+         left -= size;
+         s += size;
+         read_this_time += size;
+       }
+      *s = 0;
+    }
+  else
+    {
+      char buf2 [1024];
+      /* The buffer is full; flush the rest of it. */
+      while (read (*fd, (void *) buf2, sizeof (buf2)) > 0)
+       ;
+    }
+
+  stderr_tail = s;
+  stderr_last_read = time ((time_t *) 0);
+
+  /* Now we have read some data that we would like to put up in a dialog
+     box.  But more data may still be coming in - so don't pop up the
+     dialog right now, but instead, start a timer that will pop it up
+     a second from now.  Should more data come in in the meantime, we
+     will be called again, and will reset that timer again.  So the
+     dialog will only pop up when a second has elapsed with no new data
+     being written to stderr.
+
+     However, if the buffer is full (meaning lots of data has been written)
+     then we don't reset the timer.
+   */
+  if (read_this_time > 0)
+    {
+      if (stderr_popup_timer)
+       XtRemoveTimeOut (stderr_popup_timer);
+
+      stderr_popup_timer =
+       XtAppAddTimeOut (app, 1 * 1000, stderr_popup_timer_fn, 0);
+    }
+}
+
+void
+initialize_stderr ()
+{
+  static Boolean done = False;
+  int fds [2];
+  int in, out;
+  int new_stdout, new_stderr;
+  int stdout_fd = 1;
+  int stderr_fd = 2;
+  int flags;
+  Boolean stderr_dialog_p = get_boolean_resource ("captureStderr", "Boolean");
+  Boolean stdout_dialog_p = get_boolean_resource ("captureStdout", "Boolean");
+
+  real_stderr = stderr;
+  real_stdout = stdout;
+
+  if (!stderr_dialog_p && !stdout_dialog_p)
+    return;
+
+  if (done) return;
+  done = True;
+
+  if (pipe (fds))
+    {
+      perror ("error creating pipe:");
+      return;
+    }
+
+  in = fds [0];
+  out = fds [1];
+
+# ifdef O_NONBLOCK
+  flags = O_NONBLOCK;
+# else
+#  ifdef O_NDELAY
+  flags = O_NDELAY;
+#  else
+  ERROR!! neither O_NONBLOCK nor O_NDELAY are defined.
+#  endif
+# endif
+
+    /* Set both sides of the pipe to nonblocking - this is so that
+       our reads (in stderr_callback) will terminate, and so that
+       out writes (in the client programs) will silently fail when
+       the pipe is full, instead of hosing the program. */
+  if (fcntl (in, F_SETFL, flags) != 0)
+    {
+      perror ("fcntl:");
+      return;
+    }
+  if (fcntl (out, F_SETFL, flags) != 0)
+    {
+      perror ("fcntl:");
+      return;
+    }
+
+  if (stderr_dialog_p)
+    {
+      FILE *new_stderr_file;
+      new_stderr = dup (stderr_fd);
+      if (new_stderr < 0)
+       {
+         perror ("could not dup() a stderr:");
+         return;
+       }
+      if (! (new_stderr_file = fdopen (new_stderr, "w")))
+       {
+         perror ("could not fdopen() the new stderr:");
+         return;
+       }
+      real_stderr = new_stderr_file;
+
+      close (stderr_fd);
+      if (dup2 (out, stderr_fd) < 0)
+       {
+         perror ("could not dup() a new stderr:");
+         return;
+       }
+    }
+
+  if (stdout_dialog_p)
+    {
+      FILE *new_stdout_file;
+      new_stdout = dup (stdout_fd);
+      if (new_stdout < 0)
+       {
+         perror ("could not dup() a stdout:");
+         return;
+       }
+      if (! (new_stdout_file = fdopen (new_stdout, "w")))
+       {
+         perror ("could not fdopen() the new stdout:");
+         return;
+       }
+      real_stdout = new_stdout_file;
+
+      close (stdout_fd);
+      if (dup2 (out, stdout_fd) < 0)
+       {
+         perror ("could not dup() a new stdout:");
+         return;
+       }
+    }
+
+  XtAppAddInput (app, in, (XtPointer) XtInputReadMask, stderr_callback, 0);
+}
diff --git a/driver/subprocs.c b/driver/subprocs.c
new file mode 100644 (file)
index 0000000..689bbb0
--- /dev/null
@@ -0,0 +1,639 @@
+/* xscreensaver, Copyright (c) 1991, 1992, 1993, 1995
+ *  Jamie Zawinski <jwz@netscape.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.
+ */
+
+/* I would really like some error messages to show up on the screensaver window
+   itself when subprocs die, or when we can't launch them.  If the process
+   produces output, but does not actually die, I would like that output to go
+   to the appropriate stdout/stderr as they do now.  X and Unix conspire to
+   make this incredibly difficult.
+
+   - Not all systems have SIGIO, so we can't necessarily be signalled when a
+     process dies, so we'd have to poll it with wait() or something awful like
+     that, which would mean the main thread waking up more often than it does
+     now.
+
+   - We can't tell the difference between a process dying, and a process not
+     being launched correctly (for example, not being on $PATH) partly because
+     of the contortions we need to go through with /bin/sh in order to launch
+     it.
+
+   - We can't do X stuff from signal handlers, so we'd need to set a flag, 
+     save the error message, and notice that flag in the main thread.  The
+     problem is that the main thread is probably sleeping, waiting for the 
+     next X event, so to do this we'd have to register a pipe FD or something,
+     and write to it when something loses.
+
+   - We could assume that any output produced by a subproc indicates an error,
+     and blast that across the screen.  This means we'd need to use popen()
+     instead of forking and execing /bin/sh to run it for us.  Possibly this
+     would work, but see comment in exec_screenhack() about getting pids.
+     I think we could do the "exec " trick with popen() but would SIGIO get
+     delivered correctly?  Who knows.  (We could register the pipe-FD with
+     Xt, and handle output on it with a callback.)
+
+   - For the simple case of the programs not being on $PATH, we could just 
+     search $PATH before launching the shell, but that seems hardly worth the
+     effort...  And it's broken!!  Why should we have to duplicate half the
+     work of the shell?  (Because it's Unix, that's why!  Bend over.)
+ */
+
+#if __STDC__
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#endif
+
+#include <stdio.h>
+
+#include <X11/Xlib.h>          /* not used for much... */
+
+#ifndef ESRCH
+#include <errno.h>
+#endif
+
+#include <sys/time.h>          /* sys/resource.h needs this for timeval */
+#include <sys/resource.h>      /* for setpriority() and PRIO_PROCESS */
+#include <sys/wait.h>          /* for waitpid() and associated macros */
+#include <signal.h>            /* for the signal names */
+
+extern char **environ;         /* why isn't this in some header file? */
+
+#ifndef NO_SETUID
+#include <pwd.h>               /* for getpwnam() and struct passwd */
+#include <grp.h>               /* for getgrgid() and struct group */
+#endif /* NO_SETUID */
+
+#if !defined(SIGCHLD) && defined(SIGCLD)
+#define SIGCHLD SIGCLD
+#endif
+
+#if __STDC__
+extern int putenv (/* const char * */);        /* getenv() is in stdlib.h... */
+extern int kill (pid_t, int);          /* signal() is in sys/signal.h... */
+#endif
+
+#include "yarandom.h"
+#include "xscreensaver.h"
+
+/* this must be `sh', not whatever $SHELL happens to be. */
+char *shell;
+static pid_t pid = 0;
+char **screenhacks;
+int screenhacks_count;
+int current_hack = -1;
+char *demo_hack;
+int next_mode_p = 0;
+Bool locking_disabled_p = False;
+char *nolock_reason = 0;
+int nice_inferior = 0;
+
+extern Bool demo_mode_p;
+
+static void
+#if __STDC__
+exec_screenhack (char *command)
+#else
+exec_screenhack (command)
+     char *command;
+#endif
+{
+  char *tmp;
+  char buf [512];
+  char *av [5];
+  int ac = 0;
+
+  /* Close this fork's version of the display's fd.  It will open its own. */
+  close (ConnectionNumber (dpy));
+  
+  /* I don't believe what a sorry excuse for an operating system UNIX is!
+
+     - I want to spawn a process.
+     - I want to know it's pid so that I can kill it.
+     - I would like to receive a message when it dies of natural causes.
+     - I want the spawned process to have user-specified arguments.
+
+     The *only way* to parse arguments the way the shells do is to run a
+     shell (or duplicate what they do, which would be a *lot* of code.)
+
+     The *only way* to know the pid of the process is to fork() and exec()
+     it in the spawned side of the fork.
+
+     But if you're running a shell to parse your arguments, this gives you
+     the pid of the SHELL, not the pid of the PROCESS that you're actually
+     interested in, which is an *inferior* of the shell.  This also means
+     that the SIGCHLD you get applies to the shell, not its inferior.
+
+     So, the only solution other than implementing an argument parser here
+     is to force the shell to exec() its inferior.  What a fucking hack!
+     We prepend "exec " to the command string.
+
+     (Actually, Clint Wong <clint@jts.com> points out that process groups
+     might be used to take care of this problem; this may be worth considering
+     some day, except that, 1: this code works now, so why fix it, and 2: from
+     what I've seen in Emacs, dealing with process groups isn't especially
+     portable.)
+   */
+  tmp = command;
+  command = (char *) malloc (strlen (tmp) + 6);
+  memcpy (command, "exec ", 5);
+  memcpy (command + 5, tmp, strlen (tmp) + 1);
+
+  /* Invoke the shell as "/bin/sh -c 'exec prog -arg -arg ...'" */
+  av [ac++] = shell;
+  av [ac++] = "-c";
+  av [ac++] = command;
+  av [ac++] = 0;
+  
+  if (verbose_p)
+    printf ("%s: spawning \"%s\" in pid %d.\n", progname, command, getpid ());
+
+#if defined(SYSV) || defined(SVR4) || defined(__hpux)
+  {
+    int old_nice = nice (0);
+    int n = nice_inferior - old_nice;
+    errno = 0;
+    if (nice (n) == -1 && errno != 0)
+      {
+       sprintf (buf, "%s: %snice(%d) failed", progname,
+                (verbose_p ? "## " : ""), n);
+       perror (buf);
+      }
+  }
+#else /* !SYSV */
+#ifdef PRIO_PROCESS
+  if (setpriority (PRIO_PROCESS, getpid(), nice_inferior) != 0)
+    {
+      sprintf (buf, "%s: %ssetpriority(PRIO_PROCESS, %d, %d) failed",
+              progname, (verbose_p ? "## " : ""), getpid(), nice_inferior);
+      perror (buf);
+    }
+#else /* !PRIO_PROCESS */
+  if (nice_inferior != 0)
+    fprintf (stderr,
+          "%s: %sdon't know how to change process priority on this system.\n",
+            progname, (verbose_p ? "## " : ""));
+#endif /* !PRIO_PROCESS */
+#endif /* !SYSV */
+
+  /* Now overlay the current process with /bin/sh running the command.
+     If this returns, it's an error.
+   */
+  execve (av [0], av, environ);
+
+  sprintf (buf, "%s: %sexecve() failed", progname, (verbose_p ? "## " : ""));
+  perror (buf);
+  exit (1);    /* Note that this only exits a child fork.  */
+}
+
+/* to avoid a race between the main thread and the SIGCHLD handler */
+static int killing = 0;
+static Bool suspending = False;
+
+static char *current_hack_name P((void));
+
+static void
+#if __STDC__
+await_child_death (Bool killed)
+#else
+await_child_death (killed)
+     Bool killed;
+#endif
+{
+  Bool suspended_p = False;
+  int status;
+  pid_t kid;
+  killing = 1;
+  if (! pid)
+    return;
+
+  do
+    {
+      kid = waitpid (pid, &status, WUNTRACED);
+    }
+  while (kid == -1 && errno == EINTR);
+
+  if (kid == pid)
+    {
+      if (WIFEXITED (status))
+       {
+         int exit_status = WEXITSTATUS (status);
+         if (exit_status & 0x80)
+           exit_status |= ~0xFF;
+         /* One might assume that exiting with non-0 means something went
+            wrong.  But that loser xswarm exits with the code that it was
+            killed with, so it *always* exits abnormally.  Treat abnormal
+            exits as "normal" (don't mention them) if we've just killed
+            the subprocess.  But mention them if they happen on their own.
+          */
+         if (exit_status != 0 && (verbose_p || (! killed)))
+           fprintf (stderr,
+                    "%s: %schild pid %d (%s) exited abnormally (code %d).\n",
+                   progname, (verbose_p ? "## " : ""),
+                    pid, current_hack_name (), exit_status);
+         else if (verbose_p)
+           printf ("%s: child pid %d (%s) exited normally.\n",
+                   progname, pid, current_hack_name ());
+       }
+      else if (WIFSIGNALED (status))
+       {
+         if (!killed || WTERMSIG (status) != SIGTERM)
+           fprintf (stderr,
+                    "%s: %schild pid %d (%s) terminated with signal %d!\n",
+                    progname, (verbose_p ? "## " : ""),
+                    pid, current_hack_name (), WTERMSIG (status));
+         else if (verbose_p)
+           printf ("%s: child pid %d (%s) terminated with SIGTERM.\n",
+                   progname, pid, current_hack_name ());
+       }
+      else if (suspending)
+       {
+         suspended_p = True;
+         suspending = False; /* complain if it happens twice */
+       }
+      else if (WIFSTOPPED (status))
+       {
+         suspended_p = True;
+         fprintf (stderr, "%s: %schild pid %d (%s) stopped with signal %d!\n",
+                  progname, (verbose_p ? "## " : ""), pid,
+                  current_hack_name (), WSTOPSIG (status));
+       }
+      else
+       fprintf (stderr, "%s: %schild pid %d (%s) died in a mysterious way!",
+                progname, (verbose_p ? "## " : ""), pid, current_hack_name());
+    }
+  else if (kid <= 0)
+    fprintf (stderr, "%s: %swaitpid(%d, ...) says there are no kids?  (%d)\n",
+            progname, (verbose_p ? "## " : ""), pid, kid);
+  else
+    fprintf (stderr, "%s: %swaitpid(%d, ...) says proc %d died, not %d?\n",
+            progname, (verbose_p ? "## " : ""), pid, kid, pid);
+  killing = 0;
+  if (suspended_p != True)
+    pid = 0;
+}
+
+static char *
+current_hack_name ()
+{
+  static char chn [1024];
+  char *hack = (demo_mode_p ? demo_hack : screenhacks [current_hack]);
+  int i;
+  for (i = 0; hack [i] != 0 && hack [i] != ' ' && hack [i] != '\t'; i++)
+    chn [i] = hack [i];
+  chn [i] = 0;
+  return chn;
+}
+
+#ifdef SIGCHLD
+static void
+sigchld_handler (sig)
+     int sig;
+{
+  if (killing)
+    return;
+  if (! pid)
+    abort ();
+  await_child_death (False);
+}
+#endif
+
+
+void
+init_sigchld ()
+{
+#ifdef SIGCHLD
+  if (((int) signal (SIGCHLD, sigchld_handler)) == -1)
+    {
+      char buf [255];
+      sprintf (buf, "%s: %scouldn't catch SIGCHLD", progname,
+              (verbose_p ? "## " : ""));
+      perror (buf);
+    }
+#endif
+}
+
+
+extern void raise_window P((Bool inhibit_fade, Bool between_hacks_p));
+
+void
+spawn_screenhack (first_time_p)
+     Bool first_time_p;
+{
+  raise_window (first_time_p, True);
+  XFlush (dpy);
+
+  if (screenhacks_count || demo_mode_p)
+    {
+      char *hack;
+      pid_t forked;
+      char buf [255];
+      int new_hack;
+      if (demo_mode_p)
+       {
+         hack = demo_hack;
+       }
+      else
+       {
+         if (screenhacks_count == 1)
+           new_hack = 0;
+         else if (next_mode_p == 1)
+           new_hack = (current_hack + 1) % screenhacks_count,
+           next_mode_p = 0;
+         else if (next_mode_p == 2)
+           {
+             new_hack = ((current_hack + screenhacks_count - 1)
+                         % screenhacks_count);
+             next_mode_p = 0;
+           }
+         else
+           while ((new_hack = random () % screenhacks_count) == current_hack)
+             ;
+         current_hack = new_hack;
+         hack = screenhacks[current_hack];
+       }
+
+      switch (forked = fork ())
+       {
+       case -1:
+         sprintf (buf, "%s: %scouldn't fork",
+                  progname, (verbose_p ? "## " : ""));
+         perror (buf);
+         restore_real_vroot ();
+         exit (1);
+       case 0:
+         exec_screenhack (hack); /* this does not return */
+         break;
+       default:
+         pid = forked;
+         break;
+       }
+    }
+}
+
+void
+kill_screenhack ()
+{
+  killing = 1;
+  if (! pid)
+    return;
+  if (kill (pid, SIGTERM) < 0)
+    {
+      if (errno == ESRCH)
+       {
+         /* Sometimes we don't get a SIGCHLD at all!  WTF?
+            It's a race condition.  It looks to me like what's happening is
+            something like: a subprocess dies of natural causes.  There is a
+            small window between when the process dies and when the SIGCHLD
+            is (would have been) delivered.  If we happen to try to kill()
+            the process during that time, the kill() fails, because the
+            process is already dead.  But! no SIGCHLD is delivered (perhaps
+            because the failed kill() has reset some state in the kernel?)
+            Anyway, if kill() says "No such process", then we have to wait()
+            for it anyway, because the process has already become a zombie.
+            I love Unix.
+          */
+         await_child_death (False);
+       }
+      else
+       {
+         char buf [255];
+         sprintf (buf, "%s: %scouldn't kill child process %d", progname,
+                  (verbose_p ? "## " : ""), pid);
+         perror (buf);
+       }
+    }
+  else
+    {
+      if (verbose_p)
+       printf ("%s: killing pid %d.\n", progname, pid);
+      await_child_death (True);
+    }
+}
+
+
+void
+suspend_screenhack (suspend_p)
+     Bool suspend_p;
+{
+  
+  suspending = suspend_p;
+  if (! pid)
+    ;
+  else if (kill (pid, (suspend_p ? SIGSTOP : SIGCONT)) < 0)
+    {
+      char buf [255];
+      sprintf (buf, "%s: %scouldn't %s child process %d", progname,
+              (verbose_p ? "## " : ""),
+              (suspend_p ? "suspend" : "resume"),
+              pid);
+      perror (buf);
+    }
+  else if (verbose_p)
+    printf ("%s: %s pid %d.\n", progname,
+           (suspend_p ? "suspending" : "resuming"), pid);
+}
+
+\f
+/* Restarting the xscreensaver process from scratch. */
+
+static char **saved_argv;
+
+void
+save_argv (argc, argv)
+     int argc;
+     char **argv;
+{
+  saved_argv = (char **) malloc ((argc + 2) * sizeof (char *));
+  saved_argv [argc] = 0;
+  while (argc--)
+    {
+      int i = strlen (argv [argc]) + 1;
+      saved_argv [argc] = (char *) malloc (i);
+      memcpy (saved_argv [argc], argv [argc], i);
+    }
+}
+
+void
+restart_process ()
+{
+  XCloseDisplay (dpy);
+  fflush (stdout);
+  fflush (stderr);
+  execvp (saved_argv [0], saved_argv);
+  fprintf (stderr, "%s: %scould not restart process: %s (%d)\n",
+          progname, (verbose_p ? "## " : ""),
+          (errno == E2BIG ? "arglist too big" :
+           errno == EACCES ? "could not execute" :
+           errno == EFAULT ? "memory fault" :
+           errno == EIO ? "I/O error" :
+           errno == ENAMETOOLONG ? "name too long" :
+           errno == ELOOP ? "too many symbolic links" :
+           errno == ENOENT ? "file no longer exists" :
+           errno == ENOTDIR ? "directory no longer exists" :
+           errno == ENOEXEC ? "bad executable file" :
+           errno == ENOMEM ? "out of memory" :
+           "execvp() returned unknown error code"),
+          errno);
+  exit (1);
+}
+
+void
+demo_mode_restart_process ()
+{
+  int i;
+  for (i = 0; saved_argv [i]; i++);
+  /* add the -demo switch; save_argv() left room for this. */
+  saved_argv [i] = "-demo";
+  saved_argv [i+1] = 0;
+  restart_process ();
+}
+
+void
+hack_environment ()
+{
+  /* Store $DISPLAY into the environment, so that the $DISPLAY variable that
+     the spawned processes inherit is the same as the value of -display passed
+     in on our command line (which is not necessarily the same as what our
+     $DISPLAY variable is.)
+   */
+  char *s, buf [2048];
+  int i;
+  sprintf (buf, "DISPLAY=%s", DisplayString (dpy));
+  i = strlen (buf);
+  s = (char *) malloc (i+1);
+  strncpy (s, buf, i+1);
+  if (putenv (s))
+    abort ();
+}
+
+\f
+/* Change the uid/gid of the screensaver process, so that it is safe for it
+   to run setuid root (which it needs to do on some systems to read the 
+   encrypted passwords from the passwd file.)
+
+   hack_uid() is run before opening the X connection, so that XAuth works.
+   hack_uid_warn() is called after the connection is opened and the command
+   line arguments are parsed, so that the messages from hack_uid() get 
+   printed after we know whether we're in `verbose' mode.
+ */
+
+#ifndef NO_SETUID
+
+static int hack_uid_errno;
+static char hack_uid_buf [255], *hack_uid_error;
+
+void
+hack_uid ()
+{
+  /* If we've been run as setuid or setgid to someone else (most likely root)
+     turn off the extra permissions so that random user-specified programs
+     don't get special privileges.  (On some systems it might be necessary
+     to install this as setuid root in order to read the passwd file to
+     implement lock-mode...)
+  */
+  setgid (getgid ());
+  setuid (getuid ());
+
+  hack_uid_errno = 0;
+  hack_uid_error = 0;
+
+  /* If we're being run as root (as from xdm) then switch the user id
+     to something safe. */
+  if (getuid () == 0)
+    {
+      struct passwd *p;
+      /* Locking can't work when running as root, because we have no way of
+        knowing what the user id of the logged in user is (so we don't know
+        whose password to prompt for.)
+       */
+      locking_disabled_p = True;
+      nolock_reason = "running as root";
+      p = getpwnam ("nobody");
+      if (! p) p = getpwnam ("daemon");
+      if (! p) p = getpwnam ("bin");
+      if (! p) p = getpwnam ("sys");
+      if (! p)
+       {
+         hack_uid_error = "couldn't find safe uid; running as root.";
+         hack_uid_errno = -1;
+       }
+      else
+       {
+         struct group *g = getgrgid (p->pw_gid);
+         hack_uid_error = hack_uid_buf;
+         sprintf (hack_uid_error, "changing uid/gid to %s/%s (%d/%d).",
+                  p->pw_name, (g ? g->gr_name : "???"), p->pw_uid, p->pw_gid);
+
+         /* Change the gid to be a safe one.  If we can't do that, then
+            print a warning.  We change the gid before the uid so that we
+            change the gid while still root. */
+         if (setgid (p->pw_gid) != 0)
+           {
+             hack_uid_errno = errno;
+             sprintf (hack_uid_error, "couldn't set gid to %s (%d)",
+                      (g ? g->gr_name : "???"), p->pw_gid);
+           }
+
+         /* Now change the uid to be a safe one. */
+         if (setuid (p->pw_uid) != 0)
+           {
+             hack_uid_errno = errno;
+             sprintf (hack_uid_error, "couldn't set uid to %s (%d)",
+                      p->pw_name, p->pw_uid);
+           }
+       }
+    }
+#ifndef NO_LOCKING
+ else  /* disable locking if already being run as "someone else" */
+   {
+     struct passwd *p = getpwuid (getuid ());
+     if (!p ||
+        !strcmp (p->pw_name, "root") ||
+        !strcmp (p->pw_name, "nobody") ||
+        !strcmp (p->pw_name, "daemon") ||
+        !strcmp (p->pw_name, "bin") ||
+        !strcmp (p->pw_name, "sys"))
+       {
+        locking_disabled_p = True;
+        nolock_reason = hack_uid_buf;
+        sprintf (nolock_reason, "running as %s", p->pw_name);
+       }
+   }
+#endif /* NO_LOCKING */
+}
+
+void
+hack_uid_warn ()
+{
+  if (! hack_uid_error)
+    ;
+  else if (hack_uid_errno == 0)
+    {
+      if (verbose_p)
+       printf ("%s: %s\n", progname, hack_uid_error);
+    }
+  else
+    {
+      char buf [255];
+      sprintf (buf, "%s: %s%s", progname, (verbose_p ? "## " : ""),
+              hack_uid_error);
+      if (hack_uid_errno == -1)
+       fprintf (stderr, "%s\n", buf);
+      else
+       {
+         errno = hack_uid_errno;
+         perror (buf);
+       }
+    }
+}
+
+#endif /* !NO_SETUID */
diff --git a/driver/timers.c b/driver/timers.c
new file mode 100644 (file)
index 0000000..bb950d8
--- /dev/null
@@ -0,0 +1,472 @@
+/* xscreensaver, Copyright (c) 1991-1995 Jamie Zawinski <jwz@netscape.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.
+ */
+
+/* #define DEBUG_TIMERS */
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Intrinsic.h>
+#include <X11/Xos.h>
+#include <X11/Xmu/Error.h>
+
+#ifdef HAVE_XIDLE_EXTENSION
+#include <X11/extensions/xidle.h>
+#endif /* HAVE_XIDLE_EXTENSION */
+
+#ifdef HAVE_SAVER_EXTENSION
+#include <X11/extensions/scrnsaver.h>
+extern int saver_ext_event_number;
+extern Window server_saver_window;
+#endif /* HAVE_SAVER_EXTENSION */
+
+#include "xscreensaver.h"
+
+#if __STDC__
+# define P(x)x
+#else
+#define P(x)()
+#endif
+
+extern XtAppContext app;
+
+Time cycle;
+Time timeout;
+Time pointer_timeout;
+Time notice_events_timeout;
+
+extern Bool use_xidle_extension;
+extern Bool use_saver_extension;
+extern Bool dbox_up_p;
+extern Bool locked_p;
+extern Window screensaver_window;
+
+extern Bool handle_clientmessage P((XEvent *, Bool));
+
+static time_t last_activity_time; /* for when we have no server extensions */
+static XtIntervalId timer_id = 0;
+static XtIntervalId check_pointer_timer_id = 0;
+XtIntervalId cycle_id = 0;
+XtIntervalId lock_id = 0;
+
+void
+idle_timer (junk1, junk2)
+     void *junk1;
+     XtPointer junk2;
+{
+  /* What an amazingly shitty design.  Not only does Xt execute timeout
+     events from XtAppNextEvent() instead of from XtDispatchEvent(), but
+     there is no way to tell Xt to block until there is an X event OR a
+     timeout happens.  Once your timeout proc is called, XtAppNextEvent()
+     still won't return until a "real" X event comes in.
+
+     So this function pushes a stupid, gratuitous, unnecessary event back
+     on the event queue to force XtAppNextEvent to return Right Fucking Now.
+     When the code in sleep_until_idle() sees an event of type XAnyEvent,
+     which the server never generates, it knows that a timeout has occurred.
+   */
+  XEvent fake_event;
+  fake_event.type = 0; /* XAnyEvent type, ignored. */
+  fake_event.xany.display = dpy;
+  fake_event.xany.window  = 0;
+  XPutBackEvent (dpy, &fake_event);
+}
+
+
+static void
+#if __STDC__
+notice_events (Window window, Bool top_p)
+#else
+notice_events (window, top_p)
+     Window window;
+     Bool top_p;
+#endif
+{
+  XWindowAttributes attrs;
+  unsigned long events;
+  Window root, parent, *kids;
+  unsigned int nkids;
+
+  if (XtWindowToWidget (dpy, window))
+    /* If it's one of ours, don't mess up its event mask. */
+    return;
+
+  if (!XQueryTree (dpy, window, &root, &parent, &kids, &nkids))
+    return;
+  if (window == root)
+    top_p = False;
+
+  XGetWindowAttributes (dpy, window, &attrs);
+  events = ((attrs.all_event_masks | attrs.do_not_propagate_mask)
+           & KeyPressMask);
+
+  /* Select for SubstructureNotify on all windows.
+     Select for KeyPress on all windows that already have it selected.
+     Do we need to select for ButtonRelease?  I don't think so.
+   */
+  XSelectInput (dpy, window, SubstructureNotifyMask | events);
+
+  if (top_p && verbose_p && (events & KeyPressMask))
+    {
+      /* Only mention one window per tree (hack hack). */
+      printf ("%s: selected KeyPress on 0x%lX\n", progname,
+             (unsigned long) window);
+      top_p = False;
+    }
+
+  if (kids)
+    {
+      while (nkids)
+       notice_events (kids [--nkids], top_p);
+      XFree ((char *) kids);
+    }
+}
+
+
+int
+BadWindow_ehandler (dpy, error)
+     Display *dpy;
+     XErrorEvent *error;
+{
+  /* When we notice a window being created, we spawn a timer that waits
+     30 seconds or so, and then selects events on that window.  This error
+     handler is used so that we can cope with the fact that the window
+     may have been destroyed <30 seconds after it was created.
+   */
+  if (error->error_code == BadWindow ||
+      error->error_code == BadMatch ||
+      error->error_code == BadDrawable)
+    return 0;
+  XmuPrintDefaultErrorMessage (dpy, error, stderr);
+  exit (1);
+}
+
+void
+notice_events_timer (closure, timer)
+     XtPointer closure;
+     XtIntervalId *timer;
+{
+  Window window = (Window) closure;
+  int (*old_handler) ();
+  old_handler = XSetErrorHandler (BadWindow_ehandler);
+  notice_events (window, True);
+  XSync (dpy, False);
+  XSetErrorHandler (old_handler);
+}
+
+
+/* When the screensaver is active, this timer will periodically change
+   the running program.
+ */
+void
+cycle_timer (junk1, junk2)
+     void *junk1;
+     XtPointer junk2;
+{
+  Time how_long = cycle;
+  if (dbox_up_p)
+    {
+      if (verbose_p)
+       printf ("%s: dbox up; delaying hack change.\n", progname);
+      how_long = 30000; /* 30 secs */
+    }
+  else
+    {
+      if (verbose_p)
+       printf ("%s: changing graphics hacks.\n", progname);
+      kill_screenhack ();
+      spawn_screenhack (False);
+    }
+  cycle_id = XtAppAddTimeOut (app, how_long, cycle_timer, 0);
+
+#ifdef DEBUG_TIMERS
+  if (verbose_p)
+    printf ("%s: starting cycle_timer (%ld, %ld)\n",
+           progname, how_long, cycle_id);
+#endif
+}
+
+
+void
+activate_lock_timer (junk1, junk2)
+     void *junk1;
+     XtPointer junk2;
+{
+  if (verbose_p)
+    printf ("%s: timed out; activating lock\n", progname);
+  locked_p = True;
+}
+
+
+/* Call this when user activity (or "simulated" activity) has been noticed.
+ */
+static void
+reset_timers P((void))
+{
+  if (use_saver_extension)
+    return;
+
+#ifdef DEBUG_TIMERS
+  if (verbose_p)
+    printf ("%s: restarting idle_timer (%ld, %ld)\n",
+           progname, timeout, timer_id);
+#endif
+  XtRemoveTimeOut (timer_id);
+  timer_id = XtAppAddTimeOut (app, timeout, idle_timer, 0);
+  if (cycle_id) abort ();
+
+#ifdef DEBUG_TIMERS
+  if (verbose_p)
+    printf ("%s: starting idle_timer (%ld, %ld)\n",
+           progname, timeout, timer_id);
+#endif
+
+  last_activity_time = time ((time_t *) 0);
+}
+
+/* When we aren't using a server extension, this timer is used to periodically
+   wake up and poll the mouse position, which is possibly more reliable than
+   selecting motion events on every window.
+ */
+static void
+check_pointer_timer (closure, this_timer)
+     void *closure;
+     XtPointer this_timer;
+{
+  static int last_root_x = -1;
+  static int last_root_y = -1;
+  static Window last_child = (Window) -1;
+  static unsigned int last_mask = 0;
+  Window root, child;
+  int root_x, root_y, x, y;
+  unsigned int mask;
+  XtIntervalId *timerP = (XtIntervalId *) closure;
+
+  if (use_xidle_extension || use_saver_extension)
+    abort ();
+
+  *timerP = XtAppAddTimeOut (app, pointer_timeout, check_pointer_timer,
+                            closure);
+
+  XQueryPointer (dpy, screensaver_window, &root, &child,
+                &root_x, &root_y, &x, &y, &mask);
+  if (root_x == last_root_x && root_y == last_root_y &&
+      child == last_child && mask == last_mask)
+    return;
+
+#ifdef DEBUG_TIMERS
+  if (verbose_p && this_timer)
+    if (root_x == last_root_x && root_y == last_root_y && child == last_child)
+      printf ("%s: modifiers changed at %s.\n", progname, timestring ());
+    else
+      printf ("%s: pointer moved at %s.\n", progname, timestring ());
+#endif
+
+  last_root_x = root_x;
+  last_root_y = root_y;
+  last_child = child;
+  last_mask = mask;
+
+  reset_timers ();
+}
+
+
+void
+sleep_until_idle (until_idle_p)
+     Bool until_idle_p;
+{
+  XEvent event;
+
+  if (until_idle_p)
+    {
+      if (!use_saver_extension)
+       {
+         /* Wake up periodically to ask the server if we are idle. */
+         timer_id = XtAppAddTimeOut (app, timeout, idle_timer, 0);
+#ifdef DEBUG_TIMERS
+         if (verbose_p)
+           printf ("%s: starting idle_timer (%ld, %ld)\n",
+                   progname, timeout, timer_id);
+#endif
+       }
+
+      if (!use_xidle_extension && !use_saver_extension)
+       /* start polling the mouse position */
+       check_pointer_timer (&check_pointer_timer_id, 0);
+    }
+
+  while (1)
+    {
+      XtAppNextEvent (app, &event);
+
+      switch (event.xany.type) {
+      case 0:          /* our synthetic "timeout" event has been signalled */
+       if (until_idle_p)
+         {
+           Time idle;
+#ifdef HAVE_XIDLE_EXTENSION
+           if (use_xidle_extension)
+             {
+               if (! XGetIdleTime (dpy, &idle))
+                 {
+                   fprintf (stderr, "%s: %sXGetIdleTime() failed.\n",
+                            progname, (verbose_p ? "## " : ""));
+                   exit (1);
+                 }
+             }
+           else
+#endif /* HAVE_XIDLE_EXTENSION */
+#ifdef HAVE_SAVER_EXTENSION
+             if (use_saver_extension)
+               {
+                 /* We don't need to do anything in this case - the synthetic
+                    event isn't necessary, as we get sent specific events
+                    to wake us up. */
+                 idle = 0;
+               }
+           else
+#endif /* HAVE_SAVER_EXTENSION */
+             {
+               idle = 1000 * (last_activity_time - time ((time_t *) 0));
+             }
+           
+           if (idle >= timeout)
+             goto DONE;
+           else if (!use_saver_extension)
+             {
+               timer_id = XtAppAddTimeOut (app, timeout - idle,
+                                           idle_timer, 0);
+#ifdef DEBUG_TIMERS
+               if (verbose_p)
+                 printf ("%s: starting idle_timer (%ld, %ld)\n",
+                         progname, timeout - idle, timer_id);
+#endif /* DEBUG_TIMERS */
+             }
+         }
+       break;
+
+      case ClientMessage:
+       if (handle_clientmessage (&event, until_idle_p))
+         goto DONE;
+       break;
+
+      case CreateNotify:
+       if (!use_xidle_extension && !use_saver_extension)
+         {
+           XtAppAddTimeOut (app, notice_events_timeout, notice_events_timer,
+                            (XtPointer) event.xcreatewindow.window);
+#ifdef DEBUG_TIMERS
+           if (verbose_p)
+             printf ("%s: starting notice_events_timer for 0x%X (%lu)\n",
+                     progname,
+                     (unsigned int) event.xcreatewindow.window,
+                     notice_events_timeout);
+#endif /* DEBUG_TIMERS */
+         }
+       break;
+
+      case KeyPress:
+      case KeyRelease:
+      case ButtonPress:
+      case ButtonRelease:
+      case MotionNotify:
+
+#ifdef DEBUG_TIMERS
+       if (verbose_p)
+         {
+           if (event.xany.type == MotionNotify)
+             printf ("%s: MotionNotify at %s\n", progname, timestring ());
+           else if (event.xany.type == KeyPress)
+             printf ("%s: KeyPress seen on 0x%X at %s\n", progname,
+                     (unsigned int) event.xkey.window, timestring ());
+         }
+#endif
+
+       /* We got a user event */
+       if (!until_idle_p)
+         goto DONE;
+       else
+         reset_timers ();
+       break;
+
+      default:
+
+#ifdef HAVE_SAVER_EXTENSION
+       if (event.type == saver_ext_event_number)
+         {
+           XScreenSaverNotifyEvent *sevent =
+             (XScreenSaverNotifyEvent *) &event;
+           if (sevent->state == ScreenSaverOn)
+             {
+# ifdef DEBUG_TIMERS
+               if (verbose_p)
+                 printf ("%s: ScreenSaverOn event received at %s\n",
+                         progname, timestring ());
+# endif /* DEBUG_TIMERS */
+
+               /* Get the "real" server window out of the way as soon
+                  as possible. */
+               if (server_saver_window &&
+                   window_exists_p (dpy, server_saver_window))
+                 XUnmapWindow (dpy, server_saver_window);
+
+               if (sevent->kind != ScreenSaverExternal)
+                 {
+# ifdef DEBUG_TIMERS
+                   fprintf (stderr,
+                        "%s: ScreenSaverOn event wasn't of type External!\n",
+                            progname);
+# endif /* DEBUG_TIMERS */
+                 }
+
+               if (until_idle_p)
+                 goto DONE;
+             }
+           else if (sevent->state == ScreenSaverOff)
+             {
+# ifdef DEBUG_TIMERS
+               if (verbose_p)
+                 printf ("%s: ScreenSaverOff event received at %s\n",
+                         progname, timestring ());
+# endif /* DEBUG_TIMERS */
+               if (!until_idle_p)
+                 goto DONE;
+             }
+# ifdef DEBUG_TIMERS
+           else if (verbose_p)
+             printf ("%s: unknown ScreenSaver event received at %s\n",
+                     progname, timestring ());
+# endif /* DEBUG_TIMERS */
+         }
+       else
+
+#endif /* HAVE_SAVER_EXTENSION */
+
+         XtDispatchEvent (&event);
+      }
+    }
+ DONE:
+
+  if (check_pointer_timer_id)
+    {
+      XtRemoveTimeOut (check_pointer_timer_id);
+      check_pointer_timer_id = 0;
+    }
+  if (timer_id)
+    {
+      XtRemoveTimeOut (timer_id);
+      timer_id = 0;
+    }
+
+  if (until_idle_p && cycle_id)
+    abort ();
+
+  return;
+}
diff --git a/driver/windows.c b/driver/windows.c
new file mode 100644 (file)
index 0000000..084bce7
--- /dev/null
@@ -0,0 +1,783 @@
+/* xscreensaver, Copyright (c) 1991-1995 Jamie Zawinski <jwz@netscape.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.
+ */
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/Xos.h>
+#include <X11/Xmu/SysUtil.h>
+
+#include <signal.h>            /* for the signal names */
+
+#include "xscreensaver.h"
+
+#ifdef HAVE_SAVER_EXTENSION
+#include <X11/extensions/scrnsaver.h>
+extern Bool use_saver_extension;
+#endif /* HAVE_SAVER_EXTENSION */
+
+#if __STDC__
+extern int kill (pid_t, int);          /* signal() is in sys/signal.h... */
+#endif /* __STDC__ */
+
+extern Time timeout;
+
+extern Bool lock_p, demo_mode_p;
+
+Atom XA_VROOT, XA_XSETROOT_ID;
+Atom XA_SCREENSAVER_VERSION, XA_SCREENSAVER_ID;
+
+#if __STDC__
+extern void describe_visual (FILE *, Display *, Visual *);
+extern void reset_stderr (void);
+#endif
+
+Window screensaver_window = 0;
+Cursor cursor;
+Colormap cmap, cmap2;
+Bool install_cmap_p;
+Bool fade_p, unfade_p;
+int fade_seconds, fade_ticks;
+
+static unsigned long black_pixel;
+static Window real_vroot, real_vroot_value;
+
+#ifdef HAVE_SAVER_EXTENSION
+Window server_saver_window = 0;
+#endif /* HAVE_SAVER_EXTENSION */
+
+#define ALL_POINTER_EVENTS \
+       (ButtonPressMask | ButtonReleaseMask | EnterWindowMask | \
+        LeaveWindowMask | PointerMotionMask | PointerMotionHintMask | \
+        Button1MotionMask | Button2MotionMask | Button3MotionMask | \
+        Button4MotionMask | Button5MotionMask | ButtonMotionMask)
+
+/* I don't really understand Sync vs Async, but these seem to work... */
+#define grab_kbd(win) \
+  XGrabKeyboard (dpy, (win), True, GrabModeSync, GrabModeAsync, CurrentTime)
+#define grab_mouse(win) \
+  XGrabPointer (dpy, (win), True, ALL_POINTER_EVENTS, \
+               GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime)
+
+void
+grab_keyboard_and_mouse P((void))
+{
+  Status status;
+  XSync (dpy, False);
+
+  if (demo_mode_p) return;
+
+  status = grab_kbd (screensaver_window);
+  if (status != GrabSuccess)
+    {  /* try again in a second */
+      sleep (1);
+      status = grab_kbd (screensaver_window);
+      if (status != GrabSuccess)
+       fprintf (stderr, "%s: %scouldn't grab keyboard!  (%d)\n",
+                progname, (verbose_p ? "## " : ""), status);
+    }
+  status = grab_mouse (screensaver_window);
+  if (status != GrabSuccess)
+    {  /* try again in a second */
+      sleep (1);
+      status = grab_mouse (screensaver_window);
+      if (status != GrabSuccess)
+       fprintf (stderr, "%s: %scouldn't grab pointer!  (%d)\n",
+                progname, (verbose_p ? "## " : ""), status);
+    }
+}
+
+void
+ungrab_keyboard_and_mouse P((void))
+{
+  XUngrabPointer (dpy, CurrentTime);
+  XUngrabKeyboard (dpy, CurrentTime);
+}
+
+
+void
+ensure_no_screensaver_running ()
+{
+  int i;
+  Window root = RootWindowOfScreen (screen);
+  Window root2, parent, *kids;
+  unsigned int nkids;
+  int (*old_handler) ();
+
+  old_handler = XSetErrorHandler (BadWindow_ehandler);
+
+  if (! XQueryTree (dpy, root, &root2, &parent, &kids, &nkids))
+    abort ();
+  if (root != root2)
+    abort ();
+  if (parent)
+    abort ();
+  for (i = 0; i < nkids; i++)
+    {
+      Atom type;
+      int format;
+      unsigned long nitems, bytesafter;
+      char *version;
+
+      if (XGetWindowProperty (dpy, kids[i], XA_SCREENSAVER_VERSION, 0, 1,
+                             False, XA_STRING, &type, &format, &nitems,
+                             &bytesafter, (unsigned char **) &version)
+         == Success
+         && type != None)
+       {
+         char *id;
+         if (!XGetWindowProperty (dpy, kids[i], XA_SCREENSAVER_ID, 0, 512,
+                                  False, XA_STRING, &type, &format, &nitems,
+                                  &bytesafter, (unsigned char **) &id)
+             == Success
+             || type == None)
+           id = "???";
+
+         fprintf (stderr,
+      "%s: %salready running on display %s (window 0x%x)\n from process %s.\n",
+                  progname, (verbose_p ? "## " : ""), DisplayString (dpy),
+                  (int) kids [i], id);
+         exit (1);
+       }
+    }
+
+  if (kids) XFree ((char *) kids);
+  XSync (dpy, False);
+  XSetErrorHandler (old_handler);
+}
+
+
+void
+disable_builtin_screensaver ()
+{
+  int server_timeout, server_interval, prefer_blank, allow_exp;
+  /* Turn off the server builtin saver if it is now running. */
+  XForceScreenSaver (dpy, ScreenSaverReset);
+  XGetScreenSaver (dpy, &server_timeout, &server_interval,
+                  &prefer_blank, &allow_exp);
+
+#ifdef HAVE_SAVER_EXTENSION
+  if (use_saver_extension)
+    {
+      /* Override the values specified with "xset" with our own parameters. */
+      prefer_blank = False;
+      allow_exp = True;
+      server_interval = 0;
+      server_timeout = (timeout / 1000);
+      if (verbose_p)
+       fprintf (stderr,
+                "%s: configuring server for saver timeout of %d seconds.\n",
+                progname, server_timeout);
+      XSetScreenSaver (dpy, server_timeout, server_interval,
+                      prefer_blank, allow_exp);
+    }
+  else
+#endif /* HAVE_SAVER_EXTENSION */
+  if (server_timeout != 0)
+    {
+      server_timeout = 0;
+      XSetScreenSaver (dpy, server_timeout, server_interval,
+                      prefer_blank, allow_exp);
+      printf ("%s%sisabling server builtin screensaver.\n\
+       You can re-enable it with \"xset s on\".\n",
+             (verbose_p ? "" : progname), (verbose_p ? "\n\tD" : ": d"));
+    }
+}
+
+\f
+/* Virtual-root hackery */
+
+#ifdef _VROOT_H_
+ERROR!  You must not include vroot.h in this file.
+#endif
+
+static void
+#if __STDC__
+store_vroot_property (Window win, Window value)
+#else
+store_vroot_property (win, value)
+     Window win, value;
+#endif
+{
+#if 0
+  printf ("%s: storing XA_VROOT = 0x%x (%s) = 0x%x (%s)\n", progname, 
+         win,
+         (win == screensaver_window ? "ScreenSaver" :
+          (win == real_vroot ? "VRoot" :
+           (win == real_vroot_value ? "Vroot_value" : "???"))),
+         value,
+         (value == screensaver_window ? "ScreenSaver" :
+          (value == real_vroot ? "VRoot" :
+           (value == real_vroot_value ? "Vroot_value" : "???"))));
+#endif
+  XChangeProperty (dpy, win, XA_VROOT, XA_WINDOW, 32, PropModeReplace,
+                  (unsigned char *) &value, 1);
+}
+
+static void
+#if __STDC__
+remove_vroot_property (Window win)
+#else
+remove_vroot_property (win)
+     Window win;
+#endif
+{
+#if 0
+  printf ("%s: removing XA_VROOT from 0x%x (%s)\n", progname, win, 
+         (win == screensaver_window ? "ScreenSaver" :
+          (win == real_vroot ? "VRoot" :
+           (win == real_vroot_value ? "Vroot_value" : "???"))));
+#endif
+  XDeleteProperty (dpy, win, XA_VROOT);
+}
+
+
+static void
+kill_xsetroot_data P((void))
+{
+  Atom type;
+  int format;
+  unsigned long nitems, bytesafter;
+  Pixmap *dataP = 0;
+
+  /* If the user has been using xv or xsetroot as a screensaver (to display
+     an image on the screensaver window, as a kind of slideshow) then the
+     pixmap and its associated color cells have been put in RetainPermanent
+     CloseDown mode.  Since we're not destroying the xscreensaver window,
+     but merely unmapping it, we need to free these resources or those
+     colormap cells will stay allocated while the screensaver is off.  (We
+     could just delete the screensaver window and recreate it later, but
+     that could cause other problems.)  This code does an atomic read-and-
+     delete of the _XSETROOT_ID property, and if it held a pixmap, then we
+     cause the RetainPermanent resources of the client which created it
+     (and which no longer exists) to be freed.
+   */
+  if (XGetWindowProperty (dpy, screensaver_window, XA_XSETROOT_ID, 0, 1,
+                         True, AnyPropertyType, &type, &format, &nitems, 
+                         &bytesafter, (unsigned char **) &dataP)
+      == Success
+      && type != None)
+    {
+      if (dataP && *dataP && type == XA_PIXMAP && format == 32 &&
+         nitems == 1 && bytesafter == 0)
+       {
+         if (verbose_p)
+           printf ("%s: destroying xsetroot data (0x%lX).\n",
+                   progname, *dataP);
+         XKillClient (dpy, *dataP);
+       }
+      else
+       fprintf (stderr, "%s: %sdeleted unrecognised _XSETROOT_ID property: \n\
+       %lu, %lu; type: %lu, format: %d, nitems: %lu, bytesafter %ld\n",
+                progname, (verbose_p ? "## " : ""),
+                (unsigned long) dataP, (dataP ? *dataP : 0), type,
+                format, nitems, bytesafter);
+    }
+}
+
+
+static void handle_signals P((Bool on_p));
+
+static void
+save_real_vroot P((void))
+{
+  int i;
+  Window root = RootWindowOfScreen (screen);
+  Window root2, parent, *kids;
+  unsigned int nkids;
+
+  real_vroot = 0;
+  real_vroot_value = 0;
+  if (! XQueryTree (dpy, root, &root2, &parent, &kids, &nkids))
+    abort ();
+  if (root != root2)
+    abort ();
+  if (parent)
+    abort ();
+  for (i = 0; i < nkids; i++)
+    {
+      Atom type;
+      int format;
+      unsigned long nitems, bytesafter;
+      Window *vrootP = 0;
+
+      if (XGetWindowProperty (dpy, kids[i], XA_VROOT, 0, 1, False, XA_WINDOW,
+                             &type, &format, &nitems, &bytesafter,
+                             (unsigned char **) &vrootP)
+         != Success)
+       continue;
+      if (! vrootP)
+       continue;
+      if (real_vroot)
+       {
+         if (*vrootP == screensaver_window) abort ();
+         fprintf (stderr,
+           "%s: %smore than one virtual root window found (0x%x and 0x%x).\n",
+                  progname, (verbose_p ? "## " : ""),
+                  (int) real_vroot, (int) kids [i]);
+         exit (1);
+       }
+      real_vroot = kids [i];
+      real_vroot_value = *vrootP;
+    }
+
+  if (real_vroot)
+    {
+      handle_signals (True);
+      remove_vroot_property (real_vroot);
+      XSync (dpy, False);
+    }
+
+  XFree ((char *) kids);
+}
+
+static Bool
+restore_real_vroot_1 P((void))
+{
+  if (verbose_p && real_vroot)
+    printf ("%s: restoring __SWM_VROOT property on the real vroot (0x%lx).\n",
+           progname, (unsigned long) real_vroot);
+  remove_vroot_property (screensaver_window);
+  if (real_vroot)
+    {
+      store_vroot_property (real_vroot, real_vroot_value);
+      real_vroot = 0;
+      real_vroot_value = 0;
+      /* make sure the property change gets there before this process
+        terminates!  We might be doing this because we have intercepted
+        SIGTERM or something. */
+      XSync (dpy, False);
+      return True;
+    }
+  return False;
+}
+
+void
+restore_real_vroot ()
+{
+  if (restore_real_vroot_1 ())
+    handle_signals (False);
+}
+
+\f
+/* Signal hackery to ensure that the vroot doesn't get left in an 
+   inconsistent state
+ */
+
+static const char *sig_names [255] = { 0 };
+
+static void
+restore_real_vroot_handler (sig)
+     int sig;
+{
+  signal (sig, SIG_DFL);
+  if (restore_real_vroot_1 ())
+    fprintf (stderr, "\n%s: %s%s (%d) intercepted, vroot restored.\n",
+            progname, (verbose_p ? "## " : ""),
+            ((sig < sizeof(sig_names) && sig >= 0 && sig_names [sig])
+             ? sig_names [sig] : "unknown signal"),
+            sig);
+  kill (getpid (), sig);
+}
+
+
+static void
+#if __STDC__
+catch_signal (int sig, char *signame, Bool on_p)
+#else
+catch_signal (sig, signame, on_p)
+     int sig;
+     char *signame;
+     Bool on_p;
+#endif
+{
+  if (! on_p)
+    signal (sig, SIG_DFL);
+  else
+    {
+      sig_names [sig] = signame;
+      if (((int) signal (sig, restore_real_vroot_handler)) == -1)
+       {
+         char buf [255];
+         sprintf (buf, "%s: %scouldn't catch %s (%d)", progname,
+                  (verbose_p ? "## " : ""), signame, sig);
+         perror (buf);
+         restore_real_vroot ();
+         exit (1);
+       }
+    }
+}
+
+static void
+handle_signals (on_p)
+     Bool on_p;
+{
+#if 0
+  if (on_p) printf ("handling signals\n");
+  else printf ("unhandling signals\n");
+#endif
+
+  catch_signal (SIGHUP,  "SIGHUP",  on_p);
+  catch_signal (SIGINT,  "SIGINT",  on_p);
+  catch_signal (SIGQUIT, "SIGQUIT", on_p);
+  catch_signal (SIGILL,  "SIGILL",  on_p);
+  catch_signal (SIGTRAP, "SIGTRAP", on_p);
+  catch_signal (SIGIOT,  "SIGIOT",  on_p);
+  catch_signal (SIGABRT, "SIGABRT", on_p);
+#ifdef SIGEMT
+  catch_signal (SIGEMT,  "SIGEMT",  on_p);
+#endif
+  catch_signal (SIGFPE,  "SIGFPE",  on_p);
+  catch_signal (SIGBUS,  "SIGBUS",  on_p);
+  catch_signal (SIGSEGV, "SIGSEGV", on_p);
+#ifdef SIGSYS
+  catch_signal (SIGSYS,  "SIGSYS",  on_p);
+#endif
+  catch_signal (SIGTERM, "SIGTERM", on_p);
+#ifdef SIGXCPU
+  catch_signal (SIGXCPU, "SIGXCPU", on_p);
+#endif
+#ifdef SIGXFSZ
+  catch_signal (SIGXFSZ, "SIGXFSZ", on_p);
+#endif
+#ifdef SIGDANGER
+  catch_signal (SIGDANGER, "SIGDANGER", on_p);
+#endif
+}
+
+\f
+/* Managing the actual screensaver window */
+
+Bool
+window_exists_p (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  int (*old_handler) ();
+  XWindowAttributes xgwa;
+  xgwa.screen = 0;
+  old_handler = XSetErrorHandler (BadWindow_ehandler);
+  XGetWindowAttributes (dpy, window, &xgwa);
+  XSync (dpy, False);
+  XSetErrorHandler (old_handler);
+  return (xgwa.screen != 0);
+}
+
+void
+initialize_screensaver_window P((void))
+{
+  /* This resets the screensaver window as fully as possible, since there's
+     no way of knowing what some random client may have done to us in the
+     meantime.  We could just destroy and recreate the window, but that has
+     its own set of problems...
+   */
+  XColor black;
+  XClassHint class_hints;
+  XSetWindowAttributes attrs;
+  unsigned long attrmask;
+  int width = WidthOfScreen (screen);
+  int height = HeightOfScreen (screen);
+  char id [2048];
+
+  reset_stderr ();
+
+  black.red = black.green = black.blue = 0;
+
+  if (cmap == DefaultColormapOfScreen (screen))
+    cmap = 0;
+
+  if (install_cmap_p || visual != DefaultVisualOfScreen (screen))
+    {
+      if (! cmap)
+       {
+         cmap = XCreateColormap (dpy, RootWindowOfScreen (screen),
+                                 visual, AllocNone);
+         if (! XAllocColor (dpy, cmap, &black)) abort ();
+         black_pixel = black.pixel;
+       }
+    }
+  else
+    {
+      if (cmap)
+       {
+         XFreeColors (dpy, cmap, &black_pixel, 1, 0);
+         XFreeColormap (dpy, cmap);
+       }
+      cmap = DefaultColormapOfScreen (screen);
+      black_pixel = BlackPixelOfScreen (screen);
+    }
+
+  if (cmap2)
+    {
+      XFreeColormap (dpy, cmap2);
+      cmap2 = 0;
+    }
+
+  if (fade_p)
+    {
+      cmap2 = copy_colormap (dpy, cmap, 0);
+      if (! cmap2)
+       fade_p = unfade_p = 0;
+    }
+
+  attrmask = (CWOverrideRedirect | CWEventMask | CWBackingStore | CWColormap |
+             CWBackPixel | CWBackingPixel | CWBorderPixel);
+  attrs.override_redirect = True;
+  attrs.event_mask = (KeyPressMask | KeyReleaseMask |
+                     ButtonPressMask | ButtonReleaseMask |
+                     PointerMotionMask);
+  attrs.backing_store = NotUseful;
+  attrs.colormap = cmap;
+  attrs.background_pixel = black_pixel;
+  attrs.backing_pixel = black_pixel;
+  attrs.border_pixel = black_pixel;
+
+#if 0
+  if (demo_mode_p || lock_p) width = width / 2;  /* #### */
+#endif
+
+  if (screensaver_window || !verbose_p)
+    ;
+  else if (visual == DefaultVisualOfScreen (screen))
+    {
+      fprintf (stderr, "%s: using default visual ", progname);
+      describe_visual (stderr, dpy, visual);
+    }
+  else
+    {
+      fprintf (stderr, "%s: using visual:   ", progname);
+      describe_visual (stderr, dpy, visual);
+      fprintf (stderr, "%s: default visual: ", progname);
+      describe_visual (stderr, dpy, DefaultVisualOfScreen (screen));
+    }
+
+#ifdef HAVE_SAVER_EXTENSION
+  if (use_saver_extension)
+    {
+      XScreenSaverInfo *info;
+      Window root = RootWindowOfScreen (screen);
+
+      /* This call sets the server screensaver timeouts to what we think
+        they should be (based on the resources and args xscreensaver was
+        started with.)  It's important that we do this to sync back up
+        with the server - if we have turned on prematurely, as by an
+        ACTIVATE ClientMessage, then the server may decide to activate
+        the screensaver while it's already active.  That's ok for us,
+        since we would know to ignore that ScreenSaverActivate event,
+        but a side effect of this would be that the server would map its
+        saver window (which we then hide again right away) meaning that
+        the bits currently on the screen get blown away.  Ugly. */
+#if 0
+      /* #### Ok, that doesn't work - when we tell the server that the
+        screensaver is "off" it sends us a Deactivate event, which is
+        sensible... but causes the saver to never come on.  Hmm. */
+      disable_builtin_screensaver ();
+#endif /* 0 */
+
+#if 0
+      /* #### The MIT-SCREEN-SAVER extension gives us access to the
+        window that the server itself uses for saving the screen.
+        However, using this window in any way, in particular, calling
+        XScreenSaverSetAttributes() as below, tends to make the X server
+        crash.  So fuck it, let's try and get along without using it...
+
+        It's also inconvenient to use this window because it doesn't
+        always exist (though the ID is constant.)  So to use this
+        window, we'd have to reimplement the ACTIVATE ClientMessage to
+        tell the *server* to tell *us* to turn on, to cause the window
+        to get created at the right time.  Gag.  */
+      XScreenSaverSetAttributes (dpy, root,
+                                0, 0, width, height, 0,
+                                visual_depth, InputOutput, visual,
+                                attrmask, &attrs);
+      XSync (dpy, False);
+#endif /* 0 */
+
+      info = XScreenSaverAllocInfo ();
+      XScreenSaverQueryInfo (dpy, root, info);
+      server_saver_window = info->window;
+      if (! server_saver_window) abort ();
+      XFree (info);
+    }
+#endif /* HAVE_SAVER_EXTENSION */
+
+  if (screensaver_window)
+    {
+      XWindowChanges changes;
+      unsigned int changesmask = CWX|CWY|CWWidth|CWHeight|CWBorderWidth;
+      changes.x = 0;
+      changes.y = 0;
+      changes.width = width;
+      changes.height = height;
+      changes.border_width = 0;
+
+      XConfigureWindow (dpy, screensaver_window, changesmask, &changes);
+      XChangeWindowAttributes (dpy, screensaver_window, attrmask, &attrs);
+    }
+  else
+    {
+      screensaver_window =
+       XCreateWindow (dpy, RootWindowOfScreen (screen), 0, 0, width, height,
+                      0, visual_depth, InputOutput, visual, attrmask,
+                      &attrs);
+    }
+
+#ifdef HAVE_SAVER_EXTENSION
+  if (!use_saver_extension ||
+      window_exists_p (dpy, screensaver_window))
+    /* When using the MIT-SCREEN-SAVER extension, the window pointed to
+       by screensaver_window only exists while the saver is active.
+       So we must be careful to only try and manipulate it while it
+       exists...
+     */
+#endif /* HAVE_SAVER_EXTENSION */
+    {
+      class_hints.res_name = progname;
+      class_hints.res_class = progclass;
+      XSetClassHint (dpy, screensaver_window, &class_hints);
+      XStoreName (dpy, screensaver_window, "screensaver");
+      XChangeProperty (dpy, screensaver_window, XA_SCREENSAVER_VERSION,
+                      XA_STRING, 8, PropModeReplace,
+                      (unsigned char *) screensaver_version,
+                      strlen (screensaver_version));
+
+      sprintf (id, "%d on host ", getpid ());
+      if (! XmuGetHostname (id + strlen (id), sizeof (id) - strlen (id) - 1))
+       strcat (id, "???");
+      XChangeProperty (dpy, screensaver_window, XA_SCREENSAVER_ID, XA_STRING,
+                      8, PropModeReplace, (unsigned char *) id, strlen (id));
+
+      if (!cursor)
+       {
+         Pixmap bit;
+         bit = XCreatePixmapFromBitmapData (dpy, screensaver_window, "\000",
+                                            1, 1,
+                                            BlackPixelOfScreen (screen),
+                                            BlackPixelOfScreen (screen), 1);
+         cursor = XCreatePixmapCursor (dpy, bit, bit, &black, &black, 0, 0);
+         XFreePixmap (dpy, bit);
+       }
+
+      XSetWindowBackground (dpy, screensaver_window, black_pixel);
+      if (! demo_mode_p)
+       XDefineCursor (dpy, screensaver_window, cursor);
+      else
+       XUndefineCursor (dpy, screensaver_window);
+    }
+}
+
+
+void 
+raise_window (inhibit_fade, between_hacks_p)
+     Bool inhibit_fade, between_hacks_p;
+{
+  initialize_screensaver_window ();
+
+  if (fade_p && !inhibit_fade && !demo_mode_p)
+    {
+      int grabbed;
+      Colormap current_map = (between_hacks_p
+                             ? cmap
+                             : DefaultColormapOfScreen (screen));
+      copy_colormap (dpy, current_map, cmap2);
+      XGrabServer (dpy);
+      /* grab and blacken mouse on the root window (saver not mapped yet) */
+      grabbed = grab_mouse (RootWindowOfScreen (screen));
+      /* fade what's on the screen to black */
+      XInstallColormap (dpy, cmap2);
+      fade_colormap (dpy, current_map, cmap2, fade_seconds, fade_ticks, True);
+      XClearWindow (dpy, screensaver_window);
+      XMapRaised (dpy, screensaver_window);
+
+#ifdef HAVE_SAVER_EXTENSION
+      if (server_saver_window && window_exists_p (dpy, server_saver_window))
+       XUnmapWindow (dpy, server_saver_window);
+#endif /* HAVE_SAVER_EXTENSION */
+
+      /* Once the saver window is up, restore the colormap.
+        (The "black" pixels of the two colormaps are compatible.) */
+      XInstallColormap (dpy, cmap);
+      if (grabbed == GrabSuccess)
+       XUngrabPointer (dpy, CurrentTime);
+      XUngrabServer (dpy);
+    }
+  else
+    {
+      XClearWindow (dpy, screensaver_window);
+      XMapRaised (dpy, screensaver_window);
+#ifdef HAVE_SAVER_EXTENSION
+      if (server_saver_window && window_exists_p (dpy, server_saver_window))
+       XUnmapWindow (dpy, server_saver_window);
+#endif /* HAVE_SAVER_EXTENSION */
+    }
+
+  if (install_cmap_p)
+    XInstallColormap (dpy, cmap);
+}
+
+#ifdef __hpux
+ /* Calls to XHPDisableReset and XHPEnableReset must be balanced,
+    or BadAccess errors occur. */
+static Bool hp_locked_p = False;
+#endif /* __hpux */
+
+void
+blank_screen ()
+{
+  save_real_vroot ();
+  store_vroot_property (screensaver_window, screensaver_window);
+  raise_window (False, False);
+  grab_keyboard_and_mouse ();
+#ifdef __hpux
+  if (lock_p && !hp_locked_p)
+    XHPDisableReset (dpy);     /* turn off C-Sh-Reset */
+  hp_locked_p = True;
+#endif
+}
+
+void
+unblank_screen ()
+{
+  if (unfade_p && !demo_mode_p)
+    {
+      int grabbed;
+      Colormap default_map = DefaultColormapOfScreen (screen);
+      blacken_colormap (dpy, cmap2);
+      XGrabServer (dpy);
+      /* grab and blacken mouse on the root window. */
+      grabbed = grab_mouse (RootWindowOfScreen (screen));
+      XInstallColormap (dpy, cmap2);
+      XUnmapWindow (dpy, screensaver_window);
+      fade_colormap (dpy, default_map, cmap2, fade_seconds, fade_ticks, False);
+      XInstallColormap (dpy, default_map);
+      if (grabbed == GrabSuccess)
+       XUngrabPointer (dpy, CurrentTime);
+      XUngrabServer (dpy);
+    }
+  else
+    {
+      if (install_cmap_p)
+       {
+         XClearWindow (dpy, screensaver_window); /* avoid technicolor */
+         XInstallColormap (dpy, DefaultColormapOfScreen (screen));
+       }
+      XUnmapWindow (dpy, screensaver_window);
+    }
+  kill_xsetroot_data ();
+  ungrab_keyboard_and_mouse ();
+  restore_real_vroot ();
+#ifdef __hpux
+  if (lock_p && hp_locked_p)
+    XHPEnableReset (dpy);      /* turn C-Sh-Reset back on */
+  hp_locked_p = False;
+#endif
+}
diff --git a/driver/xscreensaver-command.c b/driver/xscreensaver-command.c
new file mode 100644 (file)
index 0000000..d0aced9
--- /dev/null
@@ -0,0 +1,151 @@
+/* xscreensaver-command, Copyright (c) 1991-1995 
+ * Jamie Zawinski <jwz@netscape.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.
+ */
+
+#include "version.h"
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xos.h>
+#if __STDC__
+# include <stdlib.h>
+#endif
+
+#ifdef _VROOT_H_
+ERROR! you must not include vroot.h in this file
+#endif
+
+static char *screensaver_version;
+static char *usage = "usage: %s -<switch>\n\
+\n\
+  This program provides external control of a running xscreensaver process.\n\
+  Version %s, copyright (c) 1991-1994 Jamie Zawinski <jwz@netscape.com>.\n\
+\n\
+  -demo                Enter interactive demo mode.\n\
+  -deactivate  Turns off the screensaver if it is on, as user input would.\n\
+  -activate    Turns it on as if the user had been idle for long enough.\n\
+  -cycle       Stops the current hack and runs a new one.\n\
+  -next                Like either -activate or -cycle, depending on which is more\n\
+               appropriate, except that the screenhack that will be run is\n\
+               the next one in the list of hacks, instead of a randomly-\n\
+               chosen one.  This option is good for looking at a demo of\n\
+               each of the hacks in place.\n\
+  -prev                Like -next, but goes in the other direction.\n\
+  -exit                Causes the screensaver process to exit.  It should be ok to\n\
+               just kill the process (NOT with -9!) but this is a slightly\n\
+               easier way.\n\
+  -restart     Causes the screensaver process to exit and then restart with\n\
+               the same command line arguments.  This is a good way of \n\
+               causing the screensaver to re-read the resource database.\n\
+  -lock         Same as -activate, but with immediate locking.\n\
+\n\
+  See the man page for more details.\n\n";
+
+static Window
+find_screensaver_window (dpy, progname)
+     Display *dpy;
+     char *progname;
+{
+  int i;
+  Window root = RootWindowOfScreen (DefaultScreenOfDisplay (dpy));
+  Window root2, parent, *kids;
+  unsigned int nkids;
+
+  if (! XQueryTree (dpy, root, &root2, &parent, &kids, &nkids))
+    abort ();
+  if (root != root2)
+    abort ();
+  if (parent)
+    abort ();
+  if (! (kids && nkids))
+    abort ();
+  for (i = 0; i < nkids; i++)
+    {
+      Atom type;
+      int format;
+      unsigned long nitems, bytesafter;
+      char *version;
+
+      if (XGetWindowProperty (dpy, kids[i],
+                             XInternAtom (dpy, "_SCREENSAVER_VERSION", False),
+                             0, 1, False, XA_STRING,
+                             &type, &format, &nitems, &bytesafter,
+                             (unsigned char **) &version)
+         == Success
+         && type != None)
+       return kids[i];
+    }
+  fprintf (stderr, "%s: no screensaver is running on display %s\n", progname,
+          DisplayString (dpy));
+  exit (1);
+}
+
+
+#define USAGE() \
+ { fprintf (stderr, usage, argv[0], screensaver_version); exit (1); }
+
+void
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  Display *dpy;
+  Window window;
+  XEvent event;
+  int i;
+  char *message = 0, *dpyname = 0;
+  screensaver_version = (char *) malloc (5);
+  memcpy (screensaver_version, screensaver_id + 17, 4);
+  screensaver_version [4] = 0;
+  for (i = 1; i < argc; i++)
+    {
+      char *s = argv [i];
+      int L = strlen (s);
+      if (L < 2) USAGE ();
+      if (!strncmp (s, "-display", L))         dpyname = argv [++i];
+      else if (message) USAGE ()
+      else if (!strncmp (s, "-activate", L))   message = "ACTIVATE";
+      else if (!strncmp (s, "-deactivate", L)) message = "DEACTIVATE";
+      else if (!strncmp (s, "-cycle", L))      message = "CYCLE";
+      else if (!strncmp (s, "-next", L))       message = "NEXT";
+      else if (!strncmp (s, "-prev", L))       message = "PREV";
+      else if (!strncmp (s, "-exit", L))       message = "EXIT";
+      else if (!strncmp (s, "-restart", L))    message = "RESTART";
+      else if (!strncmp (s, "-demo", L))       message = "DEMO";
+      else if (!strncmp (s, "-lock", L))       message = "LOCK";
+      else USAGE ();
+    }
+  if (! message) USAGE ();
+  if (!dpyname) dpyname = (char *) getenv ("DISPLAY");
+  dpy = XOpenDisplay (dpyname);
+  if (!dpy)
+    {
+      fprintf (stderr, "%s: can't open display %s\n", argv[0],
+              (dpyname ? dpyname : "(null)"));
+      exit (1);
+    }
+  window = find_screensaver_window (dpy, argv[0]);
+
+  event.xany.type = ClientMessage;
+  event.xclient.display = dpy;
+  event.xclient.window = window;
+  event.xclient.message_type = XInternAtom (dpy, "SCREENSAVER", False);
+  event.xclient.format = 32;
+  event.xclient.data.l[0] = (long) XInternAtom (dpy, message, False);
+  if (! XSendEvent (dpy, window, False, 0L, &event))
+    {
+      fprintf (stderr, "%s: XSendEvent(dpy, 0x%x ...) failed.\n", argv [0],
+              (unsigned int) window);
+      exit (1);
+    }
+  XSync (dpy, 0);
+  exit (0);
+}
diff --git a/driver/xscreensaver-command.man b/driver/xscreensaver-command.man
new file mode 100644 (file)
index 0000000..06e88cb
--- /dev/null
@@ -0,0 +1,110 @@
+.de EX         \"Begin example
+.ne 5
+.if n .sp 1
+.if t .sp .5
+.nf
+.in +.5i
+..
+.de EE
+.fi
+.in -.5i
+.if n .sp 1
+.if t .sp .5
+..
+.TH XScreenSaver 1 "22-mar-93" "X Version 11"
+.SH NAME
+xscreensaver-command - control a running xscreensaver process
+.SH SYNOPSIS
+.B xscreensaver-command
+[\-activate] [\-deactivate] [\-cycle] [\-next] [\-prev] [\-exit] [\-restart] [\-demo] [\-lock]
+.SH DESCRIPTION
+The \fIxscreensaver\-command\fP program controls a running \fIxscreensaver\fP
+process by sending it client-messages.
+.SH OPTIONS
+.I xscreensaver-command
+accepts the following options:
+.TP 8
+.B \-activate
+Tell the screensaver to turn on immediately (that is, pretend that the 
+user been idle for long enough.)  It will turn off as soon as there is
+any user activity, as usual.
+
+It is useful to run this from a menu; you may wish to run it as
+.EX
+sleep 5 ; xscreensaver-command -activate
+.EE
+to be sure that you have time to remove your hand from the mouse before
+the screensaver comes on.
+.TP 8
+.B \-deactivate
+Tell the screensaver to turn off, as if there had been user activity.
+If locking is enabled, then the screensaver will prompt for a password
+as usual.
+.TP 8
+.B \-cycle
+Tell the screensaver to change which graphics hack it is running, just
+as if the ``cycle'' timer had expired.
+.TP 8
+.B \-next
+This is like either \fI\-activate\fP or \fI\-cycle\fP, depending on which is
+more appropriate, except that the screenhack that will be run is the next
+one in the list of programs, instead of a randomly-chosen one.  This option
+is good for looking at a demo of each of the screensavers currently available.
+You might want to put this on a menu.
+.TP 8
+.B \-prev
+This is like \fI\-next\fP, but cycles in the other direction.
+.TP 8
+.B \-demo
+Cause the screensaver to enter its interactive demo mode, if it has been
+compiled with support for it.
+.TP 8
+.B \-lock
+Like \fI\-activate\fP, but a password will be required before the screensaver
+turns off, even if the screensaver's \fIlock\fP resource is false.  The 
+display will be locked immediately even if the screensaver's \fIlockTimeout\fP
+resource is non-zero.
+.TP 8
+.B \-exit
+Causes the screensaver process to exit gracefully.  This is a slightly
+safer way to kill the screensaver than by using \fIkill\fP.  
+
+Never use \fIkill -9\fP with \fIxscreensaver\fP while the screensaver is
+active.  If you are using a virtual root window manager, that can leave
+things in an inconsistent state, and you may need to restart your window
+manager to repair the damage.
+.TP 8
+.B \-restart
+Causes the screensaver process to exit and then restart with the same command
+line arguments.  This is a good way of causing the screensaver to re-read the
+resource database.
+
+If the screensaver is run from \fIxdm(1)\fP (that is, it is already running
+before you log in) then you may want to issue the ``restart'' command from 
+one of your startup scripts, so that the screensaver gets your resource
+settings instead of the default ones.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B PATH
+to find the executable to restart.
+.SH "SEE ALSO"
+.BR X (1),
+.BR xscreensaver (1)
+.SH BUGS
+Diagnostics are reported on the \fBstderr\fP of the \fIxscreensaver\fP
+process, not this process, so the caller of \fIxscreensaver-command\fP
+may not see the error messages.
+.SH COPYRIGHT
+Copyright \(co 1992, 1993 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@netscape.com>, 13-aug-92.
diff --git a/driver/xscreensaver.c b/driver/xscreensaver.c
new file mode 100644 (file)
index 0000000..76f68c2
--- /dev/null
@@ -0,0 +1,1111 @@
+/* xscreensaver, Copyright (c) 1991-1995 Jamie Zawinski <jwz@netscape.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.
+ */
+
+#include "version.h"
+
+/*   ========================================================================
+ *   First we wait until the keyboard and mouse become idle for the specified
+ *   amount of time.  We do this in one of three different ways: periodically
+ *   checking with the XIdle server extension; selecting key and mouse events
+ *   on (nearly) all windows; or by waiting for the MIT-SCREEN-SAVER extension
+ *   to send us a "you are idle" event.
+ *
+ *   Then, we map a full screen black window (or, in the case of the 
+ *   MIT-SCREEN-SAVER extension, use the one it gave us.)
+ *
+ *   We place a __SWM_VROOT property on this window, so that newly-started
+ *   clients will think that this window is a "virtual root" window.
+ *
+ *   If there is an existing "virtual root" window (one that already had
+ *   an __SWM_VROOT property) then we remove that property from that window.
+ *   Otherwise, clients would see that window (the real virtual root) instead
+ *   of ours (the impostor.)
+ *
+ *   Then we pick a random program to run, and start it.  Two assumptions 
+ *   are made about this program: that it has been specified with whatever
+ *   command-line options are necessary to make it run on the root window;
+ *   and that it has been compiled with vroot.h, so that it is able to find
+ *   the root window when a virtual-root window manager (or this program) is
+ *   running.
+ *
+ *   Then, we wait for keyboard or mouse events to be generated on the window.
+ *   When they are, we kill the inferior process, unmap the window, and restore
+ *   the __SWM_VROOT property to the real virtual root window if there was one.
+ *
+ *   While we are waiting, we also set up timers so that, after a certain 
+ *   amount of time has passed, we can start a different screenhack.  We do
+ *   this by killing the running child process with SIGTERM, and then starting
+ *   a new one in the same way.
+ *
+ *   If there was a real virtual root, meaning that we removed the __SWM_VROOT
+ *   property from it, meaning we must (absolutely must) restore it before we
+ *   exit, then we set up signal handlers for most signals (SIGINT, SIGTERM,
+ *   etc.) that do this.  Most Xlib and Xt routines are not reentrant, so it
+ *   is not generally safe to call them from signal handlers; however, this
+ *   program spends most of its time waiting, so the window of opportunity 
+ *   when code could be called reentrantly is fairly small; and also, the worst
+ *   that could happen is that the call would fail.  If we've gotten one of
+ *   these signals, then we're on our way out anyway.  If we didn't restore the
+ *   __SWM_VROOT property, that would be very bad, so it's worth a shot.  Note
+ *   that this means that, if you're using a virtual-root window manager, you
+ *   can really fuck up the world by killing this process with "kill -9".
+ *
+ *   This program accepts ClientMessages of type SCREENSAVER; these messages
+ *   may contain the atom ACTIVATE or DEACTIVATE, meaning to turn the 
+ *   screensaver on or off now, regardless of the idleness of the user,
+ *   and a few other things.  The included "xscreensaver_command" program
+ *   sends these messsages.
+ *
+ *   If we don't have the XIdle or MIT-SCREENSAVER extensions, then we do the
+ *   XAutoLock trick: notice every window that gets created, and wait 30
+ *   seconds or so until its creating process has settled down, and then
+ *   select KeyPress events on those windows which already select for
+ *   KeyPress events.  It's important that we not select KeyPress on windows
+ *   which don't select them, because that would interfere with event
+ *   propagation.  This will break if any program changes its event mask to
+ *   contain KeyRelease or PointerMotion more than 30 seconds after creating
+ *   the window, but that's probably pretty rare.
+ *   
+ *   The reason that we can't select KeyPresses on windows that don't have
+ *   them already is that, when dispatching a KeyPress event, X finds the
+ *   lowest (leafmost) window in the hierarchy on which *any* client selects
+ *   for KeyPress, and sends the event to that window.  This means that if a
+ *   client had a window with subwindows, and expected to receive KeyPress
+ *   events on the parent window instead of the subwindows, then that client
+ *   would malfunction if some other client selected KeyPress events on the
+ *   subwindows.  It is an incredible misdesign that one client can make
+ *   another client malfunction in this way.
+ *
+ *   To detect mouse motion, we periodically wake up and poll the mouse
+ *   position and button/modifier state, and notice when something has
+ *   changed.  We make this check every five seconds by default, and since the
+ *   screensaver timeout has a granularity of one minute, this makes the
+ *   chance of a false positive very small.  We could detect mouse motion in
+ *   the same way as keyboard activity, but that would suffer from the same
+ *   "client changing event mask" problem that the KeyPress events hack does.
+ *   I think polling is more reliable.
+ *
+ *   None of this crap happens if we're using one of the extensions, so install
+ *   one of them if the description above sounds just too flaky to live.  It
+ *   is, but those are your choices.
+ *
+ *   A third idle-detection option could be implement (but is not): when
+ *   running on the console display ($DISPLAY is `localhost`:0) and we're on a
+ *   machine where /dev/tty and /dev/mouse have reasonable last-modification
+ *   times, we could just stat those.  But the incremental benefit of
+ *   implementing this is really small, so forget I said anything.
+ *
+ *   Debugging hints:
+ *     - Have a second terminal handy.
+ *     - Be careful where you set your breakpoints, you don't want this to
+ *       stop under the debugger with the keyboard grabbed or the blackout
+ *       window exposed.
+ *     - you probably can't set breakpoints in functions that are called on
+ *       the other side of a call to fork() -- if your clients are dying 
+ *       with signal 5, Trace/BPT Trap, you're losing in this way.
+ *     - If you aren't using XIdle, don't leave this stopped under the
+ *       debugger for very long, or the X input buffer will get huge because
+ *       of the keypress events it's selecting for.  This can make your X
+ *       server wedge with "no more input buffers."
+ *       
+ *   ======================================================================== */
+
+#if __STDC__
+#include <stdlib.h>
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Intrinsic.h>
+#include <X11/Xos.h>
+#include <X11/Xmu/Error.h>
+
+#ifdef HAVE_XIDLE_EXTENSION
+#include <X11/extensions/xidle.h>
+#endif /* HAVE_XIDLE_EXTENSION */
+
+#ifdef HAVE_SAVER_EXTENSION
+#include <X11/extensions/scrnsaver.h>
+#endif /* HAVE_SAVER_EXTENSION */
+
+#include "yarandom.h"
+#include "xscreensaver.h"
+
+extern char *get_string_resource P((char *, char *));
+extern Bool get_boolean_resource P((char *, char *));
+extern int get_integer_resource P((char *, char *));
+extern unsigned int get_minutes_resource P((char *, char *));
+extern unsigned int get_seconds_resource P((char *, char *));
+
+extern Visual *get_visual_resource P((Display *, char *, char *));
+extern int get_visual_depth P((Display *, Visual *));
+
+extern void notice_events_timer P((XtPointer closure, XtIntervalId *timer));
+extern void cycle_timer P((void *junk1, XtPointer junk2));
+extern void activate_lock_timer P((void *junk1, XtPointer junk2));
+extern void sleep_until_idle P((Bool until_idle_p));
+
+extern void ensure_no_screensaver_running P((void));
+extern void initialize_screensaver_window P((void));
+extern void disable_builtin_screensaver P((void));
+
+extern void hack_environment P((void));
+extern void grab_keyboard_and_mouse P((void));
+extern void ungrab_keyboard_and_mouse P((void));
+
+extern void save_argv P((int argc, char **argv));
+
+extern void initialize_stderr P((void));
+
+char *screensaver_version;
+char *progname;
+char *progclass;
+XrmDatabase db;
+
+XtAppContext app;
+
+Display *dpy;
+Screen *screen;
+Visual *visual;
+int visual_depth;
+
+Widget toplevel_shell;
+
+Time lock_timeout;
+
+extern Time timeout;
+extern Time cycle;
+#ifndef NO_LOCKING
+extern Time passwd_timeout;
+#endif
+extern Time pointer_timeout;
+extern Time notice_events_timeout;
+extern XtIntervalId lock_id, cycle_id;
+
+Bool use_xidle_extension;
+Bool use_saver_extension;
+Bool verbose_p;
+Bool lock_p, locked_p;
+
+extern char **screenhacks;
+extern int screenhacks_count;
+extern char *shell;
+extern int nice_inferior;
+extern Window screensaver_window;
+extern Cursor cursor;
+extern Colormap cmap, cmap2;
+extern Bool fade_p, unfade_p;
+extern int fade_seconds, fade_ticks;
+extern Bool install_cmap_p;
+extern Bool locking_disabled_p;
+extern char *nolock_reason;
+extern Bool demo_mode_p;
+extern Bool dbox_up_p;
+extern int next_mode_p;
+
+#ifdef HAVE_SAVER_EXTENSION
+int saver_ext_event_number = 0;
+int saver_ext_error_number = 0;
+#endif /* HAVE_SAVER_EXTENSION */
+
+static time_t initial_delay;
+
+extern Atom XA_VROOT, XA_XSETROOT_ID;
+extern Atom XA_SCREENSAVER_VERSION, XA_SCREENSAVER_ID;
+
+static Atom XA_SCREENSAVER;
+static Atom XA_ACTIVATE, XA_DEACTIVATE, XA_CYCLE, XA_NEXT, XA_PREV;
+static Atom XA_EXIT, XA_RESTART, XA_DEMO, XA_LOCK;
+
+#ifdef NO_MOTIF /* kludge */
+Bool demo_mode_p = 0;
+Bool dbox_up_p = 0;
+#endif
+
+\f
+#ifdef NO_DEMO_MODE
+# define demo_mode() abort()
+#else
+extern void demo_mode P((void));
+#endif
+\f
+static XrmOptionDescRec options [] = {
+  { "-timeout",                   ".timeout",          XrmoptionSepArg, 0 },
+  { "-cycle",             ".cycle",            XrmoptionSepArg, 0 },
+  { "-idelay",            ".initialDelay",     XrmoptionSepArg, 0 },
+  { "-nice",              ".nice",             XrmoptionSepArg, 0 },
+  { "-visual",            ".visualID",         XrmoptionSepArg, 0 },
+  { "-lock-timeout",      ".lockTimeout",      XrmoptionSepArg, 0 },
+  { "-install",                   ".installColormap",  XrmoptionNoArg, "on" },
+  { "-no-install",        ".installColormap",  XrmoptionNoArg, "off" },
+  { "-verbose",                   ".verbose",          XrmoptionNoArg, "on" },
+  { "-silent",            ".verbose",          XrmoptionNoArg, "off" },
+  { "-xidle-extension",           ".xidleExtension",   XrmoptionNoArg, "on" },
+  { "-no-xidle-extension", ".xidleExtension",  XrmoptionNoArg, "off" },
+  { "-ss-extension",      ".saverExtension",   XrmoptionNoArg, "on" },
+  { "-no-ss-extension",           ".saverExtension",   XrmoptionNoArg, "off" },
+  { "-lock",              ".lock",             XrmoptionNoArg, "on" },
+  { "-no-lock",                   ".lock",             XrmoptionNoArg, "off" }
+};
+
+static char *defaults[] = {
+#include "XScreenSaver.ad.h"
+ 0
+};
+
+static void
+do_help P((void))
+{
+  printf ("\
+xscreensaver %s, copyright (c) 1991-1995 by Jamie Zawinski <jwz@netscape.com>.\n\
+The standard Xt command-line options are accepted; other options include:\n\
+\n\
+    -timeout <minutes>         When the screensaver should activate.\n\
+    -cycle <minutes>           How long to let each hack run.\n\
+    -idelay <seconds>          How long to sleep before startup.\n\
+    -visual <id-or-class>      Which X visual to run on.\n\
+    -demo                      Enter interactive demo mode on startup.\n\
+    -install                   Install a private colormap.\n\
+    -no-install                Don't.\n\
+    -verbose                   Be loud.\n\
+    -silent                    Don't.\n\
+    -xidle-extension           Use the R5 XIdle server extension.\n\
+    -no-xidle-extension        Don't.\n\
+    -ss-extension              Use the R6 MIT-SCREEN-SAVER server extension.\n\
+    -no-ss-extension           Don't.\n\
+    -lock                      Require a password before deactivating.\n\
+    -no-lock                   Don't.\n\
+    -lock-timeout <minutes>    Grace period before locking; default 0.\n\
+    -help                      This message.\n\
+\n\
+Use the `xscreensaver-command' program to control a running screensaver.\n\
+\n\
+The *programs, *colorPrograms, and *monoPrograms resources control which\n\
+graphics demos will be launched by the screensaver.  See the man page for\n\
+more details.\n\n",
+         screensaver_version);
+
+#ifdef NO_LOCKING
+  printf ("Support for locking was not enabled at compile-time.\n");
+#endif
+#ifdef NO_DEMO_MODE
+  printf ("Support for demo mode was not enabled at compile-time.\n");
+#endif
+#if !defined(HAVE_XIDLE_EXTENSION) && !defined(HAVE_SAVER_EXTENSION)
+  printf ("Support for the XIDLE and MIT-SCREEN-SAVER server extensions\
+ was not\nenabled at compile-time.\n");
+#endif /* !HAVE_XIDLE_EXTENSION && !HAVE_SAVER_EXTENSION */
+
+  fflush (stdout);
+  exit (1);
+}
+
+
+static void
+get_screenhacks P((void))
+{
+  char *data[3];
+  int i, hacks_size = 10;
+
+  data[0] = get_string_resource ("programs", "Programs");
+  data[1] = ((CellsOfScreen (screen) <= 2)
+            ? get_string_resource ("monoPrograms", "MonoPrograms")
+            : get_string_resource ("colorPrograms", "ColorPrograms"));
+  data[2] = 0;
+  if (! data[0]) data[0] = data[1], data[1] = 0;
+
+  screenhacks = (char **) malloc (sizeof (char *) * hacks_size);
+  screenhacks_count = 0;
+
+  for (i = 0; data[i]; i++)
+    {
+      int j = 0;
+      char *d = data [i];
+      int size = strlen (d);
+      while (j < size)
+       {
+         int end, start = j;
+         if (d[j] == ' ' || d[j] == '\t' || d[j] == '\n' || d[j] == 0)
+           {
+             j++;
+             continue;
+           }
+         if (hacks_size <= screenhacks_count)
+           screenhacks = (char **) realloc (screenhacks,
+                                            (hacks_size = hacks_size * 2) *
+                                            sizeof (char *));
+         screenhacks [screenhacks_count++] = d + j;
+         while (d[j] != 0 && d[j] != '\n')
+           j++;
+         end = j;
+         while (j > start && (d[j-1] == ' ' || d[j-1] == '\t'))
+           j--;
+         d[j] = 0;
+         j = end + 1;
+       }
+    }
+
+  /* shrink all whitespace to one space, for the benefit of the "demo"
+     mode display.  We only do this when we can easily tell that the
+     whitespace is not significant (no shell metachars).
+   */
+  for (i = 0; i < screenhacks_count; i++)
+    {
+      char *s = screenhacks [i];
+      char *s2;
+      int L = strlen (s);
+      int j, k;
+      for (j = 0; j < L; j++)
+       {
+         switch (s[j])
+           {
+           case '\'': case '"': case '`': case '\\':
+             goto DONE;
+           case '\t':
+             s[j] = ' ';
+           case ' ':
+             k = 0;
+             for (s2 = s+j+1; *s2 == ' ' || *s2 == '\t'; s2++)
+               k++;
+             if (k > 0)
+               for (s2 = s + j + 1; *s2; s2++)
+                 s2 [0] = s2 [k];
+             break;
+           }
+       }
+    DONE:
+      ;
+    }
+
+  if (screenhacks_count)
+    {
+      /* Shrink down the screenhacks array to be only as big as it needs to.
+        This doesn't really matter at all. */
+      screenhacks = (char **)
+       realloc (screenhacks, ((screenhacks_count + 1) * sizeof(char *)));
+      screenhacks [screenhacks_count] = 0;
+    }
+  else
+    {
+      free (screenhacks);
+      screenhacks = 0;
+    }
+}
+
+
+static void
+get_resources P((void))
+{
+  /* Note: we can't use the resource ".visual" because Xt is SO FUCKED. */
+  visual         = get_visual_resource (dpy, "visualID", "VisualID");
+  timeout         = 1000 * get_minutes_resource ("timeout", "Time");
+  cycle           = 1000 * get_minutes_resource ("cycle",   "Time");
+  lock_timeout   = 1000 * get_minutes_resource ("lockTimeout", "Time");
+  nice_inferior   = get_integer_resource ("nice", "Nice");
+  verbose_p       = get_boolean_resource ("verbose", "Boolean");
+  lock_p          = get_boolean_resource ("lock", "Boolean");
+  install_cmap_p  = get_boolean_resource ("installColormap", "Boolean");
+  fade_p         = get_boolean_resource ("fade", "Boolean");
+  unfade_p       = get_boolean_resource ("unfade", "Boolean");
+  fade_seconds   = get_seconds_resource ("fadeSeconds", "Time");
+  fade_ticks     = get_integer_resource ("fadeTicks", "Integer");
+  shell           = get_string_resource ("bourneShell", "BourneShell");
+  initial_delay   = get_seconds_resource ("initialDelay", "Time");
+  pointer_timeout = 1000 * get_seconds_resource ("pointerPollTime", "Time");
+  notice_events_timeout = 1000 * get_seconds_resource ("windowCreationTimeout",
+                                                      "Time");
+#ifndef NO_LOCKING
+  passwd_timeout  = 1000 * get_seconds_resource ("passwdTimeout", "Time");
+  if (passwd_timeout == 0) passwd_timeout = 30000;
+#endif
+  if (timeout < 10000) timeout = 10000;
+  if (cycle != 0 && cycle < 2000) cycle = 2000;
+  if (pointer_timeout == 0) pointer_timeout = 5000;
+  if (notice_events_timeout == 0) notice_events_timeout = 10000;
+  if (fade_seconds == 0 || fade_ticks == 0) fade_p = False;
+  if (! fade_p) unfade_p = False;
+
+  visual_depth = get_visual_depth (dpy, visual);
+
+  if (visual_depth <= 1 || CellsOfScreen (screen) <= 2)
+    install_cmap_p = False;
+
+#ifdef NO_LOCKING
+  locking_disabled_p = True;
+  nolock_reason = "not compiled with locking support";
+  if (lock_p)
+    {
+      lock_p = False;
+      fprintf (stderr, "%s: %snot compiled with support for locking.\n",
+              progname, (verbose_p ? "## " : ""));
+    }
+#else  /* ! NO_LOCKING */
+  if (lock_p && locking_disabled_p)
+    {
+      fprintf (stderr, "%s: %slocking is disabled (%s).\n", progname,
+              (verbose_p ? "## " : ""), nolock_reason);
+      lock_p = False;
+    }
+#endif /* ! NO_LOCKING */
+
+  /* don't set use_xidle_extension unless it is explicitly specified */
+  if (get_string_resource ("xidleExtension", "Boolean"))
+    use_xidle_extension = get_boolean_resource ("xidleExtension", "Boolean");
+  else
+#ifdef HAVE_XIDLE_EXTENSION    /* pick a default */
+    use_xidle_extension = True;
+#else  /* !HAVE_XIDLE_EXTENSION */
+    use_xidle_extension = False;
+#endif /* !HAVE_XIDLE_EXTENSION */
+
+  /* don't set use_saver_extension unless it is explicitly specified */
+  if (get_string_resource ("saverExtension", "Boolean"))
+    use_saver_extension = get_boolean_resource ("saverExtension", "Boolean");
+  else
+#ifdef HAVE_SAVER_EXTENSION    /* pick a default */
+    use_saver_extension = True;
+#else  /* !HAVE_SAVER_EXTENSION */
+    use_saver_extension = False;
+#endif /* !HAVE_SAVER_EXTENSION */
+
+
+  get_screenhacks ();
+}
+
+char *
+timestring P((void))
+{
+  long now = time ((time_t *) 0);
+  char *str = (char *) ctime (&now);
+  char *nl = (char *) strchr (str, '\n');
+  if (nl) *nl = 0; /* take off that dang newline */
+  return str;
+}
+
+#ifdef NO_SETUID
+# define hack_uid()
+# define hack_uid_warn()
+#else /* !NO_SETUID */
+extern void hack_uid P((void));
+extern void hack_uid_warn P((void));
+#endif /* NO_SETUID */
+
+
+#ifndef NO_LOCKING
+extern Bool unlock_p P((Widget));
+extern Bool lock_init P((void));
+#endif
+
+static void initialize P((int argc, char **argv));
+static void main_loop P((void));
+
+void
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  initialize (argc, argv);
+  main_loop ();
+}
+
+
+static int
+saver_ehandler (dpy, error)
+     Display *dpy;
+     XErrorEvent *error;
+{
+  fprintf (real_stderr, "\nX error in %s:\n", progname);
+  if (XmuPrintDefaultErrorMessage (dpy, error, real_stderr))
+    exit (-1);
+  else
+    fprintf (real_stderr, " (nonfatal.)\n");
+  return 0;
+}
+
+static void
+#if __STDC__
+initialize_connection (int argc, char **argv)
+#else
+initialize_connection (argc, argv)
+     int argc;
+     char **argv;
+#endif
+{
+  toplevel_shell = XtAppInitialize (&app, progclass,
+                                   options, XtNumber (options),
+                                   &argc, argv, defaults, 0, 0);
+
+  dpy = XtDisplay (toplevel_shell);
+  screen = XtScreen (toplevel_shell);
+  db = XtDatabase (dpy);
+  XtGetApplicationNameAndClass (dpy, &progname, &progclass);
+
+  if (argc == 2 && !strcmp (argv[1], "-help"))
+    do_help ();
+  else if (argc > 1)
+    {
+      fprintf (stderr, "%s: unknown option %s\n", progname, argv [1]);
+      exit (1);
+    }
+  get_resources ();
+  hack_uid_warn ();
+  hack_environment ();
+  XA_VROOT = XInternAtom (dpy, "__SWM_VROOT", False);
+  XA_SCREENSAVER = XInternAtom (dpy, "SCREENSAVER", False);
+  XA_SCREENSAVER_VERSION = XInternAtom (dpy, "_SCREENSAVER_VERSION", False);
+  XA_SCREENSAVER_ID = XInternAtom (dpy, "_SCREENSAVER_ID", False);
+  XA_XSETROOT_ID = XInternAtom (dpy, "_XSETROOT_ID", False);
+  XA_ACTIVATE = XInternAtom (dpy, "ACTIVATE", False);
+  XA_DEACTIVATE = XInternAtom (dpy, "DEACTIVATE", False);
+  XA_RESTART = XInternAtom (dpy, "RESTART", False);
+  XA_CYCLE = XInternAtom (dpy, "CYCLE", False);
+  XA_NEXT = XInternAtom (dpy, "NEXT", False);
+  XA_PREV = XInternAtom (dpy, "PREV", False);
+  XA_EXIT = XInternAtom (dpy, "EXIT", False);
+  XA_DEMO = XInternAtom (dpy, "DEMO", False);
+  XA_LOCK = XInternAtom (dpy, "LOCK", False);
+}
+
+#ifdef HAVE_SAVER_EXTENSION
+
+static int
+ignore_all_errors_ehandler (dpy, error)
+     Display *dpy;
+     XErrorEvent *error;
+{
+  return 0;
+}
+
+static void
+init_saver_extension ()
+{
+  XID kill_id;
+  Atom kill_type;
+  Window root = RootWindowOfScreen (screen);
+  XScreenSaverInfo *info;
+  Pixmap blank_pix = XCreatePixmap (dpy, root, 1, 1, 1);
+
+  /* Kill off the old MIT-SCREEN-SAVER client if there is one.
+     This tends to generate X errors, though (possibly due to a bug
+     in the server extension itself?) so just ignore errors here. */
+  if (XScreenSaverGetRegistered (dpy, XScreenNumberOfScreen (screen),
+                                &kill_id, &kill_type)
+      && kill_id != blank_pix)
+    {
+      int (*old_handler) ();
+      old_handler = XSetErrorHandler (ignore_all_errors_ehandler);
+      XKillClient (dpy, kill_id);
+      XSync (dpy, False);
+      XSetErrorHandler (old_handler);
+    }
+
+  XScreenSaverSelectInput (dpy, root, ScreenSaverNotifyMask);
+
+  XScreenSaverRegister (dpy, XScreenNumberOfScreen (screen),
+                       (XID) blank_pix, XA_PIXMAP);
+  info = XScreenSaverAllocInfo ();
+
+#if 0
+  /* #### I think this is noticing that the saver is on, and replacing it
+     without turning it off first. */
+  saver = info->window;
+  if (info->state == ScreenSaverOn)
+    {
+      if (info->kind != ScreenSaverExternal) 
+       {
+         XResetScreenSaver (display);
+         XActivateScreenSaver (display);
+       }
+      StartSaver ();
+    }
+#endif
+}
+#endif /* HAVE_SAVER_EXTENSION */
+
+
+extern void init_sigchld P((void));
+
+static void
+initialize (argc, argv)
+     int argc;
+     char **argv;
+{
+  Bool initial_demo_mode_p = False;
+  screensaver_version = (char *) malloc (5);
+  memcpy (screensaver_version, screensaver_id + 17, 4);
+  screensaver_version [4] = 0;
+  progname = argv[0]; /* reset later; this is for the benefit of lock_init() */
+
+#ifdef NO_LOCKING
+  locking_disabled_p = True;
+  nolock_reason = "not compiled with locking support";
+#else
+  locking_disabled_p = False;
+
+#ifdef SCO
+  set_auth_parameters(argc, argv);
+#endif
+
+  if (! lock_init ())  /* before hack_uid() for proper permissions */
+    {
+      locking_disabled_p = True;
+      nolock_reason = "error getting password";
+    }
+#endif
+
+  hack_uid ();
+  progclass = "XScreenSaver";
+
+  /* remove -demo switch before saving argv */
+  {
+    int i;
+    for (i = 1; i < argc; i++)
+      while (!strcmp ("-demo", argv [i]))
+       {
+         int j;
+         initial_demo_mode_p = True;
+         for (j = i; j < argc; j++)
+           argv [j] = argv [j+1];
+         argv [j] = 0;
+         argc--;
+         if (argc <= i) break;
+       }
+  }
+  save_argv (argc, argv);
+  initialize_connection (argc, argv);
+  ensure_no_screensaver_running ();
+
+  if (verbose_p)
+    printf ("\
+%s %s, copyright (c) 1991-1995 by Jamie Zawinski <jwz@netscape.com>.\n\
+ pid = %d.\n", progname, screensaver_version, getpid ());
+  ensure_no_screensaver_running ();
+
+  demo_mode_p = initial_demo_mode_p;
+  screensaver_window = 0;
+  cursor = 0;
+  initialize_screensaver_window ();
+  srandom ((int) time ((time_t *) 0));
+  cycle_id = 0;
+  lock_id = 0;
+  locked_p = False;
+
+  if (use_saver_extension)
+    {
+#ifdef HAVE_SAVER_EXTENSION
+      if (! XScreenSaverQueryExtension (dpy,
+                                       &saver_ext_event_number,
+                                       &saver_ext_error_number))
+       {
+         fprintf (stderr,
+        "%s: %sdisplay %s does not support the MIT-SCREEN-SAVER extension.\n",
+                  progname, (verbose_p ? "## " : ""), DisplayString (dpy));
+         use_saver_extension = False;
+       }
+      else if (use_xidle_extension)
+       {
+         fprintf (stderr,
+        "%s: %sMIT-SCREEN-SAVER extension used instead of XIDLE extension.\n",
+                  progname, (verbose_p ? "## " : ""));
+         use_xidle_extension = False;
+       }
+#else  /* !HAVE_SAVER_EXTENSION */
+      fprintf (stderr,
+       "%s: %snot compiled with support for the MIT-SCREEN-SAVER extension.\n",
+              progname, (verbose_p ? "## " : ""));
+      use_saver_extension = False;
+#endif /* !HAVE_SAVER_EXTENSION */
+    }
+
+  if (use_xidle_extension)
+    {
+#ifdef HAVE_XIDLE_EXTENSION
+      int first_event, first_error;
+      if (! XidleQueryExtension (dpy, &first_event, &first_error))
+       {
+         fprintf (stderr,
+                  "%s: %sdisplay %s does not support the XIdle extension.\n",
+                  progname, (verbose_p ? "## " : ""), DisplayString (dpy));
+         use_xidle_extension = False;
+       }
+#else  /* !HAVE_XIDLE_EXTENSION */
+      fprintf (stderr, "%s: %snot compiled with support for XIdle.\n",
+              progname, (verbose_p ? "## " : ""));
+      use_xidle_extension = False;
+#endif /* !HAVE_XIDLE_EXTENSION */
+    }
+
+  init_sigchld ();
+
+  disable_builtin_screensaver ();
+
+#ifdef HAVE_SAVER_EXTENSION
+  if (use_saver_extension)
+    init_saver_extension ();
+#endif /* HAVE_SAVER_EXTENSION */
+
+  if (verbose_p && use_saver_extension)
+    fprintf (stderr, "%s: using MIT-SCREEN-SAVER server extension.\n",
+            progname);
+  if (verbose_p && use_xidle_extension)
+    fprintf (stderr, "%s: using XIdle server extension.\n",
+            progname);
+
+  initialize_stderr ();
+  XSetErrorHandler (saver_ehandler);
+
+  if (initial_demo_mode_p)
+    /* If the user wants demo mode, don't wait around before doing it. */
+    initial_delay = 0;
+
+  if (!use_xidle_extension && !use_saver_extension)
+    {
+      if (initial_delay)
+       {
+         if (verbose_p)
+           {
+             printf ("%s: waiting for %d second%s...", progname,
+                     (int) initial_delay, (initial_delay == 1 ? "" : "s"));
+             fflush (stdout);
+           }
+         sleep (initial_delay);
+         if (verbose_p)
+           printf (" done.\n");
+       }
+      if (verbose_p)
+       {
+         printf ("%s: selecting events on extant windows...", progname);
+         fflush (stdout);
+       }
+      notice_events_timer ((XtPointer)
+                          RootWindowOfScreen (XtScreen (toplevel_shell)),
+                          0);
+      if (verbose_p)
+       printf (" done.\n");
+    }
+}
+
+
+extern void suspend_screenhack P((Bool suspend_p));
+
+static void
+main_loop ()
+{
+  while (1)
+    {
+      if (! demo_mode_p)
+       sleep_until_idle (True);
+
+      if (demo_mode_p)
+       demo_mode ();
+      else
+       {
+         if (verbose_p)
+           printf ("%s: user is idle; waking up at %s.\n", progname,
+                   timestring());
+         blank_screen ();
+         spawn_screenhack (True);
+         if (cycle)
+           cycle_id = XtAppAddTimeOut (app, cycle,
+                                       (XtTimerCallbackProc)cycle_timer, 0);
+
+#ifndef NO_LOCKING
+         if (lock_p && lock_timeout == 0)
+           locked_p = True;
+         if (lock_p && !locked_p)
+           /* locked_p might be true already because of ClientMessage */
+           lock_id = XtAppAddTimeOut (app,lock_timeout,
+                                      (XtTimerCallbackProc)
+                                      activate_lock_timer,0);
+#endif
+
+       PASSWD_INVALID:
+
+         sleep_until_idle (False); /* until not idle */
+
+#ifndef NO_LOCKING
+         if (locked_p)
+           {
+             Bool val;
+             if (locking_disabled_p) abort ();
+             dbox_up_p = True;
+
+             /* We used to ungrab the keyboard here, before calling unlock_p()
+                to pop up the dialog box.  This left the keyboard ungrabbed
+                for a small window, during an insecure state.  Bennett Todd
+                was seeing the bahavior that, when the load was high, he could
+                actually get characters through to a shell under the saver
+                window (he accidentally typed his password there...)
+
+                So the ungrab has been moved down into pop_passwd_dialog()
+                just after the server is grabbed, closing this window
+                entirely.
+              */
+             /* ungrab_keyboard_and_mouse (); */
+
+             suspend_screenhack (True);
+             XUndefineCursor (dpy, screensaver_window);
+             if (verbose_p)
+               printf ("%s: prompting for password.\n", progname);
+             val = unlock_p (toplevel_shell);
+             if (verbose_p && val == False)
+               printf ("%s: password incorrect!\n", progname);
+             dbox_up_p = False;
+             XDefineCursor (dpy, screensaver_window, cursor);
+             suspend_screenhack (False);
+
+             /* I think this grab is now redundant, but it shouldn't hurt. */
+             grab_keyboard_and_mouse ();
+
+             if (! val)
+               goto PASSWD_INVALID;
+             locked_p = False;
+           }
+#endif
+         unblank_screen ();
+         kill_screenhack ();
+         if (cycle_id)
+           {
+             XtRemoveTimeOut (cycle_id);
+             cycle_id = 0;
+           }
+#ifndef NO_LOCKING
+         if (lock_id)
+           {
+             XtRemoveTimeOut (lock_id);
+             lock_id = 0;
+           }
+#endif
+         if (verbose_p)
+           printf ("%s: user is active; going to sleep at %s.\n", progname,
+                   timestring ());
+       }
+    }
+}
+
+\f
+
+Bool
+handle_clientmessage (event, until_idle_p)
+     XEvent *event;
+     Bool until_idle_p;
+{
+  Atom type = 0;
+  if (event->xclient.message_type != XA_SCREENSAVER)
+    {
+      char *str;
+      str = XGetAtomName (dpy, event->xclient.message_type);
+      fprintf (stderr, "%s: %sunrecognised ClientMessage type %s received\n",
+              progname, (verbose_p ? "## " : ""),
+              (str ? str : "(null)"));
+      if (str) XFree (str);
+      return False;
+    }
+  if (event->xclient.format != 32)
+    {
+      fprintf (stderr, "%s: %sClientMessage of format %d received, not 32\n",
+              progname, (verbose_p ? "## " : ""), event->xclient.format);
+      return False;
+    }
+  type = event->xclient.data.l[0];
+  if (type == XA_ACTIVATE)
+    {
+      if (until_idle_p)
+       {
+         if (verbose_p)
+           printf ("%s: ACTIVATE ClientMessage received.\n", progname);
+         if (use_saver_extension)
+           {
+             XForceScreenSaver (dpy, ScreenSaverActive);
+             return False;
+           }
+         else
+           {
+             return True;
+           }
+       }
+      fprintf (stderr,
+              "%s: %sClientMessage ACTIVATE received while already active.\n",
+              progname, (verbose_p ? "## " : ""));
+    }
+  else if (type == XA_DEACTIVATE)
+    {
+      if (! until_idle_p)
+       {
+         if (verbose_p)
+           printf ("%s: DEACTIVATE ClientMessage received.\n", progname);
+         if (use_saver_extension)
+           {
+             XForceScreenSaver (dpy, ScreenSaverReset);
+             return False;
+           }
+         else
+           {
+             return True;
+           }
+       }
+      fprintf (stderr,
+              "%s: %sClientMessage DEACTIVATE received while inactive.\n",
+              progname, (verbose_p ? "## " : ""));
+    }
+  else if (type == XA_CYCLE)
+    {
+      if (! until_idle_p)
+       {
+         if (verbose_p)
+           printf ("%s: CYCLE ClientMessage received.\n", progname);
+         if (cycle_id)
+           XtRemoveTimeOut (cycle_id);
+         cycle_id = 0;
+         cycle_timer (0, 0);
+         return False;
+       }
+      fprintf (stderr,
+              "%s: %sClientMessage CYCLE received while inactive.\n",
+              progname, (verbose_p ? "## " : ""));
+    }
+  else if (type == XA_NEXT || type == XA_PREV)
+    {
+      if (verbose_p)
+       printf ("%s: %s ClientMessage received.\n", progname,
+               (type == XA_NEXT ? "NEXT" : "PREV"));
+      next_mode_p = 1 + (type == XA_PREV);
+
+      if (! until_idle_p)
+       {
+         if (cycle_id)
+           XtRemoveTimeOut (cycle_id);
+         cycle_id = 0;
+         cycle_timer (0, 0);
+       }
+      else
+       return True;
+    }
+  else if (type == XA_EXIT)
+    {
+      /* Ignore EXIT message if the screen is locked. */
+      if (until_idle_p || !locked_p)
+       {
+         if (verbose_p)
+           printf ("%s: EXIT ClientMessage received.\n", progname);
+         if (! until_idle_p)
+           {
+             unblank_screen ();
+             kill_screenhack ();
+             XSync (dpy, False);
+           }
+         exit (0);
+       }
+      else
+       fprintf (stderr, "%s: %sEXIT ClientMessage received while locked.\n",
+                progname, (verbose_p ? "## " : ""));
+    }
+  else if (type == XA_RESTART)
+    {
+      /* The RESTART message works whether the screensaver is active or not,
+        unless the screen is locked, in which case it doesn't work.
+       */
+      if (until_idle_p || !locked_p)
+       {
+         if (verbose_p)
+           printf ("%s: RESTART ClientMessage received.\n", progname);
+         if (! until_idle_p)
+           {
+             unblank_screen ();
+             kill_screenhack ();
+             XSync (dpy, False);
+           }
+         restart_process ();
+       }
+      else
+       fprintf(stderr, "%s: %sRESTART ClientMessage received while locked.\n",
+               progname, (verbose_p ? "## " : ""));
+    }
+  else if (type == XA_DEMO)
+    {
+#ifdef NO_DEMO_MODE
+      fprintf (stderr,
+              "%s: %snot compiled with support for DEMO mode\n",
+              progname, (verbose_p ? "## " : ""));
+#else
+      if (until_idle_p)
+       {
+         if (verbose_p)
+           printf ("%s: DEMO ClientMessage received.\n", progname);
+         demo_mode_p = True;
+         return True;
+       }
+      fprintf (stderr,
+              "%s: %sDEMO ClientMessage received while active.\n",
+              progname, (verbose_p ? "## " : ""));
+#endif
+    }
+  else if (type == XA_LOCK)
+    {
+#ifdef NO_LOCKING
+      fprintf (stderr, "%s: %snot compiled with support for LOCK mode\n",
+              progname, (verbose_p ? "## " : ""));
+#else
+      if (locking_disabled_p)
+       fprintf (stderr,
+              "%s: %sLOCK ClientMessage received, but locking is disabled.\n",
+                progname, (verbose_p ? "## " : ""));
+      else if (locked_p)
+       fprintf (stderr,
+              "%s: %sLOCK ClientMessage received while already locked.\n",
+                progname, (verbose_p ? "## " : ""));
+      else
+       {
+         locked_p = True;
+         if (verbose_p) 
+           printf ("%s: LOCK ClientMessage received;%s locking.\n",
+                   progname, until_idle_p ? " activating and" : "");
+
+         if (lock_id)  /* we're doing it now, so lose the timeout */
+           {
+             XtRemoveTimeOut (lock_id);
+             lock_id = 0;
+           }
+
+         if (until_idle_p)
+           {
+             if (use_saver_extension)
+               {
+                 XForceScreenSaver (dpy, ScreenSaverActive);
+                 return False;
+               }
+             else
+               {
+                 return True;
+               }
+           }
+       }
+#endif
+    }
+  else
+    {
+      char *str;
+      str = (type ? XGetAtomName(dpy, type) : 0);
+      if (str)
+       fprintf (stderr,
+                "%s: %sunrecognised screensaver ClientMessage %s received\n",
+                progname, (verbose_p ? "## " : ""), str);
+      else
+       fprintf (stderr,
+               "%s: %sunrecognised screensaver ClientMessage 0x%x received\n",
+                progname, (verbose_p ? "## " : ""),
+                (unsigned int) event->xclient.data.l[0]);
+      if (str) XFree (str);
+    }
+  return False;
+}
diff --git a/driver/xscreensaver.h b/driver/xscreensaver.h
new file mode 100644 (file)
index 0000000..ea792e2
--- /dev/null
@@ -0,0 +1,70 @@
+/* xscreensaver, Copyright (c) 1993, 1995 Jamie Zawinski <jwz@netscape.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.
+ */
+
+#if __STDC__
+# include <stdlib.h>
+# include <unistd.h>
+#endif
+
+#include <stdio.h>
+
+#if __STDC__
+# define P(x)x
+#else
+# define P(x)()
+# ifndef const
+#  define const /**/
+# endif
+#endif
+
+#ifdef NO_MOTIF
+# define NO_DEMO_MODE
+
+  /* #### If anyone ever finishes the Athena locking code, remove this.
+     Until then, Locking requires Motif. */
+# ifndef NO_LOCKING
+#  define NO_LOCKING
+# endif
+
+#endif
+
+extern char *progname, *progclass;
+extern char *screensaver_version;
+
+extern Display *dpy;
+extern Screen *screen;
+extern Visual *visual;
+extern int visual_depth;
+
+extern Bool verbose_p;
+
+extern FILE *real_stderr;
+extern FILE *real_stdout;
+
+extern void initialize_screensaver_window P((void));
+extern void raise_window P((Bool inhibit_fade, Bool between_hacks_p));
+extern void blank_screen P((void));
+extern void unblank_screen P((void));
+extern void restart_process P((void));
+
+extern void restore_real_vroot P((void));
+
+extern void spawn_screenhack P((Bool));
+extern void kill_screenhack P((void));
+
+extern Colormap copy_colormap P((Display *, Colormap, Colormap));
+extern void fade_colormap P((Display*, Colormap, Colormap, int, int, Bool));
+extern void blacken_colormap P((Display *, Colormap));
+
+extern int BadWindow_ehandler P((Display *dpy, XErrorEvent *error));
+
+extern char *timestring P((void));
+extern Bool window_exists_p P((Display *dpy, Window window));
diff --git a/driver/xscreensaver.man b/driver/xscreensaver.man
new file mode 100644 (file)
index 0000000..18bf571
--- /dev/null
@@ -0,0 +1,551 @@
+.de EX         \"Begin example
+.ne 5
+.if n .sp 1
+.if t .sp .5
+.nf
+.in +.5i
+..
+.de EE
+.fi
+.in -.5i
+.if n .sp 1
+.if t .sp .5
+..
+.TH XScreenSaver 1 "6-Jan-95" "X Version 11"
+.SH NAME
+xscreensaver - graphics hack and screen locker, launched when the user is idle
+.SH SYNOPSIS
+.B xscreensaver
+[\-display \fIhost:display.screen\fP] [\-timeout \fIint\fP] [\-cycle \fIint\fP] [\-nice \fIint\fP] [\-verbose] [\-silent] [\-xidle] [\-no-xidle] [\-lock] [\-no-lock] [\-lock\-timeout \fIint\fP] [\-demo] [\-visual \fIvisual\fP] [\-install] [\-no-install] [\-xrm \fIresources\fP]
+.SH DESCRIPTION
+The \fIxscreensaver\fP program waits until the keyboard and mouse have been 
+idle for a period, and then runs a graphics demo chosen at random.  It 
+turns off as soon as there is any mouse or keyboard activity.
+
+This program can lock your terminal in order to prevent others from using it,
+though its default mode of operation is merely to display pretty pictures on
+your screen when it is not in use.  
+
+The benefit that this program has over the combination of the
+.BR xlock (1)
+and
+.BR xautolock (1)
+programs is the ease with which new graphics hacks can be installed.  You
+don't need to recompile (or even re-run) this program to add a new display
+mode.
+.SH OPTIONS
+.I xscreensaver
+accepts the following options:
+.TP 8
+.B \-timeout \fIminutes\fP
+The screensaver will activate after the keyboard and mouse have been idle
+for this many minutes.
+.TP 8
+.B \-cycle \fIminutes\fP
+After the screensaver has been running for this many minutes, the currently
+running sub-process will be killed (with \fBSIGTERM\fP), and a new one 
+started.  If this is 0, then the sub-process will not be killed; only one
+demo will run until the screensaver is deactivated by user activity.
+.TP 8
+.B \-nice \fIinteger\fP
+The sub-processes created by \fIxscreensaver\fP will be ``niced'' to this
+level, so that they do not consume cycles that are needed elsewhere.
+.TP 8
+.B \-verbose
+Print diagnostics.
+.TP 8
+.B \-silent
+
+.TP 8
+.B \-xidle\-extension
+Use the \fBXIDLE\fP server extension to decide whether the user is idle.
+This is the default if \fIxscreensaver\fP has been compiled with support
+for this extension.  On X11R4 or X11R5 systems, the XIdle method is faster 
+and more reliable than what will be done otherwise, so use it if you can.
+.TP 8
+.B \-no\-xidle\-extension
+Don't use the \fBXIDLE\fP server extension.
+.TP 8
+.B \-ss\-extension
+Use the \fBMIT\-SCREEN\-SAVER\fP server extension to decide whether the user
+is idle.  This is the default if \fIxscreensaver\fP has been compiled with
+support for this extension.  On X11R6 systems, the  \fBMIT\-SCREEN\-SAVER\fP 
+method is faster and more reliable than what will be done otherwise, so use
+it if you can.
+.TP 8
+.B \-no\-ss\-extension
+Don't use the \fBMIT\-SCREEN\-SAVER\fP server extension.
+.TP 8
+.B \-lock
+Enable locking: before the screensaver will turn off, it requires you to
+type the password of the person who launched the screensaver, or the root
+password.  (Note: this doesn't work if the screensaver is launched
+by
+.BR xdm (1)
+because it can't know the user-id of the logged-in user.)
+.TP 8
+.B \-no\-lock
+Disable locking.  This is the default.
+.TP 8
+.B \-lock\-timeout \fIminutes\fP
+This is how long after the screensaver activates that locking is enabled.
+For example, if this is 5, then any user activity within five minutes of
+the time when the screensaver activated will cause the screen to unblank
+without requiring a password.  After 5 minutes, a password will be
+required.  The default is 0, meaning that if locking is enabled, then
+a password will be required as soon as the screensaver activates.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are:
+.RS 8
+.TP 8
+.B best
+Use the visual which supports the most writable color cells; this is
+the default.
+.TP 8
+.B default
+Use the screen's default visual (the visual of the root window.)  This is
+not necessarily the most colorful visual, which is why it is not the default.
+.TP 8
+.I class
+One of \fBStaticGray\fP, \fBStaticColor\fP, \fBTrueColor\fP, \fBGrayScale\fP, 
+\fBPseudoColor\fP, or \fBDirectColor\fP.  Selects the deepest visual of
+the given class.
+.TP 8
+.I number
+A number (decimal or hex) is interpreted as a visual id number, as reported
+by the
+.BR xdpyinfo (1)
+program; in this way you can select a shallower visual if desired.
+.RE
+.TP 8
+.B \-no\-install
+Use the default colormap.  This is the default.
+.TP 8
+.B \-install
+Install a private colormap while the screensaver is on, so that the graphics
+hacks can get as many colors as possible.
+.TP 8
+.B \-demo
+Enter the interactive demo mode immediately after startup.  Normally
+demo mode is invoked via the
+.BR xscreensaver\-command (1)
+program.
+.SH X RESOURCES
+\fIxscreensaver\fP understands the following resources:
+.PP
+.TP 8
+.B timeout \fR(class \fBTime\fP)
+Same as the \fI\-timeout\fP command-line option.  Default 10 minutes.
+.TP 8
+.B cycle \fR(class \fBTime\fP)
+Same as the \fI\-cycle\fP command-line option.  Default 10 minutes.
+.TP 8
+.B nice \fR(class \fBNice\fP)
+Same as the \fI\-nice\fP command-line option.  Default 10.
+.TP 8
+.B verbose \fR(class \fBBoolean\fP)
+Same as the \fI\-verbose\fP command-line option.
+.TP 8
+.B xidle \fR(class \fBBoolean\fP)
+Same as the \fI\-xidle\fP command-line option.
+.TP 8
+.B lock \fR(class \fBBoolean\fP)
+Same as the \fI\-lock\fP command-line option.
+.TP 8
+.B lockTimeout \fR(class \fBTime\fP)
+Same as the \fI\-lock\-timeout\fP command-line option.
+.TP 8
+.B fade \fR(class \fBBoolean\fP)
+If this is true, then when the screensaver activates, the current contents
+of the screen will fade to black instead of simply winking out.  This only
+works on displays with writable colormaps.  Default true.  A fade will also
+be done when switching graphics hacks (when the \fIcycle\fP timer expires.)
+.TP 8
+.B unfade \fR(class \fBBoolean\fP)
+If this is true, then when the screensaver deactivates, the original contents
+of the screen will fade in from black instead of appearing immediately.  This
+only works on displays with writable colormaps, and if \fIfade\fP is true
+as well.  Default false.
+.TP 8
+.B fadeSeconds \fR(class \fBTime\fP)
+If \fIfade\fP is true, this is how long the fade will be in 
+seconds (default 1.)
+.TP 8
+.B fadeTicks \fR(class \fBInteger\fP)
+If \fIfade\fP is true, this is how many times a second the colormap will
+be changed to effect a fade.  Higher numbers yield smoother fades, but
+may make the fades take longer if your server isn't fast enough to keep
+up.  Default 75.
+.TP 8
+.B installColormap \fR(class \fBBoolean\fP)
+Same as the \fI\-install\fP command-line option.  Default false.
+.TP 8
+.B passwdTimeout \fR(class \fBTime\fP)
+If \fIlock\fP is true, this is how many seconds the password dialog box
+should be left on the screen before giving up (default 30.)  This should
+not be too large: the X server is grabbed for the duration that the password
+dialog box is up (for security purposes) and leaving the server grabbed for
+too long can cause problems.
+.TP 8
+.B visualID \fR(class \fBVisualID\fP)
+Same as the \fI\-visual\fP command-line option.  Default \fBbest\fP.
+.TP 8
+.B captureStderr \fR(class \fBBoolean\fP)
+Whether \fIxscreensaver\fP should redirect its standard-error stream to the
+window itself.  Since its nature is to take over the screen, you would not
+normally see error messages generated by the screensaver or the programs it
+runs; this resource will cause the output of all relevant programs to be
+drawn on the screensaver window itself instead of written to the controlling
+terminal of the screensaver driver process.  Default: True.
+.TP 8
+.B captureStdout \fR(class \fBBoolean\fP)
+Like \fBcaptureStderr\fP but for the standard-output stream.  Default: True.
+.TP 8
+.B font \fR(class \fBFont\fP)
+The font used for the stdout/stderr text, if \fBcaptureStdout\fP or
+\fBcaptureStderr\fP are true.  Default \fB*\-medium\-r\-*\-140\-*\-m\-*\fP
+(a 14 point fixed-width font.)
+.TP 8
+.B textForeground \fR(class \fBForeground\fP)
+The foreground color used for the stdout/stderr text, if \fBcaptureStdout\fP 
+or \fBcaptureStderr\fP are true.  Default: Yellow.
+.TP 8
+.B textBackground \fR(class \fBBackground\fP)
+The background color used for the stdout/stderr text, if \fBcaptureStdout\fP 
+or \fBcaptureStderr\fP are true.  Default: Black.
+.TP 8
+.B programs \fR(class \fBPrograms\fP)
+The graphics hacks which \fIxscreensaver\fP runs when the user is idle,
+in addition to those specified in colorPrograms or monoPrograms (as 
+appropriate.)  The value of this resource is a string, one \fIsh\fP command 
+per line.  Each line must contain exactly one command -- no semicolons.
+
+When the screensaver starts up, one of these is selected at random, and
+run.  After the \fIcycle\fP period expires, it is killed, and another
+is selected and run.
+
+If the value of this resource (and the applicable one of \fBcolorPrograms\fP
+or \fBmonoPrograms\fP) is empty, then no programs will be run; the screen
+will simply be made black.
+
+Note that you must escape the newlines; here is an example of how you
+might set this in your \fI.Xdefaults\fP file:
+.EX
+xscreensaver.programs:  \\
+        qix -root                        \\n\\
+        ico -r -faces -sleep 1 -obj ico  \\n\\
+        xdaliclock -builtin2 -root       \\n\\
+        xwave -root
+.EE
+To use a program as a screensaver, two things are required: that that
+program draw on the root window (or be able to be configured to draw on
+the root window); and that that program understand ``virtual root''
+windows, as used by virtual window managers such as \fItvtwm\fP.
+
+It is quite easy to make programs understand virtual roots if they
+don't already: you merely need to include the file \fI"vroot.h"\fP in
+them after the standard X includes, and recompile.  This file is distributed
+with X11r5, and is included with xscreensaver as well.
+.TP 8
+.B monoPrograms \fR(class \fBMonoPrograms\fP)
+This resource is appended to the value of the \fIprograms\fP resource if
+the display on which the screensaver is running is monochrome.
+.TP 8
+.B colorPrograms \fR(class \fBColorPrograms\fP)
+This resource is appended to the value of the \fIprograms\fP resource if
+the display on which the screensaver is running is not monochrome.
+.PP
+.RS 4
+\fBNOTE: this means that if you want to completely replace the list of 
+programs which xscreensaver runs, you must set at least \fItwo\fP,
+possibly \fIthree\fP resources.  It is not enough to just set 
+the \fBprograms\fP resource -- you must also set \fBcolorPrograms\fP 
+or \fBmonoPrograms\fP or both.\fP
+.RE
+.PP
+Normally you won't need to change the following resources:
+.TP 8
+.B bourneShell \fR(class \fBBourneShell\fP)
+The pathname of the shell that \fIxscreensaver\fP uses to start subprocesses.
+This must be whatever your local variant of \fB/bin/sh\fP is -- in particular,
+it must not be \fBcsh\fP.
+.TP 8
+.B windowCreationTimeout \fR(class \fBTime\fP)
+When \fIXIdle\fP is not in use, this controls the delay between when 
+windows are created and when \fIxscreensaver\fP selects events on them.
+Default 30 seconds.
+.TP 8
+.B pointerPollTime \fR(class \fBTime\fP)
+When \fIXIdle\fP is not in use, this controls how frequently \fIxscreensaver\fP
+checks to see if the mouse position or buttons have changed.  Default 5 seconds.
+.TP 8
+.B initialDelay \fR(class \fBTime\fP)
+When \fIXIdle\fP is not in use, \fIxscreensaver\fP will wait this many seconds
+before selecting events on existing windows, under the assumption that 
+\fIxscreensaver\fP is started during your login procedure, and the window 
+state may be in flux.  Default 30 seconds.
+.SH "HOW IT WORKS"
+When it is time to activate the screensaver, a full-screen black window is
+created.  This window is given the appropriate properties so that, to any 
+subsequently-created programs, it will appear to be a ``virtual root'' 
+window.  Because of this, any program which draws on the root window (and 
+which understands virtual roots) can be used as a screensaver.
+.PP
+When the user becomes active again, the screensaver window is unmapped and
+the running subprocess is killed by sending it \fBSIGTERM\fP.  This is also
+how the subprocesses are killed when the screensaver decides that it's time
+to run a different demo: the old one is killed and a new one is launched.
+.PP
+Before launching a subprocess, \fIxscreensaver\fP stores an appropriate value
+for \fB$DISPLAY\fP in the environment that the child will recieve.  (This is
+so that if you start \fIxscreensaver\fP with a \fI-display\fP argument, the
+programs which \fIxscreensaver\fP launches will draw on the same display.)
+.PP
+When the screensaver turns off, or is killed, care is taken to restore 
+the ``real'' virtual root window if there is one.  Because of this, it is
+important that you not kill the screensaver process with \fIkill -9\fP if
+you are running a virtual-root window manager.  If you kill it with \-9,
+you may need to restart your window manager to repair the damage.  This
+isn't an issue if you aren't running a virtual-root window manager.
+.PP
+For all the gory details, see the commentary at the top of xscreensaver.c.
+.PP
+You can control a running screensaver process by using the
+.BR xscreensaver\-command (1)
+program (which see.)
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH USING XDM(1)
+You can run \fIxscreensaver\fP from your xdm session, so that the 
+screensaver will run even when nobody is logged in on the console.  
+Simply add \fB"xscreensaver &"\fP to your \fI/usr/lib/X11/xdm/Xsetup\fP 
+file.  Because \fIxdm\fP grabs the keyboard, keypresses will not make 
+the screensaver deactivate, but any mouse activity will.
+.PP
+(If your system does not seem to be executing the \fIXsetup\fP file, you
+may need to configure it to do so -- the traditional way to do this is
+to make that file the value of the \fIDisplayManager*setup\fP resource
+in the \fIxdm-config\fP file.  See the man page for
+.BR xdm (1)
+for more details.)
+.PP
+Users may want to add \fB"xscreensaver-command -restart"\fP to their 
+startup scripts, so that the screensaver will be reinitialized with
+their private resource settings when they log in.
+.PP
+It is safe to run this program as root (as \fIxdm\fP is likely to do.)  If 
+run as root, \fIxscreensaver\fP changes its effective user and group ids to
+something safe (like \fI"nobody"\fP) before connecting to the X server
+or launching user-specified programs.
+.PP
+Locking doesn't work if the screensaver is launched by \fIxdm\fP.  To get
+around this, you can run the screensaver from \fIxdm\fP without locking, 
+and kill and restart it from your personal X startup script to enable
+locking.
+.SH DEMO MODE
+If \fIxscreensaver\fP receives the \fBDEMO\fP ClientMessage, it pops up
+a dialog box from which you can examine and experiment with the screensaver's
+client programs.
+.PP
+Clicking left on an element in the scrolling list will place the indicated
+program and its args in the text field to be edited.  Edit the arguments and
+hit return to run the program with the parameters you have specified.
+.PP
+Double-clicking on an element in the scrolling list will run the indicated
+program immediately.
+.PP
+When a client program is launched, the dialog box is hidden.  Clicking
+any mouse button will re-expose the dialog box (but will not kill the 
+client program.)
+.TP 8
+.B Run Next
+Clicking this button will run the next program in the list after the 
+currently-selected one, and will scroll around to the top when it reaches
+the bottom.
+.TP 8
+.B Run Previous
+Opposite of Run Next; at the top, it scrolls around to the bottom.
+.TP 8
+.B Edit Parameters
+This pops up a second dialog box, in which you have the option to 
+interactively change most of the screensaver's operational parameters,
+such as its timeouts, and whether it should hack colormaps.  Changing
+these parameters here will affect only the running \fIxscreensaver\fP
+process; to make the changes permanent, you need to edit your X resource
+file.
+.TP 8
+.B Exit Demo Mode
+Returns to normal screensaver operation.
+.TP 8
+.B Reinitialize
+Causes the screensaver process to exit and then restart with the same 
+command-line arguments.  This causes the X resource database to be 
+re-read.  This is just like the \fI\-restart\fP argument to
+.BR xscreensaver\-command (1)
+except that when executed from this button, the screensaver will 
+automatically return to demo mode after restarting.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver\-command (1),
+.BR xlock (1),
+.BR xnlock (1),
+.BR xautolock (1),
+.BR xdm (1),
+.BR qix (1),
+.BR pyro (1),
+.BR helix (1),
+.BR rorschach (1),
+.BR hopalong (1),
+.BR attraction (1),
+.BR greynetic (1),
+.BR rocks (1),
+.BR noseguy (1),
+.BR blitspin (1),
+.BR imsmap (1),
+.BR slidescreen (1),
+.BR decayscreen (1),
+.BR hypercube (1),
+.BR flame (1),
+.BR maze (1),
+.BR ico (1),
+.BR xdaliclock (1),
+.BR xbouncebits (1),
+.BR xswarm (1),
+.BR xwave (1),
+.BR xfishtank (1)
+.SH BUGS
+If you think you have changed the \fBprograms\fP resource but the
+screensaver is ignoring it, you are confused -- you need to set 
+the \fBcolorPrograms\fP and/or \fBmonoPrograms\fP resources as well.
+(This is not a bug, but I mention it here because people think that
+it is with great regularity.)
+.PP
+If you are not making use of one of the server extensions (\fBXIDLE\fP
+or \fBMIT-SCREEN-SAVER\fP), then it is possible, in rare situations,
+for \fIxscreensaver\fP to interfere with event propagation and make
+another X program malfunction.  For this to occur, that other application
+would need to \fInot\fP select \fBKeyPress\fP events on its non-leaf windows
+within the first 30 seconds of their existence, but then select for them later.
+In this case, that client \fImight\fP fail to receive those events.
+This isn't very likely, since programs generally select a constant set
+of events immediately after creating their windows and then don't change
+them, but this is the reason that it's a good idea to install and use one
+of the server extensions instead, to work around this shortcoming in the
+X protocol.
+.PP
+Although this program ``nices'' the subprocesses that it starts, 
+graphics-intensive subprograms can still overload the machine by causing
+the X server process itself (which is not ``niced'') to suck a lot of 
+cycles.  Care should be taken to slow down programs intended for use as 
+screensavers by inserting strategic calls to
+.BR sleep (3)
+or
+.BR usleep (3)
+\.
+
+Also, it will cause your X server to be pretty much permanently swapped in.
+(but the same is true of any program that draws periodically, like xclock or
+xload.)
+.PP
+If the subprocess is drawing too quickly and the connection to the X
+server is a slow one (such as an X terminal running over a phone line) then 
+the screensaver might not turn off right away when the user becomes active
+again (the
+.BR ico (1)
+demo has this problem if being run in full-speed mode).  This can be
+alleviated by inserting strategic calls to
+.BR XSync (3)
+in code intended for use as a screensaver.  This prevents too much graphics
+activity from being buffered up.
+.PP
+The screensaver only runs on the default screen of the display.  If you have
+more than one screen, you can run multiple screensaver processes, one for
+each screen.  This interacts poorly with locking.  In an ideal world, the
+screensaver would save (and lock) both screens simultaniously, and any activity
+would restore both screens.  It would be nice if one could run different hacks
+on each screen simultaniously.  However, I don't have access to a multi-headed
+workstation, so it would be hard for me to implement something like this.
+.PP
+If you don't have Motif, you can't compile with support for locking or
+demo mode.
+.PP
+Locking doesn't work if the screensaver is launched by \fIxdm\fP.
+The reason for this is that when it is launched by \fIxdm\fP, the
+screensaver process is owned by some standard user id (such as \fIroot\fP
+or \fIdaemon\fP) instead of the user who is logged in on the console.
+In order for the screensaver to prompt for the password of the person
+who had logged in from \fIxdm\fP, it would need to know who that user was, 
+and there is no reliable and safe way to figure that out.  (And even if 
+there was, there would be some other security issues here as well.)
+
+So if you want to use it as a locker, you must start it with your user id.
+If it has already been started by \fIxdm\fP, you can kill it with
+\fBxscreensaver-command -exit\fP, and then start it again as you.
+.PP
+If you get an error message like ``couldn't get password of foo'' then 
+this probably means that you're on a system in which the
+.BR getpwent (3)
+library routine can only be effectively used by root.  If this is the case, 
+then \fIxscreensaver\fP must be installed as setuid to root.  Care has 
+been taken to make this a safe thing to do.
+.PP
+The \fBinstallColormap\fP option doesn't work very well with the
+.BR twm (1)
+window manager and its descendants.  There is a race condition between the
+screensaver and this window manager, which can result in the screensaver's
+colormap not getting installed properly, meaning the graphics hacks will
+appear in essentially random colors.  The
+.BR mwm (1)
+and
+.BR olwm (1)
+window managers don't seem to have this problem.  The race condition exists
+because X apparently does not provide a way for an OverrideRedirect window to 
+have its own colormap, short of grabbing the server (which is neither a good 
+idea, nor really possible with the current design.)  What happens is that, as 
+soon as the screensaver installs its colormap, \fBtwm\fP responds to 
+the \fBColormapNotify\fP event that is generated by re-instaling the default
+colormap.  Apparently, \fBtwm\fP doesn't \fIalways\fP do this; it seems to do
+it regularly if the screensaver is activated from a menu item, but seems to
+not do it if the screensaver comes on of its own volition, or is activated
+from another console.  Any thoughts on this problem are welcome...
+.PP
+Apparently there are some problems with ``XView'' programs getting confused
+and thinking that the screensaver window is the real root window even when
+the screensaver is not active: ClientMessages intended for the window manager
+are sent to the screensaver window instead.  This could be solved by making
+xscreensaver forward all unrecognised ClientMessages to the real root window,
+but there may be other problems as well.
+.PP
+When using the \fBMIT-SCREEN-SAVER\fP extension in conjunction with 
+the \fBfade\fP option, you may notice an unattractive flicker just before 
+the fade begins.  This is because the server maps a black window just before 
+it tells the \fIxscreensaver\fP process to activate.  The \fIxscreensaver\fP 
+process immediately unmaps that window, but this results in a flicker.  I 
+haven't figured out how to get around this yet.
+.PP
+There need to be a lot more graphics hacks.  In particular, there should be
+a simulation of a Lavalite (tm).
+.SH COPYRIGHT
+Copyright \(co 1992, 1993, 1994, 1995 by Jamie Zawinski.  Permission to use, 
+copy, modify, distribute, and sell this software and its documentation for 
+any purpose is hereby granted without fee, provided that the above copyright
+notice appear in all copies and that both that copyright notice and this
+permission notice appear in supporting documentation.  No representations are
+made about the suitability of this software for any purpose.  It is provided
+"as is" without express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@netscape.com>, 13-aug-92.
+Please let me know if you find any bugs or make any improvements.
+
+Thanks to David Wojtowicz for implementing \fIlockTimeout\fP.
+
+Thanks to Martin Kraemer for adding support for shadow passwords and 
+locking-disabled diagnostics.
diff --git a/hacks/.gdbinit b/hacks/.gdbinit
new file mode 100644 (file)
index 0000000..0bd0142
--- /dev/null
@@ -0,0 +1,3 @@
+b exit
+b abort
+set args -geom =700x700+0+0
diff --git a/hacks/Imakefile b/hacks/Imakefile
new file mode 100644 (file)
index 0000000..d2276c4
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Imakefile file for xscreensaver, Copyright (c) 1993, 1995 Jamie Zawinski.
+ *
+ * You should not need to edit this file; edit ../config.h instead.
+ *
+ */
+
+#include "../config.h"
+
+#ifdef HAVE_XPM
+ /* Yeah, this means that all hacks link against libXpm even though only
+    one hack actually uses it.  It doesn't matter: it's a library. */
+# define XPMDEFS -DHAVE_XPM
+# define XPMLIB -lXpm
+#else
+# define XPMDEFS
+# define XPMLIB
+#endif
+
+          UTILS = ../utils
+       INCLUDES = -I$(UTILS)
+        DEFINES = R5ISMS XPMDEFS
+LOCAL_LIBRARIES = $(XMULIB) $(XTOOLLIB) XPMLIB $(EXTENSIONLIB) $(XLIB) -lm
+          HACKS = attraction.c greynetic.c helix.c hopalong.c xroger-hack.c \
+                  noseguy.c pyro.c qix.c rocks.c rorschach.c blitspin.c \
+                  imsmap.c slidescreen.c decayscreen.c maze.c hypercube.c \
+                  halo.c flame.c pedal.c lmorph.c
+            MEN = attraction.man greynetic.man helix.man hopalong.man \
+                  noseguy.man pyro.man xroger.man qix.man rocks.man \
+                  rorschach.man blitspin.man imsmap.man slidescreen.man \
+                  decayscreen.man maze.man hypercube.man halo.man flame.man \
+                  pedal.man lmorph.man
+       TARFILES = README Imakefile screenhack.c $(HACKS) screenhack.h \
+                  vroot.h xlock.h default.xbm $(MEN) .gdbinit noses/\*
+
+all::
+
+echo_tarfiles:
+       @echo $(TARFILES)
+
+#define        ScreenhackTarget(p,ps,deps)                                      @@\
+all:: p                                                                         @@\
+p: deps screenhack.h ps.o $(DEPLIBS)                                    @@\
+       RemoveTargetProgram($@)                                          @@\
+       $(CCENVSETUP)                                                      \
+       $(CC) -o $@ $(LDOPTIONS) deps ps.o $(LOCAL_LIBRARIES) $(LDLIBS)  @@\
+                                                                        @@\
+InstallProgram(p,$(BINDIR))                                             @@\
+InstallManPage(p,$(MANDIR))                                             @@\
+clean::                                                                         @@\
+       $(RM) p
+
+HOBJS=screenhack.o $(UTILS)/resources.o $(UTILS)/visual.o \
+                  $(UTILS)/usleep.o $(UTILS)/yarandom.o
+
+ScreenhackTarget (qix, qix, $(HOBJS) $(UTILS)/hsv.o)
+ScreenhackTarget (helix, helix, $(HOBJS) $(UTILS)/hsv.o)
+ScreenhackTarget (pyro, pyro, $(HOBJS) $(UTILS)/hsv.o)
+ScreenhackTarget (attraction, attraction, $(HOBJS) $(UTILS)/hsv.o $(UTILS)/spline.o)
+ScreenhackTarget (rorschach, rorschach, $(HOBJS) $(UTILS)/hsv.o)
+ScreenhackTarget (hopalong, hopalong, $(HOBJS) $(UTILS)/hsv.o)
+ScreenhackTarget (xroger, xroger-hack, $(HOBJS) $(UTILS)/hsv.o $(UTILS)/xroger.o)
+ScreenhackTarget (rocks, rocks, $(HOBJS))
+ScreenhackTarget (noseguy, noseguy, $(HOBJS))
+ScreenhackTarget (blitspin, blitspin, $(HOBJS))
+ScreenhackTarget (greynetic, greynetic, $(HOBJS))
+ScreenhackTarget (slidescreen, slidescreen, $(HOBJS) $(UTILS)/grabscreen.o)
+ScreenhackTarget (decayscreen, decayscreen, $(HOBJS) $(UTILS)/grabscreen.o)
+ScreenhackTarget (imsmap, imsmap, $(HOBJS) $(UTILS)/hsv.o)
+ScreenhackTarget (maze, maze, $(HOBJS) $(UTILS)/xroger.o)
+ScreenhackTarget (hypercube, hypercube, $(HOBJS))
+ScreenhackTarget (halo, halo, $(HOBJS) $(UTILS)/hsv.o)
+ScreenhackTarget (flame, flame, $(HOBJS) $(UTILS)/hsv.o)
+ScreenhackTarget (pedal, pedal, $(HOBJS) $(UTILS)/hsv.o)
+ScreenhackTarget (lmorph, lmorph, $(HOBJS))
diff --git a/hacks/README b/hacks/README
new file mode 100644 (file)
index 0000000..c5ebcd6
--- /dev/null
@@ -0,0 +1,9 @@
+
+This directory contains various graphics hacks.  These are independent from
+the xscreensaver program (in the ../driver/ directory) but some of them use
+the utility functions found in the ../utils/ directory.
+
+If you have compilation problems, check the parameters in ../config.h.
+
+The file xlock.h makes it really easy to turn `xlock' modules into standalone
+programs that can be used with xscreensaver; check it out.
diff --git a/hacks/attraction.c b/hacks/attraction.c
new file mode 100644 (file)
index 0000000..8e3f188
--- /dev/null
@@ -0,0 +1,685 @@
+/* xscreensaver, Copyright (c) 1992, 1995 Jamie Zawinski <jwz@netscape.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.
+ */
+
+/* Simulation of a pair of quasi-gravitational fields, maybe sorta kinda
+   a little like the strong and weak electromagnetic forces.  Derived from
+   a Lispm screensaver by John Pezaris <pz@mit.edu>.  Mouse control and
+   viscosity added by "Philip Edward Cutone, III" <pc2d+@andrew.cmu.edu>.
+
+   John sez:
+
+   The simulation started out as a purely accurate gravitational simulation,
+   but, with constant simulation step size, I quickly realized the field being
+   simulated while grossly gravitational was, in fact, non-conservative.  It
+   also had the rather annoying behavior of dealing very badly with colliding
+   orbs.  Therefore, I implemented a negative-gravity region (with two
+   thresholds; as I read your code, you only implemented one) to prevent orbs
+   from every coming too close together, and added a viscosity factor if the
+   speed of any orb got too fast.  This provides a nice stable system with
+   interesting behavior.
+
+   I had experimented with a number of fields including the van der Waals
+   force (very interesting orbiting behavior) and 1/r^3 gravity (not as
+   interesting as 1/r^2).  An even normal viscosity (rather than the
+   thresholded version to bleed excess energy) is also not interesting.
+   The 1/r^2, -1/r^2, -10/r^2 thresholds proved not only robust but also
+   interesting -- the orbs never collided and the threshold viscosity fixed
+   the non-conservational problem.
+
+   Philip sez:
+   > An even normal viscosity (rather than the thresholded version to
+   > bleed excess energy) is also not interesting.
+
+   unless you make about 200 points.... set the viscosity to about .8
+   and drag the mouse through it.   it makes a nice wave which travels
+   through the field.
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include "screenhack.h"
+#include "spline.h"
+
+struct ball {
+  float x, y;
+  float vx, vy;
+  float dx, dy;
+  float mass;
+  int size;
+  XColor color;
+  int hue;
+};
+
+static unsigned int default_fg_pixel;
+static struct ball *balls;
+static int npoints;
+static int threshold;
+static int delay;
+static int global_size;
+static int segments;
+static Bool glow_p;
+static Bool orbit_p;
+static XPoint *point_stack;
+static int point_stack_size, point_stack_fp, pixel_stack_fp, pixel_stack_size;
+static unsigned long *pixel_stack;
+static unsigned int color_shift;
+
+/*flip mods for mouse interaction*/
+static Bool mouse_p;
+int mouse_x, mouse_y, mouse_mass, root_x, root_y;
+static float viscosity;
+
+static enum object_mode {
+  ball_mode, line_mode, polygon_mode, spline_mode, spline_filled_mode,
+  tail_mode
+} mode;
+
+static enum color_mode {
+  cycle_mode, random_mode
+} cmode;
+
+static GC draw_gc, erase_gc;
+
+#define MAX_SIZE 16
+
+#define min(a,b) ((a)<(b)?(a):(b))
+#define max(a,b) ((a)>(b)?(a):(b))
+
+static void
+init_balls (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  int i;
+  XWindowAttributes xgwa;
+  XGCValues gcv;
+  int xlim, ylim, midx, midy, r, vx, vy;
+  double th;
+  Colormap cmap;
+  char *mode_str;
+  XGetWindowAttributes (dpy, window, &xgwa);
+  xlim = xgwa.width;
+  ylim = xgwa.height;
+  cmap = xgwa.colormap;
+  midx = xlim/2;
+  midy = ylim/2;
+  r = get_integer_resource ("radius", "Integer");
+  if (r <= 0 || r > min (xlim/2, ylim/2))
+    r = min (xlim/2, ylim/2) - 50;
+  vx = get_integer_resource ("vx", "Integer");
+  vy = get_integer_resource ("vy", "Integer");
+  npoints = get_integer_resource ("points", "Integer");
+  if (npoints < 1)
+    npoints = 3 + (random () % 5);
+  balls = (struct ball *) malloc (npoints * sizeof (struct ball));
+  segments = get_integer_resource ("segments", "Integer");
+  if (segments < 0) segments = 1;
+  threshold = get_integer_resource ("threshold", "Integer");
+  if (threshold < 0) threshold = 0;
+  delay = get_integer_resource ("delay", "Integer");
+    if (delay < 0) delay = 0;
+  global_size = get_integer_resource ("size", "Integer");
+  if (global_size < 0) global_size = 0;
+  glow_p = get_boolean_resource ("glow", "Boolean");
+  orbit_p = get_boolean_resource ("orbit", "Boolean");
+  color_shift = get_integer_resource ("colorShift", "Integer");
+  if (color_shift >= 360) color_shift = 5;
+
+  /*flip mods for mouse interaction*/
+  mouse_p = get_boolean_resource ("mouse", "Boolean");
+  mouse_mass = get_integer_resource ("mouseSize", "Integer");
+  mouse_mass =  mouse_mass *  mouse_mass *10;
+
+  viscosity = get_float_resource ("viscosity", "Float");
+
+  mode_str = get_string_resource ("mode", "Mode");
+  if (! mode_str) mode = ball_mode;
+  else if (!strcmp (mode_str, "balls")) mode = ball_mode;
+  else if (!strcmp (mode_str, "lines")) mode = line_mode;
+  else if (!strcmp (mode_str, "polygons")) mode = polygon_mode;
+  else if (!strcmp (mode_str, "tails")) mode = tail_mode;
+  else if (!strcmp (mode_str, "splines")) mode = spline_mode;
+  else if (!strcmp (mode_str, "filled-splines")) mode = spline_filled_mode;
+  else {
+    fprintf (stderr,
+            "%s: mode must be balls, lines, tails, polygons, splines, or\n\
+       filled-splines, not \"%s\"\n",
+            progname, mode_str);
+    exit (1);
+  }
+
+  mode_str = get_string_resource ("colorMode", "ColorMode");
+  if (! mode_str) cmode = cycle_mode;
+  else if (!strcmp (mode_str, "cycle")) cmode = cycle_mode;
+  else if (!strcmp (mode_str, "random")) cmode = random_mode;
+  else {
+    fprintf (stderr, "%s: colorMode must be cycle or random, not \"%s\"\n",
+            progname, mode_str);
+    exit (1);
+  }
+
+  if (mode != ball_mode && mode != tail_mode) glow_p = False;
+  
+  if (mode == polygon_mode && npoints < 3)
+    mode = line_mode;
+
+  if (mode != ball_mode)
+    {
+      int size = (segments ? segments : 1);
+      point_stack_size = size * (npoints + 1);
+      point_stack = (XPoint *) calloc (point_stack_size, sizeof (XPoint));
+      point_stack_fp = 0;
+      if (segments > 0)
+       pixel_stack_size = segments;
+      else
+       pixel_stack_size = (360 / color_shift);
+      pixel_stack = (unsigned long *)
+       calloc (pixel_stack_size, sizeof (unsigned int));
+      pixel_stack_fp = 0;
+    }
+
+  gcv.line_width = (mode == tail_mode
+                   ? (global_size ? global_size : (MAX_SIZE * 2 / 3))
+                   : 1);
+  gcv.cap_style = (mode == tail_mode ? CapRound : CapButt);
+
+  gcv.foreground = default_fg_pixel =
+    get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+  draw_gc = XCreateGC (dpy, window, GCForeground|GCLineWidth|GCCapStyle, &gcv);
+  gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
+  erase_gc = XCreateGC (dpy, window, GCForeground|GCLineWidth|GCCapStyle,&gcv);
+
+  if (!mono_p && mode != ball_mode)
+    for (i = 0; i < pixel_stack_size; i++)
+      {
+       XColor color;
+       color.pixel = default_fg_pixel;
+       XQueryColor (dpy, cmap, &color);
+       if (!XAllocColor (dpy, cmap, &color)) abort ();
+       pixel_stack [i] = color.pixel;
+      }
+
+#define rand_size() min (MAX_SIZE, 8 + (random () % (MAX_SIZE - 9)))
+
+  if (orbit_p && !global_size)
+    /* To orbit, all objects must be the same mass, or the math gets
+       really hairy... */
+    global_size = rand_size ();
+
+  th = frand (M_PI+M_PI);
+  for (i = 0; i < npoints; i++)
+    {
+      int new_size = (global_size ? global_size : rand_size ());
+      balls [i].dx = 0;
+      balls [i].dy = 0;
+      balls [i].size = new_size;
+      balls [i].mass = (new_size * new_size * 10);
+      balls [i].x = midx + r * cos (i * ((M_PI+M_PI) / npoints) + th);
+      balls [i].y = midy + r * sin (i * ((M_PI+M_PI) / npoints) + th);
+      if (! orbit_p)
+       {
+         balls [i].vx = vx ? vx : ((6.0 - (random () % 11)) / 8.0);
+         balls [i].vy = vy ? vy : ((6.0 - (random () % 11)) / 8.0);
+       }
+      balls [i].color.pixel = default_fg_pixel;
+      balls [i].color.flags = DoRed | DoGreen | DoBlue;
+      if (!mono_p)
+       {
+         if (i != 0 && (glow_p || mode != ball_mode))
+           balls [i].hue = balls [0].hue;
+         else
+           balls [i].hue = random () % 360;
+         hsv_to_rgb (balls [i].hue, 1.0, 1.0,
+                     &balls [i].color.red, &balls [i].color.green,
+                     &balls [i].color.blue);
+         if (!XAllocColor (dpy, cmap, &balls [i].color))
+           mono_p = True; /* just give up */
+       }
+    }
+
+  if (orbit_p)
+    {
+      double a = 0;
+      double v;
+      double v_mult = get_float_resource ("vMult", "Float");
+      if (v_mult == 0.0) v_mult = 1.0;
+
+      for (i = 1; i < npoints; i++)
+       {
+          double _2ipi_n = (2 * i * M_PI / npoints);
+         double x = r * cos (_2ipi_n);
+         double y = r * sin (_2ipi_n);
+         double distx = r - x;
+         double dist2 = (distx * distx) + (y * y);
+          double dist = sqrt (dist2);
+          double a1 = ((balls[i].mass / dist2) *
+                       ((dist < threshold) ? -1.0 : 1.0) *
+                       (distx / dist));
+         a += a1;
+       }
+      if (a < 0.0)
+       {
+         fprintf (stderr, "%s: domain error: forces on balls too great\n",
+                  progname);
+         exit (-1);
+       }
+      v = sqrt (a * r) * v_mult;
+      for (i = 0; i < npoints; i++)
+       {
+         double k = ((2 * i * M_PI / npoints) + th);
+         balls [i].vx = -v * sin (k);
+         balls [i].vy =  v * cos (k);
+       }
+    }
+
+  if (mono_p) glow_p = False;
+  XClearWindow (dpy, window);
+}
+
+static void
+compute_force (i, dx_ret, dy_ret)
+     int i;
+     float *dx_ret, *dy_ret;
+{
+  int j;
+  float x_dist, y_dist, dist, dist2;
+  *dx_ret = 0;
+  *dy_ret = 0;
+  for (j = 0; j < npoints; j++)
+    {
+      float x_dist, y_dist, dist, dist2;
+
+      if (i == j) continue;
+      x_dist = balls [j].x - balls [i].x;
+      y_dist = balls [j].y - balls [i].y;
+      dist2 = (x_dist * x_dist) + (y_dist * y_dist);
+      dist = sqrt (dist2);
+             
+      if (dist > 0.1) /* the balls are not overlapping */
+       {
+         float new_acc = ((balls[j].mass / dist2) *
+                          ((dist < threshold) ? -1.0 : 1.0));
+         float new_acc_dist = new_acc / dist;
+         *dx_ret += new_acc_dist * x_dist;
+         *dy_ret += new_acc_dist * y_dist;
+       }
+      else
+       {               /* the balls are overlapping; move randomly */
+         *dx_ret += (frand (10.0) - 5.0);
+         *dy_ret += (frand (10.0) - 5.0);
+       }
+    }
+
+  if (mouse_p)
+    {
+      x_dist = mouse_x - balls [i].x;
+      y_dist = mouse_y - balls [i].y;
+      dist2 = (x_dist * x_dist) + (y_dist * y_dist);
+      dist = sqrt (dist2);
+       
+      if (dist > 0.1) /* the balls are not overlapping */
+       {
+         float new_acc = ((mouse_mass / dist2) *
+                          ((dist < threshold) ? -1.0 : 1.0));
+         float new_acc_dist = new_acc / dist;
+         *dx_ret += new_acc_dist * x_dist;
+         *dy_ret += new_acc_dist * y_dist;
+       }
+      else
+       {               /* the balls are overlapping; move randomly */
+         *dx_ret += (frand (10.0) - 5.0);
+         *dy_ret += (frand (10.0) - 5.0);
+       }
+    }
+}
+
+static void
+run_balls (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  int last_point_stack_fp = point_stack_fp;
+  static int tick = 500, xlim, ylim;
+  static Colormap cmap;
+  int i;
+
+  /*flip mods for mouse interaction*/
+  Window  root1, child1;
+  int mask;
+  if (mouse_p)
+    {
+      XQueryPointer(dpy, window, &root1, &child1,
+                   &root_x, &root_y, &mouse_x, &mouse_y, &mask);
+    }
+
+  if (tick++ == 500)
+    {
+      XWindowAttributes xgwa;
+      XGetWindowAttributes (dpy, window, &xgwa);
+      tick = 0;
+      xlim = xgwa.width;
+      ylim = xgwa.height;
+      cmap = xgwa.colormap;
+    }
+
+  /* compute the force of attraction/repulsion among all balls */
+  for (i = 0; i < npoints; i++)
+    compute_force (i, &balls[i].dx, &balls[i].dy);
+
+  /* move the balls according to the forces now in effect */
+  for (i = 0; i < npoints; i++)
+    {
+      float old_x = balls[i].x;
+      float old_y = balls[i].y;
+      float new_x, new_y;
+      int size = balls[i].size;
+      balls[i].vx += balls[i].dx;
+      balls[i].vy += balls[i].dy;
+
+      /* don't let them get too fast: impose a terminal velocity
+         (actually, make the medium have friction) */
+      if (balls[i].vx > 10)
+       {
+         balls[i].vx *= 0.9;
+         balls[i].dx = 0;
+       }
+      else if (viscosity != 1)
+       {
+         balls[i].vx *= viscosity;
+       }
+
+      if (balls[i].vy > 10)
+       {
+         balls[i].vy *= 0.9;
+         balls[i].dy = 0;
+       }
+      else if (viscosity != 1)
+       {
+         balls[i].vy *= viscosity;
+       }
+
+      balls[i].x += balls[i].vx;
+      balls[i].y += balls[i].vy;
+
+      /* bounce off the walls */
+      if (balls[i].x >= (xlim - balls[i].size))
+       {
+         balls[i].x = (xlim - balls[i].size - 1);
+         if (balls[i].vx > 0)
+           balls[i].vx = -balls[i].vx;
+       }
+      if (balls[i].y >= (ylim - balls[i].size))
+       {
+         balls[i].y = (ylim - balls[i].size - 1);
+         if (balls[i].vy > 0)
+           balls[i].vy = -balls[i].vy;
+       }
+      if (balls[i].x <= 0)
+       {
+         balls[i].x = 0;
+         if (balls[i].vx < 0)
+           balls[i].vx = -balls[i].vx;
+       }
+      if (balls[i].y <= 0)
+       {
+         balls[i].y = 0;
+         if (balls[i].vy < 0)
+           balls[i].vy = -balls[i].vy;
+       }
+
+      new_x = balls[i].x;
+      new_y = balls[i].y;
+
+      /* make color saturation be related to particle acceleration. */
+      if (glow_p)
+       {
+         float limit = 0.5;
+         double s, v, fraction;
+         float vx = balls [i].dx;
+         float vy = balls [i].dy;
+         XColor new_color;
+         if (vx < 0) vx = -vx;
+         if (vy < 0) vy = -vy;
+         fraction = vx + vy;
+         if (fraction > limit) fraction = limit;
+
+         s = 1 - (fraction / limit);
+         v = 1.0;
+
+         s = (s * 0.75) + 0.25;
+
+         hsv_to_rgb (balls [i].hue, s, v, 
+                     &new_color.red, &new_color.green, &new_color.blue);
+         if (XAllocColor (dpy, cmap, &new_color))
+           {
+             XFreeColors (dpy, cmap, &balls [i].color.pixel, 1, 0);
+             balls [i].color = new_color;
+           }
+       }
+
+      if (mode == ball_mode)
+       {
+         if (!mono_p)
+           XSetForeground (dpy, draw_gc, balls [i].color.pixel);
+         XFillArc (dpy, window, erase_gc, (int) old_x, (int) old_y,
+                   size, size, 0, 360*64);
+         XFillArc (dpy, window, draw_gc,  (int) new_x, (int) new_y,
+                   size, size, 0, 360*64);
+       }
+      if (mode != ball_mode)
+       {
+         point_stack [point_stack_fp].x = new_x;
+         point_stack [point_stack_fp].y = new_y;
+         point_stack_fp++;
+       }
+    }
+
+  /* draw the lines or polygons after computing all points */
+  if (mode != ball_mode)
+    {
+      point_stack [point_stack_fp].x = balls [0].x; /* close the polygon */
+      point_stack [point_stack_fp].y = balls [0].y;
+      point_stack_fp++;
+      if (point_stack_fp == point_stack_size)
+       point_stack_fp = 0;
+      else if (point_stack_fp > point_stack_size) /* better be aligned */
+       abort ();
+      if (!mono_p)
+       {
+         XColor color2, desired;
+         color2 = balls [0].color;
+         switch (cmode)
+           {
+           case cycle_mode:
+             cycle_hue (&color2, color_shift);
+             break;
+           case random_mode:
+             color2.red =   random () % 65535;
+             color2.green = random () % 65535;
+             color2.blue =  random () % 65535;
+             break;
+           default:
+             abort ();
+           }
+             
+         desired = color2;
+         if (XAllocColor (dpy, cmap, &color2))
+           {
+             /* XAllocColor returns the actual RGB that the hardware let us
+                allocate.  Restore the requested values into the XColor struct
+                so that limited-resolution hardware doesn't cause cycle_hue to
+                get "stuck". */
+             color2.red = desired.red;
+             color2.green = desired.green;
+             color2.blue = desired.blue;
+           }
+         else
+           {
+             color2 = balls [0].color;
+             if (!XAllocColor (dpy, cmap, &balls [0].color))
+               abort ();
+           }
+         pixel_stack [pixel_stack_fp++] = balls [0].color.pixel;
+         if (pixel_stack_fp >= pixel_stack_size)
+           pixel_stack_fp = 0;
+         XFreeColors (dpy, cmap, pixel_stack + pixel_stack_fp, 1, 0);
+         balls [0].color = color2;
+         XSetForeground (dpy, draw_gc, balls [0].color.pixel);
+       }
+    }
+
+  switch (mode)
+    {
+    case ball_mode:
+      break;
+    case line_mode:
+      if (segments > 0)
+       XDrawLines (dpy, window, erase_gc, point_stack + point_stack_fp,
+                   npoints + 1, CoordModeOrigin);
+      XDrawLines (dpy, window, draw_gc, point_stack + last_point_stack_fp,
+                 npoints + 1, CoordModeOrigin);
+      break;
+    case polygon_mode:
+      if (segments > 0)
+       XFillPolygon (dpy, window, erase_gc, point_stack + point_stack_fp,
+                     npoints + 1, (npoints == 3 ? Convex : Complex),
+                     CoordModeOrigin);
+      XFillPolygon (dpy, window, draw_gc, point_stack + last_point_stack_fp,
+                   npoints + 1, (npoints == 3 ? Convex : Complex),
+                   CoordModeOrigin);
+      break;
+    case tail_mode:
+      {
+       int i;
+       for (i = 0; i < npoints; i++)
+         {
+           int index = point_stack_fp + i;
+           int next_index = (index + (npoints + 1)) % point_stack_size;
+           XDrawLine (dpy, window, erase_gc,
+                      point_stack [index].x,
+                      point_stack [index].y,
+                      point_stack [next_index].x,
+                      point_stack [next_index].y);
+
+           index = last_point_stack_fp + i;
+           next_index = (index - (npoints + 1)) % point_stack_size;
+           if (next_index < 0) next_index += point_stack_size;
+           if (point_stack [next_index].x == 0 &&
+               point_stack [next_index].y == 0)
+             continue;
+           XDrawLine (dpy, window, draw_gc,
+                      point_stack [index].x,
+                      point_stack [index].y,
+                      point_stack [next_index].x,
+                      point_stack [next_index].y);
+         }
+      }
+      break;
+    case spline_mode:
+    case spline_filled_mode:
+      {
+       int i;
+       static spline *s = 0;
+       if (! s) s = make_spline (npoints);
+       if (segments > 0)
+         {
+           for (i = 0; i < npoints; i++)
+             {
+               s->control_x [i] = point_stack [point_stack_fp + i].x;
+               s->control_y [i] = point_stack [point_stack_fp + i].y;
+             }
+           compute_closed_spline (s);
+           if (mode == spline_filled_mode)
+             XFillPolygon (dpy, window, erase_gc, s->points, s->n_points,
+                           (s->n_points == 3 ? Convex : Complex),
+                           CoordModeOrigin);
+           else
+             XDrawLines (dpy, window, erase_gc, s->points, s->n_points,
+                         CoordModeOrigin);
+         }
+       for (i = 0; i < npoints; i++)
+         {
+           s->control_x [i] = point_stack [last_point_stack_fp + i].x;
+           s->control_y [i] = point_stack [last_point_stack_fp + i].y;
+         }
+       compute_closed_spline (s);
+       if (mode == spline_filled_mode)
+         XFillPolygon (dpy, window, draw_gc, s->points, s->n_points,
+                       (s->n_points == 3 ? Convex : Complex),
+                       CoordModeOrigin);
+       else
+         XDrawLines (dpy, window, draw_gc, s->points, s->n_points,
+                     CoordModeOrigin);
+      }
+      break;
+    default:
+      abort ();
+    }
+
+  XSync (dpy, True);
+}
+
+\f
+char *progclass = "Attraction";
+
+char *defaults [] = {
+  "Attraction.background:      black",         /* to placate SGI */
+  "Attraction.foreground:      white",
+  "*mode:      balls",
+  "*points:    0",
+  "*size:      0",
+  "*threshold: 100",
+  "*delay:     10000",
+  "*glow:      false",
+  "*mouseSize: 10",
+  "*mouse:     false",
+  "*viscosity: 1",
+  "*orbit:     false",
+  "*colorShift:        3",
+  "*segments:  100",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-mode",           ".mode",        XrmoptionSepArg, 0 },
+  { "-points",         ".points",      XrmoptionSepArg, 0 },
+  { "-threshold",      ".threshold",   XrmoptionSepArg, 0 },
+  { "-segments",       ".segments",    XrmoptionSepArg, 0 },
+  { "-delay",          ".delay",       XrmoptionSepArg, 0 },
+  { "-size",           ".size",        XrmoptionSepArg, 0 },
+  { "-color-mode",     ".colorMode",   XrmoptionSepArg, 0 },
+  { "-color-shift",    ".colorShift",  XrmoptionSepArg, 0 },
+  { "-radius",         ".radius",      XrmoptionSepArg, 0 },
+  { "-vx",             ".vx",          XrmoptionSepArg, 0 },
+  { "-vy",             ".vy",          XrmoptionSepArg, 0 },
+  { "-vmult",          ".vMult",       XrmoptionSepArg, 0 },
+  { "-mouse-size",     ".mouseSize",   XrmoptionSepArg, 0 },
+  { "-mouse",          ".mouse",       XrmoptionNoArg, "true" },
+  { "-nomouse",                ".mouse",       XrmoptionNoArg, "false" },
+  { "-viscosity",      ".viscosity",   XrmoptionSepArg, 0 },
+  { "-glow",           ".glow",        XrmoptionNoArg, "true" },
+  { "-noglow",         ".glow",        XrmoptionNoArg, "false" },
+  { "-orbit",          ".orbit",       XrmoptionNoArg, "true" }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  init_balls (dpy, window);
+  while (1)
+    {
+      run_balls (dpy, window);
+      if (delay) usleep (delay);
+    }
+}
diff --git a/hacks/attraction.man b/hacks/attraction.man
new file mode 100644 (file)
index 0000000..e3f9424
--- /dev/null
@@ -0,0 +1,179 @@
+.de EX         \"Begin example
+.ne 5
+.if n .sp 1
+.if t .sp .5
+.nf
+.in +.5i
+..
+.de EE
+.fi
+.in -.5i
+.if n .sp 1
+.if t .sp .5
+..
+.TH XScreenSaver 1 "14-Dec-95" "X Version 11"
+.SH NAME
+attraction - interactions of opposing forces
+.SH SYNOPSIS
+.B attraction
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-points \fIint\fP] [\-threshold \fIint\fP] [\-mode balls | lines | polygons | splines | filled-splines | tails ] [\-color-mode cycle | random] [\-size \fIint\fP] [\-segments \fIint\fP] [\-delay \fIusecs\fP] [\-color-shift \fIdegrees\fP] [\-radius \fIint\fP] [\-vx \fIint\fP] [\-vy \fIint\fP] [\-glow] [\-noglow] [\-orbit] [\-viscosity \fIfloat\fP] [\-mouse] [\-no-mouse] [\-mouse-size]
+.SH DESCRIPTION
+The \fIattraction\fP program has several visually different modes of 
+operation, all of which are based on the interactions of a set of control
+points which attract each other up to a certain distance, and then begin
+to repel each other.  The attraction/repulsion is proportional to the 
+distance between any two particles.
+.SH OPTIONS
+.I attraction
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono 
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-points integer
+How many control points should be used, or 0 to select the number randomly.
+Default 0.  Between 3 and 15 works best.
+.TP 8
+.B \-threshold integer
+The distance (in pixels) from each particle at which the attractive force
+becomes repulsive.  Default 100.
+.TP 8
+.B \-mode "balls | lines | polygons | tails | splines | filled-splines"
+In \fIballs\fP mode (the default) the control points are drawn as filled
+circles.  The larger the circle, the more massive the particle.
+
+In \fIlines\fP mode, the control points are connected by straight lines;
+the effect is something like \fIqix\fP.
+
+In \fIpolygons\fP mode, the control points are connected by straight
+lines, and filled in.  This is most interesting in color.
+
+In \fIsplines\fP mode, a closed spline is interpolated from the control 
+points.
+
+In \fIfilled-splines\fP mode, the splines are filled in instead of being
+outlines.  This is most interesting in color.
+
+In \fItails\fP mode, the path which each particle follows is indicated
+by a worm-like trail, whose length is controlled by the \fIsegments\fP
+parameter.
+.TP 8
+.B \-color-mode cycle | random
+Whether colors should cycle through the spectrum, or be picked randomly.
+.TP 8
+.B \-size integer
+The size of the balls in pixels, or 0, meaning to select the sizes 
+randomly (the default.)  If this is specified, then all balls will be 
+the same size.  This option has an effect in all modes, since the ``size''
+of the balls controls their mass.
+.TP 8
+.B \-segments integer
+If in \fIlines\fP or \fIpolygons\fP mode, how many sets of line segments
+or polygons should be drawn. Default 100.  This has no effect in \fIballs\fP
+mode.  If \fIsegments\fP is 0, then no segments will ever be erased (this
+is only useful in color.)
+.TP 8
+.B \-delay microseconds
+How much of a delay should be introduced between steps of the animation.
+Default 10000, or about 0.01 seconds.
+.TP 8
+.B \-color-shift degrees
+If on a color display, the color of the line segments or polygons will 
+cycle through the spectrum.  This specifies how far the hue of each segment
+should be from the next, in degrees on the HSV wheel.  Default 3.
+This has no effect in \fIballs\fP mode.
+.TP 8
+.B \-radius
+The size in pixels of the circle on which the points are initially positioned.
+The default is slightly smaller than the size of the window.
+.TP 8
+.B \-glow
+This is consulted only in \fIballs\fP mode.  If this is specified, then 
+the saturation of the colors of the points will vary according to their
+current acceleration.  This has the effect that the balls flare brighter
+when they are reacting to each other most strongly.
+
+In \fIglow\fP mode, all of the balls will be drawn the same (random)
+color, modulo the saturation shifts.  In non-glow mode, the balls will
+each be drawn in a random color that doesn't change.
+.TP 8
+.B \-noglow
+Don't do ``glowing.''  This is the default.
+.TP 8
+.B \-vx pixels
+.TP 8
+.B \-vy pixels
+Initial velocity of the balls.  This has no effect in \fB\-orbit\fP mode.
+.TP 8
+.B \-orbit
+Make the initial force on each ball be tangential to the circle on which
+they are initially placed, with the right velocity to hold them in orbit
+about each other.  After a while, roundoff errors will cause the orbit
+to decay.
+.TP 8
+.B \-vmult float
+In orbit mode, the initial velocity of the balls is multiplied by this;
+a number less than 1 will make the balls pull closer together, and a larger
+number will make them move apart.  The default is 1, meaning stability.
+.TP 8
+.B \-viscosity float
+This sets the viscosity of the hypothetical fluid through which the control
+points move; the default is 1, meaning no resistance.  Values higher than 1
+aren't interesting; lower values cause less motion.
+
+One interesting thing to try is
+.EX
+attraction -viscosity 0.8 -points 75 \\
+  -mouse -geometry =500x500
+.EE
+Give it a few seconds to settle down into a stable clump, and then move
+the mouse through it to make "waves".
+.TP 8
+.B \-mouse
+This will cause the mouse to be considered a control point; it will not be
+drawn, but it will influence the other points, so you can wave the mouse
+and influence the images being created.
+.TP 8
+.B \-no-mouse
+Turns off \fB\-mouse\fP.
+.TP 8
+.B \-mouse-size integer
+In \fB\-mouse\fP mode, this sets the mass of the mouse (analagously to the
+\fB\-size\fP parameter.)
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1992, 1993 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@netscape.com>, 13-aug-92.
+
+Viscosity and mouse support by Philip Edward Cutone, III.
diff --git a/hacks/blitspin.c b/hacks/blitspin.c
new file mode 100644 (file)
index 0000000..debdbae
--- /dev/null
@@ -0,0 +1,273 @@
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@netscape.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.
+ */
+
+/* Rotate a bitmap using using bitblts.
+   The bitmap must be square, and must be a power of 2 in size.
+   This was translated from SmallTalk code which appeared in the
+   August 1981 issue of Byte magazine.
+
+   The input bitmap may be non-square, it is padded and centered
+   with the background color.  Another way would be to subdivide
+   the bitmap into square components and rotate them independently
+   (and preferably in parallel), but I don't think that would be as
+   interesting looking.
+
+   It's too bad almost nothing uses blitter hardware these days,
+   or this might actually win.
+ */
+
+#include "screenhack.h"
+#include <stdio.h>
+
+#ifdef HAVE_XPM
+# include <X11/xpm.h>
+# ifndef PIXEL_ALREADY_TYPEDEFED
+#  define PIXEL_ALREADY_TYPEDEFED /* Sigh, Xmu/Drawing.h needs this... */
+# endif
+#endif
+
+#include <X11/Xmu/Drawing.h>
+
+#include "default.xbm"
+
+static Display *dpy;
+static Window window;
+static unsigned int size;
+static Pixmap self, temp, mask;
+static GC SET, CLR, CPY, IOR, AND, XOR;
+static GC gc;
+static int delay, delay2;
+static Pixmap bitmap;
+static int depth;
+static unsigned int fg, bg;
+
+static void rotate(), init (), display ();
+
+#define copy_all_to(from, xoff, yoff, to, gc)          \
+  XCopyArea (dpy, (from), (to), (gc), 0, 0,            \
+            size-(xoff), size-(yoff), (xoff), (yoff))
+
+#define copy_all_from(to, xoff, yoff, from, gc)                \
+  XCopyArea (dpy, (from), (to), (gc), (xoff), (yoff),  \
+            size-(xoff), size-(yoff), 0, 0)
+
+static void
+rotate ()
+{
+  int qwad; /* fuckin' C, man... who needs namespaces? */
+  XFillRectangle (dpy, mask, CLR, 0, 0, size, size);
+  XFillRectangle (dpy, mask, SET, 0, 0, size>>1, size>>1);
+  for (qwad = size>>1; qwad > 0; qwad>>=1)
+    {
+      if (delay) usleep (delay);
+      copy_all_to   (mask,       0,       0, temp, CPY);  /* 1 */
+      copy_all_to   (mask,       0,    qwad, temp, IOR);  /* 2 */
+      copy_all_to   (self,       0,       0, temp, AND);  /* 3 */
+      copy_all_to   (temp,       0,       0, self, XOR);  /* 4 */
+      copy_all_from (temp,    qwad,       0, self, XOR);  /* 5 */
+      copy_all_from (self,    qwad,       0, self, IOR);  /* 6 */
+      copy_all_to   (temp,    qwad,       0, self, XOR);  /* 7 */
+      copy_all_to   (self,       0,       0, temp, CPY);  /* 8 */
+      copy_all_from (temp,    qwad,    qwad, self, XOR);  /* 9 */
+      copy_all_to   (mask,       0,       0, temp, AND);  /* A */
+      copy_all_to   (temp,       0,       0, self, XOR);  /* B */
+      copy_all_to   (temp,    qwad,    qwad, self, XOR);  /* C */
+      copy_all_from (mask, qwad>>1, qwad>>1, mask, AND);  /* D */
+      copy_all_to   (mask,    qwad,       0, mask, IOR);  /* E */
+      copy_all_to   (mask,       0,    qwad, mask, IOR);  /* F */
+      display (self);
+    }
+}
+
+static void
+read_bitmap (bitmap_name, widthP, heightP)
+     char *bitmap_name;
+     int *widthP, *heightP;
+{
+#ifdef HAVE_XPM
+  XpmAttributes xpmattrs;
+  int result;
+  xpmattrs.valuemask = 0;
+  bitmap = 0;
+  result = XpmReadFileToPixmap (dpy, window, bitmap_name, &bitmap, 0,
+                               &xpmattrs);
+  switch (result)
+    {
+    case XpmColorError:
+      fprintf (stderr, "%s: warning: xpm color substitution performed\n",
+              progname);
+      /* fall through */
+    case XpmSuccess:
+      *widthP = xpmattrs.width;
+      *heightP = xpmattrs.height;
+      break;
+    case XpmFileInvalid:
+    case XpmOpenFailed:
+      bitmap = 0;
+      break;
+    case XpmColorFailed:
+      fprintf (stderr, "%s: xpm: color allocation failed\n", progname);
+      exit (-1);
+    case XpmNoMemory:
+      fprintf (stderr, "%s: xpm: out of memory\n", progname);
+      exit (-1);
+    default:
+      fprintf (stderr, "%s: xpm: unknown error code %d\n", progname, result);
+      exit (-1);
+    }
+  if (! bitmap)
+#endif
+    {
+      int xh, yh;
+      Pixmap b2;
+      bitmap = XmuLocateBitmapFile (DefaultScreenOfDisplay (dpy), bitmap_name,
+                                   0, 0, widthP, heightP, &xh, &yh);
+      if (! bitmap)
+       {
+         fprintf (stderr, "%s: couldn't find bitmap %s\n", progname,
+                  bitmap_name);
+         exit (1);
+       }
+      b2 = XmuCreatePixmapFromBitmap (dpy, window, bitmap, *widthP, *heightP,
+                                     depth, fg, bg);
+      XFreePixmap (dpy, bitmap);
+      bitmap = b2;
+    }
+}
+
+static void
+init ()
+{
+  XWindowAttributes xgwa;
+  Colormap cmap;
+  XGCValues gcv;
+  int width, height;
+  unsigned int real_size;
+  char *bitmap_name;
+  int i;
+
+  XGetWindowAttributes (dpy, window, &xgwa);
+  cmap = xgwa.colormap;
+  depth = xgwa.depth;
+
+  fg = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+  bg = get_pixel_resource ("background", "Background", dpy, cmap);
+  delay = get_integer_resource ("delay", "Integer");
+  delay2 = get_integer_resource ("delay2", "Integer");
+  if (delay < 0) delay = 0;
+  if (delay2 < 0) delay2 = 0;
+  bitmap_name = get_string_resource ("bitmap", "Bitmap");
+  if (! bitmap_name || !*bitmap_name)
+    bitmap_name = "(default)";
+
+  if (!strcmp (bitmap_name, "(default)"))
+    {
+      width = logo_width;
+      height = logo_height;
+      bitmap = XCreatePixmapFromBitmapData (dpy, window, (char *) logo_bits,
+                                           width, height, fg, bg, depth);
+    }
+  else
+    {
+      read_bitmap (bitmap_name, &width, &height);
+    }
+
+  real_size = (width > height) ? width : height;
+
+  size = real_size;
+  /* semi-sleazy way of doing (setq size (expt 2 (ceiling (log size 2)))). */
+  for (i = 31; i > 0; i--)
+    if (size & (1<<i)) break;
+  if (size & (~(1<<i)))
+    size = (size>>i)<<(i+1);
+  self = XCreatePixmap (dpy, window, size, size, depth);
+  temp = XCreatePixmap (dpy, window, size, size, depth);
+  mask = XCreatePixmap (dpy, window, size, size, depth);
+  gcv.foreground = (depth == 1 ? 1 : (~0));
+  gcv.function=GXset;  SET = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
+  gcv.function=GXclear;CLR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
+  gcv.function=GXcopy; CPY = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
+  gcv.function=GXor;   IOR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
+  gcv.function=GXand;  AND = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
+  gcv.function=GXxor;  XOR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
+
+  gcv.foreground = gcv.background = bg;
+  gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
+  /* Clear self to the background color (not to 0, which CLR does.) */
+  XFillRectangle (dpy, self, gc, 0, 0, size, size);
+  XSetForeground (dpy, gc, fg);
+
+  XCopyArea (dpy, bitmap, self, CPY, 0, 0, width, height,
+            (size - width)>>1, (size - height)>>1);
+}
+
+static void
+display (pixmap)
+     Pixmap pixmap;
+{
+  XWindowAttributes xgwa;
+  static int last_w = 0, last_h = 0;
+  XGetWindowAttributes (dpy, window, &xgwa);
+  if (xgwa.width != last_w || xgwa.height != last_h)
+    {
+      XClearWindow (dpy, window);
+      last_w = xgwa.width;
+      last_h = xgwa.height;
+    }
+#ifdef HAVE_XPM
+  if (depth != 1)
+    XCopyArea (dpy, pixmap, window, gc, 0, 0, size, size,
+              (xgwa.width-size)>>1, (xgwa.height-size)>>1);
+  else
+#endif
+    XCopyPlane (dpy, pixmap, window, gc, 0, 0, size, size,
+               (xgwa.width-size)>>1, (xgwa.height-size)>>1, 1);
+/*
+  XDrawRectangle (dpy, window, gc,
+                 ((xgwa.width-size)>>1)-1, ((xgwa.height-size)>>1)-1,
+                 size+2, size+2);
+*/
+  XSync (dpy, True);
+}
+
+\f
+char *progclass = "BlitSpin";
+
+char *defaults [] = {
+  "BlitSpin.background:        black",         /* to placate SGI */
+  "BlitSpin.foreground:        white",
+  "*delay:     500000",
+  "*delay2:    500000",
+  "*bitmap:    (default)",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-delay",          ".delay",       XrmoptionSepArg, 0 },
+  { "-delay2",         ".delay2",      XrmoptionSepArg, 0 },
+  { "-bitmap",         ".bitmap",      XrmoptionSepArg, 0 }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (d, w)
+     Display *d;
+     Window w;
+{
+  dpy = d;
+  window = w;
+  init ();
+  while (1)
+    {
+      rotate ();
+      if (delay2) usleep (delay2);
+    }
+}
diff --git a/hacks/blitspin.man b/hacks/blitspin.man
new file mode 100644 (file)
index 0000000..4198883
--- /dev/null
@@ -0,0 +1,77 @@
+.TH XScreenSaver 1 "17-aug-92" "X Version 11"
+.SH NAME
+blitspin - rotate a bitmap in an interesting way
+.SH SYNOPSIS
+.B blitspin
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-bitmap \fIfilename\fP] [\-delay \fIusecs\fP] [\-delay2 \fIusecs\fP]
+.SH DESCRIPTION
+The \fIblitspin\fP program repeatedly rotates a bitmap by 90 degrees by
+using logical operations: the bitmap is divided into quadrants, and the
+quadrants are shifted clockwise.  Then the same thing is done again with
+progressively smaller quadrants, except that all sub-quadrants of a 
+given size are rotated in parallel.  So this takes \fBO(16*log2(N))\fP 
+blits of size NxN, with the limitation that the image must be square,
+and the size must be a power of 2.
+.SH OPTIONS
+.I blitspin
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono 
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-bitmap \fIfilename\fP
+The file name of a bitmap to rotate.  It need not be square: it 
+will be padded with the background color.  If unspecified or the
+string \fI(default)\fP, a builtin bitmap is used.
+
+If support for the \fIXPM\fP library was enabled at compile-time, 
+the specified file may be in \fIXPM\fP format as well as \fIXBM\fP, and 
+thus may be a color image.
+
+The \fB*bitmapFilePath\fP resource will be searched if the bitmap
+name is not a fully-qualified pathname.
+.PP
+.TP 8
+.B \-delay microseconds
+How long to delay between steps of the rotation process, in microseconds.
+Default is 500000, one-half second.
+.PP
+.TP 8
+.B \-delay2 microseconds
+How long to delay between each 90-degree rotation, in microseconds.
+Default is 500000, one-half second.
+.B DISPLAY
+to get the default host and display number.
+.SH ENVIRONMENT
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1992, 1993 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@netscape.com>, 17-aug-92.
+
+Based on SmallTalk code which appeared in the August 1981 issue of Byte
+magazine.
diff --git a/hacks/decayscreen.c b/hacks/decayscreen.c
new file mode 100644 (file)
index 0000000..ce18a7e
--- /dev/null
@@ -0,0 +1,146 @@
+/* xscreensaver, Copyright (c) 1992, 1993, 1994 
+ * Jamie Zawinski <jwz@netscape.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.
+ */
+
+/* decayscreen
+ *
+ * Based on slidescreen program from the xscreensaver application and the
+ * decay program for Sun framebuffers.  This is the comment from the decay.c
+ * file:
+
+ * decay.c
+ *   find the screen bitmap for the console and make it "decay" by
+ *   randomly shifting random rectangles by one pixelwidth at a time.
+ *
+ *   by David Wald, 1988
+ *        rewritten by Natuerlich!
+ *   based on a similar "utility" on the Apollo ring at Yale.
+
+ * X version by
+ *
+ *  Vivek Khera <khera@cs.duke.edu>
+ *  5-AUG-1993
+ */
+
+#include "screenhack.h"
+
+static int sizex, sizey;
+static int delay;
+static GC gc;
+
+static void
+init_decay (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  XGCValues gcv;
+  XWindowAttributes xgwa;
+  int root_p;
+  Pixmap pixmap;
+
+  delay = get_integer_resource ("delay", "Integer");
+  root_p = get_boolean_resource ("root", "Boolean");
+
+  if (delay < 0) delay = 0;
+
+  gcv.function = GXcopy;
+  gcv.subwindow_mode = IncludeInferiors;
+  gc = XCreateGC (dpy, window, GCForeground |GCFunction | GCSubwindowMode,
+                 &gcv);
+
+  XGetWindowAttributes (dpy, window, &xgwa);
+  sizex = xgwa.width;
+  sizey = xgwa.height;
+
+  copy_default_colormap_contents (dpy, xgwa.colormap, xgwa.visual);
+  pixmap = grab_screen_image (dpy, window, root_p);
+}
+
+
+/*
+ * perform one iteration of decay
+ */
+static void
+decay1 (dpy, window)
+     Display *dpy;
+     Window window;
+{
+    int left, top, width, height;
+
+#define nrnd(x) (random() % (x))
+
+    switch (random() % 8) {
+      case 0:                  /* move a block left */
+      case 1:
+       left = nrnd(sizex - 1) + 1;
+       top = nrnd(sizey);
+       width = nrnd(sizex - left);
+       height = nrnd(sizey - top);
+       XCopyArea (dpy, window, window, gc, left, top, width, height,
+                  left - 1, top);
+       break;
+      case 2:                  /* move a block right */
+      case 3:
+       left = nrnd(sizex - 1);
+       top = nrnd(sizey);
+       width = nrnd(sizex - 1 - left);
+       height = nrnd(sizey - top);
+       XCopyArea (dpy, window, window, gc, left, top, width, height,
+                  left + 1, top);
+       break;
+      case 4:                  /* move a block up */
+       left = nrnd(sizex);
+       top = nrnd(sizey - 1) + 1;
+       width = nrnd(sizex - left);
+       height = nrnd(sizey - top);
+       XCopyArea (dpy, window, window, gc, left, top, width, height,
+                  left, top - 1);
+       break;
+      default:                 /* move block down (biased to this) */
+       left = nrnd(sizex);
+       top = nrnd(sizey - 1);
+       width = nrnd(sizex - left);
+       height = nrnd(sizey - 1 - top);
+       XCopyArea (dpy, window, window, gc, left, top, width, height,
+                  left, top + 1);
+       break;
+    }
+    XSync (dpy, True);
+#undef nrnd
+}
+
+\f
+char *progclass = "DecayScreen";
+
+char *defaults [] = {
+  "DecayScreen.mappedWhenManaged:false",
+  "DecayScreen.dontClearWindow:         true",
+  "*delay:                     10",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-delay",          ".delay",               XrmoptionSepArg, 0 },
+};
+
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+     Display *dpy;
+     Window window;
+{
+    init_decay (dpy, window);
+    while (1) {
+       decay1 (dpy, window);
+       if (delay) usleep (delay);
+    }
+}
diff --git a/hacks/decayscreen.man b/hacks/decayscreen.man
new file mode 100644 (file)
index 0000000..007301b
--- /dev/null
@@ -0,0 +1,53 @@
+.TH XScreenSaver 1 "05-aug-93" "X Version 11"
+.SH NAME
+decayscreen - make a screen meltdown.
+.SH SYNOPSIS
+.B decayscreen
+[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-delay \fIusecs\fP]
+.SH DESCRIPTION
+The \fIdecayscreen\fP program creates a melting effect by randomly
+shifting rectangles around the screen.
+.SH OPTIONS
+.I decayscreen
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono 
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-delay \fImicroseconds\fP
+Slow it down.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH "SEE ALSO"
+X(1),
+xscreensaver(1)
+.SH COPYRIGHT
+Copyright 1992 by Vivek Khera.  Permission to use, copy, modify, distribute, 
+and sell this software and its documentation for any purpose is hereby granted
+without fee, provided that the above copyright notice appear in all copies and
+that both that copyright notice and this permission notice appear in 
+supporting documentation.  No representations are made about the suitability
+of this software for any purpose.  It is provided "as is" without express or
+implied warranty.
+.SH AUTHOR
+Vivek Khera <khera@cs.duke.edu>, 05-Aug-93; based on code by David Wald, 1988.
diff --git a/hacks/default.xbm b/hacks/default.xbm
new file mode 100644 (file)
index 0000000..dcd2ff5
--- /dev/null
@@ -0,0 +1,1686 @@
+#define logo_width 464
+#define logo_height 435
+static unsigned char logo_bits[] = {
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x60,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0x60,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xf0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xf0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xf0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xf8,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xf8,0x01,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xf8,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xfc,0x01,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xfc,0x01,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xfc,0x03,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xfc,0x07,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xfe,0x07,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xfe,0x07,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xfe,0x07,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xff,
+0x0f,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xff,0x0f,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0x80,0xff,0x0f,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0x80,0xff,0x1f,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0x80,0xff,0x3f,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0x80,0xff,0x3f,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0x80,0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0,
+0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0x7f,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0x7f,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xe0,0xff,0x7f,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xe0,0xff,0xff,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xf0,0xff,0xff,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xf0,0xff,0xff,0x01,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xf0,0xff,0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff,
+0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xf8,0xff,0xff,0x03,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0x03,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xfc,0xff,0xff,0x03,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xfc,0xff,0xff,0x07,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xfc,0xff,0xff,0x07,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xfe,0xff,0xff,0x07,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xfe,
+0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xfe,0xff,0xff,
+0x0f,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xff,0xff,0xff,0x0f,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0x80,0xff,0xff,0xff,0x1f,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0x80,0xff,0xff,0xff,0x1f,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0x80,0xff,0xff,0xff,0x1f,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0x80,0xff,0xff,0xff,0x1f,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0,
+0xff,0xff,0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,
+0xff,0x7f,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0xff,0x7f,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0xff,0x7f,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0xff,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xe0,0xff,0xff,0xff,0xff,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xf0,0xff,0xff,0xff,0xff,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xf0,0xff,0xff,0xff,0xff,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff,
+0xff,0xff,0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff,0xff,0xff,
+0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xf8,0xff,0xff,0xff,0xff,0x03,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xf8,0xff,0xff,0xff,0xff,0x03,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xf8,0xff,0xff,0xff,0xff,0x03,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xf8,0xff,0xff,0xff,0xff,0x07,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xfc,0xff,0xdf,0xff,0xff,0x07,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xfe,
+0xff,0xdf,0xff,0xff,0x07,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xfe,0xff,0x8f,
+0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xfe,0xff,0x0f,0xff,0xff,
+0x0f,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xfe,0xff,0x0f,0xff,0xff,0x0f,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xff,0xff,0x07,0xff,0xff,0x1f,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xff,0xff,0x07,0xff,0xff,0x1f,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0x80,0xff,0xff,0x07,0xfe,0xff,0x1f,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0,
+0xff,0xff,0x03,0xfc,0xff,0x3f,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,
+0x03,0xfc,0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0x03,0xfc,
+0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xe0,0xff,0xff,0x01,0xf8,0xff,0x7f,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xe0,0xff,0xff,0x01,0xf8,0xff,0x7f,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xe0,0xff,0xff,0,0xf0,0x03,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xe0,0xff,0xff,0,0xf0,0x03,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xe0,0xff,0x1f,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff,
+0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xf0,0x07,0,0,
+0x80,0xff,0x03,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xf8,0xff,0xff,
+0xff,0xff,0x03,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xf8,0xff,0xff,0xff,0xff,
+0x03,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xc0,0xff,0xff,0xff,0x03,0,0,0xe0,0xff,0x7f,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xfc,0xff,0xff,0,0,0,0,0,0xe0,0xff,0x07,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xe0,0xff,
+0x7f,0xfe,0,0,0,0,0,0,0xfc,0x7f,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xfe,0xff,0x01,0xfe,
+0x01,0,0,0,0,0,0xc0,0xff,0x03,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xfe,0xff,0x01,0xfe,0x01,0,
+0,0,0,0,0xc0,0xff,0x03,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xf0,0xff,0x07,0,0xce,0x07,0,0,0,
+0,0,0,0xfe,0x1f,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xfe,0x7f,0,0,0x87,0x1f,0,0,0,0,0,
+0,0xc0,0xff,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xe0,0xff,0x07,0,0x80,0x03,0x3e,0,0,0,0,0,0,0,
+0xfe,0x07,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xfc,
+0x3f,0,0,0x80,0x03,0xf8,0,0,0,0,0,0,0,0xe0,0x3f,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xfc,0x3f,0,
+0,0x80,0x03,0xf8,0,0,0,0,0,0,0,0xe0,0x3f,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0x80,0xff,0x07,0,0,0xc0,
+0x01,0xe0,0x01,0,0,0,0,0,0,0,0xff,0x01,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xf0,0xff,0x7f,0,0,0xc0,0xfb,0xff,
+0x0f,0,0,0,0,0,0,0,0xf0,0x0f,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xfe,0xff,0xff,0x07,0,0xc0,0xff,0xff,0x3f,0,
+0,0,0,0,0,0,0x80,0xff,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0x80,0xff,0xc0,0xff,0x7f,0,0xe0,0xff,0xff,0x7f,0,0,0,
+0,0,0,0,0,0xfe,0x01,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0x80,0xff,0xc0,0xff,0x7f,0,0xe0,0xff,0xff,0x7f,0,0,0,0,0,
+0,0,0,0xfe,0x01,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0,0x1f,
+0,0xf8,0xff,0x0f,0xf0,0x0f,0xc0,0xff,0x01,0,0,0,0,0,0,
+0,0xf0,0x0f,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xe0,0x0f,0,0,
+0xff,0x7f,0xf0,0x01,0,0xf8,0x03,0,0,0,0,0,0,0,0xc0,
+0x3f,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xf0,0x01,0,0,0x80,0xff,
+0x7b,0,0,0xe0,0x07,0,0,0,0,0,0,0,0,0xfe,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xf8,0,0,0,0,0xfc,0x3f,0,
+0,0x80,0x1f,0,0,0,0,0,0,0,0,0xf0,0x03,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xf8,0,0,0,0,0xfc,0x3f,0,0,0x80,
+0x1f,0,0,0,0,0,0,0,0,0xf0,0x03,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0x3c,0,0,0,0,0xe0,0x7f,0,0,0,0x7e,0,
+0,0,0,0,0,0,0,0xe0,0x0f,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0x3e,0,0,0,0,0,0xff,0x03,0,0,0x70,0,0,0,
+0,0,0,0,0,0x80,0x3f,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0x80,0x0f,
+0,0,0,0,0,0xf0,0x1f,0,0,0,0,0,0,0,0,
+0,0,0,0,0xfc,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xc0,0x0f,0,0,
+0,0,0,0,0xfe,0x01,0,0,0,0,0,0,0,0,0,
+0,0,0xf0,0x01,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xc0,0x07,0,0,0,0,
+0,0,0xf8,0x07,0,0,0,0,0,0,0,0,0,0,0,
+0xe0,0x07,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xc0,0x07,0,0,0,0,0,0,
+0xf8,0x07,0,0,0,0,0,0,0,0,0,0,0,0xe0,0x07,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xe0,0x03,0,0,0,0,0,0,0xe0,0x3f,
+0,0,0,0,0,0,0,0,0,0,0,0x80,0x0f,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xf0,0x01,0,0,0,0,0,0,0x80,0xff,0,0,
+0,0,0,0,0,0,0,0,0,0,0x3f,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xf8,0x01,0,0,0,0,0,0,0,0xfc,0x07,0,0,0,
+0,0,0,0,0,0,0,0,0x7c,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xf8,
+0,0,0,0xfe,0x03,0,0,0,0xf0,0x0f,0,0,0,0,0,
+0,0,0,0,0,0,0xf8,0x01,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xf8,0,0,
+0,0xfe,0x03,0,0,0,0xf0,0x0f,0,0,0,0,0,0,0,
+0,0,0,0,0xf8,0x01,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xfc,0,0,0xf0,0xff,
+0x1f,0,0,0,0x80,0x7f,0,0,0,0,0,0,0,0,0,
+0,0,0xf0,0x03,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0x3f,0,0,0xfc,0xff,0x7f,0,
+0,0,0,0xfe,0x01,0,0,0,0,0,0,0,0,0,0,
+0xc0,0x07,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0x80,0x1f,0,0,0xff,0x47,0x7f,0,0,0,
+0,0xf8,0x0f,0,0,0,0,0,0,0,0,0,0,0x80,0x0f,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xf0,0x07,0x80,0xff,0xff,0x3f,0x7c,0,0,0,0,0xc0,
+0xff,0,0,0,0,0,0,0,0,0,0,0,0x3e,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xf0,0x07,0x80,0xff,0xff,0x3f,0x7c,0,0,0,0,0xc0,0xff,0,
+0,0,0,0,0,0,0,0,0,0,0x3e,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xfc,
+0x03,0xc0,0xff,0xfe,0xff,0x7d,0,0,0,0,0x80,0xff,0x01,0,0,
+0,0,0,0,0,0,0,0,0x7c,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0,0x40,
+0,0,0xfe,0x7f,0,0,0,0,0x80,0xff,0x07,0,0,0,0,
+0,0,0,0,0,0,0xf0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xf0,0x3f,0,0,0x80,0x03,
+0xf8,0x3f,0,0,0,0,0x80,0xe7,0x1f,0,0,0,0,0,0,
+0,0,0,0,0xf0,0x01,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xfe,0x0f,0,0,0xf0,0xff,0xff,0x1f,
+0,0,0,0,0x80,0xc7,0x7f,0,0,0,0,0,0,0,0,
+0,0,0xe0,0x03,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xfe,0x0f,0,0,0xf0,0xff,0xff,0x1f,0,0,
+0,0,0x80,0xc7,0x7f,0,0,0,0,0,0,0,0,0,0,
+0xe0,0x03,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xc0,0xff,0x03,0,0,0xf0,0xff,0xff,0x0f,0,0,0,0,
+0xc0,0x0f,0xff,0x01,0,0,0,0,0,0,0,0,0,0xc0,0x07,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xf0,0x7f,0,0,0,0xc0,0xff,0xff,0x01,0,0,0,0,0xc0,0x0f,
+0xfc,0x07,0,0,0,0,0,0,0,0,0,0x80,0x0f,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xff,0x0f,
+0,0,0,0,0,0,0,0,0,0,0,0xc0,0x0f,0xf0,0x0f,
+0,0,0,0,0,0,0,0,0,0,0x1f,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0x80,0xff,0x01,0,0,
+0,0,0,0,0,0,0,0,0,0xe0,0x1f,0x80,0x3f,0,0,
+0,0,0,0,0,0,0,0,0x1c,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xf8,0x0f,0,0,0,0,0,
+0,0,0,0,0,0,0,0xf0,0x1c,0,0xfe,0x03,0,0,0,
+0,0,0,0,0,0,0x78,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xf8,0x0f,0,0,0,0,0,0,0,
+0,0,0,0,0,0xf0,0x1c,0,0xfe,0x03,0,0,0,0,0,
+0,0,0,0,0x78,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xfe,0x01,0,0,0,0,0,0,0,0,0,
+0,0,0,0x70,0x1c,0,0xf0,0x07,0,0,0,0,0,0,0,
+0,0,0xf0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0x3f,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0x70,0x38,0,0xc0,0x1f,0,0,0,0,0,0,0,0,0,
+0xe0,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x80,
+0x0f,0,0,0,0,0,0,0,0,0,0,0,0,0,0x70,
+0x78,0,0,0x7f,0,0,0,0,0,0,0,0,0,0xc0,0x03,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xc0,0x03,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0x70,0x70,0,
+0,0xfc,0,0,0,0,0,0,0,0,0,0xc0,0x07,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xc0,0x03,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0x70,0x70,0,0,0xfc,
+0,0,0,0,0,0,0,0,0,0xc0,0x07,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xc0,0x01,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0x38,0x70,0,0,0xfe,0x03,0xfe,
+0x7f,0,0,0,0,0,0,0,0x0f,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xe0,0x01,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0x38,0xf0,0,0,0xfe,0x0f,0xff,0xff,0x01,
+0,0,0,0,0,0,0x0f,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xe0,0x01,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0x18,0xe0,0,0x80,0x9f,0xff,0x3f,0xfe,0x03,0,0,
+0,0,0,0,0x0f,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xe0,0x01,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0x1c,0xe0,0,0x80,0x0f,0xff,0x07,0xc0,0x0f,0,0,0,0,
+0,0,0x1e,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xe0,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0x1c,0xe0,0,0x80,0x0f,0xff,0x07,0xc0,0x0f,0,0,0,0,0,0,
+0x1e,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0,0xf1,
+0x1f,0,0,0,0,0,0,0,0,0,0,0,0,0x0e,0xe0,
+0,0xc0,0x07,0xfc,0x01,0,0x1f,0,0,0,0,0,0,0x3e,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xc0,0xe1,0xff,0,
+0,0,0,0,0,0,0,0,0,0,0,0x0e,0xe0,0x01,0xe0,
+0x03,0x60,0,0,0x38,0,0,0,0,0,0,0x3c,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xc0,0xc3,0xff,0x01,0,0,
+0,0,0,0,0,0,0,0,0,0x07,0xc0,0x01,0xf0,0x01,0,
+0xe0,0x03,0xf0,0,0,0,0,0,0,0x38,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0x80,0x07,0xf0,0x03,0,0,0,0,
+0,0,0,0,0,0,0,0x07,0xc0,0x03,0xf8,0,0,0xf8,0x1f,
+0xe0,0,0,0,0,0,0,0x38,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0x80,0x07,0xf0,0x03,0,0,0,0,0,0,
+0,0,0,0,0,0x07,0xc0,0x03,0xf8,0,0,0xf8,0x1f,0xe0,0,
+0,0,0,0,0,0x38,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0x80,0x0f,0xc0,0x07,0,0,0,0,0,0,0,0,
+0,0,0,0x07,0x80,0x03,0x78,0,0,0xf8,0x7f,0xe0,0x01,0,0,
+0,0,0,0x78,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0x0f,0x80,0x0f,0,0,0,0,0,0,0,0,0,0,
+0x80,0x03,0x80,0x03,0x3e,0,0,0x78,0x7e,0xc0,0x03,0,0,0,0,
+0,0x78,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0x1e,0x1c,0x0f,0,0,0,0,0,0,0,0,0,0,0x80,0xf3,
+0x9f,0x03,0x1f,0,0,0,0xf0,0x80,0x03,0,0,0,0,0,0x70,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0x1e,0xfe,
+0x0f,0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0x07,
+0x0f,0,0,0,0xe0,0,0x07,0,0,0,0,0,0x70,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0x1e,0xfe,0x0f,0,
+0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0x07,0x0f,0,
+0,0,0xe0,0,0x07,0,0,0,0,0,0x70,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0x7c,0xfc,0x0f,0,0,0,
+0,0,0,0,0,0,0,0xc0,0xff,0xff,0x87,0x07,0,0,0,
+0xe0,0,0x07,0,0,0,0,0,0x70,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0x7c,0xf8,0x0f,0,0,0,0,0,
+0,0,0,0,0,0xc0,0x3f,0xf4,0xc7,0x07,0,0,0,0xe0,0,
+0x07,0,0,0,0,0,0x70,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xf0,0x01,0,0,0,0,0,0,0,0,
+0,0,0,0xe0,0x03,0x80,0xe7,0x01,0,0,0,0xe0,0,0x07,0,
+0,0,0,0,0xe0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xf0,0x03,0,0,0,0,0,0,0,0,0,0,
+0,0xe0,0,0,0xff,0x01,0,0,0,0xe0,0x80,0x07,0,0,0,
+0,0,0xe0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xe0,0x03,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xff,0,0,0,0,0xf8,0x80,0x03,0,0,0,0,0,
+0xe0,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xe0,
+0x03,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xff,0,0,0,0,0xf8,0x80,0x03,0,0,0,0,0,0xe0,0x01,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0x80,0x07,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0x7e,0,
+0,0,0,0x7c,0xc0,0x01,0,0,0,0,0,0xe0,0x01,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0x1f,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0x3e,0,0x80,0x07,
+0xe0,0x3f,0xe0,0x01,0,0,0,0,0,0xc0,0x01,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0x1f,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0x1e,0,0xc0,0xff,0xff,0x0f,
+0xe0,0,0,0,0,0,0,0xc0,0x01,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0x1e,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0x1f,0,0xe0,0xff,0xff,0x03,0xe0,0,
+0,0,0,0,0,0xc0,0x01,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0x1e,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0x1f,0,0xe0,0xff,0xff,0x03,0xe0,0,0,0,
+0,0,0,0xc0,0x01,0,0,0,0,0,0,0,0,0,0,
+0,0,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0x3f,0,0x1e,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0x80,0x07,0,0x80,0xff,0x7f,0,0xf8,0x01,0,0,0,0,
+0,0xc0,0x01,0,0,0,0,0,0,0,0,0,0,0,0,
+0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0x03,0x1e,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xc0,0x07,0,0,0,0,0,0xfc,0x07,0,0,0,0,0,0xc0,
+0x01,0,0,0,0,0,0,0,0,0,0,0,0,0xe0,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x1e,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xe0,0x03,
+0,0,0,0,0,0xfe,0x0f,0,0,0,0,0,0xc0,0x01,0,
+0,0,0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x0f,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xf0,0x01,0,0,
+0,0,0x80,0xcf,0x3f,0,0,0xfe,0x01,0,0xc0,0x01,0,0,0,
+0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x0f,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xf0,0x01,0,0,0,0,
+0x80,0xcf,0x3f,0,0,0xfe,0x01,0,0xc0,0x01,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x0f,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xf0,0,0,0,0,0,0xe0,0xe7,
+0xff,0,0,0xfe,0x0f,0,0xc0,0xe1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0x03,0,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0x03,0x0f,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0x7c,0,0,0,0,0xf0,0xff,0xf9,0xff,0x01,
+0,0xe0,0x1f,0,0xc0,0xe1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0x03,0,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0x03,0x0f,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0x7e,0,0,0,0xc0,0xff,0x7f,0xfe,0xe1,0x07,0,0xc0,
+0xff,0,0xc0,0xe1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0x01,0,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0x03,0x07,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0x1e,0,0,0,0xfc,0xff,0x1f,0xff,0x81,0x0f,0,0x80,0xf1,0x03,
+0xc0,0xe1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0,0,
+0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,
+0x07,0,0,0,0,0,0,0,0,0,0,0,0,0,0x1e,
+0,0,0,0xfc,0xff,0x1f,0xff,0x81,0x0f,0,0x80,0xf1,0x03,0xc0,0xe1,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0,0,0xc0,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x81,0x0f,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0x1f,0,0,
+0,0xff,0x3f,0x80,0xff,0,0x1f,0,0x80,0xc1,0x07,0xc0,0xe1,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0,0,0,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc1,0xff,0x3f,0,0,
+0,0,0,0,0,0,0,0,0,0x80,0x0f,0,0x03,0xc0,0x3f,
+0,0xe0,0x7f,0,0x7e,0,0x80,0x01,0x1f,0xe0,0xe1,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0,0,0,0xfc,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0xff,0xff,0x03,0,0,0,
+0,0,0,0,0,0,0,0x80,0x0f,0x80,0x07,0xf0,0x07,0,0xf0,
+0x3f,0,0xf8,0,0x80,0x01,0x3c,0xe0,0xe1,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0x03,0,0,0,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0xff,0xff,0x7f,0,0,0,0,0,
+0,0,0,0,0,0xc0,0x03,0x80,0xff,0xff,0x01,0,0xfc,0x1f,0,
+0xf0,0x01,0xc0,0x01,0x38,0xe0,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0,0,0,0,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0x7f,0xf0,0,0xf8,0xff,0x07,0,0,0,0,0,0,
+0,0,0,0xe0,0x03,0,0xfe,0x1f,0,0x80,0xbf,0x07,0,0x80,0x07,
+0xc0,0x01,0xe0,0xf1,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,
+0,0,0,0,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0x7f,0xf0,0,0xf8,0xff,0x07,0,0,0,0,0,0,0,0,
+0,0xe0,0x03,0,0xfe,0x1f,0,0x80,0xbf,0x07,0,0x80,0x07,0xc0,0x01,
+0xe0,0xf1,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0,0,
+0,0,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
+0xf0,0,0,0xfe,0x7f,0,0,0,0,0,0,0,0,0,0xf0,
+0x01,0,0xf8,0x03,0,0xc0,0xcf,0x03,0,0x80,0x1f,0xf0,0x01,0xe0,0x71,
+0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0,0,0,0,
+0,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xf0,0,
+0,0xe0,0xff,0x03,0,0,0,0,0,0,0,0,0xf8,0,0,
+0,0,0,0xe0,0xe7,0x03,0,0,0x7e,0xff,0,0xc0,0x73,0xf0,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0,0,0,0,0,0xfc,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xf0,0,0,0,
+0xfc,0x1f,0,0,0,0,0,0,0,0,0x78,0,0,0,0,
+0,0xf8,0xf3,0,0,0,0xfc,0x7f,0,0,0x7f,0xf0,0xff,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0,0,0,0,0,0,0xf0,0xff,0xff,
+0xff,0x1f,0,0,0,0,0,0,0,0xf0,0,0,0,0xe0,0xff,
+0,0,0,0,0,0,0,0,0x3c,0,0,0,0,0,0x7c,
+0xf8,0,0,0,0xf8,0xff,0xff,0xff,0x7f,0xf0,0xff,0xff,0xff,0xff,0xff,
+0xff,0xff,0xff,0x7f,0,0,0,0,0,0,0xf0,0xff,0xff,0xff,0x1f,
+0,0,0,0,0,0,0,0xf0,0,0,0,0xe0,0xff,0,0,
+0,0,0,0,0,0,0x3c,0,0,0,0,0,0x7c,0xf8,0,
+0,0,0xf8,0xff,0xff,0xff,0x7f,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+0xff,0x7f,0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0x3f,0,0,
+0,0,0,0,0,0x70,0,0,0,0x80,0xff,0x0f,0,0,0,
+0,0,0,0,0x3e,0,0,0,0,0,0x7f,0x7c,0,0,0,
+0xe0,0xff,0xff,0xff,0x7f,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,
+0,0,0,0,0,0,0x80,0xff,0xff,0xff,0xff,0,0,0,0,
+0,0,0,0x78,0,0,0,0,0xfe,0x7f,0,0,0,0,0,
+0,0,0x1e,0,0,0,0,0xc0,0x1f,0x3e,0,0,0,0xc0,0xff,
+0xff,0xff,0x7f,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0,0,
+0,0,0,0,0,0xff,0xff,0xff,0xff,0x01,0,0,0,0,0,
+0,0x7c,0,0,0,0,0xf0,0xff,0x03,0,0,0,0,0,0,
+0x0f,0,0,0,0,0xe0,0x07,0x1f,0,0,0,0x80,0x0f,0,0,
+0x3c,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0,0,0,0,
+0,0,0,0xfc,0xff,0xff,0xff,0x07,0,0,0,0,0,0,0x3c,
+0,0,0,0,0,0xfe,0x0f,0,0,0,0,0,0,0x0f,0,
+0,0,0,0xfc,0x83,0x0f,0,0,0,0,0x0f,0,0,0x38,0xf0,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0,0,0,0,0,0,
+0,0xfc,0xff,0xff,0xff,0x07,0,0,0,0,0,0,0x3c,0,0,
+0,0,0,0xfe,0x0f,0,0,0,0,0,0,0x0f,0,0,0,
+0,0xfc,0x83,0x0f,0,0,0,0,0x0f,0,0,0x38,0xf0,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0x01,0,0,0,0,0,0,0,0xf0,
+0xff,0xff,0xff,0x0f,0,0,0,0,0,0,0x1e,0,0,0,0xf8,
+0xff,0xff,0x3f,0,0,0,0,0,0x80,0x07,0,0,0,0,0xff,
+0x80,0x07,0,0,0,0,0x3e,0,0,0x38,0,0,0,0,0,
+0xff,0xff,0xff,0x7f,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,
+0xff,0x7f,0,0,0,0,0,0,0x0f,0,0,0,0xff,0xff,0xff,
+0xff,0x03,0,0,0,0,0xe0,0x01,0,0,0,0xe0,0x1f,0xe0,0x03,
+0,0,0,0,0x78,0,0,0x1c,0,0,0,0,0xe0,0xff,0xff,
+0xff,0x0f,0,0,0,0,0,0,0,0,0,0xff,0xff,0xff,0xff,
+0,0,0,0,0,0x80,0x0f,0,0,0,0xff,0x3f,0xe0,0xff,0x0f,
+0,0,0,0,0xf0,0x01,0,0,0,0xf8,0x07,0xf0,0x01,0,0,
+0,0,0xf0,0x01,0,0x1e,0,0,0,0,0xf0,0xff,0xff,0xff,0x07,
+0,0,0,0,0,0,0,0,0,0xfe,0xff,0xff,0xff,0x03,0,
+0,0,0,0x80,0x07,0,0,0,0xe0,0xff,0x01,0xfe,0x3f,0,0,
+0,0,0xf0,0,0,0,0,0xfe,0x01,0xf8,0,0,0,0,0,
+0xc0,0x03,0,0x0e,0,0,0,0,0xfc,0xff,0xff,0xff,0x01,0,0,
+0,0,0,0,0,0,0,0xfe,0xff,0xff,0xff,0x03,0,0,0,
+0,0x80,0x07,0,0,0,0xe0,0xff,0x01,0xfe,0x3f,0,0,0,0,
+0xf0,0,0,0,0,0xfe,0x01,0xf8,0,0,0,0,0,0xc0,0x03,
+0,0x0e,0,0,0,0,0xfc,0xff,0xff,0xff,0x01,0,0,0,0,
+0,0,0,0,0,0xf8,0xff,0xff,0xff,0x07,0,0,0,0,0x80,
+0x07,0,0,0,0,0xf8,0x07,0xc0,0xff,0x01,0,0,0,0xf8,0,
+0,0,0x80,0x7f,0,0x78,0,0,0,0,0,0xc0,0x0f,0,0x0e,
+0,0,0,0,0xff,0xff,0xff,0xff,0,0,0,0,0,0,0,
+0,0,0,0xf0,0xff,0xff,0xff,0x1f,0,0,0,0,0xc0,0xe3,0xff,
+0xff,0,0,0xc0,0x1f,0x80,0xff,0x03,0,0,0,0x3c,0,0,0,
+0xe0,0x1f,0,0x3e,0,0,0,0,0,0,0x0f,0,0x07,0,0,
+0,0x80,0xff,0xff,0xff,0x1f,0,0,0,0,0,0,0,0,0,
+0,0xc0,0xff,0xff,0xff,0x7f,0,0,0,0,0xc0,0xfb,0xff,0xff,0x0f,
+0,0,0x3e,0x80,0xf3,0x1f,0,0,0,0x3e,0,0,0,0xf8,0x07,
+0,0x1e,0,0,0,0,0,0,0x1e,0,0x07,0,0,0,0xe0,
+0xff,0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,0,0,
+0xff,0xff,0xff,0xff,0,0,0,0,0xc0,0xff,0xff,0xff,0xff,0,0,
+0x7c,0xc0,0x81,0xff,0,0,0,0x1f,0,0,0,0xff,0x01,0,0x0f,
+0,0,0,0,0,0,0x7c,0x80,0x07,0,0,0,0xf0,0xff,0xff,
+0xff,0x03,0,0,0,0,0,0,0,0,0,0,0,0xfc,0xff,
+0xff,0xff,0x03,0,0,0,0xc0,0x7f,0,0xe0,0xff,0x3f,0,0xf0,0xc0,
+0x01,0xfe,0x03,0,0,0x0f,0,0,0xc0,0x7f,0,0xc0,0x07,0,0,
+0,0,0,0,0xf0,0xc0,0x03,0,0,0,0xfc,0xff,0xff,0xff,0,
+0,0,0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0xff,
+0x03,0,0,0,0xc0,0x7f,0,0xe0,0xff,0x3f,0,0xf0,0xc0,0x01,0xfe,
+0x03,0,0,0x0f,0,0,0xc0,0x7f,0,0xc0,0x07,0,0,0,0,
+0,0,0xf0,0xc0,0x03,0,0,0,0xfc,0xff,0xff,0xff,0,0,0,
+0,0,0,0,0,0,0,0,0,0xf8,0xff,0xff,0xff,0x07,0,
+0,0,0xc0,0x0f,0,0,0xfc,0xff,0x03,0xc0,0xe3,0x01,0xf0,0x07,0,
+0x80,0x07,0,0,0xf0,0x1f,0,0xc0,0x07,0,0,0,0,0,0,
+0xf0,0xc1,0x01,0,0,0,0xff,0xff,0xff,0x7f,0,0,0,0,0,
+0,0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0x1f,0,0,0,
+0xc0,0x07,0,0,0,0xfc,0xff,0,0xf7,0,0,0x3f,0,0xc0,0x03,
+0,0,0xff,0,0,0xe0,0x01,0,0,0,0,0,0,0xc0,0xe3,
+0x01,0,0,0xc0,0xff,0xff,0xff,0x0f,0,0,0,0,0,0,0,
+0,0,0,0,0,0x80,0xff,0xff,0xff,0xff,0,0,0,0xc0,0x01,
+0,0,0,0xc0,0xff,0x07,0x7f,0,0,0xfc,0,0xe0,0x03,0,0xe0,
+0x3f,0,0,0xf0,0x01,0,0,0,0,0,0,0x80,0xff,0,0,
+0,0xf0,0xff,0xff,0xff,0x07,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xfe,0xff,0xff,0xff,0,0,0,0xc0,0x01,0,0,
+0,0,0xfe,0x7f,0x7f,0,0,0xf8,0x01,0xe0,0x01,0,0xfc,0x07,0,
+0,0xf8,0,0,0,0,0,0,0,0,0xff,0,0,0,0xfc,
+0xff,0xff,0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xfe,0xff,0xff,0xff,0,0,0,0xc0,0x01,0,0,0,0,
+0xfe,0x7f,0x7f,0,0,0xf8,0x01,0xe0,0x01,0,0xfc,0x07,0,0,0xf8,
+0,0,0,0,0,0,0,0,0xff,0,0,0,0xfc,0xff,0xff,
+0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xfc,0xff,0xff,0xff,0x03,0,0,0xc0,0x03,0,0,0,0,0xe0,0xff,
+0x3f,0,0,0xf0,0x07,0xf0,0,0,0xff,0x03,0,0,0x7c,0,0,
+0,0,0,0,0,0,0x7e,0,0,0,0xff,0xff,0xff,0x7f,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff,
+0xff,0xff,0x0f,0,0,0xc0,0x03,0,0,0,0,0,0xfe,0x3f,0,
+0,0xc0,0x3f,0xf8,0,0xf8,0x3f,0,0,0,0x3c,0,0,0,0,
+0,0,0,0,0x3c,0,0,0x80,0xff,0xff,0xff,0x3f,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0xff,
+0x3f,0,0,0xc0,0x03,0,0,0,0,0,0xf0,0xff,0x0f,0,0,
+0x7f,0x7c,0,0xfe,0x07,0,0,0,0x1e,0,0,0,0,0,0,
+0,0,0x1e,0,0,0xe0,0xff,0xff,0xff,0x0f,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,0xff,0x7f,0,
+0,0x80,0x07,0,0,0,0,0,0,0xff,0x7f,0,0,0xfc,0x3e,
+0xe0,0x7f,0,0,0,0,0x1f,0,0,0,0,0,0,0,0,
+0x1f,0,0,0xf8,0xff,0xff,0xff,0x03,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0x80,0xff,0xff,0xff,0x7f,0,0,0x80,
+0x07,0,0,0,0,0,0,0xff,0x7f,0,0,0xfc,0x3e,0xe0,0x7f,
+0,0,0,0,0x1f,0,0,0,0,0,0,0,0,0x1f,0,
+0,0xf8,0xff,0xff,0xff,0x03,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xfe,0xff,0xff,0xff,0x01,0,0x80,0x0f,0,
+0,0,0,0,0,0xf0,0xff,0x1f,0,0xf0,0x1f,0xfe,0x0f,0,0,
+0,0x80,0x0f,0,0,0,0,0,0,0,0,0x07,0,0,0xfc,
+0xff,0xff,0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xf8,0xff,0xff,0xff,0x03,0,0,0x0f,0,0,0,
+0,0,0,0,0xfc,0xff,0x3f,0xc0,0xff,0xff,0,0,0,0,0xc0,
+0x07,0,0,0,0,0,0,0,0x80,0x03,0,0,0xff,0xff,0xff,
+0x3f,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xf0,0xff,0xff,0xff,0x0f,0,0,0x1e,0,0,0,0,0,
+0,0,0,0xfe,0xff,0xff,0xff,0x1f,0,0,0,0,0xe0,0x03,0,
+0,0,0,0,0,0,0xe0,0x03,0,0xc0,0xff,0xff,0xff,0x1f,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0x80,0xff,0xff,0xff,0x7f,0,0,0x3c,0,0,0,0,0,0,0,
+0,0,0xfc,0xff,0xff,0x03,0,0,0,0,0xf0,0x01,0,0,0,
+0,0,0,0,0xf8,0,0,0xf8,0xff,0xff,0xff,0x03,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0x80,0xff,
+0xff,0xff,0x7f,0,0,0x3c,0,0,0,0,0,0,0,0,0,
+0xfc,0xff,0xff,0x03,0,0,0,0,0xf0,0x01,0,0,0,0,0,
+0,0,0xf8,0,0,0xf8,0xff,0xff,0xff,0x03,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xfe,0xff,0xff,
+0xff,0,0,0x78,0,0,0,0,0,0,0,0,0,0,0xf8,
+0xff,0x1f,0,0,0,0,0xf0,0,0,0,0,0,0,0,0,
+0x7c,0,0,0xfc,0xff,0xff,0xff,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0xff,0x03,
+0,0xf0,0,0,0,0,0,0,0,0,0,0,0,0xfe,0x7f,
+0,0,0,0,0x7c,0,0,0,0,0,0,0,0,0x3e,0,
+0,0xff,0xff,0xff,0x7f,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xf0,0xff,0xff,0xff,0x07,0,0xe0,
+0x01,0,0,0,0,0,0,0,0,0,0,0x7c,0xfe,0,0,
+0,0,0x3c,0,0,0,0,0,0,0,0x80,0x1f,0,0xc0,0xff,
+0xff,0xff,0x1f,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0x1f,0,0xc0,0x03,0,
+0,0,0,0,0,0,0,0,0,0x78,0xf8,0x03,0,0,0,
+0x1e,0,0,0,0,0,0,0,0xc0,0x07,0,0xe0,0xff,0xff,0xff,
+0x07,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0x80,0xff,0xff,0xff,0x7f,0,0x80,0x07,0,0,0,
+0,0,0,0,0,0,0,0x70,0xe0,0x0f,0,0,0,0x0f,0,
+0,0,0,0,0,0,0xf0,0x03,0,0xf8,0xff,0xff,0xff,0x03,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0x80,0xff,0xff,0xff,0x7f,0,0x80,0x07,0,0,0,0,0,
+0,0,0,0,0,0x70,0xe0,0x0f,0,0,0,0x0f,0,0,0,
+0,0,0,0,0xf0,0x03,0,0xf8,0xff,0xff,0xff,0x03,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xff,0xff,0xff,0xff,0,0x80,0x0f,0,0,0,0,0,0,0,
+0,0,0,0x70,0,0x3f,0,0,0x80,0x0f,0,0,0,0,0,
+0,0,0xf8,0x01,0,0xfe,0xff,0xff,0x7f,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xfc,
+0xff,0xff,0xff,0x03,0,0x1f,0,0,0,0,0,0,0,0,0,
+0,0x70,0,0xfe,0,0,0xc0,0x03,0,0,0,0,0,0,0,
+0x7e,0,0x80,0xff,0xff,0xff,0x3f,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff,0xff,
+0xff,0x0f,0,0x3e,0,0,0,0,0,0,0,0,0,0,0x70,
+0,0xf8,0x01,0,0xc0,0x03,0,0,0,0,0,0,0,0x3e,0,
+0xc0,0xff,0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0xff,0x3f,
+0,0xf8,0,0,0,0,0,0,0,0,0,0,0x70,0,0x80,
+0x0f,0,0xf0,0x01,0,0,0,0,0,0,0xc0,0x0f,0,0xf8,0xff,
+0xff,0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0xff,0x3f,0,0xf8,
+0,0,0,0,0,0,0,0,0,0,0x70,0,0x80,0x0f,0,
+0xf0,0x01,0,0,0,0,0,0,0xc0,0x0f,0,0xf8,0xff,0xff,0xff,
+0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xff,0xff,0xff,0xff,0,0xe0,0x01,0,
+0,0,0,0,0,0,0,0,0x70,0,0,0x3e,0,0xf0,0,
+0,0,0,0,0,0,0xe0,0x07,0,0xfe,0xff,0xff,0xff,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xfc,0xff,0xff,0xff,0x03,0xc0,0x03,0,0,0,
+0,0,0,0,0,0,0x70,0,0,0xfc,0,0x78,0,0,0,
+0,0,0,0,0xf8,0x01,0x80,0xff,0xff,0xff,0x3f,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xf0,0xff,0xff,0xff,0x0f,0xc0,0x07,0,0,0,0,0,
+0,0,0,0,0x78,0,0,0xe0,0x03,0x3c,0,0,0,0,0,
+0,0,0x7c,0,0xe0,0xff,0xff,0xff,0x0f,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xc0,0xff,0xff,0xff,0x1f,0,0x0f,0,0,0,0,0,0,0,
+0,0,0x7c,0,0,0xc0,0x1f,0x1e,0,0,0,0,0,0,0,
+0x3e,0,0xf0,0xff,0xff,0xff,0x03,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0,
+0xff,0xff,0xff,0x1f,0,0x0f,0,0,0,0,0,0,0,0,0,
+0x7c,0,0,0xc0,0x1f,0x1e,0,0,0,0,0,0,0,0x3e,0,
+0xf0,0xff,0xff,0xff,0x03,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,
+0xff,0x7f,0,0x1e,0,0,0,0,0,0,0,0,0,0x7c,0,
+0,0,0x3f,0x0f,0,0,0,0,0,0,0x80,0x0f,0,0xfc,0xff,
+0xff,0xff,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xfe,0xff,0xff,0xff,
+0x01,0x7c,0,0,0,0,0,0,0,0,0,0x3c,0,0,0,
+0xfc,0x0f,0,0,0,0,0,0,0xe0,0x07,0,0xff,0xff,0xff,0x3f,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0xff,0x03,0x78,
+0,0,0,0,0,0,0,0,0,0x3c,0,0,0,0xf8,0x07,
+0,0,0,0,0,0,0xf0,0x01,0xc0,0xff,0xff,0xff,0x1f,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xf0,0xff,0xff,0xff,0x07,0xf0,0x01,0,
+0,0,0,0,0,0,0,0x1c,0,0,0,0xfc,0x03,0,0,
+0,0,0,0,0xf8,0,0xf0,0xff,0xff,0xff,0x07,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xf0,0xff,0xff,0xff,0x07,0xf0,0x01,0,0,0,
+0,0,0,0,0,0x1c,0,0,0,0xfc,0x03,0,0,0,0,
+0,0,0xf8,0,0xf0,0xff,0xff,0xff,0x07,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xe0,0xff,0xff,0xff,0x1f,0xe0,0x03,0,0,0,0,0,
+0,0,0,0x1c,0,0,0,0xfc,0x01,0,0,0,0,0,0,
+0x7e,0,0xf8,0xff,0xff,0xff,0x01,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xff,0xff,0xff,0xff,0x80,0x0f,0,0,0,0,0,0,0,
+0,0x1e,0,0,0,0xff,0,0,0,0,0,0,0x80,0x0f,0,
+0xfe,0xff,0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xfc,0xff,0xff,0xff,0x01,0x1f,0,0,0,0,0,0,0,0,0x0e,
+0,0,0x80,0x7f,0,0,0,0,0,0,0xc0,0x07,0x80,0xff,0xff,
+0xff,0x0f,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xf8,0xff,
+0xff,0xff,0x07,0x3e,0,0,0,0,0,0,0,0,0x0e,0,0,
+0xc0,0x3f,0,0,0,0,0,0,0xf0,0x01,0xe0,0xff,0xff,0xff,0x07,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0xff,0xff,
+0x0f,0x7c,0,0,0,0,0,0,0,0,0x0f,0,0,0xe0,0x3f,
+0,0,0,0,0,0,0xf8,0x01,0xf8,0xff,0xff,0xff,0x01,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0x0f,0x7c,
+0,0,0,0,0,0,0,0,0x0f,0,0,0xe0,0x3f,0,0,
+0,0,0,0,0xf8,0x01,0xf8,0xff,0xff,0xff,0x01,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xc0,0xff,0xff,0xff,0x3f,0xf0,0,0,
+0,0,0,0,0,0,0x0f,0,0,0xf0,0x1f,0,0,0,0,
+0,0,0x7e,0,0xfc,0xff,0xff,0xff,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xfe,0xff,0xff,0x7f,0xe0,0x01,0,0,0,
+0,0,0,0x80,0x07,0,0,0xfc,0x1f,0,0,0,0,0,0,
+0x3e,0,0xff,0xff,0xff,0x3f,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xfc,0xff,0xff,0xff,0xe0,0x03,0,0,0,0,0,
+0,0x80,0x07,0,0,0xfc,0x0f,0,0,0,0,0,0,0x1f,0xc0,
+0xff,0xff,0xff,0x1f,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xf0,0xff,0xff,0xff,0xc1,0x07,0,0,0,0,0,0,0xc0,
+0x03,0,0,0xfe,0x07,0,0,0,0,0,0xc0,0x0f,0xf0,0xff,0xff,
+0xff,0x07,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xf0,0xff,0xff,0xff,0xc1,0x07,0,0,0,0,0,0,0xc0,0x03,0,
+0,0xfe,0x07,0,0,0,0,0,0xc0,0x0f,0xf0,0xff,0xff,0xff,0x07,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff,
+0xff,0xff,0x83,0x0f,0,0,0,0,0,0,0xc0,0x01,0,0,0xff,
+0x07,0,0,0,0,0,0xc0,0x07,0xf8,0xff,0xff,0xff,0x03,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,0xff,
+0x0f,0x1e,0,0,0,0,0,0,0xe0,0x01,0,0xc0,0xef,0x03,0,
+0,0,0,0,0xe0,0x01,0xff,0xff,0xff,0x7f,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xfe,0xff,0xff,0x0f,0x1c,
+0,0,0,0,0,0,0xf0,0,0,0xe0,0xf3,0x01,0,0,0,
+0,0,0xf0,0x80,0xff,0xff,0xff,0x1f,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0x1f,0x38,0,0,
+0,0,0,0,0x70,0,0,0xf0,0xf9,0,0,0,0,0,0,
+0x78,0xe0,0xff,0xff,0xff,0x07,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xfc,0xff,0xff,0x1f,0x38,0,0,0,0,
+0,0,0x70,0,0,0xf0,0xf9,0,0,0,0,0,0,0x78,0xe0,
+0xff,0xff,0xff,0x07,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xf0,0xff,0xff,0x7f,0xf0,0,0,0,0,0,0,
+0x78,0,0,0x78,0x7c,0,0,0,0,0,0,0x3c,0xf0,0xff,0xff,
+0xff,0x03,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0x80,0xff,0xff,0xff,0xe0,0,0,0,0,0,0,0x78,0,
+0,0x7e,0x7c,0,0,0,0,0,0,0x3c,0xf8,0xff,0xff,0xff,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xff,0xff,0xff,0xe0,0x01,0,0,0,0,0,0x3c,0,0,0x3e,
+0x3e,0,0,0,0,0,0,0x1f,0xfe,0xff,0xff,0x7f,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xfe,
+0xff,0xff,0xc1,0x03,0,0,0,0,0,0x3c,0,0,0x0f,0x1e,0,
+0,0,0,0,0,0x0f,0xfe,0xff,0xff,0x1f,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xfe,0xff,0xff,
+0xc1,0x03,0,0,0,0,0,0x3c,0,0,0x0f,0x1e,0,0,0,
+0,0,0,0x0f,0xfe,0xff,0xff,0x1f,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0x83,0x07,
+0,0,0,0,0,0x1e,0,0xc0,0x07,0x0f,0,0,0,0,0,
+0x80,0x07,0xff,0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xf0,0xff,0xff,0x07,0x0f,0,0,
+0,0,0,0x0f,0,0xe0,0x83,0x0f,0,0,0,0,0,0x80,0xc7,
+0xff,0xff,0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xc0,0xff,0xff,0x0f,0x0f,0,0,0,0,
+0,0x07,0,0xf0,0x81,0x07,0,0,0,0,0,0xc0,0xc3,0xff,0xff,
+0xff,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xff,0xff,0x1f,0x1c,0,0,0,0,0x80,0x03,
+0,0x7c,0xc0,0x03,0,0,0,0,0,0xe0,0xe1,0xff,0xff,0x7f,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xfe,0xff,0x3f,0x3c,0,0,0,0,0xc0,0x03,0,0x3f,
+0xe0,0x01,0,0,0,0,0,0xe0,0xe0,0xff,0xff,0x1f,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xfe,0xff,0x3f,0x3c,0,0,0,0,0xc0,0x03,0,0x3f,0xe0,0x01,
+0,0,0,0,0,0xe0,0xe0,0xff,0xff,0x1f,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xf8,
+0xff,0x3f,0x3c,0,0,0,0,0xe0,0x01,0x80,0x1f,0xe0,0x01,0,0,
+0,0,0,0xf0,0xe0,0xff,0xff,0x07,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xf8,0xff,0x3f,
+0x38,0,0,0,0,0xe0,0,0xe0,0x07,0xf0,0,0,0,0,0,
+0,0x78,0xf8,0xff,0xff,0x01,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xf8,0xff,0x3f,0x38,0,
+0,0,0,0xf0,0,0xf0,0x03,0x70,0,0,0,0,0,0,0x78,
+0xf8,0xff,0xff,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xf8,0xff,0x3f,0x38,0,0,0,
+0,0x70,0,0xfe,0,0x38,0,0,0,0,0,0,0x3c,0xfc,0xff,
+0x3f,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xf8,0xff,0x3f,0x38,0,0,0,0,0x70,
+0,0xfe,0,0x38,0,0,0,0,0,0,0x3c,0xfc,0xff,0x3f,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xf8,0xff,0x3f,0x38,0,0,0,0,0x38,0x80,0x3f,
+0,0x3c,0,0,0,0,0,0,0x1c,0xfc,0xff,0x3f,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xfc,0xff,0x3f,0x38,0,0,0,0,0x1c,0xc0,0x0f,0,0x1c,
+0,0,0,0,0,0,0x1e,0xfc,0xff,0x3f,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xfc,0xff,0x1f,0x38,0,0,0,0,0x1e,0xf0,0x03,0,0x1e,0,0,
+0,0,0,0,0x1e,0xfc,0xff,0x3f,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xfe,0xff,
+0x1f,0x38,0,0,0,0,0x0f,0x7f,0,0,0x0f,0,0,0,0,
+0,0,0x0f,0xfc,0xff,0x3f,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xfe,0xff,0x1f,0x38,
+0,0,0,0,0x0f,0x7f,0,0,0x0f,0,0,0,0,0,0,
+0x0f,0xfc,0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xfe,0xff,0x1f,0x38,0,0,
+0,0,0xe7,0x3f,0,0,0x07,0,0,0,0,0,0,0x0f,0xfc,
+0xff,0x7f,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xff,0xff,0x0f,0x38,0,0,0,0x80,
+0xfb,0x0f,0,0x80,0x03,0,0,0,0,0,0,0x07,0xfc,0xff,0x7f,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xff,0xff,0x07,0x38,0,0,0,0xc0,0xff,0x01,
+0,0xc0,0x03,0,0,0,0,0,0x80,0x07,0xf8,0xff,0xff,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xff,0xff,0x07,0x38,0,0,0,0xe0,0x3f,0,0,0xc0,
+0x01,0,0,0,0,0,0xc0,0x03,0xf8,0xff,0xff,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xff,0xff,0x07,0x38,0,0,0,0xe0,0x3f,0,0,0xc0,0x01,0,
+0,0,0,0,0xc0,0x03,0xf8,0xff,0xff,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0x80,0xff,
+0xff,0x07,0x38,0,0,0,0xe0,0x0f,0,0,0xe0,0,0,0,0,
+0,0,0xc0,0x03,0xf8,0xff,0xff,0x01,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,0x03,
+0x38,0,0,0,0xf0,0x03,0,0,0xf0,0,0,0,0,0,0,
+0xe0,0x01,0xf8,0xff,0xff,0x01,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0x03,0x38,0,
+0,0,0x70,0,0,0,0x70,0,0,0,0,0,0,0xe0,0x01,
+0xf0,0xff,0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xc0,0xff,0xff,0x01,0x38,0,0,0,
+0,0,0,0,0x78,0,0,0,0,0,0,0xe0,0,0xf0,0xff,
+0xff,0x03,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xe0,0xff,0xff,0,0x38,0,0,0,0,0,
+0,0,0x38,0,0,0,0,0,0,0xf0,0,0xf0,0xff,0xff,0x03,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xe0,0xff,0xff,0,0x38,0,0,0,0,0,0,0,
+0x38,0,0,0,0,0,0,0xf0,0,0xf0,0xff,0xff,0x03,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xe0,0xff,0xff,0,0x38,0,0,0,0,0,0,0,0x3c,0,
+0,0,0,0,0,0xf0,0,0xe0,0xff,0xff,0x07,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xe0,
+0xff,0xff,0,0x38,0,0,0,0,0,0,0,0x1e,0,0,0,
+0,0,0,0x78,0,0xe0,0xff,0xff,0x07,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff,0x7f,
+0,0x18,0,0,0,0,0,0,0,0x1e,0,0,0,0,0,
+0,0x78,0,0xc0,0xff,0xff,0x0f,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xf0,0xff,0x7f,0,0x18,
+0,0,0,0,0,0,0,0x0f,0,0,0,0,0,0,0x3c,
+0,0xc0,0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xf0,0xff,0x7f,0,0x18,0,0,
+0,0,0,0,0,0x0f,0,0,0,0,0,0,0x3c,0,0xc0,
+0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xf8,0xff,0x7f,0,0x1c,0,0,0,0,
+0,0,0x80,0x07,0,0,0,0,0,0,0x3c,0,0x80,0xff,0xff,
+0x0f,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xf8,0xff,0x3f,0,0x1c,0,0,0,0,0,0,
+0x80,0x07,0,0,0,0,0,0,0x1e,0,0x80,0xff,0xff,0x1f,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xfc,0xff,0x1f,0,0x1c,0,0,0,0,0,0,0xc0,0x03,
+0,0,0,0,0,0,0x1e,0,0x80,0xff,0xff,0x1f,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xfc,0xff,0x1f,0,0x1c,0,0,0,0,0,0,0xc0,0x03,0,0,
+0,0,0,0,0x1f,0,0,0xff,0xff,0x1f,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xfc,0xff,
+0x1f,0,0x1c,0,0,0,0,0,0,0xc0,0x03,0,0,0,0,
+0,0,0x1f,0,0,0xff,0xff,0x1f,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xfe,0xff,0x0f,0,
+0x1c,0,0,0,0,0,0,0xe0,0x01,0,0,0,0,0,0,
+0x0f,0,0,0xff,0xff,0x3f,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xfe,0xff,0x0f,0,0x1c,0,
+0,0,0,0,0,0xe0,0,0,0,0,0,0,0,0x0f,0,
+0,0xff,0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xfe,0xff,0x07,0,0x1c,0,0,0,
+0,0,0,0xf0,0,0,0,0,0,0,0x80,0x07,0,0,0xfe,
+0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xff,0xff,0x07,0,0x1e,0,0,0,0,0,
+0,0x70,0,0,0,0,0,0,0x80,0x07,0,0,0xfe,0xff,0x7f,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xff,0xff,0x07,0,0x1e,0,0,0,0,0,0,0x70,
+0,0,0,0,0,0,0x80,0x07,0,0,0xfe,0xff,0x7f,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xff,0xff,0x07,0,0x1e,0,0,0,0,0,0,0x78,0,0,
+0,0,0,0,0x80,0x07,0,0,0xfc,0xff,0x7f,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0x80,0xff,
+0xff,0x03,0,0x1e,0,0,0,0,0,0,0x38,0,0,0,0,
+0,0,0x80,0x03,0,0,0xfc,0xff,0xff,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,0x03,
+0,0x1e,0,0,0,0,0,0,0x3c,0,0,0,0,0,0,
+0xc0,0x03,0,0,0xfc,0xff,0xff,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0x03,0,0x1e,
+0,0,0,0,0,0,0x1e,0,0,0,0,0,0,0xc0,0x03,
+0,0,0xf8,0xff,0xff,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xc0,0xff,0xff,0x03,0,0x1e,0,0,
+0,0,0,0,0x1e,0,0,0,0,0,0,0xc0,0x03,0,0,
+0xf8,0xff,0xff,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xc0,0xff,0xff,0x01,0,0x1e,0,0,0,0,
+0,0,0x1e,0,0,0,0,0,0,0xc0,0x03,0,0,0xf8,0xff,
+0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xe0,0xff,0xff,0x01,0,0x1c,0,0,0,0,0,0,
+0x0f,0,0,0,0,0,0,0xc0,0x01,0,0,0xf0,0xff,0xff,0x01,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xe0,0xff,0xff,0,0,0x1c,0,0,0,0,0,0x80,0x07,0,
+0,0,0,0,0,0xc0,0x01,0,0,0xf0,0xff,0xff,0x01,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xe0,
+0xff,0xff,0,0,0x3c,0,0,0,0,0,0x80,0x07,0,0,0,
+0,0,0,0xc0,0x01,0,0,0xf0,0xff,0xff,0x03,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff,0x7f,
+0,0,0x3c,0,0,0,0,0,0x80,0x03,0,0,0,0,0,
+0,0xc0,0x01,0,0,0xe0,0xff,0xff,0x03,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xf0,0xff,0x7f,0,0,
+0x3c,0,0,0,0,0,0x80,0x03,0,0,0,0,0,0,0xc0,
+0x01,0,0,0xe0,0xff,0xff,0x03,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xf0,0xff,0x7f,0,0,0x38,0,
+0,0,0,0,0xc0,0x03,0,0,0,0,0,0,0xc0,0x01,0,
+0,0xe0,0xff,0xff,0x03,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xf8,0xff,0x3f,0,0,0x38,0,0,0,
+0,0,0xc0,0x01,0,0,0,0,0,0,0xc0,0x01,0,0,0xe0,
+0xff,0xff,0x07,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xf8,0xff,0x3f,0,0,0x38,0,0,0,0,0,
+0xe0,0x01,0,0,0,0,0,0,0xc0,0x01,0,0,0xc0,0xff,0xff,
+0x07,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xfc,0xff,0x1f,0,0,0x38,0,0,0,0,0,0xe0,0,
+0,0,0,0,0,0,0xc0,0x01,0,0,0xc0,0xff,0xff,0x07,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xfc,0xff,0x1f,0,0,0x38,0,0,0,0,0,0xe0,0,0,0,
+0,0,0,0,0xc0,0x01,0,0,0xc0,0xff,0xff,0x07,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xfc,0xff,
+0x1f,0,0,0x38,0,0,0,0,0,0xf0,0,0,0,0,0,
+0,0,0xc0,0x01,0,0,0x80,0xff,0xff,0x0f,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xfc,0xff,0x1f,0,
+0,0x38,0,0,0,0,0,0x78,0,0,0,0,0,0,0,
+0xc0,0x03,0,0,0x80,0xff,0xff,0x0f,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xfe,0xff,0x0f,0,0,0x38,
+0,0,0,0,0,0x78,0,0,0,0,0,0,0,0xc0,0x03,
+0,0,0,0xff,0xff,0x1f,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xfe,0xff,0x0f,0,0,0x3c,0,0,
+0,0,0,0x3c,0,0,0,0,0,0,0,0x80,0x07,0,0,
+0,0xff,0xff,0x1f,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xfe,0xff,0x0f,0,0,0x3c,0,0,0,0,
+0,0x3c,0,0,0,0,0,0,0,0x80,0x07,0,0,0,0xff,
+0xff,0x1f,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xff,0x07,0,0,0xfc,0x3f,0,0,0,0,0,0x3e,
+0,0,0,0,0,0,0,0x80,0x07,0,0,0,0xfe,0xff,0x1f,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0x0f,0,0xe0,0xff,0xff,0x3f,0,0,0,0,0,0x1e,0,0,
+0,0,0,0,0,0,0x0f,0,0,0,0xfe,0xff,0x3f,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xfc,0xff,0xff,0xff,0x3f,0,0,0,0,0,0x0f,0,0,0,0,
+0,0,0,0,0x0f,0,0,0,0xfe,0xff,0x3f,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0xff,
+0xff,0x0f,0x3c,0,0,0,0,0,0x0f,0,0,0,0,0,0,
+0,0,0x0e,0,0,0,0xfc,0xff,0x3f,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0x0f,
+0x3c,0,0,0,0,0,0x0f,0,0,0,0,0,0,0,0,
+0x0e,0,0,0,0xfc,0xff,0x3f,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0x01,0,0x38,0,
+0,0,0,0x80,0x07,0,0,0,0,0,0,0,0,0x1e,0,
+0,0,0xfc,0xff,0x7f,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xf0,0xff,0xff,0,0,0,0x38,0,0,0,
+0,0x80,0x07,0,0,0,0,0,0,0,0,0x3c,0,0,0,
+0xfc,0xff,0x7f,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xff,0xff,0x03,0,0,0,0x38,0,0,0,0,0xc0,
+0x03,0,0,0,0,0,0,0,0,0x78,0,0,0,0xf8,0xff,
+0x7f,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xfc,0xff,0x1f,0,0,0,0,0x78,0,0,0,0,0xc0,0x01,0,
+0,0,0,0,0,0,0,0x70,0,0,0,0xf8,0xff,0xff,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,
+0x01,0,0,0,0,0x70,0,0,0,0,0xe0,0x01,0,0,0,
+0,0,0,0,0,0xf0,0x01,0,0,0xf0,0xff,0xff,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0x01,0,
+0,0,0,0x70,0,0,0,0,0xe0,0x01,0,0,0,0,0,
+0,0,0,0xf0,0x01,0,0,0xf0,0xff,0xff,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xff,0xff,0x07,0,0xfe,0,0,
+0,0x70,0,0,0,0,0xe0,0,0,0,0,0,0,0,0,
+0,0xe0,0x03,0,0,0xf0,0xff,0xff,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xf0,0xff,0x1f,0,0xf8,0xff,0,0,0,0x70,
+0,0,0,0,0xf0,0,0,0,0,0,0,0,0,0,0xc0,
+0x03,0,0,0xf0,0xff,0xff,0x01,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xfe,0x7f,0,0xe0,0xff,0x7f,0,0,0,0x70,0,0,
+0,0,0xf8,0,0,0,0,0,0,0,0,0,0x80,0x0f,0,
+0,0xf0,0xff,0xff,0x01,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xe0,0xff,0x03,0,0xf0,0xff,0x3f,0,0,0,0x70,0,0,0,0,
+0x78,0,0,0,0,0,0,0,0,0,0,0x1f,0,0,0xe0,
+0xff,0xff,0x03,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xe0,0xff,
+0x03,0,0xf0,0xff,0x3f,0,0,0,0x70,0,0,0,0,0x78,0,
+0,0,0,0,0,0,0,0,0,0x1f,0,0,0xe0,0xff,0xff,
+0x03,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xfc,0x7f,0,0,
+0xf8,0xff,0x3f,0,0,0,0x70,0,0,0,0,0x78,0,0,0,
+0,0,0,0,0,0,0,0x7c,0,0,0xe0,0xff,0xff,0x03,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0x80,0xff,0x07,0,0,0xf8,0xff,
+0x1f,0,0,0,0xe0,0,0,0,0,0x3c,0,0,0,0,0,
+0,0,0,0,0,0xf8,0x01,0,0xe0,0xff,0xff,0x03,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xc0,0xff,0,0,0,0xfc,0xff,0x1f,0,
+0,0,0xe0,0,0,0,0,0x3c,0,0,0,0,0,0,0,
+0,0,0,0xe0,0x07,0,0xc0,0xff,0xff,0x03,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xc0,0x1f,0,0,0,0xfe,0xff,0x1f,0,0,0,
+0xe0,0,0,0,0,0x3c,0,0,0x60,0,0,0,0,0,0,
+0,0xc0,0x3f,0,0xc0,0xff,0xff,0x07,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xc0,0x1f,0,0,0,0xfe,0xff,0x1f,0,0,0,0xe0,0,
+0,0,0,0x3c,0,0,0x60,0,0,0,0,0,0,0,0xc0,
+0x3f,0,0xc0,0xff,0xff,0x07,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0x80,0x03,0,0,0,0xfe,0xff,0x0f,0,0,0,0xe0,0,0,0,
+0,0x3e,0,0,0x70,0,0,0,0,0,0,0,0,0xff,0x01,
+0x80,0xff,0xff,0x07,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xfe,0xff,0x0f,0,0,0,0xe0,0,0,0,0,0x3f,
+0,0,0x38,0,0,0,0,0,0,0,0,0xf8,0x3f,0x80,0xff,
+0xff,0x0f,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xff,0xff,0x07,0,0,0,0xc0,0x01,0,0,0,0xff,0,0,
+0x38,0,0,0,0,0,0,0,0,0xc0,0xff,0,0xfc,0xff,0x0f,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xff,
+0xff,0x07,0,0,0,0xc0,0x01,0,0,0,0xf7,0x03,0,0x3c,0,
+0,0,0,0,0,0,0,0,0xff,0x0f,0xc0,0xff,0x0f,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xff,0xff,0x07,
+0,0,0,0xc0,0x01,0,0,0,0xf7,0x03,0,0x3c,0,0,0,
+0,0,0,0,0,0,0xff,0x0f,0xc0,0xff,0x0f,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,0x03,0,0,
+0,0xc0,0x01,0,0,0x80,0xe3,0x0f,0,0x3f,0,0,0,0,0,
+0,0,0,0,0xf0,0x7f,0,0xf8,0x1f,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0x80,0xff,0xff,0x03,0,0,0,0xc0,
+0x01,0,0,0x80,0xe3,0xff,0xff,0x3f,0,0,0,0,0,0,0,
+0,0,0x80,0xff,0x03,0x80,0x0f,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0x80,0xff,0xff,0x03,0,0,0,0xc0,0x01,0,
+0,0x80,0xc3,0xff,0xff,0x3f,0,0,0,0,0,0,0,0,0,
+0,0xfe,0x1f,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xc0,0xff,0xff,0x01,0,0,0,0xc0,0x01,0,0,0xc0,
+0x01,0xff,0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0xe0,
+0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xc0,0xff,0xff,0,0,0,0,0xc0,0x01,0,0,0xc0,0x01,0xfe,
+0x7f,0x38,0,0,0,0,0,0,0,0,0,0,0,0xfe,0x1f,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0,
+0xff,0xff,0,0,0,0,0xc0,0x01,0,0,0xc0,0x01,0xfe,0x7f,0x38,
+0,0,0,0,0,0,0,0,0,0,0,0xfe,0x1f,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0xff,
+0,0,0,0,0xc1,0x01,0,0,0xe0,0,0x3e,0,0x38,0,0,
+0,0,0,0,0,0,0,0,0,0xf0,0xff,0x01,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0xff,0,0,
+0,0x80,0xc3,0x01,0,0,0xe0,0,0x7c,0,0x3c,0,0,0,0,
+0,0,0,0,0,0,0,0,0xff,0x7f,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xf0,0xff,0x7f,0,0,0,0xf0,
+0xc3,0x01,0,0,0xf0,0,0xf0,0,0x3c,0,0,0,0,0,0,
+0,0,0,0,0,0,0x80,0xff,0xff,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xf8,0xff,0x7f,0,0,0,0xf8,0xc3,0x01,
+0,0,0xf0,0,0xe0,0x01,0x3c,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xe0,0xff,0xff,0x03,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xf8,0xff,0x7f,0,0,0,0xf8,0xc3,0x01,0,0,
+0xf0,0,0xe0,0x01,0x3c,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xe0,0xff,0xff,0x03,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xf8,0xff,0x7f,0,0,0,0xff,0xc3,0x03,0,0,0x70,0,
+0xc0,0x03,0x3c,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0x80,0xff,0xff,0xff,0x07,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xf8,0xff,0x3f,0,0,0x80,0xff,0xc3,0x03,0,0,0x70,0,0xc0,0x03,
+0x3c,0,0,0,0,0,0,0,0,0,0,0,0xf0,0x01,0,
+0xf0,0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xf8,0xff,
+0x1f,0,0,0xe0,0xff,0xc3,0x03,0,0,0x78,0,0x80,0x07,0x3c,0,
+0,0,0,0,0,0,0,0,0,0,0xf0,0x7f,0,0,0,
+0xfc,0x0f,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xfc,0xff,0x1f,0,
+0,0xf8,0xff,0xc3,0x03,0,0,0x78,0,0,0x0f,0x3c,0,0,0,
+0,0,0,0,0,0,0,0,0xe0,0xff,0x0f,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xfc,0xff,0x1f,0,0,0xf8,
+0xff,0xc3,0x03,0,0,0x78,0,0,0x0f,0x3c,0,0,0,0,0,
+0,0,0,0,0,0,0xe0,0xff,0x0f,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xfc,0xff,0x0f,0,0,0xfe,0xff,0x83,
+0x03,0,0,0x3c,0,0,0x1e,0x1c,0,0,0,0,0,0,0,
+0,0xfc,0xff,0x01,0xe0,0xff,0xff,0x01,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xfe,0xff,0x0f,0,0x80,0xff,0xff,0x87,0x03,0,
+0,0x3c,0,0,0x3c,0x1c,0,0,0,0,0,0,0xf8,0xff,0xff,
+0xff,0xff,0xe1,0xff,0xff,0x03,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xfe,0xff,0x0f,0,0xc0,0xff,0xff,0x87,0x03,0,0,0x3c,
+0,0,0x78,0x1c,0,0,0,0,0,0xfe,0xff,0xff,0xff,0xff,0xff,
+0xe1,0xff,0xff,0x03,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xff,0xff,0x07,0,0xf8,0xff,0xff,0xc7,0x03,0,0,0x1c,0,0,
+0xe0,0x1c,0,0,0,0x80,0xff,0xff,0xff,0x01,0,0,0,0xc0,0xff,
+0xff,0x03,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xff,
+0xff,0x07,0,0xf8,0xff,0xff,0xc7,0x03,0,0,0x1c,0,0,0xe0,0x1c,
+0,0,0,0x80,0xff,0xff,0xff,0x01,0,0,0,0xc0,0xff,0xff,0x03,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xff,0xff,0x03,
+0,0xfe,0xff,0xff,0xc7,0x03,0,0,0x1c,0,0,0xe0,0x1f,0,0,
+0,0xf0,0xff,0xff,0,0,0,0,0,0x80,0xff,0xff,0x07,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,0x03,0,0xff,
+0xff,0xff,0xc7,0x03,0,0,0x1c,0,0,0x80,0x1f,0,0,0,0xff,
+0xff,0x03,0,0,0,0xfc,0x03,0x80,0xff,0xff,0x07,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0x80,0xff,0xff,0x03,0xc0,0xff,0xff,0xff,
+0xc7,0x03,0,0,0x1e,0,0,0,0x1f,0,0,0xf8,0xff,0x0f,0,
+0x80,0xff,0xff,0xff,0x1f,0,0xff,0xff,0x07,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0x80,0xff,0xff,0x01,0xf0,0xff,0xff,0xff,0xc3,0x03,
+0,0,0xfe,0xff,0,0,0x1f,0,0xe0,0xff,0x3f,0,0,0x80,0xff,
+0xff,0xff,0x3f,0,0xff,0xff,0x07,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xc0,0xff,0xff,0x01,0xfc,0xff,0xff,0xff,0xc1,0x03,0,0,
+0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0,0,0x80,0xff,0xff,0xff,
+0x7f,0,0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xc0,0xff,0xff,0x01,0xfc,0xff,0xff,0xff,0xc1,0x03,0,0,0xfe,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0x01,0,0,0x80,0xff,0xff,0xff,0x7f,0,
+0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xe0,
+0xff,0xff,0x01,0xff,0xff,0xff,0xff,0x80,0x03,0,0,0xfe,0xff,0xff,0xff,
+0xff,0xff,0xff,0x07,0,0,0,0,0xfe,0xff,0xff,0xff,0x01,0xfe,0xff,
+0x1f,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0xff,
+0x80,0xff,0xff,0xff,0x3f,0,0,0,0,0x7c,0,0,0xf5,0xff,0xff,
+0x3f,0,0,0,0,0,0xfc,0xff,0xff,0xff,0x07,0xfe,0xff,0x1f,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0x7f,0xf0,0xff,
+0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xf0,0xff,0xff,0xff,0x1f,0xfe,0xff,0x1f,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xf0,0xff,0x7f,0xf8,0xff,0xff,0xff,
+0x03,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xc0,0xff,0xff,0xff,0x3f,0xfe,0xff,0x3f,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xf0,0xff,0x7f,0xf8,0xff,0xff,0xff,0x03,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xc0,0xff,0xff,0xff,0x3f,0xfe,0xff,0x3f,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xf0,0xff,0xff,0xff,0xff,0xff,0x7f,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xff,
+0xff,0xff,0xff,0xfc,0xff,0x3f,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xf8,0xff,0xff,0xff,0xff,0xff,0x3f,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,
+0xff,0xff,0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xf8,0xff,0xff,0xff,0xff,0xff,0x0f,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xf0,0xff,0xff,0xff,0xff,
+0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xfc,0xff,
+0xff,0xff,0xff,0xff,0x03,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0xff,0xff,0x7f,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0xff,
+0xff,0xff,0x03,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0xff,0xff,0x7f,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0xff,0xff,0xff,
+0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0x80,0xff,0xff,0xff,0xff,0xff,0x7f,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xfc,0xff,0xff,0xff,0xff,0x7f,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xfe,0xff,0xff,0xff,0xff,0xff,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xfe,0xff,0xff,0xff,0xff,0x3f,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xfc,0xff,0xff,0xff,0xff,0xff,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xfe,0xff,0xff,0xff,0xff,0x07,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xf0,
+0xff,0xff,0xff,0xff,0xff,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xfe,0xff,0xff,0xff,0xff,0x07,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff,0xff,
+0xff,0xff,0xff,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xfe,
+0xff,0xff,0xff,0xff,0x03,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0xff,
+0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xff,0xff,0xff,
+0xff,0xff,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0x80,0xff,0xff,0xff,0xff,0xff,0x01,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,0xff,0xff,0x3f,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xfe,0xff,0xff,0xff,0xff,0x01,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0x80,0xff,0xff,0xff,0xff,0x1f,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xf8,0xff,0xff,0xff,0xff,0x03,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xc0,0xff,0xff,0xff,0xff,0x07,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xf0,0xff,0xff,0xff,0xff,0x03,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xc0,0xff,0xff,0xff,0xff,0x07,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xf0,0xff,0xff,0xff,0xff,0x03,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xc0,0xff,0xff,0xff,0xff,0x01,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0,
+0xff,0xff,0xff,0xff,0x07,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0,
+0xff,0xff,0xff,0xff,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,
+0xff,0xff,0x07,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0xff,
+0xff,0x1f,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xff,0xff,0xff,0xff,
+0x07,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0x0f,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0xff,0x0f,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0x0f,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xfc,0xff,0xff,0xff,0x0f,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xf0,0xff,0xff,0xff,0x03,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xf8,0xff,0xff,0xff,0x0f,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xf0,0xff,0xff,0xff,0x01,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xe0,0xff,0xff,0xff,0x0f,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xf8,0xff,0xff,0x7f,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xc0,0xff,0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xf8,0xff,0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xff,0xff,0xff,0x1f,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xf8,0xff,
+0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xff,0xff,
+0xff,0x1f,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xf8,0xff,0xff,0x07,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0x3f,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0x03,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0xf8,0xff,0xff,0x3f,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xfe,0xff,0xff,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0xe0,0xff,0xff,0x3f,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0xfe,0xff,0x3f,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0x80,0xff,0xff,0x3f,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xfe,0xff,0x3f,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0x80,0xff,0xff,0x3f,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xfe,0xff,0x0f,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xfe,0xff,0x7f,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xff,
+0xff,0x07,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xfc,0xff,0x7f,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xff,0xff,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff,
+0x7f,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0x80,0xff,0x3f,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0x7f,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0x80,0xff,0x1f,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0x80,0xff,0x1f,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0x80,0xff,0xff,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0xc0,0xff,0x03,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xfe,0xff,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0xc0,0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xfc,0xff,0x01,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0,
+0x7f,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xf0,0xff,0x01,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0xe0,0x1f,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0xc0,0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xe0,0x1f,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0,0xff,
+0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xe0,0x0f,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0x80,0xff,0x01,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xf0,0x03,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0xfe,0x03,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0x78,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0xf8,0x03,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0x18,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0xf0,0x03,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0x18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0xf0,0x03,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0xc0,0x07,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0x07,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+};
diff --git a/hacks/flame.c b/hacks/flame.c
new file mode 100644 (file)
index 0000000..3f98e3e
--- /dev/null
@@ -0,0 +1,297 @@
+/* xscreensaver, Copyright (c) 1993, 1995 Jamie Zawinski <jwz@netscape.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.
+ */
+
+/* This file was ported from xlock for use in xscreensaver (and standalone)
+ * by jwz on 18-Oct-93.  Original copyright reads:
+ *
+ *   static char sccsid[] = "@(#)flame.c 1.4 91/09/27 XLOCK";
+ *
+ * flame.c - recursive fractal cosmic flames.
+ *
+ * Copyright (c) 1991 by Patrick J. Naughton.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * Comments and additions should be sent to the author:
+ *
+ *                    naughton@eng.sun.com
+ *
+ *                    Patrick J. Naughton
+ *                    MS 21-14
+ *                    Sun Laboritories, Inc.
+ *                    2550 Garcia Ave
+ *                    Mountain View, CA  94043
+ *
+ * Revision History:
+ * 27-Jun-91: vary number of functions used.
+ * 24-Jun-91: fixed portability problem with integer mod (%).
+ * 06-Jun-91: Written. (received from Scott Graves, spot@cs.cmu.edu).
+ */
+
+#include "screenhack.h"
+
+#define POINT_BUFFER_SIZE 10
+#define MAXLEV 4
+
+static double f[2][3][MAXLEV]; /* three non-homogeneous transforms */
+static int max_total;
+static int max_levels;
+static int max_points;
+static int cur_level;
+static int snum;
+static int anum;
+static int num_points;
+static int total_points;
+static int pixcol;
+static int npixels;
+static unsigned long *pixels;
+static XPoint points [POINT_BUFFER_SIZE];
+static GC gc;
+
+static int delay, delay2;
+static int width, height;
+
+static short
+halfrandom (mv)
+     int mv;
+{
+  static short lasthalf = 0;
+  unsigned long r;
+
+  if (lasthalf)
+    {
+      r = lasthalf;
+      lasthalf = 0;
+    }
+  else
+    {
+      r = random ();
+      lasthalf = r >> 16;
+    }
+  return (r % mv);
+}
+
+
+static void
+init_flame (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  XGCValues gcv;
+  XWindowAttributes xgwa;
+  Colormap cmap;
+  XGetWindowAttributes (dpy, window, &xgwa);
+  width = xgwa.width;
+  height = xgwa.height;
+  cmap = xgwa.colormap;
+
+  max_points = get_integer_resource ("iterations", "Integer");
+  if (max_points <= 0) max_points = 100;
+
+  max_levels = max_points;
+
+  max_total = get_integer_resource ("points", "Integer");
+  if (max_total <= 0) max_total = 10000;
+
+  delay = get_integer_resource ("delay", "Integer");
+  if (delay < 0) delay = 0;
+  delay2 = get_integer_resource ("delay2", "Integer");
+  if (delay2 < 0) delay2 = 0;
+
+  if (mono_p)
+    npixels = 0;
+  else
+    {
+      int i = get_integer_resource ("ncolors", "Integer");
+      double saturation = 1.0;
+      double value = 1.0;
+      XColor color;
+      if (i <= 0) i = 128;
+
+      pixels = (unsigned long *) malloc ((i+1) * sizeof (*pixels));
+      for (npixels = 0; npixels < i; npixels++)
+       {
+         hsv_to_rgb ((360*npixels)/i, saturation, value,
+                     &color.red, &color.green, &color.blue);
+         if (! XAllocColor (dpy, cmap, &color))
+           break;
+         pixels [npixels] = color.pixel;
+       }
+    }
+
+  gcv.foreground = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+  gcv.background = get_pixel_resource ("background", "Background", dpy, cmap);
+
+  if (! mono_p)
+    {
+      pixcol = halfrandom (npixels);
+      gcv.foreground = (pixels [pixcol]);
+    }
+
+  gc = XCreateGC (dpy, window, GCForeground | GCBackground, &gcv);
+}
+
+static int
+recurse (x, y, l, dpy, win)
+     register double x, y;
+     register int l;
+     Display *dpy;
+     Window win;
+{
+  int xp, yp, i;
+  double nx, ny;
+
+  if (l == max_levels)
+    {
+      total_points++;
+      if (total_points > max_total) /* how long each fractal runs */
+       return 0;
+
+      if (x > -1.0 && x < 1.0 && y > -1.0 && y < 1.0)
+       {
+         xp = points[num_points].x = (int) ((width / 2) * (x + 1.0));
+         yp = points[num_points].y = (int) ((height / 2) * (y + 1.0));
+         num_points++;
+         if (num_points >= POINT_BUFFER_SIZE)
+           {
+             XDrawPoints (dpy, win, gc, points, num_points, CoordModeOrigin);
+             num_points = 0;
+             /* if (delay) usleep (delay); */
+             /* XSync (dpy, True); */
+           }
+       }
+    }
+  else
+    {
+      for (i = 0; i < snum; i++)
+       {
+         nx = f[0][0][i] * x + f[0][1][i] * y + f[0][2][i];
+         ny = f[1][0][i] * x + f[1][1][i] * y + f[1][2][i];
+         if (i < anum)
+           {
+             nx = sin(nx);
+             ny = sin(ny);
+           }
+         if (!recurse (nx, ny, l + 1, dpy, win))
+           return 0;
+       }
+    }
+  return 1;
+}
+
+
+static void
+flame (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  int i, j, k;
+  static int alt = 0;
+
+  if (!(cur_level++ % max_levels))
+    {
+      if (delay2) usleep (delay2);
+      XClearWindow (dpy, window);
+      alt = !alt;
+    }
+  else
+    {
+      if (npixels > 2)
+       {
+         XSetForeground (dpy, gc, pixels [pixcol]);
+         if (--pixcol < 0)
+           pixcol = npixels - 1;
+       }
+    }
+
+  /* number of functions */
+  snum = 2 + (cur_level % (MAXLEV - 1));
+
+  /* how many of them are of alternate form */
+  if (alt)
+    anum = 0;
+  else
+    anum = halfrandom (snum) + 2;
+
+  /* 6 coefs per function */
+  for (k = 0; k < snum; k++)
+    {
+      for (i = 0; i < 2; i++)
+       for (j = 0; j < 3; j++)
+         f[i][j][k] = ((double) (random() & 1023) / 512.0 - 1.0);
+    }
+  num_points = 0;
+  total_points = 0;
+  (void) recurse (0.0, 0.0, 0, dpy, window);
+  XDrawPoints (dpy, window, gc, points, num_points, CoordModeOrigin);
+  XSync (dpy, True);
+  if (delay) usleep (delay);
+}
+
+
+#ifdef __hpux
+/* I don't understand why this is necessary, but I'm told that this program
+   does nothing at all on HP-sUX without it.
+ */
+#undef random
+#undef srandom
+#include <math.h>
+int matherr(x)
+   register struct exception *x;
+{
+  if (x->type == PLOSS) return 1;
+  else return 0;
+}
+#endif /* __hpux */
+
+
+\f
+char *progclass = "Flame";
+
+char *defaults [] = {
+  "Flame.background:   black",         /* to placate SGI */
+  "Flame.foreground:   white",
+  "*colors:    128",
+  "*iterations:        25",
+  "*delay:     50000",
+  "*delay2:    2000000",
+  "*points:    10000",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-ncolors",                ".colors",      XrmoptionSepArg, 0 },
+  { "-iterations",     ".iterations",  XrmoptionSepArg, 0 },
+  { "-delay",          ".delay",       XrmoptionSepArg, 0 },
+  { "-delay2",         ".delay2",      XrmoptionSepArg, 0 },
+  { "-points",         ".points",      XrmoptionSepArg, 0 }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  init_flame (dpy, window);
+  while (1)
+    flame (dpy, window);
+}
diff --git a/hacks/flame.man b/hacks/flame.man
new file mode 100644 (file)
index 0000000..e532681
--- /dev/null
@@ -0,0 +1,72 @@
+.TH XScreenSaver 1 "13-aug-92" "X Version 11"
+.SH NAME
+flame - draw weird cosmic fractals
+.SH SYNOPSIS
+.B flame
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-iterations \fIinteger\fP] [\-points \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-delay2 \fImicroseconds\fP]
+.SH DESCRIPTION
+The \fIflame\fP program generates colorful fractal displays.
+.SH OPTIONS
+.I flame
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono 
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-ncolors \fIinteger\fP
+How many colors should be used (if possible).  Default 128.
+The colors used cycle through the hue, making N stops around 
+the color wheel.
+.TP 8
+.B \-iterations \fIinteger\fP
+How many fractals to generate.  Default 25.
+.TP 8
+.B \-points \fIinteger\fP
+How many pixels to draw for each fractal.  Default 10000.
+.TP 8
+.B \-delay \fImicroseconds\fP
+How long we should wait between drawing each fractal.  Default 50000,
+or about 1/20th second.
+.TP 8
+.B \-delay2 \fImicroseconds\fP
+How long we should wait before clearing the screen when each run ends.
+Default 2000000, or two seconds.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR xlock (1)
+.SH COPYRIGHT
+Copyright \(co 1991 by Patrick J. Naughton
+
+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. 
+.SH AUTHOR
+Scott Graves <spot@cs.cmu.edu>, 06-Jun-91.n
+
+Ability to run standalone or with \fIxscreensaver\fP added by 
+Jamie Zawinski <jwz@netscape.com>, 18-Oct-93.
diff --git a/hacks/greynetic.c b/hacks/greynetic.c
new file mode 100644 (file)
index 0000000..4dd3f17
--- /dev/null
@@ -0,0 +1,166 @@
+/* xscreensaver, Copyright (c) 1992, 1995 Jamie Zawinski <jwz@netscape.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.
+ */
+
+#include "screenhack.h"
+
+#define NBITS 12
+
+#include <X11/bitmaps/stipple>
+#include <X11/bitmaps/cross_weave>
+#include <X11/bitmaps/dimple1>
+#include <X11/bitmaps/dimple3>
+#include <X11/bitmaps/flipped_gray>
+#include <X11/bitmaps/gray1>
+#include <X11/bitmaps/gray3>
+#include <X11/bitmaps/hlines2>
+#include <X11/bitmaps/light_gray>
+#include <X11/bitmaps/root_weave>
+#include <X11/bitmaps/vlines2>
+#include <X11/bitmaps/vlines3>
+
+static Pixmap pixmaps [NBITS];
+static GC gc;
+static int delay;
+static unsigned long fg, bg, pixels [512];
+static int npixels;
+
+static void
+init_greynetic (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  int i;
+  XGCValues gcv;
+  XWindowAttributes xgwa;
+  Colormap cmap;
+  XGetWindowAttributes (dpy, window, &xgwa);
+  cmap = xgwa.colormap;
+  npixels = 0;
+  gcv.foreground= fg= get_pixel_resource("foreground","Foreground", dpy, cmap);
+  gcv.background= bg= get_pixel_resource("background","Background", dpy, cmap);
+  gcv.fill_style= FillOpaqueStippled;
+  gc = XCreateGC (dpy, window, GCForeground|GCBackground|GCFillStyle, &gcv);
+
+  delay = get_integer_resource ("delay", "Integer");
+  if (delay < 0) delay = 0;
+
+  i = 0;
+#define BITS(n,w,h) \
+  pixmaps [i++] = XCreatePixmapFromBitmapData (dpy, window, n, w, h, 1, 0, 1)
+
+  BITS (stipple_bits, stipple_width, stipple_height);
+  BITS (cross_weave_bits, cross_weave_width, cross_weave_height);
+  BITS (dimple1_bits, dimple1_width, dimple1_height);
+  BITS (dimple3_bits, dimple3_width, dimple3_height);
+  BITS (flipped_gray_bits, flipped_gray_width, flipped_gray_height);
+  BITS (gray1_bits, gray1_width, gray1_height);
+  BITS (gray3_bits, gray3_width, gray3_height);
+  BITS (hlines2_bits, hlines2_width, hlines2_height);
+  BITS (light_gray_bits, light_gray_width, light_gray_height);
+  BITS (root_weave_bits, root_weave_width, root_weave_height);
+  BITS (vlines2_bits, vlines2_width, vlines2_height);
+  BITS (vlines3_bits, vlines3_width, vlines3_height);
+}
+
+static void
+greynetic (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  static int tick = 500, xlim, ylim;
+  static Colormap cmap;
+  int x, y, w, h, i;
+  XGCValues gcv;
+  if (tick++ == 500)
+    {
+      XWindowAttributes xgwa;
+      XGetWindowAttributes (dpy, window, &xgwa);
+      tick = 0;
+      xlim = xgwa.width;
+      ylim = xgwa.height;
+      cmap = xgwa.colormap;
+    }
+  for (i = 0; i < 10; i++) /* minimize area, but don't try too hard */
+    {
+      w = 50 + random () % (xlim - 50);
+      h = 50 + random () % (ylim - 50);
+      if (w + h < xlim && w + h < ylim)
+       break;
+    }
+  x = random () % (xlim - w);
+  y = random () % (ylim - h);
+  gcv.stipple = pixmaps [random () % NBITS];
+  if (mono_p)
+    {
+      if (random () & 1)
+       gcv.foreground = fg, gcv.background = bg;
+      else
+       gcv.foreground = bg, gcv.background = fg;
+    }
+  else
+    {
+      XColor fgc, bgc;
+      if (npixels == sizeof (pixels) / sizeof (unsigned long))
+       goto REUSE;
+      fgc.flags = bgc.flags = DoRed|DoGreen|DoBlue;
+      fgc.red = random ();
+      fgc.green = random ();
+      fgc.blue = random ();
+      bgc.red = random ();
+      bgc.green = random ();
+      bgc.blue = random ();
+      if (! XAllocColor (dpy, cmap, &fgc))
+       goto REUSE;
+      pixels [npixels++] = fgc.pixel;
+      gcv.foreground = fgc.pixel;
+      if (! XAllocColor (dpy, cmap, &bgc))
+       goto REUSE;
+      pixels [npixels++] = bgc.pixel;
+      gcv.background = bgc.pixel;
+      goto DONE;
+    REUSE:
+      gcv.foreground = pixels [random () % npixels];
+      gcv.background = pixels [random () % npixels];
+    DONE:
+      ;
+    }
+  XChangeGC (dpy, gc, GCStipple|GCForeground|GCBackground, &gcv);
+  XFillRectangle (dpy, window, gc, x, y, w, h);
+  XSync (dpy, True);
+}
+
+\f
+char *progclass = "Greynetic";
+
+char *defaults [] = {
+  "Greynetic.background:       black",         /* to placate SGI */
+  "Greynetic.foreground:       white",
+  "*delay:     0",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-delay",          ".delay",       XrmoptionSepArg, 0 }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  init_greynetic (dpy, window);
+  while (1)
+    {
+      greynetic (dpy, window);
+      if (delay) usleep (delay);
+    }
+}
diff --git a/hacks/greynetic.man b/hacks/greynetic.man
new file mode 100644 (file)
index 0000000..8638112
--- /dev/null
@@ -0,0 +1,52 @@
+.TH XScreenSaver 1 "13-aug-92" "X Version 11"
+.SH NAME
+greynetic - draw random stippled/color rectangles
+.SH SYNOPSIS
+.B greynetic
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-delay \fIusecs\fP]
+.SH DESCRIPTION
+The \fIgreynetic\fP program draws random rectangles.
+.SH OPTIONS
+.I greynetic
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono 
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-delay \fImicroseconds\fP
+Slow it down.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1992 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@netscape.com>, 13-aug-92.
diff --git a/hacks/halo.c b/hacks/halo.c
new file mode 100644 (file)
index 0000000..d61e2ac
--- /dev/null
@@ -0,0 +1,379 @@
+/* xscreensaver, Copyright (c) 1993, 1995 Jamie Zawinski <jwz@netscape.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.
+ */
+
+/* I wanted to lay down new circles with TV:ALU-ADD instead of TV:ALU-XOR,
+   but X doesn't support arithmetic combinations of pixmaps!!  What losers.
+   I suppose I could crank out the 2's compliment math by hand, but that's
+   a real drag...
+
+   This would probably look good with shapes other than circles as well.
+
+ */
+
+#include "screenhack.h"
+#include <stdio.h>
+
+struct circle {
+  int x, y, radius;
+  int increment;
+  int dx, dy;
+};
+
+static enum color_mode {
+  seuss_mode, ramp_mode, random_mode
+} cmode;
+
+
+static struct circle *circles;
+static int count, global_count;
+static Pixmap pixmap, buffer;
+static int width, height, global_inc;
+static int delay;
+static unsigned long fg_pixel, bg_pixel;
+static XColor fgc, bgc;
+static GC draw_gc, erase_gc, copy_gc, merge_gc;
+static Bool anim_p;
+static Colormap cmap;
+
+#define min(x,y) ((x)<(y)?(x):(y))
+#define max(x,y) ((x)>(y)?(x):(y))
+
+static void
+init_circles_1 (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  int i;
+  count = (global_count ? global_count
+          : (3 + (random () % max (1, (min (width, height) / 50)))
+               + (random () % max (1, (min (width, height) / 50)))));
+  circles = (struct circle *) malloc (count * sizeof (struct circle));
+  for (i = 0; i < count; i++)
+    {
+      circles [i].x = 10 + random () % (width - 20);
+      circles [i].y = 10 + random () % (height - 20);
+      if (global_inc)
+      circles [i].increment = global_inc;
+      else
+       { /* prefer smaller increments to larger ones */
+         int j = 8;
+         int inc = ((random()%j) + (random()%j) + (random()%j)) - ((j*3)/2);
+         if (inc < 0) inc = -inc + 3;
+         circles [i].increment = inc + 3;
+       }
+      circles [i].radius = random () % circles [i].increment;
+      circles [i].dx = ((random () % 3) - 1) * (1 + random () % 5);
+      circles [i].dy = ((random () % 3) - 1) * (1 + random () % 5);
+    }
+}
+
+static void
+init_circles (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  XGCValues gcv;
+  XWindowAttributes xgwa;
+  char *mode_str = 0;
+  XGetWindowAttributes (dpy, window, &xgwa);
+  cmap = xgwa.colormap;
+  global_count = get_integer_resource ("count", "Integer");
+  if (global_count < 0) global_count = 0;
+  global_inc = get_integer_resource ("increment", "Integer");
+  if (global_inc < 0) global_inc = 0;
+  anim_p = get_boolean_resource ("animate", "Boolean");
+  delay = get_integer_resource ("delay", "Integer");
+  mode_str = get_string_resource ("colorMode", "ColorMode");
+  if (! mode_str) cmode = random_mode;
+  else if (!strcmp (mode_str, "seuss"))  cmode = seuss_mode;
+  else if (!strcmp (mode_str, "ramp"))   cmode = ramp_mode;
+  else if (!strcmp (mode_str, "random")) cmode = random_mode;
+  else {
+    fprintf (stderr,
+            "%s: colorMode must be seuss, ramp, or random, not \"%s\"\n",
+            progname, mode_str);
+    exit (1);
+  }
+
+  if (mono_p) cmode = seuss_mode;
+  if (cmode == random_mode)
+    cmode = ((random()&3) == 1) ? ramp_mode : seuss_mode;
+
+  if (cmode == ramp_mode)
+    anim_p = False;    /* This combo doesn't work right... */
+
+  if (mono_p)
+    {
+      fg_pixel = get_pixel_resource ("foreground","Foreground", dpy, cmap);
+      bg_pixel = get_pixel_resource ("background","Background", dpy, cmap);
+    }
+  else
+    {
+      int r  = random() % 360;
+      int r2 = (random() % 180) + 45;
+      double fs, bs;
+      if (cmode == seuss_mode)
+       fs = 0.5, bs = 1.0;
+      else
+       fs = 1.0, bs = 0.1;
+      hsv_to_rgb (r,          fs, 1.0, &fgc.red, &fgc.green, &fgc.blue);
+      hsv_to_rgb ((r+r2)%360, bs, 0.7, &bgc.red, &bgc.green, &bgc.blue);
+      XAllocColor (dpy, cmap, &fgc);
+      XAllocColor (dpy, cmap, &bgc);
+      fg_pixel = fgc.pixel;
+      bg_pixel = bgc.pixel;
+    }
+
+  width = max (50, xgwa.width);
+  height = max (50, xgwa.height);
+
+#ifdef DEBUG
+  width/=2; height/=2;
+#endif
+
+  pixmap = XCreatePixmap (dpy, window, width, height, 1);
+  if (cmode == seuss_mode)
+    buffer = XCreatePixmap (dpy, window, width, height, 1);
+  else
+    buffer = 0;
+
+  gcv.foreground = 1;
+  gcv.background = 0;
+  draw_gc = XCreateGC (dpy, pixmap, GCForeground | GCBackground, &gcv);
+  gcv.foreground = 0;
+  erase_gc = XCreateGC (dpy, pixmap, GCForeground, &gcv);
+  gcv.foreground = fg_pixel;
+  gcv.background = bg_pixel;
+  copy_gc = XCreateGC (dpy, window, GCForeground | GCBackground, &gcv);
+
+  if (cmode == seuss_mode)
+    {
+      gcv.foreground = 1;
+      gcv.background = 0;
+      gcv.function = GXxor;
+      merge_gc = XCreateGC (dpy, pixmap,
+                           GCForeground | GCBackground | GCFunction, &gcv);
+    }
+  else
+    {
+      gcv.foreground = fg_pixel;
+      gcv.background = bg_pixel;
+      gcv.function = GXcopy;
+      merge_gc = XCreateGC (dpy, window,
+                           GCForeground | GCBackground | GCFunction, &gcv);
+    }
+
+  init_circles_1 (dpy, window);
+  XClearWindow (dpy, window);
+  if (buffer) XFillRectangle (dpy, buffer, erase_gc, 0, 0, width, height);
+}
+
+static void
+run_circles (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  int i;
+  static int iterations = 0;
+  static int oiterations = 0;
+  static Bool first_time_p = True;
+  Bool done = False;
+  Bool inhibit_sleep = False;
+  XFillRectangle (dpy, pixmap, erase_gc, 0, 0, width, height);
+  for (i = 0; i < count; i++)
+    {
+      int radius = circles [i].radius;
+      int inc = circles [i].increment;
+      if (! (iterations & 1))
+       ;
+      else if (radius == 0)
+       ;
+      else if (radius < 0)
+       done = True;
+      else
+       {
+         /* Probably there's a simpler way to ask the musical question,
+            "is this square completely enclosed by this circle," but I've
+            forgotten too much trig to know it...  (That's not really the
+            right question anyway, but the right question is too hard.) */
+         double x1 = ((double) (-circles [i].x)) / ((double) radius);
+         double y1 = ((double) (-circles [i].y)) / ((double) radius);
+         double x2 = ((double) (width - circles [i].x)) / ((double) radius);
+         double y2 = ((double) (height - circles [i].y)) / ((double) radius);
+         x1 *= x1; x2 *= x2; y1 *= y1; y2 *= y2;
+         if ((x1 + y1) < 1 && (x2 + y2) < 1 && (x1 + y2) < 1 && (x2 + y1) < 1)
+           done = True;
+       }
+      if (radius > 0 &&
+         (cmode == seuss_mode || circles [0].increment < 0))
+       XFillArc (dpy,
+                 (cmode == seuss_mode ? pixmap : window),
+                 (cmode == seuss_mode ? draw_gc : merge_gc),
+                 circles [i].x - radius, circles [i].y - radius,
+                 radius * 2, radius * 2, 0, 360*64);
+      circles [i].radius += inc;
+    }
+
+  if (anim_p && !first_time_p)
+    inhibit_sleep = !done;
+
+  if (done)
+    {
+      if (anim_p)
+       {
+         first_time_p = False;
+         for (i = 0; i < count; i++)
+           {
+             circles [i].x += circles [i].dx;
+             circles [i].y += circles [i].dy;
+             circles [i].radius %= circles [i].increment;
+             if (circles [i].x < 0 || circles [i].x >= width)
+               {
+                 circles [i].dx = -circles [i].dx;
+                 circles [i].x += (2 * circles [i].dx);
+               }
+             if (circles [i].y < 0 || circles [i].y >= height)
+               {
+                 circles [i].dy = -circles [i].dy;
+                 circles [i].y += (2 * circles [i].dy);
+               }
+           }
+       }
+      else if (circles [0].increment < 0)
+       {
+         free (circles);
+         init_circles_1 (dpy, window);
+         if (! mono_p)
+           {
+             XColor d1, d2;
+             cycle_hue (&fgc, 10);
+             cycle_hue (&bgc, 10);
+             XFreeColors (dpy, cmap, &fgc.pixel, 1, 0);
+             XFreeColors (dpy, cmap, &bgc.pixel, 1, 0);
+             d1 = fgc;
+             d2 = bgc;
+             XAllocColor (dpy, cmap, &fgc);
+             XAllocColor (dpy, cmap, &bgc);
+             fgc.red = d1.red; fgc.green = d1.green; fgc.blue = d1.blue;
+             bgc.red = d2.red; bgc.green = d2.green; bgc.blue = d2.blue;
+             XSetForeground (dpy, copy_gc, fgc.pixel);
+             XSetBackground (dpy, copy_gc, bgc.pixel);
+           }
+       }
+#if 0
+      else if ((random () % 2) == 0)
+       {
+         iterations = 0; /* ick */
+         for (i = 0; i < count; i++)
+           circles [i].radius %= circles [i].increment;
+       }
+#endif
+      else
+       {
+         oiterations = iterations;
+         for (i = 0; i < count; i++)
+           {
+             circles [i].increment = -circles [i].increment;
+             circles [i].radius += (2 * circles [i].increment);
+           }
+       }
+    }
+
+  if (buffer)
+    XCopyPlane (dpy, pixmap, buffer, merge_gc, 0, 0, width, height, 0, 0, 1);
+  else if (cmode != seuss_mode)
+    {
+      static int ncolors = 0;
+      static XColor *colors = 0;
+      if (circles [0].increment >= 0)
+       inhibit_sleep = True;
+      else if (done)
+       {
+         int fgh, bgh;
+         double fgs, fgv, bgs, bgv;
+         if (colors)
+           for (i = 0; i < ncolors; i++)
+             XFreeColors (dpy, cmap, &colors [i].pixel, 1, 0);
+
+         rgb_to_hsv (fgc.red, fgc.green, fgc.blue, &fgh, &fgs, &fgv);
+         rgb_to_hsv (bgc.red, bgc.green, bgc.blue, &bgh, &bgs, &bgv);
+         ncolors = oiterations;
+         colors = ((XColor *)
+                   (colors
+                    ? realloc (colors, sizeof (XColor) * ncolors)
+                    : malloc (sizeof (XColor) * ncolors)));
+         
+         make_color_ramp (bgh, bgs, bgv, fgh, fgs, fgv, colors, ncolors);
+         for (i = 0; i < ncolors; i++)
+           XAllocColor (dpy, cmap, &colors [i]);
+         XSetForeground (dpy, merge_gc, colors [0].pixel);
+       }
+      else
+       {
+         XSetForeground (dpy, merge_gc, colors [iterations].pixel);
+       }
+    }
+  else
+    XCopyPlane (dpy, pixmap, window, merge_gc, 0, 0, width, height, 0, 0, 1);
+
+  if (buffer && (anim_p
+                ? (done || (first_time_p && (iterations & 1)))
+                : (iterations & 1)))
+    {
+      XCopyPlane (dpy, buffer, window, copy_gc, 0, 0, width, height, 0, 0, 1);
+      XSync (dpy, True);
+      if (anim_p && done)
+       XFillRectangle (dpy, buffer, erase_gc, 0, 0, width, height);
+    }
+#ifdef DEBUG
+  XCopyPlane (dpy, pixmap, window, copy_gc, 0,0,width,height,width,height, 1);
+  if (buffer)
+    XCopyPlane (dpy, buffer, window, copy_gc, 0,0,width,height,0,height, 1);
+  XSync (dpy, True);
+#endif
+
+  if (done)
+    iterations = 0;
+  else
+    iterations++;
+
+  if (delay && !inhibit_sleep) usleep (delay);
+}
+
+\f
+char *progclass = "Halo";
+
+char *defaults [] = {
+  "Halo.background:    black",         /* to placate SGI */
+  "Halo.foreground:    white",
+  "*colorMode:         random",
+  "*count:             0",
+  "*delay:             100000",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-count",          ".count",       XrmoptionSepArg, 0 },
+  { "-delay",          ".delay",       XrmoptionSepArg, 0 },
+  { "-animate",                ".animate",     XrmoptionNoArg, "True" },
+  { "-mode",           ".colorMode",   XrmoptionSepArg, 0 }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  init_circles (dpy, window);
+  while (1)
+    run_circles (dpy, window);
+}
diff --git a/hacks/halo.man b/hacks/halo.man
new file mode 100644 (file)
index 0000000..5239ab5
--- /dev/null
@@ -0,0 +1,68 @@
+.TH XScreenSaver 1 "7-jul-93" "X Version 11"
+.SH NAME
+halo - draw circular patterns
+.SH SYNOPSIS
+.B halo
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-count \fIint\fP] [\-delay \fIusecs\fP] [\-mode seuss | ramp | random ] [\-animate]
+.SH DESCRIPTION
+The \fIhalo\fP program draws cool patterns based on circles.
+.SH OPTIONS
+.I halo
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono 
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-count \fIinteger\fP
+How many circles to draw.  Default 0, meaning random.
+.TP 8
+.B \-mode "seuss | ramp | random"
+In \fIseuss\fP mode, alternating striped curves will be drawn.
+
+In \fIramp\fP mode, a color ramp will be drawn.
+
+\fIrandom\fP means pick the mode randomly.
+.TP 8
+.B \-delay \fImicroseconds\fP
+How much of a delay should be introduced between steps of the animation.
+Default 100000, or about 0.1 second.
+.TP 8
+.B \-animate
+If specified, then the centerpoints of the circles will bounce around.
+Otherwise, the circles will be drawn once, erased, and a new set of
+circles will be drawn.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1993 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@netscape.com>, 6-jul-93.
diff --git a/hacks/helix.c b/hacks/helix.c
new file mode 100644 (file)
index 0000000..84c4fd8
--- /dev/null
@@ -0,0 +1,208 @@
+/* xscreensaver, Copyright (c) 1992, 1995 Jamie Zawinski <jwz@netscape.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.
+ */
+
+#include <math.h>
+#include "screenhack.h"
+
+static double sins [360];
+static double coss [360];
+
+static GC draw_gc, erase_gc;
+static unsigned int default_fg_pixel;
+
+static void
+init_helix (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  int i;
+  XGCValues gcv;
+  XWindowAttributes xgwa;
+  Colormap cmap;
+  XGetWindowAttributes (dpy, window, &xgwa);
+  cmap = xgwa.colormap;
+  gcv.foreground = default_fg_pixel =
+    get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+  draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+  gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
+  erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+
+  for (i = 0; i < 360; i++)
+    {
+      sins [i] = sin ((((double) i) / 180.0) * M_PI);
+      coss [i] = cos ((((double) i) / 180.0) * M_PI);
+    }
+}
+
+static int
+gcd (a, b)
+     int a, b;
+{
+  while (b > 0)
+    {
+      int tmp;
+      tmp = a % b;
+      a = b;
+      b = tmp;
+    }
+  return (a < 0 ? -a : a);
+}
+
+static void
+helix (dpy, window,
+       radius1, radius2, d_angle,
+       factor1, factor2, factor3, factor4)
+     Display *dpy;
+     Window window;
+     int radius1, radius2, d_angle;
+     int factor1, factor2, factor3, factor4;
+{
+  XWindowAttributes xgwa;
+  int width, height;
+  int xmid, ymid;
+  int x1, y1, x2, y2, angle, limit;
+  int i;
+
+  XClearWindow (dpy, window);
+  XGetWindowAttributes (dpy, window, &xgwa);
+  width = xgwa.width;
+  height = xgwa.height;
+
+  xmid = width / 2;
+  ymid = height / 2;
+  x1 = xmid;
+  y1 = ymid + radius2;
+  x2 = xmid;
+  y2 = ymid + radius1;
+  angle = 0;
+  limit = 1 + (360 / gcd (360, d_angle));
+  
+  for (i = 0; i < limit; i++)
+    {
+      int tmp;
+#define pmod(x,y) (tmp = (x % y), (tmp >= 0 ? tmp : tmp + y))
+      x1 = xmid + (((double) radius1) * sins [pmod ((angle * factor1), 360)]);
+      y1 = ymid + (((double) radius2) * coss [pmod ((angle * factor2), 360)]);
+      XDrawLine (dpy, window, draw_gc, x1, y1, x2, y2);
+      x2 = xmid + (((double) radius2) * sins [pmod ((angle * factor3), 360)]);
+      y2 = ymid + (((double) radius1) * coss [pmod ((angle * factor4), 360)]);
+      XDrawLine (dpy, window, draw_gc, x1, y1, x2, y2);
+      angle += d_angle;
+      XFlush (dpy);
+    }
+}
+
+#define min(a,b) ((a)<(b)?(a):(b))
+
+static void
+random_helix (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  Colormap cmap;
+  int width, height;
+  int radius, radius1, radius2, d_angle, factor1, factor2, factor3, factor4;
+  double divisor;
+  XColor color;
+  int i, got_color = 0;
+  XWindowAttributes xgwa;
+  XGetWindowAttributes (dpy, window, &xgwa);
+  width = xgwa.width;
+  height = xgwa.height;
+  cmap = xgwa.colormap;
+
+  radius = min (width, height) / 2;
+
+  d_angle = 0;
+  factor1 = 2;
+  factor2 = 2;
+  factor3 = 2;
+  factor4 = 2;
+
+  divisor = ((frand (3.0) + 1) * (((random() & 1) * 2) - 1));
+
+  if ((random () & 1) == 0)
+    {
+      radius1 = radius;
+      radius2 = radius / divisor;
+    }
+  else
+    {
+      radius2 = radius;
+      radius1 = radius / divisor;
+    }
+
+  while (gcd (360, d_angle) >= 2)
+    d_angle = random () % 360;
+
+#define random_factor()                                \
+  (((random() % 7) ? ((random() & 1) + 1) : 3) \
+   * (((random() & 1) * 2) - 1))
+
+  while (gcd (gcd (gcd (factor1, factor2), factor3), factor4) != 1)
+    {
+      factor1 = random_factor ();
+      factor2 = random_factor ();
+      factor3 = random_factor ();
+      factor4 = random_factor ();
+    }
+
+  if (mono_p)
+    XSetForeground (dpy, draw_gc, default_fg_pixel);
+  else
+    {
+      hsv_to_rgb (random () % 360, frand (1.0), frand (0.5) + 0.5,
+                 &color.red, &color.green, &color.blue);
+      if ((got_color = XAllocColor (dpy, cmap, &color)))
+       XSetForeground (dpy, draw_gc, color.pixel);
+      else
+       XSetForeground (dpy, draw_gc, default_fg_pixel);
+    }
+  helix (dpy, window, radius1, radius2, d_angle,
+        factor1, factor2, factor3, factor4);
+
+  XSync (dpy, True);
+  sleep (5);
+
+  for (i = 0; i < height; i++)
+    {
+      int y = (random () % height);
+      XDrawLine (dpy, window, erase_gc, 0, y, width, y);
+      XFlush (dpy);
+      if ((i % 50) == 0)
+       usleep (10000);
+    }
+  XClearWindow (dpy, window);
+  if (got_color) XFreeColors (dpy, cmap, &color.pixel, 1, 0);
+  XSync (dpy, True);
+  sleep (1);
+}
+
+\f
+char *progclass = "Helix";
+
+char *defaults [] = {
+  "Helix.background: black",           /* to placate SGI */
+  0
+};
+
+XrmOptionDescRec options [] = { { 0, } };
+int options_size = 0;
+
+void
+screenhack (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  init_helix (dpy, window);
+  while (1)
+    random_helix (dpy, window);
+}
diff --git a/hacks/helix.man b/hacks/helix.man
new file mode 100644 (file)
index 0000000..76c7cfe
--- /dev/null
@@ -0,0 +1,50 @@
+.TH XScreenSaver 1 "13-aug-92" "X Version 11"
+.SH NAME
+helix - draw helical string-art patterns
+.SH SYNOPSIS
+.B helix
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP]
+.SH DESCRIPTION
+The \fIhelix\fP program draws interesting patterns composed of line segments
+in random colors.
+.SH OPTIONS
+.I helix
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono 
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1992 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@netscape.com>, 13-aug-92.
diff --git a/hacks/hopalong.c b/hacks/hopalong.c
new file mode 100644 (file)
index 0000000..2a91ece
--- /dev/null
@@ -0,0 +1,236 @@
+/* xscreensaver, Copyright (c) 1992, 1995 Jamie Zawinski <jwz@netscape.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.
+ */
+
+/* This file was ported from xlock for use in xscreensaver (and standalone)
+ * by jwz on 12-Aug-92.  Original copyright reads:
+ *
+ * hopalong.c - Real Plane Fractals for xlock, the X Window System lockscreen.
+ *
+ * Copyright (c) 1991 by Patrick J. Naughton.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * Comments and additions should be sent to the author:
+ *
+ *                    naughton@eng.sun.com
+ *
+ *                    Patrick J. Naughton
+ *                    MS 21-14
+ *                    Sun Laboritories, Inc.
+ *                    2550 Garcia Ave
+ *                    Mountain View, CA  94043
+ *
+ * Revision History:
+ * 29-Oct-90: fix bad (int) cast.
+ * 29-Jul-90: support for multiple screens.
+ * 08-Jul-90: new timing and colors and new algorithm for fractals.
+ * 15-Dec-89: Fix for proper skipping of {White,Black}Pixel() in colors.
+ * 08-Oct-89: Fixed long standing typo bug in RandomInitHop();
+ *           Fixed bug in memory allocation in inithop();
+ *           Moved seconds() to an extern.
+ *           Got rid of the % mod since .mod is slow on a sparc.
+ * 20-Sep-89: Lint.
+ * 31-Aug-88: Forked from xlock.c for modularity.
+ * 23-Mar-88: Coded HOPALONG routines from Scientific American Sept. 86 p. 14.
+ */
+
+#include <math.h>
+#include "screenhack.h"
+
+static GC gc;
+static int batchcount = 1000;
+
+static unsigned int *pixels = 0, fg_pixel, bg_pixel;
+static int npixels;
+static unsigned int delay;
+static int timeout;
+
+typedef struct {
+    int         centerx;
+    int         centery;       /* center of the screen */
+    double      a;
+    double      b;
+    double      c;
+    double      i;
+    double      j;             /* hopalong parameters */
+    int         inc;
+    int         pix;
+    long        startTime;
+}           hopstruct;
+
+static hopstruct hop;
+static XPoint *pointBuffer = 0;        /* pointer for XDrawPoints */
+
+static void
+inithop(dsp,win)
+     Display *dsp;
+    Window      win;
+{
+    double      range;
+    XWindowAttributes xgwa;
+    hopstruct  *hp = &hop;
+    XGCValues gcv;
+    Colormap cmap;
+    XGetWindowAttributes (dsp, win, &xgwa);
+    cmap = xgwa.colormap;
+
+    if (! pixels)
+      {
+       XColor color;
+       int i = get_integer_resource ("ncolors", "Integer");
+       int shift;
+       if (i <= 2) i = 2, mono_p = True;
+       shift = 360 / i;
+       pixels = (unsigned int *) calloc (i, sizeof (unsigned int));
+       fg_pixel = get_pixel_resource ("foreground", "Foreground", dsp, cmap);
+       bg_pixel = get_pixel_resource ("background", "Background", dsp, cmap);
+       if (! mono_p)
+         {
+           hsv_to_rgb (random () % 360, 1.0, 1.0, 
+                       &color.red, &color.green, &color.blue);
+           for (npixels = 0; npixels < i; npixels++)
+             {
+               if (! XAllocColor (dsp, cmap, &color))
+                 break;
+               pixels[npixels] = color.pixel;
+               cycle_hue (&color, shift);
+             }
+         }
+       timeout = get_integer_resource ("timeout", "Seconds");
+       if (timeout <= 0) timeout = 30;
+       delay = get_integer_resource ("delay", "Usecs");
+
+       gcv.foreground = fg_pixel;
+       gc = XCreateGC (dsp, win, GCForeground, &gcv);
+      }
+
+    XClearWindow (dsp, win);
+
+    hp->centerx = xgwa.width / 2;
+    hp->centery = xgwa.height / 2;
+    range = sqrt((double) hp->centerx * hp->centerx +
+                (double) hp->centery * hp->centery) /
+       (10.0 + random() % 10);
+
+    hp->pix = 0;
+#define frand0() (((double) random()) / ((unsigned int) (~0)))
+    hp->inc = (int) (frand0() * 200) - 100;
+    hp->a = frand0() * range - range / 2.0;
+    hp->b = frand0() * range - range / 2.0;
+    hp->c = frand0() * range - range / 2.0;
+    if (!(random() % 2))
+       hp->c = 0.0;
+
+    hp->i = hp->j = 0.0;
+
+    if (!pointBuffer)
+       pointBuffer = (XPoint *) malloc(batchcount * sizeof(XPoint));
+
+    XSetForeground(dsp, gc, bg_pixel);
+    XFillRectangle(dsp, win, gc, 0, 0,
+                  hp->centerx * 2, hp->centery * 2);
+    XSetForeground(dsp, gc, fg_pixel);
+    hp->startTime = time ((time_t *) 0);
+}
+
+
+static void
+drawhop(dsp,win)
+     Display *dsp;
+    Window      win;
+{
+    double      oldj;
+    int         k = batchcount;
+    XPoint     *xp = pointBuffer;
+    hopstruct  *hp = &hop;
+
+    hp->inc++;
+    if (! mono_p) {
+       XSetForeground(dsp, gc, pixels[hp->pix]);
+       if (++hp->pix >= npixels)
+           hp->pix = 0;
+    }
+    while (k--) {
+       oldj = hp->j;
+       hp->j = hp->a - hp->i;
+       hp->i = oldj + (hp->i < 0
+                       ? sqrt(fabs(hp->b * (hp->i + hp->inc) - hp->c))
+                       : -sqrt(fabs(hp->b * (hp->i + hp->inc) - hp->c)));
+       xp->x = hp->centerx + (int) (hp->i + hp->j);
+       xp->y = hp->centery - (int) (hp->i - hp->j);
+       xp++;
+    }
+    XDrawPoints(dsp, win, gc,
+               pointBuffer, batchcount, CoordModeOrigin);
+    XSync (dsp, True);
+    if ((time ((time_t *) 0) - hp->startTime) > timeout)
+      {
+       int i;
+       XSetForeground(dsp, gc, bg_pixel);
+       for (i = 0; i < hp->centery; i++)
+         {
+           int y = (random () % (hp->centery << 1));
+           XDrawLine (dsp, win, gc, 0, y, hp->centerx << 1, y);
+           XFlush (dsp);
+           if ((i % 50) == 0)
+             usleep (10000);
+         }
+       XClearWindow (dsp, win);
+       XFlush (dsp);
+       sleep (1);
+       inithop(dsp,win);
+      }
+}
+
+\f
+char *progclass = "Hopalong";
+
+char *defaults [] = {
+  "Hopalong.background:        black",         /* to placate SGI */
+  "Hopalong.foreground:        white",
+  "*count:     1000",
+  "*ncolors:   100",
+  "*timeout:   20",
+  "*delay:     0",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-count",          ".count",       XrmoptionSepArg, 0 },
+  { "-ncolors",                ".ncolors",     XrmoptionSepArg, 0 },
+  { "-timeout",                ".timeout",     XrmoptionSepArg, 0 },
+  { "-delay",          ".delay",       XrmoptionSepArg, 0 },
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  inithop (dpy, window);
+  while (1)
+    {
+      drawhop (dpy, window);
+      XSync (dpy, True);
+      if (delay) usleep (delay);
+    }
+}
diff --git a/hacks/hopalong.man b/hacks/hopalong.man
new file mode 100644 (file)
index 0000000..d812c7b
--- /dev/null
@@ -0,0 +1,69 @@
+.TH XScreenSaver 1 "13-aug-92" "X Version 11"
+.SH NAME
+hopalong - draw real plane fractals
+.SH SYNOPSIS
+.B hopalong
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-count \fIinteger\fP] [\-ncolors \fIinteger\fP] [\-timeout \fIseconds\fP] [\-delay \fImicroseconds\fP]
+.SH DESCRIPTION
+The \fIhopalong\fP program generates real plane fractals as described in
+the September 1986 issue of Scientific American.
+.SH OPTIONS
+.I hopalong
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono 
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-count \fIinteger\fP
+How many pixels should be drawn before a color change.  Default 1000.
+.TP 8
+.B \-ncolors \fIinteger\fP
+How many colors should be used (if possible).  Default 100.
+The colors used cycle through the hue, making N stops around 
+the color wheel.
+.TP 8
+.B \-timeout \fIseconds\fP
+How many seconds we should generate for before clearing the screen
+and starting over.  Default 20.
+.TP 8
+.B \-delay \fImicroseconds\fP
+How long we should wait between drawing each pixel.  Default 0.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR xlock (1)
+.SH COPYRIGHT
+Copyright \(co 1988-91 by Patrick J. Naughton
+
+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. 
+.SH AUTHOR
+Patrick J. Naughton <naughton@eng.sun.com>, 23-mar-88.
+
+Ability to run standalone or with \fIxscreensaver\fP added by 
+Jamie Zawinski <jwz@netscape.com>, 13-aug-92.
diff --git a/hacks/hypercube.c b/hacks/hypercube.c
new file mode 100644 (file)
index 0000000..05574fb
--- /dev/null
@@ -0,0 +1,334 @@
+/* xscreensaver, Copyright (c) 1992, 1995 Jamie Zawinski <jwz@netscape.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.
+ *
+ * This code derived from TI Explorer Lisp code by Joe Keane, Fritz Mueller,
+ * and Jamie Zawinski.
+ */
+
+#include <math.h>
+#include "screenhack.h"
+
+static Display *dpy;
+static Window window;
+static GC color0, color1, color2, color3, color4, color5, color6, color7;
+static GC black;
+
+static int delay;
+
+static int observer_z;
+static int x_offset, y_offset;
+static int unit_pixels;
+
+struct point_state {
+  int old_x, old_y;
+  int new_x, new_y;
+  Bool same_p;
+};
+
+static void
+move_line (state0, state1, gc)
+     struct point_state *state0, *state1;
+     GC gc;
+{
+  if (state0->same_p && state1->same_p)
+    return;
+  if (mono_p)
+    {
+      XDrawLine (dpy, window, black,
+                state0->old_x, state0->old_y, state1->old_x, state1->old_y);
+      XDrawLine (dpy, window, gc,
+                state0->new_x, state0->new_y, state1->new_x, state1->new_y);
+    }
+  else
+    {
+      XSegment segments [2];
+      segments [0].x1 = state0->old_x; segments [0].y1 = state0->old_y;
+      segments [0].x2 = state1->old_x; segments [0].y2 = state1->old_y;
+      segments [1].x1 = state0->new_x; segments [1].y1 = state0->new_y;
+      segments [1].x2 = state1->new_x; segments [1].y2 = state1->new_y;
+      XDrawSegments (dpy, window, gc, segments, 2);
+    }
+}
+
+static void
+hyper (xy, xz, yz, xw, yw, zw)
+     double xy, xz, yz, xw, yw, zw;
+{
+  double cos_xy = cos (xy), sin_xy = sin (xy);
+  double cos_xz = cos (xz), sin_xz = sin (xz);
+  double cos_yz = cos (yz), sin_yz = sin (yz);
+  double cos_xw = cos (xw), sin_xw = sin (xw);
+  double cos_yw = cos (yw), sin_yw = sin (yw);
+  double cos_zw = cos (zw), sin_zw = sin (zw);
+
+  double ax = 1.0, ay = 0.0, az = 0.0, aw = 0.0;
+  double bx = 0.0, by = 1.0, bz = 0.0, bw = 0.0;
+  double cx = 0.0, cy = 0.0, cz = 1.0, cw = 0.0;
+  double dx = 0.0, dy = 0.0, dz = 0.0, dw = 1.0;
+
+  double _tmp0_, _tmp1_;
+
+  struct point_state points [16];
+  memset (points, 0, sizeof (points));
+
+#define mmmm (&points[0])
+#define mmmp (&points[1])
+#define mmpm (&points[2])
+#define mmpp (&points[3])
+#define mpmm (&points[4])
+#define mpmp (&points[5])
+#define mppm (&points[6])
+#define mppp (&points[7])
+#define pmmm (&points[8])
+#define pmmp (&points[9])
+#define pmpm (&points[10])
+#define pmpp (&points[11])
+#define ppmm (&points[12])
+#define ppmp (&points[13])
+#define pppm (&points[14])
+#define pppp (&points[15])
+
+  while (1)
+    {
+      double temp_mult;
+
+#define compute(a,b,c,d,point_state) \
+      temp_mult = (unit_pixels / (((a*az) + (b*bz) + (c*cz) + (d*dz) +   \
+                                  (a*aw) + (b*bw) + (c*cw) + (d*dw))     \
+                                 - observer_z));                         \
+  point_state->old_x = point_state->new_x;                               \
+  point_state->old_y = point_state->new_y;                               \
+  point_state->new_x = ((((a*ax) + (b*bx) + (c*cx) + (d*dx)) * temp_mult) \
+                       + x_offset);                                      \
+  point_state->new_y = ((((a*ay) + (b*by) + (c*cy) + (d*dy)) * temp_mult) \
+                       + y_offset);                                      \
+  point_state->same_p = (point_state->old_x == point_state->new_x &&     \
+                        point_state->old_y == point_state->new_y);
+
+      compute (-1, -1, -1, -1, mmmm);
+      compute (-1, -1, -1,  1, mmmp);
+      compute (-1, -1,  1, -1, mmpm);
+      compute (-1, -1,  1,  1, mmpp);
+      compute (-1,  1, -1, -1, mpmm);
+      compute (-1,  1, -1,  1, mpmp);
+      compute (-1,  1,  1, -1, mppm);
+      compute (-1,  1,  1,  1, mppp);
+      compute ( 1, -1, -1, -1, pmmm);
+      compute ( 1, -1, -1,  1, pmmp);
+      compute ( 1, -1,  1, -1, pmpm);
+      compute ( 1, -1,  1,  1, pmpp);
+      compute ( 1,  1, -1, -1, ppmm);
+      compute ( 1,  1, -1,  1, ppmp);
+      compute ( 1,  1,  1, -1, pppm);
+      compute ( 1,  1,  1,  1, pppp);
+
+      move_line (mmmm, mmmp, color0);
+      move_line (mmmm, mmpm, color0);
+      move_line (mmpm, mmpp, color0);
+      move_line (mmmp, mmpp, color0);
+      
+      move_line (pmmm, pmmp, color1);
+      move_line (pmmm, pmpm, color1);
+      move_line (pmpm, pmpp, color1);
+      move_line (pmmp, pmpp, color1);
+      
+      move_line (mpmm, mpmp, color2);
+      move_line (mpmm, mppm, color2);
+      move_line (mppm, mppp, color2);
+      move_line (mpmp, mppp, color2);
+      
+      move_line (mmpp, mppp, color3);
+      move_line (mmpp, pmpp, color3);
+      move_line (pmpp, pppp, color3);
+      move_line (mppp, pppp, color3);
+      
+      move_line (mmmm, mpmm, color4);
+      move_line (mmmm, pmmm, color4);
+      move_line (mpmm, ppmm, color4);
+      move_line (pmmm, ppmm, color4);
+      
+      move_line (mmmp, mpmp, color5);
+      move_line (mmmp, pmmp, color5);
+      move_line (pmmp, ppmp, color5);
+      move_line (mpmp, ppmp, color5);
+      
+      move_line (mmpm, mppm, color6);
+      move_line (mmpm, pmpm, color6);
+      move_line (pmpm, pppm, color6);
+      move_line (mppm, pppm, color6);
+      
+      move_line (ppmm, ppmp, color7);
+      move_line (ppmm, pppm, color7);
+      move_line (pppm, pppp, color7);
+      move_line (ppmp, pppp, color7);
+
+ /* If you get error messages about the following forms, and you think you're
+    using an ANSI C conforming compiler, then you're mistaken.  Possibly you're
+    mixing an ANSI compiler with a non-ANSI preprocessor, or vice versa.
+    Regardless, your system is broken; it's not a bug in this program.
+  */
+#if __STDC__
+# define rotate(name,dim0,dim1,cos,sin) \
+      _tmp0_ = ((name##dim0 * cos) + (name##dim1 * sin)); \
+      _tmp1_ = ((name##dim1 * cos) - (name##dim0 * sin)); \
+      name##dim0 = _tmp0_; \
+      name##dim1 = _tmp1_;
+
+# define rotates(dim0,dim1) \
+      if (sin_##dim0##dim1 != 0) {                                \
+        rotate(a, dim0, dim1, cos_##dim0##dim1, sin_##dim0##dim1); \
+        rotate(b, dim0, dim1, cos_##dim0##dim1, sin_##dim0##dim1); \
+        rotate(c, dim0, dim1, cos_##dim0##dim1, sin_##dim0##dim1); \
+        rotate(d, dim0, dim1, cos_##dim0##dim1, sin_##dim0##dim1); \
+      }
+
+#else /* !__STDC__, courtesy of Andreas Luik <luik@isa.de> */
+# define rotate(name,dim0,dim1,cos,sin) \
+      _tmp0_ = ((name/**/dim0 * cos) + (name/**/dim1 * sin)); \
+      _tmp1_ = ((name/**/dim1 * cos) - (name/**/dim0 * sin)); \
+      name/**/dim0 = _tmp0_; \
+      name/**/dim1 = _tmp1_;
+
+# define rotates(dim0,dim1) \
+      if (sin_/**/dim0/**/dim1 != 0) {                                \
+        rotate(a,dim0,dim1,cos_/**/dim0/**/dim1,sin_/**/dim0/**/dim1); \
+        rotate(b,dim0,dim1,cos_/**/dim0/**/dim1,sin_/**/dim0/**/dim1); \
+        rotate(c,dim0,dim1,cos_/**/dim0/**/dim1,sin_/**/dim0/**/dim1); \
+        rotate(d,dim0,dim1,cos_/**/dim0/**/dim1,sin_/**/dim0/**/dim1); \
+      }
+#endif /* !__STDC__ */
+
+      rotates (x,y);
+      rotates (x,z);
+      rotates (y,z);
+      rotates (x,w);
+      rotates (y,w);
+      rotates (z,w);
+
+      XSync (dpy, True);
+      if (delay) usleep (delay);
+    }
+}
+
+\f
+char *progclass = "Hypercube";
+
+char *defaults [] = {
+  "Hypercube.background:       black",         /* to placate SGI */
+  "Hypercube.foreground:       white",
+  "*color0:    red",
+  "*color1:    orange",
+  "*color2:    yellow",
+  "*color3:    white",
+  "*color4:    green",
+  "*color5:    cyan",
+  "*color6:    dodgerblue",
+  "*color7:    magenta",
+
+  "*xw:                0.000",
+  "*xy:                0.010",
+  "*xz:                0.005",
+  "*yw:                0.010",
+  "*yz:                0.000",
+  "*zw:                0.000",
+
+  "*observer-z:        5",
+  "*delay:     100000",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-color0",         ".color0",      XrmoptionSepArg, 0 },
+  { "-color1",         ".color1",      XrmoptionSepArg, 0 },
+  { "-color2",         ".color2",      XrmoptionSepArg, 0 },
+  { "-color3",         ".color3",      XrmoptionSepArg, 0 },
+  { "-color4",         ".color4",      XrmoptionSepArg, 0 },
+  { "-color5",         ".color5",      XrmoptionSepArg, 0 },
+  { "-color6",         ".color6",      XrmoptionSepArg, 0 },
+  { "-color7",         ".color7",      XrmoptionSepArg, 0 },
+
+  { "-xw",             ".xw",          XrmoptionSepArg, 0 },
+  { "-xy",             ".xy",          XrmoptionSepArg, 0 },
+  { "-xz",             ".xz",          XrmoptionSepArg, 0 },
+  { "-yw",             ".yw",          XrmoptionSepArg, 0 },
+  { "-yz",             ".yz",          XrmoptionSepArg, 0 },
+  { "-zw",             ".zw",          XrmoptionSepArg, 0 },
+
+  { "-observer-z",     ".observer-z",  XrmoptionSepArg, 0 },
+  { "-delay",          ".delay",       XrmoptionSepArg, 0 }
+};
+
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+
+void
+screenhack (d, w)
+     Display *d;
+     Window w;
+{
+  XGCValues gcv;
+  XWindowAttributes xgwa;
+  Colormap cmap;
+  double xy, xz, yz, xw, yw, zw;
+  unsigned long bg;
+
+  dpy = d;
+  window = w;
+  XGetWindowAttributes (dpy, window, &xgwa);
+  cmap = xgwa.colormap;
+
+  x_offset = xgwa.width / 2;
+  y_offset = xgwa.height / 2;
+  unit_pixels = xgwa.width < xgwa.height ? xgwa.width : xgwa.height;
+
+  xy = get_float_resource ("xy", "Float");
+  xz = get_float_resource ("xz", "Float");
+  yz = get_float_resource ("yz", "Float");
+  xw = get_float_resource ("xw", "Float");
+  yw = get_float_resource ("yw", "Float");
+  zw = get_float_resource ("zw", "Float");
+
+  observer_z = get_integer_resource ("observer-z", "Integer");
+
+  delay = get_integer_resource ("delay", "Integer");
+
+  bg = get_pixel_resource ("background", "Background", dpy, cmap);
+
+  if (mono_p)
+    {
+      gcv.function = GXcopy;
+      gcv.foreground = bg;
+      black = XCreateGC (dpy, window, GCForeground|GCFunction, &gcv);
+      gcv.foreground = get_pixel_resource ("foreground", "Foreground",
+                                          dpy, cmap);
+      color0 = color1 = color2 = color3 = color4 = color5 = color6 = color7 =
+       XCreateGC (dpy, window, GCForeground|GCFunction, &gcv);
+    }
+  else
+    {
+      black = 0;
+      gcv.function = GXxor;
+#define make_gc(color,name) \
+       gcv.foreground = bg ^ get_pixel_resource ((name), "Foreground", \
+                                                 dpy, cmap);           \
+       color = XCreateGC (dpy, window, GCForeground|GCFunction, &gcv)
+
+      make_gc (color0,"color0");
+      make_gc (color1,"color1");
+      make_gc (color2,"color2");
+      make_gc (color3,"color3");
+      make_gc (color4,"color4");
+      make_gc (color5,"color5");
+      make_gc (color6,"color6");
+      make_gc (color7,"color7");
+    }
+
+  hyper (xy, xz, yz, xw, yw, zw);
+}
diff --git a/hacks/hypercube.man b/hacks/hypercube.man
new file mode 100644 (file)
index 0000000..daa6689
--- /dev/null
@@ -0,0 +1,93 @@
+.TH XScreenSaver 1 "6-dec-92" "X Version 11"
+.SH NAME
+hypercube - 2d projection of a 4d object
+.SH SYNOPSIS
+.B hypercube
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-color[0-7] \fIcolor\fP] [\-xy \fIfloat\fP] [\-xz \fIfloat\fP] [\-yz \fIfloat\fP] [\-xw \fIfloat\fP] [\-yw \fIfloat\fP] [\-zw \fIfloat\fP] [\-observer-z \fIint\fP] [\-delay \fIusecs\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP]
+.SH DESCRIPTION
+The \fIhypercube\fP program displays a wireframe projection of a hypercube
+which is rotating at user-specified rates around any or all of its four axes.
+.SH OPTIONS
+.I hypercube
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono 
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-delay \fImicroseconds\fP
+How much of a delay should be introduced between steps of the animation.
+Default 100000, or about 1/10th second.
+.TP 8
+.B \-observer-z \fIint\fP
+How far away the observer is from the center of the cube (the cube is one
+unit per side.)  Default 5.
+.TP 8
+.B \-color0 \fIcolor\fP
+.TP 8
+.B \-color1 \fIcolor\fP
+.TP 8
+.B \-color2 \fIcolor\fP
+.TP 8
+.B \-color3 \fIcolor\fP
+.TP 8
+.B \-color4 \fIcolor\fP
+.TP 8
+.B \-color5 \fIcolor\fP
+.TP 8
+.B \-color6 \fIcolor\fP
+.TP 8
+.B \-color7 \fIcolor\fP
+The colors used to draw the line segments bordering the eight faces of
+the cube.  Some of the faces have only two of their border-lines drawn in
+the specified color, and some have all four.
+.TP 8
+.B \-xw \fIfloat\fP
+.TP 8
+.B \-xy \fIfloat\fP
+.TP 8
+.B \-xz \fIfloat\fP
+.TP 8
+.B \-yw \fIfloat\fP
+.TP 8
+.B \-yz \fIfloat\fP
+.TP 8
+.B \-zw \fIfloat\fP
+The amount that the cube should be rotated around the specified axis at
+each frame of the animation, expressed in radians.  These should be small
+floating-point values (less than 0.05 works best.)  Default: xy=0.01,
+xz=0.005, yw=0.01.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1992 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@netscape.com>, 6-dec-92.
diff --git a/hacks/imsmap.c b/hacks/imsmap.c
new file mode 100644 (file)
index 0000000..7a619b9
--- /dev/null
@@ -0,0 +1,437 @@
+/* imsmap, Copyright (c) 1992 Juergen Nickelsen <nickel@cs.tu-berlin.de>
+ * Derived from code by Markus Schirmer, TU Berlin.
+ *
+ * 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 "screenhack.h"
+#include <stdio.h>
+#include <X11/Xutil.h>
+
+#define NSTEPS 7
+#define COUNT (1 << NSTEPS)
+#define CELL(c, r) cell[((unsigned int)(c)) + ((unsigned int) (r)) * xmax]
+
+static enum mode_t { MODE_H, MODE_S, MODE_V, MODE_RANDOM } mode;
+
+static GC gc, gc2;
+static Display *disp;
+static Window wind;
+static XWindowAttributes wattrs;
+
+#if defined(sun) && !__STDC__  /* sun cc doesn't know "signed char" */
+#define signed /**/
+#endif
+
+static unsigned long *pixels = 0, fg_pixel, bg_pixel;
+static int npixels = 0;
+static Colormap cmap;
+static int timeout, cycle_delay;
+static int cycle_p;
+static signed char *cell = NULL;
+static int xmax, ymax;
+static int iterations;
+
+static void
+initwin (dsp, win)
+     Display *dsp;
+     Window win;
+{
+  int fg_h, bg_h;
+  double fg_s, fg_v, bg_s, bg_v;
+
+  enum mode_t this_mode;
+  static Bool rv_p;
+  static int ncolors = 0;
+  int shift = 0;
+  double dshift = 0;
+    
+  XGCValues gcv;
+
+  XGetWindowAttributes (dsp, win, &wattrs);
+  cmap = wattrs.colormap;
+
+  if (!ncolors)
+    {
+      char *mode_str = get_string_resource ("mode", "Mode");
+      rv_p = get_boolean_resource ("reverseVideo", "ReverseVideo");
+      cycle_p = get_boolean_resource ("cycle", "Cycle");
+      ncolors = get_integer_resource ("ncolors", "Integer");
+      timeout = get_integer_resource ("timeout", "Integer");
+      cycle_delay = get_integer_resource ("cycleDelay", "Integer");
+      iterations = get_integer_resource ("iterations", "Integer");
+      if (iterations < 0) iterations = 0;
+      else if (iterations > 7) iterations = 7;
+      pixels = (unsigned long *) calloc (ncolors, sizeof (unsigned int));
+      fg_pixel = get_pixel_resource ("background", "Background", dsp, cmap);
+      bg_pixel = get_pixel_resource ("foreground", "Foreground", dsp, cmap);
+
+      if (mono_p && fg_pixel == bg_pixel)
+       bg_pixel = !bg_pixel;
+
+      if (mono_p) cycle_p = False;
+
+      gcv.foreground = fg_pixel;
+      gcv.background = bg_pixel;
+      gc = XCreateGC (dsp, win, GCForeground|GCBackground, &gcv);
+      gcv.foreground = bg_pixel;
+      gc2 = XCreateGC (dsp, win, GCForeground, &gcv);
+
+      if (!mode_str || !strcmp (mode_str, "random"))
+       mode = MODE_RANDOM;
+      else if (!strcmp (mode_str, "h") || !strcmp (mode_str, "hue"))
+       mode = MODE_H;
+      else if (!strcmp (mode_str, "s") || !strcmp (mode_str, "saturation"))
+       mode = MODE_S;
+      else if (!strcmp (mode_str, "v") || !strcmp (mode_str, "value"))
+       mode = MODE_V;
+      else
+       {
+         fprintf (stderr,
+          "%s: mode must be hue, saturation, value, or random, not \"%s\"\n",
+                  progname, mode_str);
+         mode = MODE_RANDOM;
+       }
+    }
+    else if (! mono_p)
+      XFreeColors (dsp, cmap, pixels, npixels, 0);
+
+  this_mode = mode;
+  if (!mono_p && mode == MODE_RANDOM)
+    switch (random () % 3) {
+    case 0: this_mode = MODE_H; break;
+    case 1: this_mode = MODE_S; break;
+    case 2: this_mode = MODE_V; break;
+    }
+
+  if (mono_p)
+    {
+      npixels = ncolors;
+      pixels [0] = fg_pixel;
+      pixels [1] = bg_pixel;
+    }
+  else
+    {
+      XColor fg_color, bg_color;
+
+      if (fg_pixel == bg_pixel)
+       {
+       HSV_AGAIN:
+         fg_h = random () % 360;
+         bg_h = random () % 360;
+         fg_s = frand (1.0);
+         bg_s = frand (1.0);
+       V_AGAIN:
+         fg_v = frand (1.0);
+         bg_v = frand (1.0);
+         if ((fg_v - bg_v) > -0.4 && (fg_v - bg_v) < 0.4)
+           goto V_AGAIN;
+         hsv_to_rgb (fg_h, fg_s, fg_v, 
+                     &fg_color.red, &fg_color.green, &fg_color.blue);
+         hsv_to_rgb (bg_h, bg_s, bg_v, 
+                     &bg_color.red, &bg_color.green, &bg_color.blue);
+       }
+      else
+       {
+         XQueryColor (dsp, cmap, &fg_color);
+         XQueryColor (dsp, cmap, &bg_color);
+         fg_color.pixel = fg_pixel;
+         bg_color.pixel = bg_pixel;
+       }
+      fg_color.flags = DoRed|DoGreen|DoBlue;
+      bg_color.flags = DoRed|DoGreen|DoBlue;
+
+      rgb_to_hsv (fg_color.red, fg_color.green, fg_color.blue,
+                 &fg_h, &fg_s, &fg_v);
+      rgb_to_hsv (bg_color.red, bg_color.green, bg_color.blue,
+                 &bg_h, &bg_s, &bg_v);
+
+      if (/*mode == MODE_RANDOM &&*/
+         ((this_mode == MODE_S && (fg_s-bg_s) > -0.3 && (fg_s-bg_s) < 0.3) ||
+          (this_mode == MODE_V && (fg_v-bg_v) > -0.3 && (fg_v-bg_v) < 0.3) ||
+          (this_mode == MODE_H && (fg_h-bg_h) > -30 && (fg_h-bg_h) < 30)))
+       goto HSV_AGAIN;
+
+      switch (this_mode) {
+      case MODE_H:  shift = (bg_h - fg_h) / ncolors; break;
+      case MODE_S: dshift = (bg_s - fg_s) / ncolors; break;
+      case MODE_V: dshift = (bg_v - fg_v) / ncolors; break;
+      default: abort ();
+      }
+      
+      if (mode == MODE_RANDOM &&
+         ((this_mode == MODE_H)
+          ? ((shift > -2 && shift < 2) || fg_s < 0.3 || fg_v < 0.3)
+          : (dshift > -0.005 && dshift < 0.005)))
+       goto HSV_AGAIN;
+
+      if (mode == MODE_RANDOM && this_mode == MODE_S && fg_v < 0.5)
+       goto V_AGAIN;
+
+      for (npixels = 0; npixels < ncolors; npixels++)
+       {
+         if (cycle_p)
+           {
+             unsigned long plane_masks;
+             /* allocate the writable color cells, one at a time. */
+             if (! XAllocColorCells (dsp, cmap, False, &plane_masks, 0,
+                                     &fg_color.pixel, 1))
+               {
+                 fprintf (stderr,
+   "%s: couldn't allocate %s writable color cells.  Turning off -cycle.\n",
+                          progname, (npixels ? "enough" : "any"));
+                 cycle_p = 0;
+                 goto NON_CYCLE;
+               }
+             XStoreColor (dsp, cmap, &fg_color);
+           }
+         else
+           {
+           NON_CYCLE:
+             if (!XAllocColor (dsp, cmap, &fg_color))
+               break;
+           }
+         pixels[npixels] = fg_color.pixel;
+       
+         switch (this_mode)
+           {
+           case MODE_H: fg_h = (fg_h + shift) % 360; break;
+           case MODE_S: fg_s += dshift; break;
+           case MODE_V: fg_v += dshift; break;
+           default: abort ();
+           }
+         hsv_to_rgb (fg_h, fg_s, fg_v,
+                     &fg_color.red, &fg_color.green, &fg_color.blue);
+       }
+    }
+  XSetForeground (dsp, gc, pixels [0]);
+  XFillRectangle (dsp, win, gc, 0, 0, wattrs.width, wattrs.height);
+}
+
+
+#define HEIGHT_TO_PIXEL(height) \
+       (((int) (height)) < 0 ? 0 : \
+        ((int) (height)) >= npixels ? npixels - 3 : ((int) (height)))
+
+static unsigned int
+set (l, c, size, height)
+     unsigned int l, c, size;
+     int height;
+{
+  int rang = 1 << (NSTEPS - size);
+  height = height + (random () % rang) - rang / 2;
+  CELL (l, c) = height;
+
+  return pixels [HEIGHT_TO_PIXEL (height)];
+}
+
+static void
+floyd_steinberg ()
+{
+  int x, y, err;
+
+  /* Instead of repeatedly calling XPutPixel(), we make an Image and then
+     send its bits over all at once.  This consumes much less network
+     bandwidth.  The image we create is Wx1 intead of WxH, so that we
+     don't use enormous amounts of memory.
+   */
+  XImage *image =
+    XCreateImage (disp, DefaultVisual(disp,DefaultScreen(disp)),
+                 1, XYBitmap, 0,               /* depth, format, offset */
+                 (char *) calloc ((xmax + 1) / 8, 1),  /* data */
+                 xmax, 1, 8, 0);               /* w, h, pad, bpl */
+
+  for (y = 0; y < ymax - 1; y++)
+    {
+      for (x = 0; x < xmax - 1; x++)
+       {
+         if (CELL(x, y) < 0)
+           {
+             err = CELL (x, y);
+             XPutPixel (image, x, 0, 1);
+           }
+         else
+           {
+             err = CELL (x, y) - 1;
+             XPutPixel (image, x, 0, 0);
+           }
+         /* distribute error */
+         CELL (x,   y+1) += (int) (((float) err) * 3.0/8.0);
+         CELL (x+1, y)   += (int) (((float) err) * 3.0/8.0);
+         CELL (x+1, y+1) += (int) (((float) err) * 1.0/4.0);
+       }
+      XPutImage (disp, wind, gc, image, 0, 0, 0, y, xmax, 1);
+    }
+  XDestroyImage (image);
+}
+
+static void
+draw (x, y, pixel, grid_size)  /* not called in mono mode */
+     int x, y, grid_size;
+     unsigned long pixel;
+{
+  static unsigned int last_pixel, last_valid = 0;
+  if (! (last_valid && pixel == last_pixel))
+    XSetForeground (disp, gc, pixel);
+  last_valid = 1, last_pixel = pixel;
+  if (grid_size == 1)
+    XDrawPoint (disp, wind, gc, x, y);
+  else
+    XFillRectangle (disp, wind, gc, x, y, grid_size, grid_size);
+}
+
+
+static void 
+drawmap ()
+{
+  unsigned int x, y, i, step, nextStep, x1, x2, y1, y2;
+  unsigned int pixel, qpixels [4];
+
+  xmax = wattrs.width;
+  ymax = wattrs.height;
+
+  cell = (signed char *) calloc (xmax * ymax, 1);
+  if (cell == NULL)
+    exit (1);
+
+  CELL (0, 0) = 0;
+  step = COUNT;
+  for (i = 0; i < iterations; i++)
+    {
+      nextStep = step / 2;
+      for (x = 0; x < xmax; x += step)
+       {
+         x1 = x + nextStep;
+         if (x1 >= xmax)
+           x1 = 0;
+         x2 = x + step;
+         if (x2 >= xmax)
+           x2 = 0;
+         for (y = 0; y < ymax; y += step)
+           {
+             y1 = y + nextStep;
+             if (y1 >= ymax)
+               y1 = 0;
+             y2 = y + step;
+             if (y2 >= ymax)
+               y2 = 0;
+
+             qpixels [0] = pixels [HEIGHT_TO_PIXEL (CELL (x, y))];
+             qpixels [1] = pixels [HEIGHT_TO_PIXEL (CELL (x, y2))];
+             qpixels [2] = pixels [HEIGHT_TO_PIXEL (CELL (x2, y))];
+             qpixels [3] = pixels [HEIGHT_TO_PIXEL (CELL (x2, y2))];
+
+             pixel = set (x, y1, i,
+                          ((int) CELL (x, y) + (int) CELL (x, y2) + 1) / 2);
+             if (! mono_p &&
+                 (pixel != qpixels[0] || pixel != qpixels[1] || 
+                  pixel != qpixels[2] || pixel != qpixels[3]))
+               draw (x, y1, pixel, nextStep);
+
+             pixel = set (x1, y, i,
+                          ((int) CELL (x, y) + (int) CELL (x2, y) + 1) / 2);
+             if (! mono_p &&
+                 (pixel != qpixels[0] || pixel != qpixels[1] || 
+                  pixel != qpixels[2] || pixel != qpixels[3]))
+               draw (x1, y, pixel, nextStep);
+
+             pixel = set (x1, y1, i,
+                          ((int) CELL (x, y) + (int) CELL (x, y2) +
+                           (int) CELL (x2, y) + (int) CELL (x2, y2) + 2)
+                          / 4);
+             if (! mono_p &&
+                 (pixel != qpixels[0] || pixel != qpixels[1] || 
+                  pixel != qpixels[2] || pixel != qpixels[3]))
+               draw (x1, y1, pixel, nextStep);
+           }
+       }
+      step = nextStep;
+      if (!mono_p)
+       XSync (disp, True);
+    }
+  if (mono_p)
+    /* in mono-mode, we do all the drawing at the end */
+    floyd_steinberg ();
+  
+  free (cell);
+  XSync (disp, True);
+}
+
+static void
+cycle (dpy)
+     Display *dpy;
+{
+  XColor *colors = (XColor *) malloc (npixels * sizeof (XColor));
+  time_t stop;
+  int i;
+  for (i = 0; i < npixels; i++)
+    colors [i].pixel = pixels [i];
+  XQueryColors (dpy, cmap, colors, npixels);
+  stop = (time_t) ((time ((time_t) 0)) + timeout);
+  while (stop >= (time_t) time ((time_t) 0))
+    {
+      unsigned long scratch = colors [npixels-1].pixel;
+      for (i = npixels-1; i > 0; i--)
+       colors [i].pixel = colors [i-1].pixel;
+      colors [0].pixel = scratch;
+      XStoreColors (dpy, cmap, colors, npixels);
+      XSync (dpy, True);
+      if (cycle_delay) usleep (cycle_delay);
+    }
+  XSync (dpy, True);
+  free (colors);
+}
+
+
+char *progclass = "Imsmap";
+
+char *defaults [] = {
+  "Imsmap.background:  black",         /* to placate SGI */
+  "Imsmap.foreground:  black",
+  "*mode:      random",
+  "*ncolors:   50",
+  "*iterations:        7",
+  "*timeout:   10",
+  "*cycleDelay:        100000",
+  "*cycle:     true",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-ncolors",                ".ncolors",     XrmoptionSepArg, 0 },
+  { "-timeout",                ".timeout",     XrmoptionSepArg, 0 },
+  { "-cycle-delay",    ".cycleDelay",  XrmoptionSepArg, 0 },
+  { "-mode",           ".mode",        XrmoptionSepArg, 0 },
+  { "-iterations",     ".iterations",  XrmoptionSepArg, 0 },
+  { "-cycle",          ".cycle",       XrmoptionNoArg, "True"  },
+  { "-no-cycle",       ".cycle",       XrmoptionNoArg, "False" }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+
+void
+screenhack (dpy, window)
+     Display *dpy;
+     Window window;
+{
+    disp = dpy;
+    wind = window;
+    while (1)
+      {
+       initwin (dpy, window);
+       drawmap ();
+       if (timeout)
+         {
+           if (cycle_p)
+             cycle (dpy);
+           else
+             sleep (timeout);
+         }
+      }
+}
diff --git a/hacks/imsmap.man b/hacks/imsmap.man
new file mode 100644 (file)
index 0000000..1badced
--- /dev/null
@@ -0,0 +1,63 @@
+.TH XScreenSaver 1 "26-apr-93" "X Version 11"
+.SH NAME
+imsmap - generate fractal maps
+.SH SYNOPSIS
+.B imsmap
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIint\fP] [\-timeout \fIseconds\fP] [\-iterations \fIint\fP] [\-mode h|s|v|random] [\-cycle] [\-no\-cycle]
+.SH DESCRIPTION
+The \fIimsmap\fP program generates map or cloud-like patterns.  It looks
+quite different in monochrome and color.
+.SH OPTIONS
+.I imsmap
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono 
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-ncolors \fIinteger\fP
+How many colors to use.  Default 50.
+.TP 8
+.B \-timeout \fIinteger\fP
+How long to delay between images.  Default 10 seconds.
+.TP 8
+.B \-iterations \fIinteger\fP
+A measure of the resolution of the resultant image, from 0 to 7.  Default 7.
+.TP 8
+.B \-mode [ hue | saturation | value | random ]
+The axis upon which colors should be interpolated between the foreground
+and background color.  Default random.  
+.TP 8
+.B \-cycle
+Whether to do colormap cycling.  This is the default.
+.TP 8
+.B \-no\-cycle
+Turns \fI\-cycle\fP off.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH AUTHOR
+Juergen Nickelsen <nickel@cs.tu-berlin.de>, 23-aug-92.
+
+Hacked on by Jamie Zawinski <jwz@netscape.com>, 24-aug-92.
diff --git a/hacks/lmorph.c b/hacks/lmorph.c
new file mode 100644 (file)
index 0000000..9672f96
--- /dev/null
@@ -0,0 +1,501 @@
+
+/**************************************************************************
+ *
+ *  FILE            lmorph.c
+ *  MODULE OF       xscreensaver
+ *
+ *  DESCRIPTION     Bilinear interpolation for morphing line shapes.
+ *
+ *  WRITTEN BY      Sverre H. Huseby                Glenn T. Lines
+ *                  Maridalsvn. 122, leil 101       Frysjavn. 3, 5. etg.
+ *                  N-0461 Oslo                     N-0883 Oslo
+ *                  Norway                          Norway
+ *
+ *                  Phone:  +47 22 71 99 08         Phone:  +47 22 23 71 99
+ *                  E-mail: sverrehu@ifi.uio.no     E-mail: gtl@si.sintef.no
+ *
+ *                  The original idea, and the bilinear interpolation
+ *                  mathematics used, emerged in the head of the wise
+ *                  Glenn Terje Lines.
+ *
+ *  MODIFICATIONS   march 1995
+ *                    * Converted from an MS-Windows program to X Window.
+ *
+ **************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "screenhack.h"
+
+/**************************************************************************
+ *                                                                        *
+ *                       P R I V A T E    D A T A                         *
+ *                                                                        *
+ **************************************************************************/
+
+/* Define MARGINS to make some space around the figure */
+#define MARGINS /**/
+
+#define MAXFIGS    20
+#define TWO_PI     (2.0 * M_PI)
+#define RND(x)     (random() % (x))
+static int
+    cFig = 0,                   /* Number of figure arrays. */
+    cPoint,                     /* Number of points in each array. */
+    nWork,                      /* Current work array number. */
+    nFrom,                      /* Current from array number. */
+    nTo;                        /* Current to array number. */
+static long
+    delay;                      /* usecs to wait between updates. */
+static XPoint
+    *aWork[2],                  /* Working arrays. */
+    *a[MAXFIGS],                /* The figure arrays. */
+    *aTmp,                      /* Used as source when interrupting morph */
+    *aPrev,                     /* Previous points displayed. */
+    *aCurr,                     /* The current points displayed. */  
+    *aFrom,                     /* Figure converting from. */
+    *aTo;                       /* Figure converting to. */
+static double
+    gam,
+    maxGamma = 1.0,
+    delta_gam;
+static GC
+    gcDraw, gcClear;
+static Display
+    *dpy;
+static Window
+    window;
+
+
+
+/**************************************************************************
+ *                                                                        *
+ *                        P U B L I C    D A T A                          *
+ *                                                                        *
+ **************************************************************************/
+
+char *progclass = "LMorph";
+
+char *defaults [] = {
+    "LMorph.background: black",
+    "LMorph.foreground: green",
+    "*points: 150",
+    "*steps: 0",
+    "*delay: 50000",
+    0
+};
+
+XrmOptionDescRec options [] = {
+  { "-points", ".points", XrmoptionSepArg, 0 },
+  { "-steps",  ".steps",  XrmoptionSepArg, 0 },
+  { "-delay",  ".delay",  XrmoptionSepArg, 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                   *
+ *                                                                        *
+ **************************************************************************/
+
+static void *xmalloc(size)
+       size_t size;
+{
+    void *ret;
+
+    if ((ret = malloc(size)) == NULL) {
+       fprintf(stderr, "lmorph: out of memory\n");
+       exit(1);
+    }
+    return ret;
+}
+
+
+
+static double frnd()
+{
+    /*
+     *  Hm. for some reason the second line (using RAND_MAX) didn't
+     *  work on some machines, so I always use the first.
+     */
+#undef RAND_MAX
+#ifndef RAND_MAX
+    return (double) (random() & 0x7FFF) / 0x7FFF;
+#else
+    return ((double) random()) / RAND_MAX;
+#endif
+}
+
+
+
+static void initPointArrays()
+{
+    XWindowAttributes wa;
+    int q, w,
+        mx, my,                 /* Max screen coordinates. */
+        mp,                     /* Max point number. */
+        s, rx, ry,
+        marginx, marginy;
+    double scalex, scaley;
+
+    XGetWindowAttributes(dpy, window, &wa);
+    mx = wa.width - 1;
+    my = wa.height - 1;
+    mp = cPoint - 1;
+
+    aWork[0] = (XPoint *) xmalloc(cPoint * sizeof(XPoint));
+    aWork[1] = (XPoint *) xmalloc(cPoint * sizeof(XPoint));
+    aTmp     = (XPoint *) xmalloc(cPoint * sizeof(XPoint));
+
+
+    /*
+     *  Figure 0
+     */
+    a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint));
+    s = cPoint / 4;
+    for (q = 0; q < s; q++) {
+        a[cFig][q].x = ((double) q / s) * mx;
+        a[cFig][q].y = 0;
+        a[cFig][s + q].x = mx;
+        a[cFig][s + q].y = ((double) q / s) * my;
+        a[cFig][2 * s + q].x = mx - ((double) q / s) * mx;
+        a[cFig][2 * s + q].y = my;
+        a[cFig][3 * s + q].x = 0;
+        a[cFig][3 * s + q].y = my - ((double) q / s) * my;
+    }
+    for (q = 4 * s; q < cPoint; q++) 
+        a[cFig][q].x = a[cFig][q].y = 0;
+    a[cFig][mp].x = a[cFig][0].x;
+    a[cFig][mp].y = a[cFig][0].y;
+    ++cFig;
+
+    /*
+     *  Figure 1
+     */
+    a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint));
+    for (q = 0; q < cPoint; q++) {
+        a[cFig][q].x = ((double) q / cPoint) * mx;
+        a[cFig][q].y = (1.0 - sin(((double) q / mp) * TWO_PI)) * my / 2.0;
+    }
+    ++cFig;
+
+    /*
+     *  Figure 2
+     */
+    a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint));
+    rx = mx / 2;
+    ry = my / 2;
+    for (q = 0; q < cPoint; q++) {
+        a[cFig][q].x = mx / 2 + rx * sin(1 * TWO_PI * (double) q / mp);
+        a[cFig][q].y = my / 2 + ry * cos(3 * TWO_PI * (double) q / mp);
+    }
+    a[cFig][mp].x = a[cFig][0].x;
+    a[cFig][mp].y = a[cFig][0].y;
+    ++cFig;
+
+    /*
+     *  Figure 3
+     */
+    a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint));
+    rx = mx / 2;
+    ry = my / 2;
+    for (q = 0; q < cPoint; q++) {
+        a[cFig][q].x = mx / 2 + ry * sin(3 * TWO_PI * (double) q / mp);
+        a[cFig][q].y = my / 2 + ry * cos(1 * TWO_PI * (double) q / mp);
+    }
+    a[cFig][mp].x = a[cFig][0].x;
+    a[cFig][mp].y = a[cFig][0].y;
+    ++cFig;
+
+    /*
+     *  Figure 4
+     */
+    a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint));
+    rx = mx / 2;
+    ry = my / 2;
+    for (q = 0; q < cPoint; q++) {
+        a[cFig][q].x = mx / 2 + ry * (1 - 0.1 * frnd())
+           * sin(TWO_PI * (double) q / mp);
+        a[cFig][q].y = my / 2 + ry * (1 - 0.1 * frnd())
+           * cos(TWO_PI * (double) q / mp);
+    }
+    a[cFig][mp].x = a[cFig][0].x;
+    a[cFig][mp].y = a[cFig][0].y;
+    ++cFig;
+
+    /*
+     *  Figure 5
+     */
+    a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint));
+    rx = mx / 2;
+    ry = my / 2;
+    for (q = 0; q < cPoint; q++) {
+        a[cFig][q].x = mx / 2 + ry * (0.8 - 0.2 * sin(30 * TWO_PI * q / mp))
+           * sin(TWO_PI * (double) q / mp);
+        a[cFig][q].y = my / 2 + ry * (0.8 - 0.2 * sin(30 * TWO_PI * q / mp))
+           * cos(TWO_PI * (double) q / mp);
+    }
+    a[cFig][mp].x = a[cFig][0].x;
+    a[cFig][mp].y = a[cFig][0].y;
+    ++cFig;
+
+    /*
+     *  Figure 6
+     */
+    a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint));
+    rx = mx / 2;
+    ry = my / 2;
+    for (q = 0; q < cPoint; q++) {
+        a[cFig][q].x = mx / 2 + ry * sin(TWO_PI * (double) q / mp);
+        a[cFig][q].y = my / 2 + ry * cos(TWO_PI * (double) q / mp);
+    }
+    a[cFig][mp].x = a[cFig][0].x;
+    a[cFig][mp].y = a[cFig][0].y;
+    ++cFig;
+
+    /*
+     *  Figure 7
+     */
+    a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint));
+    rx = mx / 2;
+    ry = my / 2;
+    for (q = 0; q < cPoint; q++) {
+        a[cFig][q].x = mx / 2 + rx * cos(TWO_PI * (double) q / mp);
+        a[cFig][q].y = my / 2 + ry * sin(TWO_PI * (double) q / mp);
+    }
+    a[cFig][mp].x = a[cFig][0].x;
+    a[cFig][mp].y = a[cFig][0].y;
+    ++cFig;
+
+    /*
+     *  Figure 8
+     */
+    a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint));
+    for (q = 0; q < cPoint; q++) {
+        a[cFig][q].x = ((double) q / mp) * mx;
+        a[cFig][q].y = (1.0 - cos(((double) q / mp) * 3 * TWO_PI)) * my / 2.0;
+    }
+    ++cFig;
+
+    /*
+     *  Figure 9
+     */
+    a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint));
+    rx = mx / 2;
+    ry = my / 2;
+    for (q = 0; q < cPoint; q++) {
+        a[cFig][q].x = mx / 2 + rx * sin(2 * TWO_PI * (double) q / mp);
+        a[cFig][q].y = my / 2 + ry * cos(3 * TWO_PI * (double) q / mp);
+    }
+    a[cFig][mp].x = a[cFig][0].x;
+    a[cFig][mp].y = a[cFig][0].y;
+    ++cFig;
+
+    /*
+     *  Figure 10
+     */
+    a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint));
+    rx = mx / 2;
+    ry = my / 2;
+    for (q = 0; q < cPoint; q++) {
+        a[cFig][q].x = mx / 2 + ry * sin(5 * TWO_PI * (double) q / mp)
+           * ((double) q / mp);
+        a[cFig][q].y = my / 2 + ry * cos(5 * TWO_PI * (double) q / mp)
+           * ((double) q / mp);
+    }
+    ++cFig;
+
+    /*
+     *  Figure 11
+     */
+    a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint));
+    rx = mx / 2;
+    ry = my / 2;
+    for (q = 0; q < cPoint; q++) {
+        a[cFig][q].x = mx / 2 + ry * sin(6 * TWO_PI * (double) q / mp)
+           * ((double) q / mp);
+        a[cFig][q].y = my / 2 - ry * cos(6 * TWO_PI * (double) q / mp)
+           * ((double) q / mp);
+    }
+    ++cFig;
+
+    /*
+     *  Figure 12
+     */
+    a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint));
+    for (q = 0; q < cPoint; q++) {
+        a[cFig][q].x = ((double) q / mp) * mx;
+        a[cFig][q].y = (1.0 - sin(((double) q / mp) * 5 * TWO_PI)) * my / 2.0;
+    }
+    ++cFig;
+
+#ifdef MARGINS
+    /*
+     *  Make some space around the figures.
+     */
+    marginx = (mx + 1) / 10;
+    marginy = (my + 1) / 10;
+    scalex = (double) ((mx + 1) - 2.0 * marginx) / (mx + 1.0);
+    scaley = (double) ((my + 1) - 2.0 * marginy) / (my + 1.0);
+    for (q = 0; q < cFig; q++)
+       for (w = 0; w < cPoint; w++) {
+           a[q][w].x = marginx + a[q][w].x * scalex;
+           a[q][w].y = marginy + a[q][w].y * scaley;
+       }
+#endif
+}
+
+
+
+static void createPoints()
+{
+    int    q;
+    XPoint *pa = aCurr, *pa1 = aFrom, *pa2 = aTo;
+    long   lg, l1g;
+
+
+    lg = 8192L * gam, l1g = 8192L * (1.0 - gam);
+    for (q = 0; q < cPoint; q++) {
+        pa->x = (short) ((l1g * pa1->x + lg * pa2->x) / 8192L);
+        pa->y = (short) ((l1g * pa1->y + lg * pa2->y) / 8192L);
+        ++pa;
+        ++pa1;
+        ++pa2;
+    }
+}
+
+
+static void drawImage()
+{
+    register 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
+     *  entire figure using XDrawLines() afterwards.
+     */
+    if (aPrev) {
+       old0 = aPrev;
+       old1 = aPrev + 1;
+       new0 = aCurr;
+       new1 = aCurr + 1;
+       for (q = cPoint - 1; q; q--) {
+           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;
+           ++old1;
+           ++new0;
+           ++new1;
+       }
+    }
+    XDrawLines(dpy, window, gcDraw, aCurr, cPoint, CoordModeOrigin);
+    XFlush(dpy);
+}
+
+static void initLMorph()
+{
+    int               steps;
+    XGCValues         gcv;
+    XWindowAttributes wa;
+    Colormap          cmap;
+    
+    cPoint = get_integer_resource("points", "Integer");
+    steps = get_integer_resource("steps", "Integer");
+    delay = get_integer_resource("delay", "Integer");
+
+    if (steps <= 0)
+      steps = (random() % 400) + 100;
+
+    delta_gam = 1.0 / steps;
+    XGetWindowAttributes(dpy, window, &wa);
+    cmap = wa.colormap;
+    gcv.foreground = get_pixel_resource("foreground", "Foreground", dpy, cmap);
+    gcDraw = XCreateGC(dpy, window, GCForeground, &gcv);
+    XSetForeground(dpy, gcDraw, gcv.foreground);
+    gcv.foreground = get_pixel_resource("background", "Background", dpy, cmap);
+    gcClear = XCreateGC(dpy, window, GCForeground, &gcv);
+    XClearWindow(dpy, window);
+
+    srandom(time(NULL));
+    initPointArrays();
+    aCurr = aWork[nWork = 0];
+    aPrev = NULL;
+    gam = 2.0;
+    nTo = RND(cFig);
+}
+
+static void animateLMorph()
+{
+    if (gam > maxGamma) {
+        gam = 0.0;
+        if (maxGamma == 1.0) {
+            nFrom = nTo;
+            aFrom = a[nFrom];
+        } else {
+            memcpy(aTmp, aCurr, cPoint * sizeof(XPoint));
+            aFrom = aTmp;
+            nFrom = -1;
+        }
+        do {
+            nTo = RND(cFig);
+        } while (nTo == nFrom);
+        aTo = a[nTo];
+        if (RND(2)) {
+            /*
+             *  Reverse the array to get more variation.
+             */
+            int    i1, i2;
+            XPoint p;
+            
+            for (i1 = 0, i2 = cPoint - 1; i1 < cPoint / 2; i1++, i2--) {
+                p = aTo[i1];
+                aTo[i1] = aTo[i2];
+                aTo[i2] = p;
+            }
+        }
+        /*
+         *  It may be nice to interrupt the next run.
+         */
+        if (RND(3) > 0)
+            maxGamma = 0.1 + 0.7 * (RND(1001) / 1000.0);
+        else
+            maxGamma = 1.0;
+    }
+
+    createPoints();
+    drawImage();
+    aPrev = aCurr;
+    aCurr = aWork[nWork ^= 1];
+
+    gam += delta_gam;
+}
+
+
+
+/**************************************************************************
+ *                                                                        *
+ *                    P U B L I C    F U N C T I O N S                    *
+ *                                                                        *
+ **************************************************************************/
+
+void screenhack(disp, win)
+       Display *disp;
+       Window win;
+{
+    dpy = disp;
+    window = win;
+    initLMorph();
+    for (;;) {
+       animateLMorph();
+       screenhack_usleep(delay);
+    }
+}
diff --git a/hacks/lmorph.man b/hacks/lmorph.man
new file mode 100644 (file)
index 0000000..a631f24
--- /dev/null
@@ -0,0 +1,54 @@
+.TH LMORPH 1 "xscreensaver hack"
+.SH NAME
+lmorph \- morphing lines
+.SH SYNOPSIS
+.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]
+.SH DESCRIPTION
+The \fIlmorph\fP program morphs between simple linedrawings using bilinear
+interpolation.
+.SH OPTIONS
+.I lmorph
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono 
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use. Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-points \fIinteger\fP
+Number of points in each line drawing. Default is 150 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.
+.TP 8
+.B \-delay \fImicroseconds\fP
+How much of a delay should be introduced between steps of the animation.
+Default 50000.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH AUTHOR
+Sverre H. Huseby <sverrehu@ifi.uio.no> and Glenn T. Lines <gtl@si.sintef.no>,
+built on top of the screen saver routines by Jamie Zawinski <jwz@netscape.com>.
diff --git a/hacks/maze.c b/hacks/maze.c
new file mode 100644 (file)
index 0000000..6d73796
--- /dev/null
@@ -0,0 +1,792 @@
+/******************************************************************************
+ * [ maze ] ...
+ *
+ * modified:  [ 8-11-95 ] Ed James <james@mml.mmc.com>
+ *              added fill of dead-end box to solve_maze while loop.
+ * modified:  [ 3-7-93 ]  Jamie Zawinski <jwz@netscape.com>
+ *             added the XRoger logo, cleaned up resources, made
+ *             grid size a parameter.
+ * modified:  [ 3-3-93 ]  Jim Randell <jmr@mddjmr.fc.hp.com>
+ *             Added the colour stuff and integrated it with jwz's
+ *             screenhack stuff.  There's still some work that could
+ *             be done on this, particularly allowing a resource to
+ *             specify how big the squares are.
+ * modified:  [ 10-4-88 ]  Richard Hess    ...!uunet!cimshop!rhess  
+ *              [ Revised primary execution loop within main()...
+ *              [ Extended X event handler, check_events()...
+ * modified:  [ 1-29-88 ]  Dave Lemke      lemke@sun.com  
+ *              [ Hacked for X11...
+ *              [  Note the word "hacked" -- this is extremely ugly, but at 
+ *              [   least it does the job.  NOT a good programming example 
+ *              [   for X.
+ * original:  [ 6/21/85 ]  Martin Weiss    Sun Microsystems  [ SunView ]
+ *
+ ******************************************************************************
+ Copyright 1988 by Sun Microsystems, Inc. Mountain View, CA.
+  
+ All Rights Reserved
+  
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose and without fee is hereby granted, 
+ provided that the above copyright notice appear in all copies and that
+ both that copyright notice and this permission notice appear in 
+ supporting documentation, and that the names of Sun or MIT not be
+ used in advertising or publicity pertaining to distribution of the
+ software without specific prior written permission. Sun and M.I.T. 
+ make no representations about the suitability of this software for 
+ any purpose. It is provided "as is" without any express or implied warranty.
+ SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE. IN NO EVENT SHALL SUN BE LIABLE FOR ANY SPECIAL, INDIRECT
+ OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+ OR PERFORMANCE OF THIS SOFTWARE.
+ *****************************************************************************/
+
+#include "screenhack.h"
+
+#define XROGER
+
+static int solve_delay, pre_solve_delay, post_solve_delay;
+
+#include  <stdio.h>
+#include  <X11/Xlib.h>
+#include  <X11/Xutil.h>
+#include  <X11/bitmaps/gray1>
+
+#define MAX_MAZE_SIZE_X        500
+#define MAX_MAZE_SIZE_Y        500
+
+#define MOVE_LIST_SIZE  (MAX_MAZE_SIZE_X * MAX_MAZE_SIZE_Y)
+
+#define WALL_TOP       0x8000
+#define WALL_RIGHT     0x4000
+#define WALL_BOTTOM    0x2000
+#define WALL_LEFT      0x1000
+
+#define DOOR_IN_TOP    0x800
+#define DOOR_IN_RIGHT  0x400
+#define DOOR_IN_BOTTOM 0x200
+#define DOOR_IN_LEFT   0x100
+#define DOOR_IN_ANY    0xF00
+
+#define DOOR_OUT_TOP   0x80
+#define DOOR_OUT_RIGHT 0x40
+#define DOOR_OUT_BOTTOM        0x20
+#define DOOR_OUT_LEFT  0x10
+
+#define START_SQUARE   0x2
+#define END_SQUARE     0x1
+
+#define        border_x        (0)
+#define        border_y        (0)
+
+#define        get_random(x)   (random() % (x))
+  
+static int logo_x, logo_y;
+
+#ifdef XROGER
+# define logo_width  128
+# define logo_height 128
+#else
+# include  <X11/bitmaps/xlogo64>
+# define logo_width xlogo64_width
+# define logo_height xlogo64_height
+# define logo_bits xlogo64_bits
+#endif
+
+static unsigned short maze[MAX_MAZE_SIZE_X][MAX_MAZE_SIZE_Y];
+
+static struct {
+  unsigned char x;
+  unsigned char y;
+  unsigned char dir;
+} move_list[MOVE_LIST_SIZE], save_path[MOVE_LIST_SIZE], path[MOVE_LIST_SIZE];
+
+static int maze_size_x, maze_size_y;
+static int sqnum, cur_sq_x, cur_sq_y, path_length;
+static int start_x, start_y, start_dir, end_x, end_y, end_dir;
+static int grid_width, grid_height;
+
+static Display *dpy;
+static Window  win;
+static GC      gc, cgc, tgc, logo_gc;
+static Pixmap  logo_map;
+
+static int     x = 0, y = 0, restart = 0, stop = 1, state = 1;
+
+static int
+check_events()                                  /* X event handler [ rhess ] */
+{
+  XEvent       e;
+
+  if (XPending(dpy)) {
+    XNextEvent(dpy, &e);
+    switch (e.type) {
+
+    case ButtonPress:
+      switch (e.xbutton.button) {
+      case 3:
+       exit (0);
+       break;
+      case 2:
+       stop = !stop ;
+       if (state == 5) state = 4 ;
+       else {
+         restart = 1;
+         stop = 0;
+       }
+       break;
+      default:
+       restart = 1 ;
+       stop = 0 ;
+       break;
+      }
+      break;
+
+    case ConfigureNotify:
+      restart = 1;
+      break;
+    case UnmapNotify:
+      stop = 1;
+      XClearWindow (dpy, win);
+      XSync (dpy, False);
+      break;
+    case Expose:
+      restart = 1;
+      break;
+    }
+    return(1);
+  }
+  return(0);
+}
+
+
+static void
+set_maze_sizes (width, height)
+     int width, height;
+{
+  maze_size_x = width / grid_width;
+  maze_size_y = height / grid_height;
+}
+
+
+static void
+initialize_maze()         /* draw the surrounding wall and start/end squares */
+{
+  register int i, j, wall;
+  
+  /* initialize all squares */
+  for ( i=0; i<maze_size_x; i++) {
+    for ( j=0; j<maze_size_y; j++) {
+      maze[i][j] = 0;
+    }
+  }
+  
+  /* top wall */
+  for ( i=0; i<maze_size_x; i++ ) {
+    maze[i][0] |= WALL_TOP;
+  }
+  
+  /* right wall */
+  for ( j=0; j<maze_size_y; j++ ) {
+    maze[maze_size_x-1][j] |= WALL_RIGHT;
+  }
+  
+  /* bottom wall */
+  for ( i=0; i<maze_size_x; i++ ) {
+    maze[i][maze_size_y-1] |= WALL_BOTTOM;
+  }
+  
+  /* left wall */
+  for ( j=0; j<maze_size_y; j++ ) {
+    maze[0][j] |= WALL_LEFT;
+  }
+  
+  /* set start square */
+  wall = get_random(4);
+  switch (wall) {
+  case 0:      
+    i = get_random(maze_size_x);
+    j = 0;
+    break;
+  case 1:      
+    i = maze_size_x - 1;
+    j = get_random(maze_size_y);
+    break;
+  case 2:      
+    i = get_random(maze_size_x);
+    j = maze_size_y - 1;
+    break;
+  case 3:      
+    i = 0;
+    j = get_random(maze_size_y);
+    break;
+  }
+  maze[i][j] |= START_SQUARE;
+  maze[i][j] |= ( DOOR_IN_TOP >> wall );
+  maze[i][j] &= ~( WALL_TOP >> wall );
+  cur_sq_x = i;
+  cur_sq_y = j;
+  start_x = i;
+  start_y = j;
+  start_dir = wall;
+  sqnum = 0;
+  
+  /* set end square */
+  wall = (wall + 2)%4;
+  switch (wall) {
+  case 0:
+    i = get_random(maze_size_x);
+    j = 0;
+    break;
+  case 1:
+    i = maze_size_x - 1;
+    j = get_random(maze_size_y);
+    break;
+  case 2:
+    i = get_random(maze_size_x);
+    j = maze_size_y - 1;
+    break;
+  case 3:
+    i = 0;
+    j = get_random(maze_size_y);
+    break;
+  }
+  maze[i][j] |= END_SQUARE;
+  maze[i][j] |= ( DOOR_OUT_TOP >> wall );
+  maze[i][j] &= ~( WALL_TOP >> wall );
+  end_x = i;
+  end_y = j;
+  end_dir = wall;
+  
+  /* set logo */
+  if ((maze_size_x > 15) && (maze_size_y > 15))
+    {
+      int logow = 1 + logo_width / grid_width;
+      int logoh = 1 + logo_height / grid_height;
+      /* not closer than 3 grid units from a wall */
+      logo_x = get_random (maze_size_x - logow - 6) + 3;
+      logo_y = get_random (maze_size_y - logoh - 6) + 3;
+      for (i=0; i<logow; i++)
+       for (j=0; j<logoh; j++)
+         maze[logo_x + i][logo_y + j] |= DOOR_IN_TOP;
+    }
+  else
+    logo_y = logo_x = -1;
+}
+
+static int choose_door ();
+static int backup ();
+static void draw_wall ();
+static void draw_solid_square ();
+static void enter_square ();
+
+static void
+create_maze()             /* create a maze layout given the intiialized maze */
+{
+  register int i, newdoor = 0;
+  
+  do {
+    move_list[sqnum].x = cur_sq_x;
+    move_list[sqnum].y = cur_sq_y;
+    move_list[sqnum].dir = newdoor;
+    while ( ( newdoor = choose_door() ) == -1 ) { /* pick a door */
+      if ( backup() == -1 ) { /* no more doors ... backup */
+       return; /* done ... return */
+      }
+    }
+    
+    /* mark the out door */
+    maze[cur_sq_x][cur_sq_y] |= ( DOOR_OUT_TOP >> newdoor );
+    
+    switch (newdoor) {
+    case 0: cur_sq_y--;
+      break;
+    case 1: cur_sq_x++;
+      break;
+    case 2: cur_sq_y++;
+      break;
+    case 3: cur_sq_x--;
+      break;
+    }
+    sqnum++;
+    
+    /* mark the in door */
+    maze[cur_sq_x][cur_sq_y] |= ( DOOR_IN_TOP >> ((newdoor+2)%4) );
+    
+    /* if end square set path length and save path */
+    if ( maze[cur_sq_x][cur_sq_y] & END_SQUARE ) {
+      path_length = sqnum;
+      for ( i=0; i<path_length; i++) {
+       save_path[i].x = move_list[i].x;
+       save_path[i].y = move_list[i].y;
+       save_path[i].dir = move_list[i].dir;
+      }
+    }
+    
+  } while (1);
+  
+}
+
+
+static int
+choose_door()                                            /* pick a new path */
+{
+  int candidates[3];
+  register int num_candidates;
+  
+  num_candidates = 0;
+  
+  /* top wall */
+  if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_TOP )
+    goto rightwall;
+  if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_TOP )
+    goto rightwall;
+  if ( maze[cur_sq_x][cur_sq_y] & WALL_TOP )
+    goto rightwall;
+  if ( maze[cur_sq_x][cur_sq_y - 1] & DOOR_IN_ANY ) {
+    maze[cur_sq_x][cur_sq_y] |= WALL_TOP;
+    maze[cur_sq_x][cur_sq_y - 1] |= WALL_BOTTOM;
+    draw_wall(cur_sq_x, cur_sq_y, 0);
+    goto rightwall;
+  }
+  candidates[num_candidates++] = 0;
+  
+ rightwall:
+  /* right wall */
+  if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_RIGHT )
+    goto bottomwall;
+  if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_RIGHT )
+    goto bottomwall;
+  if ( maze[cur_sq_x][cur_sq_y] & WALL_RIGHT )
+    goto bottomwall;
+  if ( maze[cur_sq_x + 1][cur_sq_y] & DOOR_IN_ANY ) {
+    maze[cur_sq_x][cur_sq_y] |= WALL_RIGHT;
+    maze[cur_sq_x + 1][cur_sq_y] |= WALL_LEFT;
+    draw_wall(cur_sq_x, cur_sq_y, 1);
+    goto bottomwall;
+  }
+  candidates[num_candidates++] = 1;
+  
+ bottomwall:
+  /* bottom wall */
+  if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_BOTTOM )
+    goto leftwall;
+  if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_BOTTOM )
+    goto leftwall;
+  if ( maze[cur_sq_x][cur_sq_y] & WALL_BOTTOM )
+    goto leftwall;
+  if ( maze[cur_sq_x][cur_sq_y + 1] & DOOR_IN_ANY ) {
+    maze[cur_sq_x][cur_sq_y] |= WALL_BOTTOM;
+    maze[cur_sq_x][cur_sq_y + 1] |= WALL_TOP;
+    draw_wall(cur_sq_x, cur_sq_y, 2);
+    goto leftwall;
+  }
+  candidates[num_candidates++] = 2;
+  
+ leftwall:
+  /* left wall */
+  if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_LEFT )
+    goto donewall;
+  if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_LEFT )
+    goto donewall;
+  if ( maze[cur_sq_x][cur_sq_y] & WALL_LEFT )
+    goto donewall;
+  if ( maze[cur_sq_x - 1][cur_sq_y] & DOOR_IN_ANY ) {
+    maze[cur_sq_x][cur_sq_y] |= WALL_LEFT;
+    maze[cur_sq_x - 1][cur_sq_y] |= WALL_RIGHT;
+    draw_wall(cur_sq_x, cur_sq_y, 3);
+    goto donewall;
+  }
+  candidates[num_candidates++] = 3;
+  
+ donewall:
+  if (num_candidates == 0)
+    return ( -1 );
+  if (num_candidates == 1)
+    return ( candidates[0] );
+  return ( candidates[ get_random(num_candidates) ] );
+  
+}
+
+
+static int
+backup()                                                  /* back up a move */
+{
+  sqnum--;
+  cur_sq_x = move_list[sqnum].x;
+  cur_sq_y = move_list[sqnum].y;
+  return ( sqnum );
+}
+
+
+static void
+draw_maze_border()                                  /* draw the maze outline */
+{
+  register int i, j;
+  
+  
+  for ( i=0; i<maze_size_x; i++) {
+    if ( maze[i][0] & WALL_TOP ) {
+      XDrawLine(dpy, win, gc,
+               border_x + grid_width * i,
+               border_y,
+               border_x + grid_width * (i+1) - 1,
+               border_y);
+    }
+    if ((maze[i][maze_size_y - 1] & WALL_BOTTOM)) {
+      XDrawLine(dpy, win, gc,
+               border_x + grid_width * i,
+               border_y + grid_height * (maze_size_y) - 1,
+               border_x + grid_width * (i+1) - 1,
+               border_y + grid_height * (maze_size_y) - 1);
+    }
+  }
+  for ( j=0; j<maze_size_y; j++) {
+    if ( maze[maze_size_x - 1][j] & WALL_RIGHT ) {
+      XDrawLine(dpy, win, gc,
+               border_x + grid_width * maze_size_x - 1,
+               border_y + grid_height * j,
+               border_x + grid_width * maze_size_x - 1,
+               border_y + grid_height * (j+1) - 1);
+    }
+    if ( maze[0][j] & WALL_LEFT ) {
+      XDrawLine(dpy, win, gc,
+               border_x,
+               border_y + grid_height * j,
+               border_x,
+               border_y + grid_height * (j+1) - 1);
+    }
+  }
+  
+  if (logo_x != -1)
+    {
+      Window r;
+      int x, y;
+      unsigned int w, h, bw, d;
+      XGetGeometry (dpy, logo_map, &r, &x, &y, &w, &h, &bw, &d);
+      XCopyPlane (dpy, logo_map, win, logo_gc,
+                 0, 0, w, h,
+                 border_x + 3 + grid_width * logo_x,
+                 border_y + 3 + grid_height * logo_y, 1);
+    }
+  draw_solid_square (start_x, start_y, start_dir, tgc);
+  draw_solid_square (end_x, end_y, end_dir, tgc);
+}
+
+
+static void
+draw_wall(i, j, dir)                                   /* draw a single wall */
+     int i, j, dir;
+{
+  switch (dir) {
+  case 0:
+    XDrawLine(dpy, win, gc,
+             border_x + grid_width * i, 
+             border_y + grid_height * j,
+             border_x + grid_width * (i+1), 
+             border_y + grid_height * j);
+    break;
+  case 1:
+    XDrawLine(dpy, win, gc,
+             border_x + grid_width * (i+1), 
+             border_y + grid_height * j,
+             border_x + grid_width * (i+1), 
+             border_y + grid_height * (j+1));
+    break;
+  case 2:
+    XDrawLine(dpy, win, gc,
+             border_x + grid_width * i, 
+             border_y + grid_height * (j+1),
+             border_x + grid_width * (i+1), 
+             border_y + grid_height * (j+1));
+    break;
+  case 3:
+    XDrawLine(dpy, win, gc,
+             border_x + grid_width * i, 
+             border_y + grid_height * j,
+             border_x + grid_width * i, 
+             border_y + grid_height * (j+1));
+    break;
+  }
+}
+
+int bw;
+
+static void
+draw_solid_square(i, j, dir, gc)          /* draw a solid square in a square */
+     register int i, j, dir;
+     GC        gc;
+{
+  switch (dir) {
+  case 0: XFillRectangle(dpy, win, gc,
+                        border_x + bw + grid_width * i, 
+                        border_y - bw + grid_height * j, 
+                        grid_width - (bw+bw), grid_height);
+    break;
+  case 1: XFillRectangle(dpy, win, gc,
+                        border_x + bw + grid_width * i, 
+                        border_y + bw + grid_height * j, 
+                        grid_width, grid_height - (bw+bw));
+    break;
+  case 2: XFillRectangle(dpy, win, gc,
+                        border_x + bw + grid_width * i, 
+                        border_y + bw + grid_height * j, 
+                        grid_width - (bw+bw), grid_height);
+    break;
+  case 3: XFillRectangle(dpy, win, gc,
+                        border_x - bw + grid_width * i, 
+                        border_y + bw + grid_height * j, 
+                        grid_width, grid_height - (bw+bw));
+    break;
+  }
+  XSync (dpy, False);
+}
+
+
+static void
+solve_maze()                             /* solve it with graphical feedback */
+{
+  int i;
+  
+  
+  /* plug up the surrounding wall */
+  maze[start_x][start_y] |= (WALL_TOP >> start_dir);
+  maze[end_x][end_y] |= (WALL_TOP >> end_dir);
+  
+  /* initialize search path */
+  i = 0;
+  path[i].x = end_x;
+  path[i].y = end_y;
+  path[i].dir = -1;
+  
+  /* do it */
+  while (1) {
+    if ( ++path[i].dir >= 4 ) {
+      XFillRectangle(dpy, win, cgc,
+                    border_x + bw + grid_width * (int)(path[i].x),
+                    border_y + bw + grid_height * (int)(path[i].y),
+                    grid_width - (bw+bw), grid_height - (bw+bw));
+      i--;
+      draw_solid_square( (int)(path[i].x), (int)(path[i].y), 
+                       (int)(path[i].dir), cgc);
+    }
+    else if ( ! (maze[path[i].x][path[i].y] & 
+                (WALL_TOP >> path[i].dir))  && 
+            ( (i == 0) || ( (path[i].dir != 
+                             (int)(path[i-1].dir+2)%4) ) ) ) {
+      enter_square(i);
+      i++;
+      if ( maze[path[i].x][path[i].y] & START_SQUARE ) {
+       return;
+      }
+    } 
+    if (check_events()) return;
+    /* Abort solve on expose - cheapo repaint strategy */
+    if (solve_delay) usleep (solve_delay);
+  }
+} 
+
+
+static void
+enter_square(n)                            /* move into a neighboring square */
+     int n;
+{
+  draw_solid_square( (int)path[n].x, (int)path[n].y, 
+                   (int)path[n].dir, tgc);
+  
+  path[n+1].dir = -1;
+  switch (path[n].dir) {
+  case 0: path[n+1].x = path[n].x;
+    path[n+1].y = path[n].y - 1;
+    break;
+  case 1: path[n+1].x = path[n].x + 1;
+    path[n+1].y = path[n].y;
+    break;
+  case 2: path[n+1].x = path[n].x;
+    path[n+1].y = path[n].y + 1;
+    break;
+  case 3: path[n+1].x = path[n].x - 1;
+    path[n+1].y = path[n].y;
+    break;
+  }
+}
+
+/* ----<eof> */
+
+
+/*
+ *  jmr additions for Jamie Zawinski's <jwz@netscape.com> screensaver stuff,
+ *  note that the code above this has probably been hacked about in some
+ *  arbitrary way.
+ */
+
+char *progclass = "Maze";
+
+char *defaults[] = {
+  "Maze.background:    black",         /* to placate SGI */
+  "Maze.foreground:    white",         /* to placate SGI */
+  "*gridSize:  0",
+  "*solveDelay:        5000",
+  "*preDelay:  2000000",
+  "*postDelay: 4000000",
+  "*liveColor: green",
+  "*deadColor: red",
+#ifdef XROGER
+  "*logoColor: red3",
+#endif
+  0
+};
+
+XrmOptionDescRec options[] = {
+  { "-grid-size",      ".gridSize",    XrmoptionSepArg, 0 },
+  { "-solve-delay",    ".solveDelay",  XrmoptionSepArg, 0 },
+  { "-pre-delay",      ".preDelay",    XrmoptionSepArg, 0 },
+  { "-post-delay",     ".postDelay",   XrmoptionSepArg, 0 },
+  { "-live-color",     ".liveColor",   XrmoptionSepArg, 0 },
+  { "-dead-color",     ".deadColor",   XrmoptionSepArg, 0 }
+};
+
+int options_size = (sizeof(options)/sizeof(options[0]));
+
+void screenhack(display,window)
+     Display *display;
+     Window window;
+{
+  Pixmap gray;
+  int size, root;
+  XWindowAttributes xgwa;
+  unsigned long bg, fg, pfg, pbg, lfg;
+
+  size = get_integer_resource ("gridSize", "Dimension");
+  root = get_boolean_resource("root", "Boolean");
+  solve_delay = get_integer_resource ("solveDelay", "Integer");
+  pre_solve_delay = get_integer_resource ("preDelay", "Integer");
+  post_solve_delay = get_integer_resource ("postDelay", "Integer");
+
+  if (size < 2) size = 7 + (random () % 30);
+  grid_width = grid_height = size;
+  bw = (size > 6 ? 3 : (size-1)/2);
+
+  dpy = display; win = window; /* the maze stuff uses global variables */
+
+  XGetWindowAttributes (dpy, win, &xgwa);
+
+  x = 0;
+  y = 0;
+
+  set_maze_sizes (xgwa.width, xgwa.height);
+
+  if (! root)
+    XSelectInput (dpy, win, ExposureMask|ButtonPressMask|StructureNotifyMask);
+  
+  gc = XCreateGC(dpy, win, 0, 0);
+  cgc = XCreateGC(dpy, win, 0, 0);
+  tgc = XCreateGC(dpy,win,0,0);
+  logo_gc = XCreateGC(dpy, win, 0, 0);
+  
+  gray = XCreateBitmapFromData (dpy,win,gray1_bits,gray1_width,gray1_height);
+
+  bg  = get_pixel_resource ("background","Background", dpy, xgwa.colormap);
+  fg  = get_pixel_resource ("foreground","Foreground", dpy, xgwa.colormap);
+  lfg = get_pixel_resource ("logoColor", "Foreground", dpy, xgwa.colormap);
+  pfg = get_pixel_resource ("liveColor", "Foreground", dpy, xgwa.colormap);
+  pbg = get_pixel_resource ("deadColor", "Foreground", dpy, xgwa.colormap);
+  if (mono_p) lfg = pfg = fg;
+
+  if (lfg == bg)
+    lfg = ((bg == WhitePixel (dpy, DefaultScreen (dpy)))
+          ? BlackPixel (dpy, DefaultScreen (dpy))
+          : WhitePixel (dpy, DefaultScreen (dpy)));
+
+  XSetForeground (dpy, gc, fg);
+  XSetBackground (dpy, gc, bg);
+  XSetForeground (dpy, cgc, pbg);
+  XSetBackground (dpy, cgc, bg);
+  XSetForeground (dpy, tgc, pfg);
+  XSetBackground (dpy, tgc, bg);
+  XSetForeground (dpy, logo_gc, lfg);
+  XSetBackground (dpy, logo_gc, bg);
+
+  XSetStipple (dpy, cgc, gray);
+  XSetFillStyle (dpy, cgc, FillOpaqueStippled);
+  
+#ifdef XROGER
+  {
+    int w, h;
+    XGCValues gcv;
+    GC draw_gc, erase_gc;
+    extern void skull ();
+    /* round up to grid size */
+    w = ((logo_width  / grid_width) + 1)  * grid_width;
+    h = ((logo_height / grid_height) + 1) * grid_height;
+    logo_map = XCreatePixmap (dpy, win, w, h, 1);
+    gcv.foreground = 1L;
+    draw_gc = XCreateGC (dpy, logo_map, GCForeground, &gcv);
+    gcv.foreground = 0L;
+    erase_gc= XCreateGC (dpy, logo_map, GCForeground, &gcv);
+    XFillRectangle (dpy, logo_map, erase_gc, 0, 0, w, h);
+    skull (dpy, logo_map, draw_gc, erase_gc, 5, 0, w-10, h-10);
+    XFreeGC (dpy, draw_gc);
+    XFreeGC (dpy, erase_gc);
+  }
+#else
+  if  (!(logo_map = XCreateBitmapFromData (dpy, win, logo_bits,
+                                          logo_width, logo_height)))
+    {
+      fprintf (stderr, "Can't create logo pixmap\n");
+      exit (1);
+    }
+#endif
+  XMapRaised(dpy, win);
+  srandom(getpid());
+
+  restart = root;
+
+  while (1) {                            /* primary execution loop [ rhess ] */
+    if (check_events()) continue ;
+    if (restart || stop) goto pop;
+    switch (state) {
+    case 1:
+      initialize_maze();
+      break;
+    case 2:
+      XClearWindow(dpy, win);
+      draw_maze_border();
+      break;
+    case 3:
+      create_maze();
+      break;
+    case 4:
+      XSync (dpy, False);
+      usleep (pre_solve_delay);
+      break;
+    case 5:
+      solve_maze();
+      break;
+    case 6:
+      XSync (dpy, False);
+      usleep (post_solve_delay);
+      state = 0 ;
+      break;
+    default:
+      abort ();
+    }
+    ++state;
+  pop:
+    if (restart)
+      {
+       static XWindowAttributes wattr;
+       restart = 0;
+       stop = 0;
+       state = 1;
+       XGetWindowAttributes (dpy, win, &wattr);
+       set_maze_sizes (wattr.width, wattr.height);
+       XClearWindow (dpy, win);
+       XSync (dpy, False);
+      }
+  }
+}
diff --git a/hacks/maze.man b/hacks/maze.man
new file mode 100644 (file)
index 0000000..f93a70f
--- /dev/null
@@ -0,0 +1,107 @@
+.TH XScreenSaver 1 "7-mar-93" "X Version 11"
+.SH NAME
+maze \- an automated X11 demo repeatedly creating and solving a random maze
+.SH SYNOPSIS
+.B maze 
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-install] [\-visual \fIvisual\fP] [\-grid\-size \fIpixels\fP] [\-live\-color \fIcolor\fP] [\-dead\-color \fIcolor\fP] [\-solve\-delay \fIusecs\fP] [\-pre\-delay \fIusecs\fP] [\-post\-delay \fIusecs\fP]
+.SH DESCRIPTION
+The \fImaze\fP program creates a "random" maze and then solves it with 
+graphical feedback. 
+.SH OPTIONS
+.I maze
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-grid\-size \fIpixels\fP
+The size of each block of the maze, in pixels; default is 0, meaning
+pick a random grid size.
+.TP 8
+.B \-live\-color \fIcolor\fP
+The color of the path.
+.TP 8
+.B \-dead\-color \fIcolor\fP
+The color of the failed path (it is also stippled with a 50% pattern.)
+.TP 8
+.B \-solve\-delay \fIinteger\fP
+Delay (in microseconds) between each step of the solution path.
+Default 5000, or about 1/200th second.
+.TP 8
+.B \-pre\-delay \fIinteger\fP
+Delay (in microseconds) between generating a maze and starting to solve it.
+Default 2000000 (2 seconds.)
+.TP 8
+.B \-post\-delay \fIinteger\fP
+Delay (in microseconds) after solving a maze and before generating a new one.
+Default 4000000 (4 seconds.)
+.PP
+Clicking the mouse in the maze window controls it.
+.TP 16
+.B "LeftButton
+Clears the window and restarts maze.
+.TP 16
+.B MiddleButton
+Pause or unpause the program.
+.TP 16
+.B RightButton
+Exit.
+.SH BUGS
+Expose events force a restart of maze.
+
+Mouse actions are based on "raw" values (Button1, Button2 and Button3)
+instead of using the pointer map.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+.PP
+Copyright \(co 1988 by Sun Microsystems, Inc. Mountain View, CA.
+.PP  
+All Rights Reserved
+.PP
+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, and that
+the names of Sun or MIT not be used in advertising or publicity pertaining to
+distribution of the software without specific prior written permission. Sun
+and M.I.T.  make no representations about the suitability of this software for
+any purpose. It is provided "as is" without any express or implied warranty.
+.PP
+SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN
+NO EVENT SHALL SUN BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.SH AUTHOR(s)
+.nf
+Jim Randell    [ XScreenSaver version ] jmr@mddjmr.fc.hp.com
+  HPLabs, Bristol
+Richard Hess   [ X11 extensions ]      {...}!uunet!cimshop!rhess
+  Consilium, Mountain View, CA
+Dave Lemke     [ X11 version ]         lemke@sun.COM
+  Sun MicroSystems, Mountain View, CA
+Martin Weiss   [ SunView version ]
+  Sun MicroSystems, Mountain View, CA
+.fi
diff --git a/hacks/noseguy.c b/hacks/noseguy.c
new file mode 100644 (file)
index 0000000..3a6542c
--- /dev/null
@@ -0,0 +1,653 @@
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@netscape.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.
+ */
+
+/* Make a little guy with a big nose and a hat wanter around the screen,
+   spewing out messages.  Derived from xnlock by Dan Heller <argv@sun.com>.
+ */
+
+#include "screenhack.h"
+#include <stdio.h>
+
+#if __STDC__
+extern FILE *popen (const char *, const char *);
+extern int pclose (FILE *);
+#endif
+
+#define Pixel unsigned long
+
+#define font_height(font)              (font->ascent + font->descent)
+#define FONT_NAME                      "-*-times-*-*-*-*-18-*-*-*-*-*-*-*"
+
+static Display *dpy;
+static Window window;
+static int Width, Height;
+static GC fg_gc, bg_gc, text_fg_gc, text_bg_gc;
+static char *words, *get_words();
+static int x, y;
+static XFontStruct *font;
+static char *def_words = "I'm out running around.";
+static void init_images(), walk(), talk();
+static int think();
+static unsigned long interval, look(); 
+static Pixmap left0, left1, right0, right1;
+static Pixmap left_front, right_front, front, down;
+
+static char *program, *orig_program, *filename, *text;
+
+#define FROM_ARGV    1
+#define FROM_PROGRAM 2
+#define FROM_FILE    3
+#define FROM_RESRC   4
+static int getwordsfrom;
+
+#define IS_MOVING  1
+#define GET_PASSWD 2
+static int state;      /* indicates states: walking or getting passwd */
+
+static void (*next_fn) ();
+
+#include "noses/nose.0.left"
+#include "noses/nose.1.left"
+#include "noses/nose.0.right"
+#include "noses/nose.1.right"
+#include "noses/nose.left.front"
+#include "noses/nose.right.front"
+#include "noses/nose.front"
+#include "noses/nose.down"
+
+static void
+init_images ()
+{
+  static Pixmap *images[] = {
+    &left0, &left1, &right0, &right1,
+    &left_front, &right_front, &front, &down
+  };
+  static unsigned char *bits[] = {
+    nose_0_left_bits, nose_1_left_bits, nose_0_right_bits,
+    nose_1_right_bits, nose_left_front_bits, nose_right_front_bits,
+    nose_front_bits, nose_down_bits
+  };
+  int i;
+
+  for (i = 0; i < sizeof (images) / sizeof (images[0]); i++)
+    if (!(*images[i] =
+         XCreatePixmapFromBitmapData(dpy, window,
+                                     (char *) bits[i], 64, 64, 1, 0, 1)))
+      {
+       fprintf (stderr, "%s: Can't load nose images", progname);
+       exit (1);
+      }
+}
+
+#define LEFT   001
+#define RIGHT  002
+#define DOWN   004
+#define UP     010
+#define FRONT  020
+#define X_INCR 3
+#define Y_INCR 2
+
+static void
+move()
+{
+    static int      length,
+                    dir;
+
+    if (!length)
+    {
+       register int    tries = 0;
+       dir = 0;
+       if ((random() & 1) && think())
+       {
+           talk(0);            /* sets timeout to itself */
+           return;
+       }
+       if (!(random() % 3) && (interval = look()))
+       {
+           next_fn = move;
+           return;
+       }
+       interval = 20 + random() % 100;
+       do
+       {
+           if (!tries)
+               length = Width / 100 + random() % 90, tries = 8;
+           else
+               tries--;
+           switch (random() % 8)
+           {
+           case 0:
+               if (x - X_INCR * length >= 5)
+                   dir = LEFT;
+               break;
+           case 1:
+               if (x + X_INCR * length <= Width - 70)
+                   dir = RIGHT;
+               break;
+           case 2:
+               if (y - (Y_INCR * length) >= 5)
+                   dir = UP, interval = 40;
+               break;
+           case 3:
+               if (y + Y_INCR * length <= Height - 70)
+                   dir = DOWN, interval = 20;
+               break;
+           case 4:
+               if (x - X_INCR * length >= 5 && y - (Y_INCR * length) >= 5)
+                   dir = (LEFT | UP);
+               break;
+           case 5:
+               if (x + X_INCR * length <= Width - 70 &&
+                   y - Y_INCR * length >= 5)
+                   dir = (RIGHT | UP);
+               break;
+           case 6:
+               if (x - X_INCR * length >= 5 &&
+                   y + Y_INCR * length <= Height - 70)
+                   dir = (LEFT | DOWN);
+               break;
+           case 7:
+               if (x + X_INCR * length <= Width - 70 &&
+                   y + Y_INCR * length <= Height - 70)
+                   dir = (RIGHT | DOWN);
+               break;
+           default:
+               /* No Defaults */
+               break;
+           }
+       } while (!dir);
+    }
+    walk(dir);
+    --length;
+    next_fn = move;
+}
+
+static void
+walk(dir)
+    register int    dir;
+{
+    register int    incr = 0;
+    static int      lastdir;
+    static int      up = 1;
+    static Pixmap   frame;
+
+    if (dir & (LEFT | RIGHT))
+    {                          /* left/right movement (mabye up/down too) */
+       up = -up;               /* bouncing effect (even if hit a wall) */
+       if (dir & LEFT)
+       {
+           incr = X_INCR;
+           frame = (up < 0) ? left0 : left1;
+       }
+       else
+       {
+           incr = -X_INCR;
+           frame = (up < 0) ? right0 : right1;
+       }
+       if ((lastdir == FRONT || lastdir == DOWN) && dir & UP)
+       {
+
+           /*
+            * workaround silly bug that leaves screen dust when guy is
+            * facing forward or down and moves up-left/right.
+            */
+           XCopyPlane(dpy, frame, window, fg_gc, 0, 0, 64, 64, x, y, 1L);
+           XFlush(dpy);
+       }
+       /* note that maybe neither UP nor DOWN is set! */
+       if (dir & UP && y > Y_INCR)
+           y -= Y_INCR;
+       else if (dir & DOWN && y < Height - 64)
+           y += Y_INCR;
+    }
+    /* Explicit up/down movement only (no left/right) */
+    else if (dir == UP)
+       XCopyPlane(dpy, front, window, fg_gc,
+                  0, 0, 64, 64, x, y -= Y_INCR, 1L);
+    else if (dir == DOWN)
+       XCopyPlane(dpy, down, window, fg_gc,
+                  0, 0, 64, 64, x, y += Y_INCR, 1L);
+    else if (dir == FRONT && frame != front)
+    {
+       if (up > 0)
+           up = -up;
+       if (lastdir & LEFT)
+           frame = left_front;
+       else if (lastdir & RIGHT)
+           frame = right_front;
+       else
+           frame = front;
+       XCopyPlane(dpy, frame, window, fg_gc, 0, 0, 64, 64, x, y, 1L);
+    }
+    if (dir & LEFT)
+       while (--incr >= 0)
+       {
+           XCopyPlane(dpy, frame, window, fg_gc,
+                      0, 0, 64, 64, --x, y + up, 1L);
+           XFlush(dpy);
+       }
+    else if (dir & RIGHT)
+       while (++incr <= 0)
+       {
+           XCopyPlane(dpy, frame, window, fg_gc,
+                      0, 0, 64, 64, ++x, y + up, 1L);
+           XFlush(dpy);
+       }
+    lastdir = dir;
+}
+
+static int
+think()
+{
+    if (random() & 1)
+       walk(FRONT);
+    if (random() & 1)
+    {
+       if (getwordsfrom == FROM_PROGRAM)
+           words = get_words(0, (char **) 0);
+       return 1;
+    }
+    return 0;
+}
+
+#define MAXLINES 40
+
+static void
+talk(force_erase)
+    int             force_erase;
+{
+    int             width = 0,
+                    height,
+                    Z,
+                    total = 0;
+    static int      X,
+                    Y,
+                    talking;
+    static struct
+    {
+       int             x,
+                       y,
+                       width,
+                       height;
+    }               s_rect;
+    register char  *p,
+                   *p2;
+    char            buf[BUFSIZ],
+                    args[MAXLINES][256];
+
+    /* clear what we've written */
+    if (talking || force_erase)
+    {
+       if (!talking)
+           return;
+       XFillRectangle(dpy, window, bg_gc, s_rect.x - 5, s_rect.y - 5,
+                      s_rect.width + 10, s_rect.height + 10);
+       talking = 0;
+       if (!force_erase)
+         next_fn = move;
+       interval = 0;
+       {
+         /* might as well check the window for size changes now... */
+         XWindowAttributes xgwa;
+         XGetWindowAttributes (dpy, window, &xgwa);
+         Width = xgwa.width + 2;
+         Height = xgwa.height + 2;
+       }
+       return;
+    }
+    talking = 1;
+    walk(FRONT);
+    p = strcpy(buf, words);
+
+    if (!(p2 = index(p, '\n')) || !p2[1])
+      {
+       total = strlen (words);
+       strcpy (args[0], words);
+       width = XTextWidth(font, words, total);
+       height = 0;
+      }
+    else
+      /* p2 now points to the first '\n' */
+      for (height = 0; p; height++)
+       {
+         int             w;
+         *p2 = 0;
+         if ((w = XTextWidth(font, p, p2 - p)) > width)
+           width = w;
+         total += p2 - p;      /* total chars; count to determine reading
+                                * time */
+         (void) strcpy(args[height], p);
+         if (height == MAXLINES - 1)
+           {
+             puts("Message too long!");
+             break;
+           }
+         p = p2 + 1;
+         if (!(p2 = index(p, '\n')))
+           break;
+       }
+    height++;
+
+    /*
+     * Figure out the height and width in pixels (height, width) extend the
+     * new box by 15 pixels on the sides (30 total) top and bottom.
+     */
+    s_rect.width = width + 30;
+    s_rect.height = height * font_height(font) + 30;
+    if (x - s_rect.width - 10 < 5)
+       s_rect.x = 5;
+    else if ((s_rect.x = x + 32 - (s_rect.width + 15) / 2)
+            + s_rect.width + 15 > Width - 5)
+       s_rect.x = Width - 15 - s_rect.width;
+    if (y - s_rect.height - 10 < 5)
+       s_rect.y = y + 64 + 5;
+    else
+       s_rect.y = y - 5 - s_rect.height;
+
+    XFillRectangle(dpy, window, text_bg_gc,
+        s_rect.x, s_rect.y, s_rect.width, s_rect.height);
+
+    /* make a box that's 5 pixels thick. Then add a thin box inside it */
+    XSetLineAttributes(dpy, text_fg_gc, 5, 0, 0, 0);
+    XDrawRectangle(dpy, window, text_fg_gc,
+                  s_rect.x, s_rect.y, s_rect.width - 1, s_rect.height - 1);
+    XSetLineAttributes(dpy, text_fg_gc, 0, 0, 0, 0);
+    XDrawRectangle(dpy, window, text_fg_gc,
+        s_rect.x + 7, s_rect.y + 7, s_rect.width - 15, s_rect.height - 15);
+
+    X = 15;
+    Y = 15 + font_height(font);
+
+    /* now print each string in reverse order (start at bottom of box) */
+    for (Z = 0; Z < height; Z++)
+    {
+       XDrawString(dpy, window, text_fg_gc, s_rect.x + X, s_rect.y + Y,
+                   args[Z], strlen(args[Z]));
+       Y += font_height(font);
+    }
+    interval = (total / 15) * 1000;
+    if (interval < 2000) interval = 2000;
+    next_fn = talk;
+}
+
+static unsigned long
+look()
+{
+    if (random() % 3)
+    {
+       XCopyPlane(dpy, (random() & 1) ? down : front, window, fg_gc,
+                  0, 0, 64, 64, x, y, 1L);
+       return 1000L;
+    }
+    if (!(random() % 5))
+       return 0;
+    if (random() % 3)
+    {
+       XCopyPlane(dpy, (random() & 1) ? left_front : right_front,
+                  window, fg_gc, 0, 0, 64, 64, x, y, 1L);
+       return 1000L;
+    }
+    if (!(random() % 5))
+       return 0;
+    XCopyPlane(dpy, (random() & 1) ? left0 : right0, window, fg_gc,
+              0, 0, 64, 64, x, y, 1L);
+    return 1000L;
+}
+
+
+static void
+init_words()
+{
+  char *mode = get_string_resource ("mode", "Mode");
+
+  program = get_string_resource ("program", "Program");
+  filename = get_string_resource ("filename", "Filename");
+  text = get_string_resource ("text", "Text");
+
+  if (program) /* get stderr on stdout, so it shows up on the window */
+    {
+      orig_program = program;
+      program = (char *) malloc (strlen (program) + 10);
+      strcpy (program, "( ");
+      strcat (program, orig_program);
+      strcat (program, " ) 2>&1");
+    }
+
+  if (!mode || !strcmp (mode, "program"))
+    getwordsfrom = FROM_PROGRAM;
+  else if (!strcmp (mode, "file"))
+    getwordsfrom = FROM_FILE;
+  else if (!strcmp (mode, "string"))
+    getwordsfrom = FROM_RESRC;
+  else
+    {
+      fprintf (stderr,
+              "%s: mode must be program, file, or string, not %s\n",
+              progname, mode);
+      exit (1);
+    }
+
+  if (getwordsfrom == FROM_PROGRAM && !program)
+    {
+      fprintf (stderr, "%s: no program specified.\n", progname);
+      exit (1);
+    }
+  if (getwordsfrom == FROM_FILE && !filename)
+    {
+      fprintf (stderr, "%s: no file specified.\n", progname);
+      exit (1);
+    }
+
+  words = get_words(); 
+}
+
+static int first_time = 1;
+
+static char *
+get_words()
+{
+    FILE           *pp;
+    static char     buf[BUFSIZ];
+    register char  *p = buf;
+
+    buf[0] = '\0';
+
+    switch (getwordsfrom)
+    {
+    case FROM_PROGRAM:
+       if ((pp = popen(program, "r")))
+       {
+           while (fgets(p, sizeof(buf) - strlen(buf), pp))
+           {
+               if (strlen(buf) + 1 < sizeof(buf))
+                   p = buf + strlen(buf);
+               else
+                   break;
+           }
+           (void) pclose(pp);
+           if (! buf[0])
+             sprintf (buf, "\"%s\" produced no output!", orig_program);
+           else if (!first_time &&
+                    !strcmp (buf, "sh: fortune: not found\n"))
+             switch (random () % 20)
+               {
+               case 1: strcat (buf, "( Get with the program, bub. )\n");
+                 break;
+               case 2: strcat (buf,
+                 "( I blow my nose at you, you silly person! ) \n"); break;
+               case 3: strcat (buf,
+                 "\nThe resource you want to\nset is `noseguy.program'\n");
+                 break;
+               case 4:
+                 strcat(buf,"\nHelp!!  Help!!\nAAAAAAGGGGHHH!!  \n\n"); break;
+               case 5: strcpy (buf, "You have new mail.\n"); break;
+               case 6:
+                 strcat(buf,"( Hello?  Are you paying attention? )\n");break;
+               case 7:
+                 strcat (buf, "sh: what kind of fool do you take me for? \n");
+                 break;
+               }
+           first_time = 0;
+           p = buf;
+       }
+       else
+       {
+           perror(program);
+           p = def_words;
+       }
+       break;
+    case FROM_FILE:
+       if ((pp = fopen(filename, "r")))
+       {
+           while (fgets(p, sizeof(buf) - strlen(buf), pp))
+           {
+               if (strlen(buf) + 1 < sizeof(buf))
+                   p = buf + strlen(buf);
+               else
+                   break;
+           }
+           (void) fclose(pp);
+           if (! buf[0])
+             sprintf (buf, "file \"%s\" is empty!", filename);
+           p = buf;
+       }
+       else
+       {
+         sprintf (buf, "couldn't read file \"%s\"!", filename);
+         p = buf;
+       }
+       break;
+    case FROM_RESRC:
+       p = text;
+       break;
+    default:
+       p = def_words;
+       break;
+    }
+
+    if (!p || *p == '\0')
+       p = def_words;
+    return p;
+}
+
+
+\f
+char *progclass = "Noseguy";
+
+char *defaults [] = {
+  "Noseguy.background: black",         /* to placate SGI */
+  "Noseguy.foreground: white",
+  "*mode:              program",
+  "*program:           fortune -s",
+  "noseguy.font:       -*-new century schoolbook-*-r-*-*-*-180-*-*-*-*-*-*",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-mode",           ".mode",                XrmoptionSepArg, 0 },
+  { "-program",                ".program",             XrmoptionSepArg, 0 },
+  { "-text",           ".text",                XrmoptionSepArg, 0 },
+  { "-filename",       ".filename",            XrmoptionSepArg, 0 },
+  { "-font",           ".font",                XrmoptionSepArg, 0 },
+  { "-text-foreground",        ".textForeground",      XrmoptionSepArg, 0 },
+  { "-text-background",        ".textBackground",      XrmoptionSepArg, 0 }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+
+static void
+noseguy_init (d, w)
+     Display *d;
+     Window w;
+{
+  Pixel fg, bg, text_fg, text_bg;
+  XWindowAttributes xgwa;
+  Colormap cmap;
+  char *fontname = get_string_resource ("font", "Font");
+  char **list;
+  int foo, i;
+  XGCValues gcvalues;
+  dpy = d;
+  window = w;
+  XGetWindowAttributes (dpy, window, &xgwa);
+  Width = xgwa.width + 2;
+  Height = xgwa.height + 2;
+  cmap = xgwa.colormap;
+
+  init_words();
+  init_images();
+
+  if (!fontname || !(font = XLoadQueryFont(dpy, fontname)))
+    {
+       list = XListFonts(dpy, FONT_NAME, 32767, &foo);
+       for (i = 0; i < foo; i++)
+           if ((font = XLoadQueryFont(dpy, list[i])))
+               break;
+       if (!font)
+         {
+           fprintf (stderr, "%s: Can't find a large font.", progname);
+           exit (1);
+         }
+       XFreeFontNames(list);
+    }
+
+  fg = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+  bg = get_pixel_resource ("background", "Background", dpy, cmap);
+  text_fg = get_pixel_resource ("textForeground", "Foreground", dpy, cmap);
+  text_bg = get_pixel_resource ("textBackground", "Background", dpy, cmap);
+  /* notice when unspecified */
+  if (! get_string_resource ("textForeground", "Foreground"))
+    text_fg = bg;
+  if (! get_string_resource ("textBackground", "Background"))
+    text_bg = fg;
+
+  gcvalues.font = font->fid;
+  gcvalues.graphics_exposures = False;
+  gcvalues.foreground = fg;
+  gcvalues.background = bg;
+  fg_gc = XCreateGC (dpy, window,
+                    GCForeground|GCBackground|GCGraphicsExposures|GCFont,
+                    &gcvalues);
+  gcvalues.foreground = bg;
+  gcvalues.background = fg;
+  bg_gc = XCreateGC (dpy, window,
+                    GCForeground|GCBackground|GCGraphicsExposures|GCFont,
+                    &gcvalues);
+  gcvalues.foreground = text_fg;
+  gcvalues.background = text_bg;
+  text_fg_gc = XCreateGC (dpy, window,
+                         GCForeground|GCBackground|GCGraphicsExposures|GCFont,
+                         &gcvalues);
+  gcvalues.foreground = text_bg;
+  gcvalues.background = text_fg;
+  text_bg_gc = XCreateGC (dpy, window,
+                         GCForeground|GCBackground|GCGraphicsExposures|GCFont,
+                         &gcvalues);
+  x = Width / 2;
+  y = Height / 2;
+  state = IS_MOVING;
+}
+     
+void
+screenhack (d, w)
+     Display *d;
+     Window w;
+{
+  noseguy_init (d, w);
+  next_fn = move;
+  while (1)
+    {
+      next_fn (0);
+      XSync (dpy, True);
+      usleep (interval * 1000);
+    }
+}
+
diff --git a/hacks/noseguy.man b/hacks/noseguy.man
new file mode 100644 (file)
index 0000000..fe18d8d
--- /dev/null
@@ -0,0 +1,74 @@
+.TH XScreenSaver 1 "13-aug-92" "X Version 11"
+.SH NAME
+noseguy - a little guy with a big nose wanders around being witty
+.SH SYNOPSIS
+.B noseguy
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-text-foreground \fIcolor\fP] [\-text-background \fIcolor\fP] [\-font \fIfont\fP] [\-window] [\-root] [\-install] [\-visual \fIvisual\fP] [\-mode \fImode\fP] [\-program \fIprogram\fP] [\-filename \file\fP] [\-text \fItext\fP]
+.SH DESCRIPTION
+A little man with a big nose and a hat runs around spewing out messages to
+the screen.  This code (and its bitmaps) were extracted from the \fIxnlock\fP
+program.
+.SH OPTIONS
+.I noseguy
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-font \fIfont\fP
+The font used for the messages.
+.TP 8
+.B \-mode [ program | file | string ]
+In \fIprogram\fP mode, the messages are gotten by running a program.
+The program used is controlled by the \fI\-program\fP option, and 
+the \fI.program\fP resource.
+
+In \fIfilename\fP mode, the message used is the contents of a file.
+The file used is controlled by the \fI\-file\fP option, and 
+the \fI.filename\fP resource.
+
+In \fIstring\fP mode, the message is whatever was specified on the 
+command line as the \fI\-text\fP option, or in the resource database
+as the \fI.text\fP resource.
+.TP 8
+.B \-program \fIprogram\fP
+If \fImode\fP is \fIprogram\fP (the default), then this program will be
+run periodically, and its output will be the text of the messages.  The
+default program is \fI"fortune -s"\fP, but \fIyow\fP is also a good choice.
+.TP 8
+.B \-filename \fIfile\fP
+If \fImode\fP is \fIfile\fP, then the contents of this file will be used
+for all messages.
+.TP 8
+.B \-text \fIstring\fP
+If \fImode\fP is \fIstring\fP, then this text will be used for all messages.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR xnlock (1)
+.SH COPYRIGHT
+Copyright 1985, 1990 by Dan Heller <argv@sun.com>.
+.SH AUTHOR
+Dan Heller <argv@sun.com>, 1985.
+
+Ability to run standalone or with \fIxscreensaver\fP added by 
+Jamie Zawinski <jwz@netscape.com>, 13-aug-92.
diff --git a/hacks/noses/CVS/Entries b/hacks/noses/CVS/Entries
new file mode 100644 (file)
index 0000000..7c60d8f
--- /dev/null
@@ -0,0 +1,8 @@
+/nose.0.left/1.1/Fri Mar 17 18:30:19 1995 Thu Aug 25 15:04:28 1994//
+/nose.0.right/1.1/Fri Mar 17 18:30:19 1995 Thu Aug 25 15:04:29 1994//
+/nose.1.left/1.1/Fri Mar 17 18:30:20 1995 Thu Aug 25 15:04:30 1994//
+/nose.1.right/1.1/Fri Mar 17 18:30:20 1995 Thu Aug 25 15:04:31 1994//
+/nose.down/1.1/Fri Mar 17 18:30:20 1995 Thu Aug 25 15:04:32 1994//
+/nose.front/1.1/Fri Mar 17 18:30:20 1995 Thu Aug 25 15:04:33 1994//
+/nose.left.front/1.1/Fri Mar 17 18:30:20 1995 Thu Aug 25 15:04:34 1994//
+/nose.right.front/1.1/Fri Mar 17 18:30:20 1995 Thu Aug 25 15:04:35 1994//
diff --git a/hacks/noses/CVS/Repository b/hacks/noses/CVS/Repository
new file mode 100644 (file)
index 0000000..5c363df
--- /dev/null
@@ -0,0 +1 @@
+/m/src/xscreensaver/hacks/noses
diff --git a/hacks/noses/nose.0.left b/hacks/noses/nose.0.left
new file mode 100644 (file)
index 0000000..cb3d152
--- /dev/null
@@ -0,0 +1,38 @@
+#define nose_0_left_width 64
+#define nose_0_left_height 64
+static unsigned char nose_0_left_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,
+ 0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
+ 0x40,0x00,0x00,0x04,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
+ 0x08,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x20,0x00,
+ 0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0xf0,0x03,0x00,0x00,0x80,0x00,
+ 0x00,0x00,0x0e,0x0c,0x00,0x00,0x80,0x01,0x00,0x00,0x03,0x30,0x00,0x00,0x00,
+ 0x01,0x00,0x80,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x40,0x00,0xc0,0x00,0x00,
+ 0x00,0x02,0x00,0x20,0x00,0x80,0x00,0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00,
+ 0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x08,0x00,0x00,
+ 0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,
+ 0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,
+ 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,
+ 0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,
+ 0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x01,0x00,0x00,
+ 0x18,0x00,0x20,0x00,0x00,0x01,0x00,0x00,0x08,0x00,0x40,0x00,0x80,0x00,0x00,
+ 0x00,0x08,0x00,0x80,0x00,0x40,0x00,0x00,0x00,0x0c,0x00,0x00,0x01,0x20,0x00,
+ 0x00,0x00,0x04,0x00,0x00,0x06,0x18,0x00,0x00,0x00,0x06,0x00,0x00,0xf8,0x07,
+ 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x0f,0x00,0x00,0x00,
+ 0x00,0xff,0x00,0x04,0x10,0x00,0x00,0x00,0xc0,0x00,0x03,0x03,0x10,0x00,0x00,
+ 0x00,0x30,0x00,0x0c,0x01,0x20,0x00,0x00,0x00,0x08,0x00,0x98,0x00,0x20,0x00,
+ 0x00,0x00,0x0c,0x03,0x60,0x00,0x20,0x00,0x00,0x00,0xc2,0x00,0xc0,0x00,0x20,
+ 0x00,0x00,0x00,0x42,0x00,0x80,0x00,0x20,0x00,0x00,0x00,0x21,0x00,0x00,0x01,
+ 0x20,0x00,0x00,0x00,0x21,0x00,0x00,0x01,0x20,0x00,0x00,0x00,0x21,0x00,0x00,
+ 0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x01,0x00,
+ 0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x02,
+ 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x20,0x00,0x00,0x00,
+ 0x18,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x10,0x00,0x00,
+ 0x00,0xc0,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00};
diff --git a/hacks/noses/nose.0.right b/hacks/noses/nose.0.right
new file mode 100644 (file)
index 0000000..f387baa
--- /dev/null
@@ -0,0 +1,38 @@
+#define nose_0_right_width 64
+#define nose_0_right_height 64
+static unsigned char nose_0_right_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x20,0x00,
+ 0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,
+ 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,
+ 0x20,0x00,0x00,0x02,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,
+ 0x04,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x10,0x00,
+ 0x00,0xfc,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x01,0x00,0x00,0xc0,0x0f,
+ 0x00,0x00,0x80,0x01,0x00,0x00,0x30,0x70,0x00,0x00,0x80,0x00,0x00,0x00,0x0c,
+ 0xc0,0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x40,0x00,0x00,0x00,
+ 0x03,0x00,0x02,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x20,0x00,0x00,
+ 0x00,0x00,0x00,0x08,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x00,
+ 0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,
+ 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,
+ 0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,
+ 0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,
+ 0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x18,0x00,0x00,0x80,0x00,
+ 0x00,0x08,0x00,0x10,0x00,0x00,0x80,0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00,
+ 0x01,0x00,0x02,0x00,0x30,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x20,0x00,0x00,
+ 0x00,0x04,0x80,0x00,0x00,0x60,0x00,0x00,0x00,0x18,0x60,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0xe0,0x1f,0x00,0x00,0x80,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x1f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x08,0x20,0x00,0xff,0x00,0x00,0x00,0x00,0x08,0xc0,0xc0,0x00,0x03,0x00,
+ 0x00,0x00,0x04,0x80,0x30,0x00,0x0c,0x00,0x00,0x00,0x04,0x00,0x19,0x00,0x10,
+ 0x00,0x00,0x00,0x04,0x00,0x06,0xc0,0x30,0x00,0x00,0x00,0x04,0x00,0x03,0x00,
+ 0x43,0x00,0x00,0x00,0x04,0x00,0x01,0x00,0x42,0x00,0x00,0x00,0x04,0x80,0x00,
+ 0x00,0x84,0x00,0x00,0x00,0x04,0x80,0x00,0x00,0x84,0x00,0x00,0x00,0x04,0x00,
+ 0x00,0x00,0x84,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x02,
+ 0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,
+ 0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x20,0x00,0x00,
+ 0x00,0x04,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x0e,0x00,
+ 0x00,0x00,0xf0,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00};
diff --git a/hacks/noses/nose.1.left b/hacks/noses/nose.1.left
new file mode 100644 (file)
index 0000000..8a6b829
--- /dev/null
@@ -0,0 +1,38 @@
+#define nose_1_left_width 64
+#define nose_1_left_height 64
+static unsigned char nose_1_left_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,
+ 0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
+ 0x40,0x00,0x00,0x04,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
+ 0x08,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x20,0x00,
+ 0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0xf0,0x03,0x00,0x00,0x80,0x00,
+ 0x00,0x00,0x0e,0x0c,0x00,0x00,0x80,0x01,0x00,0x00,0x03,0x30,0x00,0x00,0x00,
+ 0x01,0x00,0x80,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x40,0x00,0xc0,0x00,0x00,
+ 0x00,0x02,0x00,0x20,0x00,0x80,0x00,0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00,
+ 0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x08,0x00,0x00,
+ 0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,
+ 0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,
+ 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,
+ 0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,
+ 0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x01,0x00,0x00,
+ 0x18,0x00,0x10,0x00,0x00,0x01,0x00,0x00,0x08,0x00,0x20,0x00,0x80,0x00,0x00,
+ 0x00,0x08,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x0c,0x00,0x80,0x00,0x20,0x00,
+ 0x00,0x00,0xe4,0x00,0x00,0x03,0x18,0x00,0x00,0x00,0x26,0x03,0x00,0xfc,0x07,
+ 0x00,0x00,0x00,0x12,0x0c,0x00,0x00,0xf8,0xff,0xff,0xff,0x11,0x10,0x80,0x1f,
+ 0x00,0x00,0x00,0x00,0x08,0x20,0x60,0x60,0xc0,0x07,0x00,0x00,0x04,0x40,0x10,
+ 0xc0,0x20,0x08,0x00,0x1f,0x02,0x40,0x08,0x00,0x21,0x10,0xc0,0x60,0x02,0x40,
+ 0x04,0x00,0x12,0x20,0x20,0x80,0x02,0x20,0xc2,0x00,0x14,0x40,0x18,0x00,0x03,
+ 0x20,0x22,0x00,0x0c,0x80,0x04,0x03,0x02,0x10,0x12,0x00,0x08,0x80,0x86,0x00,
+ 0x04,0x10,0x12,0x00,0x10,0x80,0x42,0x00,0x18,0x08,0x12,0x00,0x10,0x40,0x42,
+ 0x00,0x00,0x04,0x02,0x00,0x20,0x40,0x42,0x00,0x00,0x04,0x02,0x00,0x00,0x20,
+ 0x42,0x00,0x00,0x02,0x04,0x00,0x00,0x20,0x02,0x00,0x00,0x01,0x04,0x00,0x00,
+ 0x20,0x02,0x00,0x00,0x01,0x08,0x00,0x00,0x20,0x04,0x00,0x80,0x00,0x10,0x00,
+ 0x00,0x20,0x0c,0x00,0x80,0x00,0x60,0x00,0x00,0x10,0x08,0x00,0x40,0x00,0x80,
+ 0xff,0xff,0x0f,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0x0f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00};
diff --git a/hacks/noses/nose.1.right b/hacks/noses/nose.1.right
new file mode 100644 (file)
index 0000000..f7c8962
--- /dev/null
@@ -0,0 +1,38 @@
+#define nose_1_right_width 64
+#define nose_1_right_height 64
+static unsigned char nose_1_right_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x20,0x00,
+ 0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,
+ 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,
+ 0x20,0x00,0x00,0x02,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,
+ 0x04,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x10,0x00,
+ 0x00,0xfc,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x01,0x00,0x00,0xc0,0x0f,
+ 0x00,0x00,0x80,0x01,0x00,0x00,0x30,0x70,0x00,0x00,0x80,0x00,0x00,0x00,0x0c,
+ 0xc0,0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x40,0x00,0x00,0x00,
+ 0x03,0x00,0x02,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x20,0x00,0x00,
+ 0x00,0x00,0x00,0x08,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x00,
+ 0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,
+ 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,
+ 0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,
+ 0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,
+ 0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x18,0x00,0x00,0x80,0x00,
+ 0x00,0x08,0x00,0x10,0x00,0x00,0x80,0x00,0x00,0x08,0x00,0x10,0x00,0x00,0x00,
+ 0x01,0x00,0x04,0x00,0x30,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x27,0x00,0x00,
+ 0x00,0x04,0x00,0x01,0xc0,0x64,0x00,0x00,0x00,0x18,0xc0,0x00,0x30,0x48,0x00,
+ 0x00,0x00,0xe0,0x3f,0x00,0x08,0x88,0xff,0xff,0xff,0x1f,0x00,0x00,0x04,0x10,
+ 0x00,0x00,0x00,0x00,0xf8,0x01,0x02,0x20,0x00,0x00,0xe0,0x03,0x06,0x06,0x02,
+ 0x40,0xf8,0x00,0x10,0x04,0x03,0x08,0x02,0x40,0x06,0x03,0x08,0x84,0x00,0x10,
+ 0x04,0x40,0x01,0x04,0x04,0x48,0x00,0x20,0x04,0xc0,0x00,0x18,0x02,0x28,0x00,
+ 0x43,0x08,0x40,0xc0,0x20,0x01,0x30,0x00,0x44,0x08,0x20,0x00,0x61,0x01,0x10,
+ 0x00,0x48,0x10,0x18,0x00,0x42,0x01,0x08,0x00,0x48,0x20,0x00,0x00,0x42,0x02,
+ 0x08,0x00,0x48,0x20,0x00,0x00,0x42,0x02,0x04,0x00,0x40,0x40,0x00,0x00,0x42,
+ 0x04,0x00,0x00,0x40,0x80,0x00,0x00,0x40,0x04,0x00,0x00,0x20,0x80,0x00,0x00,
+ 0x40,0x04,0x00,0x00,0x20,0x00,0x01,0x00,0x20,0x04,0x00,0x00,0x10,0x00,0x01,
+ 0x00,0x30,0x04,0x00,0x00,0x08,0x00,0x02,0x00,0x10,0x08,0x00,0x00,0x06,0x00,
+ 0x0c,0x00,0x0c,0xf0,0xff,0xff,0x01,0x00,0xf0,0xff,0x03,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00};
diff --git a/hacks/noses/nose.down b/hacks/noses/nose.down
new file mode 100644 (file)
index 0000000..e8bdba4
--- /dev/null
@@ -0,0 +1,38 @@
+#define nose_down_width 64
+#define nose_down_height 64
+static unsigned char nose_down_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0xff,0x01,0x00,0x00,0x00,0x00,0xc0,0x03,0x00,0x1e,0x00,
+ 0x00,0x00,0x00,0x38,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,
+ 0x03,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x40,0x00,0x00,0x00,
+ 0x00,0x08,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x10,0x00,0x80,
+ 0x1f,0x00,0x40,0x00,0x00,0x08,0x00,0x60,0x60,0x00,0x80,0x00,0x00,0x08,0x00,
+ 0x10,0x80,0x00,0x80,0x00,0x00,0x04,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x04,
+ 0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x18,0x80,0x01,0x00,0x02,0x00,
+ 0x02,0x00,0x68,0x60,0x01,0x00,0x02,0x00,0x02,0x00,0x88,0x1f,0x01,0x00,0x02,
+ 0x00,0x02,0x00,0x08,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x10,0x80,0x00,0x00,
+ 0x03,0x00,0x06,0x00,0x60,0x60,0x00,0x80,0x02,0x00,0x0c,0x00,0x80,0x1f,0x00,
+ 0x40,0x01,0x00,0x14,0x00,0x00,0x00,0x00,0x20,0x01,0x00,0x28,0x00,0x00,0x00,
+ 0x00,0x90,0x00,0x00,0x50,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0xa0,0x01,0x00,
+ 0x00,0x00,0x26,0x00,0x00,0x40,0x1e,0x00,0x00,0xc0,0x11,0x00,0x00,0x80,0xe1,
+ 0x03,0x00,0x3c,0x0c,0x00,0x00,0x00,0x0e,0xfc,0xff,0x83,0x03,0x00,0x00,0x00,
+ 0xf0,0x01,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x0f,0x00,0x00,0x00,
+ 0x00,0x80,0x03,0x00,0x0c,0x00,0x00,0x00,0x00,0x80,0x02,0x00,0x14,0x00,0x00,
+ 0x00,0x00,0x60,0x04,0x00,0x12,0x00,0x00,0xc0,0x7f,0x10,0x04,0x00,0x22,0xe0,
+ 0x01,0x70,0xc0,0x18,0x08,0x00,0x61,0x1c,0x06,0x10,0x00,0x0f,0x30,0xc0,0x80,
+ 0x07,0x08,0x08,0x00,0x06,0xc0,0x3f,0x80,0x01,0x08,0x08,0x00,0x18,0x00,0x02,
+ 0xc0,0x00,0x10,0x04,0x00,0x30,0x00,0x05,0x30,0x00,0x10,0x04,0x00,0x00,0x80,
+ 0x08,0x18,0x00,0x20,0x04,0x00,0x00,0x80,0x08,0x00,0x00,0x20,0x04,0x00,0x00,
+ 0x40,0x10,0x00,0x00,0x20,0x24,0x00,0x00,0x40,0x10,0x00,0x00,0x22,0x24,0x00,
+ 0x00,0x40,0x10,0x00,0x00,0x22,0x44,0x00,0x00,0x40,0x10,0x00,0x00,0x11,0x84,
+ 0x01,0x00,0xc0,0x18,0x00,0xc0,0x10,0x08,0x00,0x00,0x80,0x08,0x00,0x00,0x08,
+ 0x30,0x00,0x00,0x80,0x08,0x00,0x00,0x04,0xe0,0xff,0xff,0xff,0xf8,0xff,0xff,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00};
diff --git a/hacks/noses/nose.front b/hacks/noses/nose.front
new file mode 100644 (file)
index 0000000..64b8201
--- /dev/null
@@ -0,0 +1,38 @@
+#define nose_front_width 64
+#define nose_front_height 64
+static unsigned char nose_front_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,
+ 0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
+ 0x40,0x00,0x00,0x04,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
+ 0x08,0x00,0xc0,0x1f,0x00,0x20,0x00,0x00,0x08,0x00,0x30,0x60,0x00,0x20,0x00,
+ 0x00,0xf8,0xff,0x0f,0x80,0xff,0x3f,0x00,0x00,0x00,0x02,0x02,0x00,0x82,0x00,
+ 0x00,0x00,0x00,0x03,0x01,0x00,0x84,0x01,0x00,0x00,0x00,0x81,0x00,0x00,0x08,
+ 0x01,0x00,0x00,0x80,0x80,0x00,0x00,0x08,0x02,0x00,0x00,0x80,0x40,0x00,0x00,
+ 0x10,0x02,0x00,0x00,0x40,0x40,0x00,0x00,0x10,0x04,0x00,0x00,0x40,0x20,0x00,
+ 0x00,0x20,0x04,0x00,0x00,0x60,0x20,0x00,0x00,0x20,0x0c,0x00,0x00,0x20,0x20,
+ 0x00,0x00,0x20,0x08,0x00,0x00,0x20,0x20,0x00,0x00,0x20,0x08,0x00,0x00,0x10,
+ 0x20,0x00,0x00,0x20,0x10,0x00,0x00,0x10,0x20,0x00,0x00,0x20,0x10,0x00,0x00,
+ 0x10,0x20,0x00,0x00,0x20,0x10,0x00,0x00,0x10,0x40,0x00,0x00,0x10,0x10,0x00,
+ 0x00,0x10,0x40,0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x80,0x00,0x00,0x08,0x10,
+ 0x00,0x00,0x10,0x80,0x00,0x00,0x08,0x10,0x00,0x00,0x30,0x00,0x01,0x00,0x04,
+ 0x18,0x00,0x00,0x20,0x00,0x02,0x00,0x02,0x08,0x00,0x00,0x20,0x00,0x0c,0x80,
+ 0x01,0x08,0x00,0x00,0x60,0x00,0x30,0x60,0x00,0x0c,0x00,0x00,0x40,0x00,0xc0,
+ 0x1f,0x00,0x04,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x01,
+ 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0f,0xc0,0x0f,0x00,0x00,0x00,
+ 0x00,0x40,0x10,0x20,0x10,0x00,0x00,0x00,0x00,0x20,0x60,0x30,0x20,0x00,0x00,
+ 0x00,0x00,0x20,0xc0,0x18,0x20,0x00,0x00,0xc0,0x7f,0x10,0x80,0x0d,0x40,0xe0,
+ 0x01,0x70,0xc0,0x18,0x00,0x05,0x40,0x1c,0x06,0x10,0x00,0x0f,0x00,0x05,0x80,
+ 0x07,0x08,0x08,0x00,0x06,0x00,0x05,0x80,0x01,0x08,0x08,0x00,0x18,0x00,0x05,
+ 0xc0,0x00,0x10,0x04,0x00,0x30,0x00,0x05,0x30,0x00,0x10,0x04,0x00,0x00,0x80,
+ 0x08,0x18,0x00,0x20,0x04,0x00,0x00,0x80,0x08,0x00,0x00,0x20,0x04,0x00,0x00,
+ 0x40,0x10,0x00,0x00,0x20,0x24,0x00,0x00,0x40,0x10,0x00,0x00,0x22,0x24,0x00,
+ 0x00,0x40,0x10,0x00,0x00,0x22,0x44,0x00,0x00,0x40,0x10,0x00,0x00,0x11,0x84,
+ 0x01,0x00,0xc0,0x18,0x00,0xc0,0x10,0x08,0x00,0x00,0x80,0x08,0x00,0x00,0x08,
+ 0x30,0x00,0x00,0x80,0x08,0x00,0x00,0x04,0xe0,0xff,0xff,0xff,0xf8,0xff,0xff,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00};
diff --git a/hacks/noses/nose.left.front b/hacks/noses/nose.left.front
new file mode 100644 (file)
index 0000000..3a871ea
--- /dev/null
@@ -0,0 +1,38 @@
+#define nose_left_front_width 64
+#define nose_left_front_height 64
+static unsigned char nose_left_front_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,
+ 0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
+ 0x40,0x00,0x00,0x04,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
+ 0x08,0x00,0xe0,0x0f,0x00,0x20,0x00,0x00,0x08,0x00,0x18,0x30,0x00,0x20,0x00,
+ 0x00,0xf8,0xff,0x07,0xc0,0xff,0x3f,0x00,0x00,0x00,0x02,0x01,0x00,0x81,0x00,
+ 0x00,0x00,0x00,0x83,0x00,0x00,0x82,0x01,0x00,0x00,0x00,0x41,0x00,0x00,0x04,
+ 0x01,0x00,0x00,0x80,0x40,0x00,0x00,0x04,0x02,0x00,0x00,0x80,0x20,0x00,0x00,
+ 0x08,0x02,0x00,0x00,0x40,0x20,0x00,0x00,0x08,0x04,0x00,0x00,0x40,0x10,0x00,
+ 0x00,0x10,0x04,0x00,0x00,0x60,0x10,0x00,0x00,0x10,0x0c,0x00,0x00,0x20,0x10,
+ 0x00,0x00,0x10,0x08,0x00,0x00,0x30,0x10,0x00,0x00,0x10,0x08,0x00,0x00,0x10,
+ 0x10,0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x10,0x00,0x00,
+ 0x10,0x10,0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x20,0x00,0x00,0x08,0x10,0x00,
+ 0x00,0x10,0x20,0x00,0x00,0x08,0x10,0x00,0x00,0x10,0x40,0x00,0x00,0x04,0x10,
+ 0x00,0x00,0x30,0x40,0x00,0x00,0x04,0x10,0x00,0x00,0x20,0x80,0x00,0x00,0x02,
+ 0x18,0x00,0x00,0x20,0x00,0x01,0x00,0x01,0x08,0x00,0x00,0x60,0x00,0x06,0xc0,
+ 0x00,0x08,0x00,0x00,0x80,0x00,0x18,0x30,0x00,0x0c,0x00,0x00,0x80,0x00,0xe0,
+ 0x0f,0x00,0x04,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x01,
+ 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x0f,0x00,0x00,0x00,
+ 0x00,0xff,0x00,0x04,0x10,0x00,0x00,0x00,0xe0,0x00,0x07,0x02,0x10,0x00,0x00,
+ 0x00,0x30,0x00,0x8c,0x01,0x20,0x00,0x00,0x00,0x0c,0x00,0x90,0x00,0x20,0x00,
+ 0x00,0x00,0x04,0x03,0x60,0x00,0x20,0x00,0x00,0x00,0xc2,0x00,0xc0,0x00,0x20,
+ 0x00,0x00,0x00,0x42,0x00,0x00,0x01,0x20,0x00,0x00,0x00,0x21,0x00,0x00,0x02,
+ 0x20,0x00,0x00,0x00,0x21,0x00,0x00,0x06,0x20,0x00,0x00,0x00,0x21,0x00,0x00,
+ 0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x03,0x00,
+ 0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x02,
+ 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x20,0x00,0x00,0x00,
+ 0x18,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x10,0x00,0x00,
+ 0x00,0xc0,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00};
diff --git a/hacks/noses/nose.right.front b/hacks/noses/nose.right.front
new file mode 100644 (file)
index 0000000..f821417
--- /dev/null
@@ -0,0 +1,38 @@
+#define nose_right_front_width 64
+#define nose_right_front_height 64
+static unsigned char nose_right_front_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x20,0x00,
+ 0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,
+ 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,
+ 0x20,0x00,0x00,0x02,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,
+ 0x04,0x00,0xf0,0x07,0x00,0x10,0x00,0x00,0x04,0x00,0x0c,0x18,0x00,0x10,0x00,
+ 0x00,0xfc,0xff,0x03,0xe0,0xff,0x1f,0x00,0x00,0x00,0x81,0x00,0x80,0x40,0x00,
+ 0x00,0x00,0x80,0x41,0x00,0x00,0xc1,0x00,0x00,0x00,0x80,0x20,0x00,0x00,0x82,
+ 0x00,0x00,0x00,0x40,0x20,0x00,0x00,0x02,0x01,0x00,0x00,0x40,0x10,0x00,0x00,
+ 0x04,0x01,0x00,0x00,0x20,0x10,0x00,0x00,0x04,0x02,0x00,0x00,0x20,0x08,0x00,
+ 0x00,0x08,0x02,0x00,0x00,0x30,0x08,0x00,0x00,0x08,0x06,0x00,0x00,0x10,0x08,
+ 0x00,0x00,0x08,0x04,0x00,0x00,0x10,0x08,0x00,0x00,0x08,0x0c,0x00,0x00,0x08,
+ 0x08,0x00,0x00,0x08,0x08,0x00,0x00,0x08,0x08,0x00,0x00,0x08,0x08,0x00,0x00,
+ 0x08,0x08,0x00,0x00,0x08,0x08,0x00,0x00,0x08,0x10,0x00,0x00,0x04,0x08,0x00,
+ 0x00,0x08,0x10,0x00,0x00,0x04,0x08,0x00,0x00,0x08,0x20,0x00,0x00,0x02,0x08,
+ 0x00,0x00,0x08,0x20,0x00,0x00,0x02,0x0c,0x00,0x00,0x18,0x40,0x00,0x00,0x01,
+ 0x04,0x00,0x00,0x10,0x80,0x00,0x80,0x00,0x04,0x00,0x00,0x10,0x00,0x03,0x60,
+ 0x00,0x06,0x00,0x00,0x30,0x00,0x0c,0x18,0x00,0x01,0x00,0x00,0x20,0x00,0xf0,
+ 0x07,0x00,0x01,0x00,0x00,0x60,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x80,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x1f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x08,0x20,0x00,0xff,0x00,0x00,0x00,0x00,0x08,0x40,0xe0,0x00,0x07,0x00,
+ 0x00,0x00,0x04,0x80,0x31,0x00,0x0c,0x00,0x00,0x00,0x04,0x00,0x09,0x00,0x30,
+ 0x00,0x00,0x00,0x04,0x00,0x06,0xc0,0x20,0x00,0x00,0x00,0x04,0x00,0x03,0x00,
+ 0x43,0x00,0x00,0x00,0x04,0x80,0x00,0x00,0x42,0x00,0x00,0x00,0x04,0x40,0x00,
+ 0x00,0x84,0x00,0x00,0x00,0x04,0x60,0x00,0x00,0x84,0x00,0x00,0x00,0x04,0x00,
+ 0x00,0x00,0x84,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x02,
+ 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,
+ 0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x20,0x00,0x00,
+ 0x00,0x04,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x0e,0x00,
+ 0x00,0x00,0xf0,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00};
diff --git a/hacks/pedal.c b/hacks/pedal.c
new file mode 100644 (file)
index 0000000..8cde8d5
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ * pedal
+ *
+ * Based on a program for some old PDP-11 Graphics Display Processors
+ * at CMU.
+ *
+ * X version by
+ *
+ *  Dale Moore  <Dale.Moore@cs.cmu.edu>
+ *  24-Jun-1994
+ *
+ *  Copyright \(co 1994, by Carnegie Mellon University.  Permission to use,
+ *  copy, modify, distribute, and sell this software and its documentation
+ *  for any purpose is hereby granted without fee, provided fnord 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 fnord this software
+ *  for any purpose.  It is provided "as is" without express or implied
+ *  warranty.
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include "screenhack.h"
+
+/* If MAXLINES is too big, we might not be able to get it
+ * to the X server in the 2byte length field. Must be less
+ * than 16k
+ */
+#define MAXLINES (16 * 1024)
+#define MAXPOINTS MAXLINES
+XPoint *points;
+
+/* 
+ * If the pedal has only this many lines, it must be ugly and we dont
+ * want to see it.
+ */
+#define MINLINES 7
+
+static int sizex, sizey;
+static int delay;
+static int fadedelay;
+static int maxlines;
+static GC gc;
+static XColor foreground, background;
+static Colormap cmap;
+
+static Bool fade_p;
+
+
+/*
+ * Routine (Macro actually)
+ *   mysin
+ * Description:
+ *   Assume that degrees is .. oh 360... meaning that
+ *   there are 360 degress in a circle.  Then this function
+ *   would return the sin of the angle in degrees.  But lets
+ *   say that they are really big degrees, with 4 big degrees
+ *   the same as one regular degree.  Then this routine
+ *   would be called mysin(t, 90) and would return sin(t degrees * 4)
+ */
+#define mysin(t, degrees) sin(t * 2 * M_PI / (degrees))
+#define mycos(t, degrees) cos(t * 2 * M_PI / (degrees))
+
+/*
+ * Macro:
+ *   rand_range
+ * Description:
+ *   Return a random number between a inclusive  and b exclusive.
+ *    rand (3, 6) returns 3 or 4 or 5, but not 6.
+ */
+#define rand_range(a, b) (a + random() % (b - a))
+
+
+static int gcd (m, n)
+    int m;
+    int n;
+/* 
+ * Greatest Common Divisor (also Greates common factor).
+ */
+{
+    int r;
+
+    for (;;) {
+        r = m % n;
+        if (r == 0) return (n);
+        m = n;
+        n = r;
+    }
+}
+
+static int numlines (a, b, d)
+    int a;
+    int b;
+    int d;
+/*
+ * Description:
+ *
+ *      Given parameters a and b, how many lines will we have to draw?
+ *
+ * Algorithm:
+ *
+ *      This algorithm assumes that r = sin (theta * a), where we
+ *      evaluate theta on multiples of b.
+ *
+ *      LCM (i, j) = i * j / GCD (i, j);
+ *
+ *      So, at LCM (b, 360) we start over again.  But since we
+ *      got to LCM (b, 360) by steps of b, the number of lines is
+ *      LCM (b, 360) / b.
+ *
+ *      If a is odd, then at 180 we cross over and start the
+ *      negative.  Someone should write up an elegant way of proving
+ *      this.  Why?  Because I'm not convinced of it myself. 
+ *
+ */
+{
+#define odd(x) (x & 1)
+#define even(x) (!odd(x))
+    if ( odd(a) && odd(b) && even(d)) d /= 2;
+    return  (d / gcd (d, b));
+#undef odd
+}
+
+static int
+compute_pedal(points, maxpoints)
+XPoint *points;
+int maxpoints;
+/*
+ * Description:
+ *
+ *    Basically, it's combination spirograph and string art.
+ *    Instead of doing lines, we just use a complex polygon,
+ *    and use an even/odd rule for filling in between.
+ *
+ *    The spirograph, in mathematical terms is a polar
+ *    plot of the form r = sin (theta * c);
+ *    The string art of this is that we evaluate that
+ *    function only on certain multiples of theta.  That is
+ *    we let theta advance in some random increment.  And then
+ *    we draw a straight line between those two adjacent points.
+ *
+ *    Eventually, the lines will start repeating themselves
+ *    if we've evaluated theta on some rational portion of the
+ *    whole.
+ *
+ *    The number of lines generated is limited to the
+ *    ratio of the increment we put on theta to the whole.
+ *    If we say that there are 360 degrees in a circle, then we
+ *    will never have more than 360 lines.   
+ *
+ * Return:
+ *
+ *    The number of points.
+ *
+ */
+{
+    int a, b, d;  /* These describe a unique pedal */
+
+    double r;
+    int theta = 0;
+    XPoint *pp = points;
+    int count;
+    int numpoints;
+
+    /* Just to make sure that this division is not done inside the loop */
+    int h_width = sizex / 2, h_height = sizey / 2 ;
+
+    for (;;) {
+       d = rand_range (MINLINES, maxlines);
+
+       a = rand_range (1, d);
+       b = rand_range (1, d);
+       numpoints = numlines(a, b, d);
+       if (numpoints > MINLINES) break;
+    }
+
+    /* it might be nice to try to move as much sin and cos computing
+     * (or at least the argument computing) out of the loop.
+     */
+    for (count = numpoints; count-- ; )
+    {
+        r = mysin (theta * a, d);
+
+        /* Convert from polar to cartesian coordinates */
+       /* We could round the results, but coercing seems just fine */
+        pp->x = mysin (theta, d) * r * h_width  + h_width;
+        pp->y = mycos (theta, d) * r * h_height + h_height;
+
+        /* Advance index into array */
+        pp++;
+
+        /* Advance theta */
+        theta += b;
+        theta %= d;
+    }
+
+    return(numpoints);
+}
+
+static void
+init_pedal (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  XGCValues gcv;
+  XWindowAttributes xgwa;
+
+  fade_p = !mono_p;
+
+  delay = get_integer_resource ("delay", "Integer");
+  if (delay < 0) delay = 0;
+
+  fadedelay = get_integer_resource ("fadedelay", "Integer");
+  if (fadedelay < 0) fadedelay = 0;
+
+  maxlines = get_integer_resource ("maxlines", "Integer");
+  if (maxlines < MINLINES) maxlines = MINLINES;
+  else if (maxlines > MAXLINES) maxlines = MAXLINES;
+
+  points = (XPoint *)malloc(sizeof(XPoint) * maxlines);
+
+  XGetWindowAttributes (dpy, window, &xgwa);
+  sizex = xgwa.width;
+  sizey = xgwa.height;
+
+  if ((xgwa.visual->class != GrayScale) && (xgwa.visual->class != PseudoColor))
+    fade_p = False;
+
+  cmap = xgwa.colormap;
+
+  gcv.function = GXcopy;
+  gcv.subwindow_mode = IncludeInferiors;
+  gcv.foreground = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+  gcv.background = get_pixel_resource ("background", "Background", dpy, cmap);
+  gc = XCreateGC (
+       dpy,
+       window,
+       GCForeground | GCBackground |GCFunction | GCSubwindowMode ,
+       &gcv);
+
+  if (fade_p)
+  {
+      int status;
+      foreground.pixel = gcv.foreground;
+      XQueryColor (dpy, cmap, &foreground);
+
+      status = XAllocColorCells (
+                       dpy,
+                       cmap,
+                       0,
+                       NULL,
+                       0,
+                       &foreground.pixel,
+                       1);
+      if (status)
+      {
+         XStoreColor ( dpy, cmap, &foreground);
+         XSetForeground (dpy, gc, foreground.pixel);
+
+         background.pixel = gcv.background;
+         XQueryColor (dpy, cmap, &background);
+      }
+      else
+      {
+         /* If we cant allocate a color cell, then just forget the
+           * whole fade business.
+           */
+         fade_p = False;
+      }
+  }
+}
+
+static void
+fade_foreground (dpy, cmap, from, to, steps)
+    Display *dpy;
+    Colormap cmap;
+    XColor from;
+    XColor to;
+    int steps;
+/*
+ * This routine assumes that we have a writeable colormap.
+ * That means that the default colormap is not full, and that
+ * the visual class is PseudoColor or GrayScale.
+ */
+{
+    int i;
+    XColor inbetween;
+    int udelay = fadedelay / (steps + 1);
+
+    inbetween = foreground;
+    for (i = 0; i <= steps; i++ )
+    {
+      inbetween.red   = from.red   + (to.red   - from.red)   * i / steps ;
+      inbetween.green = from.green + (to.green - from.green) * i / steps ;
+      inbetween.blue  = from.blue  + (to.blue  - from.blue)  * i / steps ;
+      XStoreColor (dpy, cmap, &inbetween);
+      /* If we don't sync, these can bunch up */
+      XSync(dpy, 0);
+      usleep(udelay);
+    }
+}
+
+static void
+pedal (dpy, window)
+     Display *dpy;
+     Window window;
+/*
+ *    Since the XFillPolygon doesn't require that the last
+ *    point == first point, the number of points is the same
+ *    as the number of lines.  We just let XFillPolygon supply
+ *    the line from the last point to the first point.
+ *
+ */
+{
+   int numpoints;
+
+   numpoints = compute_pedal(points, maxlines);
+
+   /* Fade out, make foreground the same as background */
+   if (fade_p)
+     fade_foreground (dpy, cmap, foreground, background, 32);
+
+    /* Clear the window of previous garbage */
+    XClearWindow (dpy, window);
+
+    XFillPolygon (
+                dpy,
+                window,
+                gc,
+                points,
+                numpoints,
+                Complex,
+                CoordModeOrigin);
+
+   /* Pick a new foreground color (added by jwz) */
+   if (! mono_p)
+     {
+       XColor color;
+       hsv_to_rgb (random()%360, 1.0, 1.0,
+                  &color.red, &color.green, &color.blue);
+       XSync(dpy, 0);
+       if (fade_p)
+        {
+          foreground.red = color.red;
+          foreground.green = color.green;
+          foreground.blue = color.blue;
+          XStoreColor (dpy, cmap, &foreground);
+        }
+       else if (XAllocColor (dpy, cmap, &color))
+        {
+          XSetForeground (dpy, gc, color.pixel);
+          XFreeColors (dpy, cmap, &foreground.pixel, 1, 0);
+          foreground.red = color.red;
+          foreground.green = color.green;
+          foreground.blue = color.blue;
+          foreground.pixel = color.pixel;
+        }
+       XSync(dpy, 0);
+     }
+
+    /* Fade in by bringing the foreground back from background */
+    if (fade_p)
+       fade_foreground (dpy, cmap, background, foreground, 32);
+}
+
+\f
+char *progclass = "Pedal";
+
+/*
+ * If we are trying to save the screen, the background
+ * should be dark.
+ */
+char *defaults [] = {
+  "Pedal.background:           black",         /* to placate SGI */
+  "Pedal.foreground:           white",
+  "*delay:                     5",
+  "*fadedelay:                 200000",
+  "*maxlines:                  1000",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-delay",          ".delay",               XrmoptionSepArg, 0 },
+  { "-fadedelay",      ".fadedelay",           XrmoptionSepArg, 0 },
+  { "-maxlines",       ".maxlines",            XrmoptionSepArg, 0 },
+  { "-foreground",      ".foreground",          XrmoptionSepArg, 0 },
+  { "-background",      ".background",          XrmoptionSepArg, 0 },
+};
+
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+     Display *dpy;
+     Window window;
+{
+    init_pedal (dpy, window);
+    for (;;) {
+       pedal (dpy, window);
+       XSync(dpy, 0);
+       if (delay) sleep (delay);
+    }
+}
diff --git a/hacks/pedal.man b/hacks/pedal.man
new file mode 100644 (file)
index 0000000..7a0c3e5
--- /dev/null
@@ -0,0 +1,62 @@
+.TH XScreenSaver 1 "24-Jun-94" "X Version 11"
+.SH NAME
+pedal - pretty geometric picture program
+.SH SYNOPSIS
+.B pedal
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-delay \fIseconds\fP] [-maxlines \fInumber\fP] [-fadedelay \fIuseconds\fP] [-mono] [\-install] [\-visual \fIvisual\fP]
+.SH DESCRIPTION
+The \fIpedal\fP program displays pretty geometric pictures.
+.SH OPTIONS
+.I pedal
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-foreground \fIcolor\fP
+The color for the foreground.  Default is white.
+.TP 8
+.B \-background \fIcolor\fP
+The color for the background.  Default is black.
+.TP 8
+.B \-delay \fIseconds\fP
+The number of seconds to pause between each picture.
+.TP 8
+.B \-maxlines \fInumber\fP
+The maximum number of lines in the drawing.  Good values are
+between 20 and 2000.  Maximum value is 16K.
+.TP 8
+.B \-fadedelay \fImicroseconds\fP
+The number of micro seconds to take when fading in and out.
+.TP 8
+.B \-mono
+Don't do fading.  Pretend we're on a monochrome display.
+.PP
+To make your X server grunt under load, and to impress your
+friends, try \fIpedal -mono -delay 0 -maxlines 100\fp.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1994, by Carnegie Mellon University.  Permission to use,
+copy, modify, distribute, and sell this software and its documentation
+for any purpose is hereby granted without fee, provided fnord 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 fnord this software
+for any purpose.  It is provided "as is" without express or implied
+warranty.
+.SH AUTHOR
+Dale Moore <Dale.Moore@cs.cmu.edu>, 24-Jun-1994.
diff --git a/hacks/pyro.c b/hacks/pyro.c
new file mode 100644 (file)
index 0000000..996f783
--- /dev/null
@@ -0,0 +1,258 @@
+/* xscreensaver, Copyright (c) 1992, 1994 Jamie Zawinski <jwz@netscape.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.
+ */
+
+/* Draw some fireworks.  Inspired from TI Explorer Lisp code by 
+   John S. Pezaris <pz@hx.lcs.mit.edu>
+ */
+
+#include "screenhack.h"
+
+struct projectile {
+  int x, y;    /* position */
+  int dx, dy;  /* velocity */
+  int decay;
+  int size;
+  int fuse;
+  Bool primary;
+  Bool dead;
+  XColor color;
+  struct projectile *next_free;
+};
+
+static struct projectile *projectiles, *free_projectiles;
+
+static struct projectile *
+get_projectile ()
+{
+  struct projectile *p;
+  if (free_projectiles)
+    {
+      p = free_projectiles;
+      free_projectiles = p->next_free;
+      p->next_free = 0;
+      p->dead = False;
+      return p;
+    }
+  else
+    return 0;
+}
+
+static void
+free_projectile (p)
+     struct projectile *p;
+{
+  p->next_free = free_projectiles;
+  free_projectiles = p;
+  p->dead = True;
+}
+
+static void
+launch (xlim, ylim, g, dpy, cmap)
+     int xlim, ylim, g;
+     Display *dpy;
+     Colormap cmap;
+{
+  struct projectile *p = get_projectile ();
+  int x, dx, xxx;
+  if (! p) return;
+
+  do {
+    x = (random () % xlim);
+    dx = 30000 - (random () % 60000);
+    xxx = x + (dx * 200);
+  } while (xxx <= 0 || xxx >= xlim);
+
+  p->x = x;
+  p->y = ylim;
+  p->dx = dx;
+  p->size = 8000;
+  p->decay = 0;
+  p->dy = (random () % 4000) - 13000;
+  p->fuse = ((((random () % 500) + 500) * abs (p->dy / g)) / 1000);
+  p->primary = True;
+
+  if (! mono_p)
+    {
+      hsv_to_rgb (random () % 360, 1.0, 1.0,
+                 &p->color.red, &p->color.green, &p->color.blue);
+      p->color.flags = DoRed | DoGreen | DoBlue;
+      if (!XAllocColor (dpy, cmap, &p->color))
+       {
+         p->color.pixel = WhitePixel (dpy, DefaultScreen (dpy));
+         p->color.red = p->color.green = p->color.blue = 0;
+       }
+    }
+}
+
+static struct projectile *
+shrapnel (parent, dpy, cmap)
+     struct projectile *parent;
+     Display *dpy;
+     Colormap cmap;
+{
+  struct projectile *p = get_projectile ();
+  if (! p) return 0;
+  p->x = parent->x;
+  p->y = parent->y;
+  p->dx = (random () % 5000) - 2500 + parent->dx;
+  p->dy = (random () % 5000) - 2500 + parent->dy;
+  p->decay = (random () % 50) - 60;
+  p->size = (parent->size * 2) / 3;
+  p->fuse = 0;
+  p->primary = False;
+
+  p->color = parent->color;
+  if (! mono_p)
+    XAllocColor (dpy, cmap, &p->color); /* dup the lock */
+  
+  return p;
+}
+
+static GC draw_gc, erase_gc;
+static unsigned int default_fg_pixel;
+
+static int how_many, frequency, scatter;
+
+static Colormap
+init_pyro (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  int i;
+  Colormap cmap;
+  XGCValues gcv;
+  XWindowAttributes xgwa;
+  XGetWindowAttributes (dpy, window, &xgwa);
+  cmap = xgwa.colormap;
+  how_many = get_integer_resource ("count", "Integer");
+  frequency = get_integer_resource ("frequency", "Integer");
+  scatter = get_integer_resource ("scatter", "Integer");
+  if (how_many <= 0) how_many = 100;
+  if (frequency <= 0) frequency = 30;
+  if (scatter <= 0) scatter = 20;
+  projectiles = 0;
+  free_projectiles = 0;
+  projectiles = (struct projectile *)
+    calloc (how_many, sizeof (struct projectile));
+  for (i = 0; i < how_many; i++)
+    free_projectile (&projectiles [i]);
+  gcv.foreground = default_fg_pixel =
+    get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+  draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+  gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
+  erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+  XClearWindow (dpy, window);
+  return cmap;
+}
+
+static void
+pyro (dpy, window, cmap)
+     Display *dpy;
+     Window window;
+     Colormap cmap;
+{
+  XWindowAttributes xgwa;
+  static int xlim, ylim, real_xlim, real_ylim;
+  int g = 100;
+  int i;
+
+  if ((random () % frequency) == 0)
+    {
+      XGetWindowAttributes (dpy, window, &xgwa);
+      real_xlim = xgwa.width;
+      real_ylim = xgwa.height;
+      xlim = real_xlim * 1000;
+      ylim = real_ylim * 1000;
+      launch (xlim, ylim, g, dpy, cmap);
+    }
+
+  XSync (dpy, True);
+  usleep (10000);
+
+  for (i = 0; i < how_many; i++)
+    {
+      struct projectile *p = &projectiles [i];
+      int old_x, old_y, old_size;
+      int size, x, y;
+      if (p->dead) continue;
+      old_x = p->x >> 10;
+      old_y = p->y >> 10;
+      old_size = p->size >> 10;
+      size = (p->size += p->decay) >> 10;
+      x = (p->x += p->dx) >> 10;
+      y = (p->y += p->dy) >> 10;
+      p->dy += (p->size >> 6);
+      if (p->primary) p->fuse--;
+
+      /* erase old one */
+      XFillRectangle (dpy, window, erase_gc, old_x, old_y,
+                     old_size, old_size);
+
+      if ((p->primary ? (p->fuse > 0) : (p->size > 0)) &&
+         x < real_xlim &&
+         y < real_ylim &&
+         x > 0 &&
+         y > 0)
+       {
+         if (mono_p || p->primary)
+           XSetForeground (dpy, draw_gc, default_fg_pixel);
+         else
+           XSetForeground (dpy, draw_gc, p->color.pixel);
+
+         if /*(p->primary)*/ (size > 2)
+           XFillArc (dpy, window, draw_gc, x, y, size, size, 0, 360*64);
+         else
+           XFillRectangle (dpy, window, draw_gc, x, y, size, size);
+       }
+      else
+       {
+         free_projectile (p);
+         if (! mono_p) XFreeColors (dpy, cmap, &p->color.pixel, 1, 0);
+       }
+
+      if (p->primary && p->fuse <= 0)
+       {
+         int i = (random () % scatter) + (scatter/2);
+         while (i--)
+           shrapnel (p, dpy, cmap);
+       }
+    }
+}
+
+\f
+char *progclass = "Pyro";
+
+char *defaults [] = {
+  "Pyro.background:    black",         /* to placate SGI */
+  "Pyro.foreground:    white",
+  "*count:     100",
+  "*frequency: 30",
+  "*scatter:   20",
+  "*geometry:  800x500",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-count",          ".count",       XrmoptionSepArg, 0 },
+  { "-frequency",      ".frequency",   XrmoptionSepArg, 0 },
+  { "-scatter",                ".scatter",     XrmoptionSepArg, 0 }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  Colormap cmap = init_pyro (dpy, window);
+  while (1)
+    pyro (dpy, window, cmap);
+}
diff --git a/hacks/pyro.man b/hacks/pyro.man
new file mode 100644 (file)
index 0000000..8edb966
--- /dev/null
@@ -0,0 +1,60 @@
+.TH XScreenSaver 1 "13-aug-92" "X Version 11"
+.SH NAME
+pyro - simulate fireworks
+.SH SYNOPSIS
+.B pyro
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-count \fIinteger\fP] [\-frequency \fIinteger\fP] [\-scatter \fIinteger\fP]
+.SH DESCRIPTION
+The \fIpyro\fP program simulates fireworks, in a way similar to a Macintosh
+program of the same name.
+.SH OPTIONS
+.I pyro
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono 
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-count \fIinteger\fP
+How many particles should be allowed on the screen at once.  Default 100.
+.TP 8
+.B \-frequency \fIinteger\fP
+How often new missiles should launch.  Default 30.
+.TP 8
+.B \-scatter \fIinteger\fP
+How many particles should appear when a missile explodes.  Default 20.
+The actual number used is between \fIN\fP and \fIN+(N/2)\fP.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1992 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@netscape.com>, 13-aug-92.
diff --git a/hacks/qix.c b/hacks/qix.c
new file mode 100644 (file)
index 0000000..c26e736
--- /dev/null
@@ -0,0 +1,514 @@
+/* xscreensaver, Copyright (c) 1992, 1995 Jamie Zawinski <jwz@netscape.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.
+ */
+
+#include "screenhack.h"
+#include <stdio.h>
+
+struct qpoint {
+  int x, y;
+  int dx, dy;
+};
+
+struct qline {
+  struct qpoint p1, p2;
+  XColor color;
+  Bool dead;
+};
+
+struct qix {
+  int id;
+  int fp;
+  int nlines;
+  struct qline *lines;
+};
+
+static GC draw_gc, erase_gc;
+static unsigned int default_fg_pixel;
+static int maxx, maxy, max_spread, max_size, color_shift;
+static Bool random_p, solid_p, xor_p, transparent_p;
+static int delay;
+static int count;
+static Colormap cmap;
+static unsigned long base_pixel;
+
+static GC *gcs[2];
+
+static void
+get_geom (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  XWindowAttributes xgwa;
+  XGetWindowAttributes (dpy, window, &xgwa);
+  maxx = xgwa.width;
+  maxy = xgwa.height;
+}
+
+static struct qix *
+init_one_qix (dpy, window, nlines)
+     Display *dpy;
+     Window window;
+     int nlines;
+{
+  int i;
+  struct qix *qix = (struct qix *) calloc (1, sizeof (struct qix));
+  qix->nlines = nlines;
+  qix->lines = (struct qline *) calloc (qix->nlines, sizeof (struct qline));
+  
+  if (!mono_p && !transparent_p)
+    {
+      hsv_to_rgb (random () % 360, frand (1.0), frand (0.5) + 0.5,
+                 &qix->lines[0].color.red, &qix->lines[0].color.green,
+                 &qix->lines[0].color.blue);
+      if (!XAllocColor (dpy, cmap, &qix->lines[0].color))
+       {
+         qix->lines[0].color.pixel = default_fg_pixel;
+         XQueryColor (dpy, cmap, &qix->lines[0].color);
+         if (!XAllocColor (dpy, cmap, &qix->lines[0].color))
+           abort ();
+       }
+    }
+  qix->lines[0].p1.x = random () % maxx;
+  qix->lines[0].p1.y = random () % maxy;
+  if (max_size == 0)
+    {
+      qix->lines[0].p2.x = random () % maxx;
+      qix->lines[0].p2.y = random () % maxy;
+    }
+  else
+    {
+      qix->lines[0].p2.x = qix->lines[0].p1.x + (random () % (max_size/2));
+      qix->lines[0].p2.y = qix->lines[0].p1.y + (random () % (max_size/2));
+      if (qix->lines[0].p2.x > maxx) qix->lines[0].p2.x = maxx;
+      if (qix->lines[0].p2.y > maxy) qix->lines[0].p2.y = maxy;
+    }
+  qix->lines[0].p1.dx = (random () % (max_spread + 1)) - (max_spread / 2);
+  qix->lines[0].p1.dy = (random () % (max_spread + 1)) - (max_spread / 2);
+  qix->lines[0].p2.dx = (random () % (max_spread + 1)) - (max_spread / 2);
+  qix->lines[0].p2.dy = (random () % (max_spread + 1)) - (max_spread / 2);
+  qix->lines[0].dead = True;
+  for (i = 1; i < qix->nlines; i++)
+    {
+      qix->lines[i] = qix->lines[0];
+      if (!mono_p && !transparent_p)
+       if (!XAllocColor (dpy, cmap, &qix->lines[i].color))
+         abort ();
+    }
+  return qix;
+}
+
+/* I don't believe this fucking language doesn't have builtin exponentiation.
+   I further can't believe that the fucking ^ character means fucking XOR!! */
+static int i_exp(i,j)
+     int i, j;
+{
+  int k = 1;
+  while (j--) k *= i;
+  return k;
+}
+
+
+static void
+merge_colors (argc, argv, into_color, mask, increment_p)
+     int argc;
+     XColor **argv;
+     XColor *into_color;
+     int mask;
+     Bool increment_p;
+{
+  int j;
+  *into_color = *argv [0];
+  into_color->pixel |= mask;
+#define SHORT_INC(x,y) (x = ((((x)+(y)) > 0xFFFF) ? 0xFFFF : ((x)+(y))))
+#define SHORT_DEC(x,y) (x = ((((x)-(y)) < 0)      ? 0      : ((x)-(y))))
+  for (j = 1; j < argc; j++)
+    if (increment_p)
+      {
+       SHORT_INC (into_color->red,   argv[j]->red);
+       SHORT_INC (into_color->green, argv[j]->green);
+       SHORT_INC (into_color->blue,  argv[j]->blue);
+      }
+    else
+      {
+       SHORT_DEC (into_color->red,   argv[j]->red);
+       SHORT_DEC (into_color->green, argv[j]->green);
+       SHORT_DEC (into_color->blue,  argv[j]->blue);
+      }
+#undef SHORT_INC
+#undef SHORT_DEC
+}
+
+/* fill in all the permutations of colors that XAllocColorCells() has 
+   allocated for us.  Thanks Ron, you're an additive kind of guy. */
+static void
+permute_colors (pcolors, colors, count, plane_masks, increment_p)
+     XColor *pcolors, *colors;
+     int count;
+     unsigned long *plane_masks;
+     Bool increment_p;
+{
+  int out = 0;
+  int max = i_exp (2, count);
+  if (count > 31) abort ();
+  for (out = 1; out < max; out++)
+    {
+      XColor *argv [32];
+      int this_mask = 0;
+      int argc = 0;
+      int bit;
+      for (bit = 0; bit < 32; bit++)
+       if (out & (1<<bit))
+         {
+           argv [argc++] = &pcolors [bit];
+           this_mask |= plane_masks [bit];
+         }
+      merge_colors (argc, argv, &colors [out-1], this_mask, increment_p);
+    }
+}
+
+
+static struct qix **
+init_qix (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  int nlines;
+  struct qix **qixes;
+  XGCValues gcv;
+  XWindowAttributes xgwa;
+  XGetWindowAttributes (dpy, window, &xgwa);
+  cmap = xgwa.colormap;
+  count = get_integer_resource ("count", "Integer");
+  if (count <= 0) count = 1;
+  nlines = get_integer_resource ("segments", "Integer");
+  if (nlines <= 0) nlines = 20;
+  get_geom (dpy, window);
+  max_spread = get_integer_resource ("spread", "Integer");
+  if (max_spread <= 0) max_spread = 10;
+  max_size = get_integer_resource ("size", "Integer");
+  if (max_size < 0) max_size = 0;
+  random_p = get_boolean_resource ("random", "Boolean");
+  solid_p = get_boolean_resource ("solid", "Boolean");
+  xor_p = get_boolean_resource ("xor", "Boolean");
+  transparent_p = get_boolean_resource ("transparent", "Boolean");
+  delay = get_integer_resource ("delay", "Integer");
+  color_shift = get_integer_resource ("colorShift", "Integer");
+  if (color_shift < 0 || color_shift >= 360) color_shift = 5;
+  if (delay < 0) delay = 0;
+
+  if (count == 1 && transparent_p)
+    transparent_p = False; /* it's a no-op */
+
+  if (transparent_p && CellsOfScreen (DefaultScreenOfDisplay (dpy)) <= 2)
+    {
+      fprintf (stderr, "%s: -transparent only works on color displays.\n",
+              progname);
+      transparent_p = False;
+    }
+
+  if (xor_p && !transparent_p)
+    mono_p = True;
+
+  gcs[0] = gcs[1] = 0;
+  gcv.foreground = default_fg_pixel =
+    get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+
+  if (transparent_p)
+    {
+      Bool increment_p = get_boolean_resource ("additive", "Boolean");
+      unsigned long plane_masks [32];
+      XColor *pcolors, *colors;
+      int nplanes = count;
+      int i, total_colors;
+
+      /* permutations would be harder if the number of planes didn't fit
+        in an int.  Who has >32-bit displays anyway... */
+      if (nplanes > 31) nplanes = 31;
+
+      while (nplanes > 1 &&
+            !XAllocColorCells (dpy, cmap, False, plane_masks, nplanes,
+                               &base_pixel, 1))
+       nplanes--;
+
+      if (nplanes <= 1)
+       {
+         fprintf (stderr,
+         "%s: couldn't allocate any color planes; turning -transparent off.\n",
+                  progname);
+         transparent_p = False;
+         if (xor_p)
+           goto NON_TRANSPARENT_XOR;
+         else
+           goto NON_TRANSPARENT;
+       }
+      else if (nplanes != count)
+       {
+         fprintf (stderr,
+                  "%s: only allocated %d color planes (instead of %d).\n",
+                  progname, nplanes, count);
+         count = nplanes;
+       }
+
+      gcs[0] = (GC *) malloc (count * sizeof (GC));
+      gcs[1] = xor_p ? gcs[0] : (GC *) malloc (count * sizeof (GC));
+      total_colors = i_exp (2, count);
+      pcolors = (XColor *) calloc (count, sizeof (XColor));
+      colors = (XColor *) calloc (total_colors, sizeof (XColor));
+      for (i = 0; i < count; i++)
+       {
+         gcv.plane_mask = plane_masks [i];
+         gcv.foreground = ~0;
+         if (xor_p)
+           {
+             gcv.function = GXxor;
+             gcs [0][i] = XCreateGC (dpy, window,
+                                     GCForeground|GCFunction|GCPlaneMask,
+                                     &gcv);
+           }
+         else
+           {
+             gcs [0][i] = XCreateGC (dpy, window, GCForeground|GCPlaneMask,
+                                     &gcv);
+             gcv.foreground = 0;
+             gcs [1][i] = XCreateGC (dpy, window, GCForeground|GCPlaneMask,
+                                     &gcv);
+           }
+
+         /* pick the "primary" (not in that sense) colors.
+            If we are in subtractive mode, pick higher intensities. */
+         hsv_to_rgb (random () % 360, frand (1.0),
+                     frand (0.5) + (increment_p ? 0.2 : 0.5),
+                     &pcolors[i].red, &pcolors[i].green, &pcolors[i].blue);
+
+         pcolors [i].flags = DoRed | DoGreen | DoBlue;
+         pcolors [i].pixel = base_pixel | plane_masks [i];
+       }
+      permute_colors (pcolors, colors, count, plane_masks, increment_p);
+      /* clone the default background of the window into our "base" pixel */
+      colors [total_colors - 1].pixel =
+       get_pixel_resource ("background", "Background", dpy, cmap);
+      XQueryColor (dpy, cmap, &colors [total_colors - 1]);
+      colors [total_colors - 1].pixel = base_pixel;
+      XStoreColors (dpy, cmap, colors, total_colors);
+      XSetWindowBackground (dpy, window, base_pixel);
+      XClearWindow (dpy, window);
+    }
+  else if (xor_p)
+    {
+    NON_TRANSPARENT_XOR:
+      gcv.function = GXxor;
+      gcv.foreground =
+       (default_fg_pixel ^ get_pixel_resource ("background", "Background",
+                                               dpy, cmap));
+      draw_gc = erase_gc = XCreateGC(dpy,window,GCForeground|GCFunction,&gcv);
+    }
+  else
+    {
+    NON_TRANSPARENT:
+      draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+      gcv.foreground = get_pixel_resource ("background", "Background",
+                                          dpy, cmap);
+      erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+    }
+
+  qixes = (struct qix **) malloc ((count + 1) * sizeof (struct qix *));
+  qixes [count] = 0;
+  while (count--)
+    {
+      qixes [count] = init_one_qix (dpy, window, nlines);
+      qixes [count]->id = count;
+    }
+  return qixes;
+}
+
+static void
+free_qline (dpy, window, cmap, qline, prev, qix)
+     Display *dpy;
+     Window window;
+     Colormap cmap;
+     struct qline *qline, *prev;
+     struct qix *qix;
+{
+  if (qline->dead || !prev)
+    ;
+  else if (solid_p)
+    {
+      XPoint points [4];
+      points [0].x = qline->p1.x; points [0].y = qline->p1.y;
+      points [1].x = qline->p2.x; points [1].y = qline->p2.y;
+      points [2].x = prev->p2.x; points [2].y = prev->p2.y;
+      points [3].x = prev->p1.x; points [3].y = prev->p1.y;
+      XFillPolygon (dpy, window, (transparent_p ? gcs[1][qix->id] : erase_gc),
+                   points, 4, Complex, CoordModeOrigin);
+    }
+  else
+    XDrawLine (dpy, window, (transparent_p ? gcs[1][qix->id] : erase_gc),
+              qline->p1.x, qline->p1.y, qline->p2.x, qline->p2.y);
+
+  if (!mono_p && !transparent_p)
+    XFreeColors (dpy, cmap, &qline->color.pixel, 1, 0);
+
+  qline->dead = True;
+}
+
+static void
+add_qline (dpy, window, cmap, qline, prev_qline, qix)
+     Display *dpy;
+     Window window;
+     Colormap cmap;
+     struct qline *qline, *prev_qline;
+     struct qix *qix;
+{
+  *qline = *prev_qline;
+
+#define wiggle(point,delta,max)                                                \
+  if (random_p) delta += (random () % 3) - 1;                          \
+  if (delta > max_spread) delta = max_spread;                          \
+  else if (delta < -max_spread) delta = -max_spread;                   \
+  point += delta;                                                      \
+  if (point < 0) point = 0, delta = -delta, point += delta<<1;         \
+  else if (point > max) point = max, delta = -delta, point += delta<<1;
+  
+  wiggle (qline->p1.x, qline->p1.dx, maxx);
+  wiggle (qline->p1.y, qline->p1.dy, maxy);
+  wiggle (qline->p2.x, qline->p2.dx, maxx);
+  wiggle (qline->p2.y, qline->p2.dy, maxy);
+
+  if (max_size)
+    {
+      if (qline->p1.x - qline->p2.x > max_size)
+       qline->p1.x = qline->p2.x + max_size
+         - (random_p ? random() % max_spread : 0);
+      else if (qline->p2.x - qline->p1.x > max_size)
+       qline->p2.x = qline->p1.x + max_size
+         - (random_p ? random() % max_spread : 0);
+      if (qline->p1.y - qline->p2.y > max_size)
+       qline->p1.y = qline->p2.y + max_size
+         - (random_p ? random() % max_spread : 0);
+      else if (qline->p2.y - qline->p1.y > max_size)
+       qline->p2.y = qline->p1.y + max_size
+         - (random_p ? random() % max_spread : 0);
+    }
+
+  if (!mono_p && !transparent_p)
+    {
+      XColor desired;
+      cycle_hue (&qline->color, color_shift);
+      qline->color.flags = DoRed | DoGreen | DoBlue;
+      desired = qline->color;
+      if (XAllocColor (dpy, cmap, &qline->color))
+       {
+         /* XAllocColor returns the actual RGB that the hardware let us
+            allocate.  Restore the requested values into the XColor struct
+            so that limited-resolution hardware doesn't cause cycle_hue to
+            get "stuck". */
+         qline->color.red = desired.red;
+         qline->color.green = desired.green;
+         qline->color.blue = desired.blue;
+       }
+      else
+       {
+         qline->color = prev_qline->color;
+         if (!XAllocColor (dpy, cmap, &qline->color))
+           abort (); /* same color should work */
+       }
+      XSetForeground (dpy, draw_gc, qline->color.pixel);
+    }
+  if (! solid_p)
+    XDrawLine (dpy, window, (transparent_p ? gcs[0][qix->id] : draw_gc),
+              qline->p1.x, qline->p1.y, qline->p2.x, qline->p2.y);
+  else if (!prev_qline->dead)
+    {
+      XPoint points [4];
+      points [0].x = qline->p1.x; points [0].y = qline->p1.y;
+      points [1].x = qline->p2.x; points [1].y = qline->p2.y;
+      points [2].x = prev_qline->p2.x; points [2].y = prev_qline->p2.y;
+      points [3].x = prev_qline->p1.x; points [3].y = prev_qline->p1.y;
+      XFillPolygon (dpy, window, (transparent_p ? gcs[0][qix->id] : draw_gc),
+                   points, 4, Complex, CoordModeOrigin);
+    }
+
+  qline->dead = False;
+}
+
+static void
+qix1 (dpy, window, qix)
+     Display *dpy;
+     Window window;
+     struct qix *qix;
+{
+  int ofp = qix->fp - 1;
+  static int gtick = 0;
+  if (gtick++ == 500)
+    get_geom (dpy, window), gtick = 0;
+  if (ofp < 0) ofp = qix->nlines - 1;
+  free_qline (dpy, window, cmap, &qix->lines [qix->fp],
+             &qix->lines[(qix->fp + 1) % qix->nlines], qix);
+  add_qline (dpy, window, cmap, &qix->lines[qix->fp], &qix->lines[ofp], qix);
+  if ((++qix->fp) >= qix->nlines)
+    qix->fp = 0;
+}
+
+\f
+char *progclass = "Qix";
+
+char *defaults [] = {
+  "Qix.background:     black",         /* to placate SGI */
+  "Qix.foreground:     white",
+  "*count:     1",
+  "*segments:  50",
+  "*spread:    8",
+  "*size:      0",
+  "*colorShift:        3",
+  "*solid:     false",
+  "*delay:     10000",
+  "*random:    true",
+  "*xor:       false",
+  "*transparent:false",
+  "*additive:  true",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-count",          ".count",       XrmoptionSepArg, 0 },
+  { "-segments",       ".segments",    XrmoptionSepArg, 0 },
+  { "-spread",         ".spread",      XrmoptionSepArg, 0 },
+  { "-size",           ".size",        XrmoptionSepArg, 0 },
+  { "-delay",          ".delay",       XrmoptionSepArg, 0 },
+  { "-color-shift",    ".colorShift",  XrmoptionSepArg, 0 },
+  { "-random",         ".random",      XrmoptionNoArg, "true" },
+  { "-linear",         ".random",      XrmoptionNoArg, "false" },
+  { "-solid",          ".solid",       XrmoptionNoArg, "true" },
+  { "-hollow",         ".solid",       XrmoptionNoArg, "false" },
+  { "-xor",            ".xor",         XrmoptionNoArg, "true" },
+  { "-no-xor",         ".xor",         XrmoptionNoArg, "false" },
+  { "-transparent",    ".transparent", XrmoptionNoArg, "true" },
+  { "-non-transparent",        ".transparent", XrmoptionNoArg, "false" },
+  { "-additive",       ".additive",    XrmoptionNoArg, "true" },
+  { "-subtractive",    ".additive",    XrmoptionNoArg, "false" },
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  struct qix **q1 = init_qix (dpy, window);
+  struct qix **qn;
+  while (1)
+    for (qn = q1; *qn; qn++)
+      {
+       qix1 (dpy, window, *qn);
+       XSync (dpy, True);
+       if (delay) usleep (delay);
+      }
+}
diff --git a/hacks/qix.man b/hacks/qix.man
new file mode 100644 (file)
index 0000000..816a55a
--- /dev/null
@@ -0,0 +1,114 @@
+.TH XScreenSaver 1 "9-dec-92" "X Version 11"
+.SH NAME
+qix - bounce colored lines around a window
+.SH SYNOPSIS
+.B qix
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-segments \fIint\fP] [\-spread \fIpixels\fP] [\-size \fIpixels\fP] [\-count \fIint\fP] [\-color-shift \fIdegrees\fP] [\-delay \fIusecs\fP] [\-random] [\-linear] [\-solid] [\-hollow] [\-xor] [\-no\-xor] [\-transparent] [\-non\-transparent] [\-additive] [\-subtractive]
+.SH DESCRIPTION
+The \fIqix\fP program bounces a series of line segments around its window.
+This is truly the swiss army chainsaw of qix programs.  If you know of one
+with more display modes, I want to know about it.
+.SH OPTIONS
+.I qix
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono 
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-segments \fIinteger\fP
+How many line segments should be drawn.  Default 50.
+.TP 8
+.B \-spread \fIinteger\fP
+How far apart the endpoints of one segment should be from the next.
+Default 8.
+.TP 8
+.B \-size \fIinteger\fP
+The maximum distance one endpoint of a segment is allowed to be from
+the opposite end of that segment.  Default 0, meaning unlimited.
+.TP 8
+.B \-count \fIinteger\fP
+How many qixes to draw.  Default 1.
+.TP 8
+.B \-color\-shift \fIdegrees\fP
+If on a color display, the color of the line segments will cycle through
+the spectrum.  This specifies how far the hue of each segment should be
+from the next, in degrees on the HSV wheel.  Default 3.
+.TP 8
+.B \-delay \fImicroseconds\fP
+How much of a delay should be introduced between steps of the animation.
+Default 25000, or about 0.025 seconds.
+.TP 8
+.B \-random
+The \fIqix\fP will wander around the screen semi-randomly.  This is the
+default.
+.TP 8
+.B \-linear
+The opposite of \fI\-random\fP: the \fIqix\fP will travel in straight lines
+until it reaches a wall, and then it will bounce.
+.TP 8
+.B \-solid
+If this is specified, then the area between the line segments will be filled
+in with the appropriate color, instead of the \fIqix\fP simply being composed
+of one-pixel-wide line segments.  This option looks really good in color.
+.TP 8
+.B \-hollow
+The opposite of \fI\-solid\fP; this is the default.
+.TP 8
+.B \-xor
+If this is specified, then qix segments will be drawn and erased with xor,
+instead of being drawn in some color and erased in the background color.
+This implies \fI\-mono\fP, in that only two colors can be used.
+.TP 8
+.B \-transparent
+If this is specified, and \fI\-count\fP is greater than 1, then each qix
+will be drawn in one color, and when they overlap, the colors will be mixed.
+This only works on \fBPseudoColor\fP displays.  This looks best in
+conjuction with \fI\-solid\fP.
+.TP 8
+.B \-non\-transparent
+Turns off \fI\-transparent\fP.
+.TP 8
+.B \-additive
+If \fI\-transparent\fP is specified, then this option means that the colors
+will be mixed using an additive color model, as if the qixes were projected
+light.  This is the default.
+.TP 8
+.B \-subtractive
+If \fI\-transparent\fP is specified, then this option means that the
+colors will be mixed using a subtractive color model, as if the qixes were
+translucent filters.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1992 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@netscape.com>, 13-aug-92.
diff --git a/hacks/rocks.c b/hacks/rocks.c
new file mode 100644 (file)
index 0000000..4e9e901
--- /dev/null
@@ -0,0 +1,310 @@
+/* xscreensaver, Copyright (c) 1992, 1995 Jamie Zawinski <jwz@netscape.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.
+ */
+
+/* Flying through an asteroid field.  Based on TI Explorer Lisp code by 
+   John Nguyen <johnn@hx.lcs.mit.edu>
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include "screenhack.h"
+
+#define MIN_DEPTH 2            /* rocks disappar when they get this close */
+#define MAX_DEPTH 60           /* this is where rocks appear */
+#define MAX_WIDTH 100          /* how big (in pixels) rocks are at depth 1 */
+#define DEPTH_SCALE 100                /* how many ticks there are between depths */
+#define SIN_RESOLUTION 1000
+
+/* there's not much point in the above being user-customizable, but those
+   numbers might want to be tweaked for displays with an order of magnitude
+   higher resolution or compute power.
+ */
+
+static double sins [SIN_RESOLUTION];
+static double coss [SIN_RESOLUTION];
+static double depths [(MAX_DEPTH + 1) * DEPTH_SCALE];
+
+static Display *dpy;
+static Window window;
+static int width, height, midx, midy;
+static GC draw_gc, erase_gc;
+static Bool rotate_p ;
+
+static int speed;
+
+struct rock {
+  int real_size;
+  int r;
+  int theta;
+  int depth;
+  int size, x, y;
+};
+
+static struct rock *rocks;
+static int nrocks;
+static Pixmap pixmaps [MAX_WIDTH];
+static int delay;
+
+static void rock_reset(), rock_tick(), rock_compute(), rock_draw();
+static void init_pixmaps(), init_rocks(), tick_rocks(), rocks_once();
+
+
+static void
+rock_reset (rock)
+     struct rock *rock;
+{
+  rock->real_size = MAX_WIDTH;
+  rock->r = (SIN_RESOLUTION * 0.7) + (random () % (30 * SIN_RESOLUTION));
+  rock->theta = random () % SIN_RESOLUTION;
+  rock->depth = MAX_DEPTH * DEPTH_SCALE;
+  rock_compute (rock);
+  rock_draw (rock, True);
+}
+
+static void
+rock_tick (rock, d)
+     struct rock *rock;
+     int d;
+{
+  if (rock->depth > 0)
+    {
+      rock_draw (rock, False);
+      rock->depth -= speed;
+      if (rotate_p)
+        {
+         rock->theta = (rock->theta + d) % SIN_RESOLUTION;
+        }
+      while (rock->theta < 0)
+       rock->theta += SIN_RESOLUTION;
+      if (rock->depth < (MIN_DEPTH * DEPTH_SCALE))
+       rock->depth = 0;
+      else
+       {
+         rock_compute (rock);
+         rock_draw (rock, True);
+       }
+    }
+  else if ((random () % 40) == 0)
+    rock_reset (rock);
+}
+
+static void
+rock_compute (rock)
+     struct rock *rock;
+{
+  double factor = depths [rock->depth];
+  rock->size = (int) ((rock->real_size * factor) + 0.5);
+  rock->x = midx + (coss [rock->theta] * rock->r * factor);
+  rock->y = midy + (sins [rock->theta] * rock->r * factor);
+}
+
+static void
+rock_draw (rock, draw_p)
+     struct rock *rock;
+     Bool draw_p;
+{
+  GC gc = draw_p ? draw_gc : erase_gc;
+  if (rock->x <= 0 || rock->y <= 0 || rock->x >= width || rock->y >= height)
+    {
+      /* this means that if a rock were to go off the screen at 12:00, but
+        would have been visible at 3:00, it won't come back once the observer
+        rotates around so that the rock would have been visible again.
+        Oh well.
+       */
+      rock->depth = 0;
+      return;
+    }
+  if (rock->size <= 1)
+    XDrawPoint (dpy, window, gc, rock->x, rock->y);
+  else if (rock->size <= 3 || !draw_p)
+    XFillRectangle (dpy, window, gc,
+                   rock->x - rock->size/2, rock->y - rock->size/2,
+                   rock->size, rock->size);
+  else if (rock->size < MAX_WIDTH)
+    XCopyPlane (dpy, pixmaps [rock->size], window, gc,
+               0, 0, rock->size, rock->size,
+               rock->x - rock->size/2, rock->y - rock->size/2,
+               1);
+  else
+    abort ();
+}
+
+
+static void
+init_pixmaps (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  int i;
+  XGCValues gcv;
+  GC fg_gc = 0, bg_gc = 0;
+  pixmaps [0] = pixmaps [1] = 0;
+  for (i = MIN_DEPTH; i < MAX_WIDTH; i++)
+    {
+      int w = (1+(i/32))<<5; /* server might be faster if word-aligned */
+      int h = i;
+      Pixmap p = XCreatePixmap (dpy, window, w, h, 1);
+      XPoint points [7];
+      pixmaps [i] = p;
+      if (! p)
+       {
+         fprintf (stderr, "%s: couldn't allocate pixmaps", progname);
+         exit (1);
+       }
+      if (! fg_gc)
+       {       /* must use drawable of pixmap, not window (fmh) */
+         gcv.foreground = 1;
+         fg_gc = XCreateGC (dpy, p, GCForeground, &gcv);
+         gcv.foreground = 0;
+         bg_gc = XCreateGC (dpy, p, GCForeground, &gcv);
+       }
+      XFillRectangle (dpy, p, bg_gc, 0, 0, w, h);
+      points [0].x = i * 0.15; points [0].y = i * 0.85;
+      points [1].x = i * 0.00; points [1].y = i * 0.20;
+      points [2].x = i * 0.30; points [2].y = i * 0.00;
+      points [3].x = i * 0.40; points [3].y = i * 0.10;
+      points [4].x = i * 0.90; points [4].y = i * 0.10;
+      points [5].x = i * 1.00; points [5].y = i * 0.55;
+      points [6].x = i * 0.45; points [6].y = i * 1.00;
+      XFillPolygon (dpy, p, fg_gc, points, 7, Nonconvex, CoordModeOrigin);
+    }
+  XFreeGC (dpy, fg_gc);
+  XFreeGC (dpy, bg_gc);
+}
+
+
+static void
+init_rocks (d, w)
+     Display *d;
+     Window w;
+{
+  int i;
+  XGCValues gcv;
+  Colormap cmap;
+  XWindowAttributes xgwa;
+  unsigned int fg, bg;
+  dpy = d;
+  window = w;
+  XGetWindowAttributes (dpy, window, &xgwa);
+  cmap = xgwa.colormap;
+  delay = get_integer_resource ("delay", "Integer");
+  if (delay < 0) delay = 0;
+  speed = get_integer_resource ("speed", "Integer");
+  if (speed < 1) speed = 1;
+  if (speed > 100) speed = 100;
+  rotate_p = get_boolean_resource ("rotate", "Boolean");
+  fg = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+  bg = get_pixel_resource ("background", "Background", dpy, cmap);
+  gcv.foreground = fg;
+  gcv.background = bg;
+  draw_gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
+  gcv.foreground = bg;
+  gcv.background = fg;
+  erase_gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
+
+  for (i = 0; i < SIN_RESOLUTION; i++)
+    {
+      sins [i] = sin ((((double) i) / (SIN_RESOLUTION / 2)) * M_PI);
+      coss [i] = cos ((((double) i) / (SIN_RESOLUTION / 2)) * M_PI);
+    }
+  /* we actually only need i/speed of these, but wtf */
+  for (i = 1; i < (sizeof (depths) / sizeof (depths[0])); i++)
+    depths [i] = atan (((double) 0.5) / (((double) i) / DEPTH_SCALE));
+  depths [0] = M_PI/2; /* avoid division by 0 */
+
+  nrocks = get_integer_resource ("count", "Count");
+  if (nrocks < 1) nrocks = 1;
+  rocks = (struct rock *) calloc (nrocks, sizeof (struct rock));
+  init_pixmaps (dpy, window);
+  XClearWindow (dpy, window);
+}
+
+
+static void
+tick_rocks (d)
+     int d;
+{
+  int i;
+  for (i = 0; i < nrocks; i++)
+    rock_tick (&rocks [i], d);
+}
+
+static void
+rocks_once ()
+{
+  static int current_delta = 0;        /* observer Z rotation */
+  static int window_tick = 50;
+
+  if (window_tick++ == 50)
+    {
+      XWindowAttributes xgwa;
+      XGetWindowAttributes (dpy, window, &xgwa);
+      window_tick = 0;
+      width = xgwa.width;
+      height = xgwa.height;
+      midx = width/2;
+      midy = height/2;
+    }
+
+  if ((random () % 50) == 0)
+    {
+      int d = current_delta;
+      int new_delta = ((random () % 11) - 5);
+      if ((random () % 10) == 0)
+       new_delta *= 5;
+
+      while (d == current_delta)
+       {
+         int i;
+         for (i = 0; i < 3; i++)
+           tick_rocks (d);
+         if (current_delta < new_delta) d++;
+         else d--;
+       }
+      current_delta = new_delta;
+    }
+  tick_rocks (current_delta);
+}
+
+\f
+char *progclass = "Rocks";
+
+char *defaults [] = {
+  "Rocks.background:   black",         /* to placate SGI */
+  "Rocks.foreground:   white",
+  "*count:     100",
+  "*delay:     50000",
+  "*speed:     100",
+  "*rotate:     true",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-count",          ".count",       XrmoptionSepArg, 0 },
+  { "-norotate",        ".rotate",      XrmoptionNoArg,  "false" },
+  { "-delay",          ".delay",       XrmoptionSepArg, 0 },
+  { "-speed",          ".speed",       XrmoptionSepArg, 0 }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  init_rocks (dpy, window);
+  while (1)
+    {
+      rocks_once ();
+      XSync (dpy, True);
+      if (delay) usleep (delay);
+    }
+}
diff --git a/hacks/rocks.man b/hacks/rocks.man
new file mode 100644 (file)
index 0000000..22256d3
--- /dev/null
@@ -0,0 +1,71 @@
+.TH XScreenSaver 1 "13-aug-92" "X Version 11"
+.SH NAME
+rocks - animation of flying through an asteroid field
+.SH SYNOPSIS
+.B rocks
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-install] [\-visual \fIvisual\fP] [\-count \fIinteger\fP] [\-delay \fIusecs\fP] [\-speed \fIinteger\fP] [\-norotate]
+.SH DESCRIPTION
+The \fIrocks\fP program draws an animation of an asteroid field moving past
+the observer (or vice versa).  Sometimes the observer picks up spin on Z axis.
+.SH OPTIONS
+.I rocks
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-count \fIinteger\fP
+Maximum number of rocks to draw on the screen at once.  Default 100.
+.TP 8
+.B \-speed \fIinteger\fP
+A measure of the speed with which the observer and the rocks pass each other,
+from 1 to 100.  Default 100, meaning ``very fast.''  If you're on a slow 
+display connection (the animation looks jerky) then try making this number 
+smaller, and/or decreasing the number of rocks.
+.TP 8
+.B \-delay \fImicroseconds\fP
+Number of microseconds to delay between each frame.  Default 50000, meaning
+about 1/20th second.  Compare and contrast with \fI\-speed\fP, above.
+.TP 8
+.B \-norotate
+Don't rotate the observer; just fly straight through the field.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH BUGS
+There should be an option to display doppler shift (a gravity rainbow.)
+
+Speed of rotation should be settable.
+
+Default speed of rotation should be relative to forward velocity.
+.SH COPYRIGHT
+Copyright \(co 1992 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Based on Lisp Machine code copyright 1988 John Nguyen <johnn@hx.lcs.mit.edu>.
+
+Ported to C and X by Jamie Zawinski <jwz@netscape.com>, 13-aug-92.
diff --git a/hacks/rorschach.c b/hacks/rorschach.c
new file mode 100644 (file)
index 0000000..bea709c
--- /dev/null
@@ -0,0 +1,140 @@
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@netscape.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.
+ */
+
+#include "screenhack.h"
+
+static GC draw_gc, erase_gc;
+static unsigned int default_fg_pixel;
+static int iterations, offset;
+static Bool xsym, ysym;
+
+static void
+init_rorschach (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  XGCValues gcv;
+  Colormap cmap;
+  XWindowAttributes xgwa;
+  XGetWindowAttributes (dpy, window, &xgwa);
+  cmap = xgwa.colormap;
+  gcv.foreground = default_fg_pixel =
+    get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+  draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+  gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
+  erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+  iterations = get_integer_resource ("iterations", "Integer");
+  offset = get_integer_resource ("offset", "Integer");
+  if (offset <= 0) offset = 3;
+  if (iterations < 10) iterations = 10;
+  xsym = get_boolean_resource ("xsymmetry", "Symmetry");
+  ysym = get_boolean_resource ("ysymmetry", "Symmetry");
+}
+
+static void
+hurm (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  Colormap cmap;
+  XWindowAttributes xgwa;
+  int xlim, ylim, x, y, i, got_color = 0;
+  XPoint points [4];
+  XColor color;
+  XClearWindow (dpy, window);
+  XGetWindowAttributes (dpy, window, &xgwa);
+  xlim = xgwa.width;
+  ylim = xgwa.height;
+  cmap = xgwa.colormap;
+
+  if (! mono_p)
+    hsv_to_rgb (random()%360, 1.0, 1.0, &color.red, &color.green, &color.blue);
+  if ((!mono_p) && (got_color = XAllocColor (dpy, cmap, &color)))
+    XSetForeground (dpy, draw_gc, color.pixel);
+  else
+    XSetForeground (dpy, draw_gc, default_fg_pixel);
+
+  x = xlim/2;
+  y = ylim/2;
+  for (i = 0; i < iterations; i++)
+    {
+      int j = 0;
+      x += ((random () % (1 + (offset << 1))) - offset);
+      y += ((random () % (1 + (offset << 1))) - offset);
+      points [j].x = x;
+      points [j].y = y;
+      j++;
+      if (xsym)
+       {
+         points [j].x = xlim - x;
+         points [j].y = y;
+         j++;
+       }
+      if (ysym)
+       {
+         points [j].x = x;
+         points [j].y = ylim - y;
+         j++;
+       }
+      if (xsym && ysym)
+       {
+         points [j].x = xlim - x;
+         points [j].y = ylim - y;
+         j++;
+       }
+      XDrawPoints (dpy, window, draw_gc, points, j, CoordModeOrigin);
+      XSync (dpy, True);
+    }
+  sleep (5);
+  for (i = 0; i < (ylim >> 1); i++)
+    {
+      int y = (random () % ylim);
+      XDrawLine (dpy, window, erase_gc, 0, y, xlim, y);
+      XFlush (dpy);
+      if ((i % 50) == 0)
+       usleep (10000);
+    }
+  XClearWindow (dpy, window);
+  if (got_color) XFreeColors (dpy, cmap, &color.pixel, 1, 0);
+  XSync (dpy, True);
+  sleep (1);
+}
+
+\f
+char *progclass = "Rorschach";
+
+char *defaults [] = {
+  "Rorschach.background:       black",         /* to placate SGI */
+  "Rorschach.foreground:       white",
+  "*xsymmetry: true",
+  "*ysymmetry: false",
+  "*iterations:        4000",
+  "*offset:    4",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-iterations",     ".iterations",  XrmoptionSepArg, 0 },
+  { "-offset",         ".offset",      XrmoptionSepArg, 0 },
+  { "-xsymmetry",      ".xsymmetry",   XrmoptionNoArg, "true" },
+  { "-ysymmetry",      ".ysymmetry",   XrmoptionNoArg, "true" }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  init_rorschach (dpy, window);
+  while (1)
+    hurm (dpy, window);
+}
diff --git a/hacks/rorschach.man b/hacks/rorschach.man
new file mode 100644 (file)
index 0000000..4619f0f
--- /dev/null
@@ -0,0 +1,64 @@
+.TH XScreenSaver 1 "13-aug-92" "X Version 11"
+.SH NAME
+rorschach - simulate ink-blot patterns
+.SH SYNOPSIS
+.B rorschach
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-iterations \fIinteger\fP] [\-offset \fIinteger\fP] [\-xsymmetry] [\-ysymmetry]
+.SH DESCRIPTION
+The \fIrorschach\fP program draws random patterns reminiscent of the
+psychological test of same name.
+.SH OPTIONS
+.I rorschach
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono 
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-iterations \fIinteger\fP
+How many dots should be drawn each time.  Default 4000.
+.TP 8
+.B \-offset \fIinteger\fP
+How far apart the dots should be.  Default 4 pixels.
+.TP 8
+.B \-xsymmetry
+Whether the images should be horizontally symmetrical.  Default true.
+.TP 8
+.B \-ysymmetry
+Whether the images should be vertically symmetrical.  Default false.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH BUGS
+May call your sanity into question.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1992 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@netscape.com>, 13-aug-92.
diff --git a/hacks/screenhack.c b/hacks/screenhack.c
new file mode 100644 (file)
index 0000000..6c7a030
--- /dev/null
@@ -0,0 +1,247 @@
+/* xscreensaver, Copyright (c) 1992, 1995 Jamie Zawinski <jwz@netscape.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.
+ *
+ * And remember: X Windows is to graphics hacking as roman numerals are to
+ * the square root of pi.
+ */
+
+/* This file contains simple code to open a window or draw on the root.
+   The idea being that, when writing a graphics hack, you can just link
+   with this .o to get all of the uninteresting junk out of the way.
+
+   -  create a procedure `screenhack(dpy, window)'
+
+   -  create a variable `char *progclass' which names this program's
+      resource class.
+
+   -  create a variable `char defaults []' for the default resources.
+
+   -  create a variable `XrmOptionDescRec options []' for the command-line,
+      and `int options_size' which is `XtNumber (options)'.
+
+   And that's it...
+ */
+
+#include "version.h"
+
+#include <stdio.h>
+#include <X11/Intrinsic.h>
+#include <X11/IntrinsicP.h>
+#include <X11/CoreP.h>
+#include <X11/Shell.h>
+#include <X11/StringDefs.h>
+#include <X11/Xmu/Error.h>
+#include "screenhack.h"
+
+char *progname;
+XrmDatabase db;
+Bool mono_p;
+
+#if __STDC__
+# define P(x) x
+#else
+# define P(x)()
+#endif
+
+
+static XrmOptionDescRec default_options [] = {
+  { "-root",   ".root",                XrmoptionNoArg, "True" },
+  { "-window", ".root",                XrmoptionNoArg, "False" },
+  { "-mono",   ".mono",                XrmoptionNoArg, "True" },
+  { "-install",        ".installColormap",     XrmoptionNoArg, "True" },
+  { "-visual", ".visualID",            XrmoptionSepArg, 0 }
+};
+
+static char *default_defaults[] = {
+  "*root:              false",
+  "*geometry:          500x500", /* this should be .geometry, but nooooo... */
+  "*mono:              false",
+  "*installColormap:   false",
+  "*visualID:          default",
+  0
+};
+
+static XrmOptionDescRec *merged_options;
+static int merged_options_size;
+static char **merged_defaults;
+
+static void
+merge_options P((void))
+{
+  int options_sizeof = options_size * sizeof (options[0]);
+  int defaults_size;
+  merged_options_size = XtNumber (default_options) + options_size;
+  merged_options = (XrmOptionDescRec *)
+    malloc (sizeof (default_options) + options_sizeof);
+  memcpy (merged_options, options, options_sizeof);
+  memcpy (merged_options + options_size, default_options,
+         sizeof (default_options));
+
+  for (defaults_size = 0; defaults [defaults_size]; defaults_size++);
+  merged_defaults = (char **)
+    malloc (sizeof (default_defaults) + (defaults_size * sizeof (char *)));
+  memcpy (merged_defaults, default_defaults, sizeof (default_defaults));
+  memcpy ((merged_defaults - 1 +
+          (sizeof (default_defaults) / sizeof (default_defaults[0]))),
+         defaults, ((defaults_size + 1) * sizeof (defaults[0])));
+}
+
+\f
+/* Make the X errors print out the name of this program, so we have some
+   clue which one has a bug when they die under the screensaver.
+ */
+
+static int
+screenhack_ehandler (dpy, error)
+     Display *dpy;
+     XErrorEvent *error;
+{
+  fprintf (stderr, "\nX error in %s:\n", progname);
+  if (XmuPrintDefaultErrorMessage (dpy, error, stderr))
+    exit (-1);
+  else
+    fprintf (stderr, " (nonfatal.)\n");
+  return 0;
+}
+
+static Bool
+MapNotify_event_p (dpy, event, window)
+     Display *dpy;
+     XEvent *event;
+     XPointer window;
+{
+  return (event->xany.type == MapNotify &&
+         event->xvisibility.window == (Window) window);
+}
+
+
+void
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  XtAppContext app;
+  Widget toplevel;
+  Display *dpy;
+  Window window;
+  Visual *visual;
+  Colormap cmap;
+  Bool root_p;
+  XEvent event;
+
+  merge_options ();
+  toplevel = XtAppInitialize (&app, progclass, merged_options,
+                             merged_options_size, &argc, argv,
+                             merged_defaults, 0, 0);
+  dpy = XtDisplay (toplevel);
+  db = XtDatabase (dpy);
+  XtGetApplicationNameAndClass (dpy, &progname, &progclass);
+  XSetErrorHandler (screenhack_ehandler);
+  if (argc > 1)
+    {
+      int i;
+      int x = 18;
+      int end = 78;
+      fprintf (stderr, "%s: unrecognised option \"%s\"\n", progname, argv[1]);
+      fprintf (stderr, "Options include: ");
+      for (i = 0; i < merged_options_size; i++)
+       {
+         char *sw = merged_options [i].option;
+         Bool argp = (merged_options [i].argKind == XrmoptionSepArg);
+         int size = strlen (sw) + (argp ? 6 : 0) + 2;
+         if (x + size >= end)
+           {
+             fprintf (stderr, "\n\t\t ");
+             x = 18;
+           }
+         x += size;
+         fprintf (stderr, "%s", sw);
+         if (argp) fprintf (stderr, " <arg>");
+         if (i != merged_options_size - 1) fprintf (stderr, ", ");
+       }
+      fprintf (stderr, ".\n");
+      exit (1);
+    }
+
+  mono_p = get_boolean_resource ("mono", "Boolean");
+  if (CellsOfScreen (DefaultScreenOfDisplay (dpy)) <= 2)
+    mono_p = True;
+
+  root_p = get_boolean_resource ("root", "Boolean");
+  if (root_p)
+    {
+      XWindowAttributes xgwa;
+      window = RootWindowOfScreen (XtScreen (toplevel));
+      XtDestroyWidget (toplevel);
+      XGetWindowAttributes (dpy, window, &xgwa);
+      cmap = xgwa.colormap;
+      visual = xgwa.visual;
+    }
+  else
+    {
+      visual = get_visual_resource (dpy, "visualID", "VisualID");
+
+      XtVaSetValues (toplevel, XtNmappedWhenManaged, False, 0);
+      XtRealizeWidget (toplevel);
+      window = XtWindow (toplevel);
+
+      if (visual != DefaultVisualOfScreen (XtScreen (toplevel)))
+       {
+         Arg av [20];
+         int ac;
+         unsigned int bg, bd;
+         Widget new;
+         cmap = XCreateColormap (dpy, window, visual, AllocNone);
+         bg = get_pixel_resource ("background", "Background", dpy, cmap);
+         bd = get_pixel_resource ("borderColor", "Foreground", dpy, cmap);
+         ac = 0;
+         XtSetArg (av[ac], XtNvisual, visual); ac++;
+         XtSetArg (av[ac], XtNcolormap, cmap); ac++;
+         XtSetArg (av[ac], XtNdepth, get_visual_depth (dpy, visual)); ac++;
+         XtSetArg (av[ac], XtNbackground, (Pixel) bg); ac++;
+         XtSetArg (av[ac], XtNborderColor, (Pixel) bd); ac++;
+         new = XtAppCreateShell (progname, progclass,
+                                 topLevelShellWidgetClass, dpy,
+                                 av, ac);
+         XtDestroyWidget (toplevel);
+         toplevel = new;
+       }
+      else if (get_boolean_resource ("installColormap", "InstallColormap"))
+       {
+         cmap = XCreateColormap (dpy, window,
+                                 DefaultVisualOfScreen (XtScreen (toplevel)),
+                                 AllocNone);
+         XSetWindowColormap (dpy, window, cmap);
+       }
+      else
+       {
+         cmap = DefaultColormap (dpy, DefaultScreen (dpy));
+       }
+
+      XtPopup (toplevel, XtGrabNone);
+      window = XtWindow (toplevel);
+    }
+
+  if (!get_boolean_resource ("dontClearWindow", "Boolean")) /* kludge-o-rama */
+    {
+      XSetWindowBackground (dpy, window,
+                           get_pixel_resource ("background", "Background",
+                                               dpy, cmap));
+      XClearWindow (dpy, window);
+    }
+
+  if (!root_p && toplevel->core.mapped_when_managed)
+    /* wait for it to be mapped */
+    XIfEvent (dpy, &event, MapNotify_event_p, (XPointer) window);
+
+  XSync (dpy, False);
+  srandom ((int) time ((time_t *) 0));
+  screenhack (dpy, window);
+}
diff --git a/hacks/screenhack.h b/hacks/screenhack.h
new file mode 100644 (file)
index 0000000..9be4367
--- /dev/null
@@ -0,0 +1,139 @@
+/* xscreensaver, Copyright (c) 1992-1995 Jamie Zawinski <jwz@netscape.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.
+ */
+
+/* Found in Don Hopkins' .plan file:
+ *
+ *   The color situation is a total flying circus.  The X approach to
+ *   device independence is to treat everything like a MicroVax framebuffer
+ *   on acid.  A truely portable X application is required to act like the
+ *   persistent customer in the Monty Python ``Cheese Shop'' sketch.  Even
+ *   the simplest applications must answer many difficult questions, like:
+ *
+ *   WHAT IS YOUR DISPLAY?
+ *       display = XOpenDisplay("unix:0");
+ *   WHAT IS YOUR ROOT?
+ *       root = RootWindow(display, DefaultScreen(display));
+ *   AND WHAT IS YOUR WINDOW?
+ *       win = XCreateSimpleWindow(display, root, 0, 0, 256, 256, 1,
+ *                                 BlackPixel(display, DefaultScreen(display)),
+ *                                 WhitePixel(display, DefaultScreen(display)))
+ *   OH ALL RIGHT, YOU CAN GO ON.
+ *
+ *   WHAT IS YOUR DISPLAY?
+ *         display = XOpenDisplay("unix:0");
+ *   WHAT IS YOUR COLORMAP?
+ *         cmap = DefaultColormap(display, DefaultScreen(display));
+ *   AND WHAT IS YOUR FAVORITE COLOR?
+ *         favorite_color = 0; / * Black. * /
+ *         / * Whoops! No, I mean: * /
+ *         favorite_color = BlackPixel(display, DefaultScreen(display));
+ *         / * AAAYYYYEEEEE!! (client dumps core & falls into the chasm) * /
+ *
+ *   WHAT IS YOUR DISPLAY?
+ *         display = XOpenDisplay("unix:0");
+ *   WHAT IS YOUR VISUAL?
+ *         struct XVisualInfo vinfo;
+ *         if (XMatchVisualInfo(display, DefaultScreen(display),
+ *                              8, PseudoColor, &vinfo) != 0)
+ *            visual = vinfo.visual;
+ *   AND WHAT IS THE NET SPEED VELOCITY OF AN XConfigureWindow REQUEST?
+ *         / * Is that a SubStructureRedirectMask or a ResizeRedirectMask? * /
+ *   WHAT?! HOW AM I SUPPOSED TO KNOW THAT?
+ *   AAAAUUUGGGHHH!!!! (server dumps core & falls into the chasm)
+ */
+
+#ifndef _SCREENHACK_H_
+#define _SCREENHACK_H_
+
+#if __STDC__
+#include <stdlib.h>
+#endif
+
+#ifdef __hpux
+ /* Which of the ten billion standards does values.h belong to?
+    What systems always have it? */
+# include <values.h>
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/Xresource.h>
+#include <X11/Xos.h>
+#include "vroot.h"
+
+extern Bool mono_p;
+extern char *progname;
+extern char *progclass;
+extern XrmDatabase db;
+extern XrmOptionDescRec options [];
+extern int options_size;
+extern char *defaults [];
+
+/* Screw it, we'll just use our own RNG.  See xscreensaver/utils/yarandom.c. */
+#include "yarandom.h"
+
+
+#undef P
+#if __STDC__
+# define P(x)x
+#else
+# define P(x)()
+#endif
+
+extern void screenhack P((Display*,Window));
+
+#define usleep screenhack_usleep
+
+extern void screenhack_usleep P((unsigned long));
+extern char *get_string_resource P((char*,char*));
+extern Bool get_boolean_resource P((char*,char*));
+extern int get_integer_resource P((char*,char*));
+extern double get_float_resource P((char*,char*));
+extern unsigned int get_pixel_resource P((char*,char*,Display*,Colormap));
+extern unsigned int get_minutes_resource P((char*,char*));
+extern unsigned int get_seconds_resource P((char*,char*));
+
+extern Visual *get_visual_resource P((Display *, char *, char *));
+extern int get_visual_depth P((Display *, Visual *));
+
+extern void hsv_to_rgb P((int,double,double,unsigned short*,
+                         unsigned short*,unsigned short*));
+extern void rgb_to_hsv P((unsigned short,unsigned short,unsigned short,
+                         int*,double*,double*));
+extern void cycle_hue P((XColor*,int));
+
+extern void make_color_ramp P((int h1, double s1, double v1,
+                              int h2, double s2, double v2,
+                              XColor *pixels, int npixels));
+
+extern Pixmap grab_screen_image P((Display *dpy, Window window, int root_p));
+extern void copy_default_colormap_contents P((Display *dpy, Colormap to_cmap,
+                                             Visual *to_visual));
+
+#if defined (__GNUC__) && (__GNUC__ >= 2)
+ /* Implement frand using GCC's statement-expression extension. */
+
+# define frand(f)                                                      \
+  ({ double tmp = (((double) random()) /                               \
+                  (((double) ((unsigned int)~0)) / ((double) (f+f)))); \
+     tmp < 0 ? (-tmp) : tmp; })
+
+#else /* not GCC2 - implement frand using a global variable.*/
+
+static double _frand_tmp_;
+# define frand(f)                                                      \
+  (_frand_tmp_ = (((double) random()) /                                \
+                 (((double) ((unsigned int)~0)) / ((double) (f+f)))),  \
+   _frand_tmp_ < 0 ? (-_frand_tmp_) : _frand_tmp_)
+
+#endif /* not GCC2 */
+
+#undef P
+#endif /* _SCREENHACK_H_ */
diff --git a/hacks/slidescreen.c b/hacks/slidescreen.c
new file mode 100644 (file)
index 0000000..6c8ccf7
--- /dev/null
@@ -0,0 +1,253 @@
+/* xscreensaver, Copyright (c) 1992, 1993, 1994 
+ * Jamie Zawinski <jwz@netscape.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.
+ */
+
+#include "screenhack.h"
+
+static int grid_size;
+static int pix_inc;
+static int hole_x, hole_y;
+static int bitmap_w, bitmap_h;
+static int xoff, yoff;
+static int grid_w, grid_h;
+static int delay, delay2;
+static GC gc;
+
+static void
+init_slide (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  int i;
+  XGCValues gcv;
+  XWindowAttributes xgwa;
+  int border;
+  int root_p;
+  unsigned long fg;
+  Pixmap pixmap;
+  Drawable d;
+  Colormap cmap;
+  Visual *visual;
+
+  XGetWindowAttributes (dpy, window, &xgwa);
+  cmap = xgwa.colormap;
+  visual = xgwa.visual;
+
+  copy_default_colormap_contents (dpy, cmap, visual);
+
+  delay = get_integer_resource ("delay", "Integer");
+  delay2 = get_integer_resource ("delay2", "Integer");
+  grid_size = get_integer_resource ("gridSize", "Integer");
+  pix_inc = get_integer_resource ("pixelIncrement", "Integer");
+  border = get_integer_resource ("internalBorderWidth", "InternalBorderWidth");
+  fg = get_pixel_resource ("background", "Background", dpy,
+                          /* Pixels always come out of default map. */
+                          XDefaultColormapOfScreen (xgwa.screen));
+  root_p = get_boolean_resource ("root", "Boolean");
+
+  if (delay < 0) delay = 0;
+  if (delay2 < 0) delay2 = 0;
+  if (pix_inc < 1) pix_inc = 1;
+  if (grid_size < 1) grid_size = 1;
+
+  gcv.foreground = fg;
+  gcv.function = GXcopy;
+  gcv.subwindow_mode = IncludeInferiors;
+  gc = XCreateGC (dpy, window, GCForeground |GCFunction | GCSubwindowMode,
+                 &gcv);
+
+  pixmap = grab_screen_image (dpy, window, root_p);
+
+  XGetWindowAttributes (dpy, window, &xgwa);
+  bitmap_w = xgwa.width;
+  bitmap_h = xgwa.height;
+
+  grid_w = bitmap_w / grid_size;
+  grid_h = bitmap_h / grid_size;
+  hole_x = random () % grid_w;
+  hole_y = random () % grid_h;
+  xoff = (bitmap_w - (grid_w * grid_size)) / 2;
+  yoff = (bitmap_h - (grid_h * grid_size)) / 2;
+
+  d = (pixmap ? pixmap : window);
+
+  if (border)
+    {
+      int i;
+      for (i = 0; i <= bitmap_w; i += grid_size)
+       XFillRectangle (dpy, d, gc, xoff+i-border/2, yoff, border, bitmap_h);
+      for (i = 0; i <= bitmap_h; i += grid_size)
+       XFillRectangle (dpy, d, gc, xoff, yoff+i-border/2, bitmap_w, border);
+    }
+
+  if (xoff)
+    {
+      XFillRectangle (dpy, d, gc, 0, 0, xoff, bitmap_h);
+      XFillRectangle (dpy, d, gc, bitmap_w - xoff, 0, xoff, bitmap_h);
+    }
+  if (yoff)
+    {
+      XFillRectangle (dpy, d, gc, 0, 0, bitmap_w, yoff);
+      XFillRectangle (dpy, d, gc, 0, bitmap_h - yoff, bitmap_w, yoff);
+    }
+
+  if (pixmap) XClearWindow (dpy, window);
+  XSync (dpy, True);
+  if (delay2) usleep (delay2 * 2);
+ for (i = 0; i < grid_size; i += pix_inc)
+   {
+     XPoint points [3];
+     points[0].x = xoff + grid_size * hole_x;
+     points[0].y = yoff + grid_size * hole_y;
+     points[1].x = points[0].x + grid_size;
+     points[1].y = points[0].y;
+     points[2].x = points[0].x;
+     points[2].y = points[0].y + i;
+     XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
+
+     points[1].x = points[0].x;
+     points[1].y = points[0].y + grid_size;
+     points[2].x = points[0].x + i;
+     points[2].y = points[0].y + grid_size;
+     XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
+
+     points[0].x = points[1].x + grid_size;
+     points[0].y = points[1].y;
+     points[2].x = points[0].x;
+     points[2].y = points[0].y - i;
+     XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
+
+     points[1].x = points[0].x;
+     points[1].y = points[0].y - grid_size;
+     points[2].x = points[1].x - i;
+     points[2].y = points[1].y;
+     XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
+
+     XSync (dpy, True);
+     if (delay) usleep (delay);
+   }
+
+  XFillRectangle (dpy, window, gc,
+                 xoff + grid_size * hole_x,
+                 yoff + grid_size * hole_y,
+                 grid_size, grid_size);
+}
+
+static void
+slide1 (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  /* this code is a total kludge, but who cares, it works... */
+ int i, x, y, ix, iy, dx, dy, dir, w, h, size, inc;
+ static int last = -1;
+ do {
+   dir = random () % 4;
+   switch (dir)
+     {
+     case 0: dx = 0,  dy = 1;  break;
+     case 1: dx = -1, dy = 0;  break;
+     case 2: dx = 0,  dy = -1; break;
+     case 3: dx = 1,  dy = 0;  break;
+     default: abort ();
+     }
+ } while (dir == last ||
+         hole_x + dx < 0 || hole_x + dx >= grid_w ||
+         hole_y + dy < 0 || hole_y + dy >= grid_h);
+ if (grid_w > 1 && grid_h > 1)
+   last = (dir == 0 ? 2 : dir == 2 ? 0 : dir == 1 ? 3 : 1);
+
+ switch (dir)
+   {
+   case 0: size = 1 + (random()%(grid_h - hole_y - 1)); h = size; w = 1; break;
+   case 1: size = 1 + (random()%hole_x);               w = size; h = 1; break;
+   case 2: size = 1 + (random()%hole_y);               h = size; w = 1; break;
+   case 3: size = 1 + (random()%(grid_w - hole_x - 1)); w = size; h = 1; break;
+   default: abort ();
+   }
+
+ if (dx == -1) hole_x -= (size - 1);
+ else if (dy == -1) hole_y -= (size - 1);
+
+ ix = x = xoff + (hole_x + dx) * grid_size;
+ iy = y = yoff + (hole_y + dy) * grid_size;
+ inc = pix_inc;
+ for (i = 0; i < grid_size; i += inc)
+   {
+     if (inc + i > grid_size)
+       inc = grid_size - i;
+     XCopyArea (dpy, window, window, gc, x, y, grid_size * w, grid_size * h,
+               x - dx * inc, y - dy * inc);
+     x -= dx * inc;
+     y -= dy * inc;
+     switch (dir)
+       {
+       case 0: XFillRectangle (dpy, window, gc,
+                              ix, y + grid_size * h, grid_size * w, iy - y);
+        break;
+       case 1: XFillRectangle (dpy, window, gc, ix, iy, x - ix, grid_size * h);
+        break;
+       case 2: XFillRectangle (dpy, window, gc, ix, iy, grid_size * w, y - iy);
+        break;
+       case 3: XFillRectangle (dpy, window, gc,
+                              x + grid_size * w, iy, ix - x, grid_size * h);
+        break;
+       }
+
+     XSync (dpy, True);
+     if (delay) usleep (delay);
+   }
+ switch (dir)
+   {
+   case 0: hole_y += size; break;
+   case 1: hole_x--; break;
+   case 2: hole_y--; break;
+   case 3: hole_x += size; break;
+   }
+}
+
+\f
+char *progclass = "SlidePuzzle";
+
+char *defaults [] = {
+  "SlidePuzzle.mappedWhenManaged:false",
+  "SlidePuzzle.dontClearWindow:         true",
+  "*background:                        black",
+  "*gridSize:                  70",
+  "*pixelIncrement:            10",
+  "*internalBorderWidth:       1",
+  "*delay:                     50000",
+  "*delay2:                    1000000",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-grid-size",      ".gridSize",            XrmoptionSepArg, 0 },
+  { "-ibw",            ".internalBorderWidth", XrmoptionSepArg, 0 },
+  { "-increment",      ".pixelIncrement",      XrmoptionSepArg, 0 },
+  { "-delay",          ".delay",               XrmoptionSepArg, 0 },
+  { "-delay2",         ".delay2",              XrmoptionSepArg, 0 },
+};
+
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  init_slide (dpy, window);
+  while (1)
+    {
+      slide1 (dpy, window);
+      if (delay2) usleep (delay2);
+    }
+}
diff --git a/hacks/slidescreen.man b/hacks/slidescreen.man
new file mode 100644 (file)
index 0000000..3d03dc5
--- /dev/null
@@ -0,0 +1,68 @@
+.TH XScreenSaver 1 "3-dec-92" "X Version 11"
+.SH NAME
+slidescreen - permute the screen image like an 8-puzzle
+.SH SYNOPSIS
+.B slidescreen
+[\-display \fIhost:display.screen\fP] [\-background \fIcolor\fP] [\-grid-size \fIpixels\fP] [\-ibw \fIpixels\fP] [\-increment \fIpixels\fP] [\-delay \fIusecs\fP] [\-delay2 \fIusecs\fP] [\-window] [\-root] [\-install] [\-visual \fIvisual\fP]
+.SH DESCRIPTION
+The \fIslidescreen\fP program takes an image of the screen, divides it into
+a grid, deletes a random square of that grid, and then randomly slides 
+one of the neighbors of this "hole" into the hole (and repeat.)
+.SH OPTIONS
+.I slidescreen
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-grid-size \fIpixels\fP
+The size of the grid cells.  Default 70 pixels.
+.TP 8
+.B \-ibw \fIpixels\fP
+The size of the "gutter" between grid cells.  Default 1 pixel.
+.TP 8
+.B \-increment \fIpixels\fP
+How many pixels by which a piece should be moved when sliding to a new 
+location.  Default 10 pixels.
+.TP 8
+.B \-delay \fImicroseconds\fP
+How much of a delay should be introduced between steps of the animation of
+the motion of each segment.  Default 50000, which is 0.05 seconds.  This
+is closely related to the \fI\-increment\fP parameter.
+.TP 8
+.B \-delay \fImicroseconds\fP
+How much of a delay should be introduced between the end of the motion of
+one segment and the beginning of the motion of another.  Default 1000000,
+which isone second.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1992 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@netscape.com>, 3-dec-92.
diff --git a/hacks/vroot.h b/hacks/vroot.h
new file mode 100644 (file)
index 0000000..e6d5764
--- /dev/null
@@ -0,0 +1,123 @@
+/*****************************************************************************/
+/**                   Copyright 1991 by Andreas Stolcke                     **/
+/**               Copyright 1990 by Solbourne Computer Inc.                 **/
+/**                          Longmont, Colorado                             **/
+/**                                                                         **/
+/**                           All Rights Reserved                           **/
+/**                                                                         **/
+/**    Permission to use, copy, modify, and distribute this software and    **/
+/**    its documentation  for  any  purpose  and  without  fee is hereby    **/
+/**    granted, provided that the above copyright notice appear  in  all    **/
+/**    copies and that both  that  copyright  notice  and  this  permis-    **/
+/**    sion  notice appear in supporting  documentation,  and  that  the    **/
+/**    name of Solbourne not be used in advertising                         **/
+/**    in publicity pertaining to distribution of the  software  without    **/
+/**    specific, written prior permission.                                  **/
+/**                                                                         **/
+/**    ANDREAS STOLCKE AND SOLBOURNE COMPUTER INC. DISCLAIMS ALL WARRANTIES **/
+/**    WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF    **/
+/**    MERCHANTABILITY  AND  FITNESS,  IN  NO  EVENT SHALL ANDREAS STOLCKE  **/
+/**    OR SOLBOURNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL    **/
+/**    DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA   **/
+/**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **/
+/**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **/
+/**    OR PERFORMANCE OF THIS SOFTWARE.                                     **/
+/*****************************************************************************/
+/*
+ * vroot.h -- Virtual Root Window handling header file
+ *
+ * This header file redefines the X11 macros RootWindow and DefaultRootWindow,
+ * making them look for a virtual root window as provided by certain `virtual'
+ * window managers like swm and tvtwm. If none is found, the ordinary root
+ * window is returned, thus retaining backward compatibility with standard
+ * window managers.
+ * The function implementing the virtual root lookup remembers the result of
+ * its last invocation to avoid overhead in the case of repeated calls
+ * on the same display and screen arguments. 
+ * The lookup code itself is taken from Tom LaStrange's ssetroot program.
+ *
+ * Most simple root window changing X programs can be converted to using
+ * virtual roots by just including
+ *
+ * #include <X11/vroot.h>
+ *
+ * after all the X11 header files.  It has been tested on such popular
+ * X clients as xphoon, xfroot, xloadimage, and xaqua.
+ * It also works with the core clients xprop, xwininfo, xwd, and editres
+ * (and is necessary to get those clients working under tvtwm).
+ * It does NOT work with xsetroot; get the xsetroot replacement included in
+ * the tvtwm distribution instead.
+ *
+ * Andreas Stolcke <stolcke@ICSI.Berkeley.EDU>, 9/7/90
+ * - replaced all NULL's with properly cast 0's, 5/6/91
+ * - free children list (suggested by Mark Martin <mmm@cetia.fr>), 5/16/91
+ * - include X11/Xlib.h and support RootWindowOfScreen, too 9/17/91
+ */
+
+#ifndef _VROOT_H_
+#define _VROOT_H_
+
+#if !defined(lint) && !defined(SABER)
+static char vroot_rcsid[] = "$Id: vroot.h,v 1.1 1994/08/25 22:04:24 jwz Exp $";
+#endif
+
+#include <X11/X.h>
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+
+static Window
+VirtualRootWindowOfScreen(screen)
+       Screen *screen;
+{
+       static Screen *save_screen = (Screen *)0;
+       static Window root = (Window)0;
+
+       if (screen != save_screen) {
+               Display *dpy = DisplayOfScreen(screen);
+               Atom __SWM_VROOT = None;
+               int i;
+               Window rootReturn, parentReturn, *children;
+               unsigned int numChildren;
+
+               root = RootWindowOfScreen(screen);
+
+               /* go look for a virtual root */
+               __SWM_VROOT = XInternAtom(dpy, "__SWM_VROOT", False);
+               if (XQueryTree(dpy, root, &rootReturn, &parentReturn,
+                                &children, &numChildren)) {
+                       for (i = 0; i < numChildren; i++) {
+                               Atom actual_type;
+                               int actual_format;
+                               unsigned long nitems, bytesafter;
+                               Window *newRoot = (Window *)0;
+
+                               if (XGetWindowProperty(dpy, children[i],
+                                       __SWM_VROOT, 0, 1, False, XA_WINDOW,
+                                       &actual_type, &actual_format,
+                                       &nitems, &bytesafter,
+                                       (unsigned char **) &newRoot) == Success
+                                   && newRoot) {
+                                   root = *newRoot;
+                                   break;
+                               }
+                       }
+                       if (children)
+                               XFree((char *)children);
+               }
+
+               save_screen = screen;
+       }
+
+       return root;
+}
+
+#undef RootWindowOfScreen
+#define RootWindowOfScreen(s) VirtualRootWindowOfScreen(s)
+
+#undef RootWindow
+#define RootWindow(dpy,screen) VirtualRootWindowOfScreen(ScreenOfDisplay(dpy,screen))
+
+#undef DefaultRootWindow
+#define DefaultRootWindow(dpy) VirtualRootWindowOfScreen(DefaultScreenOfDisplay(dpy))
+
+#endif /* _VROOT_H_ */
diff --git a/hacks/xlock.h b/hacks/xlock.h
new file mode 100644 (file)
index 0000000..19e5fda
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+**  Helpful definitions for porting xlock modes to xscreensaver.
+**  by Charles Hannum, mycroft@ai.mit.edu
+**
+**  for xlock 2.3 and xscreensaver 1.2, 28AUG92
+**
+**
+**  Modified for xlockmore 3.0 by Anthony Thyssen <anthony@cit.gu.edu.au>
+**  on August 1995.
+**
+**  To use, just copy the appropriate file from xlock, add a target
+**  for it in the Imakefile, and do the following:
+**
+**  1) If you include math.h, make sure it is before xlock.h.
+**  2) Make sure the first thing you do in initfoo() is to call
+**     XGetWindowAttributes.  This is what actually sets up the
+**     colormap and whatnot.
+**  3) Add an appropriate PROGRAM() line at the end of the .c file.
+**     The information you need for this comes from xlock's file
+**     resource.c.
+**
+**  That's about all there is to it.
+**
+**  As an added bonus, if you put an empty definition of PROGRAM() in
+**  xlock's xlock.h, you can now use the code with either xlock or
+**  xscreensaver.
+**
+**
+**  If you make any improvements to this code, please send them to me!
+**  It could certainly use some more work.
+*/
+
+#include "screenhack.h"
+
+#define MAXSCREENS 1
+
+static GC gc;
+static unsigned long *pixels = 0, fg_pixel, bg_pixel;
+static int npixels;
+static Colormap cmap;
+
+static int batchcount;
+static unsigned int delay;
+static unsigned int cycles;
+static double saturation;
+
+#ifndef min
+#define min(a,b) ((a)<(b)?(a):(b))
+#endif
+
+typedef struct {
+  GC gc;
+  int npixels;
+  u_long *pixels;
+} perscreen;
+
+static perscreen Scr[MAXSCREENS];
+static Display *dsp;
+
+static int screen = 0;
+
+static void
+My_XGetWindowAttributes (dpy, win, xgwa)
+  Display *dpy;
+  Window win;
+  XWindowAttributes *xgwa;
+{
+  XGetWindowAttributes (dpy, win, xgwa);
+
+  if (! pixels) {
+    XGCValues gcv;
+    XColor color;
+    int n;
+    int i, shift;
+
+    cmap = xgwa->colormap;
+
+    i = get_integer_resource ("ncolors", "Integer");
+    if (i <= 2) i = 2, mono_p = True;
+    shift = 360 / i;
+    pixels = (unsigned long *) calloc (i, sizeof (unsigned long));
+    fg_pixel = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+    bg_pixel = get_pixel_resource ("background", "Background", dpy, cmap);
+    if (! mono_p) {
+      for (npixels = 0; npixels < i; npixels++) {
+        hsv_to_rgb ((360*npixels)/i, saturation, 1.0,
+                   &color.red, &color.green, &color.blue);
+        if (! XAllocColor (dpy, cmap, &color))
+          break;
+        pixels[npixels] = color.pixel;
+      }
+    }
+    n = get_integer_resource ("delay", "Usecs");
+    if (n >= 0) delay = n;
+    n = get_integer_resource ("count", "Integer");
+    if (n > 0) batchcount = n;
+
+    n = get_integer_resource ("cycles", "Integer");
+    if (n >= 0) cycles = n;
+
+    gcv.foreground = fg_pixel;
+    gcv.background = bg_pixel;
+    gc = XCreateGC (dpy, win, GCForeground|GCBackground, &gcv);
+
+    XClearWindow (dpy, win);
+
+    Scr[screen].gc = gc;
+    Scr[screen].npixels = npixels;
+    Scr[screen].pixels = pixels;
+  }
+}
+
+#define XGetWindowAttributes(a,b,c) My_XGetWindowAttributes(a,b,c)
+
+#undef BlackPixel
+#define BlackPixel(a,b) bg_pixel
+#undef WhitePixel
+#define WhitePixel(a,b) fg_pixel
+#define mono mono_p
+
+#define seconds() time((time_t*)0)
+
+char *defaults[] = {
+  "*background:        black",
+  "*foreground:        white",
+  "*ncolors:   64",
+  "*delay:     -1",
+  "*count:     -1",
+  "*cycles:    -1",
+  0
+};
+
+XrmOptionDescRec options[] = {
+  {"-count",   ".count",       XrmoptionSepArg, 0},
+  {"-ncolors", ".ncolors",     XrmoptionSepArg, 0},
+  {"-delay",   ".delay",       XrmoptionSepArg, 0},
+  {"-cycles",   ".cycles",      XrmoptionSepArg, 0},
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+#define PROGRAM(Y,Z,D,B,C,S) \
+char *progclass = Y;                   \
+                                       \
+void screenhack (dpy, window)          \
+  Display *dpy;                                \
+  Window window;                       \
+{                                      \
+  batchcount = B;                      \
+  delay = D;                           \
+  cycles = C;                           \
+  saturation = S;                      \
+  dsp = dpy;                           \
+                                       \
+  init##Z (window);                    \
+  while (1) {                          \
+    draw##Z (window);                  \
+    XSync (dpy, True);                 \
+    if (delay) usleep (delay);         \
+  }                                    \
+}
diff --git a/hacks/xroger-hack.c b/hacks/xroger-hack.c
new file mode 100644 (file)
index 0000000..615ade1
--- /dev/null
@@ -0,0 +1,103 @@
+/* xscreensaver, Copyright (c) 1991-1994 Jamie Zawinski <jwz@netscape.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.
+ */
+
+#include "screenhack.h"
+
+char *progclass = "XRoger";
+
+char *defaults [] = {
+  "XRoger.background:  black",
+  "XRoger.foreground:  red",
+  "*delay:             5",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-delay",          ".delay",       XrmoptionSepArg, 0 }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+#if __STDC__
+extern void skull (Display *, Window, GC, GC, int, int, int, int);
+#endif
+
+void
+screenhack (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  double delta = 0.005;
+  XGCValues gcv;
+  Colormap cmap;
+  GC draw_gc, erase_gc;
+  unsigned int fg;
+  XColor color, color2, color3;
+  int delay = get_integer_resource ("delay", "Integer");
+  XWindowAttributes xgwa;
+  XGetWindowAttributes (dpy, window, &xgwa);
+  cmap = xgwa.colormap;
+  gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
+  erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+  fg = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+  if (fg == gcv.foreground)
+    fg = ((gcv.foreground == WhitePixel (dpy, DefaultScreen (dpy)))
+         ? BlackPixel (dpy, DefaultScreen (dpy))
+         : WhitePixel (dpy, DefaultScreen (dpy)));
+  gcv.foreground = fg;
+  draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+  color.pixel = gcv.foreground;
+  XQueryColor (dpy, cmap, &color);
+  while (1)
+    {
+      int w, h, ww, hh, x, y;
+      time_t start_time;
+      XWindowAttributes xgwa;
+      XGetWindowAttributes (dpy, window, &xgwa);
+      w = xgwa.width;
+      h = xgwa.height;
+
+      ww = 100 + random () % (w - 100);
+      hh = 100 + random () % (h - 100);
+      if (ww < 10) ww = 50;
+      if (hh < 10) hh = 50;
+      if (ww < hh) hh = ww;
+      else ww = hh;
+      x = random () % (w - ww);
+      y = random () % (h - hh);
+      XClearWindow (dpy, window);
+      skull (dpy, window, draw_gc, erase_gc, x, y, ww, hh);
+      XSync (dpy, True);
+      start_time = time ((time_t *) 0);
+      if (mono_p)
+       sleep (delay);
+      else
+       while (start_time + delay > time ((time_t *) 0))
+         {
+           int h;
+           double s, v;
+           color2 = color;
+           rgb_to_hsv (color2.red, color2.green, color2.blue, &h, &s, &v);
+           v += delta;
+           if (v >= 1.0) v = 1.0, delta = -delta;
+           if (v <= 0.7) v = 0.7, delta = -delta;
+           hsv_to_rgb (h, s, v, &color2.red, &color2.green, &color2.blue);
+           color3 = color2;
+           if (XAllocColor (dpy, cmap, &color3))
+             {
+               XSetForeground (dpy, draw_gc, color3.pixel);
+               color2.pixel = color3.pixel;
+               XFreeColors (dpy, cmap, &color.pixel, 1, 0);
+             }
+           color = color2;
+           usleep (20000);
+         }
+    }
+}
diff --git a/hacks/xroger.man b/hacks/xroger.man
new file mode 100644 (file)
index 0000000..799f500
--- /dev/null
@@ -0,0 +1,52 @@
+.TH XScreenSaver 1 "22-mar-93" "X Version 11"
+.SH NAME
+xroger - throbbing X logo, of a sort
+.SH SYNOPSIS
+.B xroger
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP]
+.SH DESCRIPTION
+The \fIxroger\fP program displays a replacement for the X logo with a more
+accurate Look and Feel.
+.SH OPTIONS
+.I xroger
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono 
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH BUGS
+It should also drip blood while making a horrible screeching noise.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1992, 1993 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided fnord 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 fnord this software for any purpose.  It is provided "as
+is" without express or fnord implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@netscape.com>, 13-aug-92.
diff --git a/screenblank.txt b/screenblank.txt
new file mode 100644 (file)
index 0000000..1762158
--- /dev/null
@@ -0,0 +1,46 @@
+From mrapple@quack.kfu.com Mon Apr 26 18:31:07 1993
+Newsgroups: alt.hackers
+From: mrapple@quack.kfu.com (Nick Sayer)
+Subject: screenblank and xautolock living in harmony
+Organization: The Duck Pond public unix: +1 408 249 9630, log in as 'guest'.
+Date: 23 Apr 1993 19:26:57 UTC
+
+
+I have a Sun and use xinit to start X. This presented a problem.
+If I use xautolock or xscreensaver to save the screen, then after
+a period of inactivity screenblank would turn the video off despite
+'xset s off'. If I didn't run screenblank, then who would take care of
+the display when X wasn't running?
+
+The hack that saved the day was to include this in .xinitrc:
+
+(
+
+while true ; do
+sleep 360
+touch /dev/console
+done
+
+) &
+killblank=$!
+
+[start up all the clients, etc, etc. Wait for the window manager
+to die, then ]
+
+kill $killblank
+
+The result is that screenblank is kept safely out of the way when X
+is running and left to do its job otherwise.
+
+Yes, I know using XDM would solve this problem.
+
+No, I'm probably not the first to think of this.
+
+You're welcome.
+
+-- 
+Nick Sayer <mrapple@quack.kfu.com>   | "Dear Sexy Nickers. I don't half fancy
+N6QQQ @ N0ARY.#NOCAL.CA.USA.NOAM     | you. Meet me at the lift at 5:30 and
++1 408 249 9630, log in as 'guest'   | we'll get it together."
+PGP 2.2 public key via finger        |               -- Mr. Lucas
+
diff --git a/utils/Imakefile b/utils/Imakefile
new file mode 100644 (file)
index 0000000..5f61d60
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Imakefile file for xscreensaver, Copyright (c) 1993, 1995 Jamie Zawinski.
+ *
+ * You should not need to edit this file; edit ../config.h instead.
+ *
+ */
+
+#include "../config.h"
+
+#ifdef NO_SELECT
+    DEFINES = R5ISMS -DNO_SELECT
+#else
+    DEFINES = R5ISMS
+#endif
+       SRCS = fade.c hsv.c resources.c spline.c usleep.c xroger.c \
+              grabscreen.c visual.c yarandom.c
+       OBJS = fade.o hsv.o resources.o spline.o usleep.o xroger.o \
+              grabscreen.o visual.o yarandom.o
+   TARFILES = README Imakefile ad2c $(SRCS) spline.h yarandom.h version.h
+
+all:: $(OBJS)
+
+echo_tarfiles:
+       @echo $(TARFILES)
diff --git a/utils/README b/utils/README
new file mode 100644 (file)
index 0000000..2f5bc11
--- /dev/null
@@ -0,0 +1,6 @@
+
+This directory contains various utilities that are used both by the 
+screensaver driver and by the demo programs; for example, a portable
+implementation of usleep(), and code for manipulating color maps.
+
+If you have compilation problems, check the parameters in ../config.h.
diff --git a/utils/ad2c b/utils/ad2c
new file mode 100755 (executable)
index 0000000..1435e55
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh
+#
+#      ad2c : Convert app-defaults file to C strings decls.
+#
+#      George Ferguson, ferguson@cs.rcohester.edu, 12 Nov 1990.
+#      19 Mar 1991 : gf
+#              Made it self-contained.
+#      6 Jan 1992 : mycroft@gnu.ai.mit.edu (Charles Hannum)
+#              Removed use of "-n" and ":read" label since Gnu and
+#              IBM sed print pattern space on "n" command. Still works
+#              with Sun sed, of course.
+#      7 Jan 1992: matthew@sunpix.East.Sun.COM (Matthew Stier)
+#              Escape quotes after escaping backslashes.
+#
+
+sed '
+/^!/d
+/^$/d
+s/\\/\\\\/g
+s/\\$//g
+s/"/\\"/g
+s/^/"/
+: test
+/\\$/b slash
+s/$/",/
+p
+d
+: slash
+n
+/^!/d
+/^$/d
+s/"/\\"/g
+s/\\\\/\\/g
+s/\\n/\\\\n/g
+s/\\t/\\\\t/g
+s/\\f/\\\\f/g
+s/\\b/\\\\b/g
+b test' "$@"
diff --git a/utils/fade.c b/utils/fade.c
new file mode 100644 (file)
index 0000000..40fe9dd
--- /dev/null
@@ -0,0 +1,176 @@
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@netscape.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.
+ */
+
+#if __STDC__
+# include <stdlib.h>
+#endif
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xos.h>
+
+#if __STDC__
+# define P(x)x
+#else
+# define P(x)()
+#endif
+
+extern int get_visual_class P((Display *, Visual *));
+extern void screenhack_usleep P((int));
+#define usleep screenhack_usleep
+
+#define MAX_COLORS 4096
+static XColor orig_colors [MAX_COLORS];
+static XColor current_colors [MAX_COLORS];
+static int ncolors;
+
+Colormap
+copy_colormap (dpy, cmap, into_cmap)
+     Display *dpy;
+     Colormap cmap, into_cmap;
+{
+  int i;
+  Screen *screen = DefaultScreenOfDisplay (dpy);
+  Visual *visual = DefaultVisualOfScreen (screen);
+  Window window = RootWindowOfScreen (screen);
+  int vclass = get_visual_class (dpy, visual);
+
+  ncolors = CellsOfScreen (screen);
+
+  /* If this is a colormap on a mono visual, or one with insanely many
+     color cells, bug out. */
+  if (ncolors <= 2 || ncolors > MAX_COLORS)
+    return 0;
+  /* If this is a non-writable visual, bug out. */
+  if (vclass == StaticGray || vclass == StaticColor || vclass == TrueColor)
+    return 0;
+
+  if (! into_cmap)
+    into_cmap = XCreateColormap (dpy, window, visual, AllocAll);
+  if (! cmap)
+    cmap = DefaultColormap (dpy, DefaultScreen (dpy));
+  for (i = 0; i < ncolors; i++)
+    orig_colors [i].pixel = i;
+  XQueryColors (dpy, cmap, orig_colors, ncolors);
+  XStoreColors (dpy, into_cmap, orig_colors, ncolors);
+  return into_cmap;
+}
+
+void
+blacken_colormap (dpy, cmap)
+     Display *dpy;
+     Colormap cmap;
+{
+  int i;
+  for (i = 0; i < ncolors; i++)
+    {
+      current_colors [i].pixel = i;
+      current_colors [i].red = current_colors [i].green =
+       current_colors [i].blue = 0;
+    }
+  XStoreColors (dpy, cmap, current_colors, ncolors);
+}
+
+
+void
+fade_colormap (dpy, cmap, cmap2, seconds, ticks, out_p)
+     Display *dpy;
+     Colormap cmap, cmap2;
+     int seconds, ticks;
+     Bool out_p;
+{
+  int i;
+  int steps = seconds * ticks;
+  XEvent dummy_event;
+
+  if (! cmap2)
+    return;
+
+  for (i = 0; i < ncolors; i++)
+    orig_colors [i].pixel = i;
+  XQueryColors (dpy, cmap, orig_colors, ncolors);
+  memcpy (current_colors, orig_colors, ncolors * sizeof (XColor));
+
+  for (i = (out_p ? steps : 0);
+       (out_p ? i > 0 : i < steps);
+       (out_p ? i-- : i++))
+    {
+      int j;
+      for (j = 0; j < ncolors; j++)
+       {
+         current_colors[j].red   = orig_colors[j].red   * i / steps;
+         current_colors[j].green = orig_colors[j].green * i / steps;
+         current_colors[j].blue  = orig_colors[j].blue  * i / steps;
+       }
+      XStoreColors (dpy, cmap2, current_colors, ncolors);
+      XSync (dpy, False);
+
+      /* If there is user activity, bug out.
+        We put the event back so that the calling code can notice it too.
+        It would be better to not remove it at all, but that's harder
+        because Xlib has such a non-design for this kind of crap, and
+        in this application it doesn't matter if the events end up out
+        of order, so in the grand unix tradition we say "fuck it" and
+        do something that mostly works for the time being.
+       */
+      if (XCheckMaskEvent (dpy, (KeyPressMask | KeyReleaseMask |
+                                ButtonPressMask | ButtonReleaseMask |
+                                PointerMotionMask),
+                          &dummy_event))
+       {
+         XPutBackEvent (dpy, &dummy_event);
+         return;
+       }
+
+      usleep (1000000 / (ticks * 2)); /* the 2 is a hack... */
+    }
+}
+
+#if 0
+
+\f
+char *progclass = "foo";
+
+char *defaults [] = {
+  0
+};
+
+XrmOptionDescRec options [] = {0};
+int options_size = 0;
+
+void
+screenhack (dpy, w)
+     Display *dpy;
+     Window w;
+{
+  Colormap cmap = DefaultColormap (dpy, DefaultScreen (dpy));
+  Colormap cmap2 = copy_colormap (dpy, cmap, 0);
+
+  int seconds = 1;
+  int ticks = 30 * seconds;
+  int delay = 1;
+
+  while (1)
+    {
+      XSync (dpy, False);
+      XGrabServer (dpy);
+      XInstallColormap (dpy, cmap2);
+      fade_colormap (dpy, cmap, cmap2, seconds, ticks, True);
+      if (delay) sleep (delay);
+      fade_colormap (dpy, cmap, cmap2, seconds, ticks, False);
+      XInstallColormap (dpy, cmap);
+      XUngrabServer (dpy);
+      XSync (dpy, False);
+      if (delay) sleep (delay);
+    }
+}
+
+#endif
diff --git a/utils/grabscreen.c b/utils/grabscreen.c
new file mode 100644 (file)
index 0000000..692e42e
--- /dev/null
@@ -0,0 +1,200 @@
+/* xscreensaver, Copyright (c) 1992, 1993, 1994 Jamie Zawinski <jwz@netscape.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.
+ */
+
+/* This file contains code for grabbing an image of the screen to hack its
+   bits.  This is a little tricky, since doing this involves the need to tell
+   the difference between drawing on the actual root window, and on the fake
+   root window used by the screensaver, since at this level the illusion 
+   breaks down...
+ */
+
+#if __STDC__
+#include <stdlib.h>
+#include <unistd.h>
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+
+static Bool
+MapNotify_event_p (dpy, event, window)
+     Display *dpy;
+     XEvent *event;
+     XPointer window;
+{
+  return (event->xany.type == MapNotify &&
+         event->xvisibility.window == (Window) window);
+}
+
+
+#if __STDC__
+static Bool screensaver_window_p (Display *, Window);
+#endif
+
+static Bool
+screensaver_window_p (dpy, window)
+     Display *dpy;
+     Window window;
+{
+  Atom type;
+  int format;
+  unsigned long nitems, bytesafter;
+  char *version;
+  if (XGetWindowProperty (dpy, window,
+                         XInternAtom (dpy, "_SCREENSAVER_VERSION", False),
+                         0, 1, False, XA_STRING,
+                         &type, &format, &nitems, &bytesafter,
+                         (unsigned char **) &version)
+      == Success
+      && type != None)
+    return True;
+  return False;
+}
+
+Pixmap
+grab_screen_image (dpy, window, root_p)
+     Display *dpy;
+     Window window;
+     int root_p;
+{
+  Pixmap pixmap = 0;
+  XWindowAttributes xgwa;
+
+  XGetWindowAttributes (dpy, window, &xgwa);
+
+  if (screensaver_window_p (dpy, window))
+    {
+      /* note: this assumes vroot.h didn't encapsulate the XRootWindowOfScreen
+        function, only the RootWindowOfScreen macro... */
+      Window real_root = XRootWindowOfScreen (DefaultScreenOfDisplay (dpy));
+
+      XSetWindowBackgroundPixmap (dpy, window, None);
+
+      /* prevent random viewer of the screen saver (locker) from messing
+        with windows.   We don't check whether it succeeded, because what
+        are our options, really... */
+      XGrabPointer (dpy, real_root, True, ButtonPressMask|ButtonReleaseMask,
+                   GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
+      XGrabKeyboard (dpy, real_root, True, GrabModeSync, GrabModeAsync,
+                    CurrentTime);
+
+      XUnmapWindow (dpy, window);
+      XSync (dpy, True);
+      sleep (5);     /* wait for everyone to swap in and handle exposes... */
+      XMapRaised (dpy, window);
+
+      XUngrabPointer (dpy, CurrentTime);
+      XUngrabKeyboard (dpy, CurrentTime);
+
+      XSync (dpy, True);
+    }
+  else if (root_p)
+    {
+      XGCValues gcv;
+      GC gc;
+      gcv.function = GXcopy;
+      gcv.subwindow_mode = IncludeInferiors;
+      gc = XCreateGC (dpy, window, GCFunction | GCSubwindowMode, &gcv);
+      pixmap = XCreatePixmap(dpy, window, xgwa.width, xgwa.height, xgwa.depth);
+      XCopyArea (dpy, RootWindowOfScreen (xgwa.screen), pixmap, gc,
+                xgwa.x, xgwa.y, xgwa.width, xgwa.height, 0, 0);
+      XFreeGC (dpy, gc);
+      XSetWindowBackgroundPixmap (dpy, window, pixmap);
+    }
+  else
+    {
+      XEvent event;
+      XSetWindowBackgroundPixmap (dpy, window, None);
+      XMapWindow (dpy, window);
+      XFlush (dpy);
+      XIfEvent (dpy, &event, MapNotify_event_p, (XPointer) window);
+      XSync (dpy, True);
+    }
+  return pixmap;
+}
+
+
+/* When we are grabbing and manipulating a screen image, it's important that
+   we use the same colormap it originally had.  So, if the screensaver was
+   started with -install, we need to copy the contents of the default colormap
+   into the screensaver's colormap.
+ */
+void
+copy_default_colormap_contents (dpy, to_cmap, to_visual)
+     Display *dpy;
+     Colormap to_cmap;
+     Visual *to_visual;
+{
+  Screen *screen = DefaultScreenOfDisplay (dpy);
+  Visual *from_visual = DefaultVisualOfScreen (screen);
+  Colormap from_cmap = XDefaultColormapOfScreen (screen);
+
+  XColor *old_colors, *new_colors;
+  unsigned long *pixels;
+  XVisualInfo vi_in, *vi_out;
+  int out_count;
+  int from_cells, to_cells, max_cells;
+  int requested;
+  int i;
+
+  if (from_cmap == to_cmap)
+    return;
+
+  vi_in.screen = XScreenNumberOfScreen (screen);
+  vi_in.visualid = XVisualIDFromVisual (from_visual);
+  vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
+                          &vi_in, &out_count);
+  if (! vi_out) abort ();
+  from_cells = vi_out [0].colormap_size;
+  XFree ((char *) vi_out);
+
+  vi_in.screen = XScreenNumberOfScreen (screen);
+  vi_in.visualid = XVisualIDFromVisual (to_visual);
+  vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
+                          &vi_in, &out_count);
+  if (! vi_out) abort ();
+  to_cells = vi_out [0].colormap_size;
+  XFree ((char *) vi_out);
+
+  max_cells = (from_cells > to_cells ? to_cells : from_cells);
+
+  old_colors = (XColor *) calloc (sizeof (XColor), max_cells);
+  new_colors = (XColor *) calloc (sizeof (XColor), max_cells);
+  pixels = (unsigned long *) calloc (sizeof (unsigned long), max_cells);
+  for (i = 0; i < max_cells; i++)
+    old_colors[i].pixel = i;
+  XQueryColors (dpy, from_cmap, old_colors, max_cells);
+
+  requested = max_cells;
+  while (requested > 0)
+    {
+      if (XAllocColorCells (dpy, to_cmap, False, 0, 0, pixels, requested))
+       {
+         /* Got all the pixels we asked for. */
+         for (i = 0; i < requested; i++)
+           new_colors[i] = old_colors [pixels[i]];
+         XStoreColors (dpy, to_cmap, new_colors, requested);
+       }
+      else
+       {
+         /* We didn't get all/any of the pixels we asked for.  This time, ask
+            for half as many.  (If we do get all that we ask for, we ask for
+            the same number again next time, so we only do O(log(n)) server
+            roundtrips.) */
+         requested = requested / 2;
+       }
+    }
+
+  free (old_colors);
+  free (new_colors);
+  free (pixels);
+}
diff --git a/utils/hsv.c b/utils/hsv.c
new file mode 100644 (file)
index 0000000..c510912
--- /dev/null
@@ -0,0 +1,120 @@
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@netscape.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.
+ */
+
+/* This file contains some utility routines for randomly picking the colors
+   to hack the screen with.
+ */
+
+#include <X11/Xlib.h>
+
+void
+#if __STDC__
+hsv_to_rgb (int h, double s, double v,
+           unsigned short *r, unsigned short *g, unsigned short *b)
+#else
+hsv_to_rgb (h,s,v, r,g,b)
+     int h;                    /* 0 - 360   */
+     double s, v;              /* 0.0 - 1.0 */
+     unsigned short *r, *g, *b;        /* 0 - 65535 */
+#endif
+{
+  double H, S, V, R, G, B;
+  double p1, p2, p3;
+  double f;
+  int i;
+  S = s; V = v;
+  H = (h % 360) / 60.0;
+  i = H;
+  f = H - i;
+  p1 = V * (1 - S);
+  p2 = V * (1 - (S * f));
+  p3 = V * (1 - (S * (1 - f)));
+  if     (i == 0) { R = V;  G = p3; B = p1; }
+  else if (i == 1) { R = p2; G = V;  B = p1; }
+  else if (i == 2) { R = p1; G = V;  B = p3; }
+  else if (i == 3) { R = p1; G = p2; B = V;  }
+  else if (i == 4) { R = p3; G = p1; B = V;  }
+  else            { R = V;  G = p1; B = p2; }
+  *r = R * 65535;
+  *g = G * 65535;
+  *b = B * 65535;
+}
+
+void
+#if __STDC__
+rgb_to_hsv (unsigned short r, unsigned short g, unsigned short b,
+           int *h, double *s, double *v)
+#else
+rgb_to_hsv (r,g,b, h,s,v)
+     unsigned short r, g, b;   /* 0 - 65535 */
+     int *h;                   /* 0 - 360   */
+     double *s, *v;            /* 0.0 - 1.0 */
+#endif
+{
+  double R, G, B, H, S, V;
+  double cmax, cmin;
+  double cmm;
+  int imax;
+  R = ((double) r) / 65535.0;
+  G = ((double) g) / 65535.0;
+  B = ((double) b) / 65535.0;
+  cmax = R; cmin = G; imax = 1;
+  if  ( cmax < G ) { cmax = G; cmin = R; imax = 2; }
+  if  ( cmax < B ) { cmax = B; imax = 3; }
+  if  ( cmin > B ) { cmin = B; }
+  cmm = cmax - cmin;
+  V = cmax;
+  if (cmm == 0)
+    S = H = 0;
+  else
+    {
+      S = cmm / cmax;
+      if      (imax == 1) H =       (G - B) / cmm;
+      else if (imax == 2) H = 2.0 + (B - R) / cmm;
+      else if (imax == 3) H = 4.0 + (R - G) / cmm;
+      if (H < 0) H += 6.0;
+    }
+  *h = (H * 60.0);
+  *s = S;
+  *v = V;
+}
+
+
+void
+make_color_ramp (h1, s1, v1, h2, s2, v2,
+                pixels, npixels)
+     int h1, h2;                       /* 0 - 360   */
+     double s1, s2, v1, v2;            /* 0.0 - 1.0 */
+     XColor *pixels;
+     int npixels;
+{
+  int dh = (h2 - h1) / npixels;
+  double ds = (s2 - s1) / npixels;
+  double dv = (v2 - v1) / npixels;
+  int i;
+  for (i = 0; i < npixels; i++)
+    hsv_to_rgb ((h1 += dh), (s1 += ds), (v1 += dv),
+               &pixels [i].red, &pixels [i].green, &pixels [i].blue);
+}
+
+
+void
+cycle_hue (color, degrees)
+     XColor *color;
+     int degrees;
+{
+  int h;
+  double s, v;
+  rgb_to_hsv (color->red, color->green, color->blue,
+             &h, &s, &v);
+  h = (h + degrees) % 360;
+  hsv_to_rgb (h, s, v, &color->red, &color->green, &color->blue);
+}
diff --git a/utils/resources.c b/utils/resources.c
new file mode 100644 (file)
index 0000000..02c499b
--- /dev/null
@@ -0,0 +1,221 @@
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@netscape.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.
+ */
+
+#if __STDC__
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xresource.h>
+
+/* Resource functions.  Assumes: */
+
+extern char *progname;
+extern char *progclass;
+extern XrmDatabase db;
+
+#if __STDC__
+char *get_string_resource (char *res_name, char *res_class);
+int parse_time (char *string, Bool seconds_default_p, Bool silent_p);
+static unsigned int get_time_resource (char *res_name, char *res_class,
+                                      Bool sec_p);
+#endif
+
+#ifndef isupper
+# define isupper(c)  ((c) >= 'A' && (c) <= 'Z')
+#endif
+#ifndef _tolower
+# define _tolower(c)  ((c) - 'A' + 'a')
+#endif
+
+char *
+get_string_resource (res_name, res_class)
+     char *res_name, *res_class;
+{
+  XrmValue value;
+  char *type;
+  char full_name [1024], full_class [1024];
+  strcpy (full_name, progname);
+  strcat (full_name, ".");
+  strcat (full_name, res_name);
+  strcpy (full_class, progclass);
+  strcat (full_class, ".");
+  strcat (full_class, res_class);
+  if (XrmGetResource (db, full_name, full_class, &type, &value))
+    {
+      char *str = (char *) malloc (value.size + 1);
+      strncpy (str, (char *) value.addr, value.size);
+      str [value.size] = 0;
+      return str;
+    }
+  return 0;
+}
+
+Bool 
+get_boolean_resource (res_name, res_class)
+     char *res_name, *res_class;
+{
+  char *tmp, buf [100];
+  char *s = get_string_resource (res_name, res_class);
+  char *os = s;
+  if (! s) return 0;
+  for (tmp = buf; *s; s++)
+    *tmp++ = isupper (*s) ? _tolower (*s) : *s;
+  *tmp = 0;
+  free (os);
+
+  if (!strcmp (buf, "on") || !strcmp (buf, "true") || !strcmp (buf, "yes"))
+    return 1;
+  if (!strcmp (buf,"off") || !strcmp (buf, "false") || !strcmp (buf,"no"))
+    return 0;
+  fprintf (stderr, "%s: %s must be boolean, not %s.\n",
+          progname, res_class, buf);
+  return 0;
+}
+
+int 
+get_integer_resource (res_name, res_class)
+     char *res_name, *res_class;
+{
+  int val;
+  char c, *s = get_string_resource (res_name, res_class);
+  if (!s) return 0;
+  if (1 == sscanf (s, " %d %c", &val, &c))
+    {
+      free (s);
+      return val;
+    }
+  fprintf (stderr, "%s: %s must be an integer, not %s.\n",
+          progname, res_name, s);
+  free (s);
+  return 0;
+}
+
+double
+get_float_resource (res_name, res_class)
+     char *res_name, *res_class;
+{
+  double val;
+  char c, *s = get_string_resource (res_name, res_class);
+  if (! s) return 0.0;
+  if (1 == sscanf (s, " %lf %c", &val, &c))
+    {
+      free (s);
+      return val;
+    }
+  fprintf (stderr, "%s: %s must be a float, not %s.\n",
+          progname, res_name, s);
+  free (s);
+  return 0.0;
+}
+
+
+unsigned int
+get_pixel_resource (res_name, res_class, dpy, cmap)
+     char *res_name, *res_class;
+     Display *dpy;
+     Colormap cmap;
+{
+  XColor color;
+  char *s = get_string_resource (res_name, res_class);
+  if (!s) goto DEFAULT;
+
+  if (! XParseColor (dpy, cmap, s, &color))
+    {
+      fprintf (stderr, "%s: can't parse color %s\n", progname, s);
+      goto DEFAULT;
+    }
+  if (! XAllocColor (dpy, cmap, &color))
+    {
+      fprintf (stderr, "%s: couldn't allocate color %s\n", progname, s);
+      goto DEFAULT;
+    }
+  free (s);
+  return color.pixel;
+ DEFAULT:
+  if (s) free (s);
+  return (strcmp (res_class, "Background")
+         ? WhitePixel (dpy, DefaultScreen (dpy))
+         : BlackPixel (dpy, DefaultScreen (dpy)));
+}
+
+
+int
+parse_time (string, seconds_default_p, silent_p)
+     char *string;
+     Bool seconds_default_p, silent_p;
+{
+  unsigned int h, m, s;
+  char c;
+  if (3 == sscanf (string,   " %u : %2u : %2u %c", &h, &m, &s, &c))
+    ;
+  else if (2 == sscanf (string, " : %2u : %2u %c", &m, &s, &c) ||
+          2 == sscanf (string,    " %u : %2u %c", &m, &s, &c))
+    h = 0;
+  else if (1 == sscanf (string,       " : %2u %c", &s, &c))
+    h = m = 0;
+  else if (1 == sscanf (string,          " %u %c",
+                       (seconds_default_p ? &s : &m), &c))
+    {
+      h = 0;
+      if (seconds_default_p) m = 0;
+      else s = 0;
+    }
+  else
+    {
+      if (! silent_p)
+       fprintf (stderr, "%s: invalid time interval specification \"%s\".\n",
+                progname, string);
+      return -1;
+    }
+  if (s >= 60 && (h != 0 || m != 0))
+    {
+      if (! silent_p)
+       fprintf (stderr, "%s: seconds > 59 in \"%s\".\n", progname, string);
+      return -1;
+    }
+  if (m >= 60 && h > 0)
+    {
+      if (! silent_p)
+       fprintf (stderr, "%s: minutes > 59 in \"%s\".\n", progname, string);
+      return -1;
+    }
+  return ((h * 60 * 60) + (m * 60) + s);
+}
+
+static unsigned int 
+get_time_resource (res_name, res_class, sec_p)
+     char *res_name, *res_class;
+     Bool sec_p;
+{
+  int val;
+  char *s = get_string_resource (res_name, res_class);
+  if (!s) return 0;
+  val = parse_time (s, sec_p, False);
+  free (s);
+  return (val < 0 ? 0 : val);
+}
+
+unsigned int 
+get_seconds_resource (res_name, res_class)
+     char *res_name, *res_class;
+{
+  return get_time_resource (res_name, res_class, True);
+}
+
+unsigned int 
+get_minutes_resource (res_name, res_class)
+     char *res_name, *res_class;
+{
+  return get_time_resource (res_name, res_class, False);
+}
diff --git a/utils/spline.c b/utils/spline.c
new file mode 100644 (file)
index 0000000..d242d63
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 1987, 1988, 1989 Stanford University
+ *
+ * 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, and that the name of Stanford not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  Stanford makes no representations about
+ * the suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* This code came with the InterViews distribution, and was translated
+   from C++ to C by Matthieu Devin <devin@lucid.com> some time in 1992.
+ */
+
+#include <stdio.h>
+#include "spline.h"
+#if __STDC__
+#include <stdlib.h>
+#endif
+#include <math.h>
+
+/* Lifted from InterViews */
+#define SMOOTHNESS 1.0
+
+#if __STDC__
+static void no_more_memory (void);
+static void grow_spline_points (spline* s);
+static void mid_point (double x0, double y0, double x1, double y1,
+                      double *mx, double *my);
+static int can_approx_with_line (double x0, double y0, double x2,
+                                double y2, double x3, double y3);
+static void add_line (spline* s, double x0, double y0, double x1, double y1);
+static void add_bezier_arc (spline* s,
+                           double x0, double y0, double x1, double y1,
+                           double x2, double y2, double x3, double y3);
+static void third_point (double x0, double y0, double x1, double y1,
+                        double *tx, double *ty);
+static void calc_section (spline* s, double cminus1x, double cminus1y,
+                         double cx, double cy, double cplus1x, double cplus1y,
+                         double cplus2x, double cplus2y);
+
+#endif
+
+static void
+no_more_memory ()
+{
+  fprintf (stderr, "No more memory\n");
+  exit (1);
+}
+
+spline*
+make_spline (size)
+     u_int size;
+{
+  spline* s = (spline*)calloc (1, sizeof (spline));
+  if (!s)
+    no_more_memory ();
+  s->n_controls = size;
+  s->control_x = (double*)calloc (s->n_controls, sizeof (double));
+  s->control_y = (double*)calloc (s->n_controls, sizeof (double));
+
+  s->n_points = 0;
+  s->allocated_points = s->n_controls;
+  s->points = (XPoint*)calloc (s->allocated_points, sizeof (XPoint));
+
+  if (!s->control_x || !s->control_y || !s->points)
+    no_more_memory ();
+
+  return s;
+}
+
+static void
+grow_spline_points (s)
+     spline* s;
+{
+  s->allocated_points *= 2;
+  s->points =
+    (XPoint*)realloc (s->points, s->allocated_points * sizeof (XPoint));
+
+  if (!s->points)
+    no_more_memory ();
+}
+
+static void 
+mid_point (x0, y0, x1, y1, mx, my)
+     double x0, y0, x1, y1, *mx, *my;
+{
+  *mx = (x0 + x1) / 2.0;
+  *my = (y0 + y1) / 2.0;
+}
+
+static void 
+third_point (x0, y0, x1, y1, tx, ty)
+     double x0, y0, x1, y1, *tx, *ty;
+{
+  *tx = (2 * x0 + x1) / 3.0;
+  *ty = (2 * y0 + y1) / 3.0;
+}
+
+static int
+can_approx_with_line (x0, y0, x2, y2, x3, y3)
+     double x0, y0, x2, y2, x3, y3;
+{
+  double triangle_area, side_squared, dx, dy;
+  
+  triangle_area = x0 * y2 - x2 * y0 + x2 * y3 - x3 * y2 + x3 * y0 - x0 * y3;
+  /* actually 4 times the area. */
+  triangle_area *= triangle_area;
+  dx = x3 - x0;
+  dy = y3 - y0;
+  side_squared = dx * dx + dy * dy;
+  return triangle_area <= SMOOTHNESS * side_squared;
+}
+
+static void
+add_line (s, x0, y0, x1, y1)
+     spline* s;
+     double x0, y0, x1, y1;
+{
+  if (s->n_points >= s->allocated_points)
+    grow_spline_points (s);
+
+  if (s->n_points == 0)
+    {
+      s->points [s->n_points].x = x0;
+      s->points [s->n_points].y = y0;
+      s->n_points += 1;
+    }
+  s->points [s->n_points].x = x1;
+  s->points [s->n_points].y = y1;
+  s->n_points += 1;
+}
+
+static void 
+add_bezier_arc (s, x0, y0, x1, y1, x2, y2, x3, y3)
+     spline* s;
+     double x0, y0, x1, y1, x2, y2, x3, y3;
+{
+  double midx01, midx12, midx23, midlsegx, midrsegx, cx,
+  midy01, midy12, midy23, midlsegy, midrsegy, cy;
+    
+  mid_point (x0, y0, x1, y1, &midx01, &midy01);
+  mid_point (x1, y1, x2, y2, &midx12, &midy12);
+  mid_point (x2, y2, x3, y3, &midx23, &midy23);
+  mid_point (midx01, midy01, midx12, midy12, &midlsegx, &midlsegy);
+  mid_point (midx12, midy12, midx23, midy23, &midrsegx, &midrsegy);
+  mid_point (midlsegx, midlsegy, midrsegx, midrsegy, &cx, &cy);    
+
+  if (can_approx_with_line (x0, y0, midlsegx, midlsegy, cx, cy))
+    add_line (s, x0, y0, cx, cy);
+  else if ((midx01 != x1) || (midy01 != y1) || (midlsegx != x2)
+          || (midlsegy != y2) || (cx != x3) || (cy != y3))
+    add_bezier_arc (s, x0, y0, midx01, midy01, midlsegx, midlsegy, cx, cy);
+
+  if (can_approx_with_line (cx, cy, midx23, midy23, x3, y3))
+    add_line (s, cx, cy, x3, y3);
+  else if ((cx != x0) || (cy != y0) || (midrsegx != x1) || (midrsegy != y1)
+          || (midx23 != x2) || (midy23 != y2))  
+    add_bezier_arc (s, cx, cy, midrsegx, midrsegy, midx23, midy23, x3, y3);
+}
+
+static void
+calc_section (s, cminus1x, cminus1y, cx, cy, cplus1x, cplus1y,
+             cplus2x, cplus2y)
+     spline* s;
+     double cminus1x, cminus1y, cx, cy, cplus1x, cplus1y, cplus2x, cplus2y;
+{
+  double p0x, p1x, p2x, p3x, tempx,
+  p0y, p1y, p2y, p3y, tempy;
+  
+  third_point (cx, cy, cplus1x, cplus1y, &p1x, &p1y);
+  third_point (cplus1x, cplus1y, cx, cy, &p2x, &p2y);
+  third_point (cx, cy, cminus1x, cminus1y, &tempx, &tempy);
+  mid_point (tempx, tempy, p1x, p1y, &p0x, &p0y);
+  third_point (cplus1x, cplus1y, cplus2x, cplus2y, &tempx, &tempy);
+  mid_point (tempx, tempy, p2x, p2y, &p3x, &p3y);
+  add_bezier_arc (s, p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y);
+}
+
+void
+compute_spline (s)
+     spline* s;
+{
+  int i;
+  s->n_points = 0;
+  
+  if (s->n_controls < 3)
+    return;
+
+  calc_section (s, s->control_x [0], s->control_y [0], s->control_x [0],
+               s->control_y [0], s->control_x [0], s->control_y [0],
+               s->control_x [1], s->control_y [1]);
+  calc_section (s, s->control_x [0], s->control_y [0], s->control_x [0],
+               s->control_y [0], s->control_x [1], s->control_y [1],
+               s->control_x [2], s->control_y [2]);
+
+  for (i = 1; i < s->n_controls - 2; i++)
+    calc_section (s, s->control_x [i - 1], s->control_y [i - 1],
+                 s->control_x [i], s->control_y [i],
+                 s->control_x [i + 1], s->control_y [i + 1],
+                 s->control_x [i + 2], s->control_y [i + 2]);
+  
+  calc_section (s, s->control_x [i - 1], s->control_y [i - 1],
+               s->control_x [i], s->control_y [i],
+               s->control_x [i + 1], s->control_y [i + 1],
+               s->control_x [i + 1], s->control_y [i + 1]);
+  calc_section (s, s->control_x [i], s->control_y [i],
+               s->control_x [i + 1], s->control_y [i + 1],
+               s->control_x [i + 1], s->control_y [i + 1],
+               s->control_x [i + 1], s->control_y [i + 1]);
+}
+
+void 
+compute_closed_spline (s)
+     spline *s;
+{
+  int i;
+  s->n_points = 0;
+
+  if (s->n_controls < 3) 
+    return;
+
+  calc_section (s,
+               s->control_x [s->n_controls - 1],
+               s->control_y [s->n_controls - 1],
+               s->control_x [0], s->control_y [0],
+               s->control_x [1], s->control_y [1],
+               s->control_x [2], s->control_y [2]);
+
+  for (i = 1; i < s->n_controls - 2; i++)
+    calc_section (s, s->control_x [i - 1], s->control_y [i - 1],
+                 s->control_x [i], s->control_y [i],
+                 s->control_x [i + 1], s->control_y [i + 1],
+                 s->control_x [i + 2], s->control_y [i + 2]);
+      
+  calc_section (s, s->control_x [i - 1], s->control_y [i - 1],
+               s->control_x [i], s->control_y [i],
+               s->control_x [i + 1], s->control_y [i + 1],
+               s->control_x [0], s->control_y [0]);
+  calc_section (s, s->control_x [i], s->control_y [i],
+               s->control_x [i + 1], s->control_y [i + 1],
+               s->control_x [0], s->control_y [0],
+               s->control_x [1], s->control_y [1]);
+}
+
+void
+just_fill_spline (s)
+     spline *s;
+{
+  int i;
+
+  while (s->allocated_points < s->n_controls + 1)
+    grow_spline_points (s);
+    
+  for (i = 0; i < s->n_controls; i++)
+    {
+      s->points [i].x = s->control_x [i];
+      s->points [i].y = s->control_y [i];
+    }
+  s->points [s->n_controls].x = s->control_x [0];
+  s->points [s->n_controls].y = s->control_y [0];
+  s->n_points = s->n_controls + 1;
+}
+
+void
+append_spline_points (s1, s2)
+     spline *s1, *s2;
+{
+  int i;
+  while (s1->allocated_points < s1->n_points + s2->n_points)
+    grow_spline_points (s1);
+  for (i = s1->n_points; i < s1->n_points + s2->n_points; i++)
+    {
+      s1->points [i].x = s2->points [i - s1->n_points].x;
+      s1->points [i].y = s2->points [i - s1->n_points].y;
+    }
+  s1->n_points = s1->n_points + s2->n_points;
+}
+
+void
+spline_bounding_box (s, rectangle_out)
+     spline* s;
+     XRectangle* rectangle_out;
+{
+  int min_x;
+  int max_x;
+  int min_y;
+  int max_y;
+  int i;
+
+  if (s->n_points == 0)
+    {
+      rectangle_out->x = 0;
+      rectangle_out->y = 0;
+      rectangle_out->width = 0;
+      rectangle_out->height = 0;
+    }
+
+  min_x = s->points [0].x;
+  max_x = min_x;
+  min_y = s->points [0].y;
+  max_y = min_y;
+
+  for (i = 1; i < s->n_points; i++)
+    {
+      if (s->points [i].x < min_x)
+       min_x = s->points [i].x;
+      if (s->points [i].x > max_x)
+       max_x = s->points [i].x;
+      if (s->points [i].y < min_y)
+       min_y = s->points [i].y;
+      if (s->points [i].y > max_y)
+       max_y = s->points [i].y;
+    }
+  rectangle_out->x = min_x;
+  rectangle_out->y = min_y;
+  rectangle_out->width = max_x - min_x;
+  rectangle_out->height = max_y - min_y;
+}
diff --git a/utils/spline.h b/utils/spline.h
new file mode 100644 (file)
index 0000000..a8a04d5
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1987, 1988, 1989 Stanford University
+ *
+ * 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, and that the name of Stanford not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  Stanford makes no representations about
+ * the suitability of this software for any purpose.  It is provided "as is"
+ * without express or implied warranty.
+ *
+ * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* This code came with the InterViews distribution, and was translated
+   from C++ to C by Matthieu Devin <devin@lucid.com> some time in 1992.
+ */
+
+#ifndef _SPLINE_H_
+#define _SPLINE_H_
+
+#include <X11/Xlib.h>
+
+#if __STDC__
+# define P(x)x
+#else
+# define P(x)()
+#endif
+
+typedef struct _spline
+{
+  /* input */
+  u_int                n_controls;
+  double*      control_x;
+  double*      control_y;
+
+  /* output */
+  u_int                n_points;
+  XPoint*      points;
+  u_int                allocated_points;
+} spline;
+
+spline* make_spline P((u_int size));
+void compute_spline P((spline* s));
+void compute_closed_spline P((spline* s));
+void just_fill_spline P((spline* s));
+void append_spline_points P((spline* s1, spline* s2));
+void spline_bounding_box P((spline* s, XRectangle* rectangle_out));
+
+#undef P
+#endif /* _SPLINE_H_ */
diff --git a/utils/usleep.c b/utils/usleep.c
new file mode 100644 (file)
index 0000000..30e7f15
--- /dev/null
@@ -0,0 +1,97 @@
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@netscape.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.
+ */
+
+#if __STDC__
+#include <stdlib.h>
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/Xos.h>   /* lazy way out */
+
+/* usleep() doesn't exist everywhere, and select() is faster anyway.
+ */
+
+#ifndef VMS
+
+#ifdef NO_SELECT
+  /* If you don't have select() or usleep(), I guess you lose...
+     Maybe you have napms() instead?  Let me know.
+   */
+void
+screenhack_usleep (usecs)
+     unsigned long usecs;
+{
+  usleep (usecs);
+}
+
+#else /* ! NO_SELECT */
+
+void
+screenhack_usleep (usecs)
+     unsigned long usecs;
+{
+  struct timeval tv;
+  tv.tv_sec  = usecs / 1000000L;
+  tv.tv_usec = usecs % 1000000L;
+  (void) select (0, 0, 0, 0, &tv);
+}
+
+#endif /* ! NO_SELECT */
+
+#else /* VMS */
+
+#define SEC_DELTA  "0000 00:00:01.00"
+#define TICK_DELTA "0000 00:00:00.08"
+static int bin_sec_delta[2], bin_tick_delta[2], deltas_set = 0;
+
+static void
+set_deltas ()
+{
+  int status;
+  extern int SYS$BINTIM ();
+  $DESCRIPTOR (str_sec_delta,  SEC_DELTA);
+  $DESCRIPTOR (str_tick_delta, TICK_DELTA);
+  if (!deltas_set)
+    {
+      status = SYS$BINTIM (&str_sec_delta, &bin_sec_delta);
+      if (!(status & 1))
+       {
+         fprintf (stderr, "%s: cannot convert delta time ", progname);
+         fprintf (stderr, SEC_DELTA);
+         fprintf (stderr, "; status code = %d\n", status);
+         exit (status);
+       }
+      status = SYS$BINTIM (&str_tick_delta, &bin_tick_delta);
+      if (!(status & 1))
+       {
+         fprintf (stderr, "%s: cannot convert delta time ", progname);
+         fprintf (stderr, TICK_DELTA);
+         fprintf (stderr, "; status code = %d\n", status);
+         exit (status);
+       }
+      deltas_set = 1;
+    }
+}
+
+void
+screenhack_usleep (usecs)
+     unsigned long usecs;
+{
+  int status, *bin_delta;
+  extern int SYS$SCHWDK (), SYS$HIBER (); 
+  
+  if (!deltas_set) set_deltas ();
+  bin_delta = (usecs == TICK_INTERVAL) ? &bin_tick_delta : &bin_sec_delta;
+  status = SYS$SCHDWK (0, 0, bin_delta, 0);
+  if ((status & 1)) (void) SYS$HIBER ();
+}
+
+#endif /*VMS */
diff --git a/utils/version.h b/utils/version.h
new file mode 100644 (file)
index 0000000..a56e38a
--- /dev/null
@@ -0,0 +1,2 @@
+static char *screensaver_id =
+       "@(#)xscreensaver 1.26, by Jamie Zawinski (jwz@netscape.com)";
diff --git a/utils/visual.c b/utils/visual.c
new file mode 100644 (file)
index 0000000..cc8b572
--- /dev/null
@@ -0,0 +1,288 @@
+/* xscreensaver, Copyright (c) 1993, 1994, 1995 
+ * Jamie Zawinski <jwz@netscape.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.
+ */
+
+/* This file contains some code for intelligently picking the best visual
+   (where "best" is biased in the direction of high color counts...)
+ */
+
+#if __STDC__
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#endif
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#if __STDC__
+# define P(x)x
+#else
+#define P(x)()
+#endif
+
+#ifndef isupper
+# define isupper(c)  ((c) >= 'A' && (c) <= 'Z')
+#endif
+#ifndef _tolower
+# define _tolower(c)  ((c) - 'A' + 'a')
+#endif
+
+extern char *progname;
+extern char *get_string_resource P((char *, char *));
+
+static Visual *pick_best_visual P ((Screen *));
+static Visual *pick_best_visual_of_class P((Screen *, int));
+static Visual *id_to_visual P((Screen *, int));
+static int screen_number P((Screen *));
+static Visual *id_to_visual P((Screen *screen, int id));
+int get_visual_depth P((Display *dpy, Visual *visual));
+
+
+#define DEFAULT_VISUAL -1
+#define BEST_VISUAL    -2
+#define SPECIFIC_VISUAL        -3
+
+Visual *
+get_visual_resource (dpy, name, class)
+     Display *dpy;
+     char *name, *class;
+{
+  Screen *screen = DefaultScreenOfDisplay (dpy);
+  char c, *v = get_string_resource (name, class);
+  char *tmp;
+  int vclass;
+  unsigned long id;
+
+  if (v)
+    for (tmp = v; *tmp; tmp++)
+      if (isupper (*tmp)) *tmp = _tolower (*tmp);
+
+  if (!v)                                        vclass = BEST_VISUAL;
+  else if (!strcmp (v, "default"))               vclass = DEFAULT_VISUAL;
+  else if (!strcmp (v, "best"))                  vclass = BEST_VISUAL;
+  else if (!strcmp (v, "staticgray"))            vclass = StaticGray;
+  else if (!strcmp (v, "staticcolor"))           vclass = StaticColor;
+  else if (!strcmp (v, "truecolor"))             vclass = TrueColor;
+  else if (!strcmp (v, "grayscale"))             vclass = GrayScale;
+  else if (!strcmp (v, "pseudocolor"))           vclass = PseudoColor;
+  else if (!strcmp (v, "directcolor"))           vclass = DirectColor;
+  else if (1 == sscanf (v, " %ld %c", &id, &c))          vclass = SPECIFIC_VISUAL;
+  else if (1 == sscanf (v, " 0x%lx %c", &id, &c)) vclass = SPECIFIC_VISUAL;
+  else
+    {
+      fprintf (stderr, "%s: unrecognized visual \"%s\".\n", progname, v);
+      vclass = DEFAULT_VISUAL;
+    }
+  if (v) free (v);
+
+  if (vclass == DEFAULT_VISUAL)
+    return DefaultVisualOfScreen (screen);
+  else if (vclass == BEST_VISUAL)
+    return pick_best_visual (screen);
+  else if (vclass == SPECIFIC_VISUAL)
+    {
+      Visual *visual = id_to_visual (screen, id);
+      if (visual) return visual;
+      fprintf (stderr, "%s: no visual with id 0x%x.\n", progname,
+              (unsigned int) id);
+      return DefaultVisualOfScreen (screen);
+    }
+  else
+    {
+      Visual *visual = pick_best_visual_of_class (screen, vclass);
+      if (visual) return visual;
+      fprintf (stderr, "%s: no visual of class %s.\n", progname, v);
+      return DefaultVisualOfScreen (screen);
+    }
+}
+
+static Visual *
+pick_best_visual (screen)
+       Screen *screen;
+{
+  /* The "best" visual is the one on which we can allocate the largest
+     range and number of colors.
+
+     Therefore, a TrueColor visual which is at least 16 bits deep is best.
+     (The assumption here being that a TrueColor of less than 16 bits is
+     really just a PseudoColor visual with a pre-allocated color cube.)
+
+     The next best thing is a PseudoColor visual of any type.  After that
+     come the non-colormappable visuals, and non-color visuals.
+   */
+  Display *dpy = DisplayOfScreen (screen);
+  Visual *visual;
+  if ((visual = pick_best_visual_of_class (screen, TrueColor)) &&
+      get_visual_depth (dpy, visual) >= 16)
+    return visual;
+  if ((visual = pick_best_visual_of_class (screen, PseudoColor)))
+    return visual;
+  if ((visual = pick_best_visual_of_class (screen, TrueColor)))
+    return visual;
+  if ((visual = pick_best_visual_of_class (screen, DirectColor)))
+    return visual;
+  if ((visual = pick_best_visual_of_class (screen, GrayScale)))
+    return visual;
+  if ((visual = pick_best_visual_of_class (screen, StaticGray)))
+    return visual;
+  return DefaultVisualOfScreen (screen);
+}
+
+static Visual *
+pick_best_visual_of_class (screen, visual_class)
+     Screen *screen;
+     int visual_class;
+{
+  /* The best visual of a class is the one which on which we can allocate
+     the largest range and number of colors, which means the one with the
+     greatest depth and number of cells.
+   */
+  Display *dpy = DisplayOfScreen (screen);
+  XVisualInfo vi_in, *vi_out;
+  int out_count;
+
+  vi_in.class = visual_class;
+  vi_in.screen = screen_number (screen);
+  vi_out = XGetVisualInfo (dpy, (VisualClassMask | VisualScreenMask),
+                          &vi_in, &out_count);
+  if (vi_out)
+    {
+      /* choose the 'best' one, if multiple */
+      int i, best;
+      Visual *visual;
+      for (i = 0, best = 0; i < out_count; i++)
+       /* It's better if it's deeper, or if it's the same depth with
+          more cells (does that ever happen?  Well, it could...) */
+       if ((vi_out [i].depth > vi_out [best].depth) ||
+           ((vi_out [i].depth == vi_out [best].depth) &&
+            (vi_out [i].colormap_size > vi_out [best].colormap_size)))
+         best = i;
+      visual = vi_out [best].visual;
+      XFree ((char *) vi_out);
+      return visual;
+    }
+  else
+    return 0;
+}
+
+static Visual *
+id_to_visual (screen, id)
+     Screen *screen;
+     int id;
+{
+  Display *dpy = DisplayOfScreen (screen);
+  XVisualInfo vi_in, *vi_out;
+  int out_count;
+  vi_in.screen = screen_number (screen);
+  vi_in.visualid = id;
+  vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
+                          &vi_in, &out_count);
+  if (vi_out)
+    {
+      Visual *v = vi_out[0].visual;
+      XFree ((char *) vi_out);
+      return v;
+    }
+  return 0;
+}
+
+int
+get_visual_depth (dpy, visual)
+     Display *dpy;
+     Visual *visual;
+{
+  XVisualInfo vi_in, *vi_out;
+  int out_count, d;
+  vi_in.screen = DefaultScreen (dpy);
+  vi_in.visualid = XVisualIDFromVisual (visual);
+  vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
+                          &vi_in, &out_count);
+  if (! vi_out) abort ();
+  d = vi_out [0].depth;
+  XFree ((char *) vi_out);
+  return d;
+}
+
+
+int
+get_visual_class (dpy, visual)
+     Display *dpy;
+     Visual *visual;
+{
+  XVisualInfo vi_in, *vi_out;
+  int out_count, c;
+  vi_in.screen = DefaultScreen (dpy);
+  vi_in.visualid = XVisualIDFromVisual (visual);
+  vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
+                          &vi_in, &out_count);
+  if (! vi_out) abort ();
+  c = vi_out [0].class;
+  XFree ((char *) vi_out);
+  return c;
+}
+
+void
+describe_visual (f, dpy, visual)
+     FILE *f;
+     Display *dpy;
+     Visual *visual;
+{
+  Screen *screen = DefaultScreenOfDisplay (dpy);
+  XVisualInfo vi_in, *vi_out;
+  int out_count;
+  vi_in.screen = screen_number (screen);
+  vi_in.visualid = XVisualIDFromVisual (visual);
+  vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
+                          &vi_in, &out_count);
+  if (! vi_out) abort ();
+  fprintf (f, "0x%02x (%s depth: %2d, cmap: %3d)\n",
+          (unsigned int) vi_out->visualid,
+          (vi_out->class == StaticGray  ? "StaticGray, " :
+           vi_out->class == StaticColor ? "StaticColor," :
+           vi_out->class == TrueColor   ? "TrueColor,  " :
+           vi_out->class == GrayScale   ? "GrayScale,  " :
+           vi_out->class == PseudoColor ? "PseudoColor," :
+           vi_out->class == DirectColor ? "DirectColor," :
+                                          "UNKNOWN:    "),
+          vi_out->depth, vi_out->colormap_size /*, vi_out->bits_per_rgb*/);
+  XFree ((char *) vi_out);
+}
+
+static int
+screen_number (screen)
+       Screen *screen;
+{
+  Display *dpy = DisplayOfScreen (screen);
+  int i;
+  for (i = 0; i < ScreenCount (dpy); i++)
+    if (ScreenOfDisplay (dpy, i) == screen)
+      return i;
+  abort ();
+}
+
+int
+visual_cells (dpy, visual)
+       Display *dpy;
+       Visual *visual;
+{
+  XVisualInfo vi_in, *vi_out;
+  int out_count, c;
+  vi_in.screen = DefaultScreen (dpy);
+  vi_in.visualid = XVisualIDFromVisual (visual);
+  vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
+                          &vi_in, &out_count);
+  if (! vi_out) abort ();
+  c = vi_out [0].colormap_size;
+  XFree ((char *) vi_out);
+  return c;
+}
diff --git a/utils/xroger.c b/utils/xroger.c
new file mode 100644 (file)
index 0000000..039a97f
--- /dev/null
@@ -0,0 +1,106 @@
+/* xscreensaver, Copyright (c) 1991-1993 Jamie Zawinski <jwz@netscape.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.
+ */
+
+#include <X11/Xlib.h>
+
+#if __STDC__
+static void crossbones (Display *, Window, GC, int x, int y, int w, int h);
+#endif
+
+static void
+crossbones (dpy, window, draw_gc, x, y, w, h)
+     Display *dpy;
+     Window window;
+     GC draw_gc;
+     int x, y, w, h;
+{
+  double xscale = w / 440.0;
+  double yscale = h / 216.0;
+  XPoint points [6];
+  points [0].x = x + xscale * 20;
+  points [0].y = y + yscale * 10;
+  points [1].x = x + xscale * 120;
+  points [1].y = y + yscale * 10;
+  points [2].x = x + xscale * 243;
+  points [2].y = y + yscale * 93;
+  points [3].x = x + xscale * 57;
+  points [3].y = y + yscale * 210;
+  points [4].x = x + xscale * 20;
+  points [4].y = y + yscale * 210;
+  points [5].x = x + xscale * 175;
+  points [5].y = y + yscale * 113;
+  XFillPolygon (dpy, window, draw_gc, points, 6, Complex, CoordModeOrigin);
+  points [0].x = x + xscale * 197;
+  points [0].y = y + yscale * 127;
+  points [1].x = x + xscale * 384;
+  points [1].y = y + yscale * 10;
+  points [2].x = x + xscale * 420;
+  points [2].y = y + yscale * 10;
+  points [3].x = x + xscale * 265;
+  points [3].y = y + yscale * 108;
+  points [4].x = x + xscale * 420;
+  points [4].y = y + yscale * 210;
+  points [5].x = x + xscale * 320;
+  points [5].y = y + yscale * 210;
+  XFillPolygon (dpy, window, draw_gc, points, 6, Complex, CoordModeOrigin);
+}
+
+
+void
+skull (dpy, window, draw_gc, erase_gc, x, y, w, h)
+     Display *dpy;
+     Window window;
+     GC draw_gc, erase_gc;
+     int x, y, w, h;
+{
+  XPoint points [3];
+  crossbones (dpy, window, draw_gc, x, y+h/2, w, h/2);
+  x += w/100;
+  y += h/15;
+  XFillArc (dpy, window, draw_gc, (int) (x + (w * 0.3)), y, w/2, h/2,
+           -40*64, 260*64);
+  XFillRectangle (dpy, window, draw_gc, (int) (x + (w * 0.35)), y + h/5,
+                 (int) (w * 0.4), h/5);
+  XFillRectangle (dpy, window, draw_gc, (int) (x + (w * 0.375)),
+                 (int) (y + (h * 0.425)), w / 20, h / 20);
+  XFillRectangle (dpy, window, draw_gc, (int) (x + (w * 0.495)),
+                 (int) (y + (h * 0.425)), w / 20, h / 20);
+  XFillRectangle (dpy, window, draw_gc, (int) (x + (w * 0.555)),
+                 (int) (y + (h * 0.425)), w / 20, h / 20);
+  XFillRectangle (dpy, window, draw_gc, (int) (x + (w * 0.675)),
+                 (int) (y + (h * 0.425)), w / 20, h / 20);
+  points [0].x = x + (w * 0.435);
+  points [0].y = y + (h * 0.425);
+  points [1].x = x + (w * 0.485);
+  points [1].y = points [0].y;
+  points [2].x = (points [0].x + points [1].x) / 2;
+  points [2].y = points [0].y + h/10;
+  XFillPolygon (dpy, window, draw_gc, points, 3, Complex, CoordModeOrigin);
+  points [0].x = x + (w * 0.615);
+  points [1].x = x + (w * 0.665);
+  points [2].x = (points [0].x + points [1].x) / 2;
+  XFillPolygon (dpy, window, draw_gc, points, 3, Complex, CoordModeOrigin);
+  points [0].x = x + (w * 0.52);
+  points [0].y = y + (h * 0.35);
+  points [1].x = points [0].x - (w * 0.05);
+  points [1].y = points [0].y;
+  points [2].x = points [0].x;
+  points [2].y = points [0].y - (w * 0.10);
+  XFillPolygon (dpy, window, erase_gc, points, 3, Complex, CoordModeOrigin);
+  points [0].x = x + (w * 0.57);
+  points [1].x = x + (w * 0.62);
+  points [2].x = points [0].x;
+  XFillPolygon (dpy, window, erase_gc, points, 3, Complex, CoordModeOrigin);
+  XFillArc (dpy, window, erase_gc, x + ((int) (w * 0.375)), y + h/7,
+           w/10, h/10, 0, 360*64);
+  XFillArc (dpy, window, erase_gc, x + ((int) (w * 0.615)), y + h/7,
+           w/10, h/10, 0, 360*64);
+}
diff --git a/utils/yarandom.c b/utils/yarandom.c
new file mode 100644 (file)
index 0000000..228b81c
--- /dev/null
@@ -0,0 +1,72 @@
+/* ya_random -- Yet Another Random Number Generator.
+
+   The unportable mess that is rand(), random(), drand48() and friends led me
+   to ask Phil Karlton <karlton@netscape.com> what the Right Thing to Do was.
+   He responded with this.  It is non-cryptographically secure, reasonably
+   random (more so than anything that is in any C library), and very fast.
+
+   I don't understand how it works at all, but he says "look at Knuth,
+   Vol. 2 (original edition), page 26, Algorithm A.  In this case n=55,
+   k=20 and m=2^32."
+
+   So there you have it.
+ */
+
+#include <unistd.h>   /* for getpid() */
+#include <sys/time.h> /* for gettimeofday() */
+
+
+/* The following 'random' numbers are taken from CRC, 18th Edition, page 622.
+   Each array element was taken from the corresponding line in the table,
+   except that a[0] was from line 100. 8s and 9s in the table were simply
+   skipped. The high order digit was taken mod 4.
+ */
+#define VectorSize 55
+static unsigned int a[VectorSize] = {
+ 035340171546, 010401501101, 022364657325, 024130436022, 002167303062, /*  5 */
+ 037570375137, 037210607110, 016272055420, 023011770546, 017143426366, /* 10 */
+ 014753657433, 021657231332, 023553406142, 004236526362, 010365611275, /* 14 */
+ 007117336710, 011051276551, 002362132524, 001011540233, 012162531646, /* 20 */
+ 007056762337, 006631245521, 014164542224, 032633236305, 023342700176, /* 25 */
+ 002433062234, 015257225043, 026762051606, 000742573230, 005366042132, /* 30 */
+ 012126416411, 000520471171, 000725646277, 020116577576, 025765742604, /* 35 */
+ 007633473735, 015674255275, 017555634041, 006503154145, 021576344247, /* 40 */
+ 014577627653, 002707523333, 034146376720, 030060227734, 013765414060, /* 45 */
+ 036072251540, 007255221037, 024364674123, 006200353166, 010126373326, /* 50 */
+ 015664104320, 016401041535, 016215305520, 033115351014, 017411670323  /* 55 */
+};
+
+static int i1, i2;
+
+unsigned int ya_random()
+{
+  register int ret = a[i1] + a[i2];
+  a[i1] = ret;
+  i1 = i1 >= VectorSize ? 0 : i1 + 1;
+  i2 = i2 >= VectorSize ? 0 : i2 + 1;
+  return ret;
+}
+
+void ya_rand_init(seed)
+   register unsigned int seed;
+{
+  int i;
+  if (seed == 0)
+    {
+      struct timeval tp;
+      struct timezone tzp;
+      gettimeofday(&tp, &tzp);
+      /* ignore overflow */
+      seed = (999*tp.tv_sec) + (1001*tp.tv_usec) + (1003 * getpid());
+    }
+
+  a[0] += seed;
+  for (i = 1; i < VectorSize; i++)
+    {
+      seed = a[i-1]*1001 + seed*999;
+      a[i] += seed;
+    }
+
+  i1 = a[0] % VectorSize;
+  i2 = (i1 + 024) % VectorSize;
+}
diff --git a/utils/yarandom.h b/utils/yarandom.h
new file mode 100644 (file)
index 0000000..53b22fd
--- /dev/null
@@ -0,0 +1,19 @@
+#undef random
+#undef rand
+#undef drand48
+#undef srandom
+#undef srand
+#undef srand48
+
+#define random()   ya_random()
+#define srandom(i) ya_rand_init(0)
+
+#undef P
+#if __STDC__
+# define P(x)x
+#else
+# define P(x)()
+#endif
+
+extern unsigned int ya_random P((void));
+extern void ya_rand_init P((unsigned int));