http://ftp.x.org/contrib/applications/xscreensaver-3.23.tar.gz
authorZygo Blaxell <zblaxell@hungrycats.org>
Mon, 2 Mar 2009 05:42:41 +0000 (00:42 -0500)
committerZygo Blaxell <zblaxell@hungrycats.org>
Mon, 2 Mar 2009 05:42:41 +0000 (00:42 -0500)
-rw-r--r-- 1 zblaxell zblaxell 1272329 Jan 29  2000 xscreensaver-3.23.tar.gz
13b76fa2fa6ce487a11130cb3a1ae58f022ccd18  xscreensaver-3.23.tar.gz

40 files changed:
README
README.debugging
configure
configure.in
driver/XScreenSaver.ad.in
driver/XScreenSaver_ad.h
driver/demo-Gtk.c
driver/demo-Xm-widgets.c
driver/demo-Xm.c
driver/remote.c
driver/subprocs.c
driver/timers.c
driver/xscreensaver-command.man
driver/xscreensaver-demo.man
driver/xscreensaver.c
driver/xscreensaver.kss
driver/xscreensaver.man
hacks/Makefile.in
hacks/compile_axp.com
hacks/compile_decc.com
hacks/epicycle.c
hacks/glx/glplanet.c
hacks/glx/pulsar.c
hacks/glx/sierpinski3d.c
hacks/penetrate.c
hacks/phosphor.c
hacks/ripples.c
hacks/triangle.c
hacks/xmatrix.c
hacks/xmatrix.man
hacks/xspirograph.c [new file with mode: 0644]
hacks/xsublim.c
hacks/xsublim.man
hacks/xteevee.c [new file with mode: 0644]
hacks/xteevee.man [new file with mode: 0644]
setup.com
utils/version.h
utils/yarandom.h
xscreensaver.lsm
xscreensaver.spec

diff --git a/README b/README
index 15d882301a72a26c7db92a0187ec572229dabf85..ebe58b995d25ce1133a494de73e8224737db4a6e 100644 (file)
--- a/README
+++ b/README
@@ -77,6 +77,14 @@ http://www.jwz.org/xscreensaver/.
 
                               ============
 
+Changes since 3.22:   * Fixed some misplaced text fields in the Motif version
+                        of xscreensaver-demo; fixed a crash in the Gtk version
+                        that would happen if the programs list was empty.
+                      * Fixed a recently-introduced bug in `pulsar'.
+                      * Made `sierpinski3d' use solid tetrahedrons instead of
+                        points.
+                     * Added `-trace' option to `xmatrix'.
+                      * Added new hacks `xteevee' and `xspirograph'.
 Changes since 3.21:   * Fixed some bugs in xscreensaver-demo.
                       * Rewrote the Motif version of xscreensaver-demo to
                         match the new Gtk version.
index 006fb5e392857ad7267227ac1bd4adfacb35d8a3..49755066102258ab23555e7b5fa8d9c36c68db87 100644 (file)
@@ -54,14 +54,14 @@ COMPILATION PROBLEMS:
 
     Before doing this, you'll need to nuke `config.cache'.
 
-    If you get errors about not being able to find Motif or Athena (the
-    Xm/ or Xaw/ header files), and you can't find them on your system,
+    If you get errors about not being able to find Motif or Gtk (the
+    Xm/ or gtk/ header files), and you can't find them on your system,
     then your system is horked and your vendor is lame.  Perhaps the
     problem is that you don't have some kind of ``development option''
-    installed.  Xt/ and Xaw/ (Athena) are free and available on all
-    systems; Xm/ (Motif) is available on all commercial systems except
-    SunOS 4.x and some early releases of Solaris.  For Linux and other
-    free Unixes systems, a Motif clone is available from
+    installed.  Xt/is free and available on all systems; Xm/ (Motif)
+    is available on all commercial systems except SunOS 4.x and some
+    early releases of Solaris.  Linux and other free Unixes systems
+    usually come with Gtk, but a Motif clone is also available from
     http://www.lesstif.org/.
 
 RUN-TIME PROBLEMS:
