http://ftp.x.org/contrib/applications/xscreensaver-3.10.tar.gz
authorZygo Blaxell <zblaxell@hungrycats.org>
Mon, 2 Mar 2009 05:42:33 +0000 (00:42 -0500)
committerZygo Blaxell <zblaxell@hungrycats.org>
Mon, 2 Mar 2009 05:42:33 +0000 (00:42 -0500)
-rw-r--r-- 1 zblaxell zblaxell 1085749 Apr 26  1999 xscreensaver-3.10.tar.gz
0ef47faea495b2452c4ffee0c809d8205e314864  xscreensaver-3.10.tar.gz

41 files changed:
README
configure
configure.in
driver/Makefile.in
driver/XScreenSaver.ad.in
driver/XScreenSaver_ad.h
driver/passwd-pwent.c
driver/passwd.c
driver/prefs.c
driver/subprocs.c
driver/windows.c
driver/xscreensaver-command.man
driver/xscreensaver-demo.man
driver/xscreensaver.c
driver/xscreensaver.h
driver/xscreensaver.man
hacks/Makefile.in
hacks/compile_axp.com
hacks/compile_decc.com
hacks/critical.c
hacks/glx/Makefile.in
hacks/glx/glplanet.c
hacks/glx/pulsar.c [new file with mode: 0644]
hacks/images/matrix.xbm [new file with mode: 0644]
hacks/images/matrix.xpm [new file with mode: 0644]
hacks/penrose.c
hacks/penrose.man
hacks/phosphor.c [new file with mode: 0644]
hacks/screenhack.c
hacks/slip.c
hacks/sphere.c
hacks/squiral.c
hacks/t3d.c
hacks/xflame.c
hacks/xlyap.c
hacks/xmatrix.c [new file with mode: 0644]
setup.com
utils/colors.c
utils/version.h
xscreensaver.lsm
xscreensaver.spec

diff --git a/README b/README
index 889044378762937c5232784ca195ae5e923ad717..417e248a26821e8165e3088f190f2c556f4afa91 100644 (file)
--- a/README
+++ b/README
@@ -77,6 +77,17 @@ http://www.jwz.org/xscreensaver/.
 
                               ============
 
+Changes since 3.09:   * Added `phosphor', `xmatrix', and `pulsar' hacks.
+                      * Fixed a bug in the color allocator that sometimes
+                        caused `starfish' to fall back to monochrome.
+                      * Reduced the amount of code that runs before root
+                        privileges are disavowed: "normal" and "shadow"
+                        passwords now do some initialization as root, but the
+                        PAM and Kerberos authorization schemes will be
+                        initialized while running as "nobody".  Supposedly 
+                        this closes a potential security hole when using
+                        Kerberos.
+                      * Added some more sanity checking to configure.
 Changes since 3.08:   * Added `compass', `squiral', `xflame', `wander',
                         `spotlight', and `critical' hacks.
                       * Added some new modes to `decayscreen'.
index 43a972c2ee534dd6e352cea86695085ce1b30ede..5d61f180ad3f110a752a3164d55d24bc4fa8d145 100755 (executable)
--- a/configure
+++ b/configure
@@ -8327,7 +8327,60 @@ eval HACKDIR=${HACKDIR}
 bindir=`echo  "${bindir}"  | sed 's@/$@@;s@//*@/@g'`
 HACKDIR=`echo "${HACKDIR}" | sed 's@/$@@;s@//*@/@g'`
 
+
+# Sanity check the subdir
+for bad_choice in xscreensaver xscreensaver-demo xscreensaver-command ; do
+  if test "${HACKDIR}" = "${bindir}/${bad_choice}" ; then
+    echo ""
+    { echo "configure: error: \"--enable-subdir=${bindir}/${bad_choice}\" won't work.
+                   There will be an executable installed with that name, so
+                   that can't be the name of a directory as well.  Please
+                   re-configure with a different directory name." 1>&2; exit 1; }
+  fi
+done
+
+
+do_dir_warning=no
+
+# Now let's see if there's a previous RPM version already installed.  Blargh!
+
+# M4 sucks!!
+
+rpmv=`(rpm -qv xscreensaver) 2>&- | \
+      sed 's/^xscreensaver-\([0-9][0-9]*[.][0-9][0-9]*\)-[0-9][0-9]*$/\1/'`
+
+
+if test \! -z "$rpmv" ; then
+  rpmbdir=`rpm -ql xscreensaver | sed -n 's@^\(.*\)/xscreensaver-demo$@\1@p'`
+  rpmhdir=`rpm -ql xscreensaver | sed -n 's@^\(.*\)/attraction$@\1@p'`
+
+  warning=no
+  warnL "There is already an installed RPM of xscreensaver $rpmv"
+  warn2 "on this system.  You might want to remove it (with"
+  warn2 '"rpm -ve xscreensaver") before running "make install"'
+  warn2 "from this directory."
+  echo ""
+  warn2 "Alternately, you could build this version of xscreensaver"
+  warn2 'as an RPM, and then install that.  An "xscreensaver.spec"'
+  warn2 "file is included.  See the RPM documentation for more info."
+  echo ""
+
+  if test "$rpmbdir" = "$rpmhdir" ; then
+    warn2 "The RPM version was installed in $rpmbdir."
+  else
+    warn2 "The RPM version was installed in $rpmbdir,"
+    warn2 "with demos in $rpmhdir."
+  fi
+
+  do_dir_warning=yes
+fi
+
+
 if test "${bindir}" = "${HACKDIR}" ; then
+  do_dir_warning=yes
+fi
+
+if test "$do_dir_warning" = yes; then
   echo ""
   echo "$warnsep"
   echo ""
index 39a30f9daf980d8f22962c02c833d03dab3dee55..75a8fe321785428a76d7c25d05815aee43202f25 100644 (file)
@@ -2180,7 +2180,60 @@ eval HACKDIR=${HACKDIR}
 bindir=`echo  "${bindir}"  | sed 's@/$@@;s@//*@/@g'`
 HACKDIR=`echo "${HACKDIR}" | sed 's@/$@@;s@//*@/@g'`
 
+
+# Sanity check the subdir
+for bad_choice in xscreensaver xscreensaver-demo xscreensaver-command ; do
+  if test "${HACKDIR}" = "${bindir}/${bad_choice}" ; then
+    echo ""
+    AC_MSG_ERROR([\"--enable-subdir=${bindir}/${bad_choice}\" won't work.
+                   There will be an executable installed with that name, so
+                   that can't be the name of a directory as well.  Please
+                   re-configure with a different directory name.])
+  fi
+done
+
+
+do_dir_warning=no
+
+# Now let's see if there's a previous RPM version already installed.  Blargh!
+
+# M4 sucks!!
+changequote(X,Y)
+rpmv=`(rpm -qv xscreensaver) 2>&- | \
+      sed 's/^xscreensaver-\([0-9][0-9]*[.][0-9][0-9]*\)-[0-9][0-9]*$/\1/'`
+changequote([,])
+
+if test \! -z "$rpmv" ; then
+  rpmbdir=`rpm -ql xscreensaver | sed -n 's@^\(.*\)/xscreensaver-demo$@\1@p'`
+  rpmhdir=`rpm -ql xscreensaver | sed -n 's@^\(.*\)/attraction$@\1@p'`
+
+  warning=no
+  warnL "There is already an installed RPM of xscreensaver $rpmv"
+  warn2 "on this system.  You might want to remove it (with"
+  warn2 '"rpm -ve xscreensaver") before running "make install"'
+  warn2 "from this directory."
+  echo ""
+  warn2 "Alternately, you could build this version of xscreensaver"
+  warn2 'as an RPM, and then install that.  An "xscreensaver.spec"'
+  warn2 "file is included.  See the RPM documentation for more info."
+  echo ""
+
+  if test "$rpmbdir" = "$rpmhdir" ; then
+    warn2 "The RPM version was installed in $rpmbdir."
+  else
+    warn2 "The RPM version was installed in $rpmbdir,"
+    warn2 "with demos in $rpmhdir."
+  fi
+
+  do_dir_warning=yes
+fi
+
+
 if test "${bindir}" = "${HACKDIR}" ; then
+  do_dir_warning=yes
+fi
+
+if test "$do_dir_warning" = yes; then
   echo ""
   echo "$warnsep"
   echo ""
index d9b512295c178766710b84e45e79fa0d0b5ef618..0187e2172b6773762c86a92fe2f4858bb6dcc191 100644 (file)
@@ -176,6 +176,7 @@ install-program: $(EXES)
           else                                                         \
            e=echo ;                                                    \
  $$e ""                                                                             ;\
+ $$e "  ####################################################################";\
  $$e "  Warning: xscreensaver has been compiled with support for shadow"     ;\
  $$e "           passwords.  If your system actually uses shadow passwords," ;\
  $$e "           then xscreensaver must be installed as a setuid root"      ;\
@@ -184,6 +185,7 @@ install-program: $(EXES)
  $$e ""                                                                             ;\
  $$e "           For now, xscreensaver will be installed non-setuid, which"  ;\
  $$e "           means that locking might not work.  (Try it and see.)"             ;\
+ $$e "  ####################################################################";\
  $$e ""                                                                             ;\
           fi ;                                                         \
        fi ;                                                            \
@@ -194,7 +196,32 @@ install-program: $(EXES)
 
 install-ad: XScreenSaver.ad
        @if [ ! -d $(AD_DIR) ]; then $(INSTALL_DIRS) $(AD_DIR) ; fi
-       $(INSTALL_DATA) XScreenSaver.ad $(AD_DIR)/XScreenSaver
+       @-echo $(INSTALL_DATA) XScreenSaver.ad $(AD_DIR)/XScreenSaver ;       \
+       if $(INSTALL_DATA) XScreenSaver.ad $(AD_DIR)/XScreenSaver ; then      \
+         true ;                                                              \
+       else                                                                  \
+         e=echo ;                                                            \
+         if [ -f $(AD_DIR)/XScreenSaver ]; then                              \
+ $$e ""                                                                             ;\
+ $$e "  ####################################################################";\
+ $$e "  Warning: unable to install $(AD_DIR)/XScreenSaver"                  ;\
+ $$e "           That file exists, and is unwritable.  It is probably from"  ;\
+ $$e "           an older version of xscreensaver, and could cause things"   ;\
+ $$e "           to malfunction.  Please delete it!"                        ;\
+ $$e "  ####################################################################";\
+ $$e ""                                                                             ;\
+           exit 1 ;                                                          \
+         else                                                                \
+ $$e ""                                                                             ;\
+ $$e "  ####################################################################";\
+ $$e "  Warning: unable to install $(AD_DIR)/XScreenSaver"                  ;\
+ $$e "           The directory is unwritable.  This is probably ok;"        ;\
+ $$e "           xscreensaver should work without that file."               ;\
+ $$e "  ####################################################################";\
+ $$e ""                                                                             ;\
+           exit 0 ;                                                          \
+         fi                                                                  \
+       fi
 
 install-man: $(MEN)
        @men="$(MEN)" ;                                                 \
@@ -235,11 +262,14 @@ install-pam:
          if [ ! -f $$dir/$$dest ]; then                                \
            e=echo ;                                                    \
  $$e ""                                                                             ;\
+ $$e "  ####################################################################";\
  $$e "  Warning: xscreensaver has been compiled with support for Pluggable"  ;\
  $$e "           Authentication Modules (PAM).  However, we were unable to"  ;\
- $$e "           install the file $$dir/$$dest.  PAM is unlikely to work"    ;\
- $$e "           without this file (and old-style password authentication"   ;\
- $$e "           will be used instead, which may or may not work.)"         ;\
+ $$e "           install the file $$dir/$$dest.  PAM is unlikely"           ;\
+ $$e "           to work without this file (and old-style password"         ;\
+ $$e "           authentication will be used instead, which may or may not"  ;\
+ $$e "           work.)"                                                    ;\
+ $$e "  ####################################################################";\
  $$e ""                                                                             ;\
          fi ;                                                          \
        elif [ -f $$conf ]; then                                        \
@@ -248,9 +278,11 @@ install-pam:
          else                                                          \
            e=echo ;                                                    \
  $$e ""                                                                             ;\
+ $$e "  ####################################################################";\
  $$e "  Warning: xscreensaver has been compiled with support for Pluggable"  ;\
  $$e "           Authentication Modules (PAM).  To complete the installation";\
  $$e "           of PAM support, you must add this to the file $$conf:"             ;\
+ $$e "  ####################################################################";\
  $$e ""                                                                             ;\
            cat $$src | grep -v '#%' | sed "s/^/        $$dest  /" ;    \
            echo "";                                                    \
index bdfcc5868dc07442a422e1cc655bcf13de359ee2..cc35ca4a413b1104613e32e0276669c01823f066 100644 (file)
@@ -4,8 +4,8 @@
 !            a screen saver and locker for the X window system
 !                            by Jamie Zawinski
 !
-!                              version 3.09
-!                                11-Apr-99
+!                              version 3.10
+!                                27-Apr-99
 !
 ! See "man xscreensaver" for more info.  The latest version is always
 ! available at http://www.jwz.org/xscreensaver/
                wander -root -advance 0 -size 10 -circles True            \
                  -length 10000 -reset 100000                           \n\
                critical -root                                          \n\
+               phosphor -root                                          \n\
+               xmatrix -root                                           \n\
                                                                          \
        mono:   rocks -root                                             \n\
        color:  rocks -root -fg darksalmon                              \n\
 @GL_KLUDGE@    atlantis -root                                          \n\
 @GL_KLUDGE@    lament -root                                            \n\
 @GL_KLUDGE@    bubble3d -root                                          \n\
-@GL_KLUDGE@    glplanet -root                                          \n
+@GL_KLUDGE@    glplanet -root                                          \n\
+@GL_KLUDGE@    pulsar -root                                            \n
  
 
 ! A few of the hacks require OpenGL, and will only be built if you have it.
index 9d4c348e1a773e419177b8b070396e039c168b4e..0178752289600f139216242742b22ac2e6e7bb52 100644 (file)
                wander -root -advance 0 -size 10 -circles True            \
                  -length 10000 -reset 100000                           \\n\
                critical -root                                          \\n\
+               phosphor -root                                          \\n\
+               xmatrix -root                                           \\n\
                                                                          \
        mono:   rocks -root                                             \\n\
        color:  rocks -root -fg darksalmon                              \\n\
                atlantis -root                                          \\n\
                lament -root                                            \\n\
                bubble3d -root                                          \\n\
-               glplanet -root                                          \\n",
+               glplanet -root                                          \\n\
+               pulsar -root                                            \\n",
 " ",
 "XScreenSaver.pointerPollTime:         5",
 "XScreenSaver.initialDelay:            0",
index 6e83e0f4a5440f757353b2c7dcb108b01a28f42f..5bfaec9ec860fa32cc6b53c7d18b02bac01842af 100644 (file)
@@ -213,7 +213,7 @@ get_encrypted_passwd(const char *user)
 #ifndef VMS
 
 Bool
-pwent_lock_init (int argc, char **argv, Bool verbose_p)
+pwent_priv_init (int argc, char **argv, Bool verbose_p)
 {
   char *u;
 
@@ -234,6 +234,17 @@ pwent_lock_init (int argc, char **argv, Bool verbose_p)
 }
 
 
+Bool
+pwent_lock_init (int argc, char **argv, Bool verbose_p)
+{
+  if (encrypted_user_passwd)
+    return True;
+  else
+    return False;
+}
+
+
+
 static Bool
 passwds_match_p (const char *cleartext, const char *ciphertext)
 {
index 25b3b04880ab2d41d7b2b279aa64b380fbc8931e..1847d1be1f7cddce077ccc22ffdfc35c0787a96c 100644 (file)
@@ -39,8 +39,10 @@ extern char *blurb(void);
 struct auth_methods {
   const char *name;
   Bool (*init) (int argc, char **argv, Bool verbose_p);
+  Bool (*priv_init) (int argc, char **argv, Bool verbose_p);
   Bool (*valid_p) (const char *typed_passwd, Bool verbose_p);
   Bool initted_p;
+  Bool priv_initted_p;
 };
 
 
@@ -53,6 +55,7 @@ extern Bool pam_lock_init (int argc, char **argv, Bool verbose_p);
 extern Bool pam_passwd_valid_p (const char *typed_passwd, Bool verbose_p);
 #endif
 extern Bool pwent_lock_init (int argc, char **argv, Bool verbose_p);
+extern Bool pwent_priv_init (int argc, char **argv, Bool verbose_p);
 extern Bool pwent_passwd_valid_p (const char *typed_passwd, Bool verbose_p);
 
 
@@ -63,15 +66,41 @@ extern Bool pwent_passwd_valid_p (const char *typed_passwd, Bool verbose_p);
  */
 struct auth_methods methods[] = {
 # ifdef HAVE_KERBEROS
-  { "Kerberos",        kerberos_lock_init,     kerberos_passwd_valid_p, False },
+  { "Kerberos",         kerberos_lock_init, 0, kerberos_passwd_valid_p,
+                        False, False },
 # endif
 # ifdef HAVE_PAM
-  { "PAM",     pam_lock_init,          pam_passwd_valid_p,      False },
+  { "PAM",              pam_lock_init, 0, pam_passwd_valid_p, 
+                        False, False },
 # endif
-  { "normal",  pwent_lock_init,        pwent_passwd_valid_p,    False }
+  { "normal",           pwent_lock_init, pwent_priv_init, pwent_passwd_valid_p,
+                        False, False }
 };
 
 
+Bool
+lock_priv_init (int argc, char **argv, Bool verbose_p)
+{
+  int i;
+  Bool any_ok = False;
+  for (i = 0; i < countof(methods); i++)
+    {
+      if (!methods[i].priv_init)
+        methods[i].priv_initted_p = True;
+      else
+        methods[i].priv_initted_p = methods[i].priv_init (argc, argv,
+                                                          verbose_p);
+
+      if (methods[i].priv_initted_p)
+        any_ok = True;
+      else if (verbose_p)
+        fprintf (stderr, "%s: initialization of %s passwords failed.\n",
+                 blurb(), methods[i].name);
+    }
+  return any_ok;
+}
+
+
 Bool
 lock_init (int argc, char **argv, Bool verbose_p)
 {
@@ -79,6 +108,9 @@ lock_init (int argc, char **argv, Bool verbose_p)
   Bool any_ok = False;
   for (i = 0; i < countof(methods); i++)
     {
+      if (!methods[i].priv_initted_p)  /* Bail if lock_priv_init failed. */
+        continue;
+
       methods[i].initted_p = methods[i].init (argc, argv, verbose_p);
       if (methods[i].initted_p)
         any_ok = True;
index e006e5778050259893f6aa65eb0ff3df81d36248..e191314292ad6aaa599d17099f4082b74b8992f5 100644 (file)
@@ -800,7 +800,6 @@ load_init_file (saver_preferences *p)
    */
   if (p->passwd_timeout <= 0) p->passwd_timeout = 30000;        /* 30 secs */
   if (p->timeout < 10000) p->timeout = 10000;                   /* 10 secs */
-  if (p->cycle < 0) p->cycle = 0;
   if (p->cycle != 0 && p->cycle < 2000) p->cycle = 2000;        /*  2 secs */
   if (p->pointer_timeout <= 0) p->pointer_timeout = 5000;       /*  5 secs */
   if (p->notice_events_timeout <= 0)
index 0e104c7ff6c85a7c51b325d660f904c0492cfb35..8b6187d9a1b6732cfb17ee13c895e3c570df625c 100644 (file)
@@ -739,7 +739,7 @@ select_visual_of_hack (saver_screen_info *ssi, const char *hack)
               (si->demoing_p
                ? "%s: warning, no \"%s\" visual for \"%s\".\n"
                : "%s: no \"%s\" visual; skipping \"%s\".\n"),
-              blurb(), (vis ? vis : "???"), in);
+              blurb(), (*vis ? vis : "???"), in);
     }
 
   return selected;
index 909abe513d4817d4c351b8ffdcc81483ed98d26b..4945202a1f228690bb8b4abe2e6b0f6ffe0659bb 100644 (file)
@@ -98,11 +98,11 @@ grab_string(int status)
 {
   switch (status)
     {
-    case GrabSuccess:     return "GrabSuccess";     break;
-    case AlreadyGrabbed:  return "AlreadyGrabbed";  break;
-    case GrabInvalidTime: return "GrabInvalidTime"; break;
-    case GrabNotViewable: return "GrabNotViewable"; break;
-    case GrabFrozen:      return "GrabFrozen";      break;
+    case GrabSuccess:     return "GrabSuccess";
+    case AlreadyGrabbed:  return "AlreadyGrabbed";
+    case GrabInvalidTime: return "GrabInvalidTime";
+    case GrabNotViewable: return "GrabNotViewable";
+    case GrabFrozen:      return "GrabFrozen";
     default:
       {
        static char foo[255];
index fb31471061251cfb5a91684d0c87e99bc4edeab5..88d09d29297620c6cb15c1bb427d8f8f538476ff 100644 (file)
@@ -11,7 +11,7 @@
 .if n .sp 1
 .if t .sp .5
 ..
-.TH XScreenSaver 1 "11-Apr-99 (3.09)" "X Version 11"
+.TH XScreenSaver 1 "27-Apr-99 (3.10)" "X Version 11"
 .SH NAME
 xscreensaver-command - control a running xscreensaver process
 .SH SYNOPSIS
index 86a470aa12f9dd15b53f82fae1a7c25e61d7c06b..01adfdcff2f24e1cd53d760f354524fc54247944 100644 (file)
@@ -11,7 +11,7 @@
 .if n .sp 1
 .if t .sp .5
 ..
-.TH XScreenSaver 1 "11-Apr-99 (3.09)" "X Version 11"
+.TH XScreenSaver 1 "27-Apr-99 (3.10)" "X Version 11"
 .SH NAME
 xscreensaver-demo - interactively control the background xscreensaver daemon
 .SH SYNOPSIS
index dda587a12f81c2da057bdff4c884b2760224a66e..4460c19df6125b9c358df07e4a3a179bb06f98e4 100644 (file)
@@ -419,12 +419,29 @@ set_version_string (saver_info *si, int *argc, char **argv)
 static void
 privileged_initialization (saver_info *si, int *argc, char **argv)
 {
+#ifndef NO_LOCKING
+  /* before hack_uid() for proper permissions */
+  lock_priv_init (*argc, argv, si->prefs.verbose_p);
+#endif /* NO_LOCKING */
+
+#ifndef NO_SETUID
+  hack_uid (si);
+#endif /* NO_SETUID */
+}
+
+
+/* Figure out what locking mechanisms are supported.
+ */
+static void
+lock_initialization (saver_info *si, int *argc, char **argv)
+{
 #ifdef NO_LOCKING
   si->locking_disabled_p = True;
   si->nolock_reason = "not compiled with locking support";
 #else /* !NO_LOCKING */
   si->locking_disabled_p = False;
-  /* before hack_uid() for proper permissions */
+
+  /* Finish initializing locking, now that we're out of privileged code. */
   if (! lock_init (*argc, argv, si->prefs.verbose_p))
     {
       si->locking_disabled_p = True;
@@ -894,7 +911,7 @@ main_loop (saver_info *si)
 
           fprintf (stderr,
                   "%s: unable to grab keyboard or mouse!  Blanking aborted.\n",
-                   blurb(), timestring ());
+                   blurb());
           continue;
         }
 
@@ -1015,6 +1032,7 @@ main (int argc, char **argv)
       exit (1);
 
   load_init_file (p);
+  lock_initialization (si, &argc, argv);
 
   if (p->xsync_p) XSynchronize (si->dpy, True);
   blurb_timestamp_p = p->timestamp_p;  /* kludge */
index 7860dfe4f41f8f15484d28e4901ebfc3ce20e352..7a61d166b2d306bf69e27af82ae6f31ba3f7942d 100644 (file)
@@ -279,6 +279,7 @@ extern void unblank_screen (saver_info *si);
 
 #ifndef NO_LOCKING
 extern Bool unlock_p (saver_info *si);
+extern Bool lock_priv_init (int argc, char **argv, Bool verbose_p);
 extern Bool lock_init (int argc, char **argv, Bool verbose_p);
 extern Bool passwd_valid_p (const char *typed_passwd, Bool verbose_p);
 
index 445075874bb1e4ecbb52c70c55f4ebdb9219b51b..9c468f75728f6c97e7a1edace6c2802fb264f7da 100644 (file)
@@ -11,7 +11,7 @@
 .if n .sp 1
 .if t .sp .5
 ..
-.TH XScreenSaver 1 "11-Apr-99 (3.09)" "X Version 11"
+.TH XScreenSaver 1 "27-Apr-99 (3.10)" "X Version 11"
 .SH NAME
 xscreensaver - graphics hack and screen locker, launched when the user is idle
 .SH SYNOPSIS
index e9ce414e314cf6ec7671c61146e29c856f8fcc7d..fb393afa5addd44f3cd42dc18975a962b287f1d4 100644 (file)
@@ -82,7 +82,8 @@ SRCS          = attraction.c blitspin.c bouboule.c braid.c bubbles.c \
                  cynosure.c moire2.c flow.c epicycle.c interference.c \
                  truchet.c bsod.c crystal.c discrete.c distort.c kumppa.c \
                  sonar.c demon.c loop.c t3d.c penetrate.c deluxe.c compass.c \
-                 squiral.c xflame.c wander.c spotlight.c critical.c
+                 squiral.c xflame.c wander.c spotlight.c critical.c \
+                 phosphor.c xmatrix.c
 
 OBJS           = attraction.o blitspin.o bouboule.o braid.o bubbles.o \
                  bubbles-default.o decayscreen.o deco.o drift.o flag.o \
@@ -98,7 +99,8 @@ OBJS          = attraction.o blitspin.o bouboule.o braid.o bubbles.o \
                  cynosure.o moire2.o flow.o epicycle.o interference.o \
                  truchet.o bsod.o crystal.o discrete.o distort.o kumppa.o \
                  sonar.o demon.o loop.o t3d.o penetrate.o deluxe.o compass.o \
-                 squiral.o xflame.o wander.o spotlight.o critical.o
+                 squiral.o xflame.o wander.o spotlight.o critical.o \
+                 phosphor.o xmatrix.o
 
 EXES           = attraction blitspin bouboule braid bubbles decayscreen deco \
                  drift flag flame forest vines galaxy grav greynetic halo \
@@ -110,7 +112,7 @@ EXES                = attraction blitspin bouboule braid bubbles decayscreen deco \
                  ant xjack xlyap jigsaw cynosure moire2 flow epicycle \
                  interference truchet bsod crystal discrete distort kumppa \
                  sonar demon loop t3d penetrate deluxe compass squiral \
-                 xflame wander spotlight critical
+                 xflame wander spotlight critical phosphor xmatrix
 
 HACK_OBJS_1    = $(UTILS_BIN)/resources.o $(UTILS_BIN)/visual.o \
                  $(UTILS_BIN)/usleep.o $(UTILS_BIN)/yarandom.o @XMU_OBJS@
@@ -492,6 +494,12 @@ spotlight: spotlight.o     $(HACK_OBJS) $(GRAB)
 critical:      critical.o      $(HACK_OBJS) $(COL) $(ERASE)
        $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(COL) $(ERASE) $(HACK_LIBS)
 
+phosphor:      phosphor.o      $(HACK_OBJS) $(COL)
+       $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(COL) $(HACK_LIBS)
+
+xmatrix:       xmatrix.o       $(HACK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(HACK_LIBS) $(XPM_LIBS)
+
 
 # The rules for those hacks which follow the `xlockmore' API.
 #
@@ -1594,4 +1602,24 @@ critical.o: $(UTILS_SRC)/colors.h
 critical.o: $(UTILS_SRC)/grabscreen.h
 critical.o: $(UTILS_SRC)/visual.h
 critical.o: $(UTILS_SRC)/erase.h
+phosphor.o: $(srcdir)/screenhack.h
+phosphor.o: ../config.h
+phosphor.o: $(UTILS_SRC)/yarandom.h
+phosphor.o: $(UTILS_SRC)/usleep.h
+phosphor.o: $(UTILS_SRC)/resources.h
+phosphor.o: $(UTILS_SRC)/hsv.h
+phosphor.o: $(UTILS_SRC)/colors.h
+phosphor.o: $(UTILS_SRC)/grabscreen.h
+phosphor.o: $(UTILS_SRC)/visual.h
+xmatrix.o: $(srcdir)/screenhack.h
+xmatrix.o: ../config.h
+xmatrix.o: $(UTILS_SRC)/yarandom.h
+xmatrix.o: $(UTILS_SRC)/usleep.h
+xmatrix.o: $(UTILS_SRC)/resources.h
+xmatrix.o: $(UTILS_SRC)/hsv.h
+xmatrix.o: $(UTILS_SRC)/colors.h
+xmatrix.o: $(UTILS_SRC)/grabscreen.h
+xmatrix.o: $(UTILS_SRC)/visual.h
+xmatrix.o: $(srcdir)/images/matrix.xpm
+xmatrix.o: $(srcdir)/images/matrix.xbm
 
index 676d5e25e30478c9b45b9a7ffab065365e379758..13adf73932e3e1d1a7b8950bce59cbfa59011e53 100644 (file)
@@ -54,6 +54,7 @@ $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) PEDAL.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) PENETRATE.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) PENROSE.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) PHOSPHOR.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) PYRO.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) QIX.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) RD-BOMB.C
@@ -82,6 +83,7 @@ $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XJACK.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XLOCKMORE.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XLYAP.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XMATRIX.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XROGER-HACK.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XSCREENSAVER-SGIGL.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE,XLOCKMORE)/INCL=([],[-],[-.UTILS])/OBJ=SCREENHACK-XLOCK.OBJ SCREENHACK.C
index 676d5e25e30478c9b45b9a7ffab065365e379758..13adf73932e3e1d1a7b8950bce59cbfa59011e53 100644 (file)
@@ -54,6 +54,7 @@ $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) PEDAL.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) PENETRATE.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) PENROSE.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) PHOSPHOR.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) PYRO.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) QIX.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) RD-BOMB.C
@@ -82,6 +83,7 @@ $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XJACK.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XLOCKMORE.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XLYAP.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XMATRIX.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XROGER-HACK.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XSCREENSAVER-SGIGL.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE,XLOCKMORE)/INCL=([],[-],[-.UTILS])/OBJ=SCREENHACK-XLOCK.OBJ SCREENHACK.C
index ae3df0b13bd8a986a0027afa004ab4369ec2807e..17abf8f4c398b9b6e95e7b3003bec4a0a77ed120 100644 (file)
@@ -308,12 +308,11 @@ screenhack (Display *dpy, Window window)
                 x2 * cell_size + cell_size/2,
                 y2 * cell_size + cell_size/2);
 
