============
+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.
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:
(`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
fi
+PREFERRED_DEMO_PROGRAM=xscreensaver-demo-Xm
ALL_DEMO_PROGRAMS=
if test "$have_motif" = yes; then
PREFERRED_DEMO_PROGRAM=xscreensaver-demo-Xm
fi
+PREFERRED_DEMO_PROGRAM=xscreensaver-demo-Xm
ALL_DEMO_PROGRAMS=
if test "$have_motif" = yes; then
PREFERRED_DEMO_PROGRAM=xscreensaver-demo-Xm
! 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:
*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
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 \
*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. \
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: \
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.
+
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",
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 \
"*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 \
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 \
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.",
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))
{
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)
{
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;
}
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)
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)
static void
scroll_to_current_hack (GtkWidget *toplevel, prefs_pair *pair)
{
+ saver_preferences *p = pair->a;
Atom type;
int format;
unsigned long nitems, bytesafter;
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);
+ }
}
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
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"));
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);
#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
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,
#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() */
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 */
# 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 */
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)
{
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;
}
# 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; \
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)
if (parent)
abort ();
if (! (kids && nkids))
- abort ();
+ return 0;
for (i = 0; i < nkids; i++)
{
Atom type;
}
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 */
}
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
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)
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);
}
.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
.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
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 */
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.
.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
SHELL = /bin/sh
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_DIRS = @INSTALL_DIRS@
HACKDIR = @HACKDIR@
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 \
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 \
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@
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 \
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
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.
#
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
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
$ 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
$ 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
/* 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--)
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();
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;
}
}
* 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.
*/
/*-
# 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 */
#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 =
GLuint gasket1;
GLXContext *glx_context;
Window window;
-#if 0
- Window win;
-#endif
+
+ int current_depth;
+
} gasketstruct;
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 */
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] );
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;
+ }
}
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.
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();
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;
int startx, starty;
int endx, endy;
int oldx, oldy;
+ int oldx2, oldy2;
float velx, vely, fposx, fposy;
float lenMul;
XColor color;
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);
}
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;
+ }
}
}
}
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;
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;
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;
if (!m->alive)
continue;
- if (loop & 1)
+ if (loop & 1) {
if (m->outgoing) {
m->rad++;
if (m->rad >= m->max)
if (m->rad <= 0)
m->alive = 0;
}
+ }
}
}
continue;
XDrawString (state->dpy, p, state->gc1,
i * safe_width, font->ascent,
- string + i, 1);
+ (char *) (string + i), 1);
}
/* Draw the cursor. */
/* 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) */
#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
* 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"
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;
}
+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;
}
+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)
{
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;
}
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
f->y = -1;
}
- if (! (random() % 500))
+ if (!state->trace_p &&
+ ! (random() % 500))
init_spinners (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;
}
}
+ 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;
"*small: False",
"*delay: 10000",
"*insert: both",
+ "*trace: false",
+ "*tracePhone: (212) 555-0690",
"*spinners: 5",
"*density: 75",
0
{ "-bottom", ".insert", XrmoptionNoArg, "bottom" },
{ "-both", ".insert", XrmoptionNoArg, "both" },
{ "-density", ".density", XrmoptionSepArg, 0 },
+ { "-trace", ".trace", XrmoptionNoArg, "True" },
+ { "-phone", ".tracePhone", XrmoptionSepArg, 0 },
{ 0, 0, 0, 0 }
};
[\-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".
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
--- /dev/null
+/* 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);
+}
*/
-/* 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
#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"
"-*-times-*-r-*-*-*-600-*-*-p-*-*-*",
"-*-*-*-r-*-sans-*-600-*-*-p-*-*-*",
"-*-*-*-r-*-*-*-600-*-*-m-*-*-*",
-
"-*-helvetica-*-r-*-*-*-240-*-*-p-*-*-*",
"-*-lucida-*-r-*-*-*-240-*-*-p-*-*-*",
"-*-times-*-r-*-*-*-240-*-*-p-*-*-*",
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))
{
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);
}
/* 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)
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:
.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.
--- /dev/null
+/*****************************************************************************
+ * *
+ * 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);
+ }
+ }
+}
--- /dev/null
+.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.
$ 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
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)";
/* 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__
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.
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.
%define name xscreensaver
-%define version 3.22
+%define version 3.23
%define release 1
%define serial 1
%define prefix /usr/X11R6