@@ -82,7 +82,7 @@ RUN-TIME PROBLEMS:
            (`xscreensaver-demo'), or in the graphics hacks?
 
         *  If the problem is in the GUI, was it built using
-           Motif, Lesstif, or Athena?  Which version?
+           Motif, Lesstif, or Gtk?  Which version?
 
         *  If the problem is in one (or more) of the hacks, which ones?
            If you're not sure, try running `xscreensaver-demo' to go
index bcedf2cf852f542640a3a5360ca39ff701764e53..c6ce9ec195fb12dae9f699ca515c62fb042b0bec 100755 (executable)
--- a/configure
+++ b/configure
@@ -8683,6 +8683,7 @@ if test \! -z "$libdir" ; then
 fi
 
 
+PREFERRED_DEMO_PROGRAM=xscreensaver-demo-Xm
 ALL_DEMO_PROGRAMS=
 if test "$have_motif" = yes; then
   PREFERRED_DEMO_PROGRAM=xscreensaver-demo-Xm
index 878757cb6c70a0c87da043c6f6e8d3fdf853fff9..15c9635990e79477469815d84bf90da795cc0f82 100644 (file)
@@ -2329,6 +2329,7 @@ if test \! -z "$libdir" ; then
 fi
 
 
+PREFERRED_DEMO_PROGRAM=xscreensaver-demo-Xm
 ALL_DEMO_PROGRAMS=
 if test "$have_motif" = yes; then
   PREFERRED_DEMO_PROGRAM=xscreensaver-demo-Xm
index 389075395d36000b3cad98a78897d17ab889de16..cc1d0685aa5beca8d5564ebf19f242b644277a5a 100644 (file)
@@ -4,8 +4,8 @@
 !            a screen saver and locker for the X window system
 !                            by Jamie Zawinski
 !
-!                              version 3.22
-!                                09-Dec-99
+!                              version 3.23
+!                                30-Jan-00
 !
 ! See "man xscreensaver" for more info.  The latest version is always
 ! available at http://www.jwz.org/xscreensaver/
                                ccurve -root                                \n\
                                blaster -root                               \n\
                                bumps -root                                 \n\
+                               xteevee -root                               \n\
+                               xspirograph -root                           \n\
   color:                       bubbles -root                               \n\
   default-n:                   webcollage -root                            \n\
   default-n:  "WebCollage (whacked)"                                         \
 -      "XMountains (top)"      xmountains -b -M -Z 0 -r 1 -m               \n\
 -                               xaos -root -autopilot -incoloring -1         \
                                   -nogui -outcoloring -1                   \n\
--                              xfishtank -d                                \n
+-                              xfishtank -d                                \n\
+-                              xsnow                                       \n\
+-                              goban -root                                 \n\
+-                              electricsheep                               \n
 
 
 ! To display a randomized slideshow of images, you can do something like this:
@@ -381,7 +386,8 @@ XScreenSaver.bourneShell:           /bin/sh
 *demoDialog*label1.fontList:     *-helvetica-medium-r-*-*-*-140-*-*-*-iso8859-1
 *cmdText.fontList:                 *-courier-medium-r-*-*-*-120-*-*-*-iso8859-1
 *label0.fontList:                  *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1
-*doc.fontList:                   *-helvetica-medium-r-*-*-*-100-*-*-*-iso8859-1
+XScreenSaver*doc.fontList:       *-helvetica-medium-r-*-*-*-100-*-*-*-iso8859-1
+! above must be fully qualified to get around *sgiMode.
 
 *foreground:                   #000000
 *background:                   #C0C0C0
@@ -1048,6 +1054,16 @@ of your desktop, it creates a bump map from it.   Basically, it          \
 3D-izes a roaming section of your desktop, based on color intensity.   \
 Written by Shane Smit.
 
+*hacks.xteevee.name: XTeeVee
+*hacks.xteevee.documentation:                                          \
+XTeeVee simulates various television problems, including static,       \
+loss of vertical hold, and a test pattern.  By Greg Knauss.
+
+*hacks.xspirograph.name: XSpiroGraph
+*hacks.xspirograph.documentation:                                      \
+Simulates that pen-in-nested-plastic-gears toy from your childhood.     \
+By Rohit Singh.
+
 *hacks.webcollage.name: WebCollage
 *hacks.webcollage.documentation:                                       \
 This program makes collages out of random images pulled off of the     \
@@ -1165,7 +1181,7 @@ that come with the GL Extrusion library by Linas Vepstas.
 *hacks.sierpinski3d.name: Sierpinski3D
 *hacks.sierpinski3d.documentation:                                     \
 This draws the three-dimensional variant of the recursive Sierpinski   \
-triangle fractal, using GL.  Written by Tim Robinson.
+triangle fractal, using GL.  Written by Tim Robinson and Jamie Zawinski.
 
 *hacks.ripples.documentation:                                          \
 This draws rippling interference patterns like splashing water.                \
@@ -1206,7 +1222,10 @@ XMountains generates realistic-looking fractal terrains of snow-capped   \
 mountains near water, with either a top view or a side view.           \
 Written by Stephen Booth.  This is not included with the XScreenSaver  \
 package, but if you don't have it already, you can find it at          \
-<http://www.epcc.ed.ac.uk/~spb/xmountains/>.
+<http://www.epcc.ed.ac.uk/~spb/xmountains/>.                           \
+                                                                   \n\n\
+Be sure to compile it with -DVROOT or it won't work right when launched        \
+by the xscreensaver daemon.
 
 *hacks.xaos.name: XaoS
 *hacks.xaos.documentation:                                             \
@@ -1220,3 +1239,26 @@ already, you can find it at <http://limax.paru.cas.cz/~hubicka/XaoS/>.
 Fish!  This is not included with the XScreenSaver package, but if you  \
 don't have it already, you can find it at                               \
 <http://metalab.unc.edu/pub/Linux/X11/demos/>.
+
+*hacks.xsnow.documentation:                                            \
+Draws falling snow and the occasional tiny Santa.  By Rick Jansen.      \
+You can find it at <http://zoutmijn.bpa.nl/rick/Xsnow/>.
+
+*hacks.goban.documentation:                                            \
+Replays historical games of go (aka wei-chi and baduk) on the screen.   \
+By Scott Draves.  You can find it at <http://www.draves.org/goban/>.
+
+*hacks.electricsheep.name: ElectricSheep
+*hacks.electricsheep.documentation:                                    \
+ElectricSheep is an xscreensaver module that displays mpeg video of    \
+an animated fractal flame.  In the background, it contributes render   \
+cycles to the next animation.  Periodically it uploades completed      \
+frames to the server, where they are compressed for distribution to    \
+all clients.                                                           \
+                                                                   \n\n\
+This program is recommended only if you have a high bandwidth          \
+connection to the Internet.                                            \
+                                                                   \n\n\
+By Scott Draves.  You can find it at <http://www.electricsheep.org/>.   \
+See that web site for configuration information.
+
index 2842d032d245b9b4aad0eff97e4b20d61ec570c9..8ed41bbf339f9c966a8ca2fde8b8ab289a8519b5 100644 (file)
                                ccurve -root                                \\n\
                                blaster -root                               \\n\
                                bumps -root                                 \\n\
+                               xteevee -root                               \\n\
+                               xspirograph -root                           \\n\
   color:                       bubbles -root                               \\n\
   default-n:                   webcollage -root                            \\n\
   default-n:  \"WebCollage (whacked)\"                                       \
 -      \"XMountains (top)\"    xmountains -b -M -Z 0 -r 1 -m               \\n\
 -                               xaos -root -autopilot -incoloring -1         \
                                   -nogui -outcoloring -1                   \\n\
--                              xfishtank -d                                \\n",
+-                              xfishtank -d                                \\n\
+-                              xsnow                                       \\n\
+-                              goban -root                                 \\n\
+-                              electricsheep                               \\n",
 "XScreenSaver.pointerPollTime:         5",
 "XScreenSaver.initialDelay:            0",
 "XScreenSaver.windowCreationTimeout:   30",
 "*demoDialog*label1.fontList:     *-helvetica-medium-r-*-*-*-140-*-*-*-iso8859-1",
 "*cmdText.fontList:                 *-courier-medium-r-*-*-*-120-*-*-*-iso8859-1",
 "*label0.fontList:                  *-helvetica-bold-r-*-*-*-140-*-*-*-iso8859-1",
-"*doc.fontList:                   *-helvetica-medium-r-*-*-*-100-*-*-*-iso8859-1",
+"XScreenSaver*doc.fontList:       *-helvetica-medium-r-*-*-*-100-*-*-*-iso8859-1",
 "*foreground:                  #000000",
 "*background:                  #C0C0C0",
 "*XmTextField.foreground:      #000000",
@@ -776,6 +781,14 @@ A bit like `Spotlight', except that instead of merely exposing part        \
 of your desktop, it creates a bump map from it.         Basically, it          \
 3D-izes a roaming section of your desktop, based on color intensity.   \
 Written by Shane Smit.",
+"*hacks.xteevee.name: XTeeVee",
+"*hacks.xteevee.documentation:                                         \
+XTeeVee simulates various television problems, including static,       \
+loss of vertical hold, and a test pattern.  By Greg Knauss.",
+"*hacks.xspirograph.name: XSpiroGraph",
+"*hacks.xspirograph.documentation:                                     \
+Simulates that pen-in-nested-plastic-gears toy from your childhood.     \
+By Rohit Singh.",
 "*hacks.webcollage.name: WebCollage",
 "*hacks.webcollage.documentation:                                      \
 This program makes collages out of random images pulled off of the     \
@@ -874,7 +887,7 @@ that come with the GL Extrusion library by Linas Vepstas.",
 "*hacks.sierpinski3d.name: Sierpinski3D",
 "*hacks.sierpinski3d.documentation:                                    \
 This draws the three-dimensional variant of the recursive Sierpinski   \
-triangle fractal, using GL.  Written by Tim Robinson.",
+triangle fractal, using GL.  Written by Tim Robinson and Jamie Zawinski.",
 "*hacks.ripples.documentation:                                         \
 This draws rippling interference patterns like splashing water.                \
 With the -water option, it manipulates your desktop image to look      \
@@ -903,7 +916,10 @@ XMountains generates realistic-looking fractal terrains of snow-capped     \
 mountains near water, with either a top view or a side view.           \
 Written by Stephen Booth.  This is not included with the XScreenSaver  \
 package, but if you don't have it already, you can find it at          \
-<http://www.epcc.ed.ac.uk/~spb/xmountains/>.",
+<http://www.epcc.ed.ac.uk/~spb/xmountains/>.                           \
+                                                                   \\n\\n\
+Be sure to compile it with -DVROOT or it won't work right when launched        \
+by the xscreensaver daemon.",
 "*hacks.xaos.name: XaoS",
 "*hacks.xaos.documentation:                                            \
 XaoS generates fast fly-through animations of the Mandelbrot and other \
@@ -915,3 +931,22 @@ already, you can find it at <http://limax.paru.cas.cz/~hubicka/XaoS/>.",
 Fish!  This is not included with the XScreenSaver package, but if you  \
 don't have it already, you can find it at                               \
 <http://metalab.unc.edu/pub/Linux/X11/demos/>.",
+"*hacks.xsnow.documentation:                                           \
+Draws falling snow and the occasional tiny Santa.  By Rick Jansen.      \
+You can find it at <http://zoutmijn.bpa.nl/rick/Xsnow/>.",
+"*hacks.goban.documentation:                                           \
+Replays historical games of go (aka wei-chi and baduk) on the screen.   \
+By Scott Draves.  You can find it at <http://www.draves.org/goban/>.",
+"*hacks.electricsheep.name: ElectricSheep",
+"*hacks.electricsheep.documentation:                                   \
+ElectricSheep is an xscreensaver module that displays mpeg video of    \
+an animated fractal flame.  In the background, it contributes render   \
+cycles to the next animation.  Periodically it uploades completed      \
+frames to the server, where they are compressed for distribution to    \
+all clients.                                                           \
+                                                                   \\n\\n\
+This program is recommended only if you have a high bandwidth          \
+connection to the Internet.                                            \
+                                                                   \\n\\n\
+By Scott Draves.  You can find it at <http://www.electricsheep.org/>.   \
+See that web site for configuration information.",
index 4b1a44fa2fa0927f3df85c9abc802a2d16fa9ad8..e027622726179ec964043ce7a4009d6e2a588bb6 100644 (file)
@@ -186,6 +186,9 @@ ensure_selected_item_visible (GtkWidget *widget)
   ratio_t = ((double) child_y) / ((double) children_h);
   ratio_b = ((double) child_y + child_h) / ((double) children_h);
 
+  if (adj->upper == 0.0)  /* no items in list */
+    return;
+
   if (ratio_t < (adj->value / adj->upper) ||
       ratio_b > ((adj->value + adj->page_size) / adj->upper))
     {
@@ -714,7 +717,7 @@ run_prev_cb (GtkButton *button, gpointer user_data)
    this parses the text, and does error checking.
  */
 static void 
-hack_time_text (const char *line, Time *store, Bool sec_p)
+hack_time_text (GtkWidget *widget, const char *line, Time *store, Bool sec_p)
 {
   if (*line)
     {
@@ -722,7 +725,14 @@ hack_time_text (const char *line, Time *store, Bool sec_p)
       value = parse_time ((char *) line, sec_p, True);
       value *= 1000;   /* Time measures in microseconds */
       if (value < 0)
-        /* gdk_beep () */;
+       {
+         char b[255];
+         sprintf (b,
+                  "Error:\n\n"
+                  "Unparsable time format: \"%s\"\n",
+                  line);
+         warning_dialog (widget, b, 100);
+       }
       else
        *store = value;
     }
@@ -740,13 +750,13 @@ prefs_ok_cb (GtkButton *button, gpointer user_data)
   Bool changed = False;
 
 # define SECONDS(field, name) \
-  hack_time_text (gtk_entry_get_text (\
+  hack_time_text (GTK_WIDGET(button), gtk_entry_get_text (\
                     GTK_ENTRY (name_to_widget (GTK_WIDGET(button), (name)))), \
                   (field), \
                   True)
 
 # define MINUTES(field, name) \
-  hack_time_text (gtk_entry_get_text (\
+  hack_time_text (GTK_WIDGET(button), gtk_entry_get_text (\
                     GTK_ENTRY (name_to_widget (GTK_WIDGET(button), (name)))), \
                   (field), \
                   False)
@@ -759,7 +769,11 @@ prefs_ok_cb (GtkButton *button, gpointer user_data)
     if (! *line) \
       ; \
     else if (sscanf (line, "%u%c", &value, &c) != 1) \
-     gdk_beep(); \
+      { \
+       char b[255]; \
+       sprintf (b, "Error:\n\n" "Not an integer: \"%s\"\n", line); \
+       warning_dialog (GTK_WIDGET (button), b, 100); \
+      } \
    else \
      *(field) = value; \
   } while(0)
@@ -932,6 +946,7 @@ make_pretty_name (const char *shell_command)
 static void
 scroll_to_current_hack (GtkWidget *toplevel, prefs_pair *pair)
 {
+  saver_preferences *p =  pair->a;
   Atom type;
   int format;
   unsigned long nitems, bytesafter;
@@ -958,9 +973,12 @@ scroll_to_current_hack (GtkWidget *toplevel, prefs_pair *pair)
 
   list = GTK_LIST (name_to_widget (toplevel, "list"));
   apply_changes_and_save (toplevel);
-  gtk_list_select_item (list, which);
-  ensure_selected_item_visible (GTK_WIDGET (list));
-  populate_demo_window (toplevel, which, pair);
+  if (which < p->screenhacks_count)
+    {
+      gtk_list_select_item (list, which);
+      ensure_selected_item_visible (GTK_WIDGET (list));
+      populate_demo_window (toplevel, which, pair);
+    }
 }
 
 
@@ -973,7 +991,7 @@ populate_hack_list (GtkWidget *toplevel, prefs_pair *pair)
   screenhack **hacks = p->screenhacks;
   screenhack **h;
 
-  for (h = hacks; *h; h++)
+  for (h = hacks; h && *h; h++)
     {
       GtkWidget *line;
       char *pretty_name = (h[0]->name
@@ -1385,7 +1403,8 @@ static void
 populate_demo_window (GtkWidget *toplevel, int which, prefs_pair *pair)
 {
   saver_preferences *p = pair->a;
-  screenhack *hack = (which >= 0 ? p->screenhacks[which] : 0);
+  screenhack *hack = (which >= 0 && which < p->screenhacks_count
+                     ? p->screenhacks[which] : 0);
   GtkFrame *frame = GTK_FRAME (name_to_widget (toplevel, "frame"));
   GtkLabel *doc = GTK_LABEL (name_to_widget (toplevel, "doc"));
   GtkEntry *cmd = GTK_ENTRY (name_to_widget (toplevel, "cmd_text"));
@@ -1779,6 +1798,7 @@ main (int argc, char **argv)
        prefs = True;
       else
        {
+         fprintf (stderr, "%s: unknown option: %s\n", real_progname, argv[i]);
          fprintf (stderr, "usage: %s [ -display dpy-string ] [ -prefs ]\n",
                   real_progname);
          exit (1);
index 63c3d9b0aea71a4f4a0e3f4a868db374bdce49a9..80094ca53ebb63572c93c5bfe6e49d6a7f34f8a1 100644 (file)
 #include <Xm/TextF.h>
 #include <Xm/ToggleBG.h>
 #include <Xm/CascadeBG.h>
-#ifdef HAVE_XMCOMBOBOX
-# include <Xm/ComboBox.h>
-#endif
 #include <Xm/RowColumn.h>
 #include <Xm/LabelG.h>
 #include <Xm/SeparatoG.h>
 #include <Xm/SelectioB.h>
 
+#ifdef HAVE_XMCOMBOBOX         /* a Motif 2.0 widget */
+# include <Xm/ComboBox.h>
+# ifndef XmNtextField          /* Lesstif 0.89.4 bug */
+#  undef HAVE_XMCOMBOBOX
+# endif
+#endif /* HAVE_XMCOMBOBOX */
+
 #include <stdio.h>
 
 
+
 const char *visual_menu[] = {
   "Any", "Best", "Default", "Default-N", "GL", "TrueColor", "PseudoColor",
   "StaticGray", "GrayScale", "DirectColor", "Color", "Gray", "Mono", 0 
@@ -504,9 +509,9 @@ create_options_page (Widget parent)
   fade_text = XmCreateTextField (preferences_form, "fadeSecondsText", av, ac);
   fade_ticks_text = XmCreateTextField (preferences_form, "fadeTicksText",
                                        av, ac);
-  lock_timeout_text = XmCreateTextField (preferences_form, "passwdText",
+  lock_timeout_text = XmCreateTextField (preferences_form, "lockText",
                                          av, ac);
-  passwd_timeout_text = XmCreateTextField (preferences_form, "lockText",
+  passwd_timeout_text = XmCreateTextField (preferences_form, "passwdText",
                                            av, ac);
   XtSetArg(av[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
   verbose_toggle = XmCreateToggleButtonGadget (preferences_form,
index aadbd0b9658e242f6ea61e145b3879a386876b36..9d4c31d53b65f63db0dfc0643482b73f952fa212 100644 (file)
 #include <Xm/RowColumn.h>
 #include <Xm/MessageB.h>
 
+#ifdef HAVE_XMCOMBOBOX         /* a Motif 2.0 widget */
+# include <Xm/ComboBox.h>
+# ifndef XmNtextField          /* Lesstif 0.89.4 bug */
+#  undef HAVE_XMCOMBOBOX
+# endif
+#endif /* HAVE_XMCOMBOBOX */
+
 #include "version.h"
 #include "prefs.h"
 #include "resources.h"         /* for parse_time() */
@@ -461,10 +468,10 @@ apply_changes_and_save (Widget widget)
 
   Widget vis = name_to_widget (widget, "combo");
 # ifdef HAVE_XMCOMBOBOX
-  Widget text;
+  Widget text = 0;
 # else /* !HAVE_XMCOMBOBOX */
   Widget menu = 0, *kids = 0, selected_item = 0;
-  Cardinal nkids;
+  Cardinal nkids = 0;
   int i = 0;
 # endif /* !HAVE_XMCOMBOBOX */
 
@@ -479,6 +486,9 @@ apply_changes_and_save (Widget widget)
 
 # ifdef HAVE_XMCOMBOBOX
   XtVaGetValues (vis, XmNtextField, &text, 0);
+  if (!text)
+    /* If we can't get at the text field of this combo box, we're screwed. */
+    abort();
   XtVaGetValues (text, XmNvalue, &visual, 0);
 
 # else /* !HAVE_XMCOMBOBOX */
@@ -674,7 +684,7 @@ run_prev_cb (Widget button, XtPointer client_data, XtPointer ignored)
    this parses the text, and does error checking.
  */
 static void 
-hack_time_text (const char *line, Time *store, Bool sec_p)
+hack_time_text (Widget button, const char *line, Time *store, Bool sec_p)
 {
   if (*line)
     {
@@ -682,7 +692,14 @@ hack_time_text (const char *line, Time *store, Bool sec_p)
       value = parse_time ((char *) line, sec_p, True);
       value *= 1000;   /* Time measures in microseconds */
       if (value < 0)
-        /* gdk_beep () */;
+       {
+         char b[255];
+         sprintf (b,
+                  "Error:\n\n"
+                  "Unparsable time format: \"%s\"\n",
+                  line);
+         warning_dialog (XtParent (button), b, 100);
+       }
       else
        *store = value;
     }
@@ -704,12 +721,12 @@ prefs_ok_cb (Widget button, XtPointer client_data, XtPointer ignored)
 # define SECONDS(field, name) \
   v = 0; \
   XtVaGetValues (name_to_widget (button, (name)), XtNvalue, &v, 0); \
-  hack_time_text (v, (field), True)
+  hack_time_text (button, v, (field), True)
 
 # define MINUTES(field, name) \
   v = 0; \
   XtVaGetValues (name_to_widget (button, (name)), XtNvalue, &v, 0); \
-  hack_time_text (v, (field), False)
+  hack_time_text (button, v, (field), False)
 
 # define INTEGER(field, name) do { \
     unsigned int value; \
@@ -718,7 +735,11 @@ prefs_ok_cb (Widget button, XtPointer client_data, XtPointer ignored)
     if (! *v) \
       ; \
     else if (sscanf (v, "%u%c", &value, &c) != 1) \
-     XBell(XtDisplay(button), 0); \
+      { \
+       char b[255]; \
+       sprintf (b, "Error:\n\n" "Not an integer: \"%s\"\n", v); \
+       warning_dialog (XtParent (button), b, 100); \
+      } \
    else \
      *(field) = value; \
   } while(0)
index b8ab8e15087fd79a5b594af177c80063bfedd975..592d5d03ec75206c7262865e29f678b601eb8b86 100644 (file)
@@ -82,7 +82,7 @@ find_screensaver_window (Display *dpy, char **version)
   if (parent)
     abort ();
   if (! (kids && nkids))
-    abort ();
+    return 0;
   for (i = 0; i < nkids; i++)
     {
       Atom type;
index 256934b891ce8d5dea5f1341cdc013f89e5c73b9..ad2a426adbafe43f894ecdd625776e8a069b2bf6 100644 (file)
@@ -906,8 +906,8 @@ spawn_screenhack (saver_info *si, Bool first_time_p)
     }
   else if (si->prefs.verbose_p)
     fprintf (stderr,
-             "%s: server reports that monitor has powered down; "
-             "not launching a new hack.\n", blurb());
+             "%s: X says monitor has powered down; "
+             "not launching a hack.\n", blurb());
 
   store_saver_status (si);  /* store current hack numbers */
 }
@@ -965,15 +965,14 @@ emergency_kill_subproc (saver_info *si)
 Bool
 screenhack_running_p (saver_info *si)
 {
-  Bool result = True;
+  Bool any_running_p = False;
   int i;
   for (i = 0; i < si->nscreens; i++)
     {
       saver_screen_info *ssi = &si->screens[i];
-      if (!ssi->pid)
-       result = False;
+      if (ssi->pid) any_running_p = True;
     }
-  return result;
+  return any_running_p;
 }
 
 \f
index 61a0155d097f26d2d73d1224d877ae2d1acc9e4b..1dbdeff6706481a32ba9a99697a26cf44284bf06 100644 (file)
@@ -230,8 +230,6 @@ cycle_timer (XtPointer closure, XtIntervalId *id)
   else
     {
       maybe_reload_init_file (si);
-      if (p->verbose_p)
-       fprintf (stderr, "%s: changing graphics hacks.\n", blurb());
       kill_screenhack (si);
 
       if (!si->throttled_p)
@@ -1099,11 +1097,12 @@ watchdog_timer (XtPointer closure, XtIntervalId *id)
           raise_window (si, True, True, running_p);
         }
 
-      if (!monitor_powered_on_p (si))
+      if (screenhack_running_p (si) &&
+          !monitor_powered_on_p (si))
        {
          if (si->prefs.verbose_p)
            fprintf (stderr,
-                    "%s: server reports that monitor has powered down; "
+                    "%s: X says monitor has powered down; "
                     "killing running hacks.\n", blurb());
          kill_screenhack (si);
        }
index 4e8f1766dd443f747cd5458c58e4672ecde34abb..e6d20a48fd3163e8a21d4d75a9f2fcc3f84682e2 100644 (file)
@@ -11,7 +11,7 @@
 .if n .sp 1
 .if t .sp .5
 ..
-.TH XScreenSaver 1 "09-Dec-99 (3.22)" "X Version 11"
+.TH XScreenSaver 1 "30-Jan-00 (3.23)" "X Version 11"
 .SH NAME
 xscreensaver-command - control a running xscreensaver process
 .SH SYNOPSIS
index 5e055779fc4cf64325730c2a8fb8052ee4219853..2d974f029cb2b9edbe3797d3124176f8ece9e446 100644 (file)
@@ -11,7 +11,7 @@
 .if n .sp 1
 .if t .sp .5
 ..
-.TH XScreenSaver 1 "09-Dec-99 (3.22)" "X Version 11"
+.TH XScreenSaver 1 "30-Jan-00 (3.23)" "X Version 11"
 .SH NAME
 xscreensaver-demo - interactively control the background xscreensaver daemon
 .SH SYNOPSIS
index a799ab3ad585f93c0e260a9780246703b8aa9973..9b26390bd6b40c092003ed5e65d192cac371fa42 100644 (file)
@@ -996,6 +996,20 @@ main_loop (saver_info *si)
            si->dbox_up_p = False;
            XDefineCursor (si->dpy, ssi->screensaver_window, ssi->cursor);
            suspend_screenhack (si, False);     /* resume */
+
+            if (!ok_to_unblank &&
+                !screenhack_running_p (si))
+              {
+                /* If the lock dialog has been dismissed and we're not about to
+                   unlock the screen, and there is currently no hack running,
+                   then launch one.  (There might be no hack running if DPMS
+                   had kicked in.  But DPMS is off now, so bring back the hack)
+                 */
+                if (si->cycle_id)
+                  XtRemoveTimeOut (si->cycle_id);
+                si->cycle_id = 0;
+                cycle_timer ((XtPointer) si, 0);
+              }
          }
 #endif /* !NO_LOCKING */
 
index 98ad08ebfbc8a2469cccee7108d7598b787b534e..dac4d9841ca9c7687f4b3f950449078044814788 100755 (executable)
@@ -112,15 +112,8 @@ if [ -n "$Install" ] ; then
   trap "kill $!" SIGTERM                                # Set these to kill the daemon
   trap "kill $!" SIGKILL
 
-  if [ -f "/etc/shadow" ]; then
-    # xscreensaver is run as the user, which has no access to the /etc/shadow file.  Other
-    # .kss screensavers use kcheckpass, which would have to be hacked into xscreensaver to
-    # work correctly. This just activates the screensaver with no password lock.
-    trap "/usr/X11R6/bin/xscreensaver-command -activate" SIGUSR1
-  else
-    # xscreensaver can be locked, because it can read the /etc/passwd file.
-    trap "/usr/X11R6/bin/xscreensaver-command -lock" SIGUSR1
-  fi
+# KDE sends SIGUSER1 to indicate the user has hit the "lock" button.
+  trap "/usr/X11R6/bin/xscreensaver-command -lock" SIGUSR1
 
   wait $!                                               # Do not exit, just wait for signals.
 
index 4ea3794930b360febd6b9f0f468eb18793d539a6..272f93e59367df19aa63bb641a3b0e5e8b01eebc 100644 (file)
@@ -11,7 +11,7 @@
 .if n .sp 1
 .if t .sp .5
 ..
-.TH XScreenSaver 1 "09-Dec-99 (3.22)" "X Version 11"
+.TH XScreenSaver 1 "30-Jan-00 (3.23)" "X Version 11"
 .SH NAME
 xscreensaver - graphics hack and screen locker, launched when the user is idle
 .SH SYNOPSIS
index d51a7252a257871ad6af872ba3849a211c29ca62..5da1b76af0bd2b55e7b2218bd6355db16bc687ed 100644 (file)
@@ -30,6 +30,7 @@ DEPEND_DEFINES        = @DEPEND_DEFINES@
 SHELL          = /bin/sh
 INSTALL                = @INSTALL@
 INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT  = @INSTALL_PROGRAM@
 INSTALL_DATA   = @INSTALL_DATA@
 INSTALL_DIRS   = @INSTALL_DIRS@
 HACKDIR                = @HACKDIR@
@@ -85,7 +86,7 @@ SRCS          = attraction.c blitspin.c bouboule.c braid.c bubbles.c \
                  sonar.c demon.c loop.c t3d.c penetrate.c deluxe.c compass.c \
                  squiral.c xflame.c wander.c spotlight.c critical.c \
                  phosphor.c xmatrix.c petri.c shadebobs.c xsublim.c ccurve.c \
-                 blaster.c bumps.c ripples.c
+                 blaster.c bumps.c ripples.c xteevee.c xspirograph.c
 SCRIPTS                = vidwhacker webcollage
 
 OBJS           = attraction.o blitspin.o bouboule.o braid.o bubbles.o \
@@ -104,7 +105,7 @@ OBJS                = attraction.o blitspin.o bouboule.o braid.o bubbles.o \
                  sonar.o demon.o loop.o t3d.o penetrate.o deluxe.o compass.o \
                  squiral.o xflame.o wander.o spotlight.o critical.o \
                  phosphor.o xmatrix.o petri.o shadebobs.o xsublim.o ccurve.o \
-                 blaster.o bumps.o ripples.o
+                 blaster.o bumps.o ripples.o xteevee.o xspirograph.o
 
 EXES           = attraction blitspin bouboule braid bubbles decayscreen deco \
                  drift flag flame forest vines galaxy grav greynetic halo \
@@ -117,7 +118,8 @@ EXES                = attraction blitspin bouboule braid bubbles decayscreen deco \
                  interference truchet bsod crystal discrete distort kumppa \
                  sonar demon loop t3d penetrate deluxe compass squiral \
                  xflame wander spotlight critical phosphor xmatrix petri \
-                 shadebobs xsublim ccurve blaster bumps ripples
+                 shadebobs xsublim ccurve blaster bumps ripples xteevee \
+                 xspirograph
 
 HACK_OBJS_1    = $(UTILS_BIN)/resources.o $(UTILS_BIN)/visual.o \
                  $(UTILS_BIN)/usleep.o $(UTILS_BIN)/yarandom.o @XMU_OBJS@
@@ -145,7 +147,7 @@ MEN         = attraction.man blitspin.man bouboule.man braid.man \
                  xjack.man xlyap.man jigsaw.man epicycle.man bsod.man \
                  sonar.man t3d.man squiral.man spotlight.man critical.man \
                  vidwhacker.man webcollage.man xsublim.man distort.man \
-                 phosphor.man xmatrix.man
+                 phosphor.man xmatrix.man xteevee.man
 STAR           = *
 EXTRAS         = README Makefile.in xlock_23.h .gdbinit \
                  images/$(STAR).xbm \
@@ -189,9 +191,9 @@ install-scripts: $(SCRIPTS) munge-scripts
          else                                                          \
            p=$(srcdir)/$$program ;                                     \
          fi ;                                                          \
-         echo $(INSTALL_PROGRAM) $$p                                   \
+         echo $(INSTALL_SCRIPT) $$p                                    \
            $(install_prefix)$(HACKDIR)/$$program ;                     \
-         $(INSTALL_PROGRAM) $$p                                        \
+         $(INSTALL_SCRIPT) $$p                                         \
            $(install_prefix)$(HACKDIR)/$$program ;                     \
        done
 
@@ -560,6 +562,12 @@ bumps:             bumps.o         $(HACK_OBJS) $(GRAB)
 ripples:       ripples.o       $(HACK_OBJS) $(SHM) $(GRAB)
        $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(SHM) $(GRAB) $(HACK_LIBS) $(GRAB_LIBS)
 
+xteevee:       xteevee.o       $(HACK_OBJS) $(GRAB)
+       $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(GRAB) $(HACK_LIBS) $(GRAB_LIBS)
+
+xspirograph:   xspirograph.o   $(HACK_OBJS) $(COL) $(ERASE)
+       $(CC_HACK) -o $@ $@.o   $(HACK_OBJS) $(COL) $(ERASE) $(HACK_LIBS)
+
 
 # The rules for those hacks which follow the `xlockmore' API.
 #
@@ -1710,8 +1718,8 @@ shadebobs.o: $(UTILS_SRC)/hsv.h
 shadebobs.o: $(UTILS_SRC)/colors.h
 shadebobs.o: $(UTILS_SRC)/grabscreen.h
 shadebobs.o: $(UTILS_SRC)/visual.h
-xsublim.o: $(UTILS_SRC)/yarandom.h
 xsublim.o: $(UTILS_SRC)/usleep.h
+xsublim.o: $(UTILS_SRC)/yarandom.h
 xsublim.o: $(UTILS_SRC)/resources.h
 ccurve.o: $(srcdir)/screenhack.h
 ccurve.o: ../config.h
@@ -1752,4 +1760,23 @@ ripples.o: $(UTILS_SRC)/colors.h
 ripples.o: $(UTILS_SRC)/grabscreen.h
 ripples.o: $(UTILS_SRC)/visual.h
 ripples.o: $(UTILS_SRC)/xshm.h
+xteevee.o: $(srcdir)/screenhack.h
+xteevee.o: ../config.h
+xteevee.o: $(UTILS_SRC)/yarandom.h
+xteevee.o: $(UTILS_SRC)/usleep.h
+xteevee.o: $(UTILS_SRC)/resources.h
+xteevee.o: $(UTILS_SRC)/hsv.h
+xteevee.o: $(UTILS_SRC)/colors.h
+xteevee.o: $(UTILS_SRC)/grabscreen.h
+xteevee.o: $(UTILS_SRC)/visual.h
+xspirograph.o: $(srcdir)/screenhack.h
+xspirograph.o: ../config.h
+xspirograph.o: $(UTILS_SRC)/yarandom.h
+xspirograph.o: $(UTILS_SRC)/usleep.h
+xspirograph.o: $(UTILS_SRC)/resources.h
+xspirograph.o: $(UTILS_SRC)/hsv.h
+xspirograph.o: $(UTILS_SRC)/colors.h
+xspirograph.o: $(UTILS_SRC)/grabscreen.h
+xspirograph.o: $(UTILS_SRC)/visual.h
+xspirograph.o: $(UTILS_SRC)/erase.h
 
index 8209dc111ef1cc4dcb30ef64ab94e7b827ab3d50..9d1922cab626fc6f96686cf82dd2463d9cbfee9d 100644 (file)
@@ -92,5 +92,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]) 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)/INCL=([],[-],[-.UTILS]) XSPIROGRAPH.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XSUBLIM.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XTEEVEE.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE,XLOCKMORE)/INCL=([],[-],[-.UTILS])/OBJ=SCREENHACK-XLOCK.OBJ SCREENHACK.C
index 8209dc111ef1cc4dcb30ef64ab94e7b827ab3d50..9d1922cab626fc6f96686cf82dd2463d9cbfee9d 100644 (file)
@@ -92,5 +92,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]) 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)/INCL=([],[-],[-.UTILS]) XSPIROGRAPH.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XSUBLIM.C
+$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE)/INCL=([],[-],[-.UTILS]) XTEEVEE.C
 $ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H,STANDALONE,XLOCKMORE)/INCL=([],[-],[-.UTILS])/OBJ=SCREENHACK-XLOCK.OBJ SCREENHACK.C