-      /* Flush changes to display, and discard any pending input --
-        we'll never look at it anyhow, and it saves it filling up
-        memory. */
-      XSync (dpy, True); 
+      XSync (dpy, False); 
+      screenhack_handle_events (dpy);
 
-      usleep (delay_usecs);
+      if (delay_usecs)
+        usleep (delay_usecs);
     }
 
     i_restart = (i_restart + 1) % n_restart;
index 16b8bd68e6b661a5d09e440e08b6a2a46de60dab..cd0820023cb153ee4248f19676f85024ae864c92 100644 (file)
@@ -64,17 +64,17 @@ SRCS                = atlantis.c b_draw.c b_lockglue.c b_sphere.c bubble3d.c \
                  morph3d.c pipeobjs.c pipes.c rubik.c s1_1.c s1_2.c s1_3.c \
                  s1_4.c s1_5.c s1_6.c s1_b.c shark.c sproingies.c \
                  sproingiewrap.c stairs.c superquadrics.c swim.c whale.c \
-                 xlock-gl.c xpm-ximage.c glplanet.c
+                 xlock-gl.c xpm-ximage.c glplanet.c pulsar.c
 
 OBJS           = atlantis.o b_draw.o b_lockglue.o b_sphere.o bubble3d.o \
                  buildlwo.o cage.o dolphin.o gears.o lament.o moebius.o \
                  morph3d.o pipeobjs.o pipes.o rubik.o s1_1.o s1_2.o s1_3.o \
                  s1_4.o s1_5.o s1_6.o s1_b.o shark.o sproingies.o \
                  sproingiewrap.o stairs.o superquadrics.o swim.o whale.o \
-                 xlock-gl.o xpm-ximage.o glplanet.o
+                 xlock-gl.o xpm-ximage.o glplanet.o pulsar.o
 
 GL_EXES                = cage gears moebius pipes sproingies stairs superquadrics \
-                 morph3d rubik atlantis lament bubble3d glplanet
+                 morph3d rubik atlantis lament bubble3d glplanet pulsar
 EXES           = @GL_EXES@
 
 HACK_OBJS      = screenhack-gl.o xlock-gl.o $(HACK_BIN)/xlockmore.o \
@@ -249,6 +249,9 @@ bubble3d:   bubble3d.o      $(HACK_OBJS) $(B3D)
 glplanet:      glplanet.o      $(HACK_OBJS) xpm-ximage.o
        $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) xpm-ximage.o $(XPM_LIBS)
 
+pulsar:                pulsar.o                $(HACK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(HACK_LIBS)
+
 
 ##############################################################################
 #
@@ -505,4 +508,16 @@ glplanet.o: $(UTILS_SRC)/visual.h
 glplanet.o: $(UTILS_SRC)/xshm.h
 glplanet.o: $(HACK_SRC)/images/earth.xbm
 glplanet.o: $(srcdir)/xpm-ximage.h
+pulsar.o: $(HACK_SRC)/xlockmore.h
+pulsar.o: ../../config.h
+pulsar.o: $(HACK_SRC)/xlockmoreI.h
+pulsar.o: $(HACK_SRC)/screenhack.h
+pulsar.o: $(UTILS_SRC)/yarandom.h
+pulsar.o: $(UTILS_SRC)/usleep.h
+pulsar.o: $(UTILS_SRC)/resources.h
+pulsar.o: $(UTILS_SRC)/hsv.h
+pulsar.o: $(UTILS_SRC)/colors.h
+pulsar.o: $(UTILS_SRC)/grabscreen.h
+pulsar.o: $(UTILS_SRC)/visual.h
+pulsar.o: $(UTILS_SRC)/xshm.h
 
index 7c71fc7d135c75e015801c462e70df6e16851c29..39ae21bb05cb8e23f709b83e00250790afc6655a 100644 (file)
@@ -323,7 +323,7 @@ setup_file_texture (ModeInfo *mi, char *filename)
                exit (1);
          }
 
-       setup_xbm_texture (data, width, height, &gp->fg, &gp->bg);
+       setup_xbm_texture ((char *) data, width, height, &gp->fg, &gp->bg);
   }
 #else  /* !XMU */
 
diff --git a/hacks/glx/pulsar.c b/hacks/glx/pulsar.c
new file mode 100644 (file)
index 0000000..b7a8e43
--- /dev/null
@@ -0,0 +1,783 @@
+/* -*- Mode: C; tab-width: 4 -*- */
+/* pulsar --- pulsar module for xscreensaver */
+/*-
+ * 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.
+
+ * Revision History:
+ * 4-Apr-1999:  dek@cgl.ucsf.edu  Created module "pulsar"
+ *
+ */
+
+#include <math.h> 
+#include <stdio.h>
+#include <stdlib.h>
+
+/*-
+ * due to a Bug/feature in VMS X11/Intrinsic.h has to be placed before xlock.
+ * otherwise caddr_t is not defined correctly
+ */
+
+#include <X11/Intrinsic.h>
+
+#ifdef STANDALONE
+# define PROGCLASS                                             "Screensaver"
+# define HACK_INIT                                             init_screensaver
+# define HACK_DRAW                                             draw_screensaver
+# define screensaver_opts                              xlockmore_opts
+#define        DEFAULTS                        "*light:                        False   \n" \
+                                        "*wire:                                False   \n" \
+                                        "*blend:                       True    \n" \
+                                        "*fog:                         False   \n" \
+                                        "*antialias:           False   \n" \
+                                        "*texture:                     False   \n" \
+                                        "*texture_quality:     False   \n" \
+                                        "*mipmap:                      False   \n" \
+                                        "*fps:                         False   \n" \
+                                        "*doDepth:                     False   \n" \
+
+# include "xlockmore.h"                                /* from the xscreensaver distribution */
+#else /* !STANDALONE */
+# include "xlock.h"                                    /* from the xlockmore distribution */
+#endif /* !STANDALONE */
+
+#ifdef USE_GL /* whole file */
+
+#ifdef HAVE_XPM
+# include <X11/xpm.h>
+# ifndef PIXEL_ALREADY_TYPEDEFED
+# define PIXEL_ALREADY_TYPEDEFED /* Sigh, Xmu/Drawing.h needs this... */
+# endif
+#endif
+
+#ifdef HAVE_XMU
+# ifndef VMS
+#  include <X11/Xmu/Drawing.h>
+#else  /* VMS */
+#  include <Xmu/Drawing.h>
+# endif /* VMS */
+#endif
+
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+#include <string.h>
+#include <malloc.h>
+#include <stdio.h>
+
+/* Functions for loading and storing textures */
+
+#define checkImageWidth 64
+#define checkImageHeight 64
+
+char *Textures[] = {
+  "./test.ppm4",
+};
+
+typedef struct {
+    int sizeX, sizeY;
+    GLubyte *data;
+} PPMImage;
+
+/* Functions for handling the frames per second timer */
+#include "GL/glx.h"
+
+#ifndef SAMPLE_FRAMES
+#define SAMPLE_FRAMES 10
+#endif
+
+static GLint base;
+static int FrameCounter = 0;
+static double oldtime=-1., newtime=-1.;
+static char FPSstring[1024]="FPS: NONE"; 
+
+static float x_pos=0, y_pos=0;
+
+#define FONT "-*-courier-medium-r-normal-*-240-*"
+
+
+
+#define NUM_TRIANGLES 5
+static float scale_x=1, scale_y=1, scale_z=1;
+static int frame = 0;
+struct triangle
+{
+  GLfloat tx, ty, tz;
+  GLfloat rx, ry, rz;
+
+  GLfloat dtx, dty, dtz;
+  GLfloat drx, dry, drz;
+
+};
+struct triangle triangles[NUM_TRIANGLES];
+GLint tri_list;
+
+
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+#define WIDTH 800
+#define HEIGHT 600
+
+int global_width=WIDTH, global_height=HEIGHT;
+
+
+static XrmOptionDescRec opts[] = {
+  {"-light",   ".pulsar.light",   XrmoptionNoArg, (caddr_t) "true" },
+  {"+light",   ".pulsar.light",   XrmoptionNoArg, (caddr_t) "false" },
+  {"-wire",   ".pulsar.wire",   XrmoptionNoArg, (caddr_t) "true" },
+  {"+wire",   ".pulsar.wire",   XrmoptionNoArg, (caddr_t) "false" },
+  {"-blend",   ".pulsar.blend",   XrmoptionNoArg, (caddr_t) "true" },
+  {"+blend",   ".pulsar.blend",   XrmoptionNoArg, (caddr_t) "false" },
+  {"-fog",   ".pulsar.fog",   XrmoptionNoArg, (caddr_t) "true" },
+  {"+fog",   ".pulsar.fog",   XrmoptionNoArg, (caddr_t) "false" },
+  {"-antialias",   ".pulsar.antialias",   XrmoptionNoArg, (caddr_t) "true" },
+  {"+antialias",   ".pulsar.antialias",   XrmoptionNoArg, (caddr_t) "false" },
+  {"-texture",   ".pulsar.texture",   XrmoptionNoArg, (caddr_t) "true" },
+  {"+texture",   ".pulsar.texture",   XrmoptionNoArg, (caddr_t) "false" },
+  {"-texture_quality",   ".pulsar.texture_quality",   XrmoptionNoArg, (caddr_t) "true" },
+  {"+texture_quality",   ".pulsar.texture_quality",   XrmoptionNoArg, (caddr_t) "false" },
+  {"-mipmap",   ".pulsar.mipmap",   XrmoptionNoArg, (caddr_t) "true" },
+  {"+mipmap",   ".pulsar.mipmap",   XrmoptionNoArg, (caddr_t) "false" },
+  {"-fps",   ".pulsar.fps",   XrmoptionNoArg, (caddr_t) "true" },
+  {"+fps",   ".pulsar.fps",   XrmoptionNoArg, (caddr_t) "false" },
+  {"-do_depth",   ".pulsar.doDepth",   XrmoptionNoArg, (caddr_t) "true" },
+  {"+do_depth",   ".pulsar.doDepth",   XrmoptionNoArg, (caddr_t) "false" },
+};
+
+#define DEF_LIGHT  "False"
+#define DEF_WIRE   "False"
+#define DEF_BLEND   "True"
+#define DEF_FOG   "False"
+#define DEF_ANTIALIAS   "False"
+#define DEF_TEXTURE   "False"
+#define DEF_TEXTURE_QUALITY   "False"
+#define DEF_MIPMAP   "False"
+#define DEF_FPS   "False"
+#define DEF_DO_DEPTH   "False"
+
+static int do_light;
+static int do_wire;
+static int do_blend;
+static int do_fog;
+static int do_antialias;
+static int do_texture;
+static int do_texture_quality;
+static int do_mipmap;
+static int do_fps;
+static int do_depth;
+
+static argtype vars[] = {
+  {(caddr_t *) &do_light,    "light",   "Light",   DEF_LIGHT,   t_Bool},
+  {(caddr_t *) &do_wire,    "wire",   "Wire",   DEF_WIRE,   t_Bool},
+  {(caddr_t *) &do_blend,    "blend",   "Blend",   DEF_BLEND,   t_Bool},
+  {(caddr_t *) &do_fog,    "fog",   "Fog",   DEF_FOG,   t_Bool},
+  {(caddr_t *) &do_antialias,    "antialias",   "Antialias",   DEF_ANTIALIAS,   t_Bool},
+  {(caddr_t *) &do_texture,    "texture",   "Texture",   DEF_TEXTURE,   t_Bool},
+  {(caddr_t *) &do_texture_quality,    "texture_quality",   "Texture_quality",   DEF_TEXTURE_QUALITY,   t_Bool},
+  {(caddr_t *) &do_mipmap,    "mipmap",   "Mipmap",   DEF_MIPMAP,   t_Bool},
+  {(caddr_t *) &do_fps,    "fps",   "fps",   DEF_FPS,   t_Bool},
+  {(caddr_t *) &do_depth,    "doDepth",   "DoDepth",   DEF_DO_DEPTH,   t_Bool},
+};
+
+
+ModeSpecOpt screensaver_opts = {countof(opts), opts, countof(vars), vars, NULL};
+
+#ifdef USE_MODULES
+ModStruct   screensaver_description =
+{"screensaver", "init_screensaver", "draw_screensaver", "release_screensaver",
+ "draw_screensaver", "init_screensaver", NULL, &screensaver_opts,
+ 1000, 1, 2, 1, 4, 1.0, "",
+ "OpenGL screensaver", 0, NULL};
+#endif
+
+
+/* structure for holding the screensaver data */
+typedef struct {
+  int screen_width, screen_height;
+  GLXContext *glx_context;
+  Window window;
+  XColor fg, bg;
+} screensaverstruct;
+
+static screensaverstruct *Screensaver = NULL;
+
+
+void FPS_Setup(void)
+{
+  Display *Dpy;
+  XFontStruct *fontInfo;
+  Font id;
+  int first=0, last=255;
+
+  Dpy = XOpenDisplay(NULL);
+  fontInfo = XLoadQueryFont(Dpy, FONT);
+  if (fontInfo == NULL)
+    {
+      fprintf(stderr, "Failed to load font %s\n", FONT);
+      exit(1);
+    }
+
+  id = fontInfo->fid;
+  first = fontInfo->min_char_or_byte2;
+  last = fontInfo->max_char_or_byte2;
+  
+  base = glGenLists((GLuint) last+1);
+  if (base == 0) {
+    fprintf (stderr, "out of display lists\n");
+    exit(1);
+  }
+  glXUseXFont(id, first, last-first+1, base+first);
+
+}
+
+void PrintString(float x, float y, char *string)
+{
+  int len, i;
+
+  /* save the current state */
+  /* note: could be expensive! */
+  glPushAttrib(GL_ALL_ATTRIB_BITS);
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  gluOrtho2D(0, global_width, 0, global_height);
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+
+  /* disable lighting and texturing when drawing bitmaps! */
+  glDisable(GL_TEXTURE_2D);
+  glDisable(GL_LIGHTING);
+  glDisable(GL_BLEND);
+
+  /* draw a black background */
+
+  /* draw the text */
+  glColor3f(1,1,1);
+  glRasterPos2f( x, y);
+  len = (int) strlen(string);
+  for (i = 0; i < len; i++) {
+    glCallList(base+string[i]);
+  }
+
+  /* clean up after our state changes */
+  glPopAttrib();
+}
+
+double gettime(void)
+{
+  struct timeval now;
+#ifdef GETTIMEOFDAY_TWO_ARGS
+  struct timezone tzp;
+  gettimeofday(&now, &tzp);
+#else
+  gettimeofday(&now);
+#endif
+  return (double) (now.tv_sec + (((double) now.tv_usec) * 0.000001));
+}
+
+void DoFPS(void)
+{
+  /* every SAMPLE_FRAMES frames, get the time and use it to get the 
+     frames per second */
+  if (!(FrameCounter % SAMPLE_FRAMES)) {
+    oldtime = newtime;
+    newtime = gettime();
+    sprintf(FPSstring, "FPS: %.02f", SAMPLE_FRAMES/(newtime-oldtime));
+  }
+
+  PrintString(x_pos,y_pos,FPSstring);
+
+  FrameCounter++;
+}
+
+GLubyte *Generate_Image(int *width, int *height, int *format)
+{
+  GLubyte *result;
+  int i, j, c;
+  int counter=0;
+
+  *width = checkImageWidth;
+  *height = checkImageHeight;
+  result = (GLubyte *)malloc(4 * *width * *height);
+
+  counter = 0;
+  for (i = 0; i < checkImageWidth; i++) {
+    for (j = 0; j < checkImageHeight; j++) {
+      c = (((((i&0x8)==0))^(((j&0x8))==0)))*255;
+      result[counter++] = (GLubyte) c;
+      result[counter++] = (GLubyte) c;
+      result[counter++] = (GLubyte) c;
+      result[counter++] = (GLubyte) 255;
+    }
+  }
+
+  *format = GL_RGBA;
+  return result;
+}
+
+
+
+#ifdef TIFF
+#include <tiffio>
+/* Load a TIFF texture: requires libtiff */
+uint32 *LoadTIFF(char *filename, int *width, int *height, int *format)
+{
+  TIFF *tif;
+  char emsg[1024];
+  uint32 *raster;
+  TIFFRGBAImage img;
+  tsize_t npixels;
+
+  tif = TIFFOpen(filename, "r");
+  if (tif == NULL) {
+    fprintf(stderr, "Problem showing %s\n", filename);
+    return Generate_Image(&width, &height, &format);
+  }
+  if (TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
+    npixels = (tsize_t) (img.width * img.height);
+    raster = (uint32 *) _TIFFmalloc(npixels * (tsize_t) sizeof(uint32));
+    if (raster != NULL) {
+      if (TIFFRGBAImageGet(&img, raster, img.width, img.height) == 0) {
+        TIFFError(filename, emsg);
+       return Generate_Image(&width, &height, &format);
+      }
+    }
+    TIFFRGBAImageEnd(&img);
+  } else {
+    TIFFError(filename, emsg);
+    return Generate_Image(&width, &height, &format);
+  }
+
+  *width = img.width;
+  *height = img.height;
+  *format = GL_RGBA;
+
+  TIFFClose(tif);
+  return raster;
+}
+#endif
+
+
+/* Load a modified version of PPM format with an extra byte for alpha */
+GLubyte *LoadPPM4(const char *filename, int *width, int *height, int *format)
+{
+  char buff[1024];
+  PPMImage *result;
+  FILE *fp;
+  int maxval;
+
+  fp = fopen(filename, "rb");
+  if (!fp)
+    {
+      fprintf(stderr, "Unable to open file '%s'\n", filename);
+      return  Generate_Image(width, height, format);
+    }
+
+  if (!fgets(buff, sizeof(buff), fp))
+    {
+      perror(filename);
+      return  Generate_Image(width, height, format);
+    }
+
+  if (buff[0] != '6' || buff[1] != 'P')
+    {
+      fprintf(stderr, "Invalid image format (must be `6P')\n");
+      return  Generate_Image(width, height, format);
+    }
+
+  result = malloc(sizeof(PPMImage));
+  if (!result)
+    {
+      fprintf(stderr, "Unable to allocate memory\n");
+      return  Generate_Image(width, height, format);
+    }
+
+  do
+    {
+      fgets(buff, sizeof(buff), fp);
+    }
+  while (buff[0] == '#');
+    
+  if (sscanf(buff, "%d %d", &result->sizeX, &result->sizeY) != 2)
+    {
+      fprintf(stderr, "Error loading image `%s'\n", filename);
+      return  Generate_Image(width, height, format);
+    }
+
+  if (fscanf(fp, "%d", &maxval) != 1)
+    {
+      fprintf(stderr, "Error loading image `%s'\n", filename);
+      return  Generate_Image(width, height, format);
+    }
+
+  while (fgetc(fp) != '\n')
+    ;
+
+  result->data = (GLubyte *)malloc(4 * result->sizeX * result->sizeY);
+  if (!result)
+    {
+      fprintf(stderr, "Unable to allocate memory\n");
+      exit(1);
+    }
+
+  if (fread(result->data, 4 * result->sizeX, result->sizeY, fp) != result->sizeY)
+    {
+      fprintf(stderr, "Error loading image `%s'\n", filename);
+      return  Generate_Image(width, height, format);
+    }
+
+  fclose(fp);
+
+  *width = result->sizeX;
+  *height = result->sizeY;
+  *format = GL_RGBA;
+  return result->data;
+}
+
+/* Load a plain PPM image */
+GLubyte *LoadPPM(const char *filename, int *width, int *height, int *format)
+{
+  char buff[1024];
+  PPMImage *result;
+  FILE *fp;
+  int maxval;
+
+  fp = fopen(filename, "rb");
+  if (!fp)
+    {
+      fprintf(stderr, "Unable to open file '%s'\n", filename);
+      return  Generate_Image(width, height, format);
+      exit(1);
+    }
+  if (!fgets(buff, sizeof(buff), fp))
+    {
+      perror(filename);
+      return  Generate_Image(width, height, format);
+    }
+
+  if (buff[0] != 'P' || buff[1] != '6')
+    {
+      fprintf(stderr, "Invalid image format (must be `P6')\n");
+      return  Generate_Image(width, height, format);
+    }
+
+  result = malloc(sizeof(PPMImage));
+  if (!result)
+    {
+      fprintf(stderr, "Unable to allocate memory\n");
+      return  Generate_Image(width, height, format);
+    }
+
+  do
+    {
+      fgets(buff, sizeof(buff), fp);
+    }
+  while (buff[0] == '#');
+    
+  if (sscanf(buff, "%d %d", &result->sizeX, &result->sizeY) != 2)
+    {
+      fprintf(stderr, "Error loading image `%s'\n", filename);
+      return  Generate_Image(width, height, format);
+    }
+
+  if (fscanf(fp, "%d", &maxval) != 1)
+    {
+      fprintf(stderr, "Error loading image `%s'\n", filename);
+      return  Generate_Image(width, height, format);
+    }
+
+  while (fgetc(fp) != '\n')
+    ;
+
+  result->data = (GLubyte *)malloc(3 * result->sizeX * result->sizeY);
+  if (!result)
+    {
+      fprintf(stderr, "Unable to allocate memory\n");
+      return  Generate_Image(width, height, format);
+    }
+
+  if (fread(result->data, 3 * result->sizeX, result->sizeY, fp) != result->sizeY)
+    {
+      fprintf(stderr, "Error loading image `%s'\n", filename);
+      return  Generate_Image(width, height, format);
+    }
+
+  fclose(fp);
+
+  *width = result->sizeX;
+  *height = result->sizeY;
+  *format = GL_RGB;
+  return result->data;
+}
+
+/* Create a texture in OpenGL.  First an image is loaded 
+   and stored in a raster buffer, then it's  */
+void Create_Texture(char *filename)
+{
+  int height, width;
+  GLubyte *image;
+  GLint a;
+  int format;
+
+  fprintf(stdout, "Loading texture '%s'\n", filename);
+
+  if ( !strncmp((filename+strlen(filename)-3), "ppm", 3))
+    image = LoadPPM(filename, &width, &height, &format);
+  else if ( !strncmp((filename+strlen(filename)-4), "ppm4", 4))
+    image = LoadPPM4(filename, &width, &height, &format);
+#ifdef TIFF
+  else if ( !strncmp((filename+strlen(filename)-4), "tiff", 4))
+    image = (GLubyte *)LoadTIFF(filename, &width, &height, &format);
+#endif
+  else {
+    fprintf(stderr, "Unknown file format extension: '%s'\n", filename);
+    image = Generate_Image(&width, &height, &format);
+  }
+
+  /* GL_MODULATE or GL_DECAL depending on what you want */
+  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+  if (do_texture_quality) {
+       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+       glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+  }
+  else {
+       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+       glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
+  }
+
+  if (do_mipmap)
+       a=gluBuild2DMipmaps(GL_TEXTURE_2D, format, width, height, format, GL_UNSIGNED_BYTE, image);
+  else 
+       glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0,
+                                format, GL_UNSIGNED_BYTE, image);
+
+  free(image);
+}
+
+void resetProjection(void) {
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  glFrustum(-1, 1, -1, 1, 1, 100); 
+  glMatrixMode(GL_MODELVIEW);
+  glLoadIdentity();
+}
+
+
+void GenerateTriangle(void)
+{
+  int i;
+
+  tri_list = glGenLists(1);
+  glNewList(tri_list,GL_COMPILE);
+/*    glBegin(GL_TRIANGLES); */
+  glBegin(GL_QUADS);
+  glColor4f(1,0,0,.4); glNormal3f(0,0,1);  glTexCoord2f(0,0); glVertex2f(-1, -1);
+  glColor4f(0,1,0,.4); glNormal3f(0,0,1);  glTexCoord2f(0,1); glVertex2f(-1,  1);
+  glColor4f(0,0,1,.4); glNormal3f(0,0,1);  glTexCoord2f(1,1); glVertex2f( 1,  1);
+  glColor4f(1,1,1,1); glNormal3f(0,0,1);  glTexCoord2f(1,0); glVertex2f( 1,  -1);
+  glEnd();
+  glEndList();
+
+  for (i=0; i < NUM_TRIANGLES; i++)
+    {
+      triangles[i].rx = 0.;
+      triangles[i].ry = 0.;
+      triangles[i].rz = 0.;
+      triangles[i].tx = 0.;
+      triangles[i].ty = 0.;
+      triangles[i].tz = -10;
+
+      triangles[i].drx = drand48() * 5.;
+      triangles[i].dry = drand48() * 5.;
+      triangles[i].drz = 0;
+    }
+}
+
+void initializeGL(GLsizei width, GLsizei height) 
+{
+  GLfloat fogColor[4] = { 0.1, 0.1, 0.1, 0.1 };
+
+  global_width=width;
+  global_height=height;
+
+  glViewport( 0, 0, width, height ); 
+  resetProjection();
+
+  if (do_depth)
+       glEnable(GL_DEPTH_TEST);
+
+  if (do_fps)
+       FPS_Setup();
+
+  if (do_antialias) {
+       do_blend = 1;
+       glEnable(GL_LINE_SMOOTH);
+  }
+
+  if (do_blend) {
+       glEnable(GL_BLEND);
+       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  }
+
+
+  if (do_light) {
+       glShadeModel(GL_SMOOTH);
+       glEnable(GL_COLOR_MATERIAL);
+       glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
+  }
+
+  if (do_wire)
+       glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+  else 
+       glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+
+  if (do_fog) {
+       glEnable(GL_FOG);
+       glFogi(GL_FOG_MODE, GL_LINEAR);
+       glFogfv(GL_FOG_COLOR, fogColor);
+       glFogf(GL_FOG_DENSITY, 0.35);
+/*     glHint(GL_FOG_HINT, GL_FASTEST); */
+       glFogf(GL_FOG_START, 50.0);
+       glFogf(GL_FOG_END, 100.0);
+  }
+       
+
+  if (do_texture)
+       {
+         Create_Texture(Textures[0]); 
+       }
+
+  GenerateTriangle();
+}
+void drawTriangles(void) {
+  int i;
+  for (i=0; i < NUM_TRIANGLES; i++)
+    {
+      glPushMatrix();
+      glTranslatef(triangles[i].tx,0,0);
+      glTranslatef(0,triangles[i].ty,0);
+      glTranslatef(0,0,triangles[i].tz);
+      glRotatef(triangles[i].rx, 1,0,0);
+      glRotatef(triangles[i].ry, 0,1,0);
+      glRotatef(triangles[i].rz, 0,0,1);
+      glCallList(tri_list);
+      glPopMatrix();
+
+      triangles[i].rx += triangles[i].drx;
+      triangles[i].ry += triangles[i].dry;
+      triangles[i].rz += triangles[i].drz;
+
+    }
+}
+
+GLvoid drawScene(GLvoid) 
+{
+
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  /* we have to do this here because the FPS meter turns these 3 features off!! */
+  {
+       if (do_light) {
+         glEnable(GL_LIGHTING);
+         glEnable(GL_LIGHT0);
+       }
+       
+       if (do_texture) {
+         glEnable(GL_TEXTURE_2D);
+       }
+       
+       if (do_blend) {
+         glEnable(GL_BLEND);
+         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+       }
+  }
+
+  resetProjection();
+  glScalef(scale_x, scale_y, scale_z);
+  drawTriangles();
+  
+  scale_x = cos(frame/360.)*10.;
+  scale_y = sin(frame/360.)*10.;
+  scale_z = 1;
+
+  frame++;
+  DoFPS();
+}
+
+
+void draw_screensaver(ModeInfo * mi)
+{
+  screensaverstruct *gp = &Screensaver[MI_SCREEN(mi)];
+  Display    *display = MI_DISPLAY(mi);
+  Window      window = MI_WINDOW(mi);
+
+  if (!gp->glx_context)
+       return;
+
+  glXMakeCurrent(display, window, *(gp->glx_context));
+  drawScene();
+  glXSwapBuffers(display, window);
+}
+
+/* Standard reshape function */
+static void
+reshape(int width, int height)
+{
+  glViewport( 0, 0, global_width, global_height );
+  resetProjection();
+}
+
+void
+init_screensaver(ModeInfo * mi)
+{
+  int screen = MI_SCREEN(mi);
+
+  screensaverstruct *gp;
+
+  if (Screensaver == NULL) {
+       if ((Screensaver = (screensaverstruct *) calloc(MI_NUM_SCREENS(mi), sizeof (screensaverstruct))) == NULL)
+         return;
+  }
+  gp = &Screensaver[screen];
+
+  gp->window = MI_WINDOW(mi);
+  if ((gp->glx_context = init_GL(mi)) != NULL) {
+       reshape(MI_WIDTH(mi), MI_HEIGHT(mi));
+       initializeGL(MI_WIDTH(mi), MI_HEIGHT(mi));
+  } else {
+       MI_CLEARWINDOW(mi);
+  }
+}
+
+
+/* all sorts of nice cleanup code should go here! */
+void release_screensaver(ModeInfo * mi)
+{
+  int screen;
+  if (Screensaver != NULL) {
+       for (screen = 0; screen < MI_NUM_SCREENS(mi); screen++) {
+/*       screensaverstruct *gp = &Screensaver[screen];*/
+       }
+       (void) free((void *) Screensaver);
+       Screensaver = NULL;
+  }
+  FreeAllGL(mi);
+}
+#endif
+
diff --git a/hacks/images/matrix.xbm b/hacks/images/matrix.xbm
new file mode 100644 (file)
index 0000000..9d29751
--- /dev/null
@@ -0,0 +1,394 @@
+#define matrix_width 56
+#define matrix_height 837
+static char matrix_bits[] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xf7,0xff,0xff,0x7b,0xff,
+ 0xff,0xaf,0xc8,0xff,0xff,0x4d,0xfd,0xff,0x0f,0x22,0xff,0x7f,0x75,0xfb,0xff,
+ 0x17,0x89,0xff,0xff,0xda,0xf5,0xff,0x47,0x25,0xfe,0xff,0xfd,0xfb,0xff,0x0b,
+ 0x1f,0xff,0x7f,0xfa,0xf2,0xff,0x85,0x17,0xfe,0xbf,0xfd,0xf5,0xff,0x45,0x9d,
+ 0xfe,0x7f,0xf5,0xf7,0xff,0x52,0x17,0xfd,0xaf,0xfd,0xe9,0xff,0x81,0x1f,0xfe,
+ 0xbf,0xfe,0xf7,0xff,0x4a,0x2d,0xfa,0xbf,0xfa,0xe9,0xff,0xa1,0x1f,0xfd,0xbf,
+ 0xfd,0xf7,0xff,0x92,0x2e,0xfc,0xdf,0xda,0xe9,0xff,0x85,0x9b,0xfe,0x7f,0xfd,
+ 0xf7,0xff,0x52,0x0f,0xfe,0xdf,0xfa,0xf2,0xff,0x85,0x3d,0xfe,0xff,0xfa,0xfb,
+ 0xff,0x47,0x8f,0xfe,0x7f,0xf9,0xea,0xff,0x0b,0x15,0xfe,0xff,0xdd,0xf5,0xff,
+ 0x87,0x0b,0xff,0x7f,0x75,0xfb,0xff,0x17,0xad,0xfe,0xff,0xff,0xfe,0xff,0x5f,
+ 0xa1,0xff,0xff,0x4b,0xff,0xff,0x5f,0xd4,0xff,0xff,0xff,0xff,0xff,0x77,0xeb,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xff,
+ 0xff,0xff,0xf4,0xff,0xff,0x57,0xff,0xff,0x3f,0x90,0xff,0xff,0x4b,0xfd,0xff,
+ 0x7f,0x48,0xff,0xff,0xa7,0xff,0xff,0x7f,0xe8,0xff,0xff,0xcf,0xff,0xff,0x3f,
+ 0xe8,0xff,0xff,0xa7,0xff,0xff,0x7f,0xf8,0xff,0xff,0xcb,0xff,0xff,0x3f,0xfc,
+ 0xff,0xff,0xcf,0xff,0xff,0x7f,0xf8,0xff,0xff,0xc7,0xff,0xff,0x3f,0xfa,0xff,
+ 0xff,0xeb,0xff,0xff,0x7f,0xf8,0xff,0xff,0xa7,0xff,0xff,0x3f,0xfc,0xff,0xff,
+ 0xcf,0xff,0xff,0x7f,0xf8,0xff,0xff,0xe7,0xff,0xff,0x3f,0xfa,0xff,0xff,0xcb,
+ 0xff,0xff,0x7f,0xf8,0xff,0xff,0xcf,0xff,0xff,0x3f,0xfc,0xff,0xff,0xc7,0xff,
+ 0xff,0x7f,0xf8,0xff,0xff,0xd7,0xff,0xff,0x3f,0xfc,0xff,0xff,0xcb,0xff,0xff,
+ 0x7f,0xf8,0xff,0xff,0xcf,0xff,0xff,0x3f,0xf8,0xff,0xff,0xe7,0xff,0xff,0x5f,
+ 0xfa,0xff,0xff,0xad,0xff,0xff,0x3f,0xe8,0xff,0xff,0xd7,0xff,0xff,0x57,0xf5,
+ 0xff,0xff,0xff,0xff,0xff,0xbf,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0x7f,0xfb,0xff,0xff,0xed,0xff,0xff,0x4f,0xad,0xff,0xff,0xb5,0xfa,0xff,
+ 0x0f,0x12,0xff,0x7f,0x79,0xfb,0xff,0x07,0x09,0xff,0xff,0xea,0xf5,0xff,0x97,
+ 0x2a,0xff,0x7f,0xfd,0xff,0xff,0x87,0x5e,0xff,0xff,0xf4,0xf5,0xff,0x4b,0x2b,
+ 0xff,0xff,0xfa,0xff,0xff,0x05,0xbf,0xff,0xff,0xfa,0xff,0xff,0x8b,0xfd,0xff,
+ 0xff,0xfa,0xff,0xff,0x47,0xf7,0xff,0xff,0xda,0xff,0xff,0x8f,0xfe,0xff,0xff,
+ 0xf5,0xff,0xff,0x27,0xfa,0xff,0xff,0xdb,0xff,0xff,0x1f,0xfd,0xff,0xff,0xee,
+ 0xff,0xff,0xaf,0xea,0xff,0xff,0x57,0xff,0xff,0x5f,0xf4,0xff,0xff,0xef,0xff,
+ 0xff,0x77,0xd1,0xff,0xff,0xbb,0xfe,0xff,0xaf,0xd4,0xff,0xbf,0x5f,0xfd,0xff,
+ 0xbb,0x42,0xff,0xff,0x75,0xfb,0xff,0x4f,0x29,0xff,0x7f,0xdf,0xfa,0xff,0x25,
+ 0x05,0xff,0xff,0x55,0xfb,0xff,0x97,0x40,0xff,0x7f,0xab,0xfa,0xff,0x2f,0x12,
+ 0xff,0xff,0x75,0xfd,0xff,0x8b,0x44,0xff,0xff,0xdf,0xff,0xff,0x7f,0xb5,0xff,
+ 0xff,0xff,0xff,0xff,0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x5f,0xf5,0xff,0xff,0x55,0xff,0xff,
+ 0x8f,0xd2,0xff,0xff,0x7a,0xfd,0xff,0x17,0x44,0xff,0x7f,0x55,0xff,0xff,0x07,
+ 0xa3,0xff,0xff,0xf9,0xfb,0xff,0x4f,0xa9,0xff,0xff,0xfc,0xfe,0xff,0x05,0x57,
+ 0xff,0xff,0xda,0xff,0xff,0x8b,0xad,0xff,0x7f,0xf5,0xff,0xff,0x47,0xfa,0xff,
+ 0xff,0xba,0xff,0xff,0x0f,0xfd,0xff,0xff,0xea,0xff,0xff,0x0f,0xf5,0xff,0xff,
+ 0xd5,0xff,0xff,0x47,0xfc,0xff,0x7f,0xf5,0xff,0xff,0x17,0xf5,0xff,0xff,0xaa,
+ 0xff,0xff,0x05,0xfa,0xff,0xbf,0xfd,0xff,0xff,0x4b,0xfd,0xff,0xff,0xf6,0xff,
+ 0xff,0x25,0xfb,0xff,0x5f,0xfd,0xff,0xff,0x91,0xff,0xff,0xbf,0xfb,0xff,0xff,
+ 0xc5,0xb6,0xff,0x7f,0xdd,0xfb,0xff,0x15,0x5b,0xff,0xff,0xfd,0xfa,0xff,0xc7,
+ 0x0d,0xff,0xff,0x76,0xfb,0xff,0x95,0x26,0xff,0xff,0xdd,0xff,0xff,0x5f,0x91,
+ 0xff,0xff,0x77,0xfd,0xff,0xaf,0xd4,0xff,0xff,0xdf,0xff,0xff,0x5f,0xd5,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x5f,0xfd,0xff,0xff,0xd7,0xff,0xff,0x7f,0xfc,0xff,0xff,0xe5,0xff,0xff,0x17,
+ 0xf8,0xff,0xff,0xab,0xff,0xff,0xaf,0xf4,0xff,0xff,0xd7,0xff,0xff,0x2f,0xe8,
+ 0xff,0xff,0x55,0xff,0xff,0x9f,0xe4,0xff,0x7f,0xaf,0xfe,0xff,0x57,0xd0,0xff,
+ 0xff,0x55,0xff,0xff,0x2f,0xa2,0xff,0xff,0xaf,0xfa,0xff,0x5f,0x11,0xff,0xff,
+ 0x6a,0xfb,0xff,0x2f,0x44,0xff,0xff,0xad,0xf5,0xff,0x97,0x22,0xfe,0xff,0xd6,
+ 0xfa,0xff,0x2b,0x14,0xfd,0xff,0x55,0xeb,0xff,0x8f,0x48,0xfe,0xff,0x6a,0xf5,
+ 0xff,0x05,0x02,0xfa,0x7f,0x91,0xed,0xff,0x17,0x50,0xfd,0xff,0x4a,0xf5,0xff,
+ 0x03,0x08,0xfd,0x7f,0xeb,0xff,0xff,0x4d,0xd2,0xfe,0xff,0xb5,0xfe,0xff,0x2f,
+ 0xfa,0xff,0xff,0xef,0xff,0xff,0x57,0xed,0xff,0xff,0xfb,0xff,0xff,0xaf,0xfc,
+ 0xff,0xff,0xff,0xff,0xff,0x5f,0xff,0xff,0xff,0xef,0xff,0xff,0x7f,0xfd,0xff,
+ 0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,
+ 0xaf,0xf6,0xff,0xff,0x55,0xff,0xff,0x5f,0xc1,0xff,0xff,0x5f,0xfd,0xff,0x97,
+ 0xa8,0xff,0xff,0xaa,0xfe,0xff,0x17,0x81,0xff,0xff,0x5f,0xfd,0xff,0x6f,0x62,
+ 0xff,0xff,0xf7,0xfe,0xff,0xbf,0x95,0xff,0xff,0x5f,0xfb,0xff,0xdf,0xa2,0xff,
+ 0xff,0xfe,0xfe,0xff,0xbf,0x4a,0xff,0xff,0x2b,0xfd,0xff,0xaf,0xa0,0xff,0xff,
+ 0xab,0xfe,0xff,0x17,0x80,0xff,0x7f,0x55,0xfb,0xff,0x4f,0xd5,0xff,0xff,0xfa,
+ 0xff,0xff,0x05,0xd2,0xff,0xff,0x6d,0xff,0xff,0x4b,0xf5,0xff,0x5f,0xf9,0xff,
+ 0xff,0x85,0xfe,0xff,0x7f,0xfd,0xff,0xff,0x13,0xf7,0xff,0xdf,0xf6,0xff,0xff,
+ 0xc5,0xfd,0xff,0xbf,0xfd,0xff,0xff,0x51,0xff,0xff,0xff,0xbe,0xff,0xff,0x8f,
+ 0xa5,0xff,0xff,0xf5,0xfa,0xff,0x4b,0x2b,0xff,0xff,0xfe,0xff,0xff,0x97,0x95,
+ 0xff,0xff,0xb7,0xfa,0xff,0xaf,0x4a,0xff,0xff,0xdf,0xff,0xff,0x5f,0xe5,0xff,
+ 0xff,0x7b,0xff,0xff,0x7f,0xd2,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xfe,0xff,0xff,0xeb,0xff,0xff,
+ 0x3f,0xfd,0xff,0xff,0xff,0xff,0xff,0xaf,0xfa,0xff,0xff,0xad,0xff,0xff,0x7f,
+ 0xe9,0xff,0xff,0xff,0xfe,0xff,0xbf,0xd2,0xff,0xff,0x2f,0xff,0xff,0xff,0xc2,
+ 0xff,0xff,0xff,0xfa,0xff,0x7f,0x2b,0xff,0xff,0xbf,0xfb,0xff,0xff,0x15,0xff,
+ 0xff,0xff,0xf5,0xff,0x7f,0x8b,0xfe,0xff,0x5b,0xf5,0xff,0x4f,0x11,0xfe,0x7f,
+ 0x6d,0xf1,0xff,0x97,0x04,0xff,0xff,0xa9,0xf4,0xff,0x0f,0x01,0xfe,0x7f,0xdd,
+ 0xf2,0xff,0x45,0x14,0xfe,0xff,0xf5,0xf5,0xff,0x0b,0x8b,0xfe,0xbf,0xfe,0xf5,
+ 0xff,0xc2,0x1d,0xff,0xdf,0xba,0xf7,0xff,0x2b,0x17,0xfe,0x7f,0xfd,0xf2,0xff,
+ 0x81,0x9d,0xfe,0xbf,0xff,0xfb,0xff,0x55,0x17,0xfe,0xff,0xfa,0xf5,0xff,0xa5,
+ 0x1b,0xff,0x7f,0xfb,0xf5,0xff,0x4b,0x8d,0xfe,0xff,0xbd,0xfa,0xff,0x0f,0x27,
+ 0xff,0x7f,0xf5,0xf7,0xff,0xcb,0x92,0xfe,0xff,0x7f,0xfd,0xff,0xaf,0xaa,0xff,
+ 0xff,0xd7,0xff,0xff,0x5f,0xd5,0xff,0xff,0x7f,0xff,0xff,0x7f,0xf5,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x5f,0xf5,0xff,0xff,0xdb,0xff,0xff,0xef,0x96,0xff,0xff,0x7e,0xfd,0xff,0x1f,
+ 0x55,0xff,0xff,0xa9,0xf7,0xff,0x87,0x90,0xfe,0xff,0x74,0xf9,0xff,0x0f,0x0a,
+ 0xfd,0xff,0xd2,0xee,0xff,0x07,0x49,0xfe,0xff,0xfa,0xfb,0xff,0x17,0x55,0xff,
+ 0xff,0xad,0xff,0xff,0x4f,0xfa,0xff,0xff,0xfb,0xff,0xff,0x17,0xbd,0xff,0xff,
+ 0xee,0xff,0xff,0xaf,0xfa,0xff,0xff,0xd7,0xff,0xff,0x5f,0xfa,0xff,0xff,0xef,
+ 0xff,0xff,0x7f,0xfa,0xff,0xff,0xb7,0xff,0xff,0xbf,0xf8,0xff,0xff,0xef,0xff,
+ 0xff,0x7f,0xed,0xff,0xff,0xbf,0xff,0xff,0xbf,0xf4,0xff,0xff,0xef,0xff,0xff,
+ 0xff,0xea,0xff,0xff,0xbf,0xfe,0xff,0xff,0xe5,0xff,0xff,0x7f,0xff,0xff,0xff,
+ 0xe7,0xff,0xff,0x7f,0xff,0xff,0xff,0xd3,0xff,0xff,0xff,0xfd,0xff,0xff,0xa5,
+ 0xff,0xff,0xbf,0xfe,0xff,0xff,0xa7,0xff,0xff,0xff,0xfb,0xff,0xff,0x57,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0x2f,0xff,0xff,0xff,0xfb,0xff,0xff,0xbf,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0x5f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf5,0xff,0xff,0x6f,0xff,0xff,0xbf,0xd4,
+ 0xff,0xff,0xfb,0xff,0xff,0xaf,0x56,0xff,0xff,0xb6,0xfa,0xff,0x5f,0x29,0xff,
+ 0xff,0xfb,0xf5,0xff,0x87,0x8e,0xfe,0x7f,0xd9,0xf5,0xff,0x8f,0x12,0xfe,0xff,
+ 0xfd,0xf5,0xff,0x0f,0x1b,0xff,0xff,0x74,0xf3,0xff,0x07,0x15,0xfe,0xff,0xda,
+ 0xfa,0xff,0x97,0x8a,0xfe,0xff,0x6b,0xf5,0xff,0x0f,0x01,0xfe,0xff,0x15,0xf2,
+ 0xff,0x5f,0x20,0xff,0xff,0x56,0xf9,0xff,0x17,0x04,0xfe,0xff,0xab,0xea,0xff,
+ 0x4f,0x10,0xfd,0x7f,0xa5,0xf5,0xff,0x17,0x82,0xfe,0xff,0xda,0xf5,0xff,0x4f,
+ 0x28,0xfe,0xff,0xe9,0xf6,0xff,0x0f,0x16,0xfd,0xff,0xfd,0xeb,0xff,0x87,0x55,
+ 0xfd,0xff,0xb4,0xff,0xff,0x97,0x2e,0xfa,0xff,0xfb,0xea,0xff,0x0f,0x9b,0xfe,
+ 0x7f,0xf9,0xf3,0xff,0x47,0x1d,0xfd,0xff,0xfd,0xeb,0xff,0x97,0x16,0xfe,0xff,
+ 0xd7,0xfd,0xff,0x4f,0xab,0xfe,0xff,0x7d,0xf7,0xff,0x7f,0x55,0xff,0xff,0xff,
+ 0xff,0xff,0xbf,0xaa,0xff,0xff,0xb7,0xff,0xff,0xff,0xf7,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe8,
+ 0xff,0xff,0x5f,0xff,0xff,0xbf,0xd6,0xff,0xff,0xf7,0xfd,0xff,0xaf,0x52,0xff,
+ 0xff,0xdd,0xf7,0xff,0x5f,0x2d,0xff,0xff,0xf5,0xfa,0xff,0x07,0x15,0xfe,0xff,
+ 0xfa,0xeb,0xff,0x97,0xae,0xfe,0xff,0xdd,0xfd,0xff,0x4f,0x1b,0xfa,0xff,0xfa,
+ 0xf7,0xff,0x8f,0xae,0xfd,0xff,0xfd,0xdb,0xff,0x47,0x5b,0xfc,0xff,0xf4,0xf6,
+ 0xff,0x0f,0x2f,0xfb,0xff,0xda,0xf7,0xff,0x8f,0x9a,0xfc,0xff,0xfa,0xea,0xff,
+ 0x87,0x2a,0xfe,0xff,0x55,0xfb,0xff,0x17,0x04,0xfd,0xff,0x50,0xe9,0xff,0x0f,
+ 0x81,0xfe,0xff,0xad,0xfa,0xff,0x07,0x14,0xff,0xff,0xd6,0xff,0xff,0x5f,0x50,
+ 0xff,0xff,0xeb,0xff,0xff,0x97,0xfc,0xff,0xff,0x57,0xff,0xff,0x3f,0xea,0xff,
+ 0xff,0xef,0xff,0xff,0xbf,0xe8,0xff,0xff,0xaf,0xfe,0xff,0x7f,0xe4,0xff,0xff,
+ 0x77,0xff,0xff,0xff,0xd2,0xff,0xff,0xbf,0xff,0xff,0x7f,0xd5,0xff,0xff,0xff,
+ 0xfd,0xff,0xff,0x57,0xff,0xff,0x7f,0xff,0xff,0xff,0xab,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xff,0x7f,0xff,0xff,0xff,0xe2,0xff,0xff,
+ 0x5f,0xff,0xff,0xff,0xe5,0xff,0xff,0xbf,0xfe,0xff,0xff,0xd3,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xe1,0xff,0xff,0xbf,0xfe,0xff,0xff,0xc7,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xe1,0xff,0xff,0xbf,0xfd,0xff,0xff,0x97,0xff,0xff,0xff,0xfe,0xff,
+ 0xff,0x53,0xff,0xff,0xff,0xfb,0xff,0x7f,0xab,0xff,0xff,0x7f,0xff,0xff,0xdf,
+ 0x16,0xff,0xff,0xed,0xf5,0xff,0x5f,0xad,0xfe,0xff,0xff,0xfb,0xff,0xa7,0x3f,
+ 0xff,0xff,0xfa,0xfb,0xff,0x5b,0x8d,0xfe,0x7f,0xff,0xf7,0xff,0xa5,0x3f,0xff,
+ 0xbf,0xed,0xfa,0xff,0x92,0x8a,0xfc,0xaf,0xbe,0xa5,0xff,0xc9,0x0a,0xe2,0xbf,
+ 0xd6,0x52,0xff,0x20,0x02,0xd0,0x9f,0xbd,0xaa,0xff,0xa1,0x55,0xe8,0xff,0xff,
+ 0xff,0xfe,0xf5,0x56,0xf7,0xbf,0xff,0xff,0xff,0xf5,0xff,0xfd,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,
+ 0xff,0xff,0xff,0xff,0x7f,0xff,0xff,0xff,0xef,0xff,0xff,0xaf,0xfc,0xff,0xff,
+ 0xf5,0xff,0xff,0x2f,0xfd,0xff,0xff,0xdb,0xff,0xff,0x5f,0xfa,0xff,0xff,0xb7,
+ 0xff,0xff,0x7f,0xe9,0xff,0xff,0xdf,0xfe,0xff,0xbf,0xe4,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xd2,0xff,0xff,0xdf,0xfd,0xff,0xff,0x4b,0xff,0xff,0x7f,0xf7,0xff,
+ 0xff,0x2d,0xff,0xff,0xff,0xfb,0xff,0xff,0x17,0xfe,0xff,0xff,0xf5,0xff,0xff,
+ 0x5f,0xff,0xff,0xff,0xf5,0xff,0xff,0x1f,0xfd,0xff,0xff,0xf7,0xff,0xff,0x17,
+ 0xfe,0xff,0x7f,0xfb,0xff,0xff,0xad,0xff,0xff,0xff,0xff,0xff,0xff,0x53,0xff,
+ 0xff,0xbf,0xfe,0xff,0xff,0xe5,0xff,0xff,0xdf,0xff,0xff,0x7f,0xea,0xff,0xff,
+ 0x6b,0xff,0xff,0xbf,0xf4,0xff,0xff,0xef,0xff,0xff,0x7f,0xfa,0xff,0xff,0xef,
+ 0xff,0xff,0x2f,0xfc,0xff,0xff,0xfb,0xff,0xff,0x9f,0xff,0xff,0xff,0xfd,0xff,
+ 0xff,0x57,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x7f,0xe5,0xff,0xff,0xb7,0xfe,0xff,0x5f,0xa9,0xff,0xff,0x7d,
+ 0xff,0xff,0x57,0x45,0xff,0xbf,0xbf,0xfa,0xff,0x55,0x53,0xfd,0xff,0x76,0xed,
+ 0xff,0xab,0x83,0xfa,0xbf,0xbf,0xf6,0xff,0xd1,0x51,0xfa,0x6f,0x7f,0xbf,0xff,
+ 0x6a,0xc7,0xfa,0xbf,0x7f,0xed,0xff,0xf1,0xa1,0xea,0xbf,0x7f,0xbf,0xff,0xf4,
+ 0xd7,0xea,0xdf,0xbe,0xf5,0xfe,0xd2,0x4b,0xd5,0xbf,0xff,0xdf,0x7d,0xf9,0xa5,
+ 0xca,0xaf,0xff,0xf5,0xfe,0xe2,0x1f,0xa6,0x7f,0xff,0xbb,0xff,0xb9,0x57,0xd5,
+ 0xaf,0xff,0xed,0xfd,0xe0,0x2f,0xca,0x7f,0xfb,0x77,0xff,0xf5,0x9f,0xea,0xbf,
+ 0xef,0xdb,0xff,0x97,0x3e,0xe9,0xff,0xfe,0x6f,0xff,0x6d,0xdb,0xf4,0xff,0xfb,
+ 0xbf,0xff,0x5f,0x7d,0xf9,0xff,0xef,0xff,0xff,0xff,0xff,0xfa,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0x7f,0x6d,0xfd,0xff,0xdf,0xab,0xff,0xbf,0x55,0xaa,0xff,0xbf,0xd6,
+ 0xfa,0xff,0x24,0x50,0xff,0xf7,0xd7,0xff,0x7f,0x5b,0xda,0xff,0xff,0xd7,0xff,
+ 0xff,0x57,0xe8,0xff,0xff,0xdb,0xff,0xff,0xbf,0xfc,0xff,0xbf,0xcf,0xff,0xbf,
+ 0x5a,0xb4,0xff,0xf7,0x6b,0xff,0xbf,0x5e,0xd8,0xff,0x7b,0xd7,0xfd,0x5f,0x25,
+ 0xea,0xfe,0xef,0xcb,0xff,0x3f,0x5d,0xb4,0xff,0xff,0x6f,0xff,0x7f,0x2b,0xd4,
+ 0xfe,0xff,0xd5,0xfb,0xff,0xbf,0xe8,0xff,0xdf,0xd7,0xff,0x7f,0x2b,0x7a,0xff,
+ 0xff,0xd7,0xff,0xff,0x7f,0xf8,0xff,0xff,0xef,0xff,0xff,0xbf,0xfc,0xff,0xff,
+ 0xd7,0xff,0xff,0x7f,0xfa,0xff,0xff,0xef,0xff,0xff,0x7f,0xfc,0xff,0xff,0xd7,
+ 0xff,0xff,0x7f,0xfa,0xff,0xff,0xef,0xff,0xff,0x7f,0xfc,0xff,0xff,0xd7,0xff,
+ 0xff,0xbf,0xf8,0xff,0xff,0xdf,0xff,0xff,0x7f,0xfa,0xff,0xff,0xe7,0xff,0xff,
+ 0x7f,0xf4,0xff,0xff,0xdf,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,
+ 0xff,0xff,0xff,0xbf,0xfe,0xff,0xff,0xef,0xff,0xff,0xff,0xfe,0xff,0xff,0xef,
+ 0xff,0xff,0x7f,0xfc,0xff,0xff,0xef,0xff,0xff,0x7f,0xfc,0xff,0xff,0xef,0xff,
+ 0xff,0x7f,0xfd,0xff,0xff,0xef,0xff,0xff,0x7f,0xfc,0xff,0xff,0xef,0xff,0xff,
+ 0x7f,0xfd,0xff,0xff,0xef,0xff,0xff,0x7f,0xfc,0xff,0xff,0xeb,0xff,0xff,0xbf,
+ 0xfc,0xff,0xff,0xdf,0xff,0xff,0x7f,0xfc,0xff,0xff,0xef,0xff,0xff,0xbf,0xfc,
+ 0xff,0xff,0xef,0xff,0xff,0x7f,0xfc,0xff,0xff,0xd7,0xff,0xff,0x7f,0xfd,0xff,
+ 0xff,0xef,0xff,0xff,0x7f,0xfa,0xff,0xff,0xef,0xff,0xff,0x7f,0xfc,0xff,0xff,
+ 0xdf,0xff,0xff,0xbf,0xfa,0xff,0xff,0xef,0xff,0xff,0xff,0xf4,0xff,0xff,0x7f,
+ 0xff,0xff,0xff,0xea,0xff,0xff,0x7f,0xff,0xff,0xff,0xe3,0xff,0xff,0xbf,0xff,
+ 0xff,0xff,0xd5,0xff,0xff,0xff,0xfe,0xff,0xff,0xf7,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xdf,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xaf,0xaa,0xfe,0xff,0x55,0xf5,0xff,0x5f,0x95,0xfa,0xff,0xff,0xdf,
+ 0xff,0x2f,0x52,0xf9,0x7f,0xd9,0xb6,0xff,0x8f,0xad,0xfa,0xff,0xf6,0xdf,0xff,
+ 0x97,0xb6,0xf0,0xff,0xfb,0xab,0xff,0x0f,0x55,0xfa,0xff,0xac,0xde,0xff,0xa7,
+ 0x54,0xf1,0xff,0xd7,0xaa,0xff,0x17,0x02,0xf8,0xff,0xb4,0xaa,0xff,0x8d,0x54,
+ 0xf2,0x7f,0xab,0xd5,0xff,0x43,0x82,0xe8,0xbf,0xdd,0x6a,0xff,0x29,0x11,0xf4,
+ 0xaf,0xb6,0xda,0xff,0x05,0x8a,0xea,0x7f,0x6b,0xeb,0xff,0xaa,0x24,0xfa,0xff,
+ 0xbd,0xb1,0xff,0x57,0x09,0xfa,0xff,0xd6,0xed,0xff,0x8f,0x14,0xfd,0xff,0x7b,
+ 0xf5,0xff,0x2f,0x25,0xfa,0x7f,0xed,0xdb,0xff,0x8f,0x9a,0xfa,0xff,0xfa,0xff,
+ 0xff,0x4f,0xab,0xfa,0xff,0xdd,0xee,0xff,0x17,0xed,0xfe,0xff,0xf7,0xff,0xff,
+ 0x4f,0xb5,0xff,0xff,0x5a,0xff,0xff,0xaf,0xea,0xff,0xff,0xef,0xff,0xff,0x3f,
+ 0xf4,0xff,0xff,0xb7,0xff,0xff,0x5f,0xe9,0xff,0xff,0xcf,0xff,0xff,0x7f,0xf4,
+ 0xff,0xff,0x7f,0xff,0xff,0xbf,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xaf,0xff,0xff,0xff,0xff,0xff,0xff,0xb7,0xff,0xff,0xff,0xfa,0xff,
+ 0xff,0x4b,0xff,0xff,0x7f,0xff,0xff,0xff,0xa5,0xff,0xff,0xdf,0xfa,0xff,0xbf,
+ 0x25,0xff,0x7f,0x75,0xfb,0xff,0x41,0x95,0xfe,0x5f,0xad,0xf5,0xff,0x01,0x08,
+ 0xff,0xbf,0xd5,0xfa,0xff,0x4a,0x25,0xfe,0xff,0x7a,0xf7,0xff,0x15,0x92,0xfe,
+ 0xff,0xcf,0xfb,0xff,0x97,0xa8,0xfa,0xff,0xea,0xde,0xff,0x4f,0x56,0xfd,0xff,
+ 0xaf,0xf7,0xff,0x3f,0xb8,0xfa,0xff,0xeb,0xdf,0xff,0xff,0xec,0xfa,0xff,0xdf,
+ 0xff,0xff,0x3f,0xfa,0xfb,0xff,0xef,0xff,0xff,0x7f,0xe9,0xfd,0xff,0x7f,0xff,
+ 0xff,0xff,0xed,0xff,0xff,0xbf,0xff,0xff,0x7f,0xe5,0xff,0xff,0xff,0xfe,0xff,
+ 0xff,0xdb,0xff,0xff,0xff,0xff,0xff,0xff,0xab,0xff,0xff,0xff,0xfd,0xff,0xff,
+ 0xef,0xff,0xff,0xff,0xff,0xff,0xff,0x5b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xff,
+ 0xff,0xff,0xe7,0xff,0xff,0xbd,0xff,0xff,0x9f,0xf3,0xff,0xff,0xff,0xfe,0xff,
+ 0xaf,0xc5,0xff,0xff,0x5a,0xff,0xff,0x97,0xe2,0xff,0xff,0xbd,0xfe,0xff,0x4f,
+ 0xd3,0xff,0xff,0xba,0xfe,0xff,0x0f,0xc5,0xff,0xff,0x7b,0xff,0xff,0xa7,0xd1,
+ 0xff,0xff,0x5c,0xfd,0xff,0x8f,0x42,0xff,0xff,0x55,0xfe,0xff,0x8a,0x64,0xff,
+ 0x57,0xba,0xfa,0x3f,0x05,0x41,0xfd,0xef,0x29,0xd5,0xbf,0x44,0x80,0xfa,0x7b,
+ 0xb5,0xfe,0xbf,0x0a,0x45,0xfd,0xef,0xba,0xfa,0x7f,0x47,0xa1,0xfe,0xff,0x6d,
+ 0xff,0xff,0x17,0xa5,0xff,0x7f,0x7d,0xfd,0xff,0x8f,0x53,0xff,0xff,0xbb,0xf7,
+ 0xff,0xaf,0x4a,0xff,0xff,0xfd,0xfd,0xff,0x8f,0x55,0xff,0x7f,0x75,0xfb,0xff,
+ 0x4f,0x2b,0xff,0xff,0xfd,0xff,0xff,0x97,0x9f,0xfe,0xff,0xff,0xf5,0xff,0x4f,
+ 0x5f,0xff,0xff,0xfa,0xfb,0xff,0x97,0x2f,0xfe,0xff,0xfd,0xff,0xff,0xdf,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xaf,0xff,0xfa,0xff,0xff,0xdf,0xff,0xdf,0xff,0xfd,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xfe,0xff,0xff,0xef,0xff,0xff,0x7f,0xfd,0xff,0xff,0xf7,0xff,0xff,
+ 0x7f,0xfc,0xff,0xff,0xdf,0xff,0xff,0x7f,0xfa,0xff,0xff,0xe7,0xff,0xff,0xbf,
+ 0xf8,0xff,0xff,0xdb,0xff,0xff,0x5b,0xfc,0xff,0x7f,0xa7,0xff,0xff,0x2a,0x48,
+ 0xff,0x9f,0xad,0xf5,0xff,0xa1,0x24,0xfe,0xaf,0xc6,0xf6,0xff,0x10,0x10,0xfd,
+ 0x5f,0x6b,0xeb,0x7f,0x41,0x4a,0xfd,0x5f,0xd7,0xfd,0xff,0x34,0x28,0xfd,0xbf,
+ 0xcf,0xeb,0xff,0xa9,0x2c,0xfd,0x5f,0xe5,0xfe,0xff,0x20,0x94,0xfc,0x2f,0x57,
+ 0xeb,0xff,0x51,0x28,0xfe,0xbf,0xa5,0xf5,0xff,0x01,0x80,0xfa,0xdf,0xae,0xeb,
+ 0xff,0x6a,0x2a,0xfe,0xbf,0xd7,0xfe,0xff,0x35,0xb8,0xff,0xff,0xef,0xff,0xff,
+ 0xbb,0x5c,0xfd,0xff,0xd7,0xff,0xff,0x7f,0xf4,0xff,0xff,0xef,0xff,0xff,0xbf,
+ 0xfc,0xff,0xff,0xd7,0xff,0xff,0x7f,0xfa,0xff,0xff,0xef,0xff,0xff,0xbf,0xfc,
+ 0xff,0xff,0xff,0xff,0xff,0x7f,0xfd,0xff,0xff,0xef,0xff,0xff,0xff,0xfe,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xef,0xff,0xff,0x7f,0xff,0xff,0xff,0xd7,0xff,0xff,0xff,0xfd,0xff,0xff,
+ 0x53,0xff,0xff,0xbf,0xfe,0xff,0xff,0x45,0xfd,0xff,0x7f,0xf5,0xff,0xff,0x53,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0x85,0xfe,0xff,0xff,0xf2,0xff,0xff,0x2b,0xff,
+ 0xff,0xff,0xfb,0xff,0xff,0x97,0xfe,0xff,0x5f,0xf5,0xff,0xff,0x01,0xfe,0xff,
+ 0x7f,0xfd,0xff,0x7f,0x55,0xff,0xff,0x5f,0xf5,0xff,0xff,0x02,0xfd,0xff,0x7f,
+ 0xfb,0xff,0xff,0xa5,0xfe,0xff,0x5f,0xed,0xff,0xff,0x43,0xfd,0xff,0x7f,0xfd,
+ 0xff,0xff,0x92,0xfe,0xff,0xbf,0xea,0xff,0xff,0x45,0xfa,0xff,0x7f,0xdb,0xff,
+ 0xff,0x13,0xfa,0xff,0xff,0xed,0xff,0xff,0x85,0xfa,0xff,0x2f,0xf5,0xff,0x2f,
+ 0x25,0xfd,0xbf,0xf5,0xda,0xff,0xb5,0x10,0xfd,0x7f,0x97,0xfd,0xff,0x0a,0x8a,
+ 0xfe,0xff,0xfd,0xf7,0xff,0x6b,0x69,0xfd,0xdf,0xef,0xff,0xff,0xaa,0xbe,0xff,
+ 0x7f,0xff,0xdf,0xff,0xef,0xff,0xf9,0xff,0xff,0xff,0xff,0xf7,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xfd,0xff,0xff,0xef,0xff,0xff,0xbf,0xfe,0xff,0xff,0xff,0xff,0xff,0x7f,
+ 0xf9,0xff,0xff,0xcf,0xff,0xff,0x7f,0xfc,0xff,0xff,0xeb,0xff,0xff,0x7f,0xf4,
+ 0xff,0xff,0xaf,0xff,0xff,0x2b,0xd8,0xff,0xaf,0xa2,0xfd,0xff,0x21,0xa2,0xfe,
+ 0x3f,0x8b,0xf6,0xff,0x08,0x28,0xfd,0x9f,0x6a,0xfb,0xff,0x50,0x80,0xfe,0xbf,
+ 0xd7,0xee,0xff,0xa2,0xd4,0xfe,0xaf,0xbe,0xff,0xff,0x51,0x52,0xff,0xbf,0x6f,
+ 0xfd,0xff,0x68,0xd5,0xff,0x5f,0xbf,0xff,0xff,0xb3,0xa2,0xff,0xbf,0xfb,0xfe,
+ 0xff,0xd0,0xd3,0xff,0x7f,0x5f,0xff,0xff,0x6b,0xe5,0xff,0xdf,0x7d,0xfd,0xff,
+ 0xa9,0xa2,0xff,0x7f,0xb7,0xff,0xff,0x55,0xd5,0xff,0xff,0xfd,0xfe,0xff,0x0b,
+ 0xd5,0xff,0xff,0xd5,0xfb,0xff,0xa7,0xaa,0xfe,0xff,0xfa,0xff,0xff,0x17,0x3d,
+ 0xff,0xff,0xed,0xeb,0xff,0x8f,0x5e,0xfd,0xff,0xff,0xff,0xff,0x5f,0x7f,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xf7,0xff,0xff,0xbf,0xff,0xff,0xff,0x51,0x9f,
+ 0xfe,0xdf,0xfe,0xf5,0xff,0xea,0x5b,0xfe,0xbf,0xff,0xfb,0xff,0xb1,0x5f,0xfd,
+ 0xdf,0xfe,0xef,0xff,0xea,0x3e,0xfd,0xbf,0xff,0xf7,0xff,0xd1,0x57,0xfd,0x7f,
+ 0xff,0xdd,0xff,0x6a,0xaf,0xfa,0xaf,0xfb,0xf7,0xff,0xe9,0x3f,0xfd,0x7f,0xff,
+ 0xfb,0xff,0xb1,0x5b,0xfd,0xbf,0xff,0xdf,0xff,0xea,0x2f,0xfa,0xdf,0xfe,0xf5,
+ 0xff,0x69,0xbf,0xfd,0xbf,0xf7,0xef,0xff,0xe1,0x57,0xfc,0x5f,0xdf,0xf5,0xff,
+ 0xb5,0x2e,0xfb,0xbf,0xff,0xdb,0xff,0xa1,0x15,0xfd,0x7f,0x75,0xf5,0xff,0x54,
+ 0x95,0xfc,0x5f,0xdf,0xf7,0xff,0x43,0x15,0xfd,0xff,0xfd,0xed,0xff,0xb4,0x5b,
+ 0xfd,0xbf,0xff,0xfb,0xff,0xeb,0x5f,0xfe,0xdf,0xff,0xff,0xff,0xf2,0x7f,0xfb,
+ 0xff,0xff,0xff,0xff,0xff,0xbf,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xfe,0xff,0x7f,0xed,0xff,0xff,0x55,0x53,
+ 0xfd,0xbf,0xb6,0xea,0xff,0x02,0x09,0xfa,0x5f,0x59,0xb5,0xff,0x41,0xa2,0xf4,
+ 0xff,0xb6,0xfe,0xff,0x17,0x91,0xfa,0xff,0x5b,0xf7,0xff,0x57,0x64,0xff,0xff,
+ 0xb7,0xfe,0xff,0x5f,0xd1,0xff,0xff,0x6f,0xff,0xff,0xaf,0xc2,0xff,0xff,0x5f,
+ 0xfd,0xff,0xff,0x65,0xff,0xff,0x7f,0xff,0xff,0xff,0xd2,0xff,0xff,0xbf,0xfe,
+ 0xff,0xff,0xe3,0xff,0xff,0x7f,0xff,0xff,0xff,0xd3,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xe5,0xff,0xff,0xbf,0xfe,0xff,0xff,0xd7,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xd3,0xff,0xff,0xff,0xfe,0xff,0xff,0xaf,0xff,0xff,0xff,0xff,0xff,0xff,0xb7,
+ 0xff,0xff,0xff,0xfb,0xff,0xff,0xbf,0xfe,0xff,0xff,0xff,0xff,0xff,0x5f,0xff,
+ 0xff,0xff,0xfb,0xff,0xff,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,
+ 0x9c,0xfe,0xff,0xd7,0xf5,0xff,0x7f,0x5a,0xfe,0xff,0xef,0xf7,0xff,0xbf,0x2c,
+ 0xfd,0xff,0xdb,0xed,0xff,0x7f,0x3a,0xfd,0xff,0xef,0xfb,0xff,0x5f,0x98,0xfa,
+ 0xff,0xab,0xd7,0xff,0x77,0x4c,0xfc,0xff,0xd7,0xea,0xff,0x1f,0x28,0xf2,0xff,
+ 0x4a,0xab,0xff,0xa5,0x08,0xf9,0xff,0xd7,0xd5,0xff,0x17,0x52,0xe8,0xff,0x6b,
+ 0xbb,0xff,0x5f,0x14,0xfa,0xff,0xd7,0xed,0xff,0x7f,0xa8,0xfa,0xff,0xdf,0xf7,
+ 0xff,0xbf,0x2c,0xfd,0xff,0xe7,0xdb,0xff,0x7f,0xaa,0xfa,0xff,0xdf,0xf6,0xff,
+ 0x7f,0x38,0xfd,0xff,0xeb,0xdb,0xff,0xbf,0x4c,0xfa,0xff,0xcf,0xff,0xff,0x7f,
+ 0x3a,0xfd,0xff,0xef,0xeb,0xff,0x7f,0x94,0xfa,0xff,0xd7,0xf6,0xff,0x7f,0x5a,
+ 0xfd,0xff,0xef,0xdb,0xff,0x7f,0x14,0xfd,0xff,0xaf,0xf6,0xff,0x7f,0x54,0xfc,
+ 0xff,0xd7,0xf5,0xff,0x7f,0x08,0xfe,0xff,0xef,0xfb,0xff,0xbf,0xaa,0xfd,0xff,
+ 0xff,0xef,0xff,0xff,0xbe,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,
+ 0xff,0xff,0x7f,0xff,0xff,0xff,0xa5,0xff,0xff,0xaf,0xfd,0xff,0xff,0xa9,0xeb,
+ 0xff,0xbf,0x77,0xff,0xff,0x52,0x95,0xfe,0xff,0xde,0xe9,0xff,0xab,0x2a,0xf2,
+ 0xff,0x6b,0x55,0xff,0x56,0x00,0xd4,0x7f,0xaf,0xeb,0xff,0x2b,0x15,0xf1,0xff,
+ 0xf5,0xb5,0xff,0xaf,0xac,0xfc,0xff,0xdf,0xff,0xff,0x57,0x2a,0xf6,0xff,0xea,
+ 0xd6,0xff,0x17,0xbd,0xfa,0xff,0xf5,0xff,0xff,0x4f,0xdd,0xfa,0xbf,0xde,0xbf,
+ 0xff,0x25,0xfa,0xfa,0xff,0xf5,0xef,0xff,0x4b,0xfd,0xf9,0x5f,0xff,0xbf,0xff,
+ 0x29,0xdd,0xf4,0x7f,0xd7,0xdf,0xff,0xe1,0xfa,0xfa,0xaf,0xff,0xbf,0xff,0x74,
+ 0x7e,0xf1,0xff,0xd7,0xdf,0xff,0xb7,0xfa,0xf9,0xff,0xef,0xaf,0xff,0x7d,0xfc,
+ 0xf8,0xff,0xb7,0xdf,0xff,0xbf,0x6c,0xf5,0xff,0xdf,0xf5,0xff,0xff,0x92,0xf8,
+ 0xff,0x6f,0xad,0xff,0xbf,0x08,0xfd,0xff,0xbf,0xf5,0xff,0x7f,0x25,0xfc,0xff,
+ 0xff,0xfe,0xff,0xff,0x95,0xff,0xff,0xff,0xfb,0xff,0xff,0x77,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xbf,0xff,
+ 0xff,0xff,0xfd,0xff,0xff,0xdf,0xfe,0xff,0xff,0xf7,0xff,0xff,0xaf,0xfe,0xfa,
+ 0xff,0xff,0xdf,0xff,0x5f,0x5a,0xf9,0xff,0xd7,0xaf,0xff,0x2f,0xbd,0xf4,0xff,
+ 0xed,0xfb,0xff,0x7f,0x5a,0xfa,0xff,0xd7,0xed,0xff,0x5f,0x2c,0xfd,0xff,0xef,
+ 0xf7,0xff,0xbf,0xb8,0xfa,0xff,0xaf,0xfa,0xff,0x7f,0x0a,0xff,0xff,0xd7,0xff,
+ 0xff,0xbf,0xd0,0xfe,0xff,0x3f,0xf5,0xff,0xff,0x44,0xff,0xff,0xaf,0xfe,0xff,
+ 0x3f,0xa1,0xff,0xff,0xb7,0xfe,0xff,0xff,0xc4,0xff,0xff,0x2f,0xfd,0xff,0x5f,
+ 0x50,0xff,0xff,0xbb,0xfe,0xff,0x7f,0xa1,0xff,0xff,0xd6,0xf5,0xff,0x05,0x8a,
+ 0xfe,0xbf,0xea,0xfa,0xff,0x8b,0x14,0xfe,0xff,0xfa,0xf7,0xff,0x05,0x55,0xff,
+ 0xbf,0xef,0xfd,0xff,0xd5,0x5e,0xfd,0xff,0xfe,0xf7,0xff,0xd5,0xff,0xfb,0xdf,
+ 0xff,0xff,0xff,0xfb,0x7f,0xfd,0xff,0xff,0xff,0xff,0xfb,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xe9,0xff,0xff,
+ 0x57,0xff,0xff,0xbf,0xd2,0xff,0xff,0xbf,0xfd,0xff,0xbf,0xc8,0xff,0xff,0xdf,
+ 0xfe,0xff,0xff,0xa2,0xff,0xff,0x7f,0xff,0xff,0xff,0x95,0xff,0xff,0xdf,0xfd,
+ 0xff,0xff,0xa3,0xff,0xff,0xff,0xfa,0xff,0xff,0x4a,0xff,0xfa,0x7f,0xfd,0xdf,
+ 0xff,0x87,0xff,0xfa,0x7f,0xf9,0xef,0xff,0x0b,0x3f,0xf9,0xff,0xfd,0xfb,0xff,
+ 0x8f,0x5d,0xfd,0xff,0xf6,0xef,0xff,0xa7,0xbe,0xfe,0xff,0xfb,0xfb,0xff,0x9f,
+ 0x2a,0xff,0xff,0xd6,0xff,0xff,0x4f,0xbe,0xff,0xff,0xef,0xff,0xff,0x7f,0xf8,
+ 0xff,0xff,0xab,0xff,0xff,0x3f,0xfc,0xff,0xff,0xef,0xff,0xff,0xff,0xea,0xff,
+ 0xff,0xbf,0xfe,0xff,0x7f,0xe9,0xff,0xff,0xff,0xff,0xff,0xff,0xd5,0xff,0xff,
+ 0xff,0xfe,0xff,0xff,0xd7,0xff,0xff,0xbf,0xff,0xff,0xff,0x55,0xff,0xff,0xff,
+ 0xfb,0xff,0xff,0x2f,0xff,0xff,0xff,0xfd,0xff,0xff,0x5f,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
diff --git a/hacks/images/matrix.xpm b/hacks/images/matrix.xpm
new file mode 100644 (file)
index 0000000..f740ad7
--- /dev/null
@@ -0,0 +1,904 @@
+/* XPM */
+static char * matrix[] = {
+"56 837 64 1",
+".     c #000000",
+"+     c #178618",
+"@     c #26C227",
+"#     c #114410",
+"$     c #7AEB7A",
+"%     c #5AC254",
+"&     c #136314",
+"*     c #1AA614",
+"=     c #52DB51",
+"-     c #127410",
+";     c #169614",
+">     c #062604",
+",     c #32D634",
+"'     c #145417",
+")     c #B2F6B0",
+"!     c #42A244",
+"~     c #62E75C",
+"{     c #2F832F",
+"]     c #3AC237",
+"^     c #246624",
+"/     c #2B7729",
+"(     c #0C360E",
+"_     c #92F294",
+":     c #4CB34A",
+"<     c #298B27",
+"[     c #0E4E0C",
+"}     c #62DE64",
+"|     c #3B9439",
+"1     c #1D5E1D",
+"2     c #26B529",
+"3     c #CCFDD1",
+"4     c #73E774",
+"5     c #32CB34",
+"6     c #021804",
+"7     c #4ED64C",
+"8     c #7AF67C",
+"9     c #2E9A34",
+"0     c #26CB24",
+"a     c #166E14",
+"b     c #52BB54",
+"c     c #5ED05C",
+"d     c #36B634",
+"e     c #0B3008",
+"f     c #44AB42",
+"g     c #020E04",
+"h     c #8AEC8C",
+"i     c #1E751C",
+"j     c #2AA62C",
+"k     c #42D73C",
+"l     c #286E26",
+"m     c #1F561E",
+"n     c #368B34",
+"o     c #40CC44",
+"p     c #3E9C3C",
+"q     c #0D3E0E",
+"r     c #66E264",
+"s     c #76EE74",
+"t     c #269624",
+"u     c #A1F2A1",
+"v     c #1C4E1C",
+"w     c #3EDE3C",
+"x     c #5ACA5C",
+"y     c #52E24C",
+"z     c #021E04",
+"........................................................",
+"...........gggggg......................gggggg...........",
+"........gggg6gggggg.................g6g6>6666gg.........",
+".......g666>>>e>z66gg..............g66>eee#e>z66g.......",
+"......g6>>>>(>((ezz6g.............66eeeq[q[[#e>66.......",
+".....g6e#m'''&&1[v#e>gg..........6z[-t*;;**2;+-[e6g.....",
+"....g6>v^{{///n|{^1#(6g.........g>e<]k7,]===7]*i[6g.....",
+"...gzze^|:f!|!::!n/^q>6g.......g>zq@}h44rrhh4=o2&ezg....",
+"...g>>[/|b!|nnp!p|n/m>6g.......6e#-o}_4}==r44}=kt#z6....",
+"..g6e[m{:%!{^l/{n!:|1(>6g.....gz[+t7hu4k@5]k=4h}2[ezg...",
+".ggzqml|fxp/''''{!c:/q>gg....gg>&j]}hur5;;;;k4)ho&e6g...",
+"..g6#^/pbx|a[[[[/f}:/#>>g.....6>i2]4hur@++++]4)$o-qe6...",
+".gz>m/npfbnl[#[#l!x:{'(e6....gzqto=44_=@++++54uh7;[q6...",
+".g6em{|!!f{a[[[#/|xf{1#>6g...gzqjk}444w@+++-]}u$7ji#>g..",
+".gze^n!fff{1q#[#l|%:{^v(6g...6z#2=r4$4k2--+-]ruh72+[zg..",
+".g6e^n!!!p{&[[qq/|b:n^m(zg...g>#d=444r,2++--5}uh=2t[>g..",
+".g6(l|:!!p{'q##ql!%:|^1q6g...gz[]}h44r,*----]4uh}]j&>g..",
+".66e^|f!pp/&[[##/|%:|lmq6g...6>#dr44~r0*++--]}uh}]t&>g..",
+".66(mnpf!fn&[[##/|%:{mv(6g...6z[j=r44$=2++--5ru$=j+[>g..",
+".g6e1/n!:bn^[[[[lpbf{mq>6g...gzqjo=44_w@++++]}u47t&q6g..",
+".ggemln!:b9^[[#[l|%!/v(>g....gzqt]=4h_=@++++@ru4o+'e6...",
+".gg>#ml|:x!i['''/!%:/#e>6....g6e-j]}huy0+;;;54uh,-[ez...",
+"..g6([mp%}f/''1^{fx!/q>gg.....g>[+jy_)$,;;2274u4o&e6g...",
+"..g6e(v{%cfi'&&lnfc:/e>6g.....g6q&+7u)40;22@=4)h][e6g...",
+"...g>(#l!bp{a//{n|!/1e6g.......6e[-o4h~k@@0k7}47jq>6....",
+"...g6ze1/nn{<{n|n/l1#66g.......g6eqjo==7k=y}=kbj-z6g....",
+"....gz>q1l{npp!pn^#(e6g.........g>e&j]k=rr4472-'q>g.....",
+"....gg6(#mm^ll//^vq>6gg.........g66'-tjd]]]od+&q>gg.....",
+".....gg6e(##vvvvq(>6g............gg>q[--<<+<-[e6z.......",
+".......g666>>zz>z6g6...............g6>zeeeee>z6z........",
+"........ggg66zg66gg.................ggz6z>66zgg.........",
+"........................................................",
+"............g.g.........................g.g.............",
+"..........gg66g6gg....................g6>z666g..........",
+".........g6z>e>z6gg..................gzze#q>z6g.........",
+"........g6>(qe(e>zgg................g>e[&[[qe>6g........",
+".......g66vlnll^mv#eg..............g6>+]=5]2t+i[6.......",
+".......g6>^|%:|{/l^ve..............6>edruhr7k]d<#.......",
+".......66>{%8}%!nn/^q..............6zq7u3)u4}7]d&.......",
+"......g6>(/x8c!{/^mqe.............gze#ou3)4oodjiq.......",
+"......g6>({b8%|mmvve6.............g>e[7u3u}j9<iq>.......",
+"......g6een%8b/#q>>6g.............g>q[7u3_o-&qe>g.......",
+"......g6>(nb_:/qee6gg.............gzq[7u3ho&[qz6g.......",
+"......gz>(nb8:{q(>z6..............g>e'7u3hk&[e>z........",
+"......g6een%8b/qe>g6..............g>q[=u3ho&[e66........",
+"......g6een%8b/q>>zg..............gzq[7u3h5&qe>g........",
+"......66>enb8:/ee6gg..............zze[=u3ho[qzzg........",
+"......g6e(n%8:/q>>6...............g>qv7u3ho&qe6.........",
+".....g6>>enb_:/qe66..............g6eq[=u3$]&q>6.........",
+"......g6eqnx8b/(>>gg..............z>q&7u3hk[qe6g........",
+".....g6>eenb8b/qe>6g.............g6eq[=u3hk&qe6g........",
+".....g6>eqnx8b/qe>gg.............g>e[&7u3h0&[e6g........",
+".....gg>eq{%8b/(ee6g.............g6e[&=u3_o[[q>g........",
+".....gzzeqnx8:/(e>6g.............g>eq&cu3ho&q(zg........",
+".....gzee#{%sb{((>6g.............g>q[-=u3_k&[e>6........",
+".....6ge#mn:c!{&#q>6.............66[-97h)4k*-&e6........",
+".....g6qv^{f%!{^'q>zg............gz&<d=4u47];&qzg.......",
+".....ggqmln|f|{lm#e6g............g6&j]7}4}7]ji#>g.......",
+"......geqvm^/^mvqe66..............gq&<jdo]9{&q>6........",
+".......gze(q#qqee6g................6eqv&i&&q#>g.........",
+"........gg6g6gg6g...................g6666666g...........",
+".........gggggg......................ggg6gg.............",
+"...........ggggg.......................ggggg............",
+"........ggg6zgg6gg..................gg6z>zz66g..........",
+".......g6z>e(e>e>6gg...............g>>eq[q#qez6g........",
+".....gg6>eeqqqqqeezgg............g6>e[[&&&&&[q>6g.......",
+".....g6>##vv#v[[#q(>6g...........g6q&-++++++-&[qzg......",
+"....gz>m/n{ll^^^^^/1qg..........g>eto=7@]@22@]oj'6......",
+"...gg>el|%!|{{{{n||{v>g........g6e[]ru4}kk7k7}r7<eg.....",
+"...gzeq{bc%pn{nn|!b|m>g........g>q&7h)u4==7=r4h}jeg.....",
+"...g>qv{bc:|/l^l{|fnm>g........gq&+=h)$=55@]7}h=9e6.....",
+"...gev^|bcp{&&'m^np{m>g........6[+d}_u4k2**;]=r7teg.....",
+"..g6qm^|bx|l'[[#m/|{v6g.......gz&t]}hu}5;++-jo}7<>g.....",
+"..ggev^|bc!i[[##vm^me6g.......g6'+d}_u4@++a-+jd9'zg.....",
+"..g6e#m|:c!/[[#(####>g........g6[ij}h)45++-&-ii&eg......",
+"...g(#m|bc!i[[#q(e>6gg.........6[ij}h)40;+-&[qe>zg......",
+"...6e(v{!%p<a'[qee>zg..........6q[+74ur,@*+&[(ezz.......",
+"...g6e(/|f!n{a1(qe>6gg.........gz[&]}$r=,@*&&qe>gg......",
+"..g6zee^n|!!p{&#q>>66g........gz>q[2=r44r,*-&qe>6g......",
+"...g6>e'l{n9!{i'vq>>gg.........g>e[;@ky=~,0*+&qe6g......",
+"...66>e[1l{|f|</&[(e6g.........6>e[+j@kr~rw02+[q>6......",
+"...gz>(#['itpp9|/1q>>6g........gzq[-+;5w4~=y0*&qe6g.....",
+"..g6eeq['1lt|ppp{^'#e6g.......gzq[-+;*5wy~~~k@;-[z6.....",
+"...ge#m1&-{{{t9!p<{^#>6........6#-;*20,,kwy~~=,2-ez.....",
+"...6qv1ll{iii<pffp|/m>zg.......z&<2]@,500wr4~r}ktqzg....",
+"...6(m1i{{<{{tpf!f!<megg.......z'tj5k=wk,wr$$44=tqzg....",
+"...ge#m/np9||!f:ff!n'egg.......6qit]=ryyr~4$$44=tq6g....",
+"...ge(v/n!f!ff:f:!p{m>6........g#&<o}444$4hhh447tqz.....",
+"...g>(q^n!!!!p!!p||lv>g........ge[-d=4444444r}}o+e6.....",
+"....g>evm^lll/ll^^^v(6g.........6eq+9d]]d5]]]dd<'zg.....",
+".....g6>e(q(#q#qq((e6g...........6>e[v&&-&-&&[[(zg......",
+"......gg66>>>>>>66ggg.............g66zeeeeeezz6zg.......",
+"........gg.6gg6g6gg.................ggg6666zzgg.........",
+"..........gg6ggg......................gg6ggg............",
+"........g666>>>6gg..................6z>>eeezzg..........",
+"......g6z>e(qee(ezgg..............g6>e#[&[[[(>6g........",
+".....gg6eeq#####ee6gg............gz>q[&-----[qz6g.......",
+"....ggzqm1mmm11mvq(>g...........gzz&;jjtjjjj+&[e6.......",
+"....gz>m{pn/l//n/^m#>g..........g>q97~=o5ok=odtiqg......",
+"...g6>(/fx:p{n|!|{/mqg.........g6e[o4uhrk=}4r759v6......",
+"...g6e#nbc:|{||!|n/^q6.........g>#-=_)hr,=r4r=kd&6......",
+"...ge(vn:cfnl/{n{//mq6.........gq&{7h)47@o777o]9&>......",
+"...gevm|:c!/11lllllm(g.........6[+j}h)45*2@]o]]9'6......",
+"..g6qv^|:x|l'1mm^^^m(g........gz&<2}hur5;jjjdddt[g......",
+"..gg(#vnfxfn^a1mvv#(>g........g6[-t=hu4=@@*t+<i'eg......",
+"..g6>ev{fxf|</m#qeezg.........g6e[+74u$}k5j-a[qeg.......",
+"..g6>e#{!xbpn{m#ee6gg.........g>q[-k$u$4=5j-[qz6g.......",
+"..gzeqvn!x:f|{^#qe66g.........gzq&+k4uh~rk2-&qzzg.......",
+"..g6e#'n!%:f9{^mq>gg..........z>[-t=$uh4yk@t&q6g........",
+"..gzq[mnfx:!|{lm#(zgg.........g>&+j=$uh4r7]t-[>zg.......",
+".g66v^/|!:pn/^1[qez6g........g6z+20}4h~75@j+&q>6g.......",
+"..g>m/n|ppn/&'vqe>>ggg........ze9]=}rr=,2;+&[(e66g......",
+"..6>mnpp!9{&'[qq(>ez6g........zej=r~~y,2;+-&[qq>6g......",
+"..g>m/nppp{a[[[['1mveg........getorrrr,@++++;jj+[6......",
+"..g6vl{n!!{^'1'1l{n/v6g.......6>+]7}r4k@;***@k}o+>g.....",
+"..gzqml|p:n-''&l{!b|1>g.......g>&j]=4hk@;*2]74_rjeg.....",
+"...gq#m/n!n/&ll{{np{m6g........6[ito=~=02@@k7}}79zg.....",
+"...g>e#1/{{{/{{{n{{^q6g........ge[ijo=k,ok77777d&>g.....",
+"....66e#1ll{nnn|nlmv(gg.........6>#-j]]7===r=]j+[zg.....",
+"....g6gqvm^^///llmvq>6..........g66&+jd@]oo]]j<&e6......",
+".....g6>(q#vvvmmvq(egg...........g6e[&i++ttt{&[#6g......",
+".......gg6>>>e>>>6ggg..............g6>eeqqqeez6gg.......",
+"........ggg6g66666g.................gg66zz>>zzg.........",
+"...........gggggg.g....................gggggg.g.........",
+"..........g.g.........................g.g...............",
+"........g6g66gg.....................66zz66g.............",
+"......g66e>>e66gg.................g6>qe#q>zgg...........",
+"......g6e>((ee>6g.................g>qq[[[qe>6...........",
+".....g6>#[milmq>66...............g6q-+*@5t&ez6..........",
+".....66qvm{n!{1(e6gg.............6>&+jo}r,j[q>6g........",
+"....g6>v^l!%c!l((e6g............g6e+25~u)$5&[qzg........",
+"....g6z[^{p:cfn&[ezzg...........g>e+dk4h)4k2+[>>6.......",
+"....6z>'a{!:xfp{a[>z6g..........6>q;@krhusrk@+q>6g......",
+"....6>em^{|:b:!p{1(e6g..........zeqt2kr$_h4r,*[q>6......",
+"....g>>ml<|fbbf!n^[qe6g.........6eqt5ky4h$$$=@+&qzg.....",
+"...gzz(&/<9fffffp{im(>6g.......g>e[*5w=~$s4~rk5;&e>g....",
+"...gz>('/<9pfff!f9{/[e6g.......g>q[*0wy~~~$$~==5+qz6....",
+"...gzeq1/t|jffj:ppp{1(>6g......gzq&j5wyr~s~44~}7j&ezg...",
+"...g>e[a{|!!dfp!p!f|l'(zg......ge[+@ky~~4~~r~~4y];&eg...",
+"...g>q[^|!j::j!<!f:p{1#e6......zq&+@y~~ss~~wr$$4,j-qz...",
+"..g6e#&i9f:::f!<9:%!n^v(6g....gz#-*5=~sss~~w=sh4=2+[>g..",
+"..ggq'1n!b]xxdj!f!f!{^'ez.....g6&t2=~__uus~~~4h47@t[z...",
+"...6q1l!bcxccb:j::dp{lm(6......6&j]~huuuu_s~$$$r7]9'z...",
+"..g6qm/pbxcxcx:d!!p|{lmqz.....g>&jo~_uu)uuss~4r}7]t&>...",
+"...gq[1{!dbdbj|<{{llmvq>g......z[+*k~$$s$~ykw,]@j+&qg...",
+"...6>e#l{ppp!<{&1''[qe>6g......6e[-]kr~~4w52*;;+&[q6g...",
+"...g6>>'^{{n|i1#((e>>z6g.......g>eq;@kk==52-&'qqe>zg....",
+"....6ze[^i{{{^[e(>>z6g..........6eq+25ok=@+[[qqzzg......",
+"....g6zqm^a//1#e>zzggg..........g6z19d@o]j-qe>>6gg......",
+".....g6qvm^^lmq666g..............6>&+jdd]t&>z6g.........",
+".....gge(##vvqe6gg...............g6#'ii++&qzgg..........",
+".......g>e>e>>gg...................6eqqq#egg............",
+".........6ggg........................6ggg...............",
+"........................................................",
+"........................................................",
+"........gg6g6g6ggg..................gg666666gg..........",
+"......g6>>ee(e(e>6g...............g>e#q[[[[[qz6.........",
+".....ggeq#vvv'vvq(z6g............g6q&i++<t++&[>zg.......",
+".....6>(vm111m1^v#e6g............6e'<tj2jjjd<i#>6.......",
+"....gzevmll{{nnn{^v#>g..........6e#+joook==}kd+&eg......",
+"....6>q1/nnnn!fb|{mveg..........6q&j]===r4$hr7j+[g......",
+"....zeq^{|p!pbxcb|/m(6..........>q&d7r~4rhu)_}o9'z......",
+"....ge(v^/{n{|:bfn/m#6g.........6q[td]k=krhh$=oj&>g.....",
+"....6ze#m1aii<|f|n/1q6g.........ze#-;2@00w=$rk]j&6g.....",
+"...g6>e(#['1&i{|n{lm#gg........g6eq&-+;**0kyykoj-6g.....",
+"...gg>>#'1ai/|9fp{/1qzg........gzeq-;2@0,wy4rkoj&>g.....",
+"...g6>('a{{|t!fbfn/mqgg........gze[;@,,=y$$h$=oj&6g.....",
+"...g>>(m/n!f:bxx:|/mqzg........6>q[jo=4sshuuh}o9&>g.....",
+"..g6e([/|!!!f!f:|{^veg........g6q&+0=$4~~4$hrk2+[6......",
+"..ggev1<!%fp{nnn/1vq>g........gz[+j=$h4r=k==o2+&eg......",
+"..6z#1l!bxftii^1mvee6g........6>-*5r_)4w5@@2t{[#zg......",
+"..g>#l{!:x!{a&1'#q>6gg........gei]74hu4,@2*;-&q>6g......",
+"..6>'/n!:fnl1''[q(ezgg........6et]=4$hy5*;;+&[q>6g......",
+"..gzm{pp|!{&[##qe>>z6.........ze97~rrr,2+--&[qezz.......",
+"..g>m/np||{&[q##qqe>g.........geto}rr=k*+---&&[e6.......",
+"..gg#m/{|p{a'&&^^m^m(g........g6ij],r4,@;**22jdt'g......",
+"..66(#m{|p{^'1l/{{{l#g........z6'-jo}r7@;*]o777]i6......",
+"...geq[ln!{^'^/nn{|/#6.........zq&+]=4w@;@0===}oi6......",
+"...g6e(ml{/ial{n/{lm(g.........g>q&*]7o5@o7=77]j'g......",
+"....66>#'^l//{{n/^m#eg..........6>e-t2]oo777odjiqg......",
+"....ggze#'^/{{/{/m#(6g..........g6z[-;2o7o77]9iv>g......",
+".....g6>eq#vmm^mv#e>6............gzeq&i;tjjj<iqe6.......",
+"......gg6>eeqq((ee6...............g6>eq[&&v'qq>g........",
+"........gg66g666ggg.................g666zz>>6gg.........",
+"..........ggggggg.....................ggggggg...........",
+"........................................................",
+".......gg>>>ezg6gg.................g6eqeqe66gg..........",
+".......eq#vmmvq>6gg................q&i<9j+&#>6g.........",
+"......gqml//{^vqe>6gg.............g&9]5o7d+&qezgg.......",
+"......g#ml/{n/^[#e66g.............6&j]o7=]2+-[>>g.......",
+".....gg(vm^//{{/^'(>6g...........gg'{tdo7k7,2;[qzg......",
+".....ggz(#m^/{p!n&#(>6g..........g6e[-j25k}4=2-[e>g.....",
+".....gz>e(mm^n!:p/'#(6g..........gzeq[;j@74hr5;-[z6.....",
+".....66>eq['&/<!|nn^[ezg.........z>e[&+;25wrr==@+q>6....",
+"....g66eeq['&^{t|pf{^(z6........g6>q[&+;*@,wy~$=2[>6....",
+"....gg>>e([''aa{9fb!^q>6g.......gzeq[&+;;@@ky4h4]&q>g...",
+"....6zev^liii<<pf%c:/qe6g.......6>q+2@000wwr4_)h5&qzg...",
+"...g6>q^n!p||pffbx4b{[>>g......g>q&d=4rryr~$_u)_,+qe6...",
+"..gg>e#{!x:f!f:bxrsxn[e>6.....gge[-,4uh4~4shu)3u=+qe6...",
+"..g6(v1nf:f9+|9pdxrb{[e>gg....gz[+27$h4ywyy~$))u,+[e6g..",
+"..g6#^l|f:|{aii{|fc:{q(>6g....g>i2o}$hrk205,=$)hk-[e6g..",
+"..6>m/||f!na1''&/!%!i#(>gg....zeto}r4$k@****,4_4@-[#zg..",
+"..g>m/p|!!{&'''&+p%!{qe>gg....gejorr44k2;;;*,ru$o-qe6g..",
+"..g>m{|p|p{a['''/pxfi#ez6.....6e97}r}~,@+;;;5ru40-[z6...",
+"..g>m{p|||l&'[[[{9x!/qe6g.....6ej7rr}}52;+;+,ru$]&q>6...",
+"..g>vln|||{&[''&{!%!iq>zg.....ge<o==rr02+;**,4u40&q>g...",
+"..ggqmlnp!na'&&^{!%!l(>zg.....g6&t]=~$=@;*2@k4u4][e>g...",
+"..g6e(v/!b|l'&//|!b|1ezg......g6q&+o4h=0*25o=4hr2[z6....",
+"...g>(#l|!n/'li{{|!n1>6g.......6e[i]}$=5*@5k7r4=j#6g....",
+"...g6eevl{lill{{{/lmqz6g.......gzq[<]ko@]5k77o]9&zzg....",
+"....g6>(v1^///{{lm#(>gg.........g6e&+jdoooo7]j-[e6g.....",
+"....gggeq#1^//l/mv>66gg.........g66(&-jdo]ooj-q>>gg.....",
+".....gg6>(q#vvvvqez6g............gg>q[&-<++{&q>6g.......",
+".......g66>e>>e>>6gg...............g6>eqqqqqe66g........",
+".........ggg6g6ggg...................gg66666zg..........",
+"...........ggg.g.......................ggg.g............",
+"........................................................",
+"......g6>e>eee(e>e>>6g............gze(#[[[[[#qqezg......",
+".....g6eqvmmmvvmvvvq>6g..........g>[&+<tt<+t+++&qzg.....",
+"....g6e#m1^lll^l1^mmqe6g........g>#ij22]@]@]ddjt&#>g....",
+"....6>(m/n/{{//{l{l^vq>g........6e[9o=77oooooood<&e6....",
+"....g>q/!%f|nnnnn||n^vq>........6e&oru4r=====rr=d+&e....",
+"....>e#nb4xf||nn|!:|/m#e........e#i=u3u4ry==r4hr]jiq....",
+"....6e#|%4x:|||n||p|/m#>........zqi}u)uhy}y=}r4}o9iq....",
+"....g>(/!x:p<{/l///^mv(>........6ev74uh~wko@]oo]ji'e....",
+"....66(^|:p|{aa'vmm##(eg........zz[d}h~},@@;;tti^'q6....",
+"....66e1n!n{{l1#qq((ee>g........z>qj=4==k@*-&&&[[qe6....",
+"....g66v^/n9p{&q#eee>66.........g6>+do==r,2-a[qqe>6.....",
+".....66qv^{|:{^qqe>66g...........6>&<27rh72&&[ez6g......",
+".....g6>q#/|b|&qee>6g............g6(&+or_w@&[qe>z.......",
+"......g>e#ln!nl[qe>66.............geq-]7$7@+&[e66.......",
+"......ggzem{|n^1ve>6g.............g6e(j7}=@*+[e>g.......",
+".......66>m/|{l1vq>6g..............6>eto}7]j+&e>g.......",
+".......gz>qm^//{^#>zg..............g>e&j]]kk@-e>6.......",
+"........g6eqvln|/m>z6g..............g>q&+]7rote>6g......",
+"........g6zee1n:nm>>gg..............g6eq[2=h=*qe6g......",
+".........g6>emn!n/q(>g...............gzeqj=$=]-[eg......",
+".........g6>>m/!n/^veg...............gzeeto4y]d<#6......",
+"..........g6>vl|n//mq6................gze+]}=7]j&6......",
+"..........gg6qm///{lqg................gg>^9ooo7]&6......",
+"...........ggeqv^/{lvg.................g6q&<do7]i6......",
+"............gg>evl|/#6..................g6eq<]}ki6......",
+".............gg6qmlm(g...................g6>^9]jmg......",
+"...............ge(#(>......................gqvive.......",
+".................gg..........................gg.........",
+"........................................................",
+"........................................................",
+"........................................................",
+"...........ggggggg.....................ggg6ggg..........",
+".........ggg66z6g6gg.................g66z>z>666g........",
+".......ggze(qqq#eez6g..............g6>#[&&&-[qez6.......",
+"......g6>e#v11m1m#(ezgg...........g6eq-<jjjjt-[q>6g.....",
+".....gg6eqm^////l1qqe6g..........g6>#&t2ook5]j-&qz6.....",
+".....g6qm^ll////ii/1#>6g.........gz&j]]oo55o00oj-ez6....",
+"....gg>m{|n{l/il{np{1(z6........g6et7}=k@555k=~7j[>6....",
+"....gz>l|%p{laiinfx!iq>6g.......g>e]}_rk@@@@=4u45&q>g...",
+"....g6e/fx!{iiii<fx!l#e6g.......gzqo$u4k0000w4u$]&qz6...",
+"....g>e/:cf<^aaa|fx:{q>>6.......6e#oh)4k@@@@w$u4,-qez...",
+"....6>e{:}ftaaa&<fcf{[ez6g......6e[7h)sw@@@@,$uh,+qe6g..",
+"...gg>(lfx!9/{{{pb%:{[e>6g.....gze[]$u4w,0,,~su4,+[e>g..",
+"...gg>(l|:f!fjfd:]x!i'e>gg.....g6e[]}$$~~~4$s_u45+[e6g..",
+"...g6e(m/|fdbxcccxxf/[#>zg.....g>q[jor~s_uu)uuu$0+&q>g..",
+"...g6>em{n:%cxcccxbf+#(e6g.....g>e[j5}$_uuuuuu_~,+[q>g..",
+"...gz>(l{ff:xbb::bx!{'(>zg.....gzq[@=~4su__$$_u$,;&qz6..",
+"...gzee/pb]b%dfjfdx!{'#e66.....g>q[5~s___$~~~$u~,;&qz6..",
+"...gz>qipb:]bf9<p:bf{1#e6g.....g>q&5rh$_s~yw~$_4k*-[zg..",
+"...gze(/!xfp9<{i<9fp{&[(6g.....g>q&5$u$ryw,0k=$rk2+[>g..",
+"...g6zq/fxf<iia-/<!9{^m(>g.....gze&o4u~w00@@,w4rk@;&e6..",
+"...gz>q{:x!{''&'i<|n{^&qz6.....g>e&7hu4,****0,==k]j&>6..",
+"...gz>e/!cpia'&'in:!{^m(6g.....gzq[]4)r02**;5yh472;'zg..",
+"....6ze/!x!{&1&'ip%:{mv(gg......6>[o$u4,2**;0ruh7j+'6g..",
+"....66e/!%!/&''[/px:n1#e6.......z>q]4u~02*;+54uh=jiqz...",
+"....ggzm/|{/aa&&/n!n^#e6g.......g6>to}7o@@22574=di[>g...",
+"....gg6qm^ll/ll^///lve>6........gg>&9d@]0]@]5oo]<[e6....",
+"......g>e(m^l///l^mv(66g..........ge[&td]o]o]dj+[>6g....",
+"......ggz>qv1mmmm#v(>6g...........gzzq&+jt9jtii'e6g.....",
+".......g66>eq((((e>>.g.............gz>e#&''[[qqegg......",
+"...........6g6g6gggg..................g66>6>66gg........",
+"............gggggg......................gggggg..........",
+"..........gg6666ggg...................gg666zggg.........",
+"........gggg66666ggg................ggz6>>>>>z6g........",
+".......gg6eqv#vv#(e>gg.............g6>q&ii++-[qe6g......",
+"......g6z>#m^^^^1#q(z6g...........66>e-t@dddji&[e6g.....",
+".....g66eevl////l1[q(6gg.........g6>q[+@oooo]*+&[>6g....",
+"....g6zqm^ll///lll/^v(z6........gz>&t@]]o5o@5oo2+[e6....",
+"....g6>v{|{{/l^^/n|n1qe6g.......gzqtk==k55@@]=r=2&q>g...",
+"...g6z(^|:!nii&&{!:!lv(>g......gzz[drhr=5@22k~h4o+[q6...",
+"...g6>(lp:|{l^&1lnf|{'#e6g.....g6q[5rhr,@2**5=4rot-q6g..",
+"...gze(/pb|i&&''anpn/^'e6g.....g>q[o~_}52*;;@=r=o2t[>g..",
+"...g6e(l!b|i''''^/n|/^mqzg.....z>q&54_=0;;;;25}=k]j&z6..",
+"..g6>(#{!xpi'&'[a{||{l1qz6....g6e[-o4ur0**;;@kr=k]j&>6..",
+"...6z>q{fxp+'&''a{!|{l1q>g.....6eqak$uy,;**;@k~rk@j&eg..",
+"..g6eeq<:x!/'&1&i{!p{lmq6g....g6qq-kh)~,****0krr7]j&>6..",
+"...6ze#{:c:ti-ia{p:p{^vezg.....ze[a7$usw000@krh4k2+[>g..",
+"...6>>q<bc%dp|t|pfb!/m#e6g.....6eq-k_)_s~ywyr4h4oj-q6g..",
+"...gzeq{b}cbf::fbbx!{v(zg......g>q&kh)u_4s_4__u$k+[eg...",
+"...g6>q/fxx%b::p!ff|^qe6g......gzq&o$uu_hhs44$$}d&#>g...",
+"...g6>>^n!fbbf|{{{/^ve66.......gzeq2=44h_~},o7o]+[z6....",
+"....6>e'inpf:p+''mv#e>gg........6eq;5=~4hr,*;;+-#ezg....",
+"....gg>#1i|!b9{1'q(e>66g........g6eij5=4h=k*;-&qq>6g....",
+".....66(#'{t!|{i^[(e>ggg.........6>[-tky$rw52+&(e6gg....",
+".....g6>e(^nf!pni'(>zzg..........g6e[&d=44r=5;[q>>g.....",
+"......g6>>m/p|||{1qe6gg...........g6eq*or}r}o*&q>zg.....",
+".......66>qml/{n/1m#e6.............z>e^t]o7=o2;iq6......",
+"........gzeeqm^//llmeg..............gzq[&t2oo]]9[6......",
+".........gg6zqml^/lm#6...............gzze&9]]o]j&6......",
+"..........g66eqvvvvq>g................g6>q1<{<{&eg......",
+"...........ggg6>>e>6g..................gg6>e(qe>g.......",
+"..............ggg.g.......................6gggg.........",
+"........................................................",
+"........................................................",
+"........................................................",
+"........................................................",
+".............gggg........................gg6g...........",
+"...........gg6ee>g.....................g6z#qe6..........",
+"..........6>(#ml'#gg..................6q[ij]t&6g........",
+"..........>(v^{|/v6g..................e'+d7ro<z6........",
+".........geqv/|:n1>6g................g#&<orh=jez6.......",
+".........g>(vlp%|mez6................gevi]ru}jq>6.......",
+".........g6>(l|%|le>zg...............gzq'b}ur][e>6......",
+"........g66>e^px|lq>z6..............zz>e#]rur]&(>6......",
+"........ggz>(^|:|l'q>6g.............g6>q[d}$}5;&q66.....",
+"......ggzz>eem{!n/^v(z6...........gg>zeq[*747o2+&>6.....",
+"......g66>>((1l|{{l1qzgg..........gzzeq[[jo}=7]j&z6g....",
+".....g6ee##vvml//{/lv>6g.........66#[--++*]ook7]+e6g....",
+"....666qm1m111m^/{|/'>6gg.......6zz&tj**j*j257}ot#>6g...",
+"...g6z>v^/l^l&'[l{!{1(>6g......g>>q+2k5@]2;+@k47j[e6g...",
+"..g6>q#m/{i^m''#^{!n^q>6gg....g6q&-joo]2*;;+274=2&e>6g..",
+".ggzqm^l/{/&''[[a/!n1qe>6g...gzz&t2]ok52;;++@kr=2&qez6..",
+".gz>vl/{{{^1[[[v^{!n^q(>z6g..gze+]]kk7@*++++2k4=2-[q>zg.",
+".g6em{||n</&1''&{|:p<^m[qe>..g>[j7r}=k52***2,}hrk@t+&[e.",
+".geq/pb!|{{/^i{{|:%b!pnl^v(g.zq&o4h4y=k0@@,krhuh4r=o2+[6",
+"g6e#nbcb!{{{{npf:%cxxxb|/^#zg>qi=_)h~k7,k=r$hu)uuuhrodi>",
+".6e#/:xp{{/ii{n|!!::::p|/mqz.>q-7hu4=o55]k7}r4hhhh4}oj&z",
+".g>q^n!{^m1''m^1l/////l^1v(g.6e&d747@tj;tj2d]]oooo]dj<'6",
+".6>evl/m'(eee(e(qq#q#####qeg.zeqt]]j+&[[['[[^&i&iiiii&#g",
+".g6>qm1#(ee>>e>z>>e>e>e((e6..g>e19ji[qqeeqeeeq#eq(q''q>.",
+"..g6e(qe>66z6g6z6z666z66666...g>#'&[e>>>z6>z>zz>z>>z>>6.",
+"....g6zg66gggggggg6ggg6g........g>zz66gggggggg6gzg6g....",
+".......................g...........................g....",
+"........................................................",
+"........................................................",
+"..........g66gg.......................66>6g.............",
+"........g6>eqe6g....................g6e[&q>g............",
+".......ggz(#mq>gg..................g6>'it&q6g...........",
+".......6(qvm^vq6gg.................>[&+jd<'66g..........",
+"......gev1l/{^#>6gg...............g[<j]k72-ez6g.........",
+"......gvl{n||/'>>zgg..............gi]c7}}o;qe>6g........",
+"......g(^/n||/^vqe6gg.............g&d7=}}od+&qz6g.......",
+"......g(#ml/nn{/&#ezgg............g'i9]o==kk2-q>6g......",
+".......g>(ml/np!{1>>6g.............6evt]7=}47jqe66......",
+".......gg6#m/{!fn^#(>zg............g6>ijo74h=d-[q>6.....",
+".......g66(#m^/n/{/^#e>g...........g6>[itd]=kko2iqeg....",
+"........g6>(qvm^/n!{^q>6............66e[^+j2o74=2&qz....",
+"........gg6>e(#v/|:!/#(>g...........g6zeq[-<o}hroi[eg...",
+"........gg6zeeq#l|bp/ve6g...........ggzeq[&+]}h4]+[>g...",
+".........g6>eeq[l|:!/vq>g............66eq[&+@}_4o<&eg...",
+".........g66>e##^|:p/ve>g............g>zq[a-]}h4]+[eg...",
+"........gg>e(vml//n/mq>g............ggeq[+*]]7=o9&q6....",
+"........g6>e[^/n{lmmq>zg............g>([+2o=7]jt&q>g....",
+"........66(#vlnp{^qe>66.............6z[-+]=47d&'e6z.....",
+".......g6ev^{{/{^v(>zgg............6>q<d7777]+[e>6g.....",
+".......ze(^npn/mvee66g.............>#&d=47oj{[qzzg......",
+"......g>(v/!%p^(e>ggg.............ge&i74urd[qe6gg.......",
+"......g(v^/|p/m(zz6g..............g'<do}}o9[e>zg........",
+"......gq^{/llmq66gg...............g&d7ob]t&>zgg.........",
+".....ggv/|/m((e6g................gg<o}k9&'qzz...........",
+".......qm/m#(>ggg..................&j]9i'e6gg...........",
+".......>(vee6zg....................e'<[qz>g.............",
+"........gggggg......................g6gggg..............",
+"..........g...........................g.................",
+"........................................................",
+"........................................................",
+"........................................................",
+".........ggg6g6g6g...................gg666666g..........",
+".......gg6gz6z>z6g6gg..............g666>>>e>>666g.......",
+".....ggz>((q#####(e>6g...........gg>#[[&-----&#ezg......",
+".....g6eqmmm1^^l^m#(eggg........gg6[&ttjj2@b2t-&#6gg....",
+"...g66>qm^ll/{nn{l1vqzgg.......g6>e&t]]]o7==7]j+&e6g....",
+"..gg>e#m^llll{npn{l1vq(>g.....gge[-t2@]]]k=4=k]j+&[e6...",
+"..g6qml^l/^&1/p:pn{ll1v(6g....6>&9]]b5@2*or$4=,]]j+[zg..",
+".g6>mln{/l^'[/|bf|{{/l^#>6g..gzeto77k]2;+5}_4r=koodie>g.",
+"gg6e1{|{/l1'[/p%:p{{{{lv(>g.gg>#j7}75@j;+5ru$}kkkko<[e6.",
+".6e(^n|{1''#ql|bp{all//1#(eg.zq&d=}k2;;a-5}h4k@5]o@j-&qg",
+"g>e#l||{mqq##a|bp{1&/{/^1#ezgeq-]}roj----@=_}k*257k@ti[>",
+"g>e#/|!l'qqq#^n!|/&al//l^mq6ze[io}$];&&&&@=4r5*@55o]dj&z",
+"6eqvlpf{'q(qq'/|n{/{/ll//lv>6q&{5}$o;&&&&*o==koo5@]oo]<e",
+".e#m{|!l&(q(([^l{{|{ill{|nm>g#-97r$5*'&&[+2ok=yk5@@7y=9#",
+"6e#v/pf/1q(qe['1/{p|i&^{|n1(6qito}$k*&[&[+;25=~y52@xr=j[",
+".zev/|f{'#qeq(['lnp|{ll/n{vegeqior47*--[&&+;574}75]k77<q",
+".g>(lp:n^[#(((q#anf!nl//{/v>.6e'brh=2+-[[[&-@7$475@o7o<e",
+".6ge^|!{l'#q(e(qmn!!n{l//l#>.z6qd}47];--[[[&j=44=oooo]ie",
+".gg>v^{ll^1''#qq'l{{nn{l^v(g.g6e<do]]2*t;-&&;]77==7]2t'6",
+"..gge#vm^l^1^'#e#m1/{pnl##>6..gzqi<9d]djd;-[-;25=rybi&e6",
+"...gg>eqm//ll1[e(##m{!|^(>gg...g6eqij]o]]j+[&-ij74}d&ezg",
+"...ggg>(#vvvvq(ee((vm^^#>gg....gg6e[i<<<+&vqq[[ij]die6g.",
+".....g66eeeeeeee>>>e(qqe6g.......g6>(#[q[[#qeqeqv&&q6g..",
+".......gggg6g6z>6666gggg...........gg66666eez6>66zgg....",
+"..........ggggg6gggggg................gggg6zgggggg......",
+"...............g...........................g............",
+"........................................................",
+"........................................................",
+"........................................................",
+".........gg.g........................gg.g...............",
+"..ggg6g66g6g6g6ggg............gg666z66z6666ggg..........",
+".gg>>>ez6zzz>z6666gg.........g6eeqq>>>>>e>>>z66g........",
+".z>eeeq(ee>>e>e>>z6ggg.......>e[#[&[qqqqqqqee>z6gg......",
+"g>#vmm''['1^^^'[###(>6g.....gq-<tt;;;;*2@2;+---[qzg.....",
+"6qm^^/ll^i{||{ll111vq>6g....6&td]oo]@5k=}=o]2jj+&qzg....",
+"6#^/{{nn{{pf%fp/{/l^#e>g....>id]777=7krhu4roooodi#e6....",
+"g(vm^l^lal|f%!{^^11vqez6....6'<*2@@525=4u4k@2jj<&q>6....",
+"6ee#['&&1&{!bp{1''[#e>6g....zq[i+;**22k$h~k*;;+-[q>g....",
+"g>>ee(#[[&{fbpi[#q((e>6gg...6eeq[&-++*,~_r0;-&&[qe>6g...",
+">ev'''['1&<!x!/''[#qeee6g...e[+;;;+;*2k$ur,;;+-&[qq6g...",
+"(vll^''&1a<:%j<&'&[[q((6g...[<]o2***2@,4u~w2**;+-&[>g...",
+"(^np{l&a-ipfcf<a&'1'[#ee6...']7},@2@@@~hu4,@2**;+-[qz...",
+"em/{ll11^-p:cfna^11'v#(>g...q9o7]@*2@@ysu$=@2**;+-&e6...",
+"e#ml111^al|:xf<^&1[m[#(>g...#ij]jj*2@@~hu4,22j;t+i'eg...",
+"6(#vv['1&ln:x!{&&m'v##(>g...>vi<+;t*2@=hu$k22;;+i-[eg...",
+"g>eq#v['m&n!x!{1''##q(egg...ge[1-++;j*=$u4,*;;i-&[#zg...",
+".66>e((q['{!%|/##qee>>6g.....6>e#'&&+;,4u}]--&[qeezg....",
+"..gg66>ee(/|b|1q(>>6gg........g6>ze[[&o}_}2&[qe>6g......",
+"....66z>eelpb|1e(>>6g...........6zzeq[]}_=2[[ee66.......",
+".....g6>>(l|:n&(>>g6g............gzeq[]}h=2[qe6zg.......",
+".....g.>>>l|:n1(>>6g.............ggzeq@}_=j[qe6g........",
+"......g6>e^|bn1(ezgg..............g>eqdrhk2[q>zg........",
+"......gg6>^|%|lqe>6g..............g6zedrur@&[ezg........",
+".......gz>^|%|/vq>g................g>edrur5<&eg.........",
+".......gg61|%|/vq>g................g6>jru}]<&qg.........",
+"........g6vm{^v(e6g.................g6ij7d<&q6g.........",
+".........ge(q(e>6g...................gqv^&qe>g..........",
+"...........6g6gg......................g6666g............",
+"............gg.g........................gg.g............",
+"........................................................",
+"...........gg..........................gz...............",
+"........g6e(qeg.....................6zq'&#6.............",
+".......6>e#vm#>....................ze'i{j&e.............",
+".......ge(v^lme....................6#v<d]9v.............",
+".......6>em/|^(g...................6eq9orj&g............",
+".......g6em{!/#g...................gz#974kig............",
+".......ggem|:/vgg..................g6#j}ho<6g...........",
+".......gz6mn:{v6g..................g>>9=h7<6g...........",
+".......gzem|:/vgg..................gz#j}ho<66...........",
+".......6g>mn:{mzgg.................6ze9}$7t>gg..........",
+".......66>m|:/m66g.................6>ej}h79>6g..........",
+".......66e^{b{v>gg.................6>qj=h7<e6g..........",
+".......66em|:{m>6g.................6>qj}h7te>g..........",
+".......g6em|:nm>zg.................6>#j}h=tez6..........",
+".......66em|:{m>>6g................6>qj}h=jee6g.........",
+".......66>^nb{1>>6g................6>ed}h7*qe>g.........",
+".......g6>m|:{me>6g................g>ej}h7jqe>6.........",
+".......g6>^/:n1e>z6g...............g>ej7h=j[qz6g........",
+".......gg6mnp{^q(>gg...............g6>j=472&[(6g........",
+"........6zvl|{l^vezg................6>{]}7]2+[>6........",
+"........6g#m^//{l#e6g...............6z&9]o77]iq6g.......",
+".........geqv/|:{1>6g................6#&+]}h7jq>6.......",
+".........g6e(m/|/1#e6................g>q^joroj&qz.......",
+"..........g6e#m^1mvq>.................6z#&9dj9<&e.......",
+"...........gg>e(#mmv>..................g6eq'itj<q.......",
+"............gg6>(#m#e...................gz>e'i9i#.......",
+"..............gg6e(eg.....................g6z#'q6.......",
+".................gg..........................g6.........",
+"........................................................",
+"........................................................",
+"........................................................",
+"............g.ggg.g.....................g.ggg.g.........",
+"........ggg6g6gg66g6ggg.............gg666z666z666gg.....",
+".......gggz6z>>>>z>6z6gg...........gg6>>>eeee>e>>z6g....",
+"......g>eqqq#q#(#q##qqez6g........ge[&&&-&-&----&&[e6g..",
+".....ggqm^^^1^&^&&^&1'v(6g.......g6&t2d222222222*t+[>g..",
+"....g66v^{{{{{{{{{{{//1#>6g.....gz>+]7,7k,ko,7okk52-qzg.",
+"....g6>m{nn/{/{/{/{{<{{'ezg.....6>et7}77ook,okkkk=5;q>6.",
+"....66>^|!p{aiiaiii{||n1(>6g....6zqd=4=k@@@0@00,=~=j&e6g",
+"...gz>(l|bt{aaaaaiii9fp^#e6g...g>e[]r_y,@@@@@00,y4r@-q>g",
+"...gz>q/!:p{ai&iii+npdpaqe6g...6>q&]4hrw0@@0@00w~4~@-q>6",
+"..g6>(#/p:!9n<<<<<<9f:fi#ez6..g6e[a,~$~=,w,wwwwy~s4@-[>z",
+"..g6>([{|f!p!|9p!f!j::p+[>>g..g6q&+5r$~~~yyy~~~~ss~0+qe6",
+"..g6(v'{!:dfjf!jfjf:fd!/[(>6..gz[+;k~4s~~~~~~~~s$$4,+[ez",
+"..g>v^{np!p!!!f!fd:::!pl&q>6..6e+]7}~~~~~~~~~s$444r5*-(z",
+"..gzmnp!!!jppj9ffd:d!f9i1[(6..gej74~4~~}~~~~~sss~~y@*+[z",
+"..6>^|f!p!9!!p!jf:bd!9{l1v(g..zed}44~~y~~y~~~$ss~yk5j+[z",
+"..6zv^{n9p9|99p9!dxdf<{&[(e6..6>+dk==~yy=yyy~sus~w,2+&#6",
+"..gge#'ltp9||<|9fbcb!i&'q>6g..g6[i;5w~=yywyy48u_~52;&q6g",
+"...6zeq&{p|<t<t<f:cb9/'#e>gg...zzq&2k~ywwwww~$)sy0;-qe6g",
+"...gz>(l|f9<n{/+t!ffn/1#ezg....z>q[@=syww,,,wr$4=52-q>g.",
+"...gg>(a|bp<i+ii{<9n{/^#>6g....g6e[@~4~w0000,wy=k]2-q>g.",
+"...gz>>l|b|/-iaaii{///lv>g.....gzeq]rh=,00@@0@,oko]+eg..",
+"....66e^|!9{iaaa&^&111v(6g......z>(2=$y,0@@@@222jj+[>g..",
+"....g6>1{!n{{/il1'v##qe>g.......g>ej74=k,0@@2;+--&[eg...",
+".....66vl{n{{{la^[e(>66g.........zz<]==kkk5@2+[[#>6g....",
+".....g6#^l{{|n{l1#e>z6g..........g>-jo7=r=ko*-qez>6.....",
+".....g6eq'/|fn{l1#>66g...........g6#&;]}4}o]j-ezzg......",
+"......g6eelp%fnl'(>gg.............g>q']ru$=]t&e6g.......",
+"......gg6em/n{^'#e66..............gg>q9o}7dt-qz6........",
+".......ggz(vmmq(e6g................g6>v{jti[q>g.........",
+".........g6z>>z6gg...................6z>eezz6g..........",
+"........................................................",
+"........................................................",
+"...............g.g.........................g.g..........",
+".............gg>ze>>g....................g6eeqqe6.......",
+"...........gg>>(qqvq>g.................g6eq[&&+&eg......",
+".........gg6ze(qvmmveg...............g66>q[&<9j<[6......",
+"......gggz6>>q'^^^lm(6g...........gg6>>eq&;22d]t'6g.....",
+"....gg6gz>>>('l/{//1#6g.........gg66>eeq[;]oko]j->6.....",
+"...gg6z>>e(qq1{pn{l1#>66.......gg>>eqq[&&*kr=7oj-ez6....",
+"..g6e#'m'1''1l{p|nn/mezg......6>[it;;*;**57rr==otq>6....",
+".6z(m/n{{n{//{<pp!fn1(z6g....6z'9o====kookwy~44=2[>6g...",
+".6e#/!%:::!p9|nnp:bpl(>6g....>#io4uh$h4~y==wrh_4@&e>g...",
+".6>q^|f!::!f!p|<p!bpl#(6g....ze&d}44hh4~~~=wrrh}]-[>6...",
+".66>v^/n|!fpp9<{|np|l1#e6....zzq<do=}444~y=,w}~}ojiq6...",
+"..g6eqvln|!!f9{-{<n{/l1q6g....gzq&<]=r~~4yk0kk=ko]j&zg..",
+"..g6zeqm/np!:|{ail////m#6g....gzeq&jo=}4syw@55koo]ji>g..",
+"...gg>evm^nj:p/1&11^l/lv>6g....g6eq+j@=~h}5***j2]o]+#zg.",
+"...ggg>eq[/pb|i[[[#v^/lm(>g....gg6e[&+]~hr0+++-;do]t'eg.",
+"....ggz>>ql|:nl[#((#m/lv(>g.....g6>eq&]rh}@+-&[ij]]{'e6.",
+".....g6z>>m{nnl1'#((#vq(>g.......g6zeqto}=]2;-[[/<&'e6..",
+"......g6z>v^//{/^[>ee>>6g.........gz>e+2oookd+qqq#e>g...",
+".......gg6e#^^/{lve>6zgg...........g6z'+2]ok]+qe>z6g....",
+"........g6ee#ml/lv#(>6g.............g6q[ij]o]t-'ezg.....",
+".........g6>emm/lmm#egg..............g6e({jo]jti#6g.....",
+"..........gggqm/l^m#e6g...............gz6&jo]djiq6g.....",
+"...........gg>#vvmmv(g.................gge&<<99{'z......",
+"............gg>eq#m#(>g.................g6eq&i9ive6.....",
+"...............ge(v#(66...................ggq'<i'>6.....",
+"................ge(e>6......................6q[qez......",
+".................6ggg........................z66g.......",
+"........................................................",
+"........................................................",
+"...........gggggg......................gggggg...........",
+"........ggggggg6gg..................g6g6666>6g..........",
+".......6eqee>(vm#e6g...............z#&qqe[+9i[zg........",
+"......ge#m#qev^{^q>6g.............6#iti&q+d72&e>g.......",
+".....g6qm^mqq1{|/me66g...........g6&t];-&*7}otqz>g......",
+"....g66vl{l'qln:{1ee>gg.........66><]7];-@=h=*[qe6g.....",
+"...g66>mnp{^[lnb|a#>>6gg.......gz>(j=472+5}hr@-qez6g....",
+"...g6>e^|:ni1{!b|iqqe>6g.......gze#d}h=5*k4_r@-&qezg....",
+".g6z>ee/|:ni1{!xp+[q(>z6g....g>>eq[5rh=@*kru~0+-[qe6g...",
+".g>e>eq/!:p/at!xp{'[qeegg....6eqq[&]rhr,@w~uy,;+&qq6g...",
+"g6e((eq/p:9/a<fx!+'[(eezgg..g>[[[[&5~hy,@wsu~,*+&[qe6g..",
+"6(v111mnfxft/!dx:<i&&[q(zg..z[<jj*j=4u~,,~sus,02*+&[>g..",
+"6#l{/llpbxf!tf%}%p/ia1&(>6g.6i]7o55r_us~w~_)_~,0@2*&qzg.",
+">mn||n|!bcbfpdxcx:9t{{^vezg.ej=r}==4_)h4rsu)u4www5]+#>g.",
+"6v^////!:x:f<!%xd!{{i^1q>6g.6<dooo]~hus~w~_us~k,52j&q>g.",
+"ge#vmmmndbp<+9:x:9i^&'#ez6..gqi<ttj=$_4w,y4usy@@2;-[z6..",
+".gg>>(q/pb9{a<pdp<a1#qe>gg...g6eq[&o4hy,@w~s~k@*-&qezg..",
+".ggg>>(lpbn-1i9f9{a'[(>66g...gg6e#&]rh=@*0y~y,@*+[q>6g..",
+"..g6ze>l|:ni&a{|n{/^[(e6g.....g6zq(]rhy0*0kr==]@+[q>6...",
+"...g66e^|:{^[^i{{<ni'e>z6......gzzqd}h7@+25,kk=@;[ezz...",
+"....g6>^{:{^['&l/{nl'e>6g.......g>ed=$72+;2@,7=o;[e>g...",
+"....g66mn:{m##''^{|{1qezg.......gzzj=h7j--;t@7r7*&qz6...",
+".....gzmn!/mqqqqm{|n^(e>6g.......g>j=4oj&&&&j,}=2&qe6g..",
+".....g6m{!/meee(vl|{^#e>gg.......gz974ot[[[[{]r7d-[e6g..",
+"......gvl|^#>>>>qmmm1m#(6g........g<]}d-eeee&tjjj;i[>6..",
+".......#^{mq>6>6>(q#m^mq>6........gid79&eze>e[&itd9&e6..",
+".......(mlv(6g6g66ze#^mqegg........v9]<vz666zz>#idj&#6g.",
+".......>(#(66gggggg>eqqe6g.........e'i[>6ggggg6e#&&#6g..",
+"........g66g....g.gg6>6g............666g....g.gg>e>6....",
+"........................................................",
+"........................................................",
+"...........ggg.........................ggg..............",
+"........gg6>>>6gg...................gg>eqezgg...........",
+".......gg6ev^#(ggg.................g66[<di[66g..........",
+".....gg66>m/nlv>6g6g.............g6z>eto=]+ez66g........",
+"....g6z>>em{!/meez6gg...........g6>eeqj=rktq#>>6g.......",
+"...g66>>eql|:{&qee>6gg.........6>zeq[&]}h=2&[qez6g......",
+"..66>eeqqq/pb|^(qeeezgg.......66eq[&&a5rh}@&&[qq>6g.....",
+".g6>e###['{p%p/'[qq(ez6g.....6ze[---+;k4u}5;+--[qe6g....",
+"gz>q1/{{i^|:c!{aa/i1mqe6....g>e&*o,,0@=hu$,@@002t&[z....",
+"g>(v/f:p|{pb}bp{{|p{lm#>g...ge&+k4hr=wrh)hr,7=r=]tiqg...",
+"6e(1|b}bpt:%cbf<pp:!{^vqg...>q&j=u)h~w$_)_~wr4h47d<[6...",
+"ge([n:%!<{9%cdp/<|!|{^m(g...6q&+=hu4w,~_)sr5krrr7dt'6...",
+"6e(#n:%!{i9fxf<a/n|n/^me6...6q[+7hu~k@=$u4w@,=r=odt[6...",
+"g>(#{!%9i&|fxf{'a{|n/^m(g...6e[-k4_y02w4u~k*@,}=odt'6...",
+"6>eq{fxp{a9bcf<i{n!n/^m(6...6e[ak$uyw0=su$,5,=4=kdt'6...",
+"6>eq{f%dn{!bcbp{npf|{^v(g...zeq-ohu$=w~_)h~,=r4r7d<'6...",
+"g>>({:x:ptfx}bf{pf:!{^v(6...6eq&khu$r=$u)_4=r$hr=d+v6...",
+"gz>e^n!|{/p:cf|/{{!n/mveg...g>e[@}$}k5~hu$}57=4=oj+#g...",
+"g6>em/nl^&nfxf{1l///mv(>g...g6e(t5752*7$u4k*@]7oj<&eg...",
+".g6>(v1[[#l!bn^[v1^^vv(z.....6ze&<j++-]4_}@+<jdjtive....",
+".gg6eqv#((l|:|^qqvv#q(>z.....g6zq&+-&&]}h}2&-+ti&'ez....",
+"..gg>>e(((lpb{^qeq((e6g.......ggeq[[[']r_72&[&v'q>z.....",
+"....g66z>e^nb{mee>6gg...........g6z>e(d}_7jq(e>66.......",
+".....gg66>m{!{vz6z6g.............g6>>e9747<ez>6g........",
+".......666v/|l#>6gg................z6z<]}b-ez6g.........",
+"........gg#m{m#g6g..................ggij7j&66g..........",
+"..........(v^veg.g...................g'<d<#g.g..........",
+"..........6eqeg.......................z#&qz.............",
+"...........ggg.........................g6g..............",
+"........................................................",
+"........................................................",
+"...............gggggg......................gggggg.......",
+".............g6>>>666gg..................gzqqez>z6g.....",
+"............g>(#qe(e>66g................ge'i&[[#ez>g....",
+"............ge#mm#q((eeg................6#ijt-&&[#q6....",
+"...........6g#1/l1[##(e6g..............z6&jk]j+--&qzg...",
+"..........g6>v/pn/1'[#q>g.............g>e+or752;+-&eg...",
+"..........66>mnf|n^^1'q>g.............6zej7hrk@@jt&#6...",
+".........g6>>^n:!|{/1'qe6............g6eq2=h4}k5j;&q6...",
+".........gg>em{p||n{^#e>g............gze[j,rrr=k2-[e6...",
+".........gze('ln9!fn^#e66............zzq[;5==r4=@-q>6...",
+"........g6>(#&l<9pf|&#ez6g..........gzq[-25wy~$=2-qe6g..",
+"........gge#m/n!!ffn^[e>gg..........g6q-t5=~~~4=@+[e6g..",
+"........g6e'^{pdfp!<l[qegg..........g6[;2krs44~=]+&q6g..",
+"........66q'l{!%ffp{i'qezg..........6>&;d=4_$~rw@;&[>g..",
+".......g66e[1{pbf!9{l'[e6g.........g6z[+*,rh4~=w5;+[>6..",
+".......g6>eq[{!bdp<<i1[q>6.........g>eq-+k~_s~wk5*+&e6..",
+"......g66z(([a9::!n{i1'qz6g.......gz>e[&+@yh4~=,52;&e6g.",
+".....6g6>e(q#/|bfj!n{l1#egg......6zzeq[&-5yhs~~=,]*-q6g.",
+"...gg6z>>e(q[-<f:!f!<{^#e6g....gg6>eqq&-+@w$44~~=k@-#zg.",
+"...gg6>z(eqq[it!ffd!9{iv>6g....gz>ee[[&-+0w~$$sryk5+qzg.",
+".g6>(q#[''&aln|!f!!pn/1#z6g..g>e[&-+;;2@@=y4~~$~=]j-e>g.",
+".g>evml^l/{{p|9|p!!|l^[qz6g..6e[+j@]@@k=r~y}~~4=52+&z6g.",
+".z(q1/{{{n|!:f!9p||n^[(e6g...z[&jo777=}$h44=rrr=@+&q>6..",
+".6>(v^////{nn{/li/{i^1#e66...ze'<doooo7777o555o52j-[6z..",
+".g6ev1lllll^^m&m'1'1^mm(zg...6>q+j]]]]@2dj*t;j;j2jt&zg..",
+".g66qmm1mmv(e(e(eee(1l1#g....g6>&tjjjj+&[[[[q[[&j]j&z...",
+"..gge#vvv[q(e>>>ez>e#vveg.....g6'&+<<+&[qe(eqee[i<<qg...",
+"...g6>ee((>>6z6g6z6zee>6.......g>e[q[[qe>>zz>>6>q[e>....",
+".....ggg6666g6g6gggg.g...........gg66666zzg6gggg.g......",
+"........................................................",
+"........................................................",
+"...........gggg........................gggg.............",
+".........g6>e>>6gg...................gzq[qez6g..........",
+".......g6ge#vvq(>6g................g66#i<+&[ezg.........",
+"......ggz>#mlmvq(>gg..............g6>ei9]j+&[e6g........",
+"....gg6z>>m/n/1qe>z6g...........g6>>eq;o=oja[e>zg.......",
+"...g6>>>qe^|:n1#eee6g6.........g6eeq[[2}h=2-[[q>66......",
+"..gg6eeeq#/px|/qq(eezgg.......g6>q[[&-]4ur5-&[[q>6g.....",
+".g6>#1l^11nbc:na&'[#qe>6.....gzeij]2*2}h)h7@**+-&[qz....",
+".geq^n!n{{f%rbp{{/l^1mqeg....6q&d=4}kk$u)h4,k5]d*<&#g...",
+".>evn:xb!|bc4xbj||{{l^meg....e[+=huh4r_))uh~r==7]dt[6...",
+"g6eqnbx:p|f%cx:ppnn/lmveg...g>#i=_uhr=4u)uh~r==o]j<#g...",
+".6eq/f%!{in!b!!p|{ll1vq>g....zq&74u4k0=~s$~~yw5]j+&qg...",
+".6>(/!%n/'-<|9nt{{^mv(>6.....ze']4u=o*0ky==wko2j+[q6....",
+"g66(/!:ni1a/{t|9{i1'q(>6....g>>'o4h=@*@5kwy=k52;&[ez....",
+".66el!:n^&&ai{9!{^'#e>66.....6z[]4$=@*2@0ky~7@;-[e>z....",
+".66e^|!ni'&'&/|:|a#q>>6g.....6>qd}$=0*2**,}h=@-&qe6g....",
+".66e^|!na1&'&/n:na#(ez6g.....6>qd}4k@*2**0=h=@-[q>>g....",
+".g6>m/|/{/aa&{n!nl[q>>gg.....g6q9o}7o0@@2k=~=]+&qe6g....",
+".g66v^/{{{{/l{nn{1'#(6zg.....g6><do7kk,05,=},2;-[z>g....",
+"..g6q^l/nn{{i{{n/^'v(>gg......gz&j]o=}7k5kk7]];+[e66....",
+"..g6eqv/|fnn/i^1^/l^mqezg.....gz'i{o}4}7]5@d2]]dt&#>g...",
+"...g6eqlpb!n/^m[mlnl^m#>g......g>q&orh4=o2t+j]=o2tiqg...",
+"....66>l|%pn/m#ev^n{lm#eg.......6>e]ru4=oj-[+]=7]9iqg...",
+"....ggzv^{lmm#(>qv^mmvq>g.......g6>i]7bjt-'e&<djt+&q6...",
+".....ggz###((e>6ze(qqq(>g........g6e&iiv'qezeq[^&&'eg...",
+".......gg6g6gg6z6gg6eeezg..........6g>6666zz6z66#v#>g...",
+".........gggg6gggggg6>6g.............gggg6gggggg>ezg....",
+"....................ggg.........................ggg.....",
+"........................................................",
+"........................................................",
+"........................................................",
+"........................................................",
+"......gg6g6g6g6g6ggg..............g66666666666gg........",
+"....gg66z6>>z>z6z666gg..........g666>>ee>e>>>z>z6g......",
+"...g6z>>>e>>>>>e>e>>z6g........g6>qeqqeqeqqqeqee>zg.....",
+"..gg(v1'#(#e(ee>q#'v#e>6......g6[+j;-&&[[q[q&-;+-[qz....",
+"..g>vl{/&'[qqeqq[1/^m#q>g.....ge<]752;+&&[&&+jo]ti&eg...",
+".gg>^np{^&'[q#(('/n{l1#>6....gze2=47@*;+&-&&*5=7]j-q6...",
+".g6>^|!ni''[(###&lnnlmv(g....g6qd}4=@*;+&---*5==]j<[6...",
+".gz>^|!nl'[[##qq&lnn/^m(6g...gz#d}4=@*++-a&-*@==]2t'zg..",
+".g6e^|!{^&[[##q#'/{n/^mqzg...g>qd}4,@*++----*o=7,dt&>g..",
+".g6e^|!na[[q####1/n{/^1q6g...gz#d}$7@;+--a--*5==k@j&>g..",
+".g6(^|fn^&[#qq##'i|n{lmqzg...g>[]}4=@*+a&&--*5=7o@j&z6..",
+".66e^|!<a[[qq#q#'/n{/lmqzg...6zqd}4k@;+-&a&-*,==o]ja>g..",
+".6ze^|!n^&[[qqq#&i|n{l1q6g...z>[d}4k@*++&-&-*5y=5]j&zg..",
+".g6e^|f{a[[qqqqq1in{/^1q>g...g>q]}$k2;+-'&-a*5==o@j&e6..",
+".g6e^|!{^[[#q(qq&/|n{l1q66...g>qd}4k@;+-&&&a*,y=k]j&>6..",
+".g6e^|fni&&[[['[a{|n{^m#6g...g>q]}4=@2*;++;+@,}=k]*&>g..",
+".g6e^|!|{l-a&&&^/nf|{l1qzg...g6qd}$},0@@*222o=4r7@j&>6..",
+".g6>^|f||{{/{//{n!:!nlmqzg...g>ed}$r==k,o5ok=4h47]t&>g..",
+"..g>mn!pn{//lllln|!p{lmq6g....6ej=4r=ko555]5=r4rk]t&zg..",
+"..g>mn|{l^11m'1&l{pn/1m(gg....6ej=r752j*tt**@7r=o2t'6g..",
+"..gzm/|/1[#(qeq('^n//mm(6.....g>9or]j+-&&[&&;]=7ojtvz...",
+"...6vl{^v(((e>ee#mll1m#eg......6<]7d+&[[qqq[-j]]jjiqg...",
+"...ge#v#ee>>z>>e(#vv#ve>g......gqi<i[qeeeeeq[-{+ii[eg...",
+"....g>>>666zz66zz>ee>>>.........6eqezz>zz>zz>q(#qeeg....",
+"......ggggggggg6g6666g6...........gggggggggz66>6>z6.....",
+"........g.g......ggg................g.g......ggg........",
+"........................................................",
+"........................................................",
+"........................................................",
+".......gggggggggg..................gggg6ggggg...........",
+".....ggg666z66ggg6ggg............gg6>>>>>z66666gg.......",
+"....g6>>>>>ee>e>>z6gg6g.........6>eeeeeq#eqee>z666g.....",
+"...gze(ee(ee((e(>>e>z6zg.......g>q[[[[[[&[[[qq#e>>z6....",
+"...6>#[[[[[[[#[##qqq(e>66g.....6q-+++++++-+---&&[[ez6g..",
+"...6#l{{{{/iaa-iiii^&^mq>6g....>-]7k,,0@@@00@@5@22t&#zg.",
+"..g>^nf!ff|n{nn9||||n{lmq>6...ged=h4$$~w,k=yy}}}=7o9&#6.",
+"..g>^|b:bbf!n9!f!!!!||{1qeg...ged}hhh_4~=y~$~444r}7j&q6.",
+"..g6v^{n!!p!9p!:pn{//l^ve>6...gz<d7}r4r~y4~4r=k5o]di#e6.",
+"...geqvl{99pp!ff9{1mmvvq6g.....g#1<]7=y~~r~s=,2*jt+&>g..",
+"...gg>evl{|<|j::|i'###q>gg.....g6e(;5k==y~4_y@;---&e6g..",
+"....66>#'^i{{9!bpi[#qee6g.......z>e&t255ky$hr0+-&[#zg...",
+"....gg6e([''&npb|i[(e>>gg.......gz>q&+;*2,~_r5+&[qezg...",
+".....g66>e([[{9%pl((ezzg.........g6>eq&++krhr@&[qz>g....",
+"......g66eeq#^p:naqee66g..........g6>q[&-@rh=@&[q>6g....",
+".......g66>eq1n:n^(e>zg............g6>e[&2=hk2&qqzz.....",
+"........g6>>(1{p{&ee>6g.............gzee[j747*[qe6g.....",
+".........g6z>[/|{1#eezg..............g>zq;]}7*-[q>6.....",
+"..........gz>vl{l^[q>66...............g>e+]7]2+&qz6.....",
+"..........g66qm/lmm#(6g...............g6>^j]]jj-[66.....",
+"...........ggevm1^^mqe6g...............g6#+jj2dt&#zg....",
+"............6>(#v^l^vqe6................6e[i<2od<&#>....",
+".............ggz#^{lm#(6.................g6>id7]jivz....",
+".............g6g(ml^mq(z.................g66vt]dt&'>....",
+"..............g6>(#v((e6..................g6e'ii&v#z....",
+"................gg6>>>>6....................g6>eeeez....",
+"..................gg66gg......................gg>z6g....",
+"....................g6g.........................gzg.....",
+"........................................................",
+"........................................................",
+"........................................................",
+".........gg6g66gzg66ggg..............6g66z66z6z66gg.....",
+".......g66>#v((>(q##(>6g...........g6z#&+&[e[&i-&qzg....",
+"......gg>evm/1#>#^l^1v(>g.........g6e#+joj-qi2odji&eg...",
+"......g6eq^n!/1qm{pnl1#>g.........g>q&d=4oj&*or}ojiq6...",
+".....66eeql|f{1#m{!|{^'(zg.......6>q[&]}4=*-j74}od;[>g..",
+"....gz>(q#lnbn^#^{|n{^mq6g......6>#[&i]}_=@-2kr=kdt&z6..",
+"....ze(qqv/|%ni'1{|n{lm#>6g.....>qv&-<oru}5;*k}=,]j-ezg.",
+"....6(#vvm{f%!/'/{p|n{^ve6g.....>[i-+t74u45*5k~==k@+[zg.",
+"....eqvm^^|:xf|i{p!!|{{m#e6.....q&{j2]}hu4y5kr$$y=oj-#>.",
+"....e#ml/np%x:!<|fb:fp|lvq>g....#ij]]=4u)h~ky4sh44y]{&eg",
+"....e#mll{pbcbp{9!::!!nl'q>....gqi9]ox4h)h4ky4$h44=];&e.",
+"....6eq#m^n:xf|l<9!fpn/mqe6.....>q&itd=hu4y5ky4$}=oj&q>.",
+"....gg>e(#/!%p/&/n!|n/lve66.....g6qq&io4ur,*,k~=yo]+'>6.",
+".....6g>eel|%pi&a{9|{l^#>6g......66eq[]}u}5*@ky=k52-e>g.",
+".....g66e(lp:|l[a{pn{/^#>6g......gz>q[]rhr5;@kryk5d-e6g.",
+"......g6e>l|%|/[^{9|{im#>gg.......gzqq]}u}5+2k=rk5jie6g.",
+"......g6zel|bni[a/|n{l1q>6.......ggze(]}h}@;@,y=k@j&ez..",
+"......gg>>^|%|i[&{|{{/m#6g........gzeqdrur0+2,}=k5j-z6..",
+"......g66e^|b|l'&{9n/l1qz6........g6>qd}hr@;2,==o]j&>6..",
+".......66>^nb|l[&{n|{^mq6g.........6zed}hr@+*k}=,@j&>g..",
+".......g6>^|%|{&lnpn{l1qzg.........g>edrur,25=~}7]j&>g..",
+".......gg>^!%!nl{pf|{lme6g.........g6e24u475kr$r7]t[>g..",
+".......g66^px:|{n!:!{^m(6..........gz>d4uhr7=rh47dt'6...",
+"........ggv/|{l^//|{lm#eg...........g6<o}7]2o7=7]j-q6...",
+"........gg(m^mvqm^l^mvq>g...........ggv9dj{-td]29+&eg...",
+".........gg>eeez(qvvq(>6.............g6eq#(e[&{+^'q6....",
+"..........gg6666eeqee>>g..............g6>z>>q[&[qeeg....",
+"...........g6gggg6>>6gg................gzgg66>eezzg.....",
+".................g.g.........................g.g........",
+"........................................................",
+"........................................................",
+"...g6>>>e>>6gzg6g6ggg..........gzeqqqeez6z6666ggg.......",
+"..6>qm1m##q(>>eee>6gggg.......ze&;j;+-&[eq#[qq>66gg.....",
+".6>em/{/l1[q(qq#q(eez6g6g....ze[jo7]]*+&[&&-&[q#ez66g...",
+".6eql|!n{l1[(#vm'v((e>zggg...z#^]}4}752+&-+;;+&[qe>66g..",
+".g>(m/|{{/^i&^^il//^^mv#(>6..6e'jor7k5@@2@@5]5o]2;<-'q6.",
+".g6evl////{{{<{{{|fpn{/1m#>g.g>q{]o]o5k,7k7k=r$r=7]jti#g",
+".g6>#m^l/i{!!!|pfbxxf!|{l1(6.g>e-;d@55k~44}}4huuh4r7]j'6",
+"..z6qv'^i{||!|{{|!::!nn/mveg..z>&+*@5k==rrkk}$hh4}7oj{qg",
+".g66e#'&/{tn!n/&{|!!n{lmvqzg.gzz#-;25wwrrk52k=4r=7bj+^eg",
+"..gz>e[1+nn|9/a[1{nn{lmve>6g..6>q[-2,=y=yk@+2k==7]ji[e>g",
+"..6zeq[^{|9n|/1[1^////^v>>g...6zq&+@7=y==5*+*@ko552+qez.",
+"..66(v1/n!||{i1q[m^1/llvez6g..z>&+j0=~yyk5*-+t22o]]+q>6g",
+"..6zq'^{|!pn{l&q##[ml{lme6g...6>&;2kr4~==5*a-a+j@7ot[>6.",
+"..66#^/{9|9|{a'q((qml{/mez6...zzi@okyry=k@;&&&&;]=]tqzz.",
+"..g>1{pn{/{{{^'qq((m/|{m(6g...gej7r=,5kkk@;&&&&;or=j[66.",
+"..6>lpf|i&^l{^'qq((m/!|1e66...zq]rh}5*@]72;&&[[t7rrj[z6.",
+"..g>^p:{1'&/{a[(((qm{!|^e6g...gedrh72;2o72+&[&&;74rd[>g.",
+"..gg#^/mv#^n|/'q(qqm/fp1(zg...g6idoj<-2k}k;&[&&t74~j'>g.",
+"...geqv#qq^nf{1(qeqm{f|^egg....6q&i-&&d=47*&&[&97$rd(zg.",
+"....gze>>e^|!n&####^/!|^e6g.....6eqq([2}4=*--a-2x4}d#6g.",
+"....ggzz>>m/|n/^//{{||/v>g......g6z>eq9or=o@]o77}}o<q6..",
+"......g6z>vln||p|!!p|/l#>6........gz>e<]=rrrr444}7]iez..",
+".......gg6qm/n|!::%!|lmq6g.........g66&jo=r4h$u4}]9&zg..",
+"........ggeqvm//{/{{mvq>g...........g6#^<jooo777j{&eg...",
+"..........ze(qvmmmmm#(e6g.............z#[&<99jj<i'#>g...",
+"...........gzze((((e>gg................6>e#''vvqe6g.....",
+"............g66>>>>z6g..................g6>eeeee6gg.....",
+".............gg6ggggg....................g6666zgg.......",
+"................g...........................g...........",
+"........................................................",
+"........................................................",
+".........gggg........................gggg...............",
+".......6eqqee>ggggg666gg...........z[&&[qe6ggg66zz6g....",
+"......gevmvv#qe6666>eqeg..........g#<jt<i&#z>z>e#'#6....",
+"......gq1l^mm#(zz>>eeq(>g.........g&j]djj-[>>eq[[&'(g...",
+"......g(^llllm#e(q#m^l1#>g........6^j]b]]t-q[&itd]jieg..",
+"......6qml/{{^'e#v1^/|{meg........6&9]oc7];[-+jdo}79q6..",
+".....ggqml{{|/1q[m^/|!|^ezg......g6^j]k=}5*&+;2kr$}d[>g.",
+".....gg(#m/|!{1#ml{{nnlm(6g......gz[i9o}4k2-t]7x==ot'zg.",
+"......6e(v/|:n^[1/nn//1#(6g.......6q&+]rh=@+20}=ooji'>g.",
+".....ggze(/|%pi'^{!|lmvqe>g......gzz#&5r_r@;@74}]j<&qe6.",
+".....g6zeql|:p<i{{n{^vqe>g.......g6eq&@}h~w0kk}7d+&[e6..",
+".....g6>>elnff|||{{lm#(>6g.......gzeq[@=4$r==w,]t-[ezg..",
+".....g6>eq&{p!f:|nl^qe>ggg.......g6q[&2k~44sr752-qezgg..",
+".....gz>eqln!f:%!nlm#>>6g........6ze[&@7~$s_$k@t-qezg...",
+"....g66e(q&{|dbx:{1'#e6zg.......gz>q[&2kr4hu4k2;-qz>g...",
+"...ggz>>q#a{p:xc:t1[ee>gg......gg>eq&-@,~hu)h=*+[q(zg...",
+"...g6eq['1/{9!:%!nlm[>>6g......g>[&+;25ky4s_4=5*+qe6g...",
+"..gzqvm/n|p|p9|9ppp{1e>6g.....g>&+j57}rrr=ry~rr7j[e>6...",
+"..g>#m/|:%!!nn/ln!:!l#>z6g....zeij]rhu$~==o@=4h4]-qz6g..",
+"..6evl{|!:!|{/1m/n:|/#(>6g....6q<]7r4h4==52j]yh}5i[(zg..",
+"..g>vl{{nnllm'[#m^ll^mvq>>g...6e<]77==]]j;+-9d]]dj<&#eg.",
+"..g>vl{/l^m#(qeeqqvmm^mvqe6...ge{]7]]dt-[&[[&&<t9dj+&qz.",
+"...6#^/mm#qe>>>>>zeqvmmvqe6....zid7jti&[eeeeeeq&<jp+&#>.",
+"...ge#m#((e66z6g666>(#qezzg....gqi<i'[#>z>>66z>e'&&#e>g.",
+"....g6z>66gggggggg6g66666g......6>eez66ggggggg6gz>>>6g..",
+"........gggg.........g..............gggg.........g......",
+"........................................................",
+"........................................................",
+"........................................................",
+"........................................................",
+"........................................................",
+"...g66>6ggg....................gzzez6gg.................",
+"..gg>(ee>6g...................g6([[qe66.................",
+".g>eq#vqeez6g................6eq&i+-[qe6g...............",
+"6e#'^lll1'q>gg..............6#it2]o]j;&q6g..............",
+"g#^/{n|{/lm(6gg.............6ido7=}kkdt[>6g.............",
+"6v1/n|!nn/1q>6gg............6id]=r4}=7*&e6gg............",
+"ge#mln|nnn^[>>6ggggg6>>g6...g#i9]=}===d+qez6ggggzee66...",
+"g6eq^/|||nl[(>zzggg6>e>>zg..gz#&do}r}}]+[e>>666>eqqe>6..",
+".g6em//||p/'e>>zzzz>e#qe>6g..6>#to7=r~o;[qe>>>zq'-&[e6g.",
+".66z#^/|f:n^q(e>e(qmm/m#>g...66ei2]}4h=2&[qqq[&+j]jie6..",
+".g66#vl|fx|&qee>(vm^/n/veg...g6>-t@}hur2&[qq[+tdo=]<qg..",
+"..gze#m|bc!^#qe((m^ln|{m>g....6z[-jrhuy@-&[[&tdo=r=teg..",
+"..g6eqv/p%pi'[q([m///l^(6g....g6#&+k4ur5;+&[+jooo]d&>6..",
+"....>>q/|!n/&'#em^{/^m#e6g.....geq&]}$}52;-[;d7od9i#6g..",
+"...g66>1{!|{l&[(mln/mqe>g......g6zq*7ryk02+&;]=]j&qeg...",
+"....gzev^{n|pi'q#m^m#e>gg.......z>q<d77}r@;&itd9i'ezg...",
+"....ggzq'^{p:n&q##v#e>6g........g6z&;2k4$y2&--<-qe6z....",
+".....66>e#{!cplq((>e666g.........z>q[ik4)r@&&[qq>>6g....",
+"......gzeq^n!nl1[qe>>g6g..........g>[&d=4=5*+&qeez6g....",
+"......gg6ev^//{{l#(>>6gg..........g6>q+d]o7,@+[ee66g....",
+".......g66>qvl{p/m>e6zgg...........g>>q&+]7ro;qq>>6g....",
+"........6z>eqml{/^m#e>6g............6ze[&j]7o2;-[ezg....",
+".........g6>>#m^lll^#>66.............g>eqit]]]]2-q>z....",
+"..........g66eq#^/|/1q>z..............g6zq&a27}oj&e>....",
+"...........gg>e(v^/lmq(6g..............g6e#&{dkb;&[zg...",
+"............gg6e(#mvmv#eg...............g6z('it<t<i#g...",
+"..............ggz>eq#mv>g.................g6ze#&it+#6...",
+"...............gggg>(v#eg..................gg66#[<iqg...",
+"................g.gg>e>g....................g.g6eqe6....",
+".....................gg..........................gg.....",
+"........................................................"};
index 6e401aa673243b545f90a8fbd8fe719c8b216b81..a8af2e51d13b43196718cdc6efc1f0b1f87b7a9a 100644 (file)
@@ -102,9 +102,6 @@ If one of these are hit penrose will reinitialize.
  * vertex rules only allow at most seven tiles to meet at a vertex.
  */
 