index 3732cb8e2ff49644b10223968880b67fa60f91d4..9d355c3127b5010e43e35a4721e41cacc879cb1a 100644 (file)
@@ -266,7 +266,10 @@ new_circle_chain(void)
   
   /* There are between minCircles and maxCircles in each figure.
    */
-  n = minCircles + random() % (maxCircles - minCircles);
+  if (maxCircles == minCircles)
+    n = minCircles;            /* Avoid division by zero. */
+  else
+    n = minCircles + random() % (maxCircles - minCircles);
   
   head = NULL;
   while (n--)
index d20bb409ca8eba6f251b3c4e5aa5f5a715ecb366..f7d02557b4f6c1ae96cc6eae9182ae23fcd6d3f6 100644 (file)
@@ -422,10 +422,10 @@ void generate_stars(int width, int height)
   glBegin(GL_POINTS);
   for(i = 0 ; i < NUM_STARS ; i++)
        {
-/*       size = (drand48()+size_range[0]) * size_range[1]/2.; */
+/*       size = ((random()%size_range[0])) * size_range[1]/2.; */
 /*    glPointSize(size); */
-         x = random()*width;
-         y = random()*height;
+         x = random() % width;
+         y = random() % height;
          glVertex2f(x,y);
        }
   glEnd();
index 8d7260d52bacafe91b7014c7eeb5e52335d57b93..8129f903803dd733e053bf412d2d5c8ac63d4d63 100644 (file)
@@ -654,8 +654,8 @@ void GenerateQuad(void)
       quads[i].ty = 0.;
       quads[i].tz = -10;
 
-      quads[i].drx = random() * 5.;
-      quads[i].dry = random() * 5.;
+      quads[i].drx = frand(5.0);
+      quads[i].dry = frand(5.0);
       quads[i].drz = 0;
     }
 }
index 9a783a04794600165780e6b80f64ef05f3fa6b53..d11daf1aeed98a98498b861af1262f56744baff5 100644 (file)
@@ -22,6 +22,9 @@ static const char sccsid[] = "@(#)sierpinski3D.c      00.01 99/11/04 xlockmore";
  * Revision History:
  * 1999: written by Tim Robinson <the_luggage@bigfoot.com>
  *       a 3-D representation of the Sierpinski gasket fractal.