-#define CELEBRATE 31415927     /* This causes a pause, an error occurred. */
-#define COMPLETION 3141593     /* This causes a pause, an error occurred. */
-
 #define MAX_TILES_PER_VERTEX 7
 #define N_VERTEX_RULES 8
 #define ALLOC_NODE( type) ((type *)malloc( sizeof( type)))
@@ -112,21 +109,28 @@ If one of these are hit penrose will reinitialize.
 
 static Bool ammann;
 
+/* How long in seconds should we wait before starting a new tiling? */
+static long redo_delay = 3;
+static long redo_delay_usec;
+
 static XrmOptionDescRec opts[] =
 {
        {"-ammann", ".penrose.ammann", XrmoptionNoArg, (caddr_t) "on"},
-       {"+ammann", ".penrose.ammann", XrmoptionNoArg, (caddr_t) "off"}
+       {"+ammann", ".penrose.ammann", XrmoptionNoArg, (caddr_t) "off"},
+       {"-redoDelay", ".penrose.redoDelay", XrmoptionSepArg, NULL}
 };
 static argtype vars[] =
 {
-       {(caddr_t *) & ammann, "ammann", "Ammann", DEF_AMMANN, t_Bool}
+       {(caddr_t *) & ammann, "ammann", "Ammann", DEF_AMMANN, t_Bool},
+       {(caddr_t *) & redo_delay, "redoDelay", "RedoDelay", "3", t_Int}
 };
 static OptionStruct desc[] =
 {
-       {"-/+ammann", "turn on/off Ammann lines"}
+       {"-/+ammann", "turn on/off Ammann lines"},
+       {"-redoDelay", "delay between new tilings"}
 };
 
-ModeSpecOpt penrose_opts = { 2, opts, 1, vars, desc };
+ModeSpecOpt penrose_opts = { 3, opts, 2, vars, desc };
 
 
 /*-
@@ -326,7 +330,7 @@ vertex_dir(ModeInfo * mi, fringe_node_c * vertex, unsigned side)
                        (void) fprintf(stderr, "v2->fived[%d]=%d, vertex->fived[%d]=%d\n",
                                      i, v2->fived[i], i, vertex->fived[i]);
        }
-       MI_PAUSE(mi) = CELEBRATE;
+       MI_PAUSE(mi) = redo_delay_usec;
        return 0;
 }
 
@@ -414,6 +418,8 @@ init_penrose(ModeInfo * mi)
        fringe_node_c *fp;
        int         i, size;
 
+       redo_delay_usec = redo_delay * 1000000;
+
        if (tilings == NULL) {
                if ((tilings = (tiling_c *) calloc(MI_NUM_SCREENS(mi),
                                                 sizeof (tiling_c))) == NULL)
@@ -715,7 +721,7 @@ check_vertex(ModeInfo * mi, fringe_node_c * vertex, tiling_c * tp)
                if (MI_WIN_IS_VERBOSE(mi)) {
                        (void) fprintf(stderr, "Dislocation occured!\n");
                }
-               MI_PAUSE(mi) = CELEBRATE;       /* Should be able to recover */
+               MI_PAUSE(mi) = redo_delay_usec; /* Should be able to recover */
        }
        if (1 == find_completions(vertex, hits, n_hits, S_LEFT, 0 /*, False */ ))
                forced_sides |= S_LEFT;