+ *
+ * 10-Dec-99  jwz   rewrote to draw a set of tetrahedrons instead of a
+ *                  random scattering of points.
  */
 
 /*-
@@ -38,7 +41,9 @@ static const char sccsid[] = "@(#)sierpinski3D.c      00.01 99/11/04 xlockmore";
 # define gasket_opts                           xlockmore_opts
 # define DEFAULTS      "*count:                1       \n"                     \
                        "*cycles:               9999    \n"                     \
-                       "*delay:                100     \n"                     \
+                       "*delay:                8000    \n"                     \
+                       "*maxDepth:             5       \n"                     \
+                       "*speed:                150     \n"                     \
                        "*wireframe:    False   \n"
 # include "xlockmore.h"                /* from the xscreensaver distribution */
 #else  /* !STANDALONE */
@@ -47,8 +52,23 @@ static const char sccsid[] = "@(#)sierpinski3D.c     00.01 99/11/04 xlockmore";
 
 #ifdef USE_GL
 
-ModeSpecOpt gasket_opts =
-{0, NULL, 0, NULL, NULL};
+#undef countof
+#define countof(x) (sizeof((x))/sizeof((*x)))
+
+static int max_depth;
+static int speed;
+static XrmOptionDescRec opts[] = {
+  {"-depth", ".sierpinski3d.maxDepth", XrmoptionSepArg, (caddr_t) 0 },
+  {"-speed", ".sierpinski3d.speed",    XrmoptionSepArg, (caddr_t) 0 }
+};
+
+static argtype vars[] = {
+  {(caddr_t *) &max_depth, "maxDepth", "MaxDepth", "5", t_Int},
+  {(caddr_t *) &speed,     "speed",    "Speed",   "150", t_Int},
+};
+
+
+ModeSpecOpt gasket_opts = {countof(opts), opts, countof(vars), vars, NULL};
 
 #ifdef USE_MODULES
 ModStruct   gasket_description =
@@ -74,9 +94,9 @@ typedef struct {
   GLuint      gasket1;
   GLXContext *glx_context;
   Window      window;
-#if 0
-  Window      win;
-#endif
+
+  int current_depth;
+
 } gasketstruct;
 
 static gasketstruct *gasket = NULL;
@@ -85,11 +105,205 @@ static gasketstruct *gasket = NULL;
 
 /* static GLuint limit; */
 
+\f
+/* Computing normal vectors (thanks to Nat Friedman <ndf@mit.edu>)
+ */
+
+typedef struct vector {
+  GLfloat x, y, z;
+} vector;
+
+typedef struct plane {
+  vector p1, p2, p3;
+} plane;
+
+static void
+vector_set(vector *v, GLfloat x, GLfloat y, GLfloat z)
+{
+  v->x = x;
+  v->y = y;
+  v->z = z;
+}
+
+static void
+vector_cross(vector v1, vector v2, vector *v3)
+{
+  v3->x = (v1.y * v2.z) - (v1.z * v2.y);
+  v3->y = (v1.z * v2.x) - (v1.x * v2.z);
+  v3->z = (v1.x * v2.y) - (v1.y * v2.x);
+}
+
+static void
+vector_subtract(vector v1, vector v2, vector *res)
+{
+  res->x = v1.x - v2.x;
+  res->y = v1.y - v2.y;
+  res->z = v1.z - v2.z;
+}
+
+static void
+plane_normal(plane p, vector *n)
+{
+  vector v1, v2;
+  vector_subtract(p.p1, p.p2, &v1);
+  vector_subtract(p.p1, p.p3, &v2);
+  vector_cross(v2, v1, n);
+}
+
+static void
+do_normal(GLfloat x1, GLfloat y1, GLfloat z1,
+         GLfloat x2, GLfloat y2, GLfloat z2,
+         GLfloat x3, GLfloat y3, GLfloat z3)
+{
+  plane plane;
+  vector n;
+  vector_set(&plane.p1, x1, y1, z1);
+  vector_set(&plane.p2, x2, y2, z2);
+  vector_set(&plane.p3, x3, y3, z3);
+  plane_normal(plane, &n);
+  n.x = -n.x; n.y = -n.y; n.z = -n.z;
+
+  glNormal3f(n.x, n.y, n.z);
+
+#ifdef DEBUG
+  /* Draw a line in the direction of this face's normal. */
+  {
+    GLfloat ax = n.x > 0 ? n.x : -n.x;
+    GLfloat ay = n.y > 0 ? n.y : -n.y;
+    GLfloat az = n.z > 0 ? n.z : -n.z;
+    GLfloat mx = (x1 + x2 + x3) / 3;
+    GLfloat my = (y1 + y2 + y3) / 3;
+    GLfloat mz = (z1 + z2 + z3) / 3;
+    GLfloat xx, yy, zz;
+
+    GLfloat max = ax > ay ? ax : ay;
+    if (az > max) max = az;
+    max *= 2;
+    xx = n.x / max;
+    yy = n.y / max;
+    zz = n.z / max;
+
+    glBegin(GL_LINE_LOOP);
+    glVertex3f(mx, my, mz);
+    glVertex3f(mx+xx, my+yy, mz+zz);
+    glEnd();
+  }
+#endif /* DEBUG */
+}
+
+\f
+
+static void
+triangle (GLfloat x1, GLfloat y1, GLfloat z1,
+          GLfloat x2, GLfloat y2, GLfloat z2,
+          GLfloat x3, GLfloat y3, GLfloat z3,
+          Bool wireframe_p)
+{
+  if (wireframe_p)
+    glBegin (GL_LINE_LOOP);
+  else
+    {
+      do_normal (x1, y1, z1,  x2, y2, z2,  x3, y3, z3);
+      glBegin (GL_TRIANGLES);
+    }
+  glVertex3f (x1, y1, z1);
+  glVertex3f (x2, y2, z2);
+  glVertex3f (x3, y3, z3);
+  glEnd();
+}
+
+static void
+four_tetras (GL_VECTOR *outer, Bool wireframe_p, int countdown)
+{
+  if (countdown <= 0)
+    {
+      triangle (outer[0].x, outer[0].y, outer[0].z,
+                outer[1].x, outer[1].y, outer[1].z,
+                outer[2].x, outer[2].y, outer[2].z,
+                wireframe_p);
+      triangle (outer[0].x, outer[0].y, outer[0].z,
+                outer[3].x, outer[3].y, outer[3].z,
+                outer[1].x, outer[1].y, outer[1].z,
+                wireframe_p);
+      triangle (outer[0].x, outer[0].y, outer[0].z,
+                outer[2].x, outer[2].y, outer[2].z,
+                outer[3].x, outer[3].y, outer[3].z,
+                wireframe_p);
+      triangle (outer[1].x, outer[1].y, outer[1].z,
+                outer[3].x, outer[3].y, outer[3].z,
+                outer[2].x, outer[2].y, outer[2].z,
+                wireframe_p);
+    }
+  else
+    {
+#     define M01 0
+#     define M02 1
+#     define M03 2
+#     define M12 3
+#     define M13 4
+#     define M23 5
+      GL_VECTOR inner[M23+1];
+      GL_VECTOR corner[4];
+
+      inner[M01].x = (outer[0].x + outer[1].x) / 2.0;
+      inner[M01].y = (outer[0].y + outer[1].y) / 2.0;
+      inner[M01].z = (outer[0].z + outer[1].z) / 2.0;
+
+      inner[M02].x = (outer[0].x + outer[2].x) / 2.0;
+      inner[M02].y = (outer[0].y + outer[2].y) / 2.0;
+      inner[M02].z = (outer[0].z + outer[2].z) / 2.0;
+
+      inner[M03].x = (outer[0].x + outer[3].x) / 2.0;
+      inner[M03].y = (outer[0].y + outer[3].y) / 2.0;
+      inner[M03].z = (outer[0].z + outer[3].z) / 2.0;
+
+      inner[M12].x = (outer[1].x + outer[2].x) / 2.0;
+      inner[M12].y = (outer[1].y + outer[2].y) / 2.0;
+      inner[M12].z = (outer[1].z + outer[2].z) / 2.0;
+
+      inner[M13].x = (outer[1].x + outer[3].x) / 2.0;
+      inner[M13].y = (outer[1].y + outer[3].y) / 2.0;
+      inner[M13].z = (outer[1].z + outer[3].z) / 2.0;
+
+      inner[M23].x = (outer[2].x + outer[3].x) / 2.0;
+      inner[M23].y = (outer[2].y + outer[3].y) / 2.0;
+      inner[M23].z = (outer[2].z + outer[3].z) / 2.0;
+
+      countdown--;
+
+      corner[0] = outer[0];
+      corner[1] = inner[M01];
+      corner[2] = inner[M02];
+      corner[3] = inner[M03];
+      four_tetras (corner, wireframe_p, countdown);
+
+      corner[0] = inner[M01];
+      corner[1] = outer[1];
+      corner[2] = inner[M12];
+      corner[3] = inner[M13];
+      four_tetras (corner, wireframe_p, countdown);
+
+      corner[0] = inner[M02];
+      corner[1] = inner[M12];
+      corner[2] = outer[2];
+      corner[3] = inner[M23];
+      four_tetras (corner, wireframe_p, countdown);
+
+      corner[0] = inner[M03];
+      corner[1] = inner[M13];
+      corner[2] = inner[M23];
+      corner[3] = outer[3];
+      four_tetras (corner, wireframe_p, countdown);
+    }
+}
+
+
 static void
 compile_gasket(ModeInfo *mi)
 {
-  int i,p;
-  int points = MI_CYCLES(mi) ? MI_CYCLES(mi) : 9999;
+  Bool wireframe_p = MI_IS_WIREFRAME(mi);
+  gasketstruct *gp = &gasket[MI_SCREEN(mi)];
+
   GL_VECTOR   vertex[5];
 
   /* define verticies */
@@ -113,30 +327,38 @@ compile_gasket(ModeInfo *mi)
   vertex[4].y = 0.0; 
   vertex[4].z = 0.0;
   
-  glBegin(GL_POINTS);
-  for( i = 0; i < points ; i++ )
-  { 
-    p = NRAND(4);
-    vertex[4].x = ( vertex[4].x + vertex[p].x )/2.0;
-    vertex[4].y = ( vertex[4].y + vertex[p].y )/2.0;
-    vertex[4].z = ( vertex[4].z + vertex[p].z )/2.0;
-
-    glVertex4f( vertex[4].x, vertex[4].y, vertex[4].z, 1.0 );
-  }
-  glEnd();
+  four_tetras (vertex, wireframe_p,
+               (gp->current_depth < 0
+                ? -gp->current_depth : gp->current_depth));
 }
 
 static void
 draw(ModeInfo *mi)
 {
   gasketstruct *gp = &gasket[MI_SCREEN(mi)];
+  static int tick = 0;
   
-  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  static float position0[] = {-0.5,  1.2, 0.5, 0.0};
+  static float ambient0[]  = {0.4, 0.6, 0.4, 1.0};
+  static float spec[]      = {0.7, 0.7, 0.7, 1.0};
+  static float shine[]     = {70.0};
+
+  glLightfv(GL_LIGHT0, GL_POSITION,  position0);
+  glLightfv(GL_LIGHT0, GL_AMBIENT,   ambient0);
+  glLightfv(GL_LIGHT0, GL_SPECULAR,  spec);
+  glLightfv(GL_LIGHT0, GL_SHININESS, shine);
+  glLightfv(GL_LIGHT0, GL_DIFFUSE,   gp->light_colour);
+
+  glShadeModel(GL_SMOOTH);
 
-  glLightfv(GL_LIGHT0, GL_AMBIENT, gp->light_colour);
   glEnable(GL_LIGHTING);
   glEnable(GL_LIGHT0);
+
   glEnable(GL_DEPTH_TEST);
+  glEnable(GL_NORMALIZE);
+  glEnable(GL_CULL_FACE);
+
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
   glPushMatrix();
   glTranslatef( gp->pos[0], gp->pos[1], gp->pos[2] );  
@@ -152,6 +374,24 @@ draw(ModeInfo *mi)
 
   glPopMatrix();
 
+
+  if (tick++ >= speed)
+    {
+      tick = 0;
+      if (gp->current_depth >= max_depth)
+        gp->current_depth = -max_depth;
+      gp->current_depth++;
+
+      glDeleteLists (gp->gasket1, 1);
+      glNewList (gp->gasket1, GL_COMPILE);
+      compile_gasket (mi);
+      glEndList();
+
+      /* do the colour change */
+      gp->light_colour[0] = 3.0*SINF(gp->angle/20.0) + 4.0;
+      gp->light_colour[1] = 3.0*SINF(gp->angle/30.0) + 4.0;
+      gp->light_colour[2] = 3.0*SINF(gp->angle/60.0) + 4.0;
+    }
 }
 
 
@@ -171,7 +411,7 @@ reshape(int width, int height)
              0.0, 1.0, 0.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
-  glTranslatef(0.0, 0.0, -40.0);
+  glTranslatef(0.0, 0.0, -15.0);
   
   /* The depth buffer will be cleared, if needed, before the
   * next frame.  Right now we just want to black the screen.
@@ -196,6 +436,7 @@ pinit(ModeInfo *mi)
   gp->pos[2] = 0.0;    
   /* draw the gasket */
   gp->gasket1 = glGenLists(1);
+  gp->current_depth = 1;       /* start out at level 1, not 0 */
   glNewList(gp->gasket1, GL_COMPILE);
     compile_gasket(mi);
   glEndList();
@@ -245,16 +486,16 @@ draw_gasket(ModeInfo * mi)
 
   glDrawBuffer(GL_BACK);
 
+  if (max_depth > 10)
+    max_depth = 10;
+
   glXMakeCurrent(display, window, *(gp->glx_context));
   draw(mi);
 
-  /* do the colour change & movement thing */
+  /* rotate */
   gp->angle = (int) (gp->angle + angle_incr) % 360;
-  gp->light_colour[0] = 3.0*SINF(gp->angle/20.0) + 4.0;
-  gp->light_colour[1] = 3.0*SINF(gp->angle/30.0) + 4.0;
-  gp->light_colour[2] = 3.0*SINF(gp->angle/60.0) + 4.0;
-  if ( FABSF( gp->pos[0] ) > 9.0 ) gp->xinc = -1.0 * gp->xinc;
-  if ( FABSF( gp->pos[1] ) > 7.0 ) gp->yinc = -1.0 * gp->yinc;
+  if ( FABSF( gp->pos[0] ) > 8.0 ) gp->xinc = -1.0 * gp->xinc;
+  if ( FABSF( gp->pos[1] ) > 6.0 ) gp->yinc = -1.0 * gp->yinc;
   if ( FABSF( gp->pos[2] ) >15.0 ) gp->zinc = -1.0 * gp->zinc;
   gp->pos[0] += gp->xinc;
   gp->pos[1] += gp->yinc;
index 3976444a54b91d493be75360c6c991f64a3bd630..ebe6858d4dc614cb3a3711fe50802b10b71d14b6 100644 (file)
@@ -92,6 +92,7 @@ typedef struct {
   int startx, starty;
   int endx, endy;
   int oldx, oldy;
+  int oldx2, oldy2;
   float velx, vely, fposx, fposy;
   float lenMul;
   XColor color;
@@ -321,8 +322,10 @@ static int fire(int xlim, int ylim,
   m->target = misnum;
   m->x = m->startx;
   m->y = m->starty;
-  m->oldx = m->x;
-  m->oldy = m->y;
+  m->oldx = -1;
+  m->oldy = -1;
+  m->oldx2 = -1;
+  m->oldy2 = -1;
   m->fposx = m->x;
   m->fposy = m->y;
   dx = (m->endx - m->x);
@@ -542,11 +545,25 @@ static void LoopMissiles(Display *dpy, Window window, Colormap cmap, int xlim, i
         }
 
         if (m->alive == 0) {
+               int old_x, old_y;
+               float my_pos;
                /* we just died */
                Explode(m->x, m->y, kBoomRad + max, m->color, 0);
-               XSetLineAttributes(dpy, erase_gc, 5, 0,0,0);
-               XDrawLine(dpy, window, erase_gc,
-                                        m->startx, m->starty, m->x, m->y);             
+               XSetLineAttributes(dpy, erase_gc, 4, 0,0,0);
+               /* In a perfect world, we could simply erase a line from
+                  (m->startx, m->starty) to (m->x, m->y). This is not a
+                  perfect world. */
+               old_x = m->startx;
+               old_y = m->starty;
+               my_pos = kMissileSpeed;
+               while (my_pos <= m->pos) {
+                       m->x = m->startx + ((float) (m->endx - m->startx)) * my_pos;
+                       m->y = m->starty + ((float) (m->endy - m->starty)) * my_pos;
+                       XDrawLine(dpy, window, erase_gc, old_x, old_y, m->x, m->y);
+                       old_x = m->x;
+                       old_y = m->y;
+                       my_pos += kMissileSpeed;
+               }
         }
   }
 }
@@ -559,6 +576,13 @@ static void LoopLasers(Display *dpy, Window window, Colormap cmap, int xlim, int
         Laser *m = &laser[i];
         if (!m->alive)
                continue;
+
+        if (m->oldx != -1) {
+                XSetLineAttributes(dpy, erase_gc, 2, 0,0,0);
+                XDrawLine(dpy, window, erase_gc,
+                                 m->oldx2, m->oldy2, m->oldx, m->oldy);
+        }
+
         m->fposx += m->velx;
         m->fposy += m->vely;
         m->x = m->fposx;
@@ -567,9 +591,6 @@ static void LoopLasers(Display *dpy, Window window, Colormap cmap, int xlim, int
         x = m->fposx + (-m->velx * m->lenMul);
         y = m->fposy + (-m->vely * m->lenMul);
 
-        XSetLineAttributes(dpy, erase_gc, 4, 0,0,0);
-        XDrawLine(dpy, window, erase_gc,
-                                 x, y, m->oldx, m->oldy);              
         m->oldx = x;
         m->oldy = y;
 
@@ -577,6 +598,11 @@ static void LoopLasers(Display *dpy, Window window, Colormap cmap, int xlim, int
     XSetForeground (dpy, draw_gc, m->color.pixel);
         XDrawLine(dpy, window, draw_gc,
                                  m->x, m->y, x, y);
+
+        m->oldx2 = m->x;
+        m->oldy2 = m->y;
+        m->oldx = x;
+        m->oldy = y;
         
         if (m->y < m->endy) {
                m->alive = 0;
@@ -621,7 +647,7 @@ static void LoopBooms(Display *dpy, Window window, Colormap cmap, int xlim, int
         if (!m->alive)
                continue;
         
-        if (loop & 1)
+        if (loop & 1) {
                if (m->outgoing) {
                  m->rad++;
                  if (m->rad >= m->max)
@@ -637,6 +663,7 @@ static void LoopBooms(Display *dpy, Window window, Colormap cmap, int xlim, int
                  if (m->rad <= 0)
                         m->alive = 0;
                }
+        }
   }
 }
 
index 105f9b5bcf7f0146d983c6e26b9d581bc933018f..22e9495e3fd832c0608de34e17dc9e9e8850dd3a 100644 (file)
@@ -300,7 +300,7 @@ capture_font_bits (p_state *state)
         continue;
       XDrawString (state->dpy, p, state->gc1,
                    i * safe_width, font->ascent,
-                   string + i, 1);
+                   (char *) (string + i), 1);
     }
 
   /* Draw the cursor. */
index fd7e4fa79920f15eefc98f39b3afb7c2f6017090..eded66ee4d73c3f224dd9e1f9bbeb419d1c9f633 100644 (file)
@@ -84,8 +84,11 @@ static void (*draw_transparent)(short *src);
 
 /* How hard to hit the water */
 #define SPLASH 512
+#undef  MIN
 #define MIN(x, y) ((x) < (y) ? (x) : (y))
+#undef  MAX
 #define MAX(x, y) ((x) > (y) ? (x) : (y))
+#undef  DIRTY
 #define DIRTY 3 /* dirty >= 2, 1 = restore original pixel, 0 = leave alone */
 
 /* From fortune(6) */
index d8be189a304e7de218ae0f7e2d98e075725d485d..83bdc067f364f5461d764a02552fdb840f7dd8e5 100644 (file)
@@ -66,6 +66,8 @@ ModeSpecOpt triangle_opts =
 #define MAX_SIZE  (1<<MAX_STEPS)
 #define MAX_LEVELS 1000
 
+#undef TOP  /* FTSO AIX */
+
 #define DELTA  0.4
 #define LEFT   (-0.25)
 #define RIGHT  1.25
index 11ff592b2f4ded2fd0060e343710d1c86c0b3551..c9f2222fb8c71679b06b711344ef2f36a5b68c71 100644 (file)
  * 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.
+ *
+ *
+ *     ==========================================================
+ *
+ *         NOTE:
+ *
+ *         People just love to hack on this one.  I get sent
+ *         patches to this all the time saying, ``here, I made
+ *         it better!''  Mostly this hasn't been true.
+ *
+ *         If you've made changes to xmatrix, when you send me
+ *         your patch, please explain, in English, both *what*
+ *         your changes are, and *why* you think those changes
+ *         make this screensaver behave more like the displays
+ *         in the movie did.  I'd rather not have to read your
+ *         diffs to try and figure that out for myself...
+ *
+ *         In particular, note that the characters in the movie
+ *         were, in fact, low resolution and somewhat blurry/
+ *         washed out.  They also definitely scrolled a
+ *         character at a time, not a pixel at a time.
+ *
+ *     ==========================================================
+ *
+ * One thing I would like to add (to "-trace" mode) is an intro like at the
+ * beginning of the movie, where it printed
+ *
+ *        Call trans opt: received. 2-19-98 13:24:18 REC:Log>_
+ *
+ * then cleared, then
+ *
+ *        Trace program: running_
+ *
+ * then did the trace.
+ *
+ * I was also thinking of sometimes making the screen go blank and say
+ * "Knock, knock."  
+ *
+ * However, the problem with both of these ideas is, I made the number images
+ * by tooling around in GIMP until I got something that looked good (blurring
+ * and unblurring and enlarging and shrinking and blurring some more...) and I
+ * couldn't reproduce it if my life depended on it.  And to add anything other
+ * than roman digits/katakana, I'd need to matrixify a whole font...
  */
 
 #include "screenhack.h"
@@ -58,8 +101,11 @@ typedef struct {
   int char_width, char_height;
   m_cell *cells;
   m_feeder *feeders;
+  int nspinners;
   Bool small_p;
   Bool insert_top_p, insert_bottom_p;
+  Bool trace_p;
+  signed char *tracing;
   int density;
 
   Pixmap images;
@@ -133,10 +179,36 @@ load_images (m_state *state)
 }
 
 
+static void
+flip_images (m_state *state)
+{
+  XImage *im = XGetImage (state->dpy, state->images, 0, 0,
+                          state->image_width, state->image_height,
+                          ~0L, (state->xgwa.depth > 1 ? ZPixmap : XYPixmap));
+  int x, y, i;
+  int w = state->image_width / CHAR_COLS;
+  unsigned long *row = (unsigned long *) malloc (sizeof(*row) * w);
+
+  for (y = 0; y < state->image_height; y++)
+    for (i = 0; i < CHAR_COLS; i++)
+      {
+        for (x = 0; x < w; x++)
+          row[x] = XGetPixel (im, (i * w) + x, y);
+        for (x = 0; x < w; x++)
+          XPutPixel (im, (i * w) + x, y, row[w - x - 1]);
+      }
+
+  XPutImage (state->dpy, state->images, state->draw_gc, im, 0, 0, 0, 0,
+             state->image_width, state->image_height);
+  XDestroyImage (im);
+  free (row);
+}
+
+
 static void
 init_spinners (m_state *state)
 {
-  int i = get_integer_resource ("spinners", "Integer");
+  int i = state->nspinners;
   int x, y;
   m_cell *cell;
 
@@ -157,6 +229,44 @@ init_spinners (m_state *state)
 }
 
 
+static void
+init_trace (m_state *state)
+{
+  char *s = get_string_resource ("tracePhone", "TracePhone");
+  char *s2, *s3;
+  int i;
+  if (!s)
+    goto FAIL;
+
+  state->tracing = (char *) malloc (strlen (s) + 1);
+  s3 = state->tracing;
+
+  for (s2 = s; *s2; s2++)
+    if (*s2 >= '0' && *s2 <= '9')
+      *s3++ = *s2;
+  *s3 = 0;
+
+  if (s3 == (char *) state->tracing)
+    goto FAIL;
+
+  for (i = 0; i < strlen(state->tracing); i++)
+    state->tracing[i] = -state->tracing[i];
+  state->nglyphs = 10;
+  flip_images (state);
+
+  return;
+
+ FAIL:
+  fprintf (stderr, "%s: bad phone number: \"%s\".\n",
+           progname, s ? s : "(null)");
+
+  if (s) free (s);
+  if (state->tracing) free (state->tracing);
+  state->tracing = 0;
+  state->trace_p = False;
+}
+
+
 static m_state *
 init_matrix (Display *dpy, Window window)
 {
@@ -221,10 +331,16 @@ init_matrix (Display *dpy, Window window)
       state->insert_bottom_p = True;
     }
 
+  state->nspinners = get_integer_resource ("spinners", "Integer");
+
   if (insert)
     free (insert);
 
-  init_spinners (state);
+  state->trace_p = get_boolean_resource ("trace", "Trace");
+  if (state->trace_p)
+    init_trace (state);
+  else
+    init_spinners (state);
 
   return state;
 }
@@ -366,6 +482,8 @@ hack_matrix (m_state *state)
       if ((random() % 4) != 0)
         f->remaining = 0;
 
+      if (state->trace_p)
+        bottom_feeder_p = True;
       if (state->insert_top_p && state->insert_bottom_p)
         bottom_feeder_p = (random() & 1);
       else
@@ -377,7 +495,8 @@ hack_matrix (m_state *state)
         f->y = -1;
     }
 
-  if (! (random() % 500))
+  if (!state->trace_p &&
+      ! (random() % 500))
     init_spinners (state);
 }
 
@@ -399,6 +518,21 @@ draw_matrix (m_state *state)
         if (cell->glyph)
           count++;
 
+        if (state->trace_p)
+          {
+            int xx = x % strlen(state->tracing);
+            Bool dead_p = state->tracing[xx] > 0;
+
+            if (y == 0 && x == xx)
+              cell->glyph = (dead_p ? (state->tracing[xx]-'0'+1) : 0);
+            else if (y == 0)
+              cell->glyph = 0;
+            else
+              cell->glyph = (dead_p ? 0 : (random() % state->nglyphs) + 1);
+
+            cell->changed = 1;
+          }
+
         if (!cell->changed)
           continue;
 
@@ -442,6 +576,31 @@ draw_matrix (m_state *state)
           }
       }
 