@@ -770,7 +776,7 @@ delete_vertex(ModeInfo * mi, fringe_node_c * vertex, tiling_c * tp)
                        (void) fprintf(stderr, "Weirdness in delete_penrose()\n");
                        (void) fprintf(stderr, "tp->fringe.nodes == vertex\n");
                }
-               MI_PAUSE(mi) = CELEBRATE;
+               MI_PAUSE(mi) = redo_delay_usec;
        }
        if (vertex->list_ptr != 0) {
                forced_node_c *node = *vertex->list_ptr;
@@ -910,7 +916,7 @@ alloc_vertex(ModeInfo * mi, angle_c dir, fringe_node_c * from, tiling_c * tp)
                        (void) fprintf(stderr, "Weirdness in alloc_vertex()\n");
                        (void) fprintf(stderr, "v = 0\n");
                }
-               MI_PAUSE(mi) = CELEBRATE;
+               MI_PAUSE(mi) = redo_delay_usec;
        }
        *v = *from;
        add_unit_vec(dir, v->fived);
@@ -1230,7 +1236,7 @@ draw_penrose(ModeInfo * mi)
        /* No visible nodes left. */
        if (tp->fringe.n_nodes == 0) {
                tp->done = True;
-               MI_PAUSE(mi) = COMPLETION;      /* Just finished drawing */
+               MI_PAUSE(mi) = redo_delay_usec; /* Just finished drawing */
                return;
        }
        if (tp->forced.n_visible > 0 && tp->failures < 10) {
index db4c818c6c9c33530c4d8ea32df0d4c3c2a28922..e4734bf82ff9be772959b5b7426b94e5a0548732 100644 (file)
@@ -3,7 +3,7 @@
 penrose - draws quasiperiodic tilings
 .SH SYNOPSIS
 .B penrose
-[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-size \fIinteger\fP] [\-ammann] [\-no\-ammann]
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-redoDelay \fIseconds\fP] [\-size \fIinteger\fP] [\-ammann] [\-no\-ammann]
 
 .SH DESCRIPTION
 The \fIpenrose\fP program draws quasiperiodic tilings.