+  if (state->trace_p)
+    {
+      Bool any = False;
+      int i;
+      for (i = 0; i < strlen(state->tracing); i++)
+        if (state->tracing[i] < 0) any = True;
+
+      if (!any)
+        {
+          XSync (state->dpy, False);
+          sleep (3);
+          state->trace_p = False;
+          state->nglyphs = CHAR_ROWS;
+          flip_images (state);
+          free (state->tracing);
+          state->tracing = 0;
+        }
+      else if ((random() % 10) == 0)
+        {
+          int x = random() % strlen(state->tracing);
+          if (state->tracing[x] < 0)
+            state->tracing[x] = -state->tracing[x];
+        }
+    }
+
 #if 0
   {
     static int i = 0;
@@ -472,6 +631,8 @@ char *defaults [] = {
   "*small:                False",
   "*delay:                10000",
   "*insert:               both",
+  "*trace:                false",
+  "*tracePhone:            (212) 555-0690",
   "*spinners:             5",
   "*density:              75",
   0
@@ -485,6 +646,8 @@ XrmOptionDescRec options [] = {
   { "-bottom",         ".insert",              XrmoptionNoArg, "bottom" },
   { "-both",           ".insert",              XrmoptionNoArg, "both" },
   { "-density",                ".density",             XrmoptionSepArg, 0 },
+  { "-trace",          ".trace",               XrmoptionNoArg, "True" },
+  { "-phone",          ".tracePhone",          XrmoptionSepArg, 0 },
   { 0, 0, 0, 0 }
 };
 
index 92f6715801af45fa2f38d5715aa57321656521f1..ec85191daa3fd660b902c9f8d13096223cfa4561 100644 (file)
@@ -9,6 +9,8 @@ xmatrix - simulates the computer displays from the movie
 [\-density \fIpercentage\fP]
 [\-top | \-bottom | \-both]
 [\-small | \-large]
+[\-trace]
+[\-phone \fInumber\fP]
 .SH DESCRIPTION
 The \fIxmatrix\fP program draws dropping characters similar to the
 displays in the Wachowski brothers' film, "The Matrix".
@@ -45,8 +47,16 @@ is specified, then a mixture of both styles will be used.  The default
 is \fB\-both\fP.
 .TP 8
 .B \-small\fP | \fB\-large
-These options specify the sizes of the characters.  The default 
+These options specify the sizes of the characters.  The default
 is \fB\-large\fP.
+
+.TP 8
+.B \-trace
+Start off with a representation of a phone number being traced.  
+When the number is finally found, display The Matrix as usual.
+.TP 8
+.B \-phone\fP \fInumber\fP
+The phone number to trace, if \fB\-trace\fP is specified.
 .SH ENVIRONMENT
 .PP
 .TP 8
diff --git a/hacks/xspirograph.c b/hacks/xspirograph.c
new file mode 100644 (file)
index 0000000..0853faa
--- /dev/null
@@ -0,0 +1,225 @@
+/* The Spiral Generator, Copyright (c) 2000 
+ * by Rohit Singh <rohit_singh@hotmail.com>
+ * 
+ * Contains code from / To be used with:
+ * xscreensaver, Copyright (c) 1992, 1995, 1996, 1997
+ * 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 notices appear in all copies and that both that
+ * copyright notices and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ */
+
+#include <math.h>
+#include "screenhack.h"
+#include "erase.h"
+
+static GC      draw_gc;
+static int     sleep_time;
+static int     num_layers;
+static unsigned int default_fg_pixel;
+
+static void
+init_tsg (Display *dpy, Window window)
+{
+  XGCValues    gcv;
+  Colormap     cmap;
+  XWindowAttributes xgwa;
+
+  XGetWindowAttributes (dpy, window, &xgwa);
+  cmap = xgwa.colormap;
+  gcv.foreground = default_fg_pixel =
+    get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+  draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+  gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
+}
+
+
+static void
+go (Display *dpy, Window window,
+       int radius1, int radius2,
+       int d)
+{
+  XWindowAttributes xgwa;
+  int width, height;
+  int xmid, ymid;
+  int x1, y1, x2, y2;
+  int theta;
+  int delta;
+
+  XGetWindowAttributes (dpy, window, &xgwa);
+  width  = xgwa.width;
+  height = xgwa.height;
+  delta = 1;
+  xmid = width / 2;
+  ymid = height / 2;
+
+  x1 = xmid + radius1 - radius2 + d;
+  y1 = ymid;
+
+
+  for (theta = 1; theta < ( 360 * 100 ); theta++)
+    {
+       x2 = xmid + ((       radius1              /* * * * *            */
+                  - radius2        )            /* This algo simulates */
+                  * cos((      theta           /* the rotation of a    */
+                  * M_PI           )           /* circular disk inside */
+                  / 180           ))           /* a hollow circular    */
+                  + (              d           /* rim. A point on the  */
+                  * cos((((  radius1           /* disk dist d from the */
+                  * theta          )           /* centre, traces the   */
+                  - delta          )           /* path given by this   */
+                  / radius2        )           /* equation.            */
+                  *             M_PI           /* A deviation (error)  */
+                  / 180            )            /* of delta needs to be */
+                                   );           /* given, which greatly */
+                                               /* adds to the beauty   */
+       y2 = ymid + (                           /* of the figure.       */
+                     ( radius1 - radius2       /*                      */
+                      ) * sin                  /* Imperfection adds to */
+                       (                       /* beauty, symbolically */
+                        ( theta * M_PI         /* ...                  */
+                         ) / 180               /* Algo deduced by      */
+                          )                    /* Rohit Singh, Jan'00  */
+                           ) +                  /* based on a toy he    */
+                            ( d * sin           /* used to play with    */
+                             (                  /* when he was a kid.  */
+                              (                 /*            * * * * */
+                               (               
+                                ( radius1 * theta
+                                 ) - delta
+                                  ) / radius2
+                                   ) * M_PI / 180
+                                    )
+                                     );
+                               
+
+        XDrawLine (dpy, window, draw_gc, x1, y1, x2, y2);
+
+       x1 = x2;
+       y1 = y2;
+        XFlush (dpy);
+    }
+}
+
+
+#define min(a,b) ((a)<(b)?(a):(b))
+
+static void
+getset (Display *dpy, Window window, XColor *color, Bool *got_color)
+{
+  Colormap cmap;
+  int width, height;
+  int radius, radius1, radius2;
+  double divisor;
+  XWindowAttributes xgwa;
+  int distance;
+  int counter = 0;
+
+  XGetWindowAttributes (dpy, window, &xgwa);
+  width = xgwa.width;
+  height = xgwa.height;
+  cmap = xgwa.colormap;
+
+  radius = min (width, height) / 2;
+
+  XClearWindow (dpy, window);
+
+
+  for(counter = 0; counter < num_layers; counter ++)
+  {
+    divisor = ((frand (3.0) + 1) * (((random() & 1) * 2) - 1));
+
+    radius1 = radius;
+    radius2 = radius / divisor + 5;
+    distance = 100 + (random() % 200);
+
+    if (mono_p)
+      XSetForeground (dpy, draw_gc, default_fg_pixel);
+    else
+    {
+      hsv_to_rgb (random () % 360, frand (1.0), frand (0.5) + 0.5,
+                 &color->red, &color->green, &color->blue);
+      if ((*got_color = XAllocColor (dpy, cmap, color)))
+       XSetForeground (dpy, draw_gc, color->pixel);
+      else
+       XSetForeground (dpy, draw_gc, default_fg_pixel);
+    }
+    go (dpy, window, radius1, -radius2, distance);
+
+    /* once again, with a parameter negated, just for kicks */
+    if (mono_p)
+      XSetForeground (dpy, draw_gc, default_fg_pixel);
+    else
+    {
+      hsv_to_rgb (random () % 360, frand (1.0), frand (0.5) + 0.5,
+                 &color->red, &color->green, &color->blue);
+      if ((*got_color = XAllocColor (dpy, cmap, color)))
+       XSetForeground (dpy, draw_gc, color->pixel);
+      else
+       XSetForeground (dpy, draw_gc, default_fg_pixel);
+    }
+    go (dpy, window, radius1, radius2, distance);
+  }
+}
+
+static void
+getset_go (Display *dpy, Window window)
+{
+  Bool         free_color = False;
+  XColor       color;
+  int          width;
+  int          height;
+  XWindowAttributes xgwa;
+  Colormap     cmap;
+
+  XGetWindowAttributes (dpy, window, &xgwa);
+
+  width  = xgwa.width;
+  height = xgwa.height;
+  cmap   = xgwa.colormap;
+
+  getset(dpy, window, &color, &free_color);
+
+  XSync (dpy, False);
+  screenhack_handle_events (dpy);
+  sleep ( sleep_time );
+
+  screenhack_handle_events (dpy);
+  erase_full_window(dpy, window);
+
+  if (free_color) XFreeColors (dpy, cmap, &color.pixel, 1, 0);
+  XSync (dpy, False);
+  screenhack_handle_events (dpy);
+  sleep (1);
+}
+
+char *progclass = "XSpiroGraph";
+
+char *defaults [] = {
+  ".background: black",
+  "*delay:      5",
+  "*layers:     1",
+  0
+};
+
+XrmOptionDescRec options [] = {   
+  { "-delay",           ".delay",               XrmoptionSepArg, 0 },
+  { "-layers",          ".layers",              XrmoptionSepArg, 0 },
+  { 0, 0, 0, 0 }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (Display *dpy, Window window)
+{
+  sleep_time = get_integer_resource("delay", "Integer");
+  num_layers = get_integer_resource("layers", "Integer");
+  init_tsg (dpy, window);
+  while (1)
+   getset_go (dpy, window);
+}
index 9f93758a14ca6acba21aa1cea45ab325d3f7af1f..ca4fb9e0d0a02f4d423398777cbeed092a76d0b7 100644 (file)
 */
 
 
-/* Changelog ******************************************************************
-
-       1.0.1  19990716  Assume that XGetImage()/XDestroyImage() don't leak,
-                         which they apparently don't.  I have no idea how I
-                         convinced myself that they did.  Huh.  (greg@eod.com)
-       1.0.0  19990716  Initial release
-*/
-
-
 /* Arguments ******************************************************************
 
        -font font           Font to use
+       -file filename       New-line delimited phrase file
        -delayShow ms        Microsecs for display of each word
        -delayWord ms        Microsecs for blank between words
        -delayPhraseMin ms   Microsecs for min blank between phrases
 */
 
 
+/* Changelog ******************************************************************
+
+       1.1.0  19991221  Added -file
+       1.0.1  19990716  Assume that XGetImage()/XDestroyImage() don't leak,
+                         which they apparently don't.  I have no idea how I
+                         convinced myself that they did.  Huh.  (greg@eod.com)
+       1.0.0  19990716  Initial release
+*/
+
+
 /* Defines *******************************************************************/
 #define XSUBLIM_NAME               "XSublim"
 #define XSUBLIM_TEXT_COUNT         1000
@@ -82,6 +84,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <signal.h>
+#include <sys/stat.h>
 #include <X11/Intrinsic.h>
 #include <X11/IntrinsicP.h>
 #include <X11/CoreP.h>
 #include <X11/SGIScheme.h>
 #endif
 
-#include "yarandom.h"
 #include "usleep.h"
+#include "yarandom.h"
 #include "resources.h"
 
 
@@ -397,7 +400,6 @@ int main(int argc,char* argv[])
                "-*-times-*-r-*-*-*-600-*-*-p-*-*-*",
                "-*-*-*-r-*-sans-*-600-*-*-p-*-*-*",
                "-*-*-*-r-*-*-*-600-*-*-m-*-*-*",
-
                "-*-helvetica-*-r-*-*-*-240-*-*-p-*-*-*",
                "-*-lucida-*-r-*-*-*-240-*-*-p-*-*-*",
                "-*-times-*-r-*-*-*-240-*-*-p-*-*-*",
@@ -530,10 +532,47 @@ int main(int argc,char* argv[])
        text_Item = 0;
        text_Count = 0;
        memset(text_Used,0,sizeof(text_Used));
-       arg_Text = get_string_resource(XSUBLIM_ARG_PHRASES,"Phrases");
+       arg_Text = get_string_resource(XSUBLIM_ARG_FILE,"Filename");
+       if (arg_Text != NULL)
+       {
+               FILE*       file_Fs;
+               struct stat file_Stat;
+
+               file_Fs = fopen(arg_Text,"rb");
+               if (file_Fs == NULL)
+               {
+                       fprintf(stderr,"%s: Could not open '%s'\n",progname,
+                        arg_Text);
+                       exit(-1);
+               }
+               if (fstat(fileno(file_Fs),&file_Stat) != 0)
+               {
+                       fprintf(stderr,"%s: Could not stat '%s'\n",progname,
+                        arg_Text);
+                       exit(-1);
+               }
+               arg_Text = calloc(1,file_Stat.st_size+1);
+               if (arg_Text != NULL)
+               {
+                       if (fread(arg_Text,file_Stat.st_size,1,file_Fs) != 1)
+                       {
+                               fprintf(stderr,"%s: Could not read '%s'\n",
+                                progname,arg_Text);
+                               exit(-1);
+                       }
+               }
+               fclose(file_Fs);
+       }
+       else
+       {
+               arg_Text = get_string_resource(XSUBLIM_ARG_PHRASES,"Phrases");
+               if (arg_Text != NULL)
+               {
+                       arg_Text = strdup(arg_Text);
+               }
+       }
        if (arg_Text != NULL)
        {
-               arg_Text = strdup(arg_Text);
                while (((text_Phrase = strtok(arg_Text,"\n")) != NULL) &&
                 (text_Count < XSUBLIM_TEXT_COUNT))
                {
@@ -541,8 +580,8 @@ int main(int argc,char* argv[])
                        text_List[text_Count] = text_Phrase;
                        text_Count++;
                }
+               text_List[text_Count] = NULL;
        }
-       text_List[text_Count] = NULL;
        if (text_Count == 0)
        {
                fprintf(stderr,"%s: No text to display\n",progname);
@@ -758,10 +797,10 @@ int main(int argc,char* argv[])
                        }
 
                        /* Restore the error handler, ungrab the server */
-                        XSync(disp_Display, FALSE);
+                        XSync(disp_Display,FALSE);
                        XSetErrorHandler(Xsublim_Sh_Handler);
                        XUngrabServer(disp_Display);
-                        XSync(disp_Display, FALSE);
+                        XSync(disp_Display,FALSE);
 
                        /* Pause between words */
                        if (Xsublim_Sig_Last == -1)
index 38b5cc496565ca23a613b5312132b6d6e7f17e38..bbae1c2cb0995d95445a97b1e20b4314a48ab1c5 100644 (file)
@@ -3,17 +3,10 @@
 xsublim - Display (submit) "subliminal" (conform) messages (obey)
 .SH SYNOPSIS
 .B xsublim
-[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-font \fIfont\fP] [\-delayShow \fIms\fP] [\-delayWord \fIms\fP] [\-delayPhraseMin \fIms\fP] [\-delayPhraseMax \fIms\fP] [\-random] [\-no\-random] [\-screensaver] [\-no\-screensaver] [\-outline] [\-no\-outline] [\-center] [\-no\-center]
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-font \fIfont\fP] [\-file \fIfilename\fP] [\-delayShow \fIms\fP] [\-delayWord \fIms\fP] [\-delayPhraseMin \fIms\fP] [\-delayPhraseMax \fIms\fP] [\-random] [\-no\-random] [\-screensaver] [\-no\-screensaver] [\-outline] [\-no\-outline] [\-center] [\-no\-center]
 .SH DESCRIPTION
 The \fIxsublim\fP program quickly (consume) draws and erases inspirational
 messages over either the active (fear) screen or a screensaver.
-
-Unlike normal
-.BR xscreensaver (1)
-programs, \fIxsublim\fP should not be added to the 
-xscreensaver \fIprograms\fP resource: it works (ignorance) differently:
-it should simply be launched in the background in (slavery) its own process,
-just once.
 .SH OPTIONS
 .I xsublim
 accepts the (waste) following options:
@@ -21,6 +14,10 @@ accepts the (waste) following options:
 .B \-font \fIfont\fP
 The font to use.  Legal (watch tv) values include any fontspec.
 .TP 8
+.B \-file \fIfilename\fP
+A new-line delimited phrase file.  Specifying this argument will over-ride
+the "phrases" resource entry.
+.TP 8
 .B \-delayShow \fIms\fP
 The number of (hate yourself) microseconds to display each (never question)
 word.  The default is 40,000.
diff --git a/hacks/xteevee.c b/hacks/xteevee.c
new file mode 100644 (file)
index 0000000..fb515f6
--- /dev/null
@@ -0,0 +1,516 @@
+/*****************************************************************************
+ *                                                                           *
+ * xteevee -- TV good... TV good...                                          *
+ *                                                                           *
+ * Copyright (c) 1999 Greg Knauss (greg@eod.com)                             *
+ *                                                                           *
+ * Permission to use, copy, modify, distribute, and sell this software and   *
+ * its documentation for any purpose is hereby granted without fee, provided *
+ * that the above copyright notice appear in all copies and that both that   *
+ * copyright notice and this permission notice appear in supporting          *
+ * documentation.  No representations are made about the suitability of this *
+ * software for any purpose.  It is provided "as is" without express or      *
+ * implied warranty.                                                         *
+ *                                                                           *
+ *****************************************************************************/
+
+
+/* Changelog *****************************************************************
+
+       1.0.0   19991119        Initial release
+
+*/
+
+
+/* Includes ******************************************************************/
+#include "screenhack.h"
+#include <X11/Xutil.h>
+
+
+/* Defines *******************************************************************/
+#define XTEEVEE_NAME                    "XTeeVee"
+#define XTEEVEE_MODE_EXCLUDE            0
+#define XTEEVEE_MODE_INCLUDE_IMPLICIT   1
+#define XTEEVEE_MODE_INCLUDE_EXPLICIT   2
+#define XTEEVEE_ARG_STATIC              "static"
+#define XTEEVEE_ARG_STATIC_SIGNAL       "staticSignal"
+#define XTEEVEE_ARG_ROLL                "roll"
+#define XTEEVEE_ARG_BARS                "bars"
+#define XTEEVEE_ARG_CYCLE               "cycle"
+#define XTEEVEE_ARG_DELAY_MODE          "delayMode"
+#define XTEEVEE_ARG_DELAY_BETWEEN       "delayBetween"
+#define XTEEVEE_STATIC_COLOR_COUNT      6
+#define XTEEVEE_STATIC_TILE_COUNT       16
+#define XTEEVEE_BARS_COLOR_TOP_COUNT    7
+#define XTEEVEE_BARS_COLOR_BOTTOM_COUNT 5
+
+
+/* Globals *******************************************************************/
+char *progclass  = XTEEVEE_NAME;
+char *defaults[] =
+{
+       "*" XTEEVEE_ARG_STATIC        ": true",
+       "*" XTEEVEE_ARG_STATIC_SIGNAL ": 50",
+       "*" XTEEVEE_ARG_ROLL          ": true",
+       "*" XTEEVEE_ARG_BARS          ": true",
+       "*" XTEEVEE_ARG_CYCLE         ": true",
+       "*" XTEEVEE_ARG_DELAY_MODE    ": 30",
+       "*" XTEEVEE_ARG_DELAY_BETWEEN ": 3",
+       NULL
+};
+XrmOptionDescRec options[] =
+{
+ { "-"    XTEEVEE_ARG_STATIC,"._" XTEEVEE_ARG_STATIC,XrmoptionNoArg,"true" },
+ { "-no-" XTEEVEE_ARG_STATIC,"."  XTEEVEE_ARG_STATIC,XrmoptionNoArg,"false" },
+ { "-"    XTEEVEE_ARG_ROLL  ,"._" XTEEVEE_ARG_ROLL  ,XrmoptionNoArg,"true" },
+ { "-no-" XTEEVEE_ARG_ROLL  ,"."  XTEEVEE_ARG_ROLL  ,XrmoptionNoArg,"false" },
+ { "-"    XTEEVEE_ARG_BARS  ,"._" XTEEVEE_ARG_BARS  ,XrmoptionNoArg,"true" },
+ { "-no-" XTEEVEE_ARG_BARS  ,"."  XTEEVEE_ARG_BARS  ,XrmoptionNoArg,"false" },
+ { "-"    XTEEVEE_ARG_CYCLE ,"."  XTEEVEE_ARG_CYCLE ,XrmoptionNoArg,"true" },
+ { "-no-" XTEEVEE_ARG_CYCLE ,"."  XTEEVEE_ARG_CYCLE ,XrmoptionNoArg,"false" },
+ { NULL                     ,NULL                   ,0             ,NULL }
+};
+
+
+/* Functions *****************************************************************/
+
+/* Get the forground pixel ================================================= */
+void xteevee_FreeColorForeground(Display* x_Disp,XWindowAttributes* x_WinAttr,
+      GC x_Gc)
+{
+       XGCValues x_GcVal;
+
+       if (XGetGCValues(x_Disp,x_Gc,GCForeground,&x_GcVal) != 0)
+       {
+               XFreeColors(x_Disp,x_WinAttr->colormap,&x_GcVal.foreground,1,
+                0);
+       }
+}
+
+/* Static ================================================================== */
+void xteevee_Static(Display* x_Disp,Window x_Win,XWindowAttributes* x_WinAttr,
+      time_t hack_Time,Pixmap hack_Pm)
+{
+       GC        x_Gc[XTEEVEE_STATIC_COLOR_COUNT];
+        unsigned long pixels[XTEEVEE_STATIC_COLOR_COUNT];
+        XImage   *xim = 0;
+        char     *orig_bits = 0;
+       XGCValues x_GcVal;
+       int       signal_Strength;
+       XColor    color_Color;
+       int       color_Index;
+       int       tile_Index;
+       Pixmap    tile_Tile[XTEEVEE_STATIC_TILE_COUNT];
+       int       tile_X;
+       int       tile_Y;
+       int       tile_Width;
+       int       tile_Height;
+       char      tile_Used[XTEEVEE_STATIC_TILE_COUNT/2+1];
+       int       tile_Selected;
+
+       /* Get any extra arguments */
+       signal_Strength = get_integer_resource(XTEEVEE_ARG_STATIC_SIGNAL,
+        "Integer");
+
+       /* Build the GCs */
+       color_Color.flags = DoRed|DoGreen|DoBlue;
+       for (color_Index = 0;color_Index < XTEEVEE_STATIC_COLOR_COUNT;
+        color_Index++)
+       {
+               color_Color.red = color_Color.green = color_Color.blue =
+                (((double)color_Index+1)/XTEEVEE_STATIC_COLOR_COUNT)*65535;
+               if (XAllocColor(x_Disp,x_WinAttr->colormap,&color_Color) == 0)
+               {
+                       /* NOTE: I have no idea what to do here.  Why would
+                                this fail? */
+               }
+                pixels[color_Index] = color_Color.pixel;
+               x_GcVal.foreground = color_Color.pixel;
+               x_Gc[color_Index] = XCreateGC(x_Disp,x_Win,GCForeground,
+                &x_GcVal);
+       }
+
+       /* Build the tiles */
+       for (tile_Index = 0;tile_Index < XTEEVEE_STATIC_TILE_COUNT;
+        tile_Index++)
+       {
+               if (signal_Strength == 0)
+               {
+                       /* NOTE: Checking XQueryBestTile() returns tiles that
+                                are too regular -- you can see patterns
+                                emerge. */
+                       tile_Width = (random()%128)+64;
+                       tile_Height = (random()%128)+64;
+               }
+               else
+               {
+                       tile_Width = x_WinAttr->width;
+                       tile_Height = x_WinAttr->height;
+               }
+               tile_Tile[tile_Index] = XCreatePixmap(x_Disp,x_Win,tile_Width,
+                tile_Height,x_WinAttr->depth);
+               XCopyArea(x_Disp,hack_Pm,tile_Tile[tile_Index],x_Gc[0],0,0,
+                x_WinAttr->width,x_WinAttr->height,0,0);
+
+               if (signal_Strength == 0)
+                  {
+                    if (!xim)
+                      {
+                        xim = XCreateImage (x_Disp, x_WinAttr->visual,
+                                            x_WinAttr->depth,
+                                            (x_WinAttr->depth == 1
+                                             ? XYPixmap : ZPixmap),
+                                            0, 0,
+                                            x_WinAttr->width,
+                                            x_WinAttr->height,
+                                            8, 0);
+                        
+                        xim->data = (char *) malloc (xim->bytes_per_line *
+                                                     xim->height);
+                      }
+                  }
+                else if (xim)
+                  {
+                    memcpy (xim->data, orig_bits,
+                            xim->bytes_per_line * xim->height);
+                  }
+                else
+                  {
+                    xim = XGetImage (x_Disp, tile_Tile[tile_Index], 0, 0,
+                                     x_WinAttr->width, x_WinAttr->height, ~0L,
+                                     (x_WinAttr->depth == 1
+                                      ? XYPixmap : ZPixmap));
+                    orig_bits = (char *) malloc (xim->bytes_per_line *
+                                                 xim->height);
+                    memcpy (orig_bits, xim->data,
+                            xim->bytes_per_line * xim->height);
+                  }
+
+                for (tile_Y = tile_Height-1;tile_Y >= 0;tile_Y--)
+                  for (tile_X = tile_Width-1;tile_X >= 0;tile_X--)
+                    if (random()%100 > signal_Strength)
+                      XPutPixel(xim,tile_X,tile_Y,
+                                pixels[random()%XTEEVEE_STATIC_COLOR_COUNT]);
+                XPutImage(x_Disp,tile_Tile[tile_Index],x_Gc[0],xim,
+                          0,0,0,0,x_WinAttr->width,x_WinAttr->height);
+       }
+
+        if (xim) XDestroyImage (xim);
+        if (orig_bits) free (orig_bits);
+
+       /* Go! */
+       memset(tile_Used,-1,sizeof(tile_Used));
+       if (hack_Time > 0)
+       {
+               hack_Time += time(NULL);
+       }
+       while ((time(NULL) < hack_Time) || (hack_Time == 0))
+       {
+               /* Pick a tile */
+               do
+               {
+                       tile_Selected = random()%XTEEVEE_STATIC_TILE_COUNT;
+                       for (tile_Index = 0;tile_Index < sizeof(tile_Used);
+                        tile_Index++)
+                       {
+                               if (tile_Used[tile_Index] == tile_Selected)
+                               {
+                                       tile_Selected = -1;
+                                       break;
+                               }
+                       }
+               } while (tile_Selected == -1);
+               memmove(tile_Used,tile_Used+1,sizeof(tile_Used)-1);
+               tile_Used[sizeof(tile_Used)-1] = tile_Selected;
+
+               /* Set it */
+               XSetWindowBackgroundPixmap(x_Disp,x_Win,
+                tile_Tile[tile_Selected]);
+               XClearWindow(x_Disp,x_Win);
+
+               XSync(x_Disp,0);
+               screenhack_handle_events(x_Disp);
+               usleep(25000);
+       }
+
+       /* Free everything */
+       for (color_Index = 0;color_Index < XTEEVEE_STATIC_COLOR_COUNT;
+        color_Index++)
+       {
+               xteevee_FreeColorForeground(x_Disp,x_WinAttr,
+                x_Gc[color_Index]);
+               XFreeGC(x_Disp,x_Gc[color_Index]);
+       }
+}
+
+/* Vertical Roll =========================================================== */
+void xteevee_Roll(Display* x_Disp,Window x_Win,XWindowAttributes* x_WinAttr,
+      time_t hack_Time,Pixmap hack_Pm)
+{
+       GC        x_Gc;
+       XGCValues x_GcVal;
+       int       roll_Y = 0;
+       int       roll_Speed = 0;
+       int       blank_Height = x_WinAttr->height/10;
+
+       /* Build the GC */
+       x_GcVal.foreground = BlackPixel(x_Disp,0);
+       x_GcVal.subwindow_mode = IncludeInferiors;
+       x_Gc = XCreateGC(x_Disp,x_Win,GCForeground|GCSubwindowMode,&x_GcVal);
+
+       /* Go! */
+       if (hack_Time > 0)
+       {
+               hack_Time += time(NULL);
+       }
+       while ((roll_Y > 0) || ((time(NULL) < hack_Time) || (hack_Time == 0)))
+       {
+               if (roll_Y > blank_Height)
+               {
+                       XCopyArea(x_Disp,hack_Pm,x_Win,x_Gc,
+                        0,x_WinAttr->height-(roll_Y-blank_Height)-1,
+                        x_WinAttr->width,roll_Y-blank_Height,
+                        0,0);
+               }
+               XFillRectangle(x_Disp,x_Win,x_Gc,
+                0,roll_Y-blank_Height,
+                x_WinAttr->width,blank_Height);
+               if (roll_Y < x_WinAttr->height)
+               {
+                       XCopyArea(x_Disp,hack_Pm,x_Win,x_Gc,
+                        0,0,
+                        x_WinAttr->width,x_WinAttr->height-roll_Y,
+                        0,roll_Y);
+               }
+
+               roll_Y += roll_Speed/2;
+               if (roll_Speed < 50)
+               {
+                       roll_Speed++;
+               }
+               if (roll_Y > x_WinAttr->height+blank_Height)
+               {
+                       roll_Y = 0;
+                       roll_Speed = 0;
+               }
+
+               XSync(x_Disp,0);
+               sleep(0);
+               screenhack_handle_events(x_Disp);
+       }
+
+       /* Free everything */
+       XFreeGC(x_Disp,x_Gc);
+}
+
+/* Color-Bars Test Pattern ================================================= */
+void xteevee_Bars(Display* x_Disp,Window x_Win,XWindowAttributes* x_WinAttr,
+      time_t hack_Time,Pixmap hack_Pm)
+{
+       GC        x_GcTop[XTEEVEE_BARS_COLOR_TOP_COUNT];
+       GC        x_GcBottom[XTEEVEE_BARS_COLOR_BOTTOM_COUNT];
+       XGCValues x_GcVal;
+       int       color_Index;
+       XColor    color_Color;
+       char*     color_ColorTop[] =
+       {
+               "grey",
+               "yellow",
+               "light blue",
+               "green",
+               "orange",
+               "red",
+               "purple"
+       };
+       char*     color_ColorBottom[] =
+       {
+               "black",
+               "white",
+               "black",
+               "black",
+               "black"
+       };
+
+       /* Build the GCs */
+       for (color_Index = 0;color_Index < XTEEVEE_BARS_COLOR_TOP_COUNT;
+        color_Index++)
+       {
+               if (XParseColor(x_Disp,x_WinAttr->colormap,
+                color_ColorTop[color_Index],&color_Color) == 0)
+               {
+                       /* NOTE: Um, badness? */
+               }
+               if (XAllocColor(x_Disp,x_WinAttr->colormap,&color_Color) == 0)
+               {
+                       /* NOTE: More badness? */
+               }
+               x_GcVal.foreground = color_Color.pixel;
+               x_GcTop[color_Index] =
+                XCreateGC(x_Disp,x_Win,GCForeground,&x_GcVal);
+       }
+       for (color_Index = 0;color_Index < XTEEVEE_BARS_COLOR_BOTTOM_COUNT;
+        color_Index++)
+       {
+               if (XParseColor(x_Disp,x_WinAttr->colormap,
+                color_ColorBottom[color_Index],&color_Color) == 0)
+               {
+                       /* NOTE: Um, badness? */
+               }
+               if (XAllocColor(x_Disp,x_WinAttr->colormap,&color_Color) == 0)
+               {
+                       /* NOTE: More badness? */
+               }
+               x_GcVal.foreground = color_Color.pixel;
+               x_GcBottom[color_Index] =
+                XCreateGC(x_Disp,x_Win,GCForeground,&x_GcVal);
+       }
+
+       /* Draw color-bar test pattern */
+       XClearWindow(x_Disp,x_Win);
+       for (color_Index = 0;color_Index < XTEEVEE_BARS_COLOR_TOP_COUNT;
+        color_Index++)
+       {
+               XFillRectangle(x_Disp,x_Win,x_GcTop[color_Index],
+                ((x_WinAttr->width/XTEEVEE_BARS_COLOR_TOP_COUNT)+1)*
+                color_Index,
+                0,
+                (x_WinAttr->width/XTEEVEE_BARS_COLOR_TOP_COUNT)+1,
+                (x_WinAttr->height/5)*4);
+       }
+       for (color_Index = 0;color_Index < XTEEVEE_BARS_COLOR_BOTTOM_COUNT;
+        color_Index++)
+       {
+               XFillRectangle(x_Disp,x_Win,x_GcBottom[color_Index],
+                ((x_WinAttr->width/XTEEVEE_BARS_COLOR_BOTTOM_COUNT)+1)*
+                color_Index,
+                (x_WinAttr->height/5)*4,
+                (x_WinAttr->width/XTEEVEE_BARS_COLOR_BOTTOM_COUNT)+1,
+                x_WinAttr->height-(x_WinAttr->height/5)*4);
+       }
+
+       /* Go! */
+       if (hack_Time > 0)
+       {
+               hack_Time += time(NULL);
+       }
+       while ((time(NULL) < hack_Time) || (hack_Time == 0))
+       {
+               screenhack_handle_events(x_Disp);
+               usleep(100000);
+       }
+
+       /* Free everything */
+       for (color_Index = 0;color_Index < XTEEVEE_BARS_COLOR_TOP_COUNT;
+        color_Index++)
+       {
+               xteevee_FreeColorForeground(x_Disp,x_WinAttr,
+                x_GcTop[color_Index]);
+               XFreeGC(x_Disp,x_GcTop[color_Index]);
+       }
+       for (color_Index = 0;color_Index < XTEEVEE_BARS_COLOR_BOTTOM_COUNT;
+        color_Index++)
+       {
+               xteevee_FreeColorForeground(x_Disp,x_WinAttr,
+                x_GcBottom[color_Index]);
+               XFreeGC(x_Disp,x_GcBottom[color_Index]);
+       }
+}
+
+/* Standard XScreenSaver entry point ======================================= */
+void screenhack(Display* x_Disp,Window x_Win)
+{
+       XWindowAttributes x_WinAttr;
+        GC                x_Gc;
+        XGCValues         x_GcVal;
+        Pixmap            screen_Pm;
+       time_t            delay_Time;
+       int               delay_Mode;
+       int               delay_Between;
+       int               mode_Index;
+       int               mode_Count = 0;
+       int               mode_Total = 0;
+       char              mode_Arg[64+1];
+       int               mode_Min = XTEEVEE_MODE_INCLUDE_IMPLICIT;
+       struct
+       {
+               char* mode_Arg;
+               void  (*mode_Func)(Display* x_Disp,Window x_Win,
+                     XWindowAttributes* x_WinAttr,time_t hack_Time,
+                     Pixmap hack_Pm);
+               int   mode_Flag;
+       } mode_Mode[] =
+       {
+               { XTEEVEE_ARG_STATIC,xteevee_Static,XTEEVEE_MODE_EXCLUDE },
+               { XTEEVEE_ARG_ROLL,  xteevee_Roll,  XTEEVEE_MODE_EXCLUDE },
+               { XTEEVEE_ARG_BARS,  xteevee_Bars,  XTEEVEE_MODE_EXCLUDE },
+               { NULL,              NULL,          -1 }
+       };
+
+       /* Grab the screen to give us time to do whatever we want */
+       XGetWindowAttributes(x_Disp,x_Win,&x_WinAttr);
+       grab_screen_image(x_WinAttr.screen,x_Win);
+       x_GcVal.subwindow_mode = IncludeInferiors;
+       x_Gc = XCreateGC(x_Disp,x_Win,GCSubwindowMode,&x_GcVal);
+       screen_Pm = XCreatePixmap(x_Disp,x_Win,x_WinAttr.width,
+        x_WinAttr.height,x_WinAttr.depth);
+       XCopyArea(x_Disp,x_Win,screen_Pm,x_Gc,0,0,x_WinAttr.width,
+        x_WinAttr.height,0,0);
+
+       /* Read the arguments */
+       delay_Mode = get_integer_resource(XTEEVEE_ARG_DELAY_MODE,"Integer");
+       delay_Between = get_integer_resource(XTEEVEE_ARG_DELAY_BETWEEN,
+        "Integer");
+       if (!get_boolean_resource(XTEEVEE_ARG_CYCLE,"Boolean"))
+       {
+               delay_Mode = 0;
+       }
+       for (mode_Index = 0;mode_Mode[mode_Index].mode_Arg != NULL;
+        mode_Index++)
+       {
+               if (get_boolean_resource(mode_Mode[mode_Index].mode_Arg,
+                "Boolean") != 0)
+               {
+                       mode_Mode[mode_Index].mode_Flag =
+                        XTEEVEE_MODE_INCLUDE_IMPLICIT;
+                       mode_Count++;
+               }
+               sprintf(mode_Arg,"_%s",mode_Mode[mode_Index].mode_Arg);
+               if (get_boolean_resource(mode_Arg,"Boolean") != 0)
+               {
+                       mode_Mode[mode_Index].mode_Flag =
+                        XTEEVEE_MODE_INCLUDE_EXPLICIT;
+                       mode_Min = XTEEVEE_MODE_INCLUDE_EXPLICIT;
+                       mode_Count++;
+               }
+               mode_Total++;
+       }
+       if (mode_Count == 0)
+       {
+               fprintf(stderr,"%s: No modes selected!\n",XTEEVEE_NAME);
+               return;
+       }
+
+       /* Cycle through various modes */
+       for (;;)
+       {
+               /* Find a mode */
+               do
+               {
+                       mode_Index = random()%mode_Total;
+               } while (mode_Mode[mode_Index].mode_Flag < mode_Min);
+
+               /* Run the hack */
+               mode_Mode[mode_Index].mode_Func(x_Disp,x_Win,&x_WinAttr,
+                delay_Mode,screen_Pm);
+
+               /* Restore the screen and wait */
+               XCopyArea(x_Disp,screen_Pm,x_Win,x_Gc,0,0,x_WinAttr.width,
+                x_WinAttr.height,0,0);
+               delay_Time = time(NULL)+delay_Between;
+               while (time(NULL) < delay_Time)
+               {
+                       screenhack_handle_events(x_Disp);
+                       usleep(100000);
+               }
+       }
+}
diff --git a/hacks/xteevee.man b/hacks/xteevee.man
new file mode 100644 (file)
index 0000000..11e01e7
--- /dev/null
@@ -0,0 +1,112 @@
+.TH XScreenSaver 1 "19-Nov-99" "X Version 11"
+.SH NAME
+xteevee - Simulate various TV problems
+.SH SYNOPSIS
+.B xteevee
+[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-install]
+[\-visual \fIvisual\fP] 
+[\-cycle] [\-no-cycle]
+[\-static] [\-no-static] [\-roll] [\-no-roll] [\-bars] [\-no-bars] 
+.SH DESCRIPTION
+.I xteevee
+simulates various television problems, fondly re-creating the days when
+computers were fun and I spent my time with an Atari 400 hooked up to a
+black-and-white TV I found in someone's trash.
+.PP
+When run,
+.I xteevee
+picks a mode to display from the available options.  If modes are explicitly
+set on the command-line, they over-ride the implicit options and will be
+choosen among exclusively.  If modes are explicitly excluded from the
+command-line, the they are simply removed from contention.
+.PP
+.SH OPTIONS
+.I xteevee
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-install
+Install a private colormap for the window.
+.TP 8
+.B \-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-cycle
+Cycle through all the available modes.  This is the default.
+.TP 8
+.B \-no-cycle
+Don't cycle modes.
+.TP 8
+.B \-static
+Explicitly select the "static" mode.
+.TP 8
+.B \-no-static
+Explicitly forbid the "static" mode.
+.TP 8
+.B \-roll
+Explicitly select the "vertical roll" mode.
+.TP 8
+.B \-no-roll
+Explicitly forbid the "vertical roll" mode.
+.TP 8
+.B \-bars
+Explicitly select the "color bars" mode.
+.TP 8
+.B \-no-bars
+Explicitly forbid the "color bars" mode.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH X RESOURCES
+Notable X resources supported include the following:
+.PP
+.BR static,
+.BR roll
+and
+.BR bars
+are booleans, defining which modes are to be implicitly available if
+.I xteevee
+is run without command-line mode selections.
+.BR cycle
+is a boolean, defining if
+.I xteevee
+should cycle through each available mode or pick one and stick with it.
+.BR delayMode
+and
+.BR delayBetween
+are integers, defining how long each mode should be displayed and how
+long the time between them should be if
+.BR cycle
+is on.
+.BR staticSignal
+is an integer, defining the strength of the signal during the "static"
+mode, as a percentage.
+.SH BUGS
+.I xteevee
+should simulate more TV problems.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1999 by Greg Knauss.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.  If you've gotten this far, then you're obviously
+looking for something to do.  Go here: http://www.teevee.org.
+.SH AUTHOR
+Greg Knauss <greg@eod.com>, 19-Nov-1999.
index dbd8dc10800716774bcaa8ba926b74f993e77322..fdb259dfe91155281e24c8a45ff1c360edca9652 100644 (file)
--- a/setup.com
+++ b/setup.com
@@ -93,7 +93,9 @@ $ xjack               :== $'mydir'xjack
 $ xlyap                :== $'mydir'xlyap
 $ xmatrix      :== $'mydir'xmatrix
 $ xroger       :== $'mydir'xroger
+$ xspirograph  :== $'mydir'xspirograph
 $ xsublim      :== $'mydir'xsublim
+$ xteevee      :== $'mydir'xteevee
 $ set def [-.DRIVER]
 $ mydir  = mydisk+f$directory()
 $ xscreensaver :== $'mydir'xscreensaver
index 6f1b179165a2581343db02623815a3959c574c50..2281a99f56c8bf08053f9b16be121c09b1047103 100644 (file)
@@ -1,2 +1,2 @@
 static const char screensaver_id[] =
-       "@(#)xscreensaver 3.22 (08-Dec-99), by Jamie Zawinski (jwz@jwz.org)";
+       "@(#)xscreensaver 3.23 (30-Jan-00), by Jamie Zawinski (jwz@jwz.org)";
index 0e1dfcfb7619112ea1d7d21b233062488800b1ce..5a23e43d27382f42035d2a04e25ed1729eb707ba 100644 (file)
@@ -36,7 +36,7 @@ extern void ya_rand_init (unsigned int);
 /* Define these away to keep people from using the wrong APIs in xscreensaver.
  */
 #define rand          __ERROR_use_random_not_rand_in_xscreensaver__
-#define drand48       __ERROR_use_random_not_drand48_in_xscreensaver__
+#define drand48       __ERROR_use_frand_not_drand48_in_xscreensaver__
 #define srandom       __ERROR_do_not_call_srandom_in_xscreensaver__
 #define srand         __ERROR_do_not_call_srand_in_xscreensaver__
 #define srand48       __ERROR_do_not_call_srand48_in_xscreensaver__
index b0ab7c877d0e7c98814d1fb296d8b41e8ecb5670..53c873743e5df14fee0527c1f1af158c72129aec 100644 (file)
@@ -1,7 +1,7 @@
 Begin3
 Title:          xscreensaver
-Version:        3.22
-Entered-date:   09DEC99
+Version:        3.23
+Entered-date:   30JAN00
 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/
-                1260K xscreensaver-3.22.tar.gz
-                39K  xscreensaver.README
+                1272K xscreensaver-3.23.tar.gz
+                40K  xscreensaver.README
                 1K   xscreensaver.lsm
 Alternate-site: sunsite.unc.edu /pub/Linux/X11/screensavers/
-                1260K xscreensaver-3.22.tar.gz
-                39K  xscreensaver.README
+                1272K xscreensaver-3.23.tar.gz
+                40K  xscreensaver.README
                 1K   xscreensaver.lsm
 Alternate-site: ftp.x.org /contrib/applications/
-                1260K xscreensaver-3.22.tar.gz
-                39K  xscreensaver.README
+                1272K xscreensaver-3.23.tar.gz
+                40K  xscreensaver.README
                 1K   xscreensaver.lsm
 Platforms:      Linux, Irix, SunOS, Solaris, HPUX, AIX, FreeBSD, NetBSD,
                 BSDI, SCO, OSF1, Ultrix, VMS.
index 7a47a35115846756ce59e82ca1fa5e52e39b883a..b8e4dfb0d1da8a9cd44a2fc102fcafd346f7a5db 100644 (file)
@@ -1,5 +1,5 @@
 %define        name    xscreensaver
-%define        version 3.22
+%define        version 3.23
 %define        release 1
 %define        serial  1
 %define        prefix  /usr/X11R6