@@ -32,6 +32,10 @@ extended a window's length beyond the edge of the window
 horizontally or vertically or forced rule choice has failed 100
 times due to areas about to become enclosed.
 
+Although quasiperiodic tilings are produced, the tiles themselves are
+not penrose tiles (darts and kites). In contrast to penrose tiles,
+these tiles can be arranged to form a periodic tiling.
+
 .SH OPTIONS
 .I penrose
 accepts the following options:
@@ -59,6 +63,15 @@ The colors are chosen randomly.
 .B \-size \fIinteger\fP
 How big the tiles should be.  Default 40 pixels.
 
+.TP 8
+.B \-delay \fImilliseconds\fP
+How long (in 1/1,000,000'ths of a second) to wait between drawing each
+tile.  Default 10,000 or .01 seconds.
+
+.TP 8
+.B \-redoDelay \fIseconds\fP
+How long to wait between starting a completely new tiling.  Default 3 seconds.
+
 .TP 8
 .B \-ammann \fIinteger\fP
 .TP 8
diff --git a/hacks/phosphor.c b/hacks/phosphor.c
new file mode 100644 (file)
index 0000000..c575bb2
--- /dev/null
@@ -0,0 +1,801 @@
+/* xscreensaver, Copyright (c) 1999 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ *
+ * Phosphor -- simulate a glass tty with long-sustain phosphor.
+ */
+
+#include "screenhack.h"
+#include <stdio.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/Intrinsic.h>
+
+extern XtAppContext app;
+
+#define FUZZY_BORDER
+
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+#define BLANK  0
+#define FLARE  1
+#define NORMAL 2
+#define FADE   3
+
+#define CURSOR_INDEX 128
+
+typedef struct {
+  unsigned char name;
+  int width, height;
+  Pixmap pixmap;
+#ifdef FUZZY_BORDER
+  Pixmap pixmap2;
+#endif /* FUZZY_BORDER */
+  Bool blank_p;
+} p_char;
+
+typedef struct {
+  p_char *p_char;
+  int state;
+  Bool changed;
+} p_cell;
+
+typedef struct {
+  Display *dpy;
+  Window window;
+  XWindowAttributes xgwa;
+  XFontStruct *font;
+  int grid_width, grid_height;
+  int char_width, char_height;
+  int scale;
+  int ticks;
+  p_char **chars;
+  p_cell *cells;
+  XGCValues gcv;
+  GC gc0;
+  GC gc1;
+#ifdef FUZZY_BORDER
+  GC gc2;
+#endif /* FUZZY_BORDER */
+  GC *gcs;
+  XImage *font_bits;
+
+  int cursor_x, cursor_y;
+  XtIntervalId cursor_timer;
+  Time cursor_blink;
+
+  FILE *pipe;
+  XtInputId pipe_id;
+  Bool input_available_p;
+  Time subproc_relaunch_delay;
+
+} p_state;
+
+
+static void capture_font_bits (p_state *state);
+static p_char *make_character (p_state *state, int c);
+static void drain_input (p_state *state);
+static void char_to_pixmap (p_state *state, p_char *pc, int c);
+static void launch_text_generator (p_state *state);
+
+
+/* About font metrics:
+
+   "lbearing" is the distance from the leftmost pixel of a character to
+   the logical origin of that character.  That is, it is the number of
+   pixels of the character which are to the left of its logical origin.
+
+   "rbearing" is the distance from the logical origin of a character to
+   the rightmost pixel of a character.  That is, it is the number of
+   pixels of the character to the right of its logical origin.
+
+   "descent" is the distance from the bottommost pixel of a character to
+   the logical baseline.  That is, it is the number of pixels of the
+   character which are below the baseline.
+
+   "ascent" is the distance from the logical baseline to the topmost pixel.
+   That is, it is the number of pixels of the character above the baseline.
+
+   Therefore, the bounding box of the "ink" of a character is
+   lbearing + rbearing by ascent + descent;
+
+   "width" is the distance from the logical origin of this character to
+   the position where the logical orgin of the next character should be
+   placed.
+
+   For our purposes, we're only interested in the part of the character
+   lying inside the "width" box.  If the characters have ink outside of
+   that box (the "charcell" box) then we're going to lose it.  Alas.
+ */
+
+static p_state *
+init_phosphor (Display *dpy, Window window)
+{
+  int i;
+  unsigned long flags;
+  p_state *state = (p_state *) calloc (sizeof(*state), 1);
+  char *fontname = get_string_resource ("font", "Font");
+  XFontStruct *font;
+
+  state->dpy = dpy;
+  state->window = window;
+
+  XGetWindowAttributes (dpy, window, &state->xgwa);
+
+  state->font = XLoadQueryFont (dpy, fontname);
+
+  if (!state->font)
+    {
+      fprintf(stderr, "couldn't load font \"%s\"\n", fontname);
+      state->font = XLoadQueryFont (dpy, "fixed");
+    }
+  if (!state->font)
+    {
+      fprintf(stderr, "couldn't load font \"fixed\"");
+      exit(1);
+    }
+
+  font = state->font;
+  state->scale = get_integer_resource ("scale", "Integer");
+  state->ticks = 3 + get_integer_resource ("ticks", "Integer");
+
+#if 0
+  for (i = 0; i < font->n_properties; i++)
+    if (font->properties[i].name == XA_FONT)
+      printf ("font: %s\n", XGetAtomName(dpy, font->properties[i].card32));
+#endif /* 0 */
+
+  state->cursor_blink = get_integer_resource ("cursor", "Time");
+  state->subproc_relaunch_delay =
+    (1000 * get_integer_resource ("relaunch", "Time"));
+
+  state->char_width  = font->max_bounds.width;
+  state->char_height = font->max_bounds.ascent + font->max_bounds.descent;
+
+  state->grid_width = state->xgwa.width / (state->char_width * state->scale);
+  state->grid_height = state->xgwa.height /(state->char_height * state->scale);
+  state->cells = (p_cell *) calloc (sizeof(p_cell),
+                                    state->grid_width * state->grid_height);
+  state->chars = (p_char **) calloc (sizeof(p_char *), 256);
+
+  state->gcs = (GC *) calloc (sizeof(GC), state->ticks + 1);
+
+  {
+    int ncolors = MAX (0, state->ticks - 3);
+    XColor *colors = (XColor *) calloc (ncolors, sizeof(XColor));
+    int h1, h2;
+    double s1, s2, v1, v2;
+
+    unsigned long fg = get_pixel_resource ("foreground", "Foreground",
+                                           state->dpy, state->xgwa.colormap);
+    unsigned long bg = get_pixel_resource ("background", "Background",
+                                           state->dpy, state->xgwa.colormap);
+    unsigned long flare = get_pixel_resource ("flareForeground", "Foreground",
+                                              state->dpy,state->xgwa.colormap);
+    unsigned long fade = get_pixel_resource ("fadeForeground", "Foreground",
+                                             state->dpy,state->xgwa.colormap);
+
+    XColor start, end;
+
+    start.pixel = fade;
+    XQueryColor (state->dpy, state->xgwa.colormap, &start);
+
+    end.pixel = bg;
+    XQueryColor (state->dpy, state->xgwa.colormap, &end);
+
+    /* Now allocate a ramp of colors from the main color to the background. */
+    rgb_to_hsv (start.red, start.green, start.blue, &h1, &s1, &v1);
+    rgb_to_hsv (end.red, end.green, end.blue, &h2, &s2, &v2);
+    make_color_ramp (state->dpy, state->xgwa.colormap,
+                     h1, s1, v1,
+                     h2, s2, v2,
+                     colors, &ncolors,
+                     False, True, False);
+
+    /* Now, GCs all around.
+     */
+    state->gcv.font = font->fid;
+    state->gcv.cap_style = CapRound;
+#ifdef FUZZY_BORDER
+    state->gcv.line_width = (int) (((long) state->scale) * 1.3);
+    if (state->gcv.line_width == state->scale)
+      state->gcv.line_width++;
+#else /* !FUZZY_BORDER */
+    state->gcv.line_width = (int) (((long) state->scale) * 0.9);
+    if (state->gcv.line_width >= state->scale)
+      state->gcv.line_width = state->scale - 1;
+    if (state->gcv.line_width < 1)
+      state->gcv.line_width = 1;
+#endif /* !FUZZY_BORDER */
+
+    flags = (GCForeground | GCBackground | GCCapStyle | GCLineWidth);
+
+    state->gcv.background = bg;
+    state->gcv.foreground = bg;
+    state->gcs[BLANK] = XCreateGC (state->dpy, state->window, flags,
+                                   &state->gcv);
+
+    state->gcv.foreground = flare;
+    state->gcs[FLARE] = XCreateGC (state->dpy, state->window, flags,
+                                   &state->gcv);
+
+    state->gcv.foreground = fg;
+    state->gcs[NORMAL] = XCreateGC (state->dpy, state->window, flags,
+                                    &state->gcv);
+
+    for (i = 0; i < ncolors; i++)
+      {
+        state->gcv.foreground = colors[i].pixel;
+        state->gcs[FADE + i] = XCreateGC (state->dpy, state->window,
+                                          flags, &state->gcv);
+      }
+  }
+
+  capture_font_bits (state);
+
+  launch_text_generator (state);
+
+  return state;
+}
+
+
+static void
+capture_font_bits (p_state *state)
+{
+  XFontStruct *font = state->font;
+  int safe_width = font->max_bounds.rbearing - font->min_bounds.lbearing;
+  int height = state->char_height;
+  unsigned char string[257];
+  int i;
+  Pixmap p = XCreatePixmap (state->dpy, state->window,
+                            (safe_width * 256), height, 1);
+
+  for (i = 0; i < 256; i++)
+    string[i] = (unsigned char) i;
+  string[256] = 0;
+
+  state->gcv.foreground = 0;
+  state->gcv.background = 0;
+  state->gc0 = XCreateGC (state->dpy, p,
+                          (GCForeground | GCBackground),
+                          &state->gcv);
+
+  state->gcv.foreground = 1;
+  state->gc1 = XCreateGC (state->dpy, p,
+                          (GCFont | GCForeground | GCBackground |
+                           GCCapStyle | GCLineWidth),
+                          &state->gcv);
+
+#ifdef FUZZY_BORDER
+  {
+    state->gcv.line_width = (int) (((long) state->scale) * 0.8);
+    if (state->gcv.line_width >= state->scale)
+      state->gcv.line_width = state->scale - 1;
+    if (state->gcv.line_width < 1)
+      state->gcv.line_width = 1;
+    state->gc2 = XCreateGC (state->dpy, p,
+                            (GCFont | GCForeground | GCBackground |
+                             GCCapStyle | GCLineWidth),
+                            &state->gcv);
+  }
+#endif /* FUZZY_BORDER */
+
+  XFillRectangle (state->dpy, p, state->gc0, 0, 0, (safe_width * 256), height);
+
+  for (i = 0; i < 256; i++)
+    {
+      if (string[i] < font->min_char_or_byte2 ||
+          string[i] > font->max_char_or_byte2)
+        continue;
+      XDrawString (state->dpy, p, state->gc1,
+                   i * safe_width, font->ascent,
+                   string + i, 1);
+    }
+
+  /* Draw the cursor. */
+  XFillRectangle (state->dpy, p, state->gc1,
+                  (CURSOR_INDEX * safe_width), 1,
+                  (font->per_char
+                   ? font->per_char['n'-font->min_char_or_byte2].width
+                   : font->max_bounds.width),
+                  font->ascent - 1);
+
+#if 0
+  XCopyPlane (state->dpy, p, state->window, state->gcs[FLARE],
+              0, 0, (safe_width * 256), height, 0, 0, 1L);
+  XSync(state->dpy, False);
+#endif
+
+  XSync (state->dpy, False);
+  state->font_bits = XGetImage (state->dpy, p, 0, 0,
+                                (safe_width * 256), height, ~0L, XYPixmap);
+  XFreePixmap (state->dpy, p);
+
+  for (i = 0; i < 256; i++)
+    state->chars[i] = make_character (state, i);
+  state->chars[CURSOR_INDEX] = make_character (state, CURSOR_INDEX);
+}
+
+
+static p_char *
+make_character (p_state *state, int c)
+{
+  p_char *pc = (p_char *) malloc (sizeof (*pc));
+  pc->name = (unsigned char) c;
+  pc->width =  state->scale * state->char_width;
+  pc->height = state->scale * state->char_height;
+  char_to_pixmap (state, pc, c);
+  return pc;
+}
+
+
+static void
+char_to_pixmap (p_state *state, p_char *pc, int c)
+{
+  Pixmap p = 0;
+  GC gc;
+#ifdef FUZZY_BORDER
+  Pixmap p2 = 0;
+  GC gc2;
+#endif /* FUZZY_BORDER */
+  int from, to;
+  int x1, y;
+
+  XFontStruct *font = state->font;
+  int safe_width = font->max_bounds.rbearing - font->min_bounds.lbearing;
+
+  int width  = state->scale * state->char_width;
+  int height = state->scale * state->char_height;
+
+  if (c < font->min_char_or_byte2 ||
+      c > font->max_char_or_byte2)
+    goto DONE;
+
+  gc = state->gc1;
+  p = XCreatePixmap (state->dpy, state->window, width, height, 1);
+  XFillRectangle (state->dpy, p, state->gc0, 0, 0, width, height);
+#ifdef FUZZY_BORDER
+  gc2 = state->gc2;
+  p2 = XCreatePixmap (state->dpy, state->window, width, height, 1);
+  XFillRectangle (state->dpy, p2, state->gc0, 0, 0, width, height);
+#endif /* FUZZY_BORDER */
+
+  from = safe_width * c;
+  to =   safe_width * (c + 1);
+
+#if 0
+  if (c > 75 && c < 150)
+    {
+      printf ("\n=========== %d (%c)\n", c, c);
+      for (y = 0; y < state->char_height; y++)
+        {
+          for (x1 = from; x1 < to; x1++)
+            printf (XGetPixel (state->font_bits, x1, y) ? "* " : ". ");
+          printf ("\n");
+        }
+    }
+#endif
+
+  pc->blank_p = True;
+  for (y = 0; y < state->char_height; y++)
+    for (x1 = from; x1 < to; x1++)
+      if (XGetPixel (state->font_bits, x1, y))
+        {
+          int xoff = state->scale / 2;
+          int x2;
+          for (x2 = x1; x2 < to; x2++)
+            if (!XGetPixel (state->font_bits, x2, y))
+              break;
+          x2--;
+          XDrawLine (state->dpy, p, gc,
+                     (x1 - from) * state->scale + xoff, y * state->scale,
+                     (x2 - from) * state->scale + xoff, y * state->scale);
+#ifdef FUZZY_BORDER
+          XDrawLine (state->dpy, p2, gc2,
+                     (x1 - from) * state->scale + xoff, y * state->scale,
+                     (x2 - from) * state->scale + xoff, y * state->scale);
+#endif /* FUZZY_BORDER */
+          x1 = x2;
+          pc->blank_p = False;
+        }
+
+  /*  if (pc->blank_p && c == CURSOR_INDEX)
+    abort();*/
+
+ DONE:
+  pc->pixmap = p;
+#ifdef FUZZY_BORDER
+  pc->pixmap2 = p2;
+#endif /* FUZZY_BORDER */
+}
+
+\f
+/* Managing the display. 
+ */
+
+static void cursor_on_timer (XtPointer closure, XtIntervalId *id);
+static void cursor_off_timer (XtPointer closure, XtIntervalId *id);
+
+static Bool
+set_cursor_1 (p_state *state, Bool on)
+{
+  p_cell *cell = &state->cells[state->grid_width * state->cursor_y
+                              + state->cursor_x];
+  p_char *cursor = state->chars[CURSOR_INDEX];
+  int new_state = (on ? NORMAL : FADE);
+
+  if (cell->p_char != cursor)
+    cell->changed = True;
+
+  if (cell->state != new_state)
+    cell->changed = True;
+
+  cell->p_char = cursor;
+  cell->state = new_state;
+  return cell->changed;
+}
+
+static void
+set_cursor (p_state *state, Bool on)
+{
+  if (set_cursor_1 (state, on))
+;
+    {
+      if (state->cursor_timer)
+        XtRemoveTimeOut (state->cursor_timer);
+      state->cursor_timer = 0;
+      cursor_on_timer (state, 0);
+    }
+}
+
+
+
+
+static void
+cursor_off_timer (XtPointer closure, XtIntervalId *id)
+{
+  p_state *state = (p_state *) closure;
+  set_cursor_1 (state, False);
+  state->cursor_timer = XtAppAddTimeOut (app, state->cursor_blink,
+                                         cursor_on_timer, closure);
+}
+
+static void
+cursor_on_timer (XtPointer closure, XtIntervalId *id)
+{
+  p_state *state = (p_state *) closure;
+  set_cursor_1 (state, True);
+  state->cursor_timer = XtAppAddTimeOut (app, 2 * state->cursor_blink,
+                                         cursor_off_timer, closure);
+}
+
+
+static void
+clear (p_state *state)
+{
+  int x, y;
+  state->cursor_x = 0;
+  state->cursor_y = 0;
+  for (y = 0; y < state->grid_height; y++)
+    for (x = 0; x < state->grid_width; x++)
+      {
+        p_cell *cell = &state->cells[state->grid_width * y + x];
+        if (cell->state == FLARE || cell->state == NORMAL)
+          {
+            cell->state = FADE;
+            cell->changed = True;
+          }
+      }
+  set_cursor (state, True);
+}
+
+
+static void
+decay (p_state *state)
+{
+  int x, y;
+  for (y = 0; y < state->grid_height; y++)
+    for (x = 0; x < state->grid_width; x++)
+      {
+        p_cell *cell = &state->cells[state->grid_width * y + x];
+        if (cell->state == FLARE)
+          {
+            cell->state = NORMAL;
+            cell->changed = True;
+          }
+        else if (cell->state >= FADE)
+          {
+            cell->state++;
+            if (cell->state >= state->ticks)
+              cell->state = BLANK;
+            cell->changed = True;
+          }
+      }
+}
+
+
+static void
+scroll (p_state *state)
+{
+  int x, y;
+  for (x = 0; x < state->grid_width; x++)
+    {
+      p_cell *from, *to;
+      for (y = 1; y < state->grid_height; y++)
+        {
+          from = &state->cells[state->grid_width * y     + x];
+          to   = &state->cells[state->grid_width * (y-1) + x];
+
+          if ((from->state == FLARE || from->state == NORMAL) &&
+              !from->p_char->blank_p)
+            {
+              *to = *from;
+              to->state = NORMAL;  /* should be FLARE?  Looks bad... */
+            }
+          else
+            {
+              if (to->state == FLARE || to->state == NORMAL)
+                to->state = FADE;
+            }
+
+          to->changed = True;
+        }
+
+      to = from;
+      if (to->state == FLARE || to->state == NORMAL)
+        {
+          to->state = FADE;
+          to->changed = True;
+        }
+    }
+  set_cursor (state, True);
+}
+
+
+static void
+print_char (p_state *state, int c)
+{
+  p_cell *cell = &state->cells[state->grid_width * state->cursor_y
+                              + state->cursor_x];
+
+  /* Start the cursor fading (in case we don't end up overwriting it.) */
+  if (cell->state == FLARE || cell->state == NORMAL)
+    {
+      cell->state = FADE;
+      cell->changed = True;
+    }
+
+  if (c == '\t') c = ' ';   /* blah. */
+
+  if (c == '\r' || c == '\n')
+    {
+      state->cursor_x = 0;
+      if (state->cursor_y == state->grid_height - 1)
+        scroll (state);
+      else
+        state->cursor_y++;
+    }
+  else if (c == '\014')
+    {
+      clear (state);
+    }
+  else
+    {
+      cell->state = FLARE;
+      cell->p_char = state->chars[c];
+      cell->changed = True;
+      state->cursor_x++;
+
+      if (c != ' ' && cell->p_char->blank_p)
+        cell->p_char = state->chars[CURSOR_INDEX];
+
+      if (state->cursor_x >= state->grid_width - 1)
+        {
+          state->cursor_x = 0;
+          if (state->cursor_y >= state->grid_height - 1)
+            scroll (state);
+          else
+            state->cursor_y++;
+        }
+    }
+  set_cursor (state, True);
+}
+
+
+static void
+update_display (p_state *state, Bool changed_only)
+{
+  int x, y;
+
+  for (y = 0; y < state->grid_height; y++)
+    for (x = 0; x < state->grid_width; x++)
+      {
+        p_cell *cell = &state->cells[state->grid_width * y + x];
+        int width, height, tx, ty;
+
+        if (changed_only && !cell->changed)
+          continue;
+
+        width = state->char_width * state->scale;
+        height = state->char_height * state->scale;
+        tx = x * width;
+        ty = y * height;
+
+        if (cell->state == BLANK || cell->p_char->blank_p)
+          {
+            XFillRectangle (state->dpy, state->window, state->gcs[BLANK],
+                            tx, ty, width, height);
+          }
+        else
+          {
+#ifdef FUZZY_BORDER
+            GC gc1 = state->gcs[cell->state];
+            GC gc2 = ((cell->state + 2) < state->ticks
+                      ? state->gcs[cell->state + 2]
+                      : 0);
+            XCopyPlane (state->dpy, cell->p_char->pixmap, state->window,
+                        (gc2 ? gc2 : gc1),
+                        0, 0, width, height, tx, ty, 1L);
+            if (gc2)
+              {
+                XSetClipMask (state->dpy, gc1, cell->p_char->pixmap2);
+                XSetClipOrigin (state->dpy, gc1, tx, ty);
+                XFillRectangle (state->dpy, state->window, gc1,
+                                tx, ty, width, height);
+                XSetClipMask (state->dpy, gc1, None);
+              }
+#else /* !FUZZY_BORDER */
+
+            XCopyPlane (state->dpy,
+                        cell->p_char->pixmap, state->window,
+                        state->gcs[cell->state],
+                        0, 0, width, height, tx, ty, 1L);
+
+#endif /* !FUZZY_BORDER */
+          }
+
+        cell->changed = False;
+      }
+}
+
+
+static void
+run_phosphor (p_state *state)
+{
+  update_display (state, True);
+  decay (state);
+  drain_input (state);
+}
+
+\f
+/* Subprocess.
+ */
+
+static void
+subproc_cb (XtPointer closure, int *source, XtInputId *id)
+{
+  p_state *state = (p_state *) closure;
+  state->input_available_p = True;
+}
+
+
+static void
+launch_text_generator (p_state *state)
+{
+  char *oprogram = get_string_resource ("program", "Program");
+  char *program = (char *) malloc (strlen (oprogram) + 10);
+
+  strcpy (program, "( ");
+  strcat (program, oprogram);
+  strcat (program, " ) 2>&1");
+
+  if ((state->pipe = popen (program, "r")))
+    {
+      state->pipe_id =
+        XtAppAddInput (app, fileno (state->pipe),
+                       (XtPointer) (XtInputReadMask | XtInputExceptMask),
+                       subproc_cb, (XtPointer) state);
+    }
+  else
+    {
+      perror (program);
+    }
+}
+
+
+static void
+relaunch_generator_timer (XtPointer closure, XtIntervalId *id)
+{
+  p_state *state = (p_state *) closure;
+  launch_text_generator (state);
+}
+
+
+static void
+drain_input (p_state *state)
+{
+  if (state->input_available_p)
+    {
+      char s[2];
+      int n = read (fileno (state->pipe), (void *) s, 1);
+      if (n == 1)
+        {
+          print_char (state, s[0]);
+        }
+      else
+        {
+          XtRemoveInput (state->pipe_id);
+          state->pipe_id = 0;
+          pclose (state->pipe);
+          state->pipe = 0;
+
+          if (state->cursor_x != 0)    /* break line if unbroken */
+            print_char (state, '\n');  /* blank line */
+          print_char (state, '\n');
+
+          /* Set up a timer to re-launch the subproc in a bit. */
+          XtAppAddTimeOut (app, state->subproc_relaunch_delay,
+                           relaunch_generator_timer,
+                           (XtPointer) state);
+        }
+        
+      state->input_available_p = False;
+    }
+}
+
+
+\f
+char *progclass = "Phosphor";
+
+char *defaults [] = {
+  ".background:                   Black",
+  ".foreground:                   Green",
+  "*fadeForeground:       DarkGreen",
+  "*flareForeground:      White",
+  "*font:                 fixed",
+  "*scale:                6",
+  "*ticks:                20",
+  "*delay:                50000",
+  "*cursor:               333",
+  "*program:            " ZIPPY_PROGRAM,
+  "*relaunch:             5",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-font",           ".font",                XrmoptionSepArg, 0 },
+  { "-scale",          ".scale",               XrmoptionSepArg, 0 },
+  { "-ticks",          ".ticks",               XrmoptionSepArg, 0 },
+  { "-delay",          ".delay",               XrmoptionSepArg, 0 },
+  { "-program",                ".program",             XrmoptionSepArg, 0 },
+  { 0, 0, 0, 0 }
+};
+
+
+void
+screenhack (Display *dpy, Window window)
+{
+  int delay = get_integer_resource ("delay", "Integer");
+  p_state *state = init_phosphor (dpy, window);
+
+  clear (state);
+
+  while (1)
+    {
+      run_phosphor (state);
+      XSync (dpy, False);
+      screenhack_handle_events (dpy);
+
+      if (XtAppPending (app) & (XtIMTimer|XtIMAlternateInput|XtIMSignal))
+        XtAppProcessEvent (app, XtIMTimer|XtIMAlternateInput|XtIMSignal);
+
+      if (delay) usleep (delay);
+    }
+}
index 7c14734664f522227911b8c2f8d06ca788286f7d..eb9d7185e0058dd0cd3e3e1c042d8a94f26d1fcb 100644 (file)
@@ -59,6 +59,7 @@
 
 char *progname;
 XrmDatabase db;
+XtAppContext app;
 Bool mono_p;
 
 static XrmOptionDescRec default_options [] = {
@@ -240,7 +241,6 @@ screenhack_handle_events (Display *dpy)
 int
 main (int argc, char **argv)
 {
-  XtAppContext app;
   Widget toplevel;
   Display *dpy;
   Window window;
index 91694e93e994b332d606655d6ecb4e7e1eb15173..395fea1cd37c0d5804d5292ce047cdfb51f63b31 100644 (file)
@@ -196,7 +196,7 @@ draw_slip(ModeInfo * mi)
                double      x, y, dx = 0, dy = 0, t, s1, s2;
 
                if (0 == s->nblits_remaining--) {
-                       static      lut[] =
+                       static int lut[] =
                        {0, 0, 0, 1, 1, 1, 2};
 
                        prepare_screen(mi, s);
index cffe98424e79bf480eb8e31183719745932874c3..e0a81e3a197e8ef1fd0ef9d813bef2406599b054 100644 (file)
@@ -106,7 +106,7 @@ draw_sphere(ModeInfo * mi)
        Display    *display = MI_DISPLAY(mi);
        GC          gc = MI_GC(mi);
        spherestruct *sp = &spheres[MI_SCREEN(mi)];
-       register    minx = 0, maxx = 0, miny = 0, maxy = 0, npts = 0;
+       int         minx = 0, maxx = 0, miny = 0, maxy = 0, npts = 0;
 
        if ((sp->dirx && ABS(sp->x) >= sp->radius) ||
            (sp->diry && ABS(sp->y) >= sp->radius)) {
index 57feea0fbb6bf324b42036c1f617c8a74e476b1f..fb7868feff039fcdb649a726e9fd51cbdcba1318 100644 (file)
@@ -219,4 +219,5 @@ XrmOptionDescRec options[] = {
     {"-ncolors", ".ncolors", XrmoptionSepArg, 0},
     {"-cycle", ".cycle", XrmoptionNoArg, "True"},
     {"-no-cycle", ".cycle", XrmoptionNoArg, "False"},
+    { 0, 0, 0, 0 }
 };
index 58ec47f2bf01ae96dfe8b35326ece537e09350b8..b569c7511fc04dcfa7172d81506e5c728df09da3 100644 (file)
@@ -209,7 +209,7 @@ initColor (double r, double g, double b)
 {
   int n,n1;
   unsigned long pixels[12];
-  long dummy;
+  unsigned long dummy;
   
   cmap = xgwa.colormap;
   
@@ -293,7 +293,7 @@ initialize (void)
     if (s && *s)
       {
         double hh, ss, vv;
-        if (3 == sscanf (s, "%lf %lf %lf", &hh, &ss, &vv, &dummy)) {
+        if (3 == sscanf (s, "%lf %lf %lf %c", &hh, &ss, &vv, &dummy)) {
           hue = hh, sat = ss, val = vv;
           hsv2rgb(hue,sat,val,&r,&g,&b);
         }
@@ -816,7 +816,8 @@ screenhack (Display *d, Window w)
 {
   Window junk_win,in_win;
   
-  int px,py,junk,kb/*,wai*/;
+  int px,py,junk/*,wai*/;
+  unsigned int kb;
 /*  int act,act1,tc;*/
   double vnorm;
   /* double var=0.0; */
index 360ef379fc1d2515073e1335d37dc8870d8b79d8..dcac9600e7497ece737f5590d6d5f5cb608be535 100755 (executable)
@@ -125,9 +125,14 @@ MakeImage(void)
 {
   XGCValues gcv;
 
+#ifdef HAVE_XSHM_EXTENSION
   shared = True;
   xim = create_xshm_image (display, visual, depth, ZPixmap, NULL,
                            &shminfo, width, height);
+#else  /* !HAVE_XSHM_EXTENSION */
+  xim = 0;
+#endif /* !HAVE_XSHM_EXTENSION */
+
   if (!xim)
     {
       shared = False;
@@ -180,10 +185,12 @@ InitColors(void)
 static void
 DisplayImage(void)
 {
+#ifdef HAVE_XSHM_EXTENSION
   if (shared)
     XShmPutImage(display, window, gc, xim, 0,(top - 1) << 1, 0,
                  (top - 1) << 1, width, height - ((top - 1) << 1), False);
   else
+#endif /* HAVE_XSHM_EXTENSION */
     XPutImage(display, window, gc, xim, 0, (top - 1) << 1, 0,
               (top - 1) << 1, width, height - ((top - 1) << 1));
 }
@@ -521,6 +528,7 @@ loadBitmap(int *w, int *h)
       *bitmap_name &&
       !!strcmp(bitmap_name, "none"))
     {
+#ifdef HAVE_XPM
       XpmInfo xpm_info = { 0, };
       XpmImage xpm_image = { 0, };
 
@@ -582,6 +590,7 @@ loadBitmap(int *w, int *h)
           return result;
         }
       else      /* failed to read XPM -- fall through and try XBM */
+#endif /* HAVE_XPM */
         {
 #ifdef HAVE_XMU
           XImage *ximage = 0;
index b180fc43341828a85e6225e2fcb788491b2b6ad1..3742df68858b61e40a6d5236a70c3f87ae738a21 100644 (file)
@@ -599,7 +599,7 @@ main_event(void)
 static int
 complyap(void)
 {
-  register i, bindex;
+  int i, bindex;
   double total, prod, x, dx, r;
 
   if (!run)
diff --git a/hacks/xmatrix.c b/hacks/xmatrix.c
new file mode 100644 (file)
index 0000000..38d9af1
--- /dev/null
@@ -0,0 +1,438 @@
+/* xscreensaver, Copyright (c) 1999 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ *
+ * Matrix -- simulate the text scrolls from the movie "The Matrix".
+ *
+ * The movie people distribute their own Windows/Mac screensaver that does
+ * a similar thing, so I wrote one for Unix.  However, that version (the
+ * Windows/Mac version at http://www.whatisthematrix.com/) doesn't match my
+ * memory of what the screens in the movie looked like, so my `xmatrix'
+ * does things differently.
+ */
+
+#include "screenhack.h"
+#include <stdio.h>
+#include <X11/Xutil.h>
+
+#ifdef HAVE_XPM
+# include <X11/xpm.h>
+# include "images/matrix.xpm"
+#endif
+
+#include "images/matrix.xbm"
+
+#define CHAR_HEIGHT 31
+
+typedef struct {
+  int glyph;
+  Bool changed;
+  int glow;
+} m_cell;
+
+typedef struct {
+  int remaining;
+  int throttle;
+  int y;
+} m_feeder;
+
+typedef struct {
+  Display *dpy;
+  Window window;
+  XWindowAttributes xgwa;
+  GC draw_gc, erase_gc;
+  int grid_width, grid_height;
+  int char_width, char_height;
+  m_cell *cells;
+  m_feeder *feeders;
+  Bool insert_top_p, insert_bottom_p;
+  int density;
+
+  Pixmap images;
+  int image_width, image_height;
+  int nglyphs;
+
+} m_state;
+
+
+static void
+load_images (m_state *state)
+{
+#ifdef HAVE_XPM
+  if (!get_boolean_resource ("mono", "Boolean") &&
+      state->xgwa.depth > 1)
+    {
+      XpmAttributes xpmattrs;
+      int result;
+      xpmattrs.valuemask = 0;
+
+# ifdef XpmCloseness
+      xpmattrs.valuemask |= XpmCloseness;
+      xpmattrs.closeness = 40000;
+# endif
+# ifdef XpmVisual
+      xpmattrs.valuemask |= XpmVisual;
+      xpmattrs.visual = state->xgwa.visual;
+# endif
+# ifdef XpmDepth
+      xpmattrs.valuemask |= XpmDepth;
+      xpmattrs.depth = state->xgwa.depth;
+# endif
+# ifdef XpmColormap
+      xpmattrs.valuemask |= XpmColormap;
+      xpmattrs.colormap = state->xgwa.colormap;
+# endif
+
+      result = XpmCreatePixmapFromData (state->dpy, state->window, matrix,
+                                        &state->images, 0 /* mask */,
+                                        &xpmattrs);
+      if (!state->images || (result != XpmSuccess && result != XpmColorError))
+        state->images = 0;
+
+      state->image_width = xpmattrs.width;
+      state->image_height = xpmattrs.height;
+      state->nglyphs = state->image_height / CHAR_HEIGHT;
+    }
+  else
+#endif /* !HAVE_XPM */
+    {
+      unsigned long fg, bg;
+      state->image_width = matrix_width;
+      state->image_height = matrix_height;
+      state->nglyphs = state->image_height / CHAR_HEIGHT;
+
+      fg = get_pixel_resource("foreground", "Foreground",
+                              state->dpy, state->xgwa.colormap);
+      bg = get_pixel_resource("background", "Background",
+                              state->dpy, state->xgwa.colormap);
+      state->images =
+        XCreatePixmapFromBitmapData (state->dpy, state->window,
+                                     (char *) matrix_bits,
+                                     state->image_width, state->image_height,
+                                     bg, fg, state->xgwa.depth);
+    }
+}
+
+
+static m_state *
+init_matrix (Display *dpy, Window window)
+{
+  XGCValues gcv;
+  char *insert;
+  m_state *state = (m_state *) calloc (sizeof(*state), 1);
+  state->dpy = dpy;
+  state->window = window;
+
+  XGetWindowAttributes (dpy, window, &state->xgwa);
+  load_images (state);
+
+  gcv.foreground = get_pixel_resource("foreground", "Foreground",
+                                      state->dpy, state->xgwa.colormap);
+  gcv.background = get_pixel_resource("background", "Background",
+                                      state->dpy, state->xgwa.colormap);
+  state->draw_gc = XCreateGC (state->dpy, state->window,
+                              GCForeground|GCBackground, &gcv);
+  gcv.foreground = gcv.background;
+  state->erase_gc = XCreateGC (state->dpy, state->window,
+                               GCForeground|GCBackground, &gcv);
+
+  state->char_width = state->image_width / 2;
+  state->char_height = CHAR_HEIGHT;
+
+  state->grid_width  = state->xgwa.width  / state->char_width;
+  state->grid_height = state->xgwa.height / state->char_height;
+  state->grid_width++;
+  state->grid_height++;
+
+  state->cells = (m_cell *)
+    calloc (sizeof(m_cell), state->grid_width * state->grid_height);
+  state->feeders = (m_feeder *) calloc (sizeof(m_feeder), state->grid_width);
+
+  state->density = get_integer_resource ("density", "Integer");
+
+  insert = get_string_resource("insert", "Insert");
+  if (insert && !strcmp(insert, "top"))
+    {
+      state->insert_top_p = True;
+      state->insert_bottom_p = False;
+    }
+  else if (insert && !strcmp(insert, "bottom"))
+    {
+      state->insert_top_p = False;
+      state->insert_bottom_p = True;
+    }
+  else if (insert && !strcmp(insert, "both"))
+    {
+      state->insert_top_p = True;
+      state->insert_bottom_p = True;
+    }
+  else
+    {
+      if (insert && *insert)
+        fprintf (stderr,
+                 "%s: `insert' must be `top', `bottom', or `both', not \%s'\n",
+                 progname, insert);
+      state->insert_top_p = False;
+      state->insert_bottom_p = True;
+    }
+
+  if (insert)
+    free (insert);
+
+  return state;
+}
+
+
+static void
+insert_glyph (m_state *state, int glyph, int x, int y)
+{
+  Bool bottom_feeder_p = (y >= 0);
+  m_cell *from, *to;
+
+  if (y >= state->grid_height)
+    return;
+
+  if (bottom_feeder_p)
+    {
+      to = &state->cells[state->grid_width * y + x];
+    }
+  else
+    {
+      for (y = state->grid_height-1; y > 0; y--)
+        {
+          from = &state->cells[state->grid_width * (y-1) + x];
+          to   = &state->cells[state->grid_width * y     + x];
+          *to = *from;
+          to->changed = True;
+        }
+      to = &state->cells[x];
+    }
+
+  to->glyph = glyph;
+  to->changed = True;
+
+  if (!to->glyph)
+    ;
+  else if (bottom_feeder_p)
+    to->glow = 1 + (random() % 2);
+  else
+    to->glow = 0;
+}
+
+
+static void
+feed_matrix (m_state *state)
+{
+  int x;
+
+  /* Update according to current feeders. */
+  for (x = 0; x < state->grid_width; x++)
+    {
+      m_feeder *f = &state->feeders[x];
+
+      if (f->throttle)         /* this is a delay tick, synced to frame. */
+        {
+          f->throttle--;
+        }
+      else if (f->remaining > 0)       /* how many items are in the pipe */
+        {
+          int g = (random() % state->nglyphs) + 1;
+          insert_glyph (state, g, x, f->y);
+          f->remaining--;
+          if (f->y >= 0)  /* bottom_feeder_p */
+            f->y++;
+        }
+      else                             /* if pipe is empty, insert spaces */
+        {
+          insert_glyph (state, 0, x, f->y);
+          if (f->y >= 0)  /* bottom_feeder_p */
+            f->y++;
+        }
+
+      if ((random() % 10) == 0)                /* randomly change throttle speed */
+        {
+          f->throttle = ((random() % 5) + (random() % 5));
+        }
+    }
+}
+
+static int
+densitizer (m_state *state)
+{
+  /* Horrid kludge that converts percentages (density of screen coverage)
+     to the parameter that actually controls this.  I got this mapping
+     empirically, on a 1024x768 screen.  Sue me. */
+  if      (state->density < 10) return 85;
+  else if (state->density < 15) return 60;
+  else if (state->density < 20) return 45;
+  else if (state->density < 25) return 25;
+  else if (state->density < 30) return 20;
+  else if (state->density < 35) return 15;
+  else if (state->density < 45) return 10;
+  else if (state->density < 50) return 8;
+  else if (state->density < 55) return 7;
+  else if (state->density < 65) return 5;
+  else if (state->density < 80) return 3;
+  else if (state->density < 90) return 2;
+  else return 1;
+}
+
+
+static void
+hack_matrix (m_state *state)
+{
+  int x;
+
+  /* Glow some characters. */
+  if (!state->insert_bottom_p)
+    {
+      int i = random() % (state->grid_width / 2);
+      while (--i > 0)
+        {
+          int x = random() % state->grid_width;
+          int y = random() % state->grid_height;
+          m_cell *cell = &state->cells[state->grid_width * y + x];
+          if (cell->glyph && cell->glow == 0)
+            {
+              cell->glow = random() % 10;
+              cell->changed = True;
+            }
+        }
+    }
+
+  /* Change some of the feeders. */
+  for (x = 0; x < state->grid_width; x++)
+    {
+      m_feeder *f = &state->feeders[x];
+      Bool bottom_feeder_p;
+
+      if (f->remaining > 0)    /* never change if pipe isn't empty */
+        continue;
+
+      if ((random() % densitizer(state)) != 0) /* then change N% of the time */
+        continue;
+
+      f->remaining = 3 + (random() % state->grid_height);
+      f->throttle = ((random() % 5) + (random() % 5));
+
+      if ((random() % 4) != 0)
+        f->remaining = 0;
+
+      if (state->insert_top_p && state->insert_bottom_p)
+        bottom_feeder_p = (random() & 1);
+      else
+        bottom_feeder_p = state->insert_bottom_p;
+
+      if (bottom_feeder_p)
+        f->y = random() % (state->grid_height / 2);
+      else
+        f->y = -1;
+    }
+}
+
+
+static void
+draw_matrix (m_state *state)
+{
+  int x, y;
+  int count = 0;
+
+  feed_matrix (state);
+  hack_matrix (state);
+
+  for (y = 0; y < state->grid_height; y++)
+    for (x = 0; x < state->grid_width; x++)
+      {
+        m_cell *cell = &state->cells[state->grid_width * y + x];
+
+        if (cell->glyph)
+          count++;
+
+        if (!cell->changed)
+          continue;
+
+        if (cell->glyph == 0)
+          XFillRectangle (state->dpy, state->window, state->erase_gc,
+                          x * state->char_width,
+                          y * state->char_height,
+                          state->char_width,
+                          state->char_height);
+        else
+          XCopyArea (state->dpy, state->images, state->window, state->draw_gc,
+                     (cell->glow ? state->char_width : 0),
+                     (cell->glyph - 1) * state->char_height,
+                     state->char_width, state->char_height,
+                     x * state->char_width,
+                     y * state->char_height);
+
+        cell->changed = False;
+
+        if (cell->glow > 0)
+          {
+            cell->glow--;
+            cell->changed = True;
+          }
+      }
+
+#if 0
+  {
+    static int i = 0;
+    static int ndens = 0;
+    static int tdens = 0;
+    i++;
+    if (i > 50)
+      {
+        int dens = (100.0 *
+                    (((double)count) /
+                     ((double) (state->grid_width * state->grid_height))));
+        tdens += dens;
+        ndens++;
+        printf ("density: %d%% (%d%%)\n", dens, (tdens / ndens));
+        i = 0;
+      }
+  }
+#endif
+
+}
+
+\f
+char *progclass = "XMatrix";
+
+char *defaults [] = {
+  ".background:                   black",
+  ".foreground:                   green",
+  "*delay:                10000",
+  "*insert:               both",
+  "*density:              85",
+  0
+};
+
+XrmOptionDescRec options [] = {
+  { "-delay",          ".delay",               XrmoptionSepArg, 0 },
+  { "-top",            ".insert",              XrmoptionNoArg, "top" },
+  { "-bottom",         ".insert",              XrmoptionNoArg, "bottom" },
+  { "-both",           ".insert",              XrmoptionNoArg, "both" },
+  { "-density",                ".density",             XrmoptionSepArg, 0 },
+  { 0, 0, 0, 0 }
+};
+
+
+void
+screenhack (Display *dpy, Window window)
+{
+  m_state *state = init_matrix (dpy, window);
+  int delay = get_integer_resource ("delay", "Integer");
+  while (1)
+    {
+      draw_matrix (state);
+      XSync (dpy, False);
+      screenhack_handle_events (dpy);
+      if (delay) usleep (delay);
+    }
+}
index a3a9a840c9c968f572eedf21c772f17ab298967c..ec96853e39367c6f46a662fc03933716a24ff35a 100644 (file)
--- a/setup.com
+++ b/setup.com
@@ -58,6 +58,7 @@ $ noseguy     :== $'mydir'noseguy
 $ pedal                :== $'mydir'pedal
 $ penetrate    :== $'mydir'penetrate
 $ penrose      :== $'mydir'penrose
+$ phosphor     :== $'mydir'phosphor
 $ pyro         :== $'mydir'pyro
 $ qix          :== $'mydir'qix
 $ rd-bomb      :== $'mydir'rd-bomb
@@ -84,6 +85,7 @@ $ worm                :== $'mydir'worm
 $ xflame       :== $'mydir'xflame
 $ xjack                :== $'mydir'xjack
 $ xlyap                :== $'mydir'xlyap
+$ xmatrix      :== $'mydir'xmatrix
 $ xroger       :== $'mydir'xroger
 $ set def [-.DRIVER]
 $ mydir  = mydisk+f$directory()
index b568a24dd11d9379b69034746bc1b855d3bc76ee..698bc9402fbeeec33d63570a0c6d240f2b645355 100644 (file)
@@ -560,7 +560,8 @@ make_uniform_colormap (Display *dpy, Visual *visual, Colormap cmap,
                  0,   S, V,
                  359, S, V,
                  colors, &ncolors,
-                 False, True, wanted_writable);
+                 False, True,
+                  (writable_pP && *writable_pP));
 
   /* If we tried for writable cells and got none, try for non-writable. */
   if (allocate_p && *ncolorsP == 0 && writable_pP && *writable_pP)
index 6e82718df27444a602399a1fd6375a8e443bbba1..ddd415786ab1e6daf7be623cfb05734c15c25a28 100644 (file)
@@ -1,2 +1,2 @@
 static const char screensaver_id[] =
-       "@(#)xscreensaver 3.09 (11-Apr-99), by Jamie Zawinski (jwz@jwz.org)";
+       "@(#)xscreensaver 3.10 (27-Apr-99), by Jamie Zawinski (jwz@jwz.org)";
index dfe67b66de41a4541458799d8d2455ba15299b17..12e7a5b03be6fa6a1b2787d448f09914613b52c1 100644 (file)
@@ -1,7 +1,7 @@
 Begin3
 Title:          xscreensaver
-Version:        3.09
-Entered-date:   11APR99
+Version:        3.10
+Entered-date:   27APR99
 Description:    A modular screen saver and locker for the X Window System.
                 Highly customizable: allows the use of any program that
                 can draw on the root window as a display mode.
@@ -10,16 +10,16 @@ Keywords:       screen saver, screen lock, lock, xlock, X11
 Author:         jwz@jwz.org (Jamie Zawinski)
 Maintained-by:  jwz@jwz.org (Jamie Zawinski)
 Primary-site:   http://www.jwz.org/xscreensaver/
-                1047K xscreensaver-3.09.tar.gz
-                29K  xscreensaver.README
+                1081K xscreensaver-3.10.tar.gz
+                30K  xscreensaver.README
                 1K   xscreensaver.lsm
 Alternate-site: sunsite.unc.edu /pub/Linux/X11/screensavers/
-                1047K xscreensaver-3.09.tar.gz
-                29K  xscreensaver.README
+                1081K xscreensaver-3.10.tar.gz
+                30K  xscreensaver.README
                 1K   xscreensaver.lsm
 Alternate-site: ftp.x.org /contrib/applications/
-                1047K xscreensaver-3.09.tar.gz
-                29K  xscreensaver.README
+                1081K xscreensaver-3.10.tar.gz
+                30K  xscreensaver.README
                 1K   xscreensaver.lsm
 Platforms:      Linux, Irix, SunOS, Solaris, HPUX, AIX, FreeBSD, NetBSD,
                 BSDI, SCO, OSF1, Ultrix, VMS.
index bab9a8fc19ea6c3692af125bb806d08ec7a8da90..c7b265c29a9dc05800cf686e990c21ac64b67635 100644 (file)
@@ -1,7 +1,7 @@
 Name: xscreensaver
 Summary: X screen saver and locker
 Vendor: Jamie Zawinski <jwz@jwz.org>
-Version: 3.09
+Version: 3.10
 Release: 1
 URL: http://www.jwz.org/xscreensaver/
 Source: xscreensaver-%{version}.tar.gz