--- /dev/null
+/*
+ * Imakefile file for xscreensaver, Copyright (c) 1991-1993 Jamie Zawinski.
+ *
+ * You should not need to edit this file; edit config.h instead.
+ *
+ */
+
+#include "config.h"
+
+ TARFILES = README Imakefile config.h screenblank.txt
+ TAR = gnutar
+
+all:: utils/Makefile driver/Makefile hacks/Makefile
+ cd utils ; $(MAKE) $@ CC="$(CC)" CCOPTIONS="$(CCOPTIONS)" CDEBUGFLAGS="$(CDEBUGFLAGS)"
+ cd driver ; $(MAKE) $@ CC="$(CC)" CCOPTIONS="$(CCOPTIONS)" CDEBUGFLAGS="$(CDEBUGFLAGS)"
+ cd hacks ; $(MAKE) $@ CC="$(CC)" CCOPTIONS="$(CCOPTIONS)" CDEBUGFLAGS="$(CDEBUGFLAGS)"
+
+clean install install.man:: utils/Makefile driver/Makefile hacks/Makefile
+ cd utils ; $(MAKE) $@
+ cd driver ; $(MAKE) $@
+ cd hacks ; $(MAKE) $@
+
+Makefiles:: utils/Makefile driver/Makefile hacks/Makefile
+
+utils/Makefile: utils/Imakefile config.h
+ cd utils ; $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)/utils
+driver/Makefile: driver/Imakefile config.h
+ cd driver ; $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)/driver
+hacks/Makefile: hacks/Imakefile config.h
+ cd hacks ; $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)/hacks
+
+# This really makes me sick...
+tar: utils/Makefile driver/Makefile hacks/Makefile
+ @NAME=`sed -n \
+ 's/[^0-9]*\([0-9].[0-9]*\).*/xscreensaver-\1/p' utils/version.h` ; \
+ rm -f $$NAME ; ln -s . $$NAME ; \
+ echo creating tar file $${NAME}.tar.Z... ; \
+ $(TAR) -vchf - `echo $(TARFILES) \
+ \`cd driver ; make echo_tarfiles | sed 's|^|driver/|g;s| | driver/|g'\` \
+ \`cd utils ; make echo_tarfiles | sed 's|^|utils/|g; s| | utils/|g'\` \
+ \`cd hacks ; make echo_tarfiles | sed 's|^|hacks/|g; s| | hacks/|g'\` \
+ | sed "s|^|$$NAME/|g; s| | $$NAME/|g" ` \
+ | compress > $${NAME}.tar.Z ; \
+ rm $$NAME
--- /dev/null
+
+See config.h for configuration parameters. To build, do the usual:
+
+ xmkmf ; make ; make install ; make install.man
+
+The xscreensaver program waits until the keyboard and mouse have been idle
+for a period, and then runs a graphics demo chosen at random. It turns off
+as soon as there is any mouse or keyboard activity.
+
+The purpose of xscreensaver is to display pretty pictures on your screen
+when it is not in use, in keeping with the philosophy that unattended
+monitors should always be doing something interesting, just like they do
+in the movies.
+
+However, xscreensaver can also be used as a screen locker, to prevent
+others from using your terminal while your are away.
+
+The benefit that this program has over the combination of the xlock and
+xautolock programs is the ease with which new graphics hacks can be
+installed: you don't need to recompile this program to add a new display
+mode, you just change some resource settings. Any program which can be
+invoked in such a way that it draws on the root window of the screen can
+now be used as a screensaver without modification [*]. The programs that
+are being run as screensavers don't need to have any special knowledge
+about what it means to be a screensaver.
+
+The XIdle extension will be used if you have it (win win.)
+
+Unfortunately, locking doesn't work if you don't have Motif.
+
+Also included are several graphics hacks for use as screensavers. There's
+nothing magic about these: they're just programs that draw on the root
+window, which are pointed at by the screensaver's default resource settings.
+
+ qix - My own implementation of this, with many more options
+ than you would have thought qix could have.
+ helix - Generates spirally "stringart" patterns.
+ rorschach - Random inkblot patterns.
+ attraction - A bouncing ball demo, or a qix-like demo, or a wild
+ color-cycling thing, with some odd rules.
+ greynetic - Random colored/stippled rectangles.
+ rocks - Flying through an asteroid field.
+ blitspin - Rotate a bitmap using bitblts.
+ imsmap - Generates random maps or cloud formations.
+ hypercube - 2d projection of a hypercube rotating on all four axes.
+ slidescreen - Divides the screen into a grid and plays a 16-puzzle on it.
+ halo - Random circular patterns.
+ pyro - Fireworks. Looks a lot like the version in xlock.
+ hopalong - Fractals. I snarfed this code from xlock.
+ noseguy - A guy with a big nose wanders around the screen saying
+ things. I snarfed this code from xnlock.
+ maze - This is the X maze demo modified to take a -root option
+ so that it works with xscreensaver.
+
+All of these will pop up their own window unless given that -root option.
+See their man pages for more details.
+
+Other reasonable things to use as screensavers, if you have them, are
+
+ xdaliclock -root -builtin2 - melting digital clock
+ xswarm -r 2>&- - swimming sperm
+ xwave -root - random 3d graphs
+ xbouncebits - bounce arbitrary bitmaps around
+ ico -r - it's dull, but it's there
+ xv -root file.gif -quit - they don't all have to animate!
+ xsplinefun - bouncing splines
+ kaleid -root - qix-like kaleidescope patterns
+ xfishtank -c black -d -r 1 - fish (use version 2.0 or later)
+
+You can get all of these from export.lcs.mit.edu. If you know of (or write)
+any other interesting programs that can be used as screensavers, please let
+me know!
+
+ -- Jamie Zawinski <jwz@lucid.com>
+
+[*] It may be necessary to include "vroot.h" in the program, but that would
+be necessary for it to work with virtual-root window managers anyway.
--- /dev/null
+/*
+ * Config file for xscreensaver, Copyright (c) 1991-1993 Jamie Zawinski.
+ * This file is included by the various Imakefiles.
+ */
+
+/* Uncomment the following line if you have the XIdle extension installed.
+ * XIdle comes on the X11r5 contrib tape, in .../contrib/extensions/xidle/.
+ * Installing it is the morally superior thing to do, but xscreensaver will
+ * work without it.
+ */
+#define HAVE_XIDLE
+
+/* Uncomment the following line if you don't have Motif. If you don't have
+ * Motif, then the screensaver won't have any dialog boxes, which means
+ * that it won't be compiled with support for demo-mode or display-locking.
+ */
+/* #define NO_MOTIF */
+
+/* Uncomment the following line if for some reason the locking code doesn't
+ * work (for example, if you don't have the crypt() system call, or if you
+ * don't use standard passwd files.)
+ */
+/* #define NO_LOCKING */
+
+/* Uncomment the following line if your system doesn't have the select()
+ * system call.
+ */
+/* #define NO_SELECT */
+
+/* Uncomment the following line if your system doesn't have the setuid(),
+ * setregid(), and getpwnam() library routines.
+ *
+ * WARNING: if you do this, it will be unsafe to run xscreensaver as root
+ * (which probably means you can't have it be started by xdm.) If you are
+ * on such a system, please try to find the corresponding way to do this,
+ * and then tell me what it is.
+ */
+/* #define NO_SETUID */
+
+
+/* You may need to edit these to correspond to where Motif is installed.
+ */
+#ifndef NO_MOTIF
+ MOTIFINCLUDES = /* -I... */
+ MOTIFLDOPTIONS = /* -L... */
+ MOTIFLIBS = -lXm
+#endif
+
+/* On some systems, only programs running as root can use the getpwent()
+ library routine. This means that, in order for locking to work, the
+ screensaver must be installed as setuid to root. Define this to make
+ that happen. (You must run "make install" as root for it to work.)
+ */
+#if defined(HPArchitecture) /* What other systems need this? Let me know. */
+# define INSTALL_SETUID
+#endif
+
+#ifdef HPArchitecture
+ CCOPTIONS = -Aa -D_HPUX_SOURCE /* eat me */
+# if (ProjectX <= 4)
+ MOTIFINCLUDES = -I/usr/include/Motif1.1
+ MOTIFLDOPTIONS = -L/usr/lib/Motif1.1
+# else /* R5 */
+ MOTIFINCLUDES = -I/usr/include/Motif1.2
+ MOTIFLDOPTIONS = -L/usr/lib/Motif1.2
+# endif /* R5 */
+#endif /* HPArchitecture */
+
+#ifdef MacIIArchitecture
+ CCOPTIONS = -D_POSIX_SOURCE
+#endif /* MacIIArchitecture */
+
+#if (ProjectX <= 4)
+# define R5ISMS -DXPointer="char*"
+#else /* r5 or better */
+# define R5ISMS
+#endif
--- /dev/null
+# If you're debugging xscreensaver and you are running a virtual root window
+# manager, you'd better let the process handle these signals: it remaps the
+# virtual root window when they arrive. If you don't do this, your window
+# manager will be hosed.
+#
+# Also, gdb copes badly with breakpoints in functions that are called on the
+# other side of a fork(). The Trace/BPT traps cause the spawned process to
+# die.
+#
+#handle 1 pass nostop
+#handle 3 pass nostop
+#handle 4 pass nostop
+#handle 6 pass nostop
+#handle 7 pass nostop
+#handle 8 pass nostop
+#handle 9 pass nostop
+#handle 10 pass nostop
+#handle 11 pass nostop
+#handle 12 pass nostop
+#handle 13 pass nostop
+#handle 15 pass nostop
+#handle 19 pass nostop
+b exit
+set args -verbose -idelay 0 -lock
+#b purify_stop_here
--- /dev/null
+/*
+ * Imakefile file for xscreensaver, Copyright (c) 1993 Jamie Zawinski.
+ *
+ * You should not need to edit this file; edit ../config.h instead.
+ *
+ */
+
+#include "../config.h"
+
+#if defined(NO_MOTIF) && !defined(NO_LOCKING)
+# define NO_LOCKING
+#endif
+
+#ifdef NO_LOCKING
+# undef INSTALL_SETUID
+#endif
+
+#ifdef HAVE_XIDLE
+# define XIDLE_DEF -DHAVE_XIDLE
+#else
+# define XIDLE_DEF
+#endif
+
+#ifdef NO_LOCKING
+# define LOCKING_DEF -DNO_LOCKING
+#else
+# define LOCKING_DEF
+#endif
+
+#ifdef NO_SETUID
+# define SETUID_DEF -DNO_SETUID
+#else
+# define SETUID_DEF
+#endif
+
+#ifdef NO_MOTIF
+# define MOTIF_DEF -DNO_MOTIF
+# define MOTIF_SRC
+# define MOTIF_OBJ
+# define MOTIF_LIB
+# define MOTIF_INC
+#else
+# define MOTIF_DEF
+# define MOTIF_SRC $(DBOX_SRCS) $(UTILS)/xroger.c
+# define MOTIF_OBJ $(DBOX_OBJS) $(UTILS)/xroger.o
+# define MOTIF_LIB $(MOTIFLDOPTIONS) $(MOTIFLIBS)
+# define MOTIF_INC $(MOTIFINCLUDES)
+#endif
+
+ UTILS = ../utils
+ INCLUDES = -I$(UTILS) MOTIF_INC
+ DEFINES = SETUID_DEF XIDLE_DEF MOTIF_DEF LOCKING_DEF R5ISMS
+ SAVERLIBS = $(XMULIB) $(XTOOLLIB) $(EXTENSIONLIB) $(XLIB) -lm
+ COMMLIBS = $(XLIB) -lm
+ UTIL_SRCS = $(UTILS)/resources.c $(UTILS)/fade.c $(UTILS)/usleep.c
+ UTIL_OBJS = $(UTILS)/resources.o $(UTILS)/fade.o $(UTILS)/usleep.o
+ DBOX_SRCS = dialogs.c demo.c lock.c
+ DBOX_OBJS = dialogs.o demo.o lock.o
+ SAVERSRCS = xscreensaver.c visual.c timers.c subprocs.c windows.c
+ SAVEROBJS = xscreensaver.o visual.o timers.o subprocs.o windows.o
+ SRCS1 = $(SAVERSRCS) MOTIF_SRC $(UTIL_SRCS)
+ OBJS1 = $(SAVEROBJS) MOTIF_OBJ $(UTIL_OBJS)
+ COMMSRCS = xscreensaver-command.c
+ COMMOBJS = xscreensaver-command.o
+ SRCS2 = $(COMMSRCS)
+ OBJS2 = $(COMMOBJS)
+ MEN = xscreensaver.man xscreensaver-command.man
+ TARFILES = README Imakefile $(SAVERSRCS) $(DBOX_SRCS) $(COMMSRCS) \
+ xscreensaver.h XScreenSaver.ad dialogs.xd $(MEN) .gdbinit
+
+#if defined(HPArchitecture) && !defined(NO_LOCKING)
+EXTRA_LIBRARIES = -lXhp11 /* for XHPDisableReset() */
+#endif
+
+all:: xscreensaver xscreensaver-command
+
+echo_tarfiles:
+ @echo $(TARFILES)
+
+PROGRAMS = xscreensaver xscreensaver-command
+
+#ifdef INSTALL_SETUID
+#undef InstallProgram
+#define InstallProgram(p,d) InstallProgramWithFlags(p,d,$(INSTUIDFLAGS))
+#endif
+
+ComplexProgramTarget_1(xscreensaver,MOTIF_LIB $(SAVERLIBS),)
+
+#ifdef INSTALL_SETUID
+#undef InstallProgram
+#define InstallProgram(p,d) InstallProgramWithFlags(p,d,)
+#endif
+
+ComplexProgramTarget_2(xscreensaver-command,$(COMMLIBS),)
+
+InstallAppDefaults(XScreenSaver)
+
+xscreensaver.o: XScreenSaver.ad.h $(UTILS)/version.h
+xscreensaver-command.o: $(UTILS)/version.h
+
+demo.o: $(UTILS)/version.h
+lock.o: $(UTILS)/version.h
+
+/* build this before calling makedepend */
+depend:: XScreenSaver.ad.h
+
+XScreenSaver.ad.h: XScreenSaver.ad
+ $(UTILS)/ad2c XScreenSaver.ad > XScreenSaver.ad.h
+
+clean::
+ $(RM) XScreenSaver.ad.h
--- /dev/null
+
+This directory contains the source for xscreensaver and xscreensaver-command,
+the screensaver driver, and the program for externally controlling it. Some
+stuff from the ../utils/ directory is used here as well.
+
+If you have compilation problems, check the parameters in ../config.h.
--- /dev/null
+! app-defaults file for XScreenSaver by Jamie Zawinski.
+
+*timeout: 10
+*cycle: 10
+*lockTimeout: 0
+*passwdTimeout: 30
+*nice: 10
+*lock: False
+*verbose: False
+*fade: True
+*unfade: False
+*fadeSeconds: 1
+*fadeTicks: 75
+
+! Turning on "installColormap" interacts erratically with twm and tvtwm,
+! but seems to work fine with mwm and olwm. Try it and see.
+!
+*installColormap: False
+
+! Programs on this list apply all the time.
+*programs: qix -root \n\
+ qix -root -solid -delay 0 -segments 100 \n\
+ qix -root -linear -count 10 -size 100 -segments 200 \n\
+ attraction -root -mode balls \n\
+ attraction -root -mode lines -points 3 -segments 200 \n\
+ attraction -root -mode splines -segments 300 \n\
+ attraction -root -mode lines -radius 300 \
+ -orbit -vmult 0.5 \n\
+ pyro -root \n\
+ helix -root \n\
+ rorschach -root -offset 7 \n\
+ hopalong -root \n\
+ greynetic -root \n\
+ xroger -root \n\
+ imsmap -root \n\
+ slidescreen -root \n\
+ hypercube -root \n\
+ halo -root \n\
+ maze -root \n
+
+! Programs on this list are run only for monochrome screens.
+*monoPrograms: qix -root -linear -count 5 -size 200 -spread 30 \
+ -segments 75 -solid -xor \n\
+ rocks -root \n\
+ noseguy -root \n
+
+! Programs on this list are run only for color (really, non-mono) screens.
+*colorPrograms: qix -root -count 4 -solid -transparent \n\
+ qix -root -count 5 -solid -transparent -linear \
+ -segments 250 -size 100 \n\
+ attraction -root -mode polygons \n\
+ attraction -root -mode filled-splines -segments 0 \n\
+ attraction -root -glow -points 10 \n\
+ rocks -root -fg darksalmon \n\
+ noseguy -root -fg yellow -bg gray30 \n
+
+
+! Some other screenhacks that you might want to track down:
+!
+! xdaliclock -root -builtin2 \n\
+! xswarm -r 2>&- \n\
+! xwave -root \n\
+! xbouncebits ... \n\
+! ico -r \n\
+! xsplinefun \n\
+! kaleid -root \n\
+! xfishtank -c black -d -r 2 \n\
+
+
+! Resources for the dialog boxes:
+!
+*fontList: *-helvetica-medium-r-*-*-*-120-*-*-*-iso8859-1
+*demoDialog*label1.fontList: *-helvetica-medium-r-*-*-*-140-*-*-*-iso8859-1
+*passwdDialog*fontList: *-helvetica-medium-r-*-*-*-140-*-*-*-iso8859-1
+*XmList.fontList: *-courier-medium-r-*-*-*-120-*-*-*-iso8859-1
+*XmTextField.fontList: *-courier-medium-r-*-*-*-120-*-*-*-iso8859-1
+*passwdDialog.passwdText.fontList: *-courier-medium-r-*-*-*-120-*-*-*-iso8859-1
+
+*XmDialogShell*foreground: black
+*XmDialogShell*background: gray90
+*XmDialogShell*XmTextField.foreground: black
+*XmDialogShell*XmTextField.background: white
+*XmDialogShell*demoList.foreground: black
+*XmDialogShell*demoList.background: white
+*XmDialogShell*rogerLabel.foreground: red3
+*XmDialogShell*rogerLabel.background: white
+
+*XmDialogShell.title: XScreenSaver
+*allowShellResize: True
+*autoUnmanage: False
+
+! This doesn't work. Motif ignores it if there is a scroll-list!
+*demoDialog.maxWidth: 600
+
+*label1.labelString: XScreenSaver %s
+*label2.labelString: Copyright © 1991-1993 by Jamie Zawinski <jwz@lucid.com>
+*demoList.visibleItemCount: 10
+*demoList.automaticSelection: True
+*next.labelString: Run Next
+*prev.labelString: Run Previous
+*edit.labelString: Edit Parameters
+*done.labelString: Exit Demo Mode
+*restart.labelString: Reinitialize
+
+*resourcesLabel.labelString: XScreenSaver Parameters
+
+! *timeoutLabel.labelString: Timeout Minutes
+! *cycleLabel.labelString: Cycle Seconds
+! *fadeSecondsLabel.labelString:Fade Seconds
+! *fadeTicksLabel.labelString: Fade Ticks
+! *lockLabel.labelString: Lock Timeout
+! *passwdLabel.labelString: Password Timeout
+! *resourcesForm*XmTextField.columns: 5
+
+*timeoutLabel.labelString: Saver Timeout
+*cycleLabel.labelString: Cycle Timeout
+*fadeSecondsLabel.labelString: Fade Duration
+*fadeTicksLabel.labelString: Fade Ticks
+*lockLabel.labelString: Lock Timeout
+*passwdLabel.labelString: Password Timeout
+*resourcesForm*XmTextField.columns: 8
+
+*verboseToggle.labelString: Verbose
+*cmapToggle.labelString: Install Colormap
+*fadeToggle.labelString: Fade Colormap
+*unfadeToggle.labelString: Unfade Colormap
+*lockToggle.labelString: Require Password
+*resourcesDone.labelString: Done
+*resourcesCancel.labelString: Cancel
+
+*passwdLabel1.labelString: XScreenSaver %s
+*passwdLabel2.labelString: This display is locked.
+*passwdLabel3.labelString: Please type %s's password to unlock it.
+*passwdDone.labelString: Done
+*passwdCancel.labelString: Cancel
+
+*passwdLabel1.alignment: ALIGNMENT_BEGINNING
+*passwdLabel2.alignment: ALIGNMENT_BEGINNING
+*passwdLabel3.alignment: ALIGNMENT_BEGINNING
+*rogerLabel.width: 150
+
+! You probably won't need to change these. They aren't consulted if the
+! XIdle extension is being used.
+!
+*pointerPollTime: 5
+*initialDelay: 30
+*windowCreationTimeout: 30
+
+*bourneShell: /bin/sh
--- /dev/null
+/* xscreensaver, Copyright (c) 1993 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#include <X11/Intrinsic.h>
+
+#if !__STDC__
+# define _NO_PROTO
+#endif
+
+#include <Xm/Xm.h>
+#include <Xm/Text.h>
+#include <Xm/List.h>
+#include <Xm/ToggleB.h>
+
+#include "xscreensaver.h"
+#include <stdio.h>
+
+extern Time timeout, cycle, lock_timeout, passwd_timeout;
+extern int fade_seconds, fade_ticks;
+extern Bool verbose_p, install_cmap_p, fade_p, unfade_p;
+extern Bool lock_p, locking_disabled_p;
+
+static void demo_mode_hack P((char *));
+static void demo_mode_done P((void));
+
+extern void demo_mode_restart_process ();
+
+extern Widget demo_dialog;
+extern Widget label1;
+extern Widget text_line;
+extern Widget demo_form;
+extern Widget demo_list;
+extern Widget next, prev, done, restart, edit;
+
+extern Widget resources_dialog;
+extern Widget resources_form;
+extern Widget res_done, res_cancel;
+extern Widget timeout_text, cycle_text, fade_text, ticks_text;
+extern Widget lock_time_text, passwd_time_text;
+extern Widget verbose_toggle, cmap_toggle, fade_toggle, unfade_toggle,
+ lock_toggle;
+
+extern create_demo_dialog ();
+extern create_resources_dialog ();
+
+static void
+focus_fuckus (dialog)
+ Widget dialog;
+{
+ XSetInputFocus (XtDisplay (dialog), XtWindow (dialog),
+ RevertToParent, CurrentTime);
+}
+
+static void
+raise_screenhack_dialog ()
+{
+ XMapRaised (XtDisplay (demo_dialog), XtWindow (demo_dialog));
+ if (resources_dialog)
+ XMapRaised (XtDisplay (resources_dialog), XtWindow (resources_dialog));
+ focus_fuckus (resources_dialog ? resources_dialog : demo_dialog);
+}
+
+static void
+destroy_screenhack_dialogs ()
+{
+ if (demo_dialog) XtDestroyWidget (demo_dialog);
+ if (resources_dialog) XtDestroyWidget (resources_dialog);
+ demo_dialog = resources_dialog = 0;
+}
+
+static void
+text_cb (button, client_data, call_data)
+ Widget button;
+ XtPointer client_data, call_data;
+{
+ char *line = XmTextGetString (button);
+ demo_mode_hack (line);
+}
+
+
+static void
+select_cb (button, client_data, call_data)
+ Widget button;
+ XtPointer client_data, call_data;
+{
+ char **hacks = (char **) client_data;
+ XmListCallbackStruct *lcb = (XmListCallbackStruct *) call_data;
+ XmTextSetString (text_line, hacks [lcb->item_position - 1]);
+ if (lcb->reason == XmCR_DEFAULT_ACTION)
+ text_cb (text_line, 0, 0);
+ focus_fuckus (demo_dialog);
+}
+
+static void
+next_cb (button, client_data, call_data)
+ Widget button;
+ XtPointer client_data, call_data;
+{
+ int *pos_list;
+ int pos_count;
+ if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
+ XmListSelectPos (demo_list, 1, True);
+ else
+ {
+ int pos = pos_list [0];
+ XmListSelectPos (demo_list, pos + 1, True);
+ XtFree ((char *) pos_list);
+ if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
+ abort ();
+ if (pos_list [0] == pos)
+ XmListSelectPos (demo_list, 1, True);
+ XtFree ((char *) pos_list);
+ }
+ text_cb (text_line, 0, 0);
+}
+
+static void
+prev_cb (button, client_data, call_data)
+ Widget button;
+ XtPointer client_data, call_data;
+{
+ int *pos_list;
+ int pos_count;
+ if (! XmListGetSelectedPos (demo_list, &pos_list, &pos_count))
+ XmListSelectPos (demo_list, 0, True);
+ else
+ {
+ XmListSelectPos (demo_list, pos_list [0] - 1, True);
+ XtFree ((char *) pos_list);
+ }
+ text_cb (text_line, 0, 0);
+}
+
+
+static void pop_resources_dialog ();
+static void make_resources_dialog ();
+
+static void
+edit_cb (button, client_data, call_data)
+ Widget button;
+ XtPointer client_data, call_data;
+{
+ Widget parent = (Widget) client_data;
+ if (! resources_dialog)
+ make_resources_dialog (parent);
+ pop_resources_dialog ();
+}
+
+static void
+done_cb (button, client_data, call_data)
+ Widget button;
+ XtPointer client_data, call_data;
+{
+ demo_mode_done ();
+}
+
+
+static void
+restart_cb (button, client_data, call_data)
+ Widget button;
+ XtPointer client_data, call_data;
+{
+ demo_mode_restart_process ();
+}
+
+void
+pop_up_dialog_box (dialog, form, where)
+ Widget dialog, form;
+ int where;
+{
+ /* I'm sure this is the wrong way to pop up a dialog box, but I can't
+ figure out how else to do it.
+
+ It's important that the screensaver dialogs not get decorated or
+ otherwise reparented by the window manager, because they need to be
+ children of the *real* root window, not the WM's virtual root, in
+ order for us to guarentee tha they are visible above the screensaver
+ window itself.
+ */
+ Arg av [100];
+ int ac = 0;
+ Dimension sw, sh, x, y, w, h;
+ XtRealizeWidget (form);
+ sw = WidthOfScreen (XtScreen (dialog));
+ sh = HeightOfScreen (XtScreen (dialog));
+ ac = 0;
+ XtSetArg (av [ac], XmNwidth, &w); ac++;
+ XtSetArg (av [ac], XmNheight, &h); ac++;
+ XtGetValues (form, av, ac);
+ switch (where)
+ {
+ case 0: /* center it in the top-right quadrant */
+ x = (sw/2 + w) / 2 + (sw/2) - w;
+ y = (sh/2 + h) / 2 - h;
+ break;
+ case 1: /* center it in the bottom-right quadrant */
+ x = (sw/2 + w) / 2 + (sw/2) - w;
+ y = (sh/2 + h) / 2 + (sh/2) - h;
+ break;
+ case 2: /* center it on the screen */
+ x = (sw + w) / 2 - w;
+ y = (sh + h) / 2 - h;
+ break;
+ default:
+ abort ();
+ }
+ if (x + w > sw) x = sw - w;
+ if (y + h > sh) y = sh - h;
+ ac = 0;
+ XtSetArg (av [ac], XmNx, x); ac++;
+ XtSetArg (av [ac], XmNy, y); ac++;
+ XtSetArg (av [ac], XtNoverrideRedirect, True); ac++;
+ XtSetArg (av [ac], XmNdefaultPosition, False); ac++;
+ /* I wonder whether this does anything useful? */
+/* XtSetArg (av [ac], XmNdialogStyle, XmDIALOG_SYSTEM_MODAL); ac++; */
+ XtSetValues (dialog, av, ac);
+ XtSetValues (form, av, ac);
+ XtManageChild (form);
+
+ focus_fuckus (dialog);
+}
+
+
+static void
+make_screenhack_dialog (parent, hacks)
+ Widget parent;
+ char **hacks;
+{
+ char buf [255];
+ Arg av[10];
+ int ac;
+ char *label;
+ Dimension max_w = 0;
+ XmString xm_label = 0;
+ XmString new_xm_label;
+
+ create_demo_dialog (parent);
+ ac = 0;
+ XtSetArg (av [ac], XmNlabelString, &xm_label); ac++;
+ XtGetValues (label1, av, ac);
+ XmStringGetLtoR (xm_label, XmSTRING_DEFAULT_CHARSET, &label);
+ if (!strcmp (label, XtName (label1)))
+ strcpy (buf, "ERROR: RESOURCES ARE NOT INSTALLED CORRECTLY");
+ else
+ sprintf (buf, label, screensaver_version);
+ new_xm_label = XmStringCreate (buf, XmSTRING_DEFAULT_CHARSET);
+ ac = 0;
+ XtSetArg (av [ac], XmNlabelString, new_xm_label); ac++;
+ XtSetValues (label1, av, ac);
+ XmStringFree (new_xm_label);
+ XtFree (label);
+
+ XtAddCallback (demo_list, XmNbrowseSelectionCallback, select_cb,
+ hacks);
+ XtAddCallback (demo_list, XmNdefaultActionCallback, select_cb,
+ hacks);
+
+ XtAddCallback (text_line, XmNactivateCallback, text_cb, 0);
+ XtAddCallback (next, XmNactivateCallback, next_cb, 0);
+ XtAddCallback (prev, XmNactivateCallback, prev_cb, 0);
+ XtAddCallback (done, XmNactivateCallback, done_cb, 0);
+ XtAddCallback (restart, XmNactivateCallback, restart_cb, 0);
+ XtAddCallback (edit, XmNactivateCallback, edit_cb, parent);
+
+ for (; *hacks; hacks++)
+ {
+ XmString xmstr = XmStringCreate (*hacks, XmSTRING_DEFAULT_CHARSET);
+ XmListAddItem (demo_list, xmstr, 0);
+ /* XmListSelectPos (widget, i, False); */
+ XmStringFree (xmstr);
+ }
+
+#if 0
+ /* Dialogs that have scroll-lists don't obey maxWidth! Fuck!! Hack it. */
+ ac = 0;
+ XtSetArg (av [ac], XmNmaxWidth, &max_w); ac++;
+ XtGetValues (demo_dialog, av, ac); /* great, this SEGVs */
+#endif
+
+ pop_up_dialog_box (demo_dialog, demo_form, 0);
+}
+
+\f
+/* the Screensaver Parameters dialog */
+
+static struct resources {
+ int timeout, cycle, secs, ticks, lock_time, passwd_time;
+ int verb, cmap, fade, unfade, lock_p;
+} res;
+
+
+extern int parse_time ();
+
+static void
+hack_time_cb (dpy, line, store, sec_p)
+ Display *dpy;
+ char *line;
+ int *store;
+ Bool sec_p;
+{
+ if (*line)
+ {
+ int value;
+ value = parse_time (line, sec_p, True);
+ if (value < 0)
+ /*XBell (dpy, 0)*/;
+ else
+ *store = value;
+ }
+}
+
+static void
+res_sec_cb (button, client_data, call_data)
+ Widget button;
+ XtPointer client_data, call_data;
+{
+ hack_time_cb (XtDisplay (button), XmTextGetString (button),
+ (int *) client_data, True);
+}
+
+static void
+res_min_cb (button, client_data, call_data)
+ Widget button;
+ XtPointer client_data, call_data;
+{
+ hack_time_cb (XtDisplay (button), XmTextGetString (button),
+ (int *) client_data, False);
+}
+
+static void
+res_int_cb (button, client_data, call_data)
+ Widget button;
+ XtPointer client_data, call_data;
+{
+ char *line = XmTextGetString (button);
+ int *store = (int *) client_data;
+ unsigned int value;
+ char c;
+ if (! *line)
+ ;
+ else if (sscanf (line, "%u%c", &value, &c) != 1)
+ XBell (XtDisplay (button), 0);
+ else
+ *store = value;
+}
+
+static void
+res_bool_cb (button, client_data, call_data)
+ Widget button;
+ XtPointer client_data, call_data;
+{
+ int *store = (int *) client_data;
+ *store = ((XmToggleButtonCallbackStruct *) call_data)->set;
+}
+
+static void
+res_cancel_cb (button, client_data, call_data)
+ Widget button;
+ XtPointer client_data, call_data;
+{
+ XtDestroyWidget (resources_dialog);
+ resources_dialog = 0;
+ raise_screenhack_dialog ();
+}
+
+
+static void
+res_done_cb (button, client_data, call_data)
+ Widget button;
+ XtPointer client_data, call_data;
+{
+ res_cancel_cb (button, client_data, call_data);
+
+ if (res.timeout < 10) res.timeout = 10;
+ if (res.cycle < 2) res.cycle = 2;
+ if (res.passwd_time < 2) res.passwd_time = 30;
+
+ timeout = res.timeout * 1000;
+ cycle = res.cycle * 1000;
+ lock_timeout = res.lock_time * 1000;
+ passwd_timeout = res.passwd_time * 1000;
+ fade_seconds = res.secs;
+ fade_ticks = res.ticks;
+ verbose_p = res.verb;
+ install_cmap_p = res.cmap;
+ fade_p = res.fade;
+ unfade_p = res.unfade;
+ lock_p = res.lock_p;
+}
+
+
+static void
+make_resources_dialog (parent)
+ Widget parent;
+{
+ Arg av[10];
+ int ac;
+
+ create_resources_dialog (parent);
+
+ XtAddCallback (res_done, XmNactivateCallback, res_done_cb, 0);
+ XtAddCallback (res_cancel, XmNactivateCallback, res_cancel_cb, 0);
+
+#define CB(widget,type,slot) \
+ XtAddCallback ((widget), XmNvalueChangedCallback, (type), (slot))
+ CB (timeout_text, res_min_cb, &res.timeout);
+ CB (cycle_text, res_min_cb, &res.cycle);
+ CB (fade_text, res_sec_cb, &res.secs);
+ CB (ticks_text, res_int_cb, &res.ticks);
+ CB (lock_time_text, res_min_cb, &res.lock_time);
+ CB (passwd_time_text, res_sec_cb, &res.passwd_time);
+ CB (verbose_toggle, res_bool_cb, &res.verb);
+ CB (cmap_toggle, res_bool_cb, &res.cmap);
+ CB (fade_toggle, res_bool_cb, &res.fade);
+ CB (unfade_toggle, res_bool_cb, &res.unfade);
+ CB (lock_toggle, res_bool_cb, &res.lock_p);
+#undef CB
+ ac = 0;
+ XtSetArg (av[ac], XmNsensitive, False); ac++;
+
+ if (locking_disabled_p)
+ {
+ XtSetValues (passwd_time_text, av, ac);
+ XtSetValues (lock_time_text, av, ac);
+ XtSetValues (lock_toggle, av, ac);
+ }
+ if (CellsOfScreen (XtScreen (parent)) <= 2)
+ {
+ XtSetValues (fade_text, av, ac);
+ XtSetValues (ticks_text, av, ac);
+ XtSetValues (cmap_toggle, av, ac);
+ XtSetValues (fade_toggle, av, ac);
+ XtSetValues (unfade_toggle, av, ac);
+ }
+}
+
+
+static void
+fmt_time (buf, s, min_p)
+ char *buf;
+ unsigned int s;
+ int min_p;
+{
+ unsigned int h = 0, m = 0;
+ if (s >= 60)
+ {
+ m += (s / 60);
+ s %= 60;
+ }
+ if (m >= 60)
+ {
+ h += (m / 60);
+ m %= 60;
+ }
+/*
+ if (min_p && h == 0 && s == 0)
+ sprintf (buf, "%u", m);
+ else if (!min_p && h == 0 && m == 0)
+ sprintf (buf, "%u", s);
+ else
+ if (h == 0)
+ sprintf (buf, "%u:%02u", m, s);
+ else
+*/
+ sprintf (buf, "%u:%02u:%02u", h, m, s);
+}
+
+static void
+pop_resources_dialog ()
+{
+ char buf [100];
+
+ res.timeout = timeout / 1000;
+ res.cycle = cycle / 1000;
+ res.lock_time = lock_timeout / 1000;
+ res.passwd_time = passwd_timeout / 1000;
+ res.secs = fade_seconds;
+ res.ticks = fade_ticks;
+ res.verb = verbose_p;
+ res.cmap = install_cmap_p;
+ res.fade = fade_p;
+ res.unfade = unfade_p;
+ res.lock_p = (lock_p && !locking_disabled_p);
+
+ fmt_time (buf, res.timeout, 1); XmTextSetString (timeout_text, buf);
+ fmt_time (buf, res.cycle, 1); XmTextSetString (cycle_text, buf);
+ fmt_time (buf, res.lock_time, 1); XmTextSetString (lock_time_text, buf);
+ fmt_time (buf, res.passwd_time, 0); XmTextSetString (passwd_time_text, buf);
+ fmt_time (buf, res.secs, 0); XmTextSetString (fade_text, buf);
+ sprintf (buf, "%u", res.ticks); XmTextSetString (ticks_text, buf);
+
+ XmToggleButtonSetState (verbose_toggle, res.verb, True);
+ XmToggleButtonSetState (cmap_toggle, res.cmap, True);
+ XmToggleButtonSetState (fade_toggle, res.fade, True);
+ XmToggleButtonSetState (unfade_toggle, res.unfade, True);
+ XmToggleButtonSetState (lock_toggle, res.lock_p, True);
+
+ pop_up_dialog_box (resources_dialog, resources_form, 1);
+}
+
+\f
+/* The code on this page isn't actually Motif-specific */
+
+Bool dbox_up_p = False;
+Bool demo_mode_p = False;
+
+extern XtAppContext app;
+extern Widget toplevel_shell;
+extern Bool use_xidle;
+extern Time notice_events_timeout;
+
+extern char **screenhacks;
+extern char *demo_hack;
+
+extern void notice_events_timer P((XtPointer closure, void *timer));
+extern Bool handle_clientmessage P((/*XEvent *, Bool*/));
+
+void
+demo_mode ()
+{
+ dbox_up_p = True;
+ initialize_screensaver_window ();
+ raise_window (True, False);
+ make_screenhack_dialog (toplevel_shell, screenhacks);
+ while (demo_mode_p)
+ {
+ XEvent event;
+ XtAppNextEvent (app, &event);
+ switch (event.xany.type)
+ {
+ case 0: /* synthetic "timeout" event */
+ break;
+
+ case ClientMessage:
+ handle_clientmessage (&event, False);
+ break;
+
+ case CreateNotify:
+#ifdef HAVE_XIDLE
+ if (! use_xidle)
+#endif
+ XtAppAddTimeOut (app, notice_events_timeout, notice_events_timer,
+ (XtPointer) event.xcreatewindow.window);
+ break;
+
+ case ButtonPress:
+ case ButtonRelease:
+ if (!XtWindowToWidget (dpy, event.xbutton.window))
+ raise_screenhack_dialog ();
+ /* fall through */
+
+ default:
+ XtDispatchEvent (&event);
+ break;
+ }
+ }
+ destroy_screenhack_dialogs ();
+ initialize_screensaver_window ();
+ unblank_screen ();
+}
+
+static void
+demo_mode_hack (hack)
+ char *hack;
+{
+ if (! demo_mode_p) abort ();
+ kill_screenhack ();
+ if (! demo_hack)
+ blank_screen ();
+ demo_hack = hack;
+ spawn_screenhack (False);
+}
+
+static void
+demo_mode_done ()
+{
+ kill_screenhack ();
+ if (demo_hack)
+ unblank_screen ();
+ demo_mode_p = False;
+ dbox_up_p = False;
+ demo_hack = 0;
+}
--- /dev/null
+
+/*
+** Generated by X-Designer
+*/
+/*
+**LIBS: -lXm -lXt -lX11
+*/
+
+#if !__STDC__
+# define _NO_PROTO
+#endif
+
+#include <X11/Xatom.h>
+#include <X11/Intrinsic.h>
+#include <X11/Shell.h>
+
+#include <Xm/Xm.h>
+#include <Xm/DialogS.h>
+#include <Xm/DrawnB.h>
+#include <Xm/Form.h>
+#include <Xm/Label.h>
+#include <Xm/List.h>
+#include <Xm/PushB.h>
+#include <Xm/ScrollBar.h>
+#include <Xm/Separator.h>
+#include <Xm/TextF.h>
+#include <Xm/ToggleB.h>
+
+
+Widget passwd_dialog;
+Widget passwd_form;
+Widget roger_label;
+Widget passwd_label1;
+Widget passwd_label3;
+Widget passwd_text;
+Widget passwd_done;
+Widget passwd_cancel;
+
+Widget resources_dialog;
+Widget resources_form;
+Widget timeout_text;
+Widget cycle_text;
+Widget fade_text;
+Widget ticks_text;
+Widget lock_time_text;
+Widget passwd_time_text;
+Widget verbose_toggle;
+Widget cmap_toggle;
+Widget fade_toggle;
+Widget unfade_toggle;
+Widget lock_toggle;
+Widget res_done;
+Widget res_cancel;
+
+Widget demo_dialog;
+Widget demo_form;
+Widget label1;
+Widget label2;
+Widget text_area;
+Widget demo_list;
+Widget text_line;
+Widget vline;
+Widget next;
+Widget prev;
+Widget edit;
+Widget done;
+Widget restart;
+Widget spacer;
+
+
+create_passwd_dialog( parent )
+Widget parent;
+{
+ Display *display = XtDisplay ( parent );
+ Widget children[8]; /* Children to manage */
+ Arg al[64]; /* Arg List */
+ register int ac = 0; /* Arg Count */
+ char from_s [256]; /* For font list conversion */
+ XrmValue from_value, to_value; /* ditto */
+ int fg, bg; /* colour values for pixmaps */
+ XmString *list_items; /* For list items */
+ int list_item; /* Index for list_items */
+ XmString xmstrings[15]; /* temporary storage for XmStrings */
+ Widget widget4;
+ Widget widget7;
+
+ passwd_dialog = XmCreateDialogShell ( parent, "passwdDialog", al, ac );
+ passwd_form = XmCreateForm ( passwd_dialog, "passwdForm", al, ac );
+ roger_label = XmCreateDrawnButton ( passwd_form, "rogerLabel", al, ac );
+ passwd_label1 = XmCreateLabel ( passwd_form, "passwdLabel1", al, ac );
+ widget4 = XmCreateLabel ( passwd_form, "passwdLabel2", al, ac );
+ passwd_label3 = XmCreateLabel ( passwd_form, "passwdLabel3", al, ac );
+ passwd_text = XmCreateTextField ( passwd_form, "passwdText", al, ac );
+ widget7 = XmCreateSeparator ( passwd_form, "widget7", al, ac );
+ passwd_done = XmCreatePushButton ( passwd_form, "passwdDone", al, ac );
+ passwd_cancel = XmCreatePushButton ( passwd_form, "passwdCancel", al, ac );
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 4); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+ XtSetValues ( roger_label,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 4); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, widget4); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftWidget, roger_label); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+ XtSetValues ( passwd_label1,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, passwd_label3); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftWidget, roger_label); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+ XtSetValues ( widget4,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, passwd_text); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftWidget, roger_label); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 30); ac++;
+ XtSetValues ( passwd_label3,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, widget7); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftWidget, roger_label); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+ XtSetValues ( passwd_text,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, passwd_done); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+ XtSetArg(al[ac], XmNleftWidget, roger_label); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 0); ac++;
+ XtSetValues ( widget7,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftWidget, roger_label); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+ XtSetValues ( passwd_done,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftWidget, passwd_done); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+ XtSetValues ( passwd_cancel,al, ac );
+ ac = 0;
+ children[ac++] = roger_label;
+ children[ac++] = passwd_label1;
+ children[ac++] = widget4;
+ children[ac++] = passwd_label3;
+ children[ac++] = passwd_text;
+ children[ac++] = widget7;
+ children[ac++] = passwd_done;
+ children[ac++] = passwd_cancel;
+ XtManageChildren(children, ac);
+ ac = 0;
+}
+
+
+
+create_resources_dialog( parent )
+Widget parent;
+{
+ Display *display = XtDisplay ( parent );
+ Widget children[22]; /* Children to manage */
+ Arg al[64]; /* Arg List */
+ register int ac = 0; /* Arg Count */
+ char from_s [256]; /* For font list conversion */
+ XrmValue from_value, to_value; /* ditto */
+ int fg, bg; /* colour values for pixmaps */
+ XmString *list_items; /* For list items */
+ int list_item; /* Index for list_items */
+ XmString xmstrings[15]; /* temporary storage for XmStrings */
+ Widget widget12;
+ Widget widget13;
+ Widget widget14;
+ Widget widget15;
+ Widget widget16;
+ Widget widget17;
+ Widget widget18;
+ Widget widget48;
+ Widget widget29;
+
+ resources_dialog = XmCreateDialogShell ( parent, "resourcesDialog", al, ac );
+ resources_form = XmCreateForm ( resources_dialog, "resourcesForm", al, ac );
+ widget12 = XmCreateLabel ( resources_form, "resourcesLabel", al, ac );
+ widget13 = XmCreateSeparator ( resources_form, "widget13", al, ac );
+ XtSetArg(al[ac], XmNalignment, XmALIGNMENT_END); ac++;
+ widget14 = XmCreateLabel ( resources_form, "timeoutLabel", al, ac );
+ ac = 0;
+ XtSetArg(al[ac], XmNalignment, XmALIGNMENT_END); ac++;
+ widget15 = XmCreateLabel ( resources_form, "cycleLabel", al, ac );
+ ac = 0;
+ XtSetArg(al[ac], XmNalignment, XmALIGNMENT_END); ac++;
+ widget16 = XmCreateLabel ( resources_form, "fadeSecondsLabel", al, ac );
+ ac = 0;
+ XtSetArg(al[ac], XmNalignment, XmALIGNMENT_END); ac++;
+ widget17 = XmCreateLabel ( resources_form, "fadeTicksLabel", al, ac );
+ ac = 0;
+ XtSetArg(al[ac], XmNalignment, XmALIGNMENT_END); ac++;
+ widget18 = XmCreateLabel ( resources_form, "lockLabel", al, ac );
+ ac = 0;
+ XtSetArg(al[ac], XmNalignment, XmALIGNMENT_END); ac++;
+ widget48 = XmCreateLabel ( resources_form, "passwdLabel", al, ac );
+ ac = 0;
+ timeout_text = XmCreateTextField ( resources_form, "timeoutText", al, ac );
+ cycle_text = XmCreateTextField ( resources_form, "cycleText", al, ac );
+ fade_text = XmCreateTextField ( resources_form, "fadeSecondsText", al, ac );
+ ticks_text = XmCreateTextField ( resources_form, "fadeTicksText", al, ac );
+ lock_time_text = XmCreateTextField ( resources_form, "passwdText", al, ac );
+ passwd_time_text = XmCreateTextField ( resources_form, "lockText", al, ac );
+ XtSetArg(al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
+ verbose_toggle = XmCreateToggleButton ( resources_form, "verboseToggle", al, ac );
+ ac = 0;
+ XtSetArg(al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
+ cmap_toggle = XmCreateToggleButton ( resources_form, "cmapToggle", al, ac );
+ ac = 0;
+ XtSetArg(al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
+ fade_toggle = XmCreateToggleButton ( resources_form, "fadeToggle", al, ac );
+ ac = 0;
+ XtSetArg(al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
+ unfade_toggle = XmCreateToggleButton ( resources_form, "unfadeToggle", al, ac );
+ ac = 0;
+ XtSetArg(al[ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++;
+ lock_toggle = XmCreateToggleButton ( resources_form, "lockToggle", al, ac );
+ ac = 0;
+ widget29 = XmCreateSeparator ( resources_form, "widget29", al, ac );
+ res_done = XmCreatePushButton ( resources_form, "resourcesDone", al, ac );
+ res_cancel = XmCreatePushButton ( resources_form, "resourcesCancel", al, ac );
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+ XtSetValues ( widget12,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 4); ac++;
+ XtSetArg(al[ac], XmNtopWidget, widget12); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 0); ac++;
+ XtSetValues ( widget13,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 4); ac++;
+ XtSetArg(al[ac], XmNtopWidget, widget13); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, timeout_text); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 20); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+ XtSetArg(al[ac], XmNrightWidget, timeout_text); ac++;
+ XtSetValues ( widget14,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+ XtSetArg(al[ac], XmNtopWidget, cycle_text); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 0); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, cycle_text); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 20); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+ XtSetArg(al[ac], XmNrightWidget, cycle_text); ac++;
+ XtSetValues ( widget15,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+ XtSetArg(al[ac], XmNtopWidget, fade_text); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 0); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, fade_text); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 20); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+ XtSetArg(al[ac], XmNrightWidget, fade_text); ac++;
+ XtSetValues ( widget16,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+ XtSetArg(al[ac], XmNtopWidget, ticks_text); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 0); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, ticks_text); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 20); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+ XtSetArg(al[ac], XmNrightWidget, ticks_text); ac++;
+ XtSetValues ( widget17,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+ XtSetArg(al[ac], XmNtopWidget, lock_time_text); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 0); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, lock_time_text); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 19); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+ XtSetArg(al[ac], XmNrightWidget, lock_time_text); ac++;
+ XtSetValues ( widget18,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+ XtSetArg(al[ac], XmNtopWidget, passwd_time_text); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 0); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, passwd_time_text); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 14); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+ XtSetArg(al[ac], XmNrightWidget, passwd_time_text); ac++;
+ XtSetValues ( widget48,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 4); ac++;
+ XtSetArg(al[ac], XmNtopWidget, widget13); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 141); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+ XtSetValues ( timeout_text,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 2); ac++;
+ XtSetArg(al[ac], XmNtopWidget, timeout_text); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+ XtSetArg(al[ac], XmNleftWidget, timeout_text); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+ XtSetValues ( cycle_text,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 2); ac++;
+ XtSetArg(al[ac], XmNtopWidget, cycle_text); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+ XtSetArg(al[ac], XmNleftWidget, cycle_text); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+ XtSetValues ( fade_text,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 2); ac++;
+ XtSetArg(al[ac], XmNtopWidget, fade_text); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+ XtSetArg(al[ac], XmNleftWidget, fade_text); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+ XtSetValues ( ticks_text,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 2); ac++;
+ XtSetArg(al[ac], XmNtopWidget, ticks_text); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+ XtSetArg(al[ac], XmNleftWidget, ticks_text); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+ XtSetValues ( lock_time_text,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 4); ac++;
+ XtSetArg(al[ac], XmNtopWidget, lock_time_text); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+ XtSetArg(al[ac], XmNleftWidget, lock_time_text); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+ XtSetValues ( passwd_time_text,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 4); ac++;
+ XtSetArg(al[ac], XmNtopWidget, widget13); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 0); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, timeout_text); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 20); ac++;
+ XtSetArg(al[ac], XmNleftWidget, timeout_text); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 20); ac++;
+ XtSetValues ( verbose_toggle,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+ XtSetArg(al[ac], XmNtopWidget, cycle_text); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 0); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, cycle_text); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+ XtSetArg(al[ac], XmNleftWidget, verbose_toggle); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 20); ac++;
+ XtSetValues ( cmap_toggle,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+ XtSetArg(al[ac], XmNtopWidget, fade_text); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 0); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, fade_text); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+ XtSetArg(al[ac], XmNleftWidget, cmap_toggle); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 20); ac++;
+ XtSetValues ( fade_toggle,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+ XtSetArg(al[ac], XmNtopWidget, ticks_text); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 0); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, ticks_text); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+ XtSetArg(al[ac], XmNleftWidget, fade_toggle); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 20); ac++;
+ XtSetValues ( unfade_toggle,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+ XtSetArg(al[ac], XmNtopWidget, lock_time_text); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 0); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, lock_time_text); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 0); ac++;
+ XtSetArg(al[ac], XmNleftWidget, unfade_toggle); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 20); ac++;
+ XtSetValues ( lock_toggle,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+ XtSetArg(al[ac], XmNtopWidget, passwd_time_text); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, res_done); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetValues ( widget29,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+ XtSetValues ( res_done,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftWidget, res_done); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+ XtSetValues ( res_cancel,al, ac );
+ ac = 0;
+ children[ac++] = widget12;
+ children[ac++] = widget13;
+ children[ac++] = widget14;
+ children[ac++] = widget15;
+ children[ac++] = widget16;
+ children[ac++] = widget17;
+ children[ac++] = widget18;
+ children[ac++] = widget48;
+ children[ac++] = timeout_text;
+ children[ac++] = cycle_text;
+ children[ac++] = fade_text;
+ children[ac++] = ticks_text;
+ children[ac++] = lock_time_text;
+ children[ac++] = passwd_time_text;
+ children[ac++] = verbose_toggle;
+ children[ac++] = cmap_toggle;
+ children[ac++] = fade_toggle;
+ children[ac++] = unfade_toggle;
+ children[ac++] = lock_toggle;
+ children[ac++] = widget29;
+ children[ac++] = res_done;
+ children[ac++] = res_cancel;
+ XtManageChildren(children, ac);
+ ac = 0;
+}
+
+
+
+create_demo_dialog( parent )
+Widget parent;
+{
+ Display *display = XtDisplay ( parent );
+ Widget children[11]; /* Children to manage */
+ Arg al[64]; /* Arg List */
+ register int ac = 0; /* Arg Count */
+ char from_s [256]; /* For font list conversion */
+ XrmValue from_value, to_value; /* ditto */
+ int fg, bg; /* colour values for pixmaps */
+ XmString *list_items; /* For list items */
+ int list_item; /* Index for list_items */
+ XmString xmstrings[15]; /* temporary storage for XmStrings */
+
+ demo_dialog = XmCreateDialogShell ( parent, "demoDialog", al, ac );
+ demo_form = XmCreateForm ( demo_dialog, "demoForm", al, ac );
+ label1 = XmCreateLabel ( demo_form, "label1", al, ac );
+ label2 = XmCreateLabel ( demo_form, "label2", al, ac );
+ demo_list = XmCreateScrolledList ( demo_form, "demoList", al, ac );
+ text_area = XtParent ( demo_list );
+
+ text_line = XmCreateTextField ( demo_form, "textLine", al, ac );
+ vline = XmCreateSeparator ( demo_form, "vline", al, ac );
+ next = XmCreatePushButton ( demo_form, "next", al, ac );
+ prev = XmCreatePushButton ( demo_form, "prev", al, ac );
+ edit = XmCreatePushButton ( demo_form, "edit", al, ac );
+ done = XmCreatePushButton ( demo_form, "done", al, ac );
+ restart = XmCreatePushButton ( demo_form, "restart", al, ac );
+ xmstrings[0] = XmStringCreateLtoR(" ", (XmStringCharSet)XmSTRING_DEFAULT_CHARSET);
+ XtSetArg(al[ac], XmNlabelString, xmstrings[0]); ac++;
+ spacer = XmCreateLabel ( demo_form, "spacer", al, ac );
+ ac = 0;
+ XmStringFree ( xmstrings [ 0 ] );
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 5); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+ XtSetValues ( label1,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 4); ac++;
+ XtSetArg(al[ac], XmNtopWidget, label1); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+ XtSetValues ( label2,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 4); ac++;
+ XtSetArg(al[ac], XmNtopWidget, label2); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, text_line); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+ XtSetValues ( text_area,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, vline); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+ XtSetValues ( text_line,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+ XtSetArg(al[ac], XmNbottomWidget, next); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+ XtSetValues ( vline,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_NONE); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 3); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+ XtSetValues ( next,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+ XtSetArg(al[ac], XmNtopWidget, next); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftWidget, next); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+ XtSetValues ( prev,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+ XtSetArg(al[ac], XmNtopWidget, prev); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftWidget, prev); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+ XtSetValues ( edit,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+ XtSetArg(al[ac], XmNtopWidget, edit); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftWidget, edit); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+ XtSetValues ( done,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+ XtSetArg(al[ac], XmNtopWidget, done); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftWidget, done); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_NONE); ac++;
+ XtSetValues ( restart,al, ac );
+ ac = 0;
+
+ XtSetArg(al[ac], XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET); ac++;
+ XtSetArg(al[ac], XmNtopOffset, 0); ac++;
+ XtSetArg(al[ac], XmNtopWidget, restart); ac++;
+ XtSetArg(al[ac], XmNbottomAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNbottomOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftAttachment, XmATTACH_WIDGET); ac++;
+ XtSetArg(al[ac], XmNleftOffset, 4); ac++;
+ XtSetArg(al[ac], XmNleftWidget, restart); ac++;
+ XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++;
+ XtSetArg(al[ac], XmNrightOffset, 4); ac++;
+ XtSetValues ( spacer,al, ac );
+ ac = 0;
+ XtManageChild(demo_list);
+ children[ac++] = label1;
+ children[ac++] = label2;
+ children[ac++] = text_line;
+ children[ac++] = vline;
+ children[ac++] = next;
+ children[ac++] = prev;
+ children[ac++] = edit;
+ children[ac++] = done;
+ children[ac++] = restart;
+ children[ac++] = spacer;
+ XtManageChildren(children, ac);
+ ac = 0;
+}
+
+
--- /dev/null
+module 'XScreenSaver'
+applicationName = 'XScreenSaver';
+generateNameC = 'dialogs.c';
+generateNameUIL = '';
+generateNameResDB = 'dialogs.ad';
+generateUidFile = '';
+generateMask = 1507557;
+useMask = 1;
+value
+object 'passwd_dialog' : XmDialogShell {
+ arguments {
+ name = 'passwdDialog';
+ XmNtitle= 'XScreenSaver';
+ XmNallowShellResize= true;
+ };
+object 'passwd_form' : XmForm {
+ arguments {
+ name = 'passwdForm';
+ XmNautoUnmanage= false;
+ };
+object 'roger_label' : XmDrawnButton {
+ arguments {
+ name = 'rogerLabel';
+ XmNwidth= 150;
+ };
+};
+object 'passwd_label1' : XmLabel {
+ arguments {
+ name = 'passwdLabel1';
+ XmNlabelString= 'XScreenSaver %s';
+ XmNalignment= 0;
+ };
+};
+object '' : XmLabel {
+ arguments {
+ name = 'passwdLabel2';
+ XmNlabelString= 'This display is locked.';
+ XmNalignment= 0;
+ };
+};
+object 'passwd_label3' : XmLabel {
+ arguments {
+ name = 'passwdLabel3';
+ XmNlabelString= 'Please type %s\'s password to unlock it.';
+ XmNalignment= 0;
+ };
+};
+object 'passwd_text' : XmTextField {
+ arguments {
+ name = 'passwdText';
+ };
+};
+object '' : XmSeparator {
+ arguments {
+ };
+};
+object 'passwd_done' : XmPushButton {
+ arguments {
+ name = 'passwdDone';
+ XmNlabelString= 'Done';
+ };
+};
+object 'passwd_cancel' : XmPushButton {
+ arguments {
+ name = 'passwdCancel';
+ XmNlabelString= 'Cancel';
+ };
+};
+ attachments {
+ attachment {
+ XmNrightAttachment = 0 0 0;
+ XmNleftAttachment = 1 0 4;
+ XmNbottomAttachment = 1 0 4;
+ XmNtopAttachment = 1 0 4;
+ };
+ attachment {
+ XmNrightAttachment = 1 0 4;
+ XmNleftAttachment = 3 1 4;
+ XmNbottomAttachment = 3 3 4;
+ XmNtopAttachment = 1 0 4;
+ };
+ attachment {
+ XmNrightAttachment = 1 0 4;
+ XmNleftAttachment = 3 1 4;
+ XmNbottomAttachment = 3 4 4;
+ XmNtopAttachment = 0 0 0;
+ };
+ attachment {
+ XmNrightAttachment = 1 0 30;
+ XmNleftAttachment = 3 1 4;
+ XmNbottomAttachment = 3 5 4;
+ XmNtopAttachment = 0 0 0;
+ };
+ attachment {
+ XmNrightAttachment = 1 0 4;
+ XmNleftAttachment = 3 1 4;
+ XmNbottomAttachment = 3 6 4;
+ XmNtopAttachment = 0 0 0;
+ };
+ attachment {
+ XmNrightAttachment = 1 0 0;
+ XmNleftAttachment = 3 1 0;
+ XmNbottomAttachment = 3 7 4;
+ XmNtopAttachment = 0 0 0;
+ };
+ attachment {
+ XmNrightAttachment = 0 0 0;
+ XmNleftAttachment = 3 1 4;
+ XmNbottomAttachment = 1 0 4;
+ XmNtopAttachment = 0 0 0;
+ };
+ attachment {
+ XmNrightAttachment = 0 0 0;
+ XmNleftAttachment = 3 7 4;
+ XmNbottomAttachment = 1 0 4;
+ XmNtopAttachment = 0 0 0;
+ };
+ };
+};
+};
+object 'resources_dialog' : XmDialogShell {
+ arguments {
+ name = 'resourcesDialog';
+ XmNtitle= 'XScreenSaver';
+ XmNallowShellResize= true;
+ };
+object 'resources_form' : XmForm {
+ arguments {
+ name = 'resourcesForm';
+ XmNautoUnmanage= false;
+ };
+object '' : XmLabel {
+ arguments {
+ name = 'resourcesLabel';
+ XmNlabelString= 'XScreenSaver Parameters';
+ };
+};
+object '' : XmSeparator {
+ arguments {
+ };
+};
+object '' : XmLabel {
+ arguments {
+ name = 'timeoutLabel';
+ XmNlabelString= 'Timeout Minutes';
+ XmNalignment= * 2;
+ };
+};
+object '' : XmLabel {
+ arguments {
+ name = 'cycleLabel';
+ XmNlabelString= 'Cycle Seconds';
+ XmNalignment= * 2;
+ };
+};
+object '' : XmLabel {
+ arguments {
+ name = 'fadeSecondsLabel';
+ XmNlabelString= 'Fade Seconds';
+ XmNalignment= * 2;
+ };
+};
+object '' : XmLabel {
+ arguments {
+ name = 'fadeTicksLabel';
+ XmNlabelString= 'Fade Ticks';
+ XmNalignment= * 2;
+ };
+};
+object '' : XmLabel {
+ arguments {
+ name = 'lockLabel';
+ XmNlabelString= 'Lock Timeout';
+ XmNalignment= * 2;
+ };
+};
+object '' : XmLabel {
+ arguments {
+ name = 'passwdLabel';
+ XmNlabelString= 'Password Timeout';
+ XmNalignment= * 2;
+ };
+};
+object 'timeout_text' : XmTextField {
+ arguments {
+ name = 'timeoutText';
+ XmNcolumns= 5;
+ };
+};
+object 'cycle_text' : XmTextField {
+ arguments {
+ name = 'cycleText';
+ XmNcolumns= 5;
+ };
+};
+object 'fade_text' : XmTextField {
+ arguments {
+ name = 'fadeSecondsText';
+ XmNcolumns= 5;
+ };
+};
+object 'ticks_text' : XmTextField {
+ arguments {
+ name = 'fadeTicksText';
+ XmNcolumns= 5;
+ };
+};
+object 'lock_time_text' : XmTextField {
+ arguments {
+ name = 'passwdText';
+ XmNcolumns= 5;
+ };
+};
+object 'passwd_time_text' : XmTextField {
+ arguments {
+ name = 'lockText';
+ XmNcolumns= 5;
+ };
+};
+object 'verbose_toggle' : XmToggleButton {
+ arguments {
+ name = 'verboseToggle';
+ XmNlabelString= 'Verbose';
+ XmNalignment= * 0;
+ };
+};
+object 'cmap_toggle' : XmToggleButton {
+ arguments {
+ name = 'cmapToggle';
+ XmNlabelString= 'Install Colormap';
+ XmNalignment= * 0;
+ };
+};
+object 'fade_toggle' : XmToggleButton {
+ arguments {
+ name = 'fadeToggle';
+ XmNlabelString= 'Fade Colormap';
+ XmNalignment= * 0;
+ };
+};
+object 'unfade_toggle' : XmToggleButton {
+ arguments {
+ name = 'unfadeToggle';
+ XmNlabelString= 'Unfade Colormap';
+ XmNalignment= * 0;
+ };
+};
+object 'lock_toggle' : XmToggleButton {
+ arguments {
+ name = 'lockToggle';
+ XmNlabelString= 'Require Password';
+ XmNalignment= * 0;
+ };
+};
+object '' : XmSeparator {
+ arguments {
+ };
+};
+object 'res_done' : XmPushButton {
+ arguments {
+ name = 'resourcesDone';
+ XmNlabelString= 'Done';
+ };
+};
+object 'res_cancel' : XmPushButton {
+ arguments {
+ name = 'resourcesCancel';
+ XmNlabelString= 'Cancel';
+ };
+};
+ attachments {
+ attachment {
+ XmNrightAttachment = 1 0 4;
+ XmNleftAttachment = 1 0 4;
+ XmNtopAttachment = 1 0 4;
+ };
+ attachment {
+ XmNrightAttachment = 1 0 0;
+ XmNleftAttachment = 1 0 0;
+ XmNbottomAttachment = 0 0 0;
+ XmNtopAttachment = 3 1 4;
+ };
+ attachment {
+ XmNrightAttachment = 3 9 4;
+ XmNleftAttachment = 1 0 20;
+ XmNbottomAttachment = 4 9;
+ XmNtopAttachment = 3 2 4;
+ };
+ attachment {
+ XmNrightAttachment = 3 10 4;
+ XmNleftAttachment = 1 0 20;
+ XmNbottomAttachment = 4 10 0;
+ XmNtopAttachment = 4 10 0;
+ };
+ attachment {
+ XmNrightAttachment = 3 11 4;
+ XmNleftAttachment = 1 0 20;
+ XmNbottomAttachment = 4 11 0;
+ XmNtopAttachment = 4 11 0;
+ };
+ attachment {
+ XmNrightAttachment = 3 12 4;
+ XmNleftAttachment = 1 0 20;
+ XmNbottomAttachment = 4 12 0;
+ XmNtopAttachment = 4 12 0;
+ };
+ attachment {
+ XmNrightAttachment = 3 13 4;
+ XmNleftAttachment = 1 0 19;
+ XmNbottomAttachment = 4 13 0;
+ XmNtopAttachment = 4 13 0;
+ };
+ attachment {
+ XmNrightAttachment = 3 14 4;
+ XmNleftAttachment = 1 0 14;
+ XmNbottomAttachment = 4 14 0;
+ XmNtopAttachment = 4 14 0;
+ };
+ attachment {
+ XmNrightAttachment = 0 0 0;
+ XmNleftAttachment = 1 0 141;
+ XmNbottomAttachment = 0 0 0;
+ XmNtopAttachment = 3 2 4;
+ };
+ attachment {
+ XmNrightAttachment = 0 0 0;
+ XmNleftAttachment = 4 9 0;
+ XmNbottomAttachment = 0 0 0;
+ XmNtopAttachment = 3 9 2;
+ };
+ attachment {
+ XmNrightAttachment = 0 0 0;
+ XmNleftAttachment = 4 10 0;
+ XmNbottomAttachment = 0 0 0;
+ XmNtopAttachment = 3 10 2;
+ };
+ attachment {
+ XmNrightAttachment = 0 0 0;
+ XmNleftAttachment = 4 11 0;
+ XmNbottomAttachment = 0 0 0;
+ XmNtopAttachment = 3 11 2;
+ };
+ attachment {
+ XmNrightAttachment = 0 0 0;
+ XmNleftAttachment = 4 12 0;
+ XmNbottomAttachment = 0 0 0;
+ XmNtopAttachment = 3 12 2;
+ };
+ attachment {
+ XmNrightAttachment = 0 0 0;
+ XmNleftAttachment = 4 13 0;
+ XmNbottomAttachment = 0 0 0;
+ XmNtopAttachment = 3 13 4;
+ };
+ attachment {
+ XmNrightAttachment = 1 0 20;
+ XmNleftAttachment = 3 9 20;
+ XmNbottomAttachment = 4 9 0;
+ XmNtopAttachment = 3 2 4;
+ };
+ attachment {
+ XmNrightAttachment = 1 0 20;
+ XmNleftAttachment = 4 15 0;
+ XmNbottomAttachment = 4 10 0;
+ XmNtopAttachment = 4 10 0;
+ };
+ attachment {
+ XmNrightAttachment = 1 0 20;
+ XmNleftAttachment = 4 16 0;
+ XmNbottomAttachment = 4 11 0;
+ XmNtopAttachment = 4 11 0;
+ };
+ attachment {
+ XmNrightAttachment = 1 0 20;
+ XmNleftAttachment = 4 17 0;
+ XmNbottomAttachment = 4 12 0;
+ XmNtopAttachment = 4 12 0;
+ };
+ attachment {
+ XmNrightAttachment = 1 0 20;
+ XmNleftAttachment = 4 18 0;
+ XmNbottomAttachment = 4 13 0;
+ XmNtopAttachment = 4 13 0;
+ };
+ attachment {
+ XmNrightAttachment = 1 0;
+ XmNleftAttachment = 1 0;
+ XmNbottomAttachment = 3 21 4;
+ XmNtopAttachment = 3 14 0;
+ };
+ attachment {
+ XmNrightAttachment = 0 0 0;
+ XmNleftAttachment = 1 0 4;
+ XmNbottomAttachment = 1 0 4;
+ XmNtopAttachment = 0 0 0;
+ };
+ attachment {
+ XmNrightAttachment = 0 0 0;
+ XmNleftAttachment = 3 21 4;
+ XmNbottomAttachment = 1 0 4;
+ XmNtopAttachment = 0 0 0;
+ };
+ };
+};
+};
+object 'demo_dialog' : XmDialogShell {
+ arguments {
+ name = 'demoDialog';
+ XmNtitle= 'XScreenSaver';
+ XmNmaxWidth= 500;
+ XmNallowShellResize= true;
+ };
+object 'demo_form' : XmForm {
+ arguments {
+ name = 'demoForm';
+ XmNautoUnmanage= false;
+ };
+object 'label1' : XmLabel {
+ arguments {
+ name = 'label1';
+ XmNlabelString= 'XScreenSaver %s';
+ };
+};
+object 'label2' : XmLabel {
+ arguments {
+ name = 'label2';
+ XmNlabelString= 'Copyright © 1991-1993 by Jamie Zawinski <jwz@lucid.com>';
+ };
+};
+object 'text_area' : XmScrolledList {
+ arguments {
+ name = 'textArea';
+ };
+object '' : XmScrollBar {
+ arguments {
+ name = 'ListhScrollBar';
+ };
+};
+object '' : XmScrollBar {
+ arguments {
+ name = 'ListvScrollBar';
+ };
+};
+object 'demo_list' : XmList {
+ arguments {
+ name = 'demoList';
+ XmNvisibleItemCount= 10;
+ XmNautomaticSelection= true;
+ XmNlistSizePolicy= 2;
+ };
+};
+};
+object 'text_line' : XmTextField {
+ arguments {
+ name = 'textLine';
+ };
+};
+object 'vline' : XmSeparator {
+ arguments {
+ name = 'vline';
+ };
+};
+object 'next' : XmPushButton {
+ arguments {
+ name = 'next';
+ XmNlabelString= 'Run Next';
+ };
+};
+object 'prev' : XmPushButton {
+ arguments {
+ name = 'prev';
+ XmNlabelString= 'Run Previous';
+ };
+};
+object 'edit' : XmPushButton {
+ arguments {
+ name = 'edit';
+ XmNlabelString= 'Edit Parameters';
+ };
+};
+object 'done' : XmPushButton {
+ arguments {
+ name = 'done';
+ XmNlabelString= 'Exit Demo Mode';
+ };
+};
+object 'restart' : XmPushButton {
+ arguments {
+ name = 'restart';
+ XmNlabelString= 'Restart Screen Saver';
+ };
+};
+object 'spacer' : XmLabel {
+ arguments {
+ name = 'spacer';
+ XmNlabelString= * ' ';
+ };
+};
+ attachments {
+ attachment {
+ XmNrightAttachment = 1 0 4;
+ XmNleftAttachment = 1 0 4;
+ XmNbottomAttachment = 0 0 0;
+ XmNtopAttachment = 1 0 5;
+ };
+ attachment {
+ XmNrightAttachment = 1 0 4;
+ XmNleftAttachment = 1 0 4;
+ XmNbottomAttachment = 0 0 0;
+ XmNtopAttachment = 3 1 4;
+ };
+ attachment {
+ XmNrightAttachment = 1 0 4;
+ XmNleftAttachment = 1 0 4;
+ XmNbottomAttachment = 3 4 4;
+ XmNtopAttachment = 3 2 4;
+ };
+ attachment {
+ XmNrightAttachment = 1 0 4;
+ XmNleftAttachment = 1 0 4;
+ XmNbottomAttachment = 3 5 4;
+ XmNtopAttachment = 0 0 0;
+ };
+ attachment {
+ XmNrightAttachment = 1 0 4;
+ XmNleftAttachment = 1 0 4;
+ XmNbottomAttachment = 3 6 4;
+ XmNtopAttachment = 0 0 0;
+ };
+ attachment {
+ XmNrightAttachment = 0 0 0;
+ XmNleftAttachment = 1 0 3;
+ XmNbottomAttachment = 1 0 4;
+ XmNtopAttachment = 0 0 0;
+ };
+ attachment {
+ XmNrightAttachment = 0 0 0;
+ XmNleftAttachment = 3 6 4;
+ XmNbottomAttachment = 1 0 4;
+ XmNtopAttachment = 4 6 0;
+ };
+ attachment {
+ XmNrightAttachment = 0 0 0;
+ XmNleftAttachment = 3 7 4;
+ XmNbottomAttachment = 1 0 4;
+ XmNtopAttachment = 4 7 0;
+ };
+ attachment {
+ XmNrightAttachment = 0 0 0;
+ XmNleftAttachment = 3 8 4;
+ XmNbottomAttachment = 1 0 4;
+ XmNtopAttachment = 4 8 0;
+ };
+ attachment {
+ XmNrightAttachment = 0 0 0;
+ XmNleftAttachment = 3 9 4;
+ XmNbottomAttachment = 1 0 4;
+ XmNtopAttachment = 4 9 0;
+ };
+ attachment {
+ XmNrightAttachment = 1 0 4;
+ XmNleftAttachment = 3 10 4;
+ XmNbottomAttachment = 1 0 4;
+ XmNtopAttachment = 4 10 0;
+ };
+ };
+};
+};
+end module;
--- /dev/null
+/* xscreensaver, Copyright (c) 1993 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#if __STDC__
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#endif
+
+#include <pwd.h>
+#include <stdio.h>
+
+#include <X11/Intrinsic.h>
+
+#if !__STDC__
+# define _NO_PROTO
+#endif
+
+#include <Xm/Xm.h>
+#include <Xm/List.h>
+#include <Xm/TextF.h>
+
+#include "xscreensaver.h"
+
+#ifndef NO_LOCKING
+
+Time passwd_timeout;
+
+extern char *screensaver_version;
+extern char *progname;
+extern XtAppContext app;
+extern Bool verbose_p;
+
+extern Widget passwd_dialog;
+extern Widget passwd_form;
+extern Widget roger_label;
+extern Widget passwd_label1;
+extern Widget passwd_label3;
+extern Widget passwd_text;
+extern Widget passwd_done;
+extern Widget passwd_cancel;
+
+extern create_passwd_dialog ();
+
+static enum { pw_read, pw_ok, pw_fail, pw_cancel, pw_time } passwd_state;
+static char typed_passwd [1024];
+
+static char root_passwd [255];
+static char user_passwd [255];
+
+Bool
+lock_init ()
+{
+ Bool ok = True;
+ struct passwd *p;
+ char *u;
+ p = getpwnam ("root");
+ if (p && p->pw_passwd && p->pw_passwd[0] != '*')
+ strcpy (root_passwd, p->pw_passwd);
+ else
+ {
+ fprintf (stderr, "%s: couldn't get root's password\n", progname);
+ strcpy (root_passwd, "*");
+ }
+
+ u = getlogin ();
+ if (u)
+ p = getpwnam (u);
+ else
+ {
+ /* getlogin() fails if not attached to a terminal;
+ in that case, use getpwuid(). */
+ p = getpwuid (getuid ());
+ u = p->pw_name;
+ }
+
+ if (p && p->pw_passwd && p->pw_passwd[0] != '*')
+ strcpy (user_passwd, p->pw_passwd);
+ else
+ {
+ fprintf (stderr, "%s: couldn't get password of \"%s\"\n", progname, u);
+ strcpy (user_passwd, "*");
+ ok = False;
+ }
+ return ok;
+}
+
+static void
+passwd_cancel_cb (button, client_data, call_data)
+ Widget button;
+ XtPointer client_data, call_data;
+{
+ passwd_state = pw_cancel;
+}
+
+static void
+passwd_done_cb (button, client_data, call_data)
+ Widget button;
+ XtPointer client_data, call_data;
+{
+ if (passwd_state != pw_read) return; /* already done */
+ if (!strcmp ((char *) crypt (typed_passwd, user_passwd), user_passwd))
+ passwd_state = pw_ok;
+ /* do not allow root to have empty passwd */
+ else if (typed_passwd [0] &&
+ !strcmp ((char *) crypt (typed_passwd, root_passwd), root_passwd))
+ passwd_state = pw_ok;
+ else
+ passwd_state = pw_fail;
+}
+
+#ifdef VERIFY_CALLBACK_WORKS
+
+ /* #### It looks to me like adding any modifyVerify callback causes
+ #### Motif 1.1.4 to free the the TextF_Value() twice. I can't see
+ #### the bug in the Motif source, but Purify complains, even if
+ #### check_passwd_cb() is a no-op.
+ */
+
+static void
+check_passwd_cb (button, client_data, call_data)
+ Widget button;
+ XtPointer client_data, call_data;
+{
+ XmTextVerifyCallbackStruct *vcb = (XmTextVerifyCallbackStruct *) call_data;
+
+ if (passwd_state != pw_read)
+ return;
+ else if (vcb->reason == XmCR_ACTIVATE)
+ {
+ passwd_done_cb (0, 0, 0);
+ }
+ else if (vcb->text->length > 1) /* don't allow "paste" operations */
+ {
+ vcb->doit = False;
+ }
+ else if (vcb->text->ptr != 0)
+ {
+ int i;
+ strncat (typed_passwd, vcb->text->ptr, vcb->text->length);
+ typed_passwd [vcb->endPos + vcb->text->length] = 0;
+ for (i = 0; i < vcb->text->length; i++)
+ vcb->text->ptr [i] = '*';
+ }
+}
+
+#else /* !VERIFY_CALLBACK_WORKS */
+
+static void keypress();
+static void backspace();
+static void kill_line();
+static void done();
+
+static XtActionsRec actions[] = {{"keypress", keypress},
+ {"backspace", backspace},
+ {"kill_line", kill_line},
+ {"done", done}
+ };
+
+#if 0 /* oh fuck, why doesn't this work? */
+static char translations[] = "\
+<Key>BackSpace: backspace()\n\
+<Key>Delete: backspace()\n\
+Ctrl<Key>H: backspace()\n\
+Ctrl<Key>U: kill_line()\n\
+Ctrl<Key>X: kill_line()\n\
+Ctrl<Key>J: done()\n\
+Ctrl<Key>M: done()\n\
+<Key>: keypress()\n\
+";
+#else
+static char translations[] = "<Key>:keypress()";
+#endif
+
+static void
+keypress (w, event, argv, argc)
+ Widget w;
+ XEvent *event;
+ String *argv;
+ Cardinal *argc;
+{
+ int i, j;
+ char s [sizeof (typed_passwd)];
+ int size = XLookupString ((XKeyEvent *) event, s, sizeof (s), 0, 0);
+ if (size != 1) return;
+
+ /* hack because I can't get translations to dance to my tune... */
+ if (*s == '\010') { backspace (w, event, argv, argc); return; }
+ if (*s == '\177') { backspace (w, event, argv, argc); return; }
+ if (*s == '\025') { kill_line (w, event, argv, argc); return; }
+ if (*s == '\030') { kill_line (w, event, argv, argc); return; }
+ if (*s == '\012') { done (w, event, argv, argc); return; }
+ if (*s == '\015') { done (w, event, argv, argc); return; }
+
+ i = j = strlen (typed_passwd);
+ typed_passwd [i] = *s;
+ s [++i] = 0;
+ while (i--)
+ s [i] = '*';
+ XmTextFieldSetString (passwd_text, s);
+ XmTextFieldSetInsertionPosition (passwd_text, j + 1);
+}
+
+static void
+backspace (w, event, argv, argc)
+ Widget w;
+ XEvent *event;
+ String *argv;
+ Cardinal *argc;
+{
+ char s [sizeof (typed_passwd)];
+ int i = strlen (typed_passwd);
+ int j = i;
+ if (i == 0)
+ return;
+ typed_passwd [--i] = 0;
+ s [i] = 0;
+ while (i--)
+ s [i] = '*';
+ XmTextFieldSetString (passwd_text, s);
+ XmTextFieldSetInsertionPosition (passwd_text, j + 1);
+}
+
+static void
+kill_line (w, event, argv, argc)
+ Widget w;
+ XEvent *event;
+ String *argv;
+ Cardinal *argc;
+{
+ memset (typed_passwd, 0, sizeof (typed_passwd));
+ XmTextFieldSetString (passwd_text, "");
+}
+
+static void
+done (w, event, argv, argc)
+ Widget w;
+ XEvent *event;
+ String *argv;
+ Cardinal *argc;
+{
+ passwd_done_cb (w, 0, 0);
+}
+
+#endif /* !VERIFY_CALLBACK_WORKS */
+
+static void
+format_into_label (widget, string)
+ Widget widget;
+ char *string;
+{
+ char *label;
+ char buf [255];
+ XmString xm_label = 0;
+ XmString new_xm_label;
+ Arg av[10];
+ int ac = 0;
+ XtSetArg (av [ac], XmNlabelString, &xm_label); ac++;
+ XtGetValues (widget, av, ac);
+ XmStringGetLtoR (xm_label, XmSTRING_DEFAULT_CHARSET, &label);
+ if (!strcmp (label, XtName (widget)))
+ strcpy (buf, "ERROR: RESOURCES ARE NOT INSTALLED CORRECTLY");
+ else
+ sprintf (buf, label, string);
+ new_xm_label = XmStringCreate (buf, XmSTRING_DEFAULT_CHARSET);
+ ac = 0;
+ XtSetArg (av [ac], XmNlabelString, new_xm_label); ac++;
+ XtSetValues (widget, av, ac);
+ XmStringFree (new_xm_label);
+ XtFree (label);
+}
+
+#if __STDC__
+extern void skull (Display *, Window, GC, GC, int, int, int, int);
+#endif
+
+static void
+roger (button, client_data, call_data)
+ Widget button;
+ XtPointer client_data, call_data;
+{
+ Display *dpy = XtDisplay (button);
+ Screen *screen = XtScreen (button);
+ Window window = XtWindow (button);
+ Arg av [10];
+ int ac = 0;
+ XGCValues gcv;
+ Colormap cmap;
+ GC draw_gc, erase_gc;
+ unsigned int fg, bg;
+ int x, y, size;
+ XWindowAttributes xgwa;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ cmap = xgwa.colormap;
+ if (xgwa.width > xgwa.height) size = xgwa.height;
+ else size = xgwa.width;
+ if (size > 40) size -= 30;
+ x = (xgwa.width - size) / 2;
+ y = (xgwa.height - size) / 2;
+ XtSetArg (av [ac], XmNforeground, &fg); ac++;
+ XtSetArg (av [ac], XmNbackground, &bg); ac++;
+ XtGetValues (button, av, ac);
+ /* if it's black on white, swap it cause it looks better (hack hack) */
+ if (fg == BlackPixelOfScreen (screen) && bg == WhitePixelOfScreen (screen))
+ fg = WhitePixelOfScreen (screen), bg = BlackPixelOfScreen (screen);
+ gcv.foreground = bg;
+ erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+ gcv.foreground = fg;
+ draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+ XFillRectangle (dpy, window, erase_gc, 0, 0, xgwa.width, xgwa.height);
+ skull (dpy, window, draw_gc, erase_gc, x, y, size, size);
+ XFreeGC (dpy, draw_gc);
+ XFreeGC (dpy, erase_gc);
+}
+
+static void
+make_passwd_dialog (parent)
+ Widget parent;
+{
+ struct passwd *pw;
+ create_passwd_dialog (parent);
+
+ XtAddCallback (passwd_done, XmNactivateCallback, passwd_done_cb, 0);
+ XtAddCallback (passwd_cancel, XmNactivateCallback, passwd_cancel_cb, 0);
+ XtAddCallback (roger_label, XmNexposeCallback, roger, 0);
+
+#ifdef VERIFY_CALLBACK_WORKS
+ XtAddCallback (passwd_text, XmNmodifyVerifyCallback, check_passwd_cb, 0);
+ XtAddCallback (passwd_text, XmNactivateCallback, check_passwd_cb, 0);
+#else
+ XtAddCallback (passwd_text, XmNactivateCallback, passwd_done_cb, 0);
+ XtOverrideTranslations (passwd_text, XtParseTranslationTable (translations));
+#endif
+
+ pw = getpwuid (getuid ());
+ format_into_label (passwd_label3, (pw->pw_name ? pw->pw_name : "???"));
+ format_into_label (passwd_label1, screensaver_version);
+}
+
+
+extern void idle_timer ();
+
+static int passwd_idle_timer_tick;
+static XtIntervalId id;
+
+static void
+passwd_idle_timer (junk1, junk2)
+ void *junk1;
+ XtPointer junk2;
+{
+ Display *dpy = XtDisplay (passwd_form);
+ Window window = XtWindow (passwd_form);
+ static Dimension x, y, d, s, ss;
+ static GC gc = 0;
+ int max = passwd_timeout / 1000;
+
+ idle_timer (junk1, junk2);
+
+ if (passwd_idle_timer_tick == max) /* first time */
+ {
+ Arg av [10];
+ int ac = 0;
+ XGCValues gcv;
+ unsigned long fg, bg;
+ XtSetArg (av [ac], XmNheight, &d); ac++;
+ XtGetValues (passwd_done, av, ac);
+ ac = 0;
+ XtSetArg (av [ac], XmNwidth, &x); ac++;
+ XtSetArg (av [ac], XmNheight, &y); ac++;
+ XtSetArg (av [ac], XmNforeground, &fg); ac++;
+ XtSetArg (av [ac], XmNbackground, &bg); ac++;
+ XtGetValues (passwd_form, av, ac);
+ x -= d;
+ y -= d;
+ d -= 4;
+ gcv.foreground = fg;
+ if (gc) XFreeGC (dpy, gc);
+ gc = XCreateGC (dpy, window, GCForeground, &gcv);
+ s = 360*64 / (passwd_idle_timer_tick - 1);
+ ss = 90*64;
+ XFillArc (dpy, window, gc, x, y, d, d, 0, 360*64);
+ XSetForeground (dpy, gc, bg);
+ x += 1;
+ y += 1;
+ d -= 2;
+ }
+
+ if (--passwd_idle_timer_tick)
+ {
+ id = XtAppAddTimeOut (app, 1000, passwd_idle_timer, 0);
+ XFillArc (dpy, window, gc, x, y, d, d, ss, s);
+ ss += s;
+ }
+}
+
+extern void pop_up_dialog_box ();
+extern int BadWindow_ehandler ();
+
+static Bool
+pop_passwd_dialog (parent)
+ Widget parent;
+{
+ Display *dpy = XtDisplay (passwd_dialog);
+ Window focus;
+ int revert_to;
+ typed_passwd [0] = 0;
+ passwd_state = pw_read;
+ XmTextFieldSetString (passwd_text, "");
+
+ XGetInputFocus (dpy, &focus, &revert_to);
+#ifndef DESTROY_WORKS
+ /* This fucker blows up if we destroy the widget. I can't figure
+ out why. The second destroy phase dereferences freed memory...
+ So we just keep it around; but unrealizing or unmanaging it
+ doesn't work right either, so we hack the window directly. FMH.
+ */
+ if (XtWindow (passwd_form))
+ XMapWindow (dpy, XtWindow (passwd_dialog));
+#endif
+ pop_up_dialog_box (passwd_dialog, passwd_form, 2);
+
+ XtManageChild (passwd_form);
+ XSetInputFocus (dpy, XtWindow (passwd_dialog), revert_to, CurrentTime);
+ XmProcessTraversal (passwd_text, 0);
+
+ passwd_idle_timer_tick = passwd_timeout / 1000;
+ id = XtAppAddTimeOut (app, 1000, passwd_idle_timer, 0);
+
+
+ XGrabServer (dpy); /* ############ DANGER! */
+
+ while (passwd_state == pw_read)
+ {
+ XEvent event;
+ XtAppNextEvent (app, &event);
+ /* wait for timer event */
+ if (event.xany.type == 0 && passwd_idle_timer_tick == 0)
+ passwd_state = pw_time;
+ XtDispatchEvent (&event);
+ }
+ XUngrabServer (dpy);
+ XSync (dpy, False); /* ###### (danger over) */
+
+ if (passwd_state != pw_time)
+ XtRemoveTimeOut (id);
+
+ if (passwd_state != pw_ok)
+ {
+ char *lose;
+ switch (passwd_state)
+ {
+ case pw_time: lose = "Timed out!"; break;
+ case pw_fail: lose = "Sorry!"; break;
+ case pw_cancel: lose = 0; break;
+ default: abort ();
+ }
+ XmProcessTraversal (passwd_cancel, 0); /* turn off I-beam */
+ if (lose)
+ {
+ XmTextFieldSetString (passwd_text, lose);
+ XmTextFieldSetInsertionPosition (passwd_text, strlen (lose) + 1);
+ passwd_idle_timer_tick = 1;
+ id = XtAppAddTimeOut (app, 3000, passwd_idle_timer, 0);
+ while (1)
+ {
+ XEvent event;
+ XtAppNextEvent (app, &event);
+ if (event.xany.type == 0 && /* wait for timer event */
+ passwd_idle_timer_tick == 0)
+ break;
+ XtDispatchEvent (&event);
+ }
+ }
+ }
+ memset (typed_passwd, 0, sizeof (typed_passwd));
+ XmTextFieldSetString (passwd_text, "");
+ XtSetKeyboardFocus (parent, None);
+
+#ifndef DESTROY_WORKS
+ XtDestroyWidget (passwd_dialog);
+ passwd_dialog = 0;
+#else
+ XUnmapWindow (XtDisplay (passwd_dialog), XtWindow (passwd_dialog));
+#endif
+ {
+ int (*old_handler) ();
+ old_handler = XSetErrorHandler (BadWindow_ehandler);
+ /* I don't understand why this doesn't refocus on the old selected
+ window when MWM is running in click-to-type mode. The value of
+ `focus' seems to be correct. */
+ XSetInputFocus (dpy, focus, revert_to, CurrentTime);
+ XSync (dpy, False);
+ XSetErrorHandler (old_handler);
+ }
+
+ return (passwd_state == pw_ok ? True : False);
+}
+
+Bool
+unlock_p (parent)
+ Widget parent;
+{
+ static Bool initted = False;
+ if (! initted)
+ {
+#ifndef VERIFY_CALLBACK_WORKS
+ XtAppAddActions (app, actions, XtNumber (actions));
+#endif
+ passwd_dialog = 0;
+ initted = True;
+ }
+ if (! passwd_dialog)
+ make_passwd_dialog (parent);
+ return pop_passwd_dialog (parent);
+}
+
+#endif /* !NO_LOCKING */
--- /dev/null
+/* xscreensaver, Copyright (c) 1991-1993 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#if __STDC__
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#endif
+
+#include <stdio.h>
+
+#include <X11/Xlib.h> /* not used for much... */
+
+#ifndef ESRCH
+#include <errno.h>
+#endif
+
+#include <sys/time.h> /* sys/resource.h needs this for timeval */
+#include <sys/resource.h> /* for setpriority() and PRIO_PROCESS */
+#include <sys/wait.h> /* for waitpid() and associated macros */
+#include <signal.h> /* for the signal names */
+
+extern char **environ; /* why isn't this in some header file? */
+
+#ifndef NO_SETUID
+#include <pwd.h> /* for getpwnam() and struct passwd */
+#include <grp.h> /* for getgrgid() and struct group */
+#endif /* NO_SETUID */
+
+#if !defined(SIGCHLD) && defined(SIGCLD)
+#define SIGCHLD SIGCLD
+#endif
+
+#if __STDC__
+extern int putenv (const char *); /* getenv() is in stdlib.h... */
+extern int kill (pid_t, int); /* signal() is in sys/signal.h... */
+#endif
+
+# if defined(SVR4) || defined(SYSV)
+# define random() rand()
+# else /* !totally-losing-SYSV */
+extern long random(); /* rand() is in stdlib.h... */
+# endif /* !totally-losing-SYSV */
+
+
+#include "xscreensaver.h"
+
+/* this must be `sh', not whatever $SHELL happens to be. */
+char *shell;
+static pid_t pid = 0;
+char **screenhacks;
+int screenhacks_count;
+int current_hack = -1;
+char *demo_hack;
+int next_mode_p = 0;
+Bool locking_disabled_p = False;
+int nice_inferior = 0;
+
+extern Bool demo_mode_p;
+
+static void
+exec_screenhack (command)
+ char *command;
+{
+ char *tmp;
+ char buf [512];
+ char *av [5];
+ int ac = 0;
+
+ /* Close this fork's version of the display's fd. It will open its own. */
+ close (ConnectionNumber (dpy));
+
+ /* I don't believe what a sorry excuse for an operating system UNIX is!
+
+ - I want to spawn a process.
+ - I want to know it's pid so that I can kill it.
+ - I would like to receive a message when it dies of natural causes.
+ - I want the spawned process to have user-specified arguments.
+
+ The *only way* to parse arguments the way the shells do is to run a
+ shell (or duplicate what they do, which would be a *lot* of code.)
+
+ The *only way* to know the pid of the process is to fork() and exec()
+ it in the spawned side of the fork.
+
+ But if you're running a shell to parse your arguments, this gives you
+ the pid of the SHELL, not the pid of the PROCESS that you're actually
+ interested in, which is an *inferior* of the shell. This also means
+ that the SIGCHLD you get applies to the shell, not its inferior.
+
+ So, the only solution other than implementing an argument parser here
+ is to force the shell to exec() its inferior. What a fucking hack!
+ We prepend "exec " to the command string.
+ */
+ tmp = command;
+ command = (char *) malloc (strlen (tmp) + 6);
+ memcpy (command, "exec ", 5);
+ memcpy (command + 5, tmp, strlen (tmp) + 1);
+
+ /* Invoke the shell as "/bin/sh -c 'exec prog -arg -arg ...'" */
+ av [ac++] = shell;
+ av [ac++] = "-c";
+ av [ac++] = command;
+ av [ac++] = 0;
+
+ if (verbose_p)
+ printf ("%s: spawning \"%s\" in pid %d.\n", progname, command, getpid ());
+
+#if defined(SYSV) || defined(__hpux)
+ {
+ int old_nice = nice (0);
+ int n = nice_inferior - old_nice;
+ errno = 0;
+ if (nice (n) == -1 && errno != 0)
+ {
+ sprintf (buf, "%s: %snice(%d) failed", progname,
+ (verbose_p ? "## " : ""), n);
+ perror (buf);
+ }
+ }
+#else /* !SYSV */
+#ifdef PRIO_PROCESS
+ if (setpriority (PRIO_PROCESS, getpid(), nice_inferior) != 0)
+ {
+ sprintf (buf, "%s: %ssetpriority(PRIO_PROCESS, %d, %d) failed",
+ progname, (verbose_p ? "## " : ""), getpid(), nice_inferior);
+ perror (buf);
+ }
+#else /* !PRIO_PROCESS */
+ if (nice_inferior != 0)
+ fprintf (stderr,
+ "%s: %sdon't know how to change process priority on this system.\n",
+ progname, (verbose_p ? "## " : ""));
+#endif /* !PRIO_PROCESS */
+#endif /* !SYSV */
+
+ /* Now overlay the current process with /bin/sh running the command.
+ If this returns, it's an error.
+ */
+ execve (av [0], av, environ);
+
+ sprintf (buf, "%s: %sexecve() failed", progname, (verbose_p ? "## " : ""));
+ perror (buf);
+ exit (1); /* Note this this only exits a child fork. */
+}
+
+/* to avoid a race between the main thread and the SIGCHLD handler */
+static int killing = 0;
+static Bool suspending = False;
+
+static char *current_hack_name P((void));
+
+static void
+await_child_death (killed)
+ Bool killed;
+{
+ Bool suspended_p = False;
+ int status;
+ pid_t kid;
+ killing = 1;
+ if (! pid)
+ return;
+
+ do
+ {
+ kid = waitpid (pid, &status, WUNTRACED);
+ }
+ while (kid == -1 && errno == EINTR);
+
+ if (kid == pid)
+ {
+ if (WIFEXITED (status))
+ {
+ int exit_status = WEXITSTATUS (status);
+ if (exit_status & 0x80)
+ exit_status |= ~0xFF;
+ if (exit_status != 0 && verbose_p)
+ printf ("%s: child pid %d (%s) exited abnormally (code %d).\n",
+ progname, pid, current_hack_name (), exit_status);
+ else if (verbose_p)
+ printf ("%s: child pid %d (%s) exited normally.\n",
+ progname, pid, current_hack_name ());
+ }
+ else if (WIFSIGNALED (status))
+ {
+ if (!killed || WTERMSIG (status) != SIGTERM)
+ fprintf (stderr,
+ "%s: %schild pid %d (%s) terminated with signal %d!\n",
+ progname, (verbose_p ? "## " : ""),
+ pid, current_hack_name (), WTERMSIG (status));
+ else if (verbose_p)
+ printf ("%s: child pid %d (%s) terminated with SIGTERM.\n",
+ progname, pid, current_hack_name ());
+ }
+ else if (suspending)
+ {
+ suspended_p = True;
+ suspending = False; /* complain if it happens twice */
+ }
+ else if (WIFSTOPPED (status))
+ {
+ suspended_p = True;
+ fprintf (stderr, "%s: %schild pid %d (%s) stopped with signal %d!\n",
+ progname, (verbose_p ? "## " : ""), pid,
+ current_hack_name (), WSTOPSIG (status));
+ }
+ else
+ fprintf (stderr, "%s: %schild pid %d (%s) died in a mysterious way!",
+ progname, (verbose_p ? "## " : ""), pid, current_hack_name());
+ }
+ else if (kid <= 0)
+ fprintf (stderr, "%s: %swaitpid(%d, ...) says there are no kids? (%d)\n",
+ progname, (verbose_p ? "## " : ""), pid, kid);
+ else
+ fprintf (stderr, "%s: %swaitpid(%d, ...) says proc %d died, not %d?\n",
+ progname, (verbose_p ? "## " : ""), pid, kid, pid);
+ killing = 0;
+ if (suspended_p != True)
+ pid = 0;
+}
+
+static char *
+current_hack_name ()
+{
+ static char chn [1024];
+ char *hack = (demo_mode_p ? demo_hack : screenhacks [current_hack]);
+ int i;
+ for (i = 0; hack [i] != 0 && hack [i] != ' ' && hack [i] != '\t'; i++)
+ chn [i] = hack [i];
+ chn [i] = 0;
+ return chn;
+}
+
+#ifdef SIGCHLD
+static void
+sigchld_handler (sig)
+ int sig;
+{
+ if (killing)
+ return;
+ if (! pid)
+ abort ();
+ await_child_death (False);
+}
+#endif
+
+
+void
+init_sigchld ()
+{
+#ifdef SIGCHLD
+ if (((int) signal (SIGCHLD, sigchld_handler)) == -1)
+ {
+ char buf [255];
+ sprintf (buf, "%s: %scouldn't catch SIGCHLD", progname,
+ (verbose_p ? "## " : ""));
+ perror (buf);
+ }
+#endif
+}
+
+
+extern void raise_window P((Bool inhibit_fade, Bool between_hacks_p));
+
+void
+spawn_screenhack (first_time_p)
+ Bool first_time_p;
+{
+ raise_window (first_time_p, True);
+ XFlush (dpy);
+
+ if (screenhacks_count || demo_mode_p)
+ {
+ char *hack;
+ pid_t forked;
+ char buf [255];
+ int new_hack;
+ if (demo_mode_p)
+ {
+ hack = demo_hack;
+ }
+ else
+ {
+ if (screenhacks_count == 1)
+ new_hack = 0;
+ else if (next_mode_p == 1)
+ new_hack = (current_hack + 1) % screenhacks_count,
+ next_mode_p = 0;
+ else if (next_mode_p == 2)
+ {
+ new_hack = ((current_hack + screenhacks_count - 1)
+ % screenhacks_count);
+ next_mode_p = 0;
+ }
+ else
+ while ((new_hack = random () % screenhacks_count) == current_hack)
+ ;
+ current_hack = new_hack;
+ hack = screenhacks[current_hack];
+ }
+
+ switch (forked = fork ())
+ {
+ case -1:
+ sprintf (buf, "%s: %scouldn't fork",
+ progname, (verbose_p ? "## " : ""));
+ perror (buf);
+ restore_real_vroot ();
+ exit (1);
+ case 0:
+ exec_screenhack (hack); /* this does not return */
+ break;
+ default:
+ pid = forked;
+ break;
+ }
+ }
+}
+
+void
+kill_screenhack ()
+{
+ killing = 1;
+ if (! pid)
+ return;
+ if (kill (pid, SIGTERM) < 0)
+ {
+ if (errno == ESRCH)
+ {
+ /* Sometimes we don't get a SIGCHLD at all! WTF?
+ It's a race condition. It looks to me like what's happening is
+ something like: a subprocess dies of natural causes. There is a
+ small window between when the process dies and when the SIGCHLD
+ is (would have been) delivered. If we happen to try to kill()
+ the process during that time, the kill() fails, because the
+ process is already dead. But! no SIGCHLD is delivered (perhaps
+ because the failed kill() has reset some state in the kernel?)
+ Anyway, if kill() says "No such process", then we have to wait()
+ for it anyway, because the process has already become a zombie.
+ I love Unix.
+ */
+ await_child_death (False);
+ }
+ else
+ {
+ char buf [255];
+ sprintf (buf, "%s: %scouldn't kill child process %d", progname,
+ (verbose_p ? "## " : ""), pid);
+ perror (buf);
+ }
+ }
+ else
+ {
+ if (verbose_p)
+ printf ("%s: killing pid %d.\n", progname, pid);
+ await_child_death (True);
+ }
+}
+
+
+void
+suspend_screenhack (suspend_p)
+ Bool suspend_p;
+{
+
+ suspending = suspend_p;
+ if (! pid)
+ ;
+ else if (kill (pid, (suspend_p ? SIGSTOP : SIGCONT)) < 0)
+ {
+ char buf [255];
+ sprintf (buf, "%s: %scouldn't %s child process %d", progname,
+ (verbose_p ? "## " : ""),
+ (suspend_p ? "suspend" : "resume"),
+ pid);
+ perror (buf);
+ }
+ else if (verbose_p)
+ printf ("%s: %s pid %d.\n", progname,
+ (suspend_p ? "suspending" : "resuming"), pid);
+}
+
+\f
+/* Restarting the xscreensaver process from scratch. */
+
+static char **saved_argv;
+
+void
+save_argv (argc, argv)
+ int argc;
+ char **argv;
+{
+ saved_argv = (char **) malloc ((argc + 2) * sizeof (char *));
+ saved_argv [argc] = 0;
+ while (argc--)
+ {
+ int i = strlen (argv [argc]) + 1;
+ saved_argv [argc] = (char *) malloc (i);
+ memcpy (saved_argv [argc], argv [argc], i);
+ }
+}
+
+void
+restart_process ()
+{
+ XCloseDisplay (dpy);
+ fflush (stdout);
+ fflush (stderr);
+ execvp (saved_argv [0], saved_argv);
+ fprintf (stderr, "%s: %scould not restart process: %s (%d)\n",
+ progname, (verbose_p ? "## " : ""),
+ (errno == E2BIG ? "arglist too big" :
+ errno == EACCES ? "could not execute" :
+ errno == EFAULT ? "memory fault" :
+ errno == EIO ? "I/O error" :
+ errno == ENAMETOOLONG ? "name too long" :
+ errno == ELOOP ? "too many symbolic links" :
+ errno == ENOENT ? "file no longer exists" :
+ errno == ENOTDIR ? "directory no longer exists" :
+ errno == ENOEXEC ? "bad executable file" :
+ errno == ENOMEM ? "out of memory" :
+ "execvp() returned unknown error code"),
+ errno);
+ exit (1);
+}
+
+void
+demo_mode_restart_process ()
+{
+ int i;
+ for (i = 0; saved_argv [i]; i++);
+ /* add the -demo switch; save_argv() left room for this. */
+ saved_argv [i] = "-demo";
+ saved_argv [i+1] = 0;
+ restart_process ();
+}
+
+void
+hack_environment ()
+{
+ /* Store $DISPLAY into the environment, so that the $DISPLAY variable that
+ the spawned processes inherit is the same as the value of -display passed
+ in on our command line (which is not necessarily the same as what our
+ $DISPLAY variable is.)
+ */
+ char *s, buf [2048];
+ int i;
+ sprintf (buf, "DISPLAY=%s", DisplayString (dpy));
+ i = strlen (buf);
+ s = (char *) malloc (i+1);
+ strncpy (s, buf, i+1);
+ if (putenv (s))
+ abort ();
+}
+
+\f
+/* Change the uid/gid of the screensaver process, so that it is safe for it
+ to run setuid root (which it needs to do on some systems to read the
+ encrypted passwords from the passwd file.)
+
+ hack_uid() is run before opening the X connection, so that XAuth works.
+ hack_uid_warn() is called after the connection is opened and the command
+ line arguments are parsed, so that the messages from hack_uid() get
+ printed after we know whether we're in `verbose' mode.
+ */
+
+#ifndef NO_SETUID
+
+static int hack_uid_errno;
+static char hack_uid_buf [255], *hack_uid_error;
+
+void
+hack_uid ()
+{
+ /* If we've been run as setuid or setgid to someone else (most likely root)
+ turn off the extra permissions so that random user-specified programs
+ don't get special privileges. (On some systems it might be necessary
+ to install this as setuid root in order to read the passwd file to
+ implement lock-mode...)
+ */
+ setgid (getgid ());
+ setuid (getuid ());
+
+ hack_uid_errno = 0;
+ hack_uid_error = 0;
+
+ /* If we're being run as root (as from xdm) then switch the user id
+ to something safe. */
+ if (getuid () == 0)
+ {
+ struct passwd *p = getpwnam ("nobody");
+ locking_disabled_p = True;
+ if (! p) p = getpwnam ("daemon");
+ if (! p) p = getpwnam ("bin");
+ if (! p) p = getpwnam ("sys");
+ if (! p)
+ {
+ hack_uid_error = "couldn't find safe uid; running as root.";
+ hack_uid_errno = -1;
+ }
+ else
+ {
+ struct group *g = getgrgid (p->pw_gid);
+ hack_uid_error = hack_uid_buf;
+ sprintf (hack_uid_error, "changing uid/gid to %s/%s (%d/%d).",
+ p->pw_name, (g ? g->gr_name : "???"), p->pw_uid, p->pw_gid);
+
+ /* Change the gid to be a safe one. If we can't do that, then
+ print a warning. We change the gid before the uid so that we
+ change the gid while still root. */
+ if (setgid (p->pw_gid) != 0)
+ {
+ hack_uid_errno = errno;
+ sprintf (hack_uid_error, "couldn't set gid to %s (%d)",
+ (g ? g->gr_name : "???"), p->pw_gid);
+ }
+
+ /* Now change the uid to be a safe one. */
+ if (setuid (p->pw_uid) != 0)
+ {
+ hack_uid_errno = errno;
+ sprintf (hack_uid_error, "couldn't set uid to %s (%d)",
+ p->pw_name, p->pw_uid);
+ }
+ }
+ }
+#ifndef NO_LOCKING
+ else /* disable locking if already being run as "someone else" */
+ {
+ struct passwd *p = getpwuid (getuid ());
+ if (!p ||
+ !strcmp (p->pw_name, "root") ||
+ !strcmp (p->pw_name, "nobody") ||
+ !strcmp (p->pw_name, "daemon") ||
+ !strcmp (p->pw_name, "bin") ||
+ !strcmp (p->pw_name, "sys"))
+ locking_disabled_p = True;
+ }
+#endif /* NO_LOCKING */
+}
+
+void
+hack_uid_warn ()
+{
+ if (! hack_uid_error)
+ ;
+ else if (hack_uid_errno == 0)
+ {
+ if (verbose_p)
+ printf ("%s: %s\n", progname, hack_uid_error);
+ }
+ else
+ {
+ char buf [255];
+ sprintf (buf, "%s: %s%s", progname, (verbose_p ? "## " : ""),
+ hack_uid_error);
+ if (hack_uid_errno == -1)
+ fprintf (stderr, "%s\n", buf);
+ else
+ {
+ errno = hack_uid_errno;
+ perror (buf);
+ }
+ }
+}
+
+#endif /* !NO_SETUID */
--- /dev/null
+/* xscreensaver, Copyright (c) 1991-1993 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Intrinsic.h>
+#include <X11/Xos.h>
+#include <X11/Xmu/Error.h>
+
+#ifdef HAVE_XIDLE
+#include <X11/extensions/xidle.h>
+#endif
+
+#include "xscreensaver.h"
+
+extern XtAppContext app;
+
+Time cycle;
+Time timeout;
+Time pointer_timeout;
+Time notice_events_timeout;
+
+extern Bool use_xidle;
+extern Bool dbox_up_p;
+extern Bool locked_p;
+extern Window screensaver_window;
+
+extern Bool handle_clientmessage P((/*XEvent *, Bool*/));
+
+static time_t last_activity_time; /* for non-XIdle mode */
+static XtIntervalId timer_id = 0;
+static XtIntervalId check_pointer_timer_id = 0;
+XtIntervalId cycle_id = 0;
+XtIntervalId lock_id = 0;
+
+void
+idle_timer (junk1, junk2)
+ void *junk1;
+ XtPointer junk2;
+{
+ /* What an amazingly shitty design. Not only does Xt execute timeout
+ events from XtAppNextEvent() instead of from XtDispatchEvent(), but
+ there is no way to tell Xt to block until there is an X event OR a
+ timeout happens. Once your timeout proc is called, XtAppNextEvent()
+ still won't return until a "real" X event comes in.
+
+ So this function pushes a stupid, gratuitous, unnecessary event back
+ on the event queue to force XtAppNextEvent to return Right Fucking Now.
+ When the code in sleep_until_idle() sees an event of type XAnyEvent,
+ which the server never generates, it knows that a timeout has occurred.
+ */
+ XEvent fake_event;
+ fake_event.type = 0; /* XAnyEvent type, ignored. */
+ fake_event.xany.display = dpy;
+ fake_event.xany.window = 0;
+ XPutBackEvent (dpy, &fake_event);
+}
+
+
+static void
+notice_events (window, top_p)
+ Window window;
+ Bool top_p;
+{
+ XWindowAttributes attrs;
+ unsigned long events;
+ Window root, parent, *kids;
+ unsigned int nkids;
+
+ if (XtWindowToWidget (dpy, window))
+ /* If it's one of ours, don't mess up its event mask. */
+ return;
+
+ if (!XQueryTree (dpy, window, &root, &parent, &kids, &nkids))
+ return;
+ if (window == root)
+ top_p = False;
+
+ XGetWindowAttributes (dpy, window, &attrs);
+ events = ((attrs.all_event_masks | attrs.do_not_propagate_mask)
+ & KeyPressMask);
+
+ /* Select for SubstructureNotify on all windows.
+ Select for KeyPress on all windows that already have it selected.
+ Do we need to select for ButtonRelease? I don't think so.
+ */
+ XSelectInput (dpy, window, SubstructureNotifyMask | events);
+
+ if (top_p && verbose_p && (events & KeyPressMask))
+ {
+ /* Only mention one window per tree (hack hack). */
+ printf ("%s: selected KeyPress on 0x%X\n", progname, window);
+ top_p = False;
+ }
+
+ if (kids)
+ {
+ while (nkids)
+ notice_events (kids [--nkids], top_p);
+ XFree ((char *) kids);
+ }
+}
+
+
+int
+BadWindow_ehandler (dpy, error)
+ Display *dpy;
+ XErrorEvent *error;
+{
+ /* When we notice a window being created, we spawn a timer that waits
+ 30 seconds or so, and then selects events on that window. This error
+ handler is used so that we can cope with the fact that the window
+ may have been destroyed <30 seconds after it was created.
+ */
+ if (error->error_code == BadWindow ||
+ error->error_code == BadDrawable)
+ return 0;
+ XmuPrintDefaultErrorMessage (dpy, error, stderr);
+ exit (1);
+}
+
+void
+notice_events_timer (closure, timer)
+ XtPointer closure;
+ void *timer;
+{
+ Window window = (Window) closure;
+ int (*old_handler) ();
+ old_handler = XSetErrorHandler (BadWindow_ehandler);
+ notice_events (window, True);
+ XSync (dpy, False);
+ XSetErrorHandler (old_handler);
+}
+
+
+/* When the screensaver is active, this timer will periodically change
+ the running program.
+ */
+void
+cycle_timer (junk1, junk2)
+ void *junk1;
+ XtPointer junk2;
+{
+ Time how_long = cycle;
+ if (dbox_up_p)
+ {
+ if (verbose_p)
+ printf ("%s: dbox up; delaying hack change.\n", progname);
+ how_long = 30000; /* 30 secs */
+ }
+ else
+ {
+ if (verbose_p)
+ printf ("%s: changing graphics hacks.\n", progname);
+ kill_screenhack ();
+ spawn_screenhack (False);
+ }
+ cycle_id = XtAppAddTimeOut (app, how_long, cycle_timer, 0);
+}
+
+
+void
+activate_lock_timer (junk1, junk2)
+ void *junk1;
+ XtPointer junk2;
+{
+ if (verbose_p)
+ printf ("%s: timed out; activating lock\n", progname);
+ locked_p = True;
+}
+
+
+/* Call this when user activity (or "simulated" activity) has been noticed.
+ */
+static void
+reset_timers ()
+{
+#ifdef DEBUG_TIMERS
+ if (verbose_p)
+ printf ("%s: restarting idle_timer (%d, %d)\n",
+ progname, timeout, timer_id);
+#endif
+ XtRemoveTimeOut (timer_id);
+ timer_id = XtAppAddTimeOut (app, timeout, idle_timer, 0);
+ if (cycle_id) abort ();
+
+ last_activity_time = time ((time_t *) 0);
+}
+
+/* When we aren't using XIdle, this timer is used to periodically wake up
+ and poll the mouse position, which is possibly more reliable than
+ selecting motion events on every window.
+ */
+static void
+check_pointer_timer (closure, this_timer)
+ void *closure;
+ XtPointer this_timer;
+{
+ static int last_root_x = -1;
+ static int last_root_y = -1;
+ static Window last_child = (Window) -1;
+ static unsigned int last_mask = 0;
+ Window root, child;
+ int root_x, root_y, x, y;
+ unsigned int mask;
+ XtIntervalId *timerP = (XtIntervalId *) closure;
+#ifdef HAVE_XIDLE
+ if (use_xidle)
+ abort ();
+#endif
+
+ *timerP = XtAppAddTimeOut (app, pointer_timeout, check_pointer_timer,
+ closure);
+
+ XQueryPointer (dpy, screensaver_window, &root, &child,
+ &root_x, &root_y, &x, &y, &mask);
+ if (root_x == last_root_x && root_y == last_root_y &&
+ child == last_child && mask == last_mask)
+ return;
+
+#ifdef DEBUG_TIMERS
+ if (verbose_p && this_timer)
+ if (root_x == last_root_x && root_y == last_root_y && child == last_child)
+ printf ("%s: modifiers changed at %s.\n", progname, timestring ());
+ else
+ printf ("%s: pointer moved at %s.\n", progname, timestring ());
+#endif
+
+ last_root_x = root_x;
+ last_root_y = root_y;
+ last_child = child;
+ last_mask = mask;
+
+ reset_timers ();
+}
+
+
+void
+sleep_until_idle (until_idle_p)
+ Bool until_idle_p;
+{
+ XEvent event;
+
+ if (until_idle_p)
+ {
+ timer_id = XtAppAddTimeOut (app, timeout, idle_timer, 0);
+#ifdef HAVE_XIDLE
+ if (! use_xidle)
+#endif
+ /* start polling the mouse position */
+ check_pointer_timer (&check_pointer_timer_id, 0);
+ }
+
+ while (1)
+ {
+ XtAppNextEvent (app, &event);
+
+ switch (event.xany.type) {
+ case 0: /* our synthetic "timeout" event has been signalled */
+ if (until_idle_p)
+ {
+ Time idle;
+#ifdef HAVE_XIDLE
+ if (use_xidle)
+ {
+ if (! XGetIdleTime (dpy, &idle))
+ {
+ fprintf (stderr, "%s: %sXGetIdleTime() failed.\n",
+ progname, (verbose_p ? "## " : ""));
+ exit (1);
+ }
+ }
+ else
+#endif /* HAVE_XIDLE */
+ idle = 1000 * (last_activity_time - time ((time_t *) 0));
+
+ if (idle >= timeout)
+ goto DONE;
+ else
+ timer_id = XtAppAddTimeOut (app, timeout - idle,
+ idle_timer, 0);
+ }
+ break;
+
+ case ClientMessage:
+ if (handle_clientmessage (&event, until_idle_p))
+ goto DONE;
+ break;
+
+ case CreateNotify:
+#ifdef HAVE_XIDLE
+ if (! use_xidle)
+#endif
+ XtAppAddTimeOut (app, notice_events_timeout, notice_events_timer,
+ (XtPointer) event.xcreatewindow.window);
+ break;
+
+ case KeyPress:
+ case KeyRelease:
+ case ButtonPress:
+ case ButtonRelease:
+ case MotionNotify:
+
+#ifdef DEBUG_TIMERS
+ if (verbose_p)
+ {
+ if (event.xany.type == MotionNotify)
+ printf ("%s: MotionNotify at %s\n", progname, timestring ());
+ else if (event.xany.type == KeyPress)
+ printf ("%s: KeyPress seen on 0x%X at %s\n", progname,
+ event.xkey.window, timestring ());
+ }
+#endif
+
+ /* We got a user event */
+ if (!until_idle_p)
+ goto DONE;
+ else
+ reset_timers ();
+ break;
+
+ default:
+ XtDispatchEvent (&event);
+ }
+ }
+ DONE:
+
+ if (check_pointer_timer_id)
+ {
+ XtRemoveTimeOut (check_pointer_timer_id);
+ check_pointer_timer_id = 0;
+ }
+ if (timer_id)
+ {
+ XtRemoveTimeOut (timer_id);
+ timer_id = 0;
+ }
+
+ if (until_idle_p && cycle_id)
+ abort ();
+
+ return;
+}
--- /dev/null
+/* xscreensaver, Copyright (c) 1993 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+/* This file contains some code for intelligently picking the best visual
+ (where "best" is somewhat biased in the direction of writable cells...)
+ */
+
+#if __STDC__
+#include <stdlib.h>
+#endif
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#ifndef isupper
+# define isupper(c) ((c) >= 'A' && (c) <= 'Z')
+#endif
+#ifndef _tolower
+# define _tolower(c) ((c) - 'A' + 'a')
+#endif
+
+extern char *progname;
+extern char *get_string_resource ();
+
+static Visual *
+pick_best_visual_of_class (display, visual_class)
+ Display *display;
+ int visual_class;
+{
+ XVisualInfo vi_in, *vi_out;
+ int out_count;
+
+ vi_in.class = visual_class;
+ vi_in.screen = DefaultScreen (display);
+ vi_out = XGetVisualInfo (display, VisualClassMask|VisualScreenMask,
+ &vi_in, &out_count);
+ if (vi_out)
+ { /* choose the 'best' one, if multiple */
+ int i, best;
+ Visual *visual;
+ for (i = 0, best = 0; i < out_count; i++)
+ if (vi_out [i].depth > vi_out [best].depth)
+ best = i;
+ visual = vi_out [best].visual;
+ XFree ((char *) vi_out);
+ return visual;
+ }
+ else
+ return 0;
+}
+
+static Visual *
+pick_best_visual (display)
+ Display *display;
+{
+ Visual *visual;
+ if (visual = pick_best_visual_of_class (display, PseudoColor))
+ return visual;
+ if (visual = pick_best_visual_of_class (display, DirectColor))
+ return visual;
+ if (visual = pick_best_visual_of_class (display, GrayScale))
+ return visual;
+ if (visual = pick_best_visual_of_class (display, StaticGray))
+ return visual;
+ return DefaultVisual (display, DefaultScreen (display));
+}
+
+
+static Visual *
+id_to_visual (dpy, id)
+ Display *dpy;
+ int id;
+{
+ XVisualInfo vi_in, *vi_out;
+ int out_count;
+ vi_in.screen = DefaultScreen (dpy);
+ vi_in.visualid = id;
+ vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
+ &vi_in, &out_count);
+ if (vi_out)
+ {
+ Visual *v = vi_out[0].visual;
+ XFree ((char *) vi_out);
+ return v;
+ }
+ return 0;
+}
+
+int
+get_visual_depth (dpy, visual)
+ Display *dpy;
+ Visual *visual;
+{
+ XVisualInfo vi_in, *vi_out;
+ int out_count, d;
+ vi_in.screen = DefaultScreen (dpy);
+ vi_in.visualid = XVisualIDFromVisual (visual);
+ vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
+ &vi_in, &out_count);
+ if (! vi_out) abort ();
+ d = vi_out [0].depth;
+ XFree ((char *) vi_out);
+ return d;
+}
+
+
+Visual *
+get_visual_resource (dpy, name, class)
+ Display *dpy;
+ char *name, *class;
+{
+ char c, *s = get_string_resource (name, class);
+ char *tmp;
+ int vclass;
+ int id;
+
+ if (s)
+ for (tmp = s; *tmp; tmp++)
+ if (isupper (*tmp)) *tmp = _tolower (*tmp);
+
+ if (!s || !strcmp (s, "best")) vclass = -1;
+ else if (!strcmp (s, "default")) vclass = -2;
+ else if (!strcmp (s, "staticgray")) vclass = StaticGray;
+ else if (!strcmp (s, "staticcolor")) vclass = StaticColor;
+ else if (!strcmp (s, "truecolor")) vclass = TrueColor;
+ else if (!strcmp (s, "grayscale")) vclass = GrayScale;
+ else if (!strcmp (s, "pseudocolor")) vclass = PseudoColor;
+ else if (!strcmp (s, "directcolor")) vclass = DirectColor;
+ else if (1 == sscanf (s, " %ld %c", &id, &c)) vclass = -3;
+ else if (1 == sscanf (s, " 0x%lx %c", &id, &c)) vclass = -3;
+ else
+ {
+ fprintf (stderr, "%s: unrecognized visual \"%s\".\n", progname, s);
+ vclass = -1;
+ }
+ if (s) free (s);
+
+ if (vclass == -1)
+ return pick_best_visual (dpy);
+ else if (vclass == -2)
+ return DefaultVisual (dpy, DefaultScreen (dpy));
+ else if (vclass == -3)
+ {
+ Visual *v = id_to_visual (dpy, id);
+ if (v) return v;
+ fprintf (stderr, "%s: no visual with id 0x%x.\n", progname, id);
+ return pick_best_visual (dpy);
+ }
+ else
+ return pick_best_visual_of_class (dpy, vclass);
+}
--- /dev/null
+/* xscreensaver, Copyright (c) 1991-1993 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/Xos.h>
+#include <X11/Xmu/SysUtil.h>
+
+#include <signal.h> /* for the signal names */
+
+#include "xscreensaver.h"
+
+#if __STDC__
+extern int kill (pid_t, int); /* signal() is in sys/signal.h... */
+#endif /* __STDC__ */
+
+extern Bool lock_p, demo_mode_p;
+
+Atom XA_VROOT, XA_XSETROOT_ID;
+Atom XA_SCREENSAVER_VERSION, XA_SCREENSAVER_ID;
+
+Window screensaver_window = 0;
+Cursor cursor;
+Colormap cmap, cmap2;
+Bool install_cmap_p;
+Bool fade_p, unfade_p;
+int fade_seconds, fade_ticks;
+
+static unsigned long black_pixel;
+static Window real_vroot, real_vroot_value;
+
+#define ALL_POINTER_EVENTS \
+ (ButtonPressMask | ButtonReleaseMask | EnterWindowMask | \
+ LeaveWindowMask | PointerMotionMask | PointerMotionHintMask | \
+ Button1MotionMask | Button2MotionMask | Button3MotionMask | \
+ Button4MotionMask | Button5MotionMask | ButtonMotionMask)
+
+/* I don't really understand Sync vs Async, but these seem to work... */
+#define grab_kbd(win) \
+ XGrabKeyboard (dpy, (win), True, GrabModeSync, GrabModeAsync, CurrentTime)
+#define grab_mouse(win) \
+ XGrabPointer (dpy, (win), True, ALL_POINTER_EVENTS, \
+ GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime)
+
+void
+grab_keyboard_and_mouse ()
+{
+ Status status;
+ XSync (dpy, False);
+
+ if (demo_mode_p) return;
+
+ status = grab_kbd (screensaver_window);
+ if (status != GrabSuccess)
+ { /* try again in a second */
+ sleep (1);
+ status = grab_kbd (screensaver_window);
+ if (status != GrabSuccess)
+ fprintf (stderr, "%s: %scouldn't grab keyboard! (%d)\n",
+ progname, (verbose_p ? "## " : ""), status);
+ }
+ status = grab_mouse (screensaver_window);
+ if (status != GrabSuccess)
+ { /* try again in a second */
+ sleep (1);
+ status = grab_mouse (screensaver_window);
+ if (status != GrabSuccess)
+ fprintf (stderr, "%s: %scouldn't grab pointer! (%d)\n",
+ progname, (verbose_p ? "## " : ""), status);
+ }
+}
+
+void
+ungrab_keyboard_and_mouse ()
+{
+ XUngrabPointer (dpy, CurrentTime);
+ XUngrabKeyboard (dpy, CurrentTime);
+}
+
+
+void
+ensure_no_screensaver_running ()
+{
+ int i;
+ Window root = RootWindowOfScreen (screen);
+ Window root2, parent, *kids;
+ unsigned int nkids;
+ int (*old_handler) ();
+
+ old_handler = XSetErrorHandler (BadWindow_ehandler);
+
+ if (! XQueryTree (dpy, root, &root2, &parent, &kids, &nkids))
+ abort ();
+ if (root != root2)
+ abort ();
+ if (parent)
+ abort ();
+ for (i = 0; i < nkids; i++)
+ {
+ Atom type;
+ int format;
+ unsigned long nitems, bytesafter;
+ char *version;
+
+ if (XGetWindowProperty (dpy, kids[i], XA_SCREENSAVER_VERSION, 0, 1,
+ False, XA_STRING, &type, &format, &nitems,
+ &bytesafter, (unsigned char **) &version)
+ == Success
+ && type != None)
+ {
+ char *id;
+ if (!XGetWindowProperty (dpy, kids[i], XA_SCREENSAVER_ID, 0, 512,
+ False, XA_STRING, &type, &format, &nitems,
+ &bytesafter, (unsigned char **) &id)
+ == Success
+ || type == None)
+ id = "???";
+
+ fprintf (stderr,
+ "%s: %salready running on display %s (window 0x%x)\n from process %s.\n",
+ progname, (verbose_p ? "## " : ""), DisplayString (dpy),
+ (int) kids [i], id);
+ exit (1);
+ }
+ }
+
+ if (kids) XFree ((char *) kids);
+ XSync (dpy, False);
+ XSetErrorHandler (old_handler);
+}
+
+
+void
+disable_builtin_screensaver ()
+{
+ int timeout, interval, prefer_blank, allow_exp;
+ XForceScreenSaver (dpy, ScreenSaverReset);
+ XGetScreenSaver (dpy, &timeout, &interval, &prefer_blank, &allow_exp);
+ if (timeout != 0)
+ {
+ XSetScreenSaver (dpy, 0, interval, prefer_blank, allow_exp);
+ printf ("%s%sisabling server builtin screensaver.\n\
+ You can re-enable it with \"xset s on\".\n",
+ (verbose_p ? "" : progname), (verbose_p ? "\n\tD" : ": d"));
+ }
+}
+
+\f
+/* Virtual-root hackery */
+
+#ifdef _VROOT_H_
+ERROR! You must not include vroot.h in this file.
+#endif
+
+static void
+store_vroot_property (win, value)
+ Window win, value;
+{
+#if 0
+ printf ("%s: storing XA_VROOT = 0x%x (%s) = 0x%x (%s)\n", progname,
+ win,
+ (win == screensaver_window ? "ScreenSaver" :
+ (win == real_vroot ? "VRoot" :
+ (win == real_vroot_value ? "Vroot_value" : "???"))),
+ value,
+ (value == screensaver_window ? "ScreenSaver" :
+ (value == real_vroot ? "VRoot" :
+ (value == real_vroot_value ? "Vroot_value" : "???"))));
+#endif
+ XChangeProperty (dpy, win, XA_VROOT, XA_WINDOW, 32, PropModeReplace,
+ (unsigned char *) &value, 1);
+}
+
+static void
+remove_vroot_property (win)
+ Window win;
+{
+#if 0
+ printf ("%s: removing XA_VROOT from 0x%x (%s)\n", progname, win,
+ (win == screensaver_window ? "ScreenSaver" :
+ (win == real_vroot ? "VRoot" :
+ (win == real_vroot_value ? "Vroot_value" : "???"))));
+#endif
+ XDeleteProperty (dpy, win, XA_VROOT);
+}
+
+
+static void
+kill_xsetroot_data ()
+{
+ Atom type;
+ int format;
+ unsigned long nitems, bytesafter;
+ Pixmap *dataP = 0;
+
+ /* If the user has been using xv or xsetroot as a screensaver (to display
+ an image on the screensaver window, as a kind of slideshow) then the
+ pixmap and its associated color cells have been put in RetainPermanent
+ CloseDown mode. Since we're not destroying the xscreensaver window,
+ but merely unmapping it, we need to free these resources or those
+ colormap cells will stay allocated while the screensaver is off. (We
+ could just delete the screensaver window and recreate it later, but
+ that could cause other problems.) This code does an atomic read-and-
+ delete of the _XSETROOT_ID property, and if it held a pixmap, then we
+ cause the RetainPermanent resources of the client which created it
+ (and which no longer exists) to be freed.
+ */
+ if (XGetWindowProperty (dpy, screensaver_window, XA_XSETROOT_ID, 0, 1,
+ True, AnyPropertyType, &type, &format, &nitems,
+ &bytesafter, (unsigned char **) &dataP)
+ == Success
+ && type != None)
+ {
+ if (dataP && *dataP && type == XA_PIXMAP && format == 32 &&
+ nitems == 1 && bytesafter == 0)
+ {
+ if (verbose_p)
+ printf ("%s: destroying xsetroot data (0x%X).\n",
+ progname, *dataP);
+ XKillClient (dpy, *dataP);
+ }
+ else
+ fprintf (stderr, "%s: %sdeleted unrecognised _XSETROOT_ID property: \n\
+ %d, %d; type: %d, format: %d, nitems: %d, bytesafter %d\n",
+ progname, (verbose_p ? "## " : ""),
+ dataP, (dataP ? *dataP : 0), type,
+ format, nitems, bytesafter);
+ }
+}
+
+
+static void handle_signals P((Bool on_p));
+
+static void
+save_real_vroot ()
+{
+ int i;
+ Window root = RootWindowOfScreen (screen);
+ Window root2, parent, *kids;
+ unsigned int nkids;
+
+ real_vroot = 0;
+ real_vroot_value = 0;
+ if (! XQueryTree (dpy, root, &root2, &parent, &kids, &nkids))
+ abort ();
+ if (root != root2)
+ abort ();
+ if (parent)
+ abort ();
+ for (i = 0; i < nkids; i++)
+ {
+ Atom type;
+ int format;
+ unsigned long nitems, bytesafter;
+ Window *vrootP = 0;
+
+ if (XGetWindowProperty (dpy, kids[i], XA_VROOT, 0, 1, False, XA_WINDOW,
+ &type, &format, &nitems, &bytesafter,
+ (unsigned char **) &vrootP)
+ != Success)
+ continue;
+ if (! vrootP)
+ continue;
+ if (real_vroot)
+ {
+ if (*vrootP == screensaver_window) abort ();
+ fprintf (stderr,
+ "%s: %smore than one virtual root window found (0x%x and 0x%x).\n",
+ progname, (verbose_p ? "## " : ""),
+ (int) real_vroot, (int) kids [i]);
+ exit (1);
+ }
+ real_vroot = kids [i];
+ real_vroot_value = *vrootP;
+ }
+
+ if (real_vroot)
+ {
+ handle_signals (True);
+ remove_vroot_property (real_vroot);
+ XSync (dpy, False);
+ }
+
+ XFree ((char *) kids);
+}
+
+static Bool
+restore_real_vroot_1 ()
+{
+ if (verbose_p && real_vroot)
+ printf ("%s: restoring __SWM_VROOT property on the real vroot (0x%x).\n",
+ progname, real_vroot);
+ remove_vroot_property (screensaver_window);
+ if (real_vroot)
+ {
+ store_vroot_property (real_vroot, real_vroot_value);
+ real_vroot = 0;
+ real_vroot_value = 0;
+ /* make sure the property change gets there before this process
+ terminates! We might be doing this because we have intercepted
+ SIGTERM or something. */
+ XSync (dpy, False);
+ return True;
+ }
+ return False;
+}
+
+void
+restore_real_vroot ()
+{
+ if (restore_real_vroot_1 ())
+ handle_signals (False);
+}
+
+\f
+/* Signal hackery to ensure that the vroot doesn't get left in an
+ inconsistent state
+ */
+
+static const char *sig_names [255] = { 0 };
+
+static void
+restore_real_vroot_handler (sig)
+ int sig;
+{
+ signal (sig, SIG_DFL);
+ if (restore_real_vroot_1 ())
+ fprintf (stderr, "\n%s: %s%s (%d) intercepted, vroot restored.\n",
+ progname, (verbose_p ? "## " : ""),
+ ((sig < sizeof(sig_names) && sig >= 0 && sig_names [sig])
+ ? sig_names [sig] : "unknown signal"),
+ sig);
+ kill (getpid (), sig);
+}
+
+
+static void
+catch_signal (sig, signame, on_p)
+ int sig;
+ char *signame;
+ Bool on_p;
+{
+ if (! on_p)
+ signal (sig, SIG_DFL);
+ else
+ {
+ sig_names [sig] = signame;
+ if (((int) signal (sig, restore_real_vroot_handler)) == -1)
+ {
+ char buf [255];
+ sprintf (buf, "%s: %scouldn't catch %s (%d)", progname,
+ (verbose_p ? "## " : ""), signame, sig);
+ perror (buf);
+ restore_real_vroot ();
+ exit (1);
+ }
+ }
+}
+
+static void
+handle_signals (on_p)
+ Bool on_p;
+{
+#if 0
+ if (on_p) printf ("handling signals\n");
+ else printf ("unhandling signals\n");
+#endif
+
+ catch_signal (SIGHUP, "SIGHUP", on_p);
+ catch_signal (SIGINT, "SIGINT", on_p);
+ catch_signal (SIGQUIT, "SIGQUIT", on_p);
+ catch_signal (SIGILL, "SIGILL", on_p);
+ catch_signal (SIGTRAP, "SIGTRAP", on_p);
+ catch_signal (SIGIOT, "SIGIOT", on_p);
+ catch_signal (SIGABRT, "SIGABRT", on_p);
+#ifdef SIGEMT
+ catch_signal (SIGEMT, "SIGEMT", on_p);
+#endif
+ catch_signal (SIGFPE, "SIGFPE", on_p);
+ catch_signal (SIGBUS, "SIGBUS", on_p);
+ catch_signal (SIGSEGV, "SIGSEGV", on_p);
+ catch_signal (SIGSYS, "SIGSYS", on_p);
+ catch_signal (SIGTERM, "SIGTERM", on_p);
+#ifdef SIGXCPU
+ catch_signal (SIGXCPU, "SIGXCPU", on_p);
+#endif
+#ifdef SIGXFSZ
+ catch_signal (SIGXFSZ, "SIGXFSZ", on_p);
+#endif
+#ifdef SIGDANGER
+ catch_signal (SIGDANGER, "SIGDANGER", on_p);
+#endif
+}
+
+\f
+/* Managing the actual screensaver window */
+
+void
+initialize_screensaver_window ()
+{
+ /* This resets the screensaver window as fully as possible, since there's
+ no way of knowing what some random client may have done to us in the
+ meantime. We could just destroy and recreate the window, but that has
+ its own set of problems...
+ */
+ XColor black;
+ XClassHint class_hints;
+ XSetWindowAttributes attrs;
+ unsigned long attrmask;
+ int width = WidthOfScreen (screen);
+ int height = HeightOfScreen (screen);
+ char id [2048];
+
+ if (cmap == DefaultColormapOfScreen (screen))
+ cmap = 0;
+
+ if ((install_cmap_p && !demo_mode_p) ||
+ (visual != DefaultVisualOfScreen (screen)))
+ {
+ if (! cmap)
+ {
+ cmap = XCreateColormap (dpy, RootWindowOfScreen (screen),
+ visual, AllocNone);
+ if (! XAllocColor (dpy, cmap, &black)) abort ();
+ black_pixel = black.pixel;
+ }
+ }
+ else
+ {
+ if (cmap)
+ {
+ XFreeColors (dpy, cmap, &black_pixel, 1, 0);
+ XFreeColormap (dpy, cmap);
+ }
+ cmap = DefaultColormapOfScreen (screen);
+ black_pixel = BlackPixelOfScreen (screen);
+ }
+
+ if (cmap2)
+ {
+ XFreeColormap (dpy, cmap2);
+ cmap2 = 0;
+ }
+
+ if (fade_p)
+ {
+ cmap2 = copy_colormap (dpy, cmap, 0);
+ if (! cmap2)
+ fade_p = unfade_p = 0;
+ }
+
+ attrmask = CWOverrideRedirect | CWEventMask | CWBackingStore | CWColormap;
+ attrs.override_redirect = True;
+ attrs.event_mask = (KeyPressMask | KeyReleaseMask |
+ ButtonPressMask | ButtonReleaseMask |
+ PointerMotionMask);
+ attrs.backing_store = NotUseful;
+ attrs.colormap = cmap;
+
+/* if (demo_mode_p || lock_p || locked_p) width = width / 2; #### */
+
+ if (screensaver_window)
+ {
+ XWindowChanges changes;
+ unsigned int changesmask = CWX|CWY|CWWidth|CWHeight|CWBorderWidth;
+ changes.x = 0;
+ changes.y = 0;
+ changes.width = width;
+ changes.height = height;
+ changes.border_width = 0;
+
+ XConfigureWindow (dpy, screensaver_window, changesmask, &changes);
+ XChangeWindowAttributes (dpy, screensaver_window, attrmask, &attrs);
+ }
+ else
+ {
+ screensaver_window =
+ XCreateWindow (dpy, RootWindowOfScreen (screen), 0, 0, width, height,
+ 0, visual_depth, InputOutput, visual, attrmask,
+ &attrs);
+ }
+
+ class_hints.res_name = progname;
+ class_hints.res_class = progclass;
+ XSetClassHint (dpy, screensaver_window, &class_hints);
+ XStoreName (dpy, screensaver_window, "screensaver");
+ XChangeProperty (dpy, screensaver_window, XA_SCREENSAVER_VERSION,
+ XA_STRING, 8, PropModeReplace,
+ (unsigned char *) screensaver_version,
+ strlen (screensaver_version));
+
+ sprintf (id, "%d on host ", getpid ());
+ if (! XmuGetHostname (id + strlen (id), sizeof (id) - strlen (id) - 1))
+ strcat (id, "???");
+ XChangeProperty (dpy, screensaver_window, XA_SCREENSAVER_ID, XA_STRING, 8,
+ PropModeReplace, (unsigned char *) id, strlen (id));
+
+ black.red = black.green = black.blue = 0;
+ if (!cursor)
+ {
+ Pixmap bit;
+ bit = XCreatePixmapFromBitmapData (dpy, screensaver_window, "\000", 1, 1,
+ BlackPixelOfScreen (screen),
+ BlackPixelOfScreen (screen), 1);
+ cursor = XCreatePixmapCursor (dpy, bit, bit, &black, &black, 0, 0);
+ XFreePixmap (dpy, bit);
+ }
+
+ XSetWindowBackground (dpy, screensaver_window, black_pixel);
+ if (! demo_mode_p)
+ XDefineCursor (dpy, screensaver_window, cursor);
+ else
+ XUndefineCursor (dpy, screensaver_window);
+}
+
+
+void
+raise_window (inhibit_fade, between_hacks_p)
+ Bool inhibit_fade, between_hacks_p;
+{
+ initialize_screensaver_window ();
+
+ if (fade_p && !inhibit_fade && !demo_mode_p)
+ {
+ int grabbed;
+ Colormap current_map = (between_hacks_p
+ ? cmap
+ : DefaultColormapOfScreen (screen));
+ copy_colormap (dpy, current_map, cmap2);
+ XGrabServer (dpy);
+ /* grab and blacken mouse on the root window (saver not mapped yet) */
+ grabbed = grab_mouse (RootWindowOfScreen (screen));
+ /* fade what's on the screen to black */
+ XInstallColormap (dpy, cmap2);
+ fade_colormap (dpy, current_map, cmap2, fade_seconds, fade_ticks, True);
+ XClearWindow (dpy, screensaver_window);
+ XMapRaised (dpy, screensaver_window);
+ XInstallColormap (dpy, cmap);
+ if (grabbed == GrabSuccess)
+ XUngrabPointer (dpy, CurrentTime);
+ XUngrabServer (dpy);
+ }
+ else
+ {
+ XClearWindow (dpy, screensaver_window);
+ XMapRaised (dpy, screensaver_window);
+ }
+
+ if (install_cmap_p && !demo_mode_p)
+ XInstallColormap (dpy, cmap);
+}
+
+void
+blank_screen ()
+{
+ save_real_vroot ();
+ store_vroot_property (screensaver_window, screensaver_window);
+ raise_window (False, False);
+ grab_keyboard_and_mouse ();
+#ifdef __hpux
+ if (lock_p)
+ XHPDisableReset (dpy); /* turn off C-Sh-Reset */
+#endif
+}
+
+void
+unblank_screen ()
+{
+ if (unfade_p && !demo_mode_p)
+ {
+ int grabbed;
+ Colormap default_map = DefaultColormapOfScreen (screen);
+ blacken_colormap (dpy, cmap2);
+ XGrabServer (dpy);
+ /* grab and blacken mouse on the root window. */
+ grabbed = grab_mouse (RootWindowOfScreen (screen));
+ XInstallColormap (dpy, cmap2);
+ XUnmapWindow (dpy, screensaver_window);
+ fade_colormap (dpy, default_map, cmap2, fade_seconds, fade_ticks, False);
+ XInstallColormap (dpy, default_map);
+ if (grabbed == GrabSuccess)
+ XUngrabPointer (dpy, CurrentTime);
+ XUngrabServer (dpy);
+ }
+ else
+ {
+ if (install_cmap_p && !demo_mode_p)
+ {
+ XClearWindow (dpy, screensaver_window); /* avoid technicolor */
+ XInstallColormap (dpy, DefaultColormapOfScreen (screen));
+ }
+ XUnmapWindow (dpy, screensaver_window);
+ }
+ kill_xsetroot_data ();
+ ungrab_keyboard_and_mouse ();
+ restore_real_vroot ();
+#ifdef __hpux
+ if (lock_p)
+ XHPEnableReset (dpy); /* turn C-Sh-Reset back on */
+#endif
+}
--- /dev/null
+/* xscreensaver-command, Copyright (c) 1991-1993 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#include "version.h"
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xos.h>
+#if __STDC__
+# include <stdlib.h>
+#endif
+
+#ifdef _VROOT_H_
+ERROR! you must not include vroot.h in this file
+#endif
+
+static char *screensaver_version;
+static char *usage = "usage: %s -<switch>\n\
+\n\
+ This program provides external control of a running xscreensaver process.\n\
+ Version %s, copyright (c) 1991-1993 Jamie Zawinski <jwz@lucid.com>.\n\
+\n\
+ -demo Enter interactive demo mode.\n\
+ -deactivate Turns off the screensaver if it is on, as user input would.\n\
+ -activate Turns it on as if the user had been idle for long enough.\n\
+ -cycle Stops the current hack and runs a new one.\n\
+ -next Like either -activate or -cycle, depending on which is more\n\
+ appropriate, except that the screenhack that will be run is\n\
+ the next one in the list of hacks, instead of a randomly-\n\
+ chosen one. This option is good for looking at a demo of\n\
+ each of the hacks in place.\n\
+ -prev Like -next, but goes in the other direction.\n\
+ -exit Causes the screensaver process to exit. It should be ok to\n\
+ just kill the process (NOT with -9!) but this is a slightly\n\
+ easier way.\n\
+ -restart Causes the screensaver process to exit and then restart with\n\
+ the same command line arguments. This is a good way of \n\
+ causing the screensaver to re-read the resource database.\n\
+ -lock Same as -activate, but with immediate locking.\n\
+\n\
+ See the man page for more details.\n\n";
+
+static Window
+find_screensaver_window (dpy, progname)
+ Display *dpy;
+ char *progname;
+{
+ int i;
+ Window root = RootWindowOfScreen (DefaultScreenOfDisplay (dpy));
+ Window root2, parent, *kids;
+ unsigned int nkids;
+
+ if (! XQueryTree (dpy, root, &root2, &parent, &kids, &nkids))
+ abort ();
+ if (root != root2)
+ abort ();
+ if (parent)
+ abort ();
+ if (! (kids && nkids))
+ abort ();
+ for (i = 0; i < nkids; i++)
+ {
+ Atom type;
+ int format;
+ unsigned long nitems, bytesafter;
+ char *version;
+
+ if (XGetWindowProperty (dpy, kids[i],
+ XInternAtom (dpy, "_SCREENSAVER_VERSION", False),
+ 0, 1, False, XA_STRING,
+ &type, &format, &nitems, &bytesafter,
+ (unsigned char **) &version)
+ == Success
+ && type != None)
+ return kids[i];
+ }
+ fprintf (stderr, "%s: no screensaver is running on display %s", progname,
+ DisplayString (dpy));
+ exit (1);
+}
+
+
+#define USAGE() \
+ { fprintf (stderr, usage, argv[0], screensaver_version); exit (1); }
+
+void
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ Display *dpy;
+ Window window;
+ XEvent event;
+ int i;
+ char *message = 0, *dpyname = 0;
+ screensaver_version = malloc (5);
+ memcpy (screensaver_version, screensaver_id + 17, 4);
+ screensaver_version [4] = 0;
+ for (i = 1; i < argc; i++)
+ {
+ char *s = argv [i];
+ int L = strlen (s);
+ if (L < 2) USAGE ();
+ if (!strncmp (s, "-display", L)) dpyname = argv [++i];
+ else if (message) USAGE ()
+ else if (!strncmp (s, "-activate", L)) message = "ACTIVATE";
+ else if (!strncmp (s, "-deactivate", L)) message = "DEACTIVATE";
+ else if (!strncmp (s, "-cycle", L)) message = "CYCLE";
+ else if (!strncmp (s, "-next", L)) message = "NEXT";
+ else if (!strncmp (s, "-prev", L)) message = "PREV";
+ else if (!strncmp (s, "-exit", L)) message = "EXIT";
+ else if (!strncmp (s, "-restart", L)) message = "RESTART";
+ else if (!strncmp (s, "-demo", L)) message = "DEMO";
+ else if (!strncmp (s, "-lock", L)) message = "LOCK";
+ else USAGE ();
+ }
+ if (! message) USAGE ();
+ if (!dpyname) dpyname = (char *) getenv ("DISPLAY");
+ dpy = XOpenDisplay (dpyname);
+ if (!dpy)
+ {
+ fprintf (stderr, "%s: can't open display %s\n", argv[0],
+ (dpyname ? dpyname : "(null)"));
+ exit (1);
+ }
+ window = find_screensaver_window (dpy, argv[0]);
+
+ event.xany.type = ClientMessage;
+ event.xclient.display = dpy;
+ event.xclient.window = window;
+ event.xclient.message_type = XInternAtom (dpy, "SCREENSAVER", False);
+ event.xclient.format = 32;
+ event.xclient.data.l[0] = (long) XInternAtom (dpy, message, False);
+ if (! XSendEvent (dpy, window, False, 0L, &event))
+ {
+ fprintf (stderr, "%s: XSendEvent(dpy, 0x%x ...) failed.\n", argv [0],
+ (unsigned int) window);
+ exit (1);
+ }
+ XSync (dpy, 0);
+ exit (0);
+}
--- /dev/null
+.de EX \"Begin example
+.ne 5
+.if n .sp 1
+.if t .sp .5
+.nf
+.in +.5i
+..
+.de EE
+.fi
+.in -.5i
+.if n .sp 1
+.if t .sp .5
+..
+.TH XScreenSaver 1 "22-mar-93" "X Version 11"
+.SH NAME
+xscreensaver-command - control a running xscreensaver process
+.SH SYNOPSIS
+.B xscreensaver-command
+[\-activate] [\-deactivate] [\-cycle] [\-next] [\-prev] [\-exit] [\-restart] [\-demo] [\-lock]
+.SH DESCRIPTION
+The \fIxscreensaver\-command\fP program controls a running \fIxscreensaver\fP
+process by sending it client-messages.
+.SH OPTIONS
+.I xscreensaver-command
+accepts the following options:
+.TP 8
+.B \-activate
+Tell the screensaver to turn on immediately (that is, pretend that the
+user been idle for long enough.) It will turn off as soon as there is
+any user activity, as usual.
+
+It is useful to run this from a menu; you may wish to run it as
+.EX
+sleep 5 ; xscreensaver-command -activate
+.EE
+to be sure that you have time to remove your hand from the mouse before
+the screensaver comes on.
+.TP 8
+.B \-deactivate
+Tell the screensaver to turn off, as if there had been user activity.
+If locking is enabled, then the screensaver will prompt for a password
+as usual.
+.TP 8
+.B \-cycle
+Tell the screensaver to change which graphics hack it is running, just
+as if the ``cycle'' timer had expired.
+.TP 8
+.B \-next
+This is like either \fI\-activate\fP or \fI\-cycle\fP, depending on which is
+more appropriate, except that the screenhack that will be run is the next
+one in the list of programs, instead of a randomly-chosen one. This option
+is good for looking at a demo of each of the screensavers currently available.
+You might want to put this on a menu.
+.TP 8
+.B \-prev
+This is like \fI\-next\fP, but cycles in the other direction.
+.TP 8
+.B \-demo
+Cause the screensaver to enter its interactive demo mode, if it has been
+compiled with support for it.
+.TP 8
+.B \-lock
+Like \fI\-activate\fP, but a password will be required before the screensaver
+turns off, even if the screensaver's \fIlock\fP resource is false. The
+display will be locked immediately even if the screensaver's \fIlockTimeout\fP
+resource is non-zero.
+.TP 8
+.B \-exit
+Causes the screensaver process to exit gracefully. This is a slightly
+safer way to kill the screensaver than by using \fIkill\fP.
+
+Never use \fIkill -9\fP with \fIxscreensaver\fP while the screensaver is
+active. If you are using a virtual root window manager, that can leave
+things in an inconsistent state, and you may need to restart your window
+manager to repair the damage.
+.TP 8
+.B \-restart
+Causes the screensaver process to exit and then restart with the same command
+line arguments. This is a good way of causing the screensaver to re-read the
+resource database.
+
+If the screensaver is run from \fIxdm(1)\fP (that is, it is already running
+before you log in) then you may want to issue the ``restart'' command from
+one of your startup scripts, so that the screensaver gets your resource
+settings instead of the default ones.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B PATH
+to find the executable to restart.
+.SH "SEE ALSO"
+.BR X (1),
+.BR xscreensaver (1)
+.SH BUGS
+Diagnostics are reported on the \fBstderr\fP of the \fIxscreensaver\fP
+process, not this process, so the caller of \fIxscreensaver-command\fP
+may not see the error messages.
+.SH COPYRIGHT
+Copyright \(co 1992, 1993 by Jamie Zawinski. Permission to use, copy, modify,
+distribute, and sell this software and its documentation for any purpose is
+hereby granted without fee, provided that the above copyright notice appear
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation. No representations are made about the
+suitability of this software for any purpose. It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@lucid.com>, 13-aug-92.
--- /dev/null
+/* xscreensaver, Copyright (c) 1991-1993 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#include "version.h"
+
+/* ========================================================================
+ * First we wait until the keyboard and mouse become idle for the specified
+ * amount of time. We do this by periodically checking with the XIdle
+ * server extension.
+ *
+ * Then, we map a full screen black window.
+ *
+ * We place a __SWM_VROOT property on this window, so that newly-started
+ * clients will think that this window is a "virtual root" window.
+ *
+ * If there is an existing "virtual root" window (one that already had
+ * an __SWM_VROOT property) then we remove that property from that window.
+ * Otherwise, clients would see that window (the real virtual root) instead
+ * of ours (the impostor.)
+ *
+ * Then we pick a random program to run, and start it. Two assumptions
+ * are made about this program: that it has been specified with whatever
+ * command-line options are necessary to make it run on the root window;
+ * and that it has been compiled with vroot.h, so that it is able to find
+ * the root window when a virtual-root window manager (or this program) is
+ * running.
+ *
+ * Then, we wait for keyboard or mouse events to be generated on the window.
+ * When they are, we kill the inferior process, unmap the window, and restore
+ * the __SWM_VROOT property to the real virtual root window if there was one.
+ *
+ * While we are waiting, we also set up timers so that, after a certain
+ * amount of time has passed, we can start a different screenhack. We do
+ * this by killing the running child process with SIGTERM, and then starting
+ * a new one in the same way.
+ *
+ * If there was a real virtual root, meaning that we removed the __SWM_VROOT
+ * property from it, meaning we must (absolutely must) restore it before we
+ * exit, then we set up signal handlers for most signals (SIGINT, SIGTERM,
+ * etc.) that do this. Most Xlib and Xt routines are not reentrant, so it
+ * is not generally safe to call them from signal handlers; however, this
+ * program spends most of its time waiting, so the window of opportunity
+ * when code could be called reentrantly is fairly small; and also, the worst
+ * that could happen is that the call would fail. If we've gotten one of
+ * these signals, then we're on our way out anyway. If we didn't restore the
+ * __SWM_VROOT property, that would be very bad, so it's worth a shot. Note
+ * that this means that, if you're using a virtual-root window manager, you
+ * can really fuck up the world by killing this process with "kill -9".
+ *
+ * This program accepts ClientMessages of type SCREENSAVER; these messages
+ * may contain the atom ACTIVATE or DEACTIVATE, meaning to turn the
+ * screensaver on or off now, regardless of the idleness of the user,
+ * and a few other things. The included "xscreensaver_command" program
+ * sends these messsages.
+ *
+ * If we don't have the XIdle extension, then we do the XAutoLock trick:
+ * notice every window that gets created, and wait 30 seconds or so until
+ * its creating process has settled down, and then select KeyPress events on
+ * those windows which already select for KeyPress events. It's important
+ * that we not select KeyPress on windows which don't select them, because
+ * that would interfere with event propagation. This will break if any
+ * program changes its event mask to contain KeyRelease or PointerMotion
+ * more than 30 seconds after creating the window, but that's probably
+ * pretty rare.
+ *
+ * The reason that we can't select KeyPresses on windows that don't have
+ * them already is that, when dispatching a KeyPress event, X finds the
+ * lowest (leafmost) window in the hierarchy on which *any* client selects
+ * for KeyPress, and sends the event to that window. This means that if a
+ * client had a window with subwindows, and expected to receive KeyPress
+ * events on the parent window instead of the subwindows, then that client
+ * would malfunction if some other client selected KeyPress events on the
+ * subwindows. It is an incredible misdesign that one client can make
+ * another client malfunction in this way.
+ *
+ * To detect mouse motion, we periodically wake up and poll the mouse
+ * position and button/modifier state, and notice when something has
+ * changed. We make this check every five seconds by default, and since the
+ * screensaver timeout has a granularity of one minute, this makes the
+ * chance of a false positive very small. We could detect mouse motion in
+ * the same way as keyboard activity, but that would suffer from the same
+ * "client changing event mask" problem that the KeyPress events hack does.
+ * I think polling is more reliable.
+ *
+ * None of this crap happens if we're using the XIdle extension, so install
+ * it if the description above sounds just too flaky to live. It is, but
+ * those are your choices.
+ *
+ * Debugging hints:
+ * - Have a second terminal handy.
+ * - Be careful where you set your breakpoints, you don't want this to
+ * stop under the debugger with the keyboard grabbed or the blackout
+ * window exposed.
+ * - you probably can't set breakpoints in functions that are called on
+ * the other side of a call to fork() -- if your clients are dying
+ * with signal 5, Trace/BPT Trap, you're losing in this way.
+ * - If you aren't using XIdle, don't leave this stopped under the
+ * debugger for very long, or the X input buffer will get huge because
+ * of the keypress events it's selecting for. This can make your X
+ * server wedge with "no more input buffers."
+ *
+ * ========================================================================
+ */
+
+#if __STDC__
+#include <stdlib.h>
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Intrinsic.h>
+#include <X11/Xos.h>
+
+#ifdef HAVE_XIDLE
+#include <X11/extensions/xidle.h>
+#endif
+
+#include "xscreensaver.h"
+
+#if defined(SVR4) || defined(SYSV)
+# define srandom(i) srand((unsigned int)(i))
+#else
+extern void srandom P((int)); /* srand() is in stdlib.h... */
+#endif
+
+extern char *get_string_resource P((char *, char *));
+extern Bool get_boolean_resource P((char *, char *));
+extern int get_integer_resource P((char *, char *));
+extern unsigned int get_minutes_resource P((char *, char *));
+extern unsigned int get_seconds_resource P((char *, char *));
+
+extern Visual *get_visual_resource P((Display *, char *, char *));
+extern int get_visual_depth P((Display *, Visual *));
+
+extern void notice_events_timer P((XtPointer closure, void *timer));
+extern void cycle_timer P((void *junk1, XtPointer junk2));
+extern void activate_lock_timer P((void *junk1, XtPointer junk2));
+extern void sleep_until_idle P((Bool until_idle_p));
+
+extern void ensure_no_screensaver_running P((void));
+extern void initialize_screensaver_window P((void));
+extern void disable_builtin_screensaver P((void));
+
+extern void hack_environment P((void));
+extern void grab_keyboard_and_mouse P((void));
+extern void ungrab_keyboard_and_mouse P((void));
+
+extern void save_argv P((int argc, char **argv));
+
+
+char *screensaver_version;
+char *progname;
+char *progclass;
+XrmDatabase db;
+
+XtAppContext app;
+
+Display *dpy;
+Screen *screen;
+Visual *visual;
+int visual_depth;
+
+Widget toplevel_shell;
+
+Time lock_timeout;
+
+extern Time timeout;
+extern Time cycle;
+extern Time passwd_timeout;
+extern Time pointer_timeout;
+extern Time notice_events_timeout;
+extern XtIntervalId lock_id, cycle_id;
+
+Bool use_xidle;
+Bool verbose_p;
+Bool lock_p, locked_p;
+
+extern char **screenhacks;
+extern int screenhacks_count;
+extern char *shell;
+extern int nice_inferior;
+extern Window screensaver_window;
+extern Cursor cursor;
+extern Colormap cmap, cmap2;
+extern Bool fade_p, unfade_p;
+extern int fade_seconds, fade_ticks;
+extern Bool install_cmap_p;
+extern Bool locking_disabled_p;
+extern Bool demo_mode_p;
+extern Bool dbox_up_p;
+extern int next_mode_p;
+
+static time_t initial_delay;
+
+extern Atom XA_VROOT, XA_XSETROOT_ID;
+extern Atom XA_SCREENSAVER_VERSION, XA_SCREENSAVER_ID;
+
+static Atom XA_SCREENSAVER;
+static Atom XA_ACTIVATE, XA_DEACTIVATE, XA_CYCLE, XA_NEXT, XA_PREV;
+static Atom XA_EXIT, XA_RESTART, XA_DEMO, XA_LOCK;
+
+#ifdef NO_MOTIF /* kludge */
+Bool demo_mode_p = 0;
+Bool dbox_up_p = 0;
+Time passwd_timeout = 0;
+#endif
+
+\f
+#ifdef NO_DEMO_MODE
+# define demo_mode() abort()
+#else
+extern void demo_mode P((void));
+#endif
+\f
+static XrmOptionDescRec options [] = {
+ { "-timeout", ".timeout", XrmoptionSepArg, 0 },
+ { "-idelay", ".initialDelay",XrmoptionSepArg, 0 },
+ { "-cycle", ".cycle", XrmoptionSepArg, 0 },
+ { "-visual", ".visual", XrmoptionSepArg, 0 },
+ { "-lock-timeout", ".lockTimeout", XrmoptionSepArg, 0 },
+ { "-verbose", ".verbose", XrmoptionNoArg, "on" },
+ { "-silent", ".verbose", XrmoptionNoArg, "off" },
+ { "-xidle", ".xidle", XrmoptionNoArg, "on" },
+ { "-no-xidle", ".xidle", XrmoptionNoArg, "off" },
+ { "-lock", ".lock", XrmoptionNoArg, "on" },
+ { "-no-lock", ".lock", XrmoptionNoArg, "off" }
+};
+
+static char *defaults[] = {
+#include "XScreenSaver.ad.h"
+ 0
+};
+
+static void
+do_help ()
+{
+ printf ("\
+xscreensaver %s, copyright (c) 1991-1993 by Jamie Zawinski <jwz@lucid.com>.\n\
+The standard Xt command-line options are accepted; other options include:\n\
+\n\
+ -timeout <minutes> when the screensaver should activate\n\
+ -cycle <minutes> how long to let each hack run\n\
+ -idelay <seconds> how long to sleep before startup\n\
+ -demo enter interactive demo mode on startup\n\
+ -verbose be loud\n\
+ -silent don't\n\
+ -xidle use the XIdle server extension\n\
+ -no-xidle don't\n\
+ -lock require a password before deactivating\n\
+ -no-lock don't\n\
+ -lock-timeout <minutes> grace period before locking; default 0\n\
+ -help this message\n\
+\n\
+Use the `xscreensaver-command' program to control a running screensaver.\n\
+\n\
+The *programs, *colorPrograms, and *monoPrograms resources control which\n\
+graphics demos will be launched by the screensaver. See the man page for\n\
+more details.\n\n",
+ screensaver_version);
+
+#ifdef NO_LOCKING
+ printf("Support for locking was not enabled at compile-time.\n");
+#endif
+#ifdef NO_DEMO_MODE
+ printf("Support for demo mode was not enabled at compile-time.\n");
+#endif
+#ifndef HAVE_XIDLE
+ printf("Support for the XIdle extension was not enabled at compile-time.\n");
+#endif
+
+ fflush (stdout);
+ exit (1);
+}
+
+
+static void
+get_screenhacks ()
+{
+ char *data[3];
+ int i, hacks_size = 10;
+
+ data[0] = get_string_resource ("programs", "Programs");
+ data[1] = ((CellsOfScreen (screen) <= 2)
+ ? get_string_resource ("monoPrograms", "MonoPrograms")
+ : get_string_resource ("colorPrograms", "ColorPrograms"));
+ data[2] = 0;
+ if (! data[0]) data[0] = data[1], data[1] = 0;
+
+ screenhacks = (char **) malloc (sizeof (char *) * hacks_size);
+ screenhacks_count = 0;
+
+ for (i = 0; data[i]; i++)
+ {
+ int j = 0;
+ char *d = data [i];
+ int size = strlen (d);
+ while (j < size)
+ {
+ int end, start = j;
+ if (d[j] == ' ' || d[j] == '\t' || d[j] == '\n' || d[j] == 0)
+ {
+ j++;
+ continue;
+ }
+ if (hacks_size <= screenhacks_count)
+ screenhacks = (char **) realloc (screenhacks,
+ (hacks_size = hacks_size * 2) *
+ sizeof (char *));
+ screenhacks [screenhacks_count++] = d + j;
+ while (d[j] != 0 && d[j] != '\n')
+ j++;
+ end = j;
+ while (j > start && (d[j-1] == ' ' || d[j-1] == '\t'))
+ j--;
+ d[j] = 0;
+ j = end + 1;
+ }
+ }
+
+ /* shrink all whitespace to one space, for the benefit of the "demo"
+ mode display. We only do this when we can easily tell that the
+ whitespace is not significant (no shell metachars).
+ */
+ for (i = 0; i < screenhacks_count; i++)
+ {
+ char *s = screenhacks [i];
+ char *s2;
+ int L = strlen (s);
+ int j, k;
+ for (j = 0; j < L; j++)
+ {
+ switch (s[j])
+ {
+ case '\'': case '"': case '`': case '\\':
+ goto DONE;
+ case '\t':
+ s[j] = ' ';
+ case ' ':
+ k = 0;
+ for (s2 = s+j+1; *s2 == ' ' || *s2 == '\t'; s2++)
+ k++;
+ if (k > 0)
+ for (s2 = s + j + 1; *s2; s2++)
+ s2 [0] = s2 [k];
+ break;
+ }
+ }
+ DONE:
+ ;
+ }
+
+ if (screenhacks_count)
+ {
+ /* Shrink down the screenhacks array to be only as big as it needs to.
+ This doesn't really matter at all. */
+ screenhacks = (char **)
+ realloc (screenhacks, ((screenhacks_count + 1) * sizeof(char *)));
+ screenhacks [screenhacks_count] = 0;
+ }
+ else
+ {
+ free (screenhacks);
+ screenhacks = 0;
+ }
+}
+
+
+static void
+get_resources ()
+{
+ visual = get_visual_resource (dpy, "visual", "Visual");
+ timeout = 1000 * get_minutes_resource ("timeout", "Time");
+ cycle = 1000 * get_minutes_resource ("cycle", "Time");
+ lock_timeout = 1000 * get_minutes_resource ("lockTimeout", "Time");
+ nice_inferior = get_integer_resource ("nice", "Nice");
+ verbose_p = get_boolean_resource ("verbose", "Boolean");
+ lock_p = get_boolean_resource ("lock", "Boolean");
+ install_cmap_p = get_boolean_resource ("installColormap", "Boolean");
+ fade_p = get_boolean_resource ("fade", "Boolean");
+ unfade_p = get_boolean_resource ("unfade", "Boolean");
+ fade_seconds = get_seconds_resource ("fadeSeconds", "Time");
+ fade_ticks = get_integer_resource ("fadeTicks", "Integer");
+ shell = get_string_resource ("bourneShell", "BourneShell");
+ initial_delay = get_seconds_resource ("initialDelay", "Time");
+ passwd_timeout = 1000 * get_seconds_resource ("passwdTimeout", "Time");
+ pointer_timeout = 1000 * get_seconds_resource ("pointerPollTime", "Time");
+ notice_events_timeout = 1000 * get_seconds_resource ("windowCreationTimeout",
+ "Time");
+ if (timeout < 10000) timeout = 10000;
+ if (cycle < 2000) cycle = 2000;
+ if (passwd_timeout == 0) passwd_timeout = 30000;
+ if (pointer_timeout == 0) pointer_timeout = 5000;
+ if (notice_events_timeout == 0) notice_events_timeout = 10000;
+ if (fade_seconds == 0 || fade_ticks == 0) fade_p = False;
+ if (! fade_p) unfade_p = False;
+
+ visual_depth = get_visual_depth (dpy, visual);
+
+ if (visual_depth <= 1 || CellsOfScreen (screen) <= 2)
+ install_cmap_p = False;
+
+#ifdef NO_LOCKING
+ locking_disabled_p = True;
+ if (lock_p)
+ {
+ lock_p = False;
+ fprintf (stderr, "%s: %snot compiled with support for locking.\n",
+ progname, (verbose_p ? "## " : ""));
+ }
+#else /* ! NO_LOCKING */
+ if (lock_p && locking_disabled_p)
+ {
+ fprintf (stderr, "%s: %slocking is disabled.\n", progname,
+ (verbose_p ? "## " : ""));
+ lock_p = False;
+ }
+#endif /* ! NO_LOCKING */
+
+ /* don't set use_xidle unless it is explicitly specified */
+ if (get_string_resource ("xidle", "Boolean"))
+ use_xidle = get_boolean_resource ("xidle", "Boolean");
+ else
+#ifdef HAVE_XIDLE /* pick a default */
+ use_xidle = True;
+#else
+ use_xidle = False;
+#endif
+ get_screenhacks ();
+}
+
+char *
+timestring ()
+{
+ long now = time ((time_t *) 0);
+ char *str = (char *) ctime (&now);
+ char *nl = (char *) strchr (str, '\n');
+ if (nl) *nl = 0; /* take off that dang newline */
+ return str;
+}
+
+#ifdef NO_SETUID
+# define hack_uid()
+# define hack_uid_warn()
+#else /* !NO_SETUID */
+extern void hack_uid P((void));
+extern void hack_uid_warn P((void));
+#endif /* NO_SETUID */
+
+
+#ifndef NO_LOCKING
+extern Bool unlock_p P((Widget));
+extern Bool lock_init P((void));
+#endif
+
+static void initialize ();
+static void main_loop ();
+static void initialize ();
+
+void
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ initialize (argc, argv);
+ main_loop ();
+}
+
+
+static void
+initialize_connection (argc, argv)
+ int argc;
+ char **argv;
+{
+ toplevel_shell = XtAppInitialize (&app, progclass,
+ options, XtNumber (options),
+ &argc, argv, defaults, 0, 0);
+
+ dpy = XtDisplay (toplevel_shell);
+ screen = XtScreen (toplevel_shell);
+ db = XtDatabase (dpy);
+ XtGetApplicationNameAndClass (dpy, &progname, &progclass);
+
+ if (argc == 2 && !strcmp (argv[1], "-help"))
+ do_help ();
+ else if (argc > 1)
+ {
+ fprintf (stderr, "%s: unknown option %s\n", progname, argv [1]);
+ exit (1);
+ }
+ get_resources ();
+ hack_uid_warn ();
+ hack_environment ();
+ XA_VROOT = XInternAtom (dpy, "__SWM_VROOT", False);
+ XA_SCREENSAVER = XInternAtom (dpy, "SCREENSAVER", False);
+ XA_SCREENSAVER_VERSION = XInternAtom (dpy, "_SCREENSAVER_VERSION", False);
+ XA_SCREENSAVER_ID = XInternAtom (dpy, "_SCREENSAVER_ID", False);
+ XA_XSETROOT_ID = XInternAtom (dpy, "_XSETROOT_ID", False);
+ XA_ACTIVATE = XInternAtom (dpy, "ACTIVATE", False);
+ XA_DEACTIVATE = XInternAtom (dpy, "DEACTIVATE", False);
+ XA_RESTART = XInternAtom (dpy, "RESTART", False);
+ XA_CYCLE = XInternAtom (dpy, "CYCLE", False);
+ XA_NEXT = XInternAtom (dpy, "NEXT", False);
+ XA_PREV = XInternAtom (dpy, "PREV", False);
+ XA_EXIT = XInternAtom (dpy, "EXIT", False);
+ XA_DEMO = XInternAtom (dpy, "DEMO", False);
+ XA_LOCK = XInternAtom (dpy, "LOCK", False);
+}
+
+extern void init_sigchld P((void));
+
+static void
+initialize (argc, argv)
+ int argc;
+ char **argv;
+{
+ Bool initial_demo_mode_p = False;
+ screensaver_version = (char *) malloc (5);
+ memcpy (screensaver_version, screensaver_id + 17, 4);
+ screensaver_version [4] = 0;
+ progname = argv[0]; /* reset later; this is for the benefit of lock_init() */
+
+#ifdef NO_LOCKING
+ locking_disabled_p = True;
+#else
+ locking_disabled_p = False;
+ if (! lock_init ()) /* before hack_uid() for proper permissions */
+ locking_disabled_p = True;
+#endif
+
+ hack_uid ();
+ progclass = "XScreenSaver";
+
+ /* remove -demo switch before saving argv */
+ {
+ int i;
+ for (i = 1; i < argc; i++)
+ while (!strcmp ("-demo", argv [i]))
+ {
+ int j;
+ initial_demo_mode_p = True;
+ for (j = i; j < argc; j++)
+ argv [j] = argv [j+1];
+ argv [j] = 0;
+ argc--;
+ if (argc <= i) break;
+ }
+ }
+ save_argv (argc, argv);
+ initialize_connection (argc, argv);
+
+ ensure_no_screensaver_running ();
+ demo_mode_p = initial_demo_mode_p;
+ screensaver_window = 0;
+ cursor = 0;
+ initialize_screensaver_window ();
+ srandom ((int) time ((time_t *) 0));
+ cycle_id = 0;
+ lock_id = 0;
+ locked_p = False;
+ if (use_xidle)
+ {
+#ifdef HAVE_XIDLE
+ int first_event, first_error;
+ if (! XidleQueryExtension (dpy, &first_event, &first_error))
+ {
+ fprintf (stderr,
+ "%s: display %s does not support the XIdle extension.\n",
+ progname, DisplayString (dpy));
+ use_xidle = 0;
+ }
+#else
+ fprintf (stderr, "%s: not compiled with support for XIdle.\n",
+ progname);
+ use_xidle = 0;
+#endif
+ }
+
+ init_sigchld ();
+
+ if (verbose_p)
+ printf ("\
+%s %s, copyright (c) 1991-1993 by Jamie Zawinski <jwz@lucid.com>.\n\
+ pid = %d.\n", progname, screensaver_version, getpid ());
+
+ disable_builtin_screensaver ();
+
+ if (initial_demo_mode_p)
+ /* If the user wants demo mode, don't wait around before doing it. */
+ initial_delay = 0;
+
+#ifdef HAVE_XIDLE
+ if (! use_xidle)
+#endif
+ {
+ if (initial_delay)
+ {
+ if (verbose_p)
+ {
+ printf ("%s: waiting for %d second%s...", progname,
+ initial_delay, (initial_delay == 1 ? "" : "s"));
+ fflush (stdout);
+ }
+ sleep (initial_delay);
+ if (verbose_p)
+ printf (" done.\n");
+ }
+ if (verbose_p)
+ {
+ printf ("%s: selecting events on extant windows...", progname);
+ fflush (stdout);
+ }
+ notice_events_timer ((XtPointer)
+ RootWindowOfScreen (XtScreen (toplevel_shell)),
+ 0);
+ if (verbose_p)
+ printf (" done.\n");
+ }
+}
+
+
+extern void suspend_screenhack P((Bool suspend_p));
+
+static void
+main_loop ()
+{
+ while (1)
+ {
+ if (! demo_mode_p)
+ sleep_until_idle (True);
+
+ if (demo_mode_p)
+ demo_mode ();
+ else
+ {
+ if (verbose_p)
+ printf ("%s: user is idle; waking up at %s.\n", progname,
+ timestring());
+ blank_screen ();
+ spawn_screenhack (True);
+ if (cycle)
+ cycle_id = XtAppAddTimeOut (app, cycle, cycle_timer, 0);
+
+#ifndef NO_LOCKING
+ if (lock_p && lock_timeout == 0)
+ locked_p = True;
+ if (lock_p && !locked_p)
+ /* locked_p might be true already because of ClientMessage */
+ lock_id = XtAppAddTimeOut (app,lock_timeout,activate_lock_timer,0);
+#endif
+
+ PASSWD_INVALID:
+
+ sleep_until_idle (False); /* until not idle */
+
+#ifndef NO_LOCKING
+ if (locked_p)
+ {
+ Bool val;
+ if (locking_disabled_p) abort ();
+ dbox_up_p = True;
+ ungrab_keyboard_and_mouse ();
+ suspend_screenhack (True);
+ XUndefineCursor (dpy, screensaver_window);
+ if (verbose_p)
+ printf ("%s: prompting for password.\n", progname);
+ val = unlock_p (toplevel_shell);
+ if (verbose_p && val == False)
+ printf ("%s: password incorrect!\n", progname);
+ dbox_up_p = False;
+ XDefineCursor (dpy, screensaver_window, cursor);
+ suspend_screenhack (False);
+ grab_keyboard_and_mouse ();
+ if (! val)
+ goto PASSWD_INVALID;
+ locked_p = False;
+ }
+#endif
+ unblank_screen ();
+ kill_screenhack ();
+ if (cycle_id)
+ {
+ XtRemoveTimeOut (cycle_id);
+ cycle_id = 0;
+ }
+#ifndef NO_LOCKING
+ if (lock_id)
+ {
+ XtRemoveTimeOut (lock_id);
+ lock_id = 0;
+ }
+#endif
+ if (verbose_p)
+ printf ("%s: user is active; going to sleep at %s.\n", progname,
+ timestring ());
+ }
+ }
+}
+
+\f
+
+Bool
+handle_clientmessage (event, until_idle_p)
+ XEvent *event;
+ Bool until_idle_p;
+{
+ Atom type;
+ if (event->xclient.message_type != XA_SCREENSAVER)
+ {
+ char *str;
+ str = XGetAtomName (dpy, event->xclient.message_type);
+ fprintf (stderr, "%s: %sunrecognised ClientMessage type %s received\n",
+ progname, (verbose_p ? "## " : ""),
+ (str ? str : "(null)"));
+ if (str) XFree (str);
+ }
+ if (event->xclient.format != 32)
+ {
+ fprintf (stderr, "%s: %sClientMessage of format %d received, not 32\n",
+ progname, (verbose_p ? "## " : ""), event->xclient.format);
+ }
+ type = event->xclient.data.l[0];
+ if (type == XA_ACTIVATE)
+ {
+ if (until_idle_p)
+ {
+ if (verbose_p)
+ printf ("%s: ACTIVATE ClientMessage received.\n", progname);
+ return True;
+ }
+ fprintf (stderr,
+ "%s: %sClientMessage ACTIVATE received while already active.\n",
+ progname, (verbose_p ? "## " : ""));
+ }
+ else if (type == XA_DEACTIVATE)
+ {
+ if (! until_idle_p)
+ {
+ if (verbose_p)
+ printf ("%s: DEACTIVATE ClientMessage received.\n", progname);
+ return True;
+ }
+ fprintf (stderr,
+ "%s: %sClientMessage DEACTIVATE received while inactive.\n",
+ progname, (verbose_p ? "## " : ""));
+ }
+ else if (type == XA_CYCLE)
+ {
+ if (! until_idle_p)
+ {
+ if (verbose_p)
+ printf ("%s: CYCLE ClientMessage received.\n", progname);
+ if (cycle_id)
+ XtRemoveTimeOut (cycle_id);
+ cycle_id = 0;
+ cycle_timer (0, 0);
+ return False;
+ }
+ fprintf (stderr,
+ "%s: %sClientMessage CYCLE received while inactive.\n",
+ progname, (verbose_p ? "## " : ""));
+ }
+ else if (type == XA_NEXT || type == XA_PREV)
+ {
+ if (verbose_p)
+ printf ("%s: %s ClientMessage received.\n", progname,
+ (type == XA_NEXT ? "NEXT" : "PREV"));
+ next_mode_p = 1 + (type == XA_PREV);
+
+ if (! until_idle_p)
+ {
+ if (cycle_id)
+ XtRemoveTimeOut (cycle_id);
+ cycle_id = 0;
+ cycle_timer (0, 0);
+ }
+ else
+ return True;
+ }
+ else if (type == XA_EXIT)
+ {
+ /* Ignore EXIT message if the screen is locked. */
+ if (until_idle_p || !locked_p)
+ {
+ if (verbose_p)
+ printf ("%s: EXIT ClientMessage received.\n", progname);
+ if (! until_idle_p)
+ {
+ unblank_screen ();
+ kill_screenhack ();
+ XSync (dpy, False);
+ }
+ exit (0);
+ }
+ else
+ fprintf (stderr, "%s: %sEXIT ClientMessage received while locked.\n",
+ progname, (verbose_p ? "## " : ""));
+ }
+ else if (type == XA_RESTART)
+ {
+ /* The RESTART message works whether the screensaver is active or not,
+ unless the screen is locked, in which case it doesn't work.
+ */
+ if (until_idle_p || !locked_p)
+ {
+ if (verbose_p)
+ printf ("%s: RESTART ClientMessage received.\n", progname);
+ if (! until_idle_p)
+ {
+ unblank_screen ();
+ kill_screenhack ();
+ XSync (dpy, False);
+ }
+ restart_process ();
+ }
+ else
+ fprintf(stderr, "%s: %sRESTART ClientMessage received while locked.\n",
+ progname, (verbose_p ? "## " : ""));
+ }
+ else if (type == XA_DEMO)
+ {
+#ifdef NO_DEMO_MODE
+ fprintf (stderr,
+ "%s: %snot compiled with support for DEMO mode\n",
+ progname, (verbose_p ? "## " : ""));
+#else
+ if (until_idle_p)
+ {
+ if (verbose_p)
+ printf ("%s: DEMO ClientMessage received.\n", progname);
+ demo_mode_p = True;
+ return True;
+ }
+ fprintf (stderr,
+ "%s: %sDEMO ClientMessage received while active.\n",
+ progname, (verbose_p ? "## " : ""));
+#endif
+ }
+ else if (type == XA_LOCK)
+ {
+#ifdef NO_LOCKING
+ fprintf (stderr, "%s: %snot compiled with support for LOCK mode\n",
+ progname, (verbose_p ? "## " : ""));
+#else
+ if (locking_disabled_p)
+ fprintf (stderr,
+ "%s: %sLOCK ClientMessage received, but locking is disabled.\n",
+ progname, (verbose_p ? "## " : ""));
+ else if (locked_p)
+ fprintf (stderr,
+ "%s: %sLOCK ClientMessage received while already locked.\n",
+ progname, (verbose_p ? "## " : ""));
+ else
+ {
+ locked_p = True;
+ if (verbose_p)
+ printf ("%s: LOCK ClientMessage received;%s locking.\n",
+ progname, until_idle_p ? " activating and" : "");
+
+ if (lock_id) /* we're doing it now, so lose the timeout */
+ {
+ XtRemoveTimeOut (lock_id);
+ lock_id = 0;
+ }
+
+ if (until_idle_p)
+ return True;
+ }
+#endif
+ }
+ else
+ {
+ char *str;
+ str = XGetAtomName (dpy, type);
+ if (str)
+ fprintf (stderr,
+ "%s: %sunrecognised screensaver ClientMessage %s received\n",
+ progname, (verbose_p ? "## " : ""), str);
+ else
+ fprintf (stderr,
+ "%s: %sunrecognised screensaver ClientMessage 0x%x received\n",
+ progname, (verbose_p ? "## " : ""),
+ event->xclient.data.l[0]);
+ if (str) XFree (str);
+ }
+ return False;
+}
--- /dev/null
+/* xscreensaver, Copyright (c) 1993 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#if __STDC__
+# include <stdlib.h>
+# include <unistd.h>
+#endif
+
+#if __STDC__
+# define P(x)x
+#else
+# define P(x)()
+#endif
+
+#ifdef NO_MOTIF
+# define NO_DEMO_MODE
+# ifndef NO_LOCKING
+# define NO_LOCKING
+# endif
+#endif
+
+extern char *progname, *progclass;
+extern char *screensaver_version;
+
+extern Display *dpy;
+extern Screen *screen;
+extern Visual *visual;
+extern int visual_depth;
+
+extern Bool verbose_p;
+
+extern void initialize_screensaver_window P(());
+extern void raise_window P((Bool inhibit_fade, Bool between_hacks_p));
+extern void blank_screen P(());
+extern void unblank_screen P((void));
+extern void restart_process P((void));
+
+extern void restore_real_vroot P((void));
+
+extern void spawn_screenhack P((Bool));
+extern void kill_screenhack P((void));
+
+extern Colormap copy_colormap P((Display *, Colormap, Colormap));
+extern void fade_colormap P((Display*, Colormap, Colormap, int, int, Bool));
+extern void blacken_colormap P((Display *, Colormap));
+
+extern int BadWindow_ehandler P((Display *dpy, XErrorEvent *error));
--- /dev/null
+.de EX \"Begin example
+.ne 5
+.if n .sp 1
+.if t .sp .5
+.nf
+.in +.5i
+..
+.de EE
+.fi
+.in -.5i
+.if n .sp 1
+.if t .sp .5
+..
+.TH XScreenSaver 1 "22-mar-93" "X Version 11"
+.SH NAME
+xscreensaver - run graphics hacks after the user has been idle for a while
+.SH SYNOPSIS
+.B xscreensaver
+[\-display \fIhost:display.screen\fP] [\-timeout \fIint\fP] [\-cycle \fIint\fP] [\-nice \fIint\fP] [\-verbose] [\-silent] [\-xidle] [\-no-xidle] [\-lock] [\-no-lock] [\-lock\-timeout \fIint\fP] [\-demo] [\-xrm \fIresources\fP]
+.SH DESCRIPTION
+The \fIxscreensaver\fP program waits until the keyboard and mouse have been
+idle for a period, and then runs a graphics demo chosen at random. It
+turns off as soon as there is any mouse or keyboard activity.
+
+This program can lock your terminal in order to prevent others from using it,
+though its default mode of operation is merely to display pretty pictures on
+your screen when it is not in use.
+
+The benefit that this program has over the combination of the
+.BR xlock (1)
+and
+.BR xautolock (1)
+programs is the ease with which new graphics hacks can be installed. You
+don't need to recompile (or even re-run) this program to add a new display
+mode.
+.SH OPTIONS
+.I xscreensaver
+accepts the following options:
+.TP 8
+.B \-timeout \fIminutes\fP
+The screensaver will activate after the keyboard and mouse have been idle
+for this many minutes.
+.TP 8
+.B \-cycle \fIminutes\fP
+After the screensaver has been running for this many minutes, the currently
+running sub-process will be killed (with \fBSIGTERM\fP), and a new one
+started. If this is 0, then the sub-process will not be killed; only one
+demo will run until the screensaver is deactivated by user activity.
+.TP 8
+.B \-nice \fIinteger\fP
+The sub-processes created by \fIxscreensaver\fP will be ``niced'' to this
+level, so that they do not consume cycles that are needed elsewhere.
+.TP 8
+.B \-verbose
+Print diagnostics.
+.TP 8
+.B \-silent
+
+.TP 8
+.B \-xidle
+Use the \fIXIdle\fP server extension to decide whether the user is idle.
+This is the default if \fIxscreensaver\fP has been compiled with support
+for XIdle. The XIdle method is faster and more reliable than what will
+be done otherwise, so use it if you can.
+.TP 8
+.B \-no\-xidle
+Don't use \fIXIdle\fP.
+.TP 8
+.B \-lock
+Enable locking: before the screensaver will turn off, it requires you to
+type the password of the person who launched the screensaver, or the root
+password. (Note: this doesn't work if the screensaver is launched
+by
+.BR xdm (1)
+because it can't know the user-id of the logged-in user.)
+.TP 8
+.B \-no\-lock
+Disable locking. This is the default.
+.TP 8
+.B \-lock\-timeout \fIminutes\fP
+This is how long after the screensaver activates that locking is enabled.
+For example, if this is 5, then any user activity within five minutes of
+the time when the screensaver activated will cause the screen to unblank
+without requiring a password. After 5 minutes, a password will be
+required. The default is 0, meaning that if locking is enabled, then
+a password will be required as soon as the screensaver activates.
+.TP 8
+.B \-demo
+Enter the interactive demo mode immediately after startup. Normally
+demo mode is invoked via the
+.BR xscreensaver\-command (1)
+program.
+.SH X RESOURCES
+\fIxscreensaver\fP understands the following resources:
+.PP
+.TP 8
+.B timeout \fR(class \fBTime\fP)
+Same as the \fI\-timeout\fP command-line option. Default 10 minutes.
+.TP 8
+.B cycle \fR(class \fBTime\fP)
+Same as the \fI\-cycle\fP command-line option. Default 10 minutes.
+.TP 8
+.B nice \fR(class \fBNice\fP)
+Same as the \fI\-nice\fP command-line option. Default 10.
+.TP 8
+.B verbose \fR(class \fBBoolean\fP)
+Same as the \fI\-verbose\fP command-line option.
+.TP 8
+.B xidle \fR(class \fBBoolean\fP)
+Same as the \fI\-xidle\fP command-line option.
+.TP 8
+.B lock \fR(class \fBBoolean\fP)
+Same as the \fI\-lock\fP command-line option.
+.TP 8
+.B lockTimeout \fR(class \fBTime\fP)
+Same as the \fI\-lock\-timeout\fP command-line option.
+.TP 8
+.B fade \fR(class \fBBoolean\fP)
+If this is true, then when the screensaver activates, the current contents
+of the screen will fade to black instead of simply winking out. This only
+works on displays with writable colormaps. Default true. A fade will also
+be done when switching graphics hacks (when the \fIcycle\fP timer expires.)
+.TP 8
+.B unfade \fR(class \fBBoolean\fP)
+If this is true, then when the screensaver deactivates, the original contents
+of the screen will fade in from black instead of appearing immediately. This
+only works on displays with writable colormaps, and if \fIfade\fP is true
+as well. Default false.
+.TP 8
+.B fadeSeconds \fR(class \fBTime\fP)
+If \fIfade\fP is true, this is how long the fade will be in
+seconds (default 1.)
+.TP 8
+.B fadeTicks \fR(class \fBInteger\fP)
+If \fIfade\fP is true, this is how many times a second the colormap will
+be changed to effect a fade. Higher numbers yield smoother fades, but
+may make the fades take longer if your server isn't fast enough to keep
+up. Default 75.
+.TP 8
+.B installColormap \fR(class \fBBoolean\fP)
+Whether a new colormap should be installed while the screensaver is on,
+so that the graphics hacks can get as many colors as possible. Default
+false.
+.TP 8
+.B passwdTimeout \fR(class \fBTime\fP)
+If \fIlock\fP is true, this is how many seconds the password dialog box
+should be left on the screen before giving up (default 30.) This should
+not be too large: the X server is grabbed for the duration that the password
+dialog box is up (for security purposes) and leaving the server grabbed for
+too long can cause problems.
+.TP 8
+.B programs \fR(class \fBPrograms\fP)
+The graphics hacks which \fIxscreensaver\fP runs when the user is idle.
+The value of this resource is a string, one \fIsh\fP command per line.
+Each line must contain exactly one command -- no semicolons.
+
+When the screensaver starts up, one of these is selected at random, and
+run. After the \fIcycle\fP period expires, it is killed, and another
+is selected and run.
+
+If the value of this resource (and the applicable one of \fBcolorPrograms\fP
+or \fBmonoPrograms\fP) is empty, then no programs will be run; the screen
+will simply be made black.
+
+Note that you must escape the newlines; here is an example of how you
+might set this in your \fI.Xdefaults\fP file:
+.EX
+xscreensaver.programs: \\
+ qix -root \\n\\
+ ico -r -faces -sleep 1 -obj ico \\n\\
+ xdaliclock -builtin2 -root \\n\\
+ xwave -root
+.EE
+To use a program as a screensaver, two things are required: that that
+program draw on the root window (or be able to be configured to draw on
+the root window); and that that program understand ``virtual root''
+windows, as used by virtual window managers such as \fItvtwm\fP.
+
+It is quite easy to make programs understand virtual roots if they
+don't already: you merely need to include the file \fI"vroot.h"\fP in
+them after the standard X includes, and recompile. This file is distributed
+with X11r5, and is included with xscreensaver as well.
+.TP 8
+.B monoPrograms \fR(class \fBMonoPrograms\fP)
+This resource is appended to the value of the \fIprograms\fP resource if
+the display on which the screensaver is running is monochrome.
+.TP 8
+.B colorPrograms \fR(class \fBColorPrograms\fP)
+This resource is appended to the value of the \fIprograms\fP resource if
+the display on which the screensaver is running is not monochrome.
+.PP
+Normally you won't need to change the following resources:
+.TP 8
+.B bourneShell \fR(class \fBBourneShell\fP)
+The pathname of the shell that \fIxscreensaver\fP uses to start subprocesses.
+This must be whatever your local variant of \fB/bin/sh\fP is -- in particular,
+it must not be \fBcsh\fP.
+.TP 8
+.B windowCreationTimeout \fR(class \fBTime\fP)
+When \fIXIdle\fP is not in use, this controls the delay between when
+windows are created and when \fIxscreensaver\fP selects events on them.
+Default 30 seconds.
+.TP 8
+.B pointerPollTime \fR(class \fBTime\fP)
+When \fIXIdle\fP is not in use, this controls how frequently \fIxscreensaver\fP
+checks to see if the mouse position or buttons have changed. Default 5 seconds.
+.TP 8
+.B initialDelay \fR(class \fBTime\fP)
+When \fIXIdle\fP is not in use, \fIxscreensaver\fP will wait this many seconds
+before selecting events on existing windows, under the assumption that
+\fIxscreensaver\fP is started during your login procedure, and the window
+state may be in flux. Default 30 seconds.
+.SH "HOW IT WORKS"
+When it is time to activate the screensaver, a full-screen black window is
+created. This window is given the appropriate properties so that, to any
+subsequently-created programs, it will appear to be a ``virtual root''
+window. Because of this, any program which draws on the root window (and
+which understands virtual roots) can be used as a screensaver.
+.PP
+When the user becomes active again, the screensaver window is unmapped and
+the running subprocess is killed by sending it \fBSIGTERM\fP. This is also
+how the subprocesses are killed when the screensaver decides that it's time
+to run a different demo: the old one is killed and a new one is launched.
+.PP
+Before launching a subprocess, \fIxscreensaver\fP stores an appropriate value
+for \fB$DISPLAY\fP in the environment that the child will recieve. (This is
+so that if you start \fIxscreensaver\fP with a \fI-display\fP argument, the
+programs which \fIxscreensaver\fP launches will draw on the same display.)
+.PP
+When the screensaver turns off, or is killed, care is taken to restore
+the ``real'' virtual root window if there is one. Because of this, it is
+important that you not kill the screensaver process with \fIkill -9\fP if
+you are running a virtual-root window manager. If you kill it with \-9,
+you may need to restart your window manager to repair the damage. This
+isn't an issue if you aren't running a virtual-root window manager.
+.PP
+For all the gory details, see the commentary at the top of xscreensaver.c.
+.PP
+You can control a running screensaver process by using the
+.BR xscreensaver\-command (1)
+program (which see.)
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH USING XDM(1)
+You can run \fIxscreensaver\fP from your xdm session, so that the
+screensaver will run even when nobody is logged in on the console.
+Simply add \fB"xscreensaver &"\fP to your \fI/usr/lib/X11/xdm/Xsetup\fP
+file. Because \fIxdm\fP grabs the keyboard, keypresses will not make
+the screensaver deactivate, but any mouse activity will.
+.PP
+Users may want to add \fB"xscreensaver-command -restart"\fP to their
+startup scripts, so that the screensaver will be reinitialized with
+their private resource settings when they log in.
+.PP
+It is safe to run this program as root (as \fIxdm\fP is likely to do.) If
+run as root, \fIxscreensaver\fP changes its effective user and group ids to
+something safe (like \fI"nobody"\fP) before connecting to the X server
+or launching user-specified programs.
+.PP
+Locking doesn't work if the screensaver is launched by \fIxdm\fP. To get
+around this, you can run the screensaver from \fIxdm\fP without locking,
+and kill and restart it from your personal X startup script to enable
+locking.
+.SH DEMO MODE
+If \fIxscreensaver\fP receives the \fBDEMO\fP ClientMessage, it pops up
+a dialog box from which you can examine and experiment with the screensaver's
+client programs.
+.PP
+Clicking left on an element in the scrolling list will place the indicated
+program and its args in the text field to be edited. Edit the arguments and
+hit return to run the program with the parameters you have specified.
+.PP
+Double-clicking on an element in the scrolling list will run the indicated
+program immediately.
+.PP
+When a client program is launched, the dialog box is hidden. Clicking
+any mouse button will re-expose the dialog box (but will not kill the
+client program.)
+.TP 8
+.B Run Next
+Clicking this button will run the next program in the list after the
+currently-selected one, and will scroll around to the top when it reaches
+the bottom.
+.TP 8
+.B Run Previous
+Opposite of Run Next; at the top, it scrolls around to the bottom.
+.TP 8
+.B Edit Parameters
+This pops up a second dialog box, in which you have the option to
+interactively change most of the screensaver's operational parameters,
+such as its timeouts, and whether it should hack colormaps. Changing
+these parameters here will affect only the running \fIxscreensaver\fP
+process; to make the changes permanent, you need to edit your X resource
+file.
+.TP 8
+.B Exit Demo Mode
+Returns to normal screensaver operation.
+.TP 8
+.B Reinitialize
+Causes the screensaver process to exit and then restart with the same
+command-line arguments. This causes the X resource database to be
+re-read. This is just like the \fI\-restart\fP argument to
+.BR xscreensaver\-command (1)
+except that when executed from this button, the screensaver will
+automatically return to demo mode after restarting.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver\-command (1),
+.BR xlock (1),
+.BR xnlock (1),
+.BR xautolock (1),
+.BR xdm (1),
+.BR qix (1),
+.BR pyro (1),
+.BR helix (1),
+.BR rorschach (1),
+.BR hopalong (1),
+.BR attraction (1),
+.BR greynetic (1),
+.BR rocks (1),
+.BR noseguy (1),
+.BR blitspin (1),
+.BR imsmap (1),
+.BR slidescreen (1),
+.BR hypercube (1),
+.BR maze (1),
+.BR ico (1),
+.BR xdaliclock (1),
+.BR xbouncebits (1),
+.BR xswarm (1),
+.BR xwave (1),
+.BR xfishtank (1)
+.SH BUGS
+If you are not using \fIXIdle\fP, and an application does not
+select \fBKeyPress\fP events on its non-leaf windows within the first
+30 seconds of their existence, but selects them later, then it is
+possible that \fIxscreensaver\fP could interfere with the propagation
+of those events. This isn't very likely, but this is the reason that
+it's a good idea to install the \fIXIdle\fP extension.
+.PP
+Although this program ``nices'' the subprocesses that it starts,
+graphics-intensive subprograms can still overload the machine by causing
+the X server process itself (which is not ``niced'') to suck a lot of
+cycles. Care should be taken to slow down programs intended for use as
+screensavers by inserting strategic calls to
+.BR sleep (3)
+or
+.BR usleep (3)
+\.
+
+Also, it will cause your X server to be pretty much permanently swapped in.
+(but the same is true of any program that draws periodically, like xclock or
+xload.)
+.PP
+If the subprocess is drawing too quickly and the connection to the X
+server is a slow one (such as an X terminal running over a phone line) then
+the screensaver might not turn off right away when the user becomes active
+again (the
+.BR ico (1)
+demo has this problem if being run in full-speed mode). This can be
+alleviated by inserting strategic calls to
+.BR XSync (3)
+in code intended for use as a screensaver. This prevents too much graphics
+activity from being buffered up.
+.PP
+The screensaver only runs on the default screen of the display. If you have
+more than one screen, you must run multiple screensaver processes, one for
+each screen. (I don't actually know whether this works, because I don't
+have access to a multi-screen machine. Comments welcome.)
+.PP
+If you don't have Motif, you can't compile with support for locking or
+demo mode.
+.PP
+When the \fBRun Next\fP and \fBRun Previous\fP buttons are used, the selected
+item may not be visible in the window. It's a Motif bug that selecting a
+different item doesn't scroll the list to show the new selected item.
+.PP
+Locking doesn't work if the screensaver is launched by \fIxdm\fP.
+.PP
+If you get an error message like ``couldn't get password of foo'' then
+this probably means that you're on a system in which the
+.BR getpwent (3)
+library routine can only be effectively used by root. If this is the case,
+then \fIxscreensaver\fP must be installed as setuid to root. Care has
+been taken to make this a safe thing to do.
+.PP
+There need to be a lot more graphics hacks. In particular, there should be
+a simulation of a Lavalite (tm).
+.PP
+The \fBinstallColormap\fP option doesn't work very well with the
+.BR twm (1)
+window manager and its descendants. There is a race condition between the
+screensaver and this window manager, which can result in the screensaver's
+colormap not getting installed properly, meaning the graphics hacks will
+appear in essentially random colors. The
+.BR mwm (1)
+and
+.BR olwm (1)
+window managers don't seem to have this problem. The race condition exists
+because X apparently does not provide a way for an OverrideRedirect window to
+have its own colormap, short of grabbing the server (which is neither a good
+idea, nor really possible with the current design.) What happens is that, as
+soon as the screensaver installs its colormap, \fBtwm\fP responds to
+the \fBColormapNotify\fP event that is generated by re-instaling the default
+colormap. Apparently, \fBtwm\fP doesn't \fIalways\fP do this; it seems to do
+it regularly if the screensaver is activated from a menu item, but seems to
+not do it if the screensaver comes on of its own volition, or is activated
+from another console. Any thoughts on this problem are welcome...
+.PP
+The \fBinstallColormap\fP option has no effect in "demo" mode, since the
+dialog boxes allocate their colors out of the screen's default colormap
+instead of the installed colormap.
+.PP
+For this same reason, locking doesn't work too well along
+with \fBinstallColormap\fP; the dialog box's colors are random.
+.PP
+Apparently there are some problems with ``XView'' programs getting confused
+and thinking that the screensaver window is the real root window even when
+the screensaver is not active: ClientMessages intended for the window manager
+are sent to the screensaver window instead. This could be solved by making
+xscreensaver forward all unrecognised ClientMessages to the real root window,
+but there may be other problems as well.
+.SH COPYRIGHT
+Copyright \(co 1992, 1993 by Jamie Zawinski. Permission to use, copy, modify,
+distribute, and sell this software and its documentation for any purpose is
+hereby granted without fee, provided that the above copyright notice appear
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation. No representations are made about the
+suitability of this software for any purpose. It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@lucid.com>, 13-aug-92.
+Please let me know if you find any bugs or make any improvements.
+
+Thanks to David Wojtowicz for implementing \fIlockTimeout\fP.
--- /dev/null
+b exit
+b abort
+set args -geom =700x700+0+0
--- /dev/null
+/*
+ * Imakefile file for xscreensaver, Copyright (c) 1993 Jamie Zawinski.
+ *
+ * You should not need to edit this file; edit ../config.h instead.
+ *
+ */
+
+#include "../config.h"
+
+ UTILS = ../utils
+ INCLUDES = -I$(UTILS)
+ DEFINES = R5ISMS
+EXTRA_LIBRARIES = $(XMULIB) $(XTOOLLIB) $(EXTENSIONLIB) $(XLIB) -lm
+ HACKS = attraction.c greynetic.c helix.c hopalong.c xroger-hack.c \
+ noseguy.c pyro.c qix.c rocks.c rorschach.c blitspin.c \
+ imsmap.c slidescreen.c maze.c hypercube.c halo.c
+ MEN = attraction.man greynetic.man helix.man hopalong.man \
+ noseguy.man pyro.man xroger.man qix.man rocks.man \
+ rorschach.man blitspin.man imsmap.man slidescreen.man \
+ maze.man hypercube.man halo.man
+ TARFILES = README Imakefile screenhack.c $(HACKS) screenhack.h \
+ vroot.h xlock.h $(MEN) .gdbinit noses/\*
+
+all::
+
+echo_tarfiles:
+ @echo $(TARFILES)
+
+#define ScreenhackTarget(p,ps,deps) @@\
+all:: p @@\
+p: deps screenhack.h ps.o $(DEPLIBS) @@\
+ RemoveTargetProgram($@) @@\
+ $(CC) -o $@ $(LDOPTIONS) deps ps.o $(LDLIBS) $(EXTRA_LOAD_FLAGS) @@\
+ @@\
+InstallProgram(p,$(BINDIR)) @@\
+InstallManPage(p,$(MANDIR)) @@\
+clean:: @@\
+ $(RM) p
+
+HOBJS=screenhack.o $(UTILS)/resources.o $(UTILS)/usleep.o
+
+ScreenhackTarget (qix, qix, $(HOBJS) $(UTILS)/hsv.o)
+ScreenhackTarget (helix, helix, $(HOBJS) $(UTILS)/hsv.o)
+ScreenhackTarget (pyro, pyro, $(HOBJS) $(UTILS)/hsv.o)
+ScreenhackTarget (attraction, attraction, $(HOBJS) $(UTILS)/hsv.o $(UTILS)/spline.o)
+ScreenhackTarget (rorschach, rorschach, $(HOBJS) $(UTILS)/hsv.o)
+ScreenhackTarget (hopalong, hopalong, $(HOBJS) $(UTILS)/hsv.o)
+ScreenhackTarget (xroger, xroger-hack, $(HOBJS) $(UTILS)/hsv.o $(UTILS)/xroger.o)
+ScreenhackTarget (rocks, rocks, $(HOBJS))
+ScreenhackTarget (noseguy, noseguy, $(HOBJS))
+ScreenhackTarget (blitspin, blitspin, $(HOBJS))
+ScreenhackTarget (greynetic, greynetic, $(HOBJS))
+ScreenhackTarget (slidescreen, slidescreen, $(HOBJS))
+ScreenhackTarget (imsmap, imsmap, $(HOBJS) $(UTILS)/hsv.o)
+ScreenhackTarget (maze, maze, $(HOBJS) $(UTILS)/xroger.o)
+ScreenhackTarget (hypercube, hypercube, $(HOBJS))
+ScreenhackTarget (halo, halo, $(HOBJS) $(UTILS)/hsv.o)
--- /dev/null
+
+This directory contains various graphics hacks. These are independent from
+the xscreensaver program (in the ../driver/ directory) but some of them use
+the utility functions found in the ../utils/ directory.
+
+If you have compilation problems, check the parameters in ../config.h.
+
+The file xlock.h makes it really easy to turn `xlock' modules into standalone
+programs that can be used with xscreensaver; check it out.
--- /dev/null
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+/* Simulation of a pair of quasi-gravitational fields, maybe sorta kinda
+ a little like the strong and weak electromagnetic forces. Derived from
+ a Lispm screensaver by John Pezaris <pz@mit.edu>.
+
+ John sez:
+
+ The simulation started out as a purely accurate gravitational simulation,
+ but, with constant simulation step size, I quickly realized the field being
+ simulated while grossly gravitational was, in fact, non-conservative. It
+ also had the rather annoying behavior of dealing very badly with colliding
+ orbs. Therefore, I implemented a negative-gravity region (with two
+ thresholds; as I read your code, you only implemented one) to prevent orbs
+ from every coming too close together, and added a viscosity factor if the
+ speed of any orb got too fast. This provides a nice stable system with
+ interesting behavior.
+
+ I had experimented with a number of fields including the van der Waals
+ force (very interesting orbiting behavior) and 1/r^3 gravity (not as
+ interesting as 1/r^2). An even normal viscosity (rather than the
+ thresholded version to bleed excess energy) is also not interesting.
+ The 1/r^2, -1/r^2, -10/r^2 thresholds proved not only robust but also
+ interesting -- the orbs never collided and the threshold viscosity fixed
+ the non-conservational problem.
+ */
+
+#include "screenhack.h"
+#include "spline.h"
+#include <stdio.h>
+#include <math.h>
+#if __STDC__
+#include <values.h>
+#endif
+
+struct ball {
+ float x, y;
+ float vx, vy;
+ float dx, dy;
+ float mass;
+ int size;
+ XColor color;
+ int hue;
+};
+
+static unsigned int default_fg_pixel;
+static struct ball *balls;
+static int npoints;
+static int threshold;
+static int delay;
+static int global_size;
+static int segments;
+static Bool glow_p;
+static Bool orbit_p;
+static XPoint *point_stack;
+static int point_stack_size, point_stack_fp, pixel_stack_fp, pixel_stack_size;
+static unsigned long *pixel_stack;
+static unsigned int color_shift;
+
+static enum object_mode {
+ ball_mode, line_mode, polygon_mode, spline_mode, spline_filled_mode,
+ tail_mode
+} mode;
+
+static enum color_mode {
+ cycle_mode, random_mode
+} cmode;
+
+static GC draw_gc, erase_gc;
+
+#define MAX_SIZE 16
+
+#define min(a,b) ((a)<(b)?(a):(b))
+#define max(a,b) ((a)>(b)?(a):(b))
+
+static void
+init_balls (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ int i;
+ XWindowAttributes xgwa;
+ XGCValues gcv;
+ int xlim, ylim, midx, midy, r, vx, vy;
+ double th;
+ Colormap cmap;
+ char *mode_str;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ xlim = xgwa.width;
+ ylim = xgwa.height;
+ cmap = xgwa.colormap;
+ midx = xlim/2;
+ midy = ylim/2;
+ r = get_integer_resource ("radius", "Integer");
+ if (r <= 0 || r > min (xlim/2, ylim/2))
+ r = min (xlim/2, ylim/2) - 50;
+ vx = get_integer_resource ("vx", "Integer");
+ vy = get_integer_resource ("vy", "Integer");
+ npoints = get_integer_resource ("points", "Integer");
+ if (npoints < 1)
+ npoints = 3 + (random () % 5);
+ balls = (struct ball *) malloc (npoints * sizeof (struct ball));
+ segments = get_integer_resource ("segments", "Integer");
+ if (segments < 0) segments = 1;
+ threshold = get_integer_resource ("threshold", "Integer");
+ if (threshold < 0) threshold = 0;
+ delay = get_integer_resource ("delay", "Integer");
+ if (delay < 0) delay = 0;
+ global_size = get_integer_resource ("size", "Integer");
+ if (global_size < 0) global_size = 0;
+ glow_p = get_boolean_resource ("glow", "Boolean");
+ orbit_p = get_boolean_resource ("orbit", "Boolean");
+ color_shift = get_integer_resource ("colorShift", "Integer");
+ if (color_shift >= 360) color_shift = 5;
+
+ mode_str = get_string_resource ("mode", "Mode");
+ if (! mode_str) mode = ball_mode;
+ else if (!strcmp (mode_str, "balls")) mode = ball_mode;
+ else if (!strcmp (mode_str, "lines")) mode = line_mode;
+ else if (!strcmp (mode_str, "polygons")) mode = polygon_mode;
+ else if (!strcmp (mode_str, "tails")) mode = tail_mode;
+ else if (!strcmp (mode_str, "splines")) mode = spline_mode;
+ else if (!strcmp (mode_str, "filled-splines")) mode = spline_filled_mode;
+ else {
+ fprintf (stderr,
+ "%s: mode must be balls, lines, tails, polygons, splines, or\n\
+ filled-splines, not \"%s\"\n",
+ progname, mode_str);
+ exit (1);
+ }
+
+ mode_str = get_string_resource ("colorMode", "ColorMode");
+ if (! mode_str) cmode = cycle_mode;
+ else if (!strcmp (mode_str, "cycle")) cmode = cycle_mode;
+ else if (!strcmp (mode_str, "random")) cmode = random_mode;
+ else {
+ fprintf (stderr, "%s: colorMode must be cycle or random, not \"%s\"\n",
+ progname, mode_str);
+ exit (1);
+ }
+
+ if (mode != ball_mode && mode != tail_mode) glow_p = False;
+
+ if (mode == polygon_mode && npoints < 3)
+ mode = line_mode;
+
+ if (mode != ball_mode)
+ {
+ int size = (segments ? segments : 1);
+ point_stack_size = size * (npoints + 1);
+ point_stack = (XPoint *) calloc (point_stack_size, sizeof (XPoint));
+ point_stack_fp = 0;
+ if (segments > 0)
+ pixel_stack_size = segments;
+ else
+ pixel_stack_size = (360 / color_shift);
+ pixel_stack = (unsigned long *)
+ calloc (pixel_stack_size, sizeof (unsigned int));
+ pixel_stack_fp = 0;
+ }
+
+ gcv.line_width = (mode == tail_mode
+ ? (global_size ? global_size : (MAX_SIZE * 2 / 3))
+ : 1);
+ gcv.cap_style = (mode == tail_mode ? CapRound : CapButt);
+
+ gcv.foreground = default_fg_pixel =
+ get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+ draw_gc = XCreateGC (dpy, window, GCForeground|GCLineWidth|GCCapStyle, &gcv);
+ gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
+ erase_gc = XCreateGC (dpy, window, GCForeground|GCLineWidth|GCCapStyle,&gcv);
+
+ if (!mono_p && mode != ball_mode)
+ for (i = 0; i < pixel_stack_size; i++)
+ {
+ XColor color;
+ color.pixel = default_fg_pixel;
+ if (!XQueryColor (dpy, cmap, &color)) abort ();
+ if (!XAllocColor (dpy, cmap, &color)) abort ();
+ pixel_stack [i] = color.pixel;
+ }
+
+#define rand_size() min (MAX_SIZE, 8 + (random () % (MAX_SIZE - 9)))
+
+ if (orbit_p && !global_size)
+ /* To orbit, all objects must be the same mass, or the math gets
+ really hairy... */
+ global_size = rand_size ();
+
+ th = frand (M_PI+M_PI);
+ for (i = 0; i < npoints; i++)
+ {
+ int new_size = (global_size ? global_size : rand_size ());
+ balls [i].dx = 0;
+ balls [i].dy = 0;
+ balls [i].size = new_size;
+ balls [i].mass = (new_size * new_size * 10);
+ balls [i].x = midx + r * cos (i * ((M_PI+M_PI) / npoints) + th);
+ balls [i].y = midy + r * sin (i * ((M_PI+M_PI) / npoints) + th);
+ if (! orbit_p)
+ {
+ balls [i].vx = vx ? vx : ((6.0 - (random () % 11)) / 8.0);
+ balls [i].vy = vy ? vy : ((6.0 - (random () % 11)) / 8.0);
+ }
+ balls [i].color.pixel = default_fg_pixel;
+ balls [i].color.flags = DoRed | DoGreen | DoBlue;
+ if (!mono_p)
+ {
+ if (i != 0 && (glow_p || mode != ball_mode))
+ balls [i].hue = balls [0].hue;
+ else
+ balls [i].hue = random () % 360;
+ hsv_to_rgb (balls [i].hue, 1.0, 1.0,
+ &balls [i].color.red, &balls [i].color.green,
+ &balls [i].color.blue);
+ if (!XAllocColor (dpy, cmap, &balls [i].color))
+ mono_p = True; /* just give up */
+ }
+ }
+
+ if (orbit_p)
+ {
+ double a = 0;
+ double v;
+ double v_mult = get_float_resource ("vMult", "Float");
+ if (v_mult == 0.0) v_mult = 1.0;
+
+ for (i = 1; i < npoints; i++)
+ {
+ double _2ipi_n = (2 * i * M_PI / npoints);
+ double x = r * cos (_2ipi_n);
+ double y = r * sin (_2ipi_n);
+ double distx = r - x;
+ double dist2 = (distx * distx) + (y * y);
+ double dist = sqrt (dist2);
+ double a1 = ((balls[i].mass / dist2) *
+ ((dist < threshold) ? -1.0 : 1.0) *
+ (distx / dist));
+ a += a1;
+ }
+ if (a < 0.0)
+ {
+ fprintf (stderr, "%s: domain error: forces on balls too great\n",
+ progname);
+ exit (-1);
+ }
+ v = sqrt (a * r) * v_mult;
+ for (i = 0; i < npoints; i++)
+ {
+ double k = ((2 * i * M_PI / npoints) + th);
+ balls [i].vx = -v * sin (k);
+ balls [i].vy = v * cos (k);
+ }
+ }
+
+ if (mono_p) glow_p = False;
+ XClearWindow (dpy, window);
+}
+
+static void
+compute_force (i, dx_ret, dy_ret)
+ int i;
+ float *dx_ret, *dy_ret;
+{
+ int j;
+ *dx_ret = 0;
+ *dy_ret = 0;
+ for (j = 0; j < npoints; j++)
+ {
+ float x_dist, y_dist, dist, dist2;
+
+ if (i == j) continue;
+ x_dist = balls [j].x - balls [i].x;
+ y_dist = balls [j].y - balls [i].y;
+ dist2 = (x_dist * x_dist) + (y_dist * y_dist);
+ dist = sqrt (dist2);
+
+ if (dist > 0.1) /* the balls are not overlapping */
+ {
+ float new_acc = ((balls[j].mass / dist2) *
+ ((dist < threshold) ? -1.0 : 1.0));
+ float new_acc_dist = new_acc / dist;
+ *dx_ret += new_acc_dist * x_dist;
+ *dy_ret += new_acc_dist * y_dist;
+ }
+ else
+ { /* the balls are overlapping; move randomly */
+ *dx_ret += (frand (10.0) - 5.0);
+ *dy_ret += (frand (10.0) - 5.0);
+ }
+ }
+}
+
+static void
+run_balls (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ int last_point_stack_fp = point_stack_fp;
+ static int tick = 500, xlim, ylim;
+ static Colormap cmap;
+ int i;
+
+ if (tick++ == 500)
+ {
+ XWindowAttributes xgwa;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ tick = 0;
+ xlim = xgwa.width;
+ ylim = xgwa.height;
+ cmap = xgwa.colormap;
+ }
+
+ /* compute the force of attraction/repulsion among all balls */
+ for (i = 0; i < npoints; i++)
+ compute_force (i, &balls[i].dx, &balls[i].dy);
+
+ /* move the balls according to the forces now in effect */
+ for (i = 0; i < npoints; i++)
+ {
+ float old_x = balls[i].x;
+ float old_y = balls[i].y;
+ float new_x, new_y;
+ int size = balls[i].size;
+ balls[i].vx += balls[i].dx;
+ balls[i].vy += balls[i].dy;
+
+ /* don't let them get too fast: impose a terminal velocity
+ (actually, make the medium have friction) */
+ if (balls[i].vx > 10)
+ {
+ balls[i].vx *= 0.9;
+ balls[i].dx = 0;
+ }
+ if (balls[i].vy > 10)
+ {
+ balls[i].vy *= 0.9;
+ balls[i].dy = 0;
+ }
+
+ balls[i].x += balls[i].vx;
+ balls[i].y += balls[i].vy;
+
+ /* bounce off the walls */
+ if (balls[i].x >= (xlim - balls[i].size))
+ {
+ balls[i].x = (xlim - balls[i].size - 1);
+ if (balls[i].vx > 0)
+ balls[i].vx = -balls[i].vx;
+ }
+ if (balls[i].y >= (ylim - balls[i].size))
+ {
+ balls[i].y = (ylim - balls[i].size - 1);
+ if (balls[i].vy > 0)
+ balls[i].vy = -balls[i].vy;
+ }
+ if (balls[i].x <= 0)
+ {
+ balls[i].x = 0;
+ if (balls[i].vx < 0)
+ balls[i].vx = -balls[i].vx;
+ }
+ if (balls[i].y <= 0)
+ {
+ balls[i].y = 0;
+ if (balls[i].vy < 0)
+ balls[i].vy = -balls[i].vy;
+ }
+
+ new_x = balls[i].x;
+ new_y = balls[i].y;
+
+ /* make color saturation be related to particle acceleration. */
+ if (glow_p)
+ {
+ float limit = 0.5;
+ double s, v, fraction;
+ float vx = balls [i].dx;
+ float vy = balls [i].dy;
+ XColor new_color;
+ if (vx < 0) vx = -vx;
+ if (vy < 0) vy = -vy;
+ fraction = vx + vy;
+ if (fraction > limit) fraction = limit;
+
+ s = 1 - (fraction / limit);
+ v = 1.0;
+
+ s = (s * 0.75) + 0.25;
+
+ hsv_to_rgb (balls [i].hue, s, v,
+ &new_color.red, &new_color.green, &new_color.blue);
+ if (XAllocColor (dpy, cmap, &new_color))
+ {
+ XFreeColors (dpy, cmap, &balls [i].color.pixel, 1, 0);
+ balls [i].color = new_color;
+ }
+ }
+
+ if (mode == ball_mode)
+ {
+ if (!mono_p)
+ XSetForeground (dpy, draw_gc, balls [i].color.pixel);
+ XFillArc (dpy, window, erase_gc, (int) old_x, (int) old_y,
+ size, size, 0, 360*64);
+ XFillArc (dpy, window, draw_gc, (int) new_x, (int) new_y,
+ size, size, 0, 360*64);
+ }
+ if (mode != ball_mode)
+ {
+ point_stack [point_stack_fp].x = new_x;
+ point_stack [point_stack_fp].y = new_y;
+ point_stack_fp++;
+ }
+ }
+
+ /* draw the lines or polygons after computing all points */
+ if (mode != ball_mode)
+ {
+ point_stack [point_stack_fp].x = balls [0].x; /* close the polygon */
+ point_stack [point_stack_fp].y = balls [0].y;
+ point_stack_fp++;
+ if (point_stack_fp == point_stack_size)
+ point_stack_fp = 0;
+ else if (point_stack_fp > point_stack_size) /* better be aligned */
+ abort ();
+ if (!mono_p)
+ {
+ XColor color2;
+ color2 = balls [0].color;
+ switch (cmode)
+ {
+ case cycle_mode:
+ cycle_hue (&color2, color_shift);
+ break;
+ case random_mode:
+ color2.red = random () % 65535;
+ color2.green = random () % 65535;
+ color2.blue = random () % 65535;
+ break;
+ default:
+ abort ();
+ }
+
+ if (!XAllocColor (dpy, cmap, &color2))
+ {
+ color2 = balls [0].color;
+ if (!XAllocColor (dpy, cmap, &balls [0].color))
+ abort ();
+ }
+ pixel_stack [pixel_stack_fp++] = balls [0].color.pixel;
+ if (pixel_stack_fp >= pixel_stack_size)
+ pixel_stack_fp = 0;
+ XFreeColors (dpy, cmap, pixel_stack + pixel_stack_fp, 1, 0);
+ balls [0].color = color2;
+ XSetForeground (dpy, draw_gc, balls [0].color.pixel);
+ }
+ }
+
+ switch (mode)
+ {
+ case ball_mode:
+ break;
+ case line_mode:
+ if (segments > 0)
+ XDrawLines (dpy, window, erase_gc, point_stack + point_stack_fp,
+ npoints + 1, CoordModeOrigin);
+ XDrawLines (dpy, window, draw_gc, point_stack + last_point_stack_fp,
+ npoints + 1, CoordModeOrigin);
+ break;
+ case polygon_mode:
+ if (segments > 0)
+ XFillPolygon (dpy, window, erase_gc, point_stack + point_stack_fp,
+ npoints + 1, (npoints == 3 ? Convex : Complex),
+ CoordModeOrigin);
+ XFillPolygon (dpy, window, draw_gc, point_stack + last_point_stack_fp,
+ npoints + 1, (npoints == 3 ? Convex : Complex),
+ CoordModeOrigin);
+ break;
+ case tail_mode:
+ {
+ int i;
+ for (i = 0; i < npoints; i++)
+ {
+ int index = point_stack_fp + i;
+ int next_index = (index + (npoints + 1)) % point_stack_size;
+ XDrawLine (dpy, window, erase_gc,
+ point_stack [index].x,
+ point_stack [index].y,
+ point_stack [next_index].x,
+ point_stack [next_index].y);
+
+ index = last_point_stack_fp + i;
+ next_index = (index - (npoints + 1)) % point_stack_size;
+ if (next_index < 0) next_index += point_stack_size;
+ if (point_stack [next_index].x == 0 &&
+ point_stack [next_index].y == 0)
+ continue;
+ XDrawLine (dpy, window, draw_gc,
+ point_stack [index].x,
+ point_stack [index].y,
+ point_stack [next_index].x,
+ point_stack [next_index].y);
+ }
+ }
+ break;
+ case spline_mode:
+ case spline_filled_mode:
+ {
+ int i;
+ static spline *s = 0;
+ if (! s) s = make_spline (npoints);
+ if (segments > 0)
+ {
+ for (i = 0; i < npoints; i++)
+ {
+ s->control_x [i] = point_stack [point_stack_fp + i].x;
+ s->control_y [i] = point_stack [point_stack_fp + i].y;
+ }
+ compute_closed_spline (s);
+ if (mode == spline_filled_mode)
+ XFillPolygon (dpy, window, erase_gc, s->points, s->n_points,
+ (s->n_points == 3 ? Convex : Complex),
+ CoordModeOrigin);
+ else
+ XDrawLines (dpy, window, erase_gc, s->points, s->n_points,
+ CoordModeOrigin);
+ }
+ for (i = 0; i < npoints; i++)
+ {
+ s->control_x [i] = point_stack [last_point_stack_fp + i].x;
+ s->control_y [i] = point_stack [last_point_stack_fp + i].y;
+ }
+ compute_closed_spline (s);
+ if (mode == spline_filled_mode)
+ XFillPolygon (dpy, window, draw_gc, s->points, s->n_points,
+ (s->n_points == 3 ? Convex : Complex),
+ CoordModeOrigin);
+ else
+ XDrawLines (dpy, window, draw_gc, s->points, s->n_points,
+ CoordModeOrigin);
+ }
+ break;
+ default:
+ abort ();
+ }
+
+ XSync (dpy, True);
+}
+
+\f
+char *progclass = "Attraction";
+
+char *defaults [] = {
+ "*background: black",
+ "*foreground: white",
+ "*mode: balls",
+ "*points: 0",
+ "*size: 0",
+ "*threshold: 100",
+ "*delay: 10000",
+ "*glow: false",
+ "*orbit: false",
+ "*colorShift: 3",
+ "*segments: 100",
+ 0
+};
+
+XrmOptionDescRec options [] = {
+ { "-mode", ".mode", XrmoptionSepArg, 0 },
+ { "-points", ".points", XrmoptionSepArg, 0 },
+ { "-threshold", ".threshold", XrmoptionSepArg, 0 },
+ { "-segments", ".segments", XrmoptionSepArg, 0 },
+ { "-delay", ".delay", XrmoptionSepArg, 0 },
+ { "-size", ".size", XrmoptionSepArg, 0 },
+ { "-color-mode", ".colorMode", XrmoptionSepArg, 0 },
+ { "-color-shift", ".colorShift", XrmoptionSepArg, 0 },
+ { "-radius", ".radius", XrmoptionSepArg, 0 },
+ { "-vx", ".vx", XrmoptionSepArg, 0 },
+ { "-vy", ".vy", XrmoptionSepArg, 0 },
+ { "-vmult", ".vMult", XrmoptionSepArg, 0 },
+ { "-glow", ".glow", XrmoptionNoArg, "true" },
+ { "-noglow", ".glow", XrmoptionNoArg, "false" },
+ { "-orbit", ".orbit", XrmoptionNoArg, "true" }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ init_balls (dpy, window);
+ while (1)
+ {
+ run_balls (dpy, window);
+ if (delay) usleep (delay);
+ }
+}
--- /dev/null
+.TH XScreenSaver 1 "22-mar-93" "X Version 11"
+.SH NAME
+attraction - interactions of opposing forces
+.SH SYNOPSIS
+.B attraction
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-points \fIint\fP] [\-threshold \fIint\fP] [\-mode balls | lines | polygons | splines | filled-splines | tails ] [\-color-mode cycle | random] [\-size \fIint\fP] [\-segments \fIint\fP] [\-delay \fIusecs\fP] [\-color-shift \fIdegrees\fP] [\-radius \fIint\fP] [\-vx \fIint\fP] [\-vy \fIint\fP] [\-glow] [\-noglow] [\-orbit]
+.SH DESCRIPTION
+The \fIattraction\fP program has several visually different modes of
+operation, all of which are based on the interactions of a set of control
+points which attract each other up to a certain distance, and then begin
+to repel each other. The attraction/repulsion is proportional to the
+distance between any two particles.
+.SH OPTIONS
+.I attraction
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-points integer
+How many control points should be used, or 0 to select the number randomly.
+Default 0. Between 3 and 15 works best.
+.TP 8
+.B \-threshold integer
+The distance (in pixels) from each particle at which the attractive force
+becomes repulsive. Default 100.
+.TP 8
+.B \-mode "balls | lines | polygons | tails | splines | filled-splines"
+In \fIballs\fP mode (the default) the control points are drawn as filled
+circles. The larger the circle, the more massive the particle.
+
+In \fIlines\fP mode, the control points are connected by straight lines;
+the effect is something like \fIqix\fP.
+
+In \fIpolygons\fP mode, the control points are connected by straight
+lines, and filled in. This is most interesting in color.
+
+In \fIsplines\fP mode, a closed spline is interpolated from the control
+points.
+
+In \fIfilled-splines\fP mode, the splines are filled in instead of being
+outlines. This is most interesting in color.
+
+In \fItails\fP mode, the path which each particle follows is indicated
+by a worm-like trail, whose length is controlled by the \fIsegments\fP
+parameter.
+.TP 8
+.B \-color-mode cycle | random
+Whether colors should cycle through the spectrum, or be picked randomly.
+.TP 8
+.B \-size integer
+The size of the balls in pixels, or 0, meaning to select the sizes
+randomly (the default.) If this is specified, then all balls will be
+the same size. This option has an effect in all modes, since the ``size''
+of the balls controls their mass.
+.TP 8
+.B \-segments integer
+If in \fIlines\fP or \fIpolygons\fP mode, how many sets of line segments
+or polygons should be drawn. Default 100. This has no effect in \fIballs\fP
+mode. If \fIsegments\fP is 0, then no segments will ever be erased (this
+is only useful in color.)
+.TP 8
+.B \-delay microseconds
+How much of a delay should be introduced between steps of the animation.
+Default 10000, or about 0.01 seconds.
+.TP 8
+.B \-color-shift degrees
+If on a color display, the color of the line segments or polygons will
+cycle through the spectrum. This specifies how far the hue of each segment
+should be from the next, in degrees on the HSV wheel. Default 3.
+This has no effect in \fIballs\fP mode.
+.TP 8
+.B \-radius
+The size in pixels of the circle on which the points are initially positioned.
+The default is slightly smaller than the size of the window.
+.TP 8
+.B \-glow
+This is consulted only in \fIballs\fP mode. If this is specified, then
+the saturation of the colors of the points will vary according to their
+current acceleration. This has the effect that the balls flare brighter
+when they are reacting to each other most strongly.
+
+In \fIglow\fP mode, all of the balls will be drawn the same (random)
+color, modulo the saturation shifts. In non-glow mode, the balls will
+each be drawn in a random color that doesn't change.
+.TP 8
+.B \-noglow
+Don't do ``glowing.'' This is the default.
+.TP 8
+.B \-vx pixels
+.TP 8
+.B \-vy pixels
+Initial velocity of the balls. This has no effect in \fB\-orbit\fP mode.
+.TP 8
+.B \-orbit
+Make the initial force on each ball be tangential to the circle on which
+they are initially placed, with the right velocity to hold them in orbit
+about each other. After a while, roundoff errors will cause the orbit
+to decay.
+.TP 8
+.B \-vmult float
+In orbit mode, the initial velocity of the balls is multiplied by this;
+a number less than 1 will make the balls pull closer together, and a larger
+number will make them move apart. The default is 1, meaning stability.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1992, 1993 by Jamie Zawinski. Permission to use, copy, modify,
+distribute, and sell this software and its documentation for any purpose is
+hereby granted without fee, provided that the above copyright notice appear
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation. No representations are made about the
+suitability of this software for any purpose. It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@lucid.com>, 13-aug-92.
--- /dev/null
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+/* Rotate a bitmap using using bitblts.
+ The bitmap must be square, and must be a power of 2 in size.
+ This was translated from SmallTalk code which appeared in the
+ August 1981 issue of Byte magazine.
+
+ The input bitmap may be non-square, it is padded and centered
+ with the background color. Another way would be to subdivide
+ the bitmap into square components and rotate them independently,
+ but I don't think that would be as interesting looking.
+
+ It's too bad almost nothing uses blitter hardware these days,
+ or this might actually win.
+ */
+
+#include "screenhack.h"
+#include <X11/Xmu/Drawing.h>
+#include <stdio.h>
+
+static Display *dpy;
+static Window window;
+static unsigned int size;
+static Pixmap self, temp, mask;
+static GC SET, CLR, CPY, IOR, AND, XOR;
+static GC gc;
+static int delay, delay2;
+static Pixmap bitmap;
+
+static void rotate(), init (), display ();
+
+#define copy_all_to(from, xoff, yoff, to, gc) \
+ XCopyArea (dpy, (from), (to), (gc), 0, 0, \
+ size-(xoff), size-(yoff), (xoff), (yoff))
+
+#define copy_all_from(to, xoff, yoff, from, gc) \
+ XCopyArea (dpy, (from), (to), (gc), (xoff), (yoff), \
+ size-(xoff), size-(yoff), 0, 0)
+
+static void
+rotate ()
+{
+ int qwad; /* fuckin' C, man... who needs namespaces? */
+ XFillRectangle (dpy, mask, CLR, 0, 0, size, size);
+ XFillRectangle (dpy, mask, SET, 0, 0, size>>1, size>>1);
+ for (qwad = size>>1; qwad > 0; qwad>>=1)
+ {
+ if (delay) usleep (delay);
+ copy_all_to (mask, 0, 0, temp, CPY); /* 1 */
+ copy_all_to (mask, 0, qwad, temp, IOR); /* 2 */
+ copy_all_to (self, 0, 0, temp, AND); /* 3 */
+ copy_all_to (temp, 0, 0, self, XOR); /* 4 */
+ copy_all_from (temp, qwad, 0, self, XOR); /* 5 */
+ copy_all_from (self, qwad, 0, self, IOR); /* 6 */
+ copy_all_to (temp, qwad, 0, self, XOR); /* 7 */
+ copy_all_to (self, 0, 0, temp, CPY); /* 8 */
+ copy_all_from (temp, qwad, qwad, self, XOR); /* 9 */
+ copy_all_to (mask, 0, 0, temp, AND); /* A */
+ copy_all_to (temp, 0, 0, self, XOR); /* B */
+ copy_all_to (temp, qwad, qwad, self, XOR); /* C */
+ copy_all_from (mask, qwad>>1, qwad>>1, mask, AND); /* D */
+ copy_all_to (mask, qwad, 0, mask, IOR); /* E */
+ copy_all_to (mask, 0, qwad, mask, IOR); /* F */
+ display (self);
+ }
+}
+
+static void
+init ()
+{
+ XWindowAttributes xgwa;
+ Colormap cmap;
+ XGCValues gcv;
+ int width, height, xh, yh;
+ unsigned int real_size;
+ char *bitmap_name;
+ int i;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ cmap = xgwa.colormap;
+
+ delay = get_integer_resource ("delay", "Integer");
+ delay2 = get_integer_resource ("delay2", "Integer");
+ if (delay < 0) delay = 0;
+ if (delay2 < 0) delay2 = 0;
+ bitmap_name = get_string_resource ("bitmap", "Bitmap");
+ if (! bitmap_name)
+ {
+ fprintf (stderr, "%s: no bitmap specified\n", progname);
+ exit (1);
+ }
+ bitmap = XmuLocateBitmapFile (DefaultScreenOfDisplay (dpy), bitmap_name,
+ 0, 0, &width, &height, &xh, &yh);
+ if (! bitmap)
+ {
+ fprintf (stderr, "%s: couldn't find bitmap %s\n", progname, bitmap_name);
+ exit (1);
+ }
+
+ real_size = (width > height) ? width : height;
+
+ size = real_size;
+ /* semi-sleazy way of doing (setq size (expt 2 (ceiling (log size 2)))). */
+ for (i = 31; i > 0; i--)
+ if (size & (1<<i)) break;
+ if (size & (~(1<<i)))
+ size = (size>>i)<<(i+1);
+ self = XCreatePixmap (dpy, window, size, size, 1);
+ temp = XCreatePixmap (dpy, window, size, size, 1);
+ mask = XCreatePixmap (dpy, window, size, size, 1);
+ gcv.foreground = 1;
+ gcv.function=GXset; SET = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
+ gcv.function=GXclear;CLR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
+ gcv.function=GXcopy; CPY = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
+ gcv.function=GXor; IOR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
+ gcv.function=GXand; AND = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
+ gcv.function=GXxor; XOR = XCreateGC(dpy,self,GCFunction|GCForeground,&gcv);
+
+ XFillRectangle (dpy, self, CLR, 0, 0, size, size);
+ XCopyArea (dpy, bitmap, self, CPY, 0, 0, width, height,
+ (size - width)>>1, (size - height)>>1);
+
+ gcv.foreground = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+ gcv.background = get_pixel_resource ("background", "Background", dpy, cmap);
+ gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
+}
+
+static void
+display (pixmap)
+ Pixmap pixmap;
+{
+ XWindowAttributes xgwa;
+ static int last_w = 0, last_h = 0;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ if (xgwa.width != last_w || xgwa.height != last_h)
+ {
+ XClearWindow (dpy, window);
+ last_w = xgwa.width;
+ last_h = xgwa.height;
+ }
+ XCopyPlane (dpy, pixmap, window, gc, 0, 0, size, size,
+ (xgwa.width-size)>>1, (xgwa.height-size)>>1, 1);
+/*
+ XDrawRectangle (dpy, window, gc,
+ ((xgwa.width-size)>>1)-1, ((xgwa.height-size)>>1)-1,
+ size+2, size+2);
+*/
+ XSync (dpy, True);
+}
+
+\f
+char *progclass = "BlitSpin";
+
+char *defaults [] = {
+ "*background: black",
+ "*foreground: white",
+ "*delay: 500000",
+ "*delay2: 500000",
+ "*bitmap: xlogo64", /* hey, pick something better! */
+ 0
+};
+
+XrmOptionDescRec options [] = {
+ { "-delay", ".delay", XrmoptionSepArg, 0 },
+ { "-delay2", ".delay2", XrmoptionSepArg, 0 },
+ { "-bitmap", ".bitmap", XrmoptionSepArg, 0 }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (d, w)
+ Display *d;
+ Window w;
+{
+ dpy = d;
+ window = w;
+ init ();
+ while (1)
+ {
+ rotate ();
+ if (delay2) usleep (delay2);
+ }
+}
--- /dev/null
+.TH XScreenSaver 1 "17-aug-92" "X Version 11"
+.SH NAME
+blitspin - rotate a bitmap in an interesting way
+.SH SYNOPSIS
+.B blitspin
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-bitmap \fIfilename\fP] [\-delay \fIusecs\fP] [\-delay2 \fIusecs\fP]
+.SH DESCRIPTION
+The \fIblitspin\fP program repeatedly rotates a bitmap by 90 degrees by
+using logical operations: the bitmap is divided into quadrants, and the
+quadrants are shifted clockwise. Then the same thing is done again with
+progressively smaller quadrants, except that all sub-quadrants of a
+given size are rotated in parallel. So this takes \fBO(16*log2(N))\fP
+blits of size NxN, with the limitation that the image must be square,
+and the size must be a power of 2.
+.SH OPTIONS
+.I blitspin
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-bitmap bitmap-name
+The bitmap to rotate. It need not be square: it will be padded with
+the background color. Default is \fIxlogo64\fP, but \fIescherknot\fP
+is also nice. You really need to run this on a bigger bitmap than
+those shipped with the X distribution to do it justice.
+
+The \fB*bitmapFilePath\fP resource will be searched if the bitmap name
+is not a fully-qualified pathname.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B \-delay microseconds
+How long to delay between steps of the rotation process, in microseconds.
+Default is 500000, one-half second.
+.PP
+.TP 8
+.B \-delay2 microseconds
+How long to delay between each 90-degree rotation, in microseconds.
+Default is 500000, one-half second.
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1992 by Jamie Zawinski. Permission to use, copy, modify,
+distribute, and sell this software and its documentation for any purpose is
+hereby granted without fee, provided that the above copyright notice appear
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation. No representations are made about the
+suitability of this software for any purpose. It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@lucid.com>, 17-aug-92.
+
+Based on SmallTalk code which appeared in the August 1981 issue of Byte
+magazine.
--- /dev/null
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#include "screenhack.h"
+
+#define NBITS 12
+
+#include <X11/bitmaps/stipple>
+#include <X11/bitmaps/cross_weave>
+#include <X11/bitmaps/dimple1>
+#include <X11/bitmaps/dimple3>
+#include <X11/bitmaps/flipped_gray>
+#include <X11/bitmaps/gray1>
+#include <X11/bitmaps/gray3>
+#include <X11/bitmaps/hlines2>
+#include <X11/bitmaps/light_gray>
+#include <X11/bitmaps/root_weave>
+#include <X11/bitmaps/vlines2>
+#include <X11/bitmaps/vlines3>
+
+static Pixmap pixmaps [NBITS];
+static GC gc;
+static int delay;
+static unsigned long fg, bg, pixels [512];
+static int npixels;
+
+static void
+init_greynetic (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ int i;
+ XGCValues gcv;
+ XWindowAttributes xgwa;
+ Colormap cmap;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ cmap = xgwa.colormap;
+ npixels = 0;
+ gcv.foreground= fg= get_pixel_resource("foreground","Foreground", dpy, cmap);
+ gcv.background= bg= get_pixel_resource("background","Background", dpy, cmap);
+ gcv.fill_style= FillOpaqueStippled;
+ gc = XCreateGC (dpy, window, GCForeground|GCBackground|GCFillStyle, &gcv);
+
+ delay = get_integer_resource ("delay", "Integer");
+ if (delay < 0) delay = 0;
+
+ i = 0;
+#define BITS(n,w,h) \
+ pixmaps [i++] = XCreatePixmapFromBitmapData (dpy, window, n, w, h, 1, 0, 1)
+
+ BITS (stipple_bits, stipple_width, stipple_height);
+ BITS (cross_weave_bits, cross_weave_width, cross_weave_height);
+ BITS (dimple1_bits, dimple1_width, dimple1_height);
+ BITS (dimple3_bits, dimple3_width, dimple3_height);
+ BITS (flipped_gray_bits, flipped_gray_width, flipped_gray_height);
+ BITS (gray1_bits, gray1_width, gray1_height);
+ BITS (gray3_bits, gray3_width, gray3_height);
+ BITS (hlines2_bits, hlines2_width, hlines2_height);
+ BITS (light_gray_bits, light_gray_width, light_gray_height);
+ BITS (root_weave_bits, root_weave_width, root_weave_height);
+ BITS (vlines2_bits, vlines2_width, vlines2_height);
+ BITS (vlines3_bits, vlines3_width, vlines3_height);
+}
+
+static void
+greynetic (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ static int tick = 500, xlim, ylim;
+ static Colormap cmap;
+ int x, y, w, h, i;
+ XGCValues gcv;
+ if (tick++ == 500)
+ {
+ XWindowAttributes xgwa;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ tick = 0;
+ xlim = xgwa.width;
+ ylim = xgwa.height;
+ cmap = xgwa.colormap;
+ }
+ for (i = 0; i < 10; i++) /* minimize area, but don't try too hard */
+ {
+ w = 50 + random () % (xlim - 50);
+ h = 50 + random () % (ylim - 50);
+ if (w + h < xlim && w + h < ylim)
+ break;
+ }
+ x = random () % (xlim - w);
+ y = random () % (ylim - h);
+ gcv.stipple = pixmaps [random () % NBITS];
+ if (mono_p)
+ {
+ if (random () % 1)
+ gcv.foreground = fg, gcv.background = bg;
+ else
+ gcv.foreground = bg, gcv.background = fg;
+ }
+ else
+ {
+ XColor fgc, bgc;
+ if (npixels == sizeof (pixels) / sizeof (unsigned long))
+ goto REUSE;
+ fgc.flags = bgc.flags = DoRed|DoGreen|DoBlue;
+ fgc.red = random ();
+ fgc.green = random ();
+ fgc.blue = random ();
+ bgc.red = random ();
+ bgc.green = random ();
+ bgc.blue = random ();
+ if (! XAllocColor (dpy, cmap, &fgc))
+ goto REUSE;
+ pixels [npixels++] = fgc.pixel;
+ gcv.foreground = fgc.pixel;
+ if (! XAllocColor (dpy, cmap, &bgc))
+ goto REUSE;
+ pixels [npixels++] = bgc.pixel;
+ gcv.background = bgc.pixel;
+ goto DONE;
+ REUSE:
+ gcv.foreground = pixels [random () % npixels];
+ gcv.background = pixels [random () % npixels];
+ DONE:
+ ;
+ }
+ XChangeGC (dpy, gc, GCStipple|GCForeground|GCBackground, &gcv);
+ XFillRectangle (dpy, window, gc, x, y, w, h);
+ XSync (dpy, True);
+}
+
+\f
+char *progclass = "Greynetic";
+
+char *defaults [] = {
+ "*background: black",
+ "*foreground: white",
+ "*delay: 0",
+ 0
+};
+
+XrmOptionDescRec options [] = {
+ { "-delay", ".delay", XrmoptionSepArg, 0 }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ init_greynetic (dpy, window);
+ while (1)
+ {
+ greynetic (dpy, window);
+ if (delay) usleep (delay);
+ }
+}
--- /dev/null
+.TH XScreenSaver 1 "13-aug-92" "X Version 11"
+.SH NAME
+greynetic - draw random stippled/color rectangles
+.SH SYNOPSIS
+.B greynetic
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-delay \fIusecs\fP]
+.SH DESCRIPTION
+The \fIgreynetic\fP program draws random rectangles.
+.SH OPTIONS
+.I greynetic
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-delay microseconds
+Slow it down.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1992 by Jamie Zawinski. Permission to use, copy, modify,
+distribute, and sell this software and its documentation for any purpose is
+hereby granted without fee, provided that the above copyright notice appear
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation. No representations are made about the
+suitability of this software for any purpose. It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@lucid.com>, 13-aug-92.
--- /dev/null
+/* xscreensaver, Copyright (c) 1993 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+/* I wanted to lay down new circles with TV:ALU-ADD instead of TV:ALU-XOR,
+ but X doesn't support arithmetic combinations of pixmaps!! What losers.
+ I suppose I could crank out the 2's compliment math by hand, but that's
+ a real drag...
+ */
+
+#include "screenhack.h"
+
+struct circle {
+ int x, y, radius;
+ int increment;
+ int dx, dy;
+};
+
+static struct circle *circles;
+static int count, global_count;
+static Pixmap pixmap, buffer;
+static int width, height, global_inc;
+static int delay;
+static unsigned long fg_pixel, bg_pixel;
+static XColor fgc, bgc;
+static Bool xor_p;
+static GC draw_gc, erase_gc, copy_gc, merge_gc;
+static Bool anim_p;
+static Colormap cmap;
+
+#define min(x,y) ((x)<(y)?(x):(y))
+#define max(x,y) ((x)>(y)?(x):(y))
+
+static void
+init_circles_1 (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ int i;
+ count = (global_count ? global_count
+ : (3 + (random () % max (1, (min (width, height) / 50)))
+ + (random () % max (1, (min (width, height) / 50)))));
+ circles = (struct circle *) malloc (count * sizeof (struct circle));
+ for (i = 0; i < count; i++)
+ {
+ circles [i].x = 10 + random () % (width - 20);
+ circles [i].y = 10 + random () % (height - 20);
+ if (global_inc)
+ circles [i].increment = global_inc;
+ else
+ { /* prefer smaller increments to larger ones */
+ int j = 8;
+ int inc = ((random()%j) + (random()%j) + (random()%j)) - ((j*3)/2);
+ if (inc < 0) inc = -inc + 3;
+ circles [i].increment = inc + 3;
+ }
+ circles [i].radius = random () % circles [i].increment;
+ circles [i].dx = ((random () % 3) - 1) * (1 + random () % 5);
+ circles [i].dy = ((random () % 3) - 1) * (1 + random () % 5);
+ }
+}
+
+static void
+init_circles (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ XGCValues gcv;
+ XWindowAttributes xgwa;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ cmap = xgwa.colormap;
+ global_count = get_integer_resource ("count", "Integer");
+ if (global_count < 0) global_count = 0;
+ global_inc = get_integer_resource ("increment", "Integer");
+ if (global_inc < 0) global_inc = 0;
+ xor_p = get_boolean_resource ("xor", "Boolean");
+/* if (mono_p) */ xor_p = True;
+ anim_p = get_boolean_resource ("animate", "Boolean");
+ delay = get_integer_resource ("delay", "Integer");
+ if (mono_p)
+ {
+ fg_pixel = get_pixel_resource ("foreground","Foreground", dpy, cmap);
+ bg_pixel = get_pixel_resource ("background","Background", dpy, cmap);
+ }
+ else
+ {
+ hsv_to_rgb (0, 0.5, 1.0, &fgc.red, &fgc.green, &fgc.blue);
+ hsv_to_rgb (180, 1.0, 0.7, &bgc.red, &bgc.green, &bgc.blue);
+ XAllocColor (dpy, cmap, &fgc);
+ XAllocColor (dpy, cmap, &bgc);
+ fg_pixel = fgc.pixel;
+ bg_pixel = bgc.pixel;
+ }
+
+ width = max (50, xgwa.width);
+ height = max (50, xgwa.height);
+
+#ifdef DEBUG
+ width/=2; height/=2;
+#endif
+
+ pixmap = XCreatePixmap (dpy, window, width, height, 1);
+ if (xor_p)
+ buffer = XCreatePixmap (dpy, window, width, height, 1);
+ else
+ buffer = 0;
+
+ gcv.foreground = 1;
+ gcv.background = 0;
+ draw_gc = XCreateGC (dpy, pixmap, GCForeground | GCBackground, &gcv);
+ gcv.foreground = 0;
+ erase_gc = XCreateGC (dpy, pixmap, GCForeground, &gcv);
+ gcv.foreground = fg_pixel;
+ gcv.background = bg_pixel;
+ copy_gc = XCreateGC (dpy, window, GCForeground | GCBackground, &gcv);
+
+ if (xor_p)
+ {
+ gcv.foreground = 1;
+ gcv.background = 0;
+ gcv.function = GXxor;
+ merge_gc = XCreateGC (dpy, pixmap,
+ GCForeground | GCBackground | GCFunction, &gcv);
+ }
+ else
+ {
+ gcv.foreground = fg_pixel;
+ gcv.background = bg_pixel;
+ gcv.function = GXcopy;
+ merge_gc = XCreateGC (dpy, window,
+ GCForeground | GCBackground | GCFunction, &gcv);
+ }
+
+ init_circles_1 (dpy, window);
+ XClearWindow (dpy, window);
+ if (buffer) XFillRectangle (dpy, buffer, erase_gc, 0, 0, width, height);
+}
+
+static void
+run_circles (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ int i;
+ static int iterations = 0;
+ static int oiterations = 0;
+ static Bool first_time_p = True;
+ Bool done = False;
+ Bool inhibit_sleep = False;
+ XFillRectangle (dpy, pixmap, erase_gc, 0, 0, width, height);
+ for (i = 0; i < count; i++)
+ {
+ int radius = circles [i].radius;
+ int inc = circles [i].increment;
+ if (! (iterations & 1))
+ ;
+ else if (radius == 0)
+ ;
+ else if (radius < 0)
+ done = True;
+ else
+ {
+ /* Probably there's a simpler way to ask the musical question,
+ "is this square completely enclosed by this circle," but I've
+ forgotten too much trig to know it... (That's not really the
+ right question anyway, but the right question is too hard.) */
+ double x1 = ((double) (-circles [i].x)) / ((double) radius);
+ double y1 = ((double) (-circles [i].y)) / ((double) radius);
+ double x2 = ((double) (width - circles [i].x)) / ((double) radius);
+ double y2 = ((double) (height - circles [i].y)) / ((double) radius);
+ x1 *= x1; x2 *= x2; y1 *= y1; y2 *= y2;
+ if ((x1 + y1) < 1 && (x2 + y2) < 1 && (x1 + y2) < 1 && (x2 + y1) < 1)
+ done = True;
+ }
+ if (radius > 0 &&
+ (xor_p || circles [0].increment < 0))
+ XFillArc (dpy,
+ (xor_p ? pixmap : window),
+ (xor_p ? draw_gc : merge_gc),
+ circles [i].x - radius, circles [i].y - radius,
+ radius * 2, radius * 2, 0, 360*64);
+ circles [i].radius += inc;
+ }
+
+ if (anim_p && !first_time_p)
+ inhibit_sleep = !done;
+
+ if (done)
+ {
+ if (anim_p)
+ {
+ first_time_p = False;
+ for (i = 0; i < count; i++)
+ {
+ circles [i].x += circles [i].dx;
+ circles [i].y += circles [i].dy;
+ circles [i].radius %= circles [i].increment;
+ if (circles [i].x < 0 || circles [i].x >= width)
+ {
+ circles [i].dx = -circles [i].dx;
+ circles [i].x += (2 * circles [i].dx);
+ }
+ if (circles [i].y < 0 || circles [i].y >= height)
+ {
+ circles [i].dy = -circles [i].dy;
+ circles [i].y += (2 * circles [i].dy);
+ }
+ }
+ }
+ else if (circles [0].increment < 0)
+ {
+ free (circles);
+ init_circles_1 (dpy, window);
+ if (! mono_p)
+ {
+ cycle_hue (&fgc, 10);
+ cycle_hue (&bgc, 10);
+ XFreeColors (dpy, cmap, &fgc.pixel, 1, 0);
+ XFreeColors (dpy, cmap, &bgc.pixel, 1, 0);
+ XAllocColor (dpy, cmap, &fgc);
+ XAllocColor (dpy, cmap, &bgc);
+ XSetForeground (dpy, copy_gc, fgc.pixel);
+ XSetBackground (dpy, copy_gc, bgc.pixel);
+ }
+ }
+#if 0
+ else if ((random () % 2) == 0)
+ {
+ iterations = 0; /* ick */
+ for (i = 0; i < count; i++)
+ circles [i].radius %= circles [i].increment;
+ }
+#endif
+ else
+ {
+ oiterations = iterations;
+ for (i = 0; i < count; i++)
+ {
+ circles [i].increment = -circles [i].increment;
+ circles [i].radius += (2 * circles [i].increment);
+ }
+ }
+ }
+
+ if (buffer)
+ XCopyPlane (dpy, pixmap, buffer, merge_gc, 0, 0, width, height, 0, 0, 1);
+ else if (!xor_p)
+ {
+ static int ncolors = 0;
+ static XColor *colors = 0;
+ if (circles [0].increment >= 0)
+ inhibit_sleep = True;
+ else if (done)
+ {
+ int fgh, bgh;
+ double fgs, fgv, bgs, bgv;
+ if (colors)
+ for (i = 0; i < ncolors; i++)
+ XFreeColors (dpy, cmap, &colors [i].pixel, 1, 0);
+
+ rgb_to_hsv (fgc.red, fgc.green, fgc.blue, &fgh, &fgs, &fgv);
+ rgb_to_hsv (bgc.red, bgc.green, bgc.blue, &bgh, &bgs, &bgv);
+ ncolors = oiterations;
+ colors = ((XColor *)
+ (colors
+ ? realloc (colors, sizeof (XColor) * ncolors)
+ : malloc (sizeof (XColor) * ncolors)));
+
+ make_color_ramp (bgh, bgs, bgv, fgh, fgs, fgv, colors, ncolors);
+ for (i = 0; i < ncolors; i++)
+ XAllocColor (dpy, cmap, &colors [i]);
+ XSetForeground (dpy, merge_gc, colors [0].pixel);
+ }
+ else
+ {
+ XSetForeground (dpy, merge_gc, colors [iterations].pixel);
+ }
+ }
+ else
+ XCopyPlane (dpy, pixmap, window, merge_gc, 0, 0, width, height, 0, 0, 1);
+
+ if (buffer && (anim_p
+ ? (done || (first_time_p && (iterations & 1)))
+ : (iterations & 1)))
+ {
+ XCopyPlane (dpy, buffer, window, copy_gc, 0, 0, width, height, 0, 0, 1);
+ XSync (dpy, True);
+ if (anim_p && done)
+ XFillRectangle (dpy, buffer, erase_gc, 0, 0, width, height);
+ }
+#ifdef DEBUG
+ XCopyPlane (dpy, pixmap, window, copy_gc, 0,0,width,height,width,height, 1);
+ if (buffer)
+ XCopyPlane (dpy, buffer, window, copy_gc, 0,0,width,height,0,height, 1);
+ XSync (dpy, True);
+#endif
+
+ if (done)
+ iterations = 0;
+ else
+ iterations++;
+
+ if (delay && !inhibit_sleep) usleep (delay);
+}
+
+\f
+char *progclass = "Halo";
+
+char *defaults [] = {
+ "*background: black",
+ "*foreground: white",
+/* "*xor: false", */
+ "*count: 0",
+ "*delay: 100000",
+ 0
+};
+
+XrmOptionDescRec options [] = {
+ { "-count", ".count", XrmoptionSepArg, 0 },
+ { "-delay", ".delay", XrmoptionSepArg, 0 },
+ { "-animate", ".animate", XrmoptionNoArg, "True" } /* ,
+ { "-xor", ".xor", XrmoptionNoArg, "True" },
+ { "-no-xor", ".xor", XrmoptionNoArg, "False" } */
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ init_circles (dpy, window);
+ while (1)
+ run_circles (dpy, window);
+}
--- /dev/null
+.TH XScreenSaver 1 "7-jul-93" "X Version 11"
+.SH NAME
+halo - draw circular patterns
+.SH SYNOPSIS
+.B halo
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-count \fIint\fP] [\-delay \fIusecs\fP] [\-animate]
+.SH DESCRIPTION
+The \fIhalo\fP program draws cool patterns based on circles.
+.SH OPTIONS
+.I halo
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-count integer
+How many circles to draw. Default 0, meaning random.
+.TP 8
+.B \-delay microseconds
+How much of a delay should be introduced between steps of the animation.
+Default 100000, or about 0.1 second.
+.TP 8
+.B \-animate
+If specified, then the centerpoints of the circles will bounce around.
+Otherwise, the circles will be drawn once, erased, and a new set of
+circles will be drawn.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1993 by Jamie Zawinski. Permission to use, copy, modify,
+distribute, and sell this software and its documentation for any purpose is
+hereby granted without fee, provided that the above copyright notice appear
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation. No representations are made about the
+suitability of this software for any purpose. It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@lucid.com>, 6-jul-93.
--- /dev/null
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#include "screenhack.h"
+#include <math.h>
+#if __STDC__
+#include <values.h>
+#endif
+
+static double sins [360];
+static double coss [360];
+
+static GC draw_gc, erase_gc;
+static unsigned int default_fg_pixel;
+
+static void
+init_helix (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ int i;
+ XGCValues gcv;
+ XWindowAttributes xgwa;
+ Colormap cmap;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ cmap = xgwa.colormap;
+ gcv.foreground = default_fg_pixel =
+ get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+ draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+ gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
+ erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+
+ for (i = 0; i < 360; i++)
+ {
+ sins [i] = sin ((((double) i) / 180.0) * M_PI);
+ coss [i] = cos ((((double) i) / 180.0) * M_PI);
+ }
+}
+
+static int
+gcd (a, b)
+ int a, b;
+{
+ while (b > 0)
+ {
+ int tmp;
+ tmp = a % b;
+ a = b;
+ b = tmp;
+ }
+ return (a < 0 ? -a : a);
+}
+
+static void
+helix (dpy, window,
+ radius1, radius2, d_angle,
+ factor1, factor2, factor3, factor4)
+ Display *dpy;
+ Window window;
+ int radius1, radius2, d_angle;
+ int factor1, factor2, factor3, factor4;
+{
+ XWindowAttributes xgwa;
+ int width, height;
+ int xmid, ymid;
+ int x1, y1, x2, y2, angle, limit;
+ int i;
+
+ XClearWindow (dpy, window);
+ XGetWindowAttributes (dpy, window, &xgwa);
+ width = xgwa.width;
+ height = xgwa.height;
+
+ xmid = width / 2;
+ ymid = height / 2;
+ x1 = xmid;
+ y1 = ymid + radius2;
+ x2 = xmid;
+ y2 = ymid + radius1;
+ angle = 0;
+ limit = 1 + (360 / gcd (360, d_angle));
+
+ for (i = 0; i < limit; i++)
+ {
+ int tmp;
+#define pmod(x,y) (tmp = (x % y), (tmp >= 0 ? tmp : tmp + y))
+ x1 = xmid + (((double) radius1) * sins [pmod ((angle * factor1), 360)]);
+ y1 = ymid + (((double) radius2) * coss [pmod ((angle * factor2), 360)]);
+ XDrawLine (dpy, window, draw_gc, x1, y1, x2, y2);
+ x2 = xmid + (((double) radius2) * sins [pmod ((angle * factor3), 360)]);
+ y2 = ymid + (((double) radius1) * coss [pmod ((angle * factor4), 360)]);
+ XDrawLine (dpy, window, draw_gc, x1, y1, x2, y2);
+ angle += d_angle;
+ XFlush (dpy);
+ }
+}
+
+#define min(a,b) ((a)<(b)?(a):(b))
+
+static void
+random_helix (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ Colormap cmap;
+ int width, height;
+ int radius, radius1, radius2, d_angle, factor1, factor2, factor3, factor4;
+ double divisor;
+ XColor color;
+ int i, got_color = 0;
+ XWindowAttributes xgwa;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ width = xgwa.width;
+ height = xgwa.height;
+ cmap = xgwa.colormap;
+
+ radius = min (width, height) / 2;
+
+ d_angle = 0;
+ factor1 = 2;
+ factor2 = 2;
+ factor3 = 2;
+ factor4 = 2;
+
+ divisor = ((frand (3.0) + 1) * (((random() % 1) * 2) - 1));
+
+ if ((random () & 1) == 0)
+ {
+ radius1 = radius;
+ radius2 = radius / divisor;
+ }
+ else
+ {
+ radius2 = radius;
+ radius1 = radius / divisor;
+ }
+
+ while (gcd (360, d_angle) >= 2)
+ d_angle = random () % 360;
+
+#define random_factor() \
+ (((random() % 7) ? ((random() % 1) + 1) : 3) \
+ * (((random() % 1) * 2) - 1))
+
+ while (gcd (gcd (gcd (factor1, factor2), factor3), factor4) != 1)
+ {
+ factor1 = random_factor ();
+ factor2 = random_factor ();
+ factor3 = random_factor ();
+ factor4 = random_factor ();
+ }
+
+ if (mono_p)
+ XSetForeground (dpy, draw_gc, default_fg_pixel);
+ else
+ {
+ hsv_to_rgb (random () % 360, frand (1.0), frand (0.5) + 0.5,
+ &color.red, &color.green, &color.blue);
+ if (got_color = XAllocColor (dpy, cmap, &color))
+ XSetForeground (dpy, draw_gc, color.pixel);
+ else
+ XSetForeground (dpy, draw_gc, default_fg_pixel);
+ }
+ helix (dpy, window, radius1, radius2, d_angle,
+ factor1, factor2, factor3, factor4);
+
+ XSync (dpy, True);
+ sleep (5);
+
+ for (i = 0; i < height; i++)
+ {
+ int y = (random () % height);
+ XDrawLine (dpy, window, erase_gc, 0, y, width, y);
+ XFlush (dpy);
+ if ((i % 50) == 0)
+ usleep (10000);
+ }
+ XClearWindow (dpy, window);
+ if (got_color) XFreeColors (dpy, cmap, &color.pixel, 1, 0);
+ XSync (dpy, True);
+ sleep (1);
+}
+
+\f
+char *progclass = "Helix";
+
+char *defaults [] = {
+ "*background: black",
+ 0
+};
+
+XrmOptionDescRec options [] = { 0 };
+int options_size = 0;
+
+void
+screenhack (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ init_helix (dpy, window);
+ while (1)
+ random_helix (dpy, window);
+}
--- /dev/null
+.TH XScreenSaver 1 "13-aug-92" "X Version 11"
+.SH NAME
+helix - draw helical string-art patterns
+.SH SYNOPSIS
+.B helix
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono]
+.SH DESCRIPTION
+The \fIhelix\fP program draws interesting patterns composed of line segments
+in random colors.
+.SH OPTIONS
+.I helix
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono
+If on a color display, pretend we're on a monochrome display.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1992 by Jamie Zawinski. Permission to use, copy, modify,
+distribute, and sell this software and its documentation for any purpose is
+hereby granted without fee, provided that the above copyright notice appear
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation. No representations are made about the
+suitability of this software for any purpose. It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@lucid.com>, 13-aug-92.
--- /dev/null
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+/* This file was ported from xlock for use in xscreensaver (and standalone)
+ * by jwz on 12-Aug-92. Original copyright reads:
+ *
+ * hopalong.c - Real Plane Fractals for xlock, the X Window System lockscreen.
+ *
+ * Copyright (c) 1991 by Patrick J. Naughton.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and that
+ * both that copyright notice and this permission notice appear in
+ * supporting documentation.
+ *
+ * This file is provided AS IS with no warranties of any kind. The author
+ * shall have no liability with respect to the infringement of copyrights,
+ * trade secrets or any patents by this file or any part thereof. In no
+ * event will the author be liable for any lost revenue or profits or
+ * other special, indirect and consequential damages.
+ *
+ * Comments and additions should be sent to the author:
+ *
+ * naughton@eng.sun.com
+ *
+ * Patrick J. Naughton
+ * MS 21-14
+ * Sun Laboritories, Inc.
+ * 2550 Garcia Ave
+ * Mountain View, CA 94043
+ *
+ * Revision History:
+ * 29-Oct-90: fix bad (int) cast.
+ * 29-Jul-90: support for multiple screens.
+ * 08-Jul-90: new timing and colors and new algorithm for fractals.
+ * 15-Dec-89: Fix for proper skipping of {White,Black}Pixel() in colors.
+ * 08-Oct-89: Fixed long standing typo bug in RandomInitHop();
+ * Fixed bug in memory allocation in inithop();
+ * Moved seconds() to an extern.
+ * Got rid of the % mod since .mod is slow on a sparc.
+ * 20-Sep-89: Lint.
+ * 31-Aug-88: Forked from xlock.c for modularity.
+ * 23-Mar-88: Coded HOPALONG routines from Scientific American Sept. 86 p. 14.
+ */
+
+#include "screenhack.h"
+#include <math.h>
+
+static GC gc;
+static int batchcount = 1000;
+
+static unsigned int *pixels = 0, fg_pixel, bg_pixel;
+static int npixels;
+static unsigned int delay;
+static int timeout;
+
+typedef struct {
+ int centerx;
+ int centery; /* center of the screen */
+ double a;
+ double b;
+ double c;
+ double i;
+ double j; /* hopalong parameters */
+ int inc;
+ int pix;
+ long startTime;
+} hopstruct;
+
+static hopstruct hop;
+static XPoint *pointBuffer = 0; /* pointer for XDrawPoints */
+
+static void
+inithop(dsp,win)
+ Display *dsp;
+ Window win;
+{
+ double range;
+ XWindowAttributes xgwa;
+ hopstruct *hp = &hop;
+ XGCValues gcv;
+ Colormap cmap;
+ XGetWindowAttributes (dsp, win, &xgwa);
+ cmap = xgwa.colormap;
+
+ if (! pixels)
+ {
+ XColor color;
+ int i = get_integer_resource ("ncolors", "Integer");
+ int shift;
+ if (i <= 2) i = 2, mono_p = True;
+ shift = 360 / i;
+ pixels = (unsigned int *) calloc (i, sizeof (unsigned int));
+ fg_pixel = get_pixel_resource ("foreground", "Foreground", dsp, cmap);
+ bg_pixel = get_pixel_resource ("background", "Background", dsp, cmap);
+ if (! mono_p)
+ {
+ hsv_to_rgb (random () % 360, 1.0, 1.0,
+ &color.red, &color.green, &color.blue);
+ for (npixels = 0; npixels < i; npixels++)
+ {
+ if (! XAllocColor (dsp, cmap, &color))
+ break;
+ pixels[npixels] = color.pixel;
+ cycle_hue (&color, shift);
+ }
+ }
+ timeout = get_integer_resource ("timeout", "Seconds");
+ if (timeout <= 0) timeout = 30;
+ delay = get_integer_resource ("delay", "Usecs");
+
+ gcv.foreground = fg_pixel;
+ gc = XCreateGC (dsp, win, GCForeground, &gcv);
+ }
+
+ XClearWindow (dsp, win);
+
+ hp->centerx = xgwa.width / 2;
+ hp->centery = xgwa.height / 2;
+ range = sqrt((double) hp->centerx * hp->centerx +
+ (double) hp->centery * hp->centery) /
+ (10.0 + random() % 10);
+
+ hp->pix = 0;
+#define frand0() (((double) random()) / ((unsigned int) (~0)))
+ hp->inc = (int) (frand0() * 200) - 100;
+ hp->a = frand0() * range - range / 2.0;
+ hp->b = frand0() * range - range / 2.0;
+ hp->c = frand0() * range - range / 2.0;
+ if (!(random() % 2))
+ hp->c = 0.0;
+
+ hp->i = hp->j = 0.0;
+
+ if (!pointBuffer)
+ pointBuffer = (XPoint *) malloc(batchcount * sizeof(XPoint));
+
+ XSetForeground(dsp, gc, bg_pixel);
+ XFillRectangle(dsp, win, gc, 0, 0,
+ hp->centerx * 2, hp->centery * 2);
+ XSetForeground(dsp, gc, fg_pixel);
+ hp->startTime = time ((time_t *) 0);
+}
+
+
+static void
+drawhop(dsp,win)
+ Display *dsp;
+ Window win;
+{
+ double oldj;
+ int k = batchcount;
+ XPoint *xp = pointBuffer;
+ hopstruct *hp = &hop;
+
+ hp->inc++;
+ if (! mono_p) {
+ XSetForeground(dsp, gc, pixels[hp->pix]);
+ if (++hp->pix >= npixels)
+ hp->pix = 0;
+ }
+ while (k--) {
+ oldj = hp->j;
+ hp->j = hp->a - hp->i;
+ hp->i = oldj + (hp->i < 0
+ ? sqrt(fabs(hp->b * (hp->i + hp->inc) - hp->c))
+ : -sqrt(fabs(hp->b * (hp->i + hp->inc) - hp->c)));
+ xp->x = hp->centerx + (int) (hp->i + hp->j);
+ xp->y = hp->centery - (int) (hp->i - hp->j);
+ xp++;
+ }
+ XDrawPoints(dsp, win, gc,
+ pointBuffer, batchcount, CoordModeOrigin);
+ XSync (dsp, True);
+ if ((time ((time_t *) 0) - hp->startTime) > timeout)
+ {
+ int i;
+ XSetForeground(dsp, gc, bg_pixel);
+ for (i = 0; i < hp->centery; i++)
+ {
+ int y = (random () % (hp->centery << 1));
+ XDrawLine (dsp, win, gc, 0, y, hp->centerx << 1, y);
+ XFlush (dsp);
+ if ((i % 50) == 0)
+ usleep (10000);
+ }
+ XClearWindow (dsp, win);
+ XFlush (dsp);
+ sleep (1);
+ inithop(dsp,win);
+ }
+}
+
+\f
+char *progclass = "Hopalong";
+
+char *defaults [] = {
+ "*background: black",
+ "*foreground: white",
+ "*count: 1000",
+ "*ncolors: 100",
+ "*timeout: 20",
+ "*delay: 0",
+ 0
+};
+
+XrmOptionDescRec options [] = {
+ { "-count", ".count", XrmoptionSepArg, 0 },
+ { "-ncolors", ".ncolors", XrmoptionSepArg, 0 },
+ { "-timeout", ".timeout", XrmoptionSepArg, 0 },
+ { "-delay", ".delay", XrmoptionSepArg, 0 },
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ inithop (dpy, window);
+ while (1)
+ {
+ drawhop (dpy, window);
+ XSync (dpy, True);
+ if (delay) usleep (delay);
+ }
+}
--- /dev/null
+.TH XScreenSaver 1 "13-aug-92" "X Version 11"
+.SH NAME
+hopalong - draw real plane fractals
+.SH SYNOPSIS
+.B hopalong
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-count \fIinteger\fP] [\-ncolors \fIinteger\fP] [\-timeout \fIseconds\fP] [\-delay \fImicroseconds\fP]
+.SH DESCRIPTION
+The \fIhopalong\fP program generates real plane fractals as described in
+the September 1986 issue of Scientific American.
+.SH OPTIONS
+.I hopalong
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-count integer
+How many pixels should be drawn before a color change. Default 1000.
+.TP 8
+.B \-ncolors integer
+How many colors should be used (if possible). Default 100.
+The colors used cycle through the hue, making N stops around
+the color wheel.
+.TP 8
+.B \-timeout seconds
+How many seconds we should generate for before clearing the screen
+and starting over. Default 20.
+.TP 8
+.B \-delay microseconds
+How long we should wait between drawing each pixel. Default 0.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR xlock (1)
+.SH COPYRIGHT
+Copyright \(co 1988-91 by Patrick J. Naughton
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation.
+.SH AUTHOR
+Patrick J. Naughton <naughton@eng.sun.com>, 23-mar-88.
+
+Ability to run standalone or with \fIxscreensaver\fP added by
+Jamie Zawinski <jwz@lucid.com>, 13-aug-92.
--- /dev/null
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * This code derived from TI Explorer Lisp code by Joe Keane, Fritz Mueller,
+ * and Jamie Zawinski.
+ */
+
+#include "screenhack.h"
+#include <math.h>
+
+static Display *dpy;
+static Window window;
+static GC color0, color1, color2, color3, color4, color5, color6, color7;
+static GC black;
+
+static int delay;
+
+static int observer_z;
+static int x_offset, y_offset;
+static int unit_pixels;
+
+struct point_state {
+ int old_x, old_y;
+ int new_x, new_y;
+ Bool same_p;
+};
+
+static void
+move_line (state0, state1, gc)
+ struct point_state *state0, *state1;
+ GC gc;
+{
+ if (state0->same_p && state1->same_p)
+ return;
+ if (mono_p)
+ {
+ XDrawLine (dpy, window, black,
+ state0->old_x, state0->old_y, state1->old_x, state1->old_y);
+ XDrawLine (dpy, window, gc,
+ state0->new_x, state0->new_y, state1->new_x, state1->new_y);
+ }
+ else
+ {
+ XSegment segments [2];
+ segments [0].x1 = state0->old_x; segments [0].y1 = state0->old_y;
+ segments [0].x2 = state1->old_x; segments [0].y2 = state1->old_y;
+ segments [1].x1 = state0->new_x; segments [1].y1 = state0->new_y;
+ segments [1].x2 = state1->new_x; segments [1].y2 = state1->new_y;
+ XDrawSegments (dpy, window, gc, segments, 2);
+ }
+}
+
+static void
+hyper (xy, xz, yz, xw, yw, zw)
+ double xy, xz, yz, xw, yw, zw;
+{
+ double cos_xy = cos (xy), sin_xy = sin (xy);
+ double cos_xz = cos (xz), sin_xz = sin (xz);
+ double cos_yz = cos (yz), sin_yz = sin (yz);
+ double cos_xw = cos (xw), sin_xw = sin (xw);
+ double cos_yw = cos (yw), sin_yw = sin (yw);
+ double cos_zw = cos (zw), sin_zw = sin (zw);
+
+ double ax = 1.0, ay = 0.0, az = 0.0, aw = 0.0;
+ double bx = 0.0, by = 1.0, bz = 0.0, bw = 0.0;
+ double cx = 0.0, cy = 0.0, cz = 1.0, cw = 0.0;
+ double dx = 0.0, dy = 0.0, dz = 0.0, dw = 1.0;
+
+ double _tmp0_, _tmp1_;
+
+ struct point_state points [16];
+ bzero (points, sizeof (points));
+
+#define mmmm (&points[0])
+#define mmmp (&points[1])
+#define mmpm (&points[2])
+#define mmpp (&points[3])
+#define mpmm (&points[4])
+#define mpmp (&points[5])
+#define mppm (&points[6])
+#define mppp (&points[7])
+#define pmmm (&points[8])
+#define pmmp (&points[9])
+#define pmpm (&points[10])
+#define pmpp (&points[11])
+#define ppmm (&points[12])
+#define ppmp (&points[13])
+#define pppm (&points[14])
+#define pppp (&points[15])
+
+ while (1)
+ {
+ double temp_mult;
+
+#define compute(a,b,c,d,point_state) \
+ temp_mult = (unit_pixels / (((a*az) + (b*bz) + (c*cz) + (d*dz) + \
+ (a*aw) + (b*bw) + (c*cw) + (d*dw)) \
+ - observer_z)); \
+ point_state->old_x = point_state->new_x; \
+ point_state->old_y = point_state->new_y; \
+ point_state->new_x = ((((a*ax) + (b*bx) + (c*cx) + (d*dx)) * temp_mult) \
+ + x_offset); \
+ point_state->new_y = ((((a*ay) + (b*by) + (c*cy) + (d*dy)) * temp_mult) \
+ + y_offset); \
+ point_state->same_p = (point_state->old_x == point_state->new_x && \
+ point_state->old_y == point_state->new_y);
+
+ compute (-1, -1, -1, -1, mmmm);
+ compute (-1, -1, -1, 1, mmmp);
+ compute (-1, -1, 1, -1, mmpm);
+ compute (-1, -1, 1, 1, mmpp);
+ compute (-1, 1, -1, -1, mpmm);
+ compute (-1, 1, -1, 1, mpmp);
+ compute (-1, 1, 1, -1, mppm);
+ compute (-1, 1, 1, 1, mppp);
+ compute ( 1, -1, -1, -1, pmmm);
+ compute ( 1, -1, -1, 1, pmmp);
+ compute ( 1, -1, 1, -1, pmpm);
+ compute ( 1, -1, 1, 1, pmpp);
+ compute ( 1, 1, -1, -1, ppmm);
+ compute ( 1, 1, -1, 1, ppmp);
+ compute ( 1, 1, 1, -1, pppm);
+ compute ( 1, 1, 1, 1, pppp);
+
+ move_line (mmmm, mmmp, color0);
+ move_line (mmmm, mmpm, color0);
+ move_line (mmpm, mmpp, color0);
+ move_line (mmmp, mmpp, color0);
+
+ move_line (pmmm, pmmp, color1);
+ move_line (pmmm, pmpm, color1);
+ move_line (pmpm, pmpp, color1);
+ move_line (pmmp, pmpp, color1);
+
+ move_line (mpmm, mpmp, color2);
+ move_line (mpmm, mppm, color2);
+ move_line (mppm, mppp, color2);
+ move_line (mpmp, mppp, color2);
+
+ move_line (mmpp, mppp, color3);
+ move_line (mmpp, pmpp, color3);
+ move_line (pmpp, pppp, color3);
+ move_line (mppp, pppp, color3);
+
+ move_line (mmmm, mpmm, color4);
+ move_line (mmmm, pmmm, color4);
+ move_line (mpmm, ppmm, color4);
+ move_line (pmmm, ppmm, color4);
+
+ move_line (mmmp, mpmp, color5);
+ move_line (mmmp, pmmp, color5);
+ move_line (pmmp, ppmp, color5);
+ move_line (mpmp, ppmp, color5);
+
+ move_line (mmpm, mppm, color6);
+ move_line (mmpm, pmpm, color6);
+ move_line (pmpm, pppm, color6);
+ move_line (mppm, pppm, color6);
+
+ move_line (ppmm, ppmp, color7);
+ move_line (ppmm, pppm, color7);
+ move_line (pppm, pppp, color7);
+ move_line (ppmp, pppp, color7);
+
+ /* If you get error messages about the following forms, and you think you're
+ using an ANSI C conforming compiler, then you're mistaken. Possibly you're
+ mixing an ANSI compiler with a non-ANSI preprocessor, or vice versa.
+ Regardless, your system is broken; it's not a bug in this program.
+ */
+#if __STDC__
+# define rotate(name,dim0,dim1,cos,sin) \
+ _tmp0_ = ((name##dim0 * cos) + (name##dim1 * sin)); \
+ _tmp1_ = ((name##dim1 * cos) - (name##dim0 * sin)); \
+ name##dim0 = _tmp0_; \
+ name##dim1 = _tmp1_;
+
+# define rotates(dim0,dim1) \
+ if (sin_##dim0##dim1 != 0) { \
+ rotate(a, dim0, dim1, cos_##dim0##dim1, sin_##dim0##dim1); \
+ rotate(b, dim0, dim1, cos_##dim0##dim1, sin_##dim0##dim1); \
+ rotate(c, dim0, dim1, cos_##dim0##dim1, sin_##dim0##dim1); \
+ rotate(d, dim0, dim1, cos_##dim0##dim1, sin_##dim0##dim1); \
+ }
+
+#else /* !__STDC__, courtesy of Andreas Luik <luik@isa.de> */
+# define rotate(name,dim0,dim1,cos,sin) \
+ _tmp0_ = ((name/**/dim0 * cos) + (name/**/dim1 * sin)); \
+ _tmp1_ = ((name/**/dim1 * cos) - (name/**/dim0 * sin)); \
+ name/**/dim0 = _tmp0_; \
+ name/**/dim1 = _tmp1_;
+
+# define rotates(dim0,dim1) \
+ if (sin_/**/dim0/**/dim1 != 0) { \
+ rotate(a,dim0,dim1,cos_/**/dim0/**/dim1,sin_/**/dim0/**/dim1); \
+ rotate(b,dim0,dim1,cos_/**/dim0/**/dim1,sin_/**/dim0/**/dim1); \
+ rotate(c,dim0,dim1,cos_/**/dim0/**/dim1,sin_/**/dim0/**/dim1); \
+ rotate(d,dim0,dim1,cos_/**/dim0/**/dim1,sin_/**/dim0/**/dim1); \
+ }
+#endif /* !__STDC__ */
+
+ rotates (x,y);
+ rotates (x,z);
+ rotates (y,z);
+ rotates (x,w);
+ rotates (y,w);
+ rotates (z,w);
+
+ XSync (dpy, True);
+ if (delay) usleep (delay);
+ }
+}
+
+\f
+char *progclass = "Hypercube";
+
+char *defaults [] = {
+ "*background: black",
+ "*foreground: white",
+ "*color0: red",
+ "*color1: orange",
+ "*color2: yellow",
+ "*color3: white",
+ "*color4: green",
+ "*color5: cyan",
+ "*color6: dodgerblue",
+ "*color7: magenta",
+
+ "*xw: 0.000",
+ "*xy: 0.010",
+ "*xz: 0.005",
+ "*yw: 0.010",
+ "*yz: 0.000",
+ "*zw: 0.000",
+
+ "*observer-z: 5",
+ "*delay: 100000",
+ 0
+};
+
+XrmOptionDescRec options [] = {
+ { "-color0", ".color0", XrmoptionSepArg, 0 },
+ { "-color1", ".color1", XrmoptionSepArg, 0 },
+ { "-color2", ".color2", XrmoptionSepArg, 0 },
+ { "-color3", ".color3", XrmoptionSepArg, 0 },
+ { "-color4", ".color4", XrmoptionSepArg, 0 },
+ { "-color5", ".color5", XrmoptionSepArg, 0 },
+ { "-color6", ".color6", XrmoptionSepArg, 0 },
+ { "-color7", ".color7", XrmoptionSepArg, 0 },
+
+ { "-xw", ".xw", XrmoptionSepArg, 0 },
+ { "-xy", ".xy", XrmoptionSepArg, 0 },
+ { "-xz", ".xz", XrmoptionSepArg, 0 },
+ { "-yw", ".yw", XrmoptionSepArg, 0 },
+ { "-yz", ".yz", XrmoptionSepArg, 0 },
+ { "-zw", ".zw", XrmoptionSepArg, 0 },
+
+ { "-observer-z", ".observer-z", XrmoptionSepArg, 0 },
+ { "-delay", ".delay", XrmoptionSepArg, 0 }
+};
+
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+
+void
+screenhack (d, w)
+ Display *d;
+ Window w;
+{
+ XGCValues gcv;
+ XWindowAttributes xgwa;
+ Colormap cmap;
+ double xy, xz, yz, xw, yw, zw;
+ unsigned long bg, pixel;
+
+ dpy = d;
+ window = w;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ cmap = xgwa.colormap;
+
+ x_offset = xgwa.width / 2;
+ y_offset = xgwa.height / 2;
+ unit_pixels = xgwa.width < xgwa.height ? xgwa.width : xgwa.height;
+
+ xy = get_float_resource ("xy", "Float");
+ xz = get_float_resource ("xz", "Float");
+ yz = get_float_resource ("yz", "Float");
+ xw = get_float_resource ("xw", "Float");
+ yw = get_float_resource ("yw", "Float");
+ zw = get_float_resource ("zw", "Float");
+
+ observer_z = get_integer_resource ("observer-z", "Integer");
+
+ delay = get_integer_resource ("delay", "Integer");
+
+ bg = get_pixel_resource ("background", "Background", dpy, cmap);
+
+ if (mono_p)
+ {
+ gcv.function = GXcopy;
+ gcv.foreground = bg;
+ black = XCreateGC (dpy, window, GCForeground|GCFunction, &gcv);
+ gcv.foreground = get_pixel_resource ("foreground", "Foreground",
+ dpy, cmap);
+ color0 = color1 = color2 = color3 = color4 = color5 = color6 = color7 =
+ XCreateGC (dpy, window, GCForeground|GCFunction, &gcv);
+ }
+ else
+ {
+ black = 0;
+ gcv.function = GXxor;
+#define make_gc(color,name) \
+ gcv.foreground = bg ^ get_pixel_resource ((name), "Foreground", \
+ dpy, cmap); \
+ color = XCreateGC (dpy, window, GCForeground|GCFunction, &gcv)
+
+ make_gc (color0,"color0");
+ make_gc (color1,"color1");
+ make_gc (color2,"color2");
+ make_gc (color3,"color3");
+ make_gc (color4,"color4");
+ make_gc (color5,"color5");
+ make_gc (color6,"color6");
+ make_gc (color7,"color7");
+ }
+
+ hyper (xy, xz, yz, xw, yw, zw);
+}
--- /dev/null
+.TH XScreenSaver 1 "6-dec-92" "X Version 11"
+.SH NAME
+hypercube - 2d projection of a 4d object
+.SH SYNOPSIS
+.B hypercube
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-color[0-7] \fIcolor\fP] [\-xy \fIfloat\fP] [\-xz \fIfloat\fP] [\-yz \fIfloat\fP] [\-xw \fIfloat\fP] [\-yw \fIfloat\fP] [\-zw \fIfloat\fP] [\-observer-z \fIint\fP] [\-window] [\-root] [\-mono] [\-delay \fIusecs\fP]
+.SH DESCRIPTION
+The \fIhypercube\fP program displays a wireframe projection of a hypercube
+which is rotating at user-specified rates around any or all of its four axes.
+.SH OPTIONS
+.I hypercube
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-delay microseconds
+How much of a delay should be introduced between steps of the animation.
+Default 100000, or about 1/10th second.
+.TP 8
+.B \-observer-z int
+How far away the observer is from the center of the cube (the cube is one
+unit per side.) Default 5.
+.TP 8
+.B \-color0 color
+.TP 8
+.B \-color1 color
+.TP 8
+.B \-color2 color
+.TP 8
+.B \-color3 color
+.TP 8
+.B \-color4 color
+.TP 8
+.B \-color5 color
+.TP 8
+.B \-color6 color
+.TP 8
+.B \-color7 color
+The colors used to draw the line segments bordering the eight faces of
+the cube. Some of the faces have only two of their border-lines drawn in
+the specified color, and some have all four.
+.TP 8
+.B \-xw float
+.TP 8
+.B \-xy float
+.TP 8
+.B \-xz float
+.TP 8
+.B \-yw float
+.TP 8
+.B \-yz float
+.TP 8
+.B \-zw float
+The amount that the cube should be rotated around the specified axis at
+each frame of the animation, expressed in radians. These should be small
+floating-point values (less than 0.05 works best.) Default: xy=0.01,
+xz=0.005, yw=0.01.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1992 by Jamie Zawinski. Permission to use, copy, modify,
+distribute, and sell this software and its documentation for any purpose is
+hereby granted without fee, provided that the above copyright notice appear
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation. No representations are made about the
+suitability of this software for any purpose. It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@lucid.com>, 6-dec-92.
--- /dev/null
+/* imsmap, Copyright (c) 1992 Juergen Nickelsen <nickel@cs.tu-berlin.de>
+ * Derived from code by Markus Schirmer, TU Berlin.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#include "screenhack.h"
+#include <stdio.h>
+#include <X11/Xutil.h>
+
+#define NSTEPS 7
+#define COUNT (1 << NSTEPS)
+#define CELL(c, r) cell[((unsigned int)(c)) + ((unsigned int) (r)) * xmax]
+
+static enum mode_t { MODE_H, MODE_S, MODE_V, MODE_RANDOM } mode;
+
+static GC gc, gc2;
+static Display *disp;
+static Window wind;
+static XWindowAttributes wattrs;
+
+#if defined(sun) && !__STDC__ /* sun cc doesn't know "signed char" */
+#define signed /**/
+#endif
+
+static unsigned long *pixels = 0, fg_pixel, bg_pixel;
+static int npixels = 0;
+static Colormap cmap;
+static int timeout, cycle_delay;
+static int cycle_p;
+static signed char *cell = NULL;
+static int xmax, ymax;
+static int iterations;
+
+static void
+initwin (dsp, win)
+ Display *dsp;
+ Window win;
+{
+ int fg_h, bg_h;
+ double fg_s, fg_v, bg_s, bg_v;
+
+ enum mode_t this_mode;
+ static Bool rv_p;
+ static int ncolors = 0;
+ int shift;
+ double dshift;
+
+ XGCValues gcv;
+
+ XGetWindowAttributes (dsp, win, &wattrs);
+ cmap = wattrs.colormap;
+
+ if (!ncolors)
+ {
+ char *mode_str = get_string_resource ("mode", "Mode");
+ rv_p = get_boolean_resource ("reverseVideo", "ReverseVideo");
+ cycle_p = get_boolean_resource ("cycle", "Cycle");
+ ncolors = get_integer_resource ("ncolors", "Integer");
+ timeout = get_integer_resource ("timeout", "Integer");
+ cycle_delay = get_integer_resource ("cycleDelay", "Integer");
+ iterations = get_integer_resource ("iterations", "Integer");
+ if (iterations < 0) iterations = 0;
+ else if (iterations > 7) iterations = 7;
+ pixels = (unsigned long *) calloc (ncolors, sizeof (unsigned int));
+ fg_pixel = get_pixel_resource ("background", "Background", dsp, cmap);
+ bg_pixel = get_pixel_resource ("foreground", "Foreground", dsp, cmap);
+
+ if (mono_p && fg_pixel == bg_pixel)
+ bg_pixel = !bg_pixel;
+
+ if (mono_p) cycle_p = False;
+
+ gcv.foreground = fg_pixel;
+ gcv.background = bg_pixel;
+ gc = XCreateGC (dsp, win, GCForeground|GCBackground, &gcv);
+ gcv.foreground = bg_pixel;
+ gc2 = XCreateGC (dsp, win, GCForeground, &gcv);
+
+ if (!mode_str || !strcmp (mode_str, "random"))
+ mode = MODE_RANDOM;
+ else if (!strcmp (mode_str, "h") || !strcmp (mode_str, "hue"))
+ mode = MODE_H;
+ else if (!strcmp (mode_str, "s") || !strcmp (mode_str, "saturation"))
+ mode = MODE_S;
+ else if (!strcmp (mode_str, "v") || !strcmp (mode_str, "value"))
+ mode = MODE_V;
+ else
+ {
+ fprintf (stderr,
+ "%s: mode must be hue, saturation, value, or random, not \"%s\"\n",
+ progname, mode_str);
+ mode = MODE_RANDOM;
+ }
+ }
+ else if (! mono_p)
+ XFreeColors (dsp, cmap, pixels, npixels, 0);
+
+ this_mode = mode;
+ if (!mono_p && mode == MODE_RANDOM)
+ switch (random () % 3) {
+ case 0: this_mode = MODE_H; break;
+ case 1: this_mode = MODE_S; break;
+ case 2: this_mode = MODE_V; break;
+ }
+
+ if (mono_p)
+ {
+ npixels = ncolors;
+ pixels [0] = fg_pixel;
+ pixels [1] = bg_pixel;
+ }
+ else
+ {
+ XColor fg_color, bg_color;
+
+ if (fg_pixel == bg_pixel)
+ {
+ HSV_AGAIN:
+ fg_h = random () % 360;
+ bg_h = random () % 360;
+ fg_s = frand (1.0);
+ bg_s = frand (1.0);
+ V_AGAIN:
+ fg_v = frand (1.0);
+ bg_v = frand (1.0);
+ if ((fg_v - bg_v) > -0.4 && (fg_v - bg_v) < 0.4)
+ goto V_AGAIN;
+ hsv_to_rgb (fg_h, fg_s, fg_v,
+ &fg_color.red, &fg_color.green, &fg_color.blue);
+ hsv_to_rgb (bg_h, bg_s, bg_v,
+ &bg_color.red, &bg_color.green, &bg_color.blue);
+ }
+ else
+ {
+ fg_color.pixel = fg_pixel;
+ if (! XQueryColor (dsp, cmap, &fg_color))
+ abort ();
+ bg_color.pixel = bg_pixel;
+ if (! XQueryColor (dsp, cmap, &bg_color))
+ abort ();
+ }
+ fg_color.flags = DoRed|DoGreen|DoBlue;
+ bg_color.flags = DoRed|DoGreen|DoBlue;
+
+ rgb_to_hsv (fg_color.red, fg_color.green, fg_color.blue,
+ &fg_h, &fg_s, &fg_v);
+ rgb_to_hsv (bg_color.red, bg_color.green, bg_color.blue,
+ &bg_h, &bg_s, &bg_v);
+
+ if (/*mode == MODE_RANDOM &&*/
+ ((this_mode == MODE_S && (fg_s-bg_s) > -0.3 && (fg_s-bg_s) < 0.3) ||
+ (this_mode == MODE_V && (fg_v-bg_v) > -0.3 && (fg_v-bg_v) < 0.3) ||
+ (this_mode == MODE_H && (fg_h-bg_h) > -30 && (fg_h-bg_h) < 30)))
+ goto HSV_AGAIN;
+
+ switch (this_mode) {
+ case MODE_H: shift = (bg_h - fg_h) / ncolors; break;
+ case MODE_S: dshift = (bg_s - fg_s) / ncolors; break;
+ case MODE_V: dshift = (bg_v - fg_v) / ncolors; break;
+ default: abort ();
+ }
+
+ if (mode == MODE_RANDOM &&
+ ((this_mode == MODE_H)
+ ? ((shift > -2 && shift < 2) || fg_s < 0.3 || fg_v < 0.3)
+ : (dshift > -0.005 && dshift < 0.005)))
+ goto HSV_AGAIN;
+
+ if (mode == MODE_RANDOM && this_mode == MODE_S && fg_v < 0.5)
+ goto V_AGAIN;
+
+ for (npixels = 0; npixels < ncolors; npixels++)
+ {
+ if (cycle_p)
+ {
+ unsigned long plane_masks;
+ /* allocate the writable color cells, one at a time. */
+ if (! XAllocColorCells (dsp, cmap, False, &plane_masks, 0,
+ &fg_color.pixel, 1))
+ {
+ fprintf (stderr,
+ "%s: couldn't allocate %s writable color cells. Turning off -cycle.\n",
+ progname, (npixels ? "enough" : "any"));
+ cycle_p = 0;
+ goto NON_CYCLE;
+ }
+ XStoreColor (dsp, cmap, &fg_color);
+ }
+ else
+ {
+ NON_CYCLE:
+ if (!XAllocColor (dsp, cmap, &fg_color))
+ break;
+ }
+ pixels[npixels] = fg_color.pixel;
+
+ switch (this_mode)
+ {
+ case MODE_H: fg_h = (fg_h + shift) % 360; break;
+ case MODE_S: fg_s += dshift; break;
+ case MODE_V: fg_v += dshift; break;
+ default: abort ();
+ }
+ hsv_to_rgb (fg_h, fg_s, fg_v,
+ &fg_color.red, &fg_color.green, &fg_color.blue);
+ }
+ }
+ XSetForeground (dsp, gc, pixels [0]);
+ XFillRectangle (dsp, win, gc, 0, 0, wattrs.width, wattrs.height);
+}
+
+
+#define HEIGHT_TO_PIXEL(height) \
+ (((int) (height)) < 0 ? 0 : \
+ ((int) (height)) >= npixels ? npixels - 3 : ((int) (height)))
+
+static unsigned int
+set (l, c, size, height)
+ unsigned int l, c, size;
+ int height;
+{
+ int rang = 1 << (NSTEPS - size);
+ height = height + (random () % rang) - rang / 2;
+ CELL (l, c) = height;
+
+ return pixels [HEIGHT_TO_PIXEL (height)];
+}
+
+static void
+floyd_steinberg ()
+{
+ int x, y, err;
+
+ /* Instead of repeatedly calling XPutPixel(), we make an Image and then
+ send its bits over all at once. This consumes much less network
+ bandwidth. The image we create is Wx1 intead of WxH, so that we
+ don't use enormous amounts of memory.
+ */
+ XImage *image =
+ XCreateImage (disp, DefaultVisual(disp,DefaultScreen(disp)),
+ 1, XYBitmap, 0, /* depth, format, offset */
+ (char *) calloc ((xmax + 1) / 8, 1), /* data */
+ xmax, 1, 8, 0); /* w, h, pad, bpl */
+
+ for (y = 0; y < ymax - 1; y++)
+ {
+ for (x = 0; x < xmax - 1; x++)
+ {
+ if (CELL(x, y) < 0)
+ {
+ err = CELL (x, y);
+ XPutPixel (image, x, 0, 1);
+ }
+ else
+ {
+ err = CELL (x, y) - 1;
+ XPutPixel (image, x, 0, 0);
+ }
+ /* distribute error */
+ CELL (x, y+1) += (int) (((float) err) * 3.0/8.0);
+ CELL (x+1, y) += (int) (((float) err) * 3.0/8.0);
+ CELL (x+1, y+1) += (int) (((float) err) * 1.0/4.0);
+ }
+ XPutImage (disp, wind, gc, image, 0, 0, 0, y, xmax, 1);
+ }
+ XDestroyImage (image);
+}
+
+static void
+draw (x, y, pixel, grid_size) /* not called in mono mode */
+ int x, y, grid_size;
+ unsigned long pixel;
+{
+ static unsigned int last_pixel, last_valid = 0;
+ if (! (last_valid && pixel == last_pixel))
+ XSetForeground (disp, gc, pixel);
+ last_valid = 1, last_pixel = pixel;
+ if (grid_size == 1)
+ XDrawPoint (disp, wind, gc, x, y);
+ else
+ XFillRectangle (disp, wind, gc, x, y, grid_size, grid_size);
+}
+
+
+static void
+drawmap ()
+{
+ unsigned int x, y, i, step, nextStep, x1, x2, y1, y2;
+ unsigned int pixel, qpixels [4];
+
+ xmax = wattrs.width;
+ ymax = wattrs.height;
+
+ cell = (signed char *) calloc (xmax * ymax, 1);
+ if (cell == NULL)
+ exit (1);
+
+ CELL (0, 0) = 0;
+ step = COUNT;
+ for (i = 0; i < iterations; i++)
+ {
+ nextStep = step / 2;
+ for (x = 0; x < xmax; x += step)
+ {
+ x1 = x + nextStep;
+ if (x1 >= xmax)
+ x1 = 0;
+ x2 = x + step;
+ if (x2 >= xmax)
+ x2 = 0;
+ for (y = 0; y < ymax; y += step)
+ {
+ y1 = y + nextStep;
+ if (y1 >= ymax)
+ y1 = 0;
+ y2 = y + step;
+ if (y2 >= ymax)
+ y2 = 0;
+
+ qpixels [0] = pixels [HEIGHT_TO_PIXEL (CELL (x, y))];
+ qpixels [1] = pixels [HEIGHT_TO_PIXEL (CELL (x, y2))];
+ qpixels [2] = pixels [HEIGHT_TO_PIXEL (CELL (x2, y))];
+ qpixels [3] = pixels [HEIGHT_TO_PIXEL (CELL (x2, y2))];
+
+ pixel = set (x, y1, i,
+ ((int) CELL (x, y) + (int) CELL (x, y2) + 1) / 2);
+ if (! mono_p &&
+ (pixel != qpixels[0] || pixel != qpixels[1] ||
+ pixel != qpixels[2] || pixel != qpixels[3]))
+ draw (x, y1, pixel, nextStep);
+
+ pixel = set (x1, y, i,
+ ((int) CELL (x, y) + (int) CELL (x2, y) + 1) / 2);
+ if (! mono_p &&
+ (pixel != qpixels[0] || pixel != qpixels[1] ||
+ pixel != qpixels[2] || pixel != qpixels[3]))
+ draw (x1, y, pixel, nextStep);
+
+ pixel = set (x1, y1, i,
+ ((int) CELL (x, y) + (int) CELL (x, y2) +
+ (int) CELL (x2, y) + (int) CELL (x2, y2) + 2)
+ / 4);
+ if (! mono_p &&
+ (pixel != qpixels[0] || pixel != qpixels[1] ||
+ pixel != qpixels[2] || pixel != qpixels[3]))
+ draw (x1, y1, pixel, nextStep);
+ }
+ }
+ step = nextStep;
+ if (!mono_p)
+ XSync (disp, True);
+ }
+ if (mono_p)
+ /* in mono-mode, we do all the drawing at the end */
+ floyd_steinberg ();
+
+ free (cell);
+ XSync (disp, True);
+}
+
+static void
+cycle (dpy)
+ Display *dpy;
+{
+ XColor *colors = malloc (npixels * sizeof (XColor));
+ time_t stop;
+ int i;
+ for (i = 0; i < npixels; i++)
+ colors [i].pixel = pixels [i];
+ XQueryColors (dpy, cmap, colors, npixels);
+ stop = (time_t) ((time ((time_t) 0)) + timeout);
+ while (stop >= (time_t) time ((time_t) 0))
+ {
+ unsigned long scratch = colors [npixels-1].pixel;
+ for (i = npixels-1; i > 0; i--)
+ colors [i].pixel = colors [i-1].pixel;
+ colors [0].pixel = scratch;
+ XStoreColors (dpy, cmap, colors, npixels);
+ XSync (dpy, True);
+ if (cycle_delay) usleep (cycle_delay);
+ }
+ XSync (dpy, True);
+ free (colors);
+}
+
+
+char *progclass = "Imsmap";
+
+char *defaults [] = {
+ "*background: black",
+ "*foreground: black",
+ "*mode: random",
+ "*ncolors: 50",
+ "*iterations: 7",
+ "*timeout: 10",
+ "*cycleDelay: 100000",
+ "*cycle: true",
+ 0
+};
+
+XrmOptionDescRec options [] = {
+ { "-ncolors", ".ncolors", XrmoptionSepArg, 0 },
+ { "-timeout", ".timeout", XrmoptionSepArg, 0 },
+ { "-cycle-delay", ".cycleDelay", XrmoptionSepArg, 0 },
+ { "-mode", ".mode", XrmoptionSepArg, 0 },
+ { "-iterations", ".iterations", XrmoptionSepArg, 0 },
+ { "-cycle", ".cycle", XrmoptionNoArg, "True" },
+ { "-no-cycle", ".cycle", XrmoptionNoArg, "False" }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+
+void
+screenhack (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ disp = dpy;
+ wind = window;
+ while (1)
+ {
+ initwin (dpy, window);
+ drawmap ();
+ if (timeout)
+ {
+ if (cycle_p)
+ cycle (dpy);
+ else
+ sleep (timeout);
+ }
+ }
+}
--- /dev/null
+.TH XScreenSaver 1 "26-apr-93" "X Version 11"
+.SH NAME
+imsmap - generate fractal maps
+.SH SYNOPSIS
+.B imsmap
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-ncolors \fIint\fP] [\-timeout \fIseconds\fP] [\-iterations \fIint\fP] [\-mode h|s|v|random] [\-cycle] [\-no\-cycle]
+.SH DESCRIPTION
+The \fIimsmap\fP program generates map or cloud-like patterns. It looks
+quite different in monochrome and color.
+.SH OPTIONS
+.I imsmap
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-ncolors integer
+How many colors to use. Default 50.
+.TP 8
+.B \-timeout integer
+How long to delay between images. Default 10 seconds.
+.TP 8
+.B \-iterations integer
+A measure of the resolution of the resultant image, from 0 to 7. Default 7.
+.TP 8
+.B \-mode hue|saturation|value|random
+The axis upon which colors should be interpolated between the foreground
+and background color. Default random.
+.TP 8
+.B \-cycle
+Whether to do colormap cycling. This is the default.
+.TP 8
+.B \-no\-cycle
+Turns \fI\-cycle\fP off.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH AUTHOR
+Juergen Nickelsen <nickel@cs.tu-berlin.de>, 23-aug-92.
+
+Hacked on by Jamie Zawinski <jwz@lucid.com>, 24-aug-92.
--- /dev/null
+/******************************************************************************
+ * [ maze ] ...
+ *
+ * modified: [ 3-7-93 ] Jamie Zawinski <jwz@lucid.com>
+ * added the XRoger logo, cleaned up resources, made
+ * grid size a parameter.
+ * modified: [ 3-3-93 ] Jim Randell <jmr@mddjmr.fc.hp.com>
+ * Added the colour stuff and integrated it with jwz's
+ * screenhack stuff. There's still some work that could
+ * be done on this, particularly allowing a resource to
+ * specify how big the squares are.
+ * modified: [ 10-4-88 ] Richard Hess ...!uunet!cimshop!rhess
+ * [ Revised primary execution loop within main()...
+ * [ Extended X event handler, check_events()...
+ * modified: [ 1-29-88 ] Dave Lemke lemke@sun.com
+ * [ Hacked for X11...
+ * [ Note the word "hacked" -- this is extremely ugly, but at
+ * [ least it does the job. NOT a good programming example
+ * [ for X.
+ * original: [ 6/21/85 ] Martin Weiss Sun Microsystems [ SunView ]
+ *
+ ******************************************************************************
+ Copyright 1988 by Sun Microsystems, Inc. Mountain View, CA.
+
+ All Rights Reserved
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose and without fee is hereby granted,
+ provided that the above copyright notice appear in all copies and that
+ both that copyright notice and this permission notice appear in
+ supporting documentation, and that the names of Sun or MIT not be
+ used in advertising or publicity pertaining to distribution of the
+ software without specific prior written permission. Sun and M.I.T.
+ make no representations about the suitability of this software for
+ any purpose. It is provided "as is" without any express or implied warranty.
+
+ SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE. IN NO EVENT SHALL SUN BE LIABLE FOR ANY SPECIAL, INDIRECT
+ OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+ OR PERFORMANCE OF THIS SOFTWARE.
+ *****************************************************************************/
+
+#include "screenhack.h"
+
+#define XROGER
+
+static int solve_delay, pre_solve_delay, post_solve_delay;
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/bitmaps/gray1>
+
+#define MAX_MAZE_SIZE_X 500
+#define MAX_MAZE_SIZE_Y 500
+
+#define MOVE_LIST_SIZE (MAX_MAZE_SIZE_X * MAX_MAZE_SIZE_Y)
+
+#define WALL_TOP 0x8000
+#define WALL_RIGHT 0x4000
+#define WALL_BOTTOM 0x2000
+#define WALL_LEFT 0x1000
+
+#define DOOR_IN_TOP 0x800
+#define DOOR_IN_RIGHT 0x400
+#define DOOR_IN_BOTTOM 0x200
+#define DOOR_IN_LEFT 0x100
+#define DOOR_IN_ANY 0xF00
+
+#define DOOR_OUT_TOP 0x80
+#define DOOR_OUT_RIGHT 0x40
+#define DOOR_OUT_BOTTOM 0x20
+#define DOOR_OUT_LEFT 0x10
+
+#define START_SQUARE 0x2
+#define END_SQUARE 0x1
+
+#define border_x (0)
+#define border_y (0)
+
+#define get_random(x) (random() % (x))
+
+static int logo_x, logo_y;
+
+#ifdef XROGER
+# define logo_width 128
+# define logo_height 128
+#else
+# include <X11/bitmaps/xlogo64>
+# define logo_width xlogo64_width
+# define logo_height xlogo64_height
+# define logo_bits xlogo64_bits
+#endif
+
+static unsigned short maze[MAX_MAZE_SIZE_X][MAX_MAZE_SIZE_Y];
+
+static struct {
+ unsigned char x;
+ unsigned char y;
+ unsigned char dir;
+} move_list[MOVE_LIST_SIZE], save_path[MOVE_LIST_SIZE], path[MOVE_LIST_SIZE];
+
+static int maze_size_x, maze_size_y;
+static int sqnum, cur_sq_x, cur_sq_y, path_length;
+static int start_x, start_y, start_dir, end_x, end_y, end_dir;
+static int maze_restart_flag, random_index;
+static int grid_width, grid_height;
+
+static Display *dpy;
+static Window win;
+static GC gc, cgc, tgc, logo_gc;
+static Pixmap logo_map;
+
+static int x = 0, y = 0, restart = 0, stop = 1, state = 1;
+
+check_events() /* X event handler [ rhess ] */
+{
+ XEvent e;
+
+ if (XPending(dpy)) {
+ XNextEvent(dpy, &e);
+ switch (e.type) {
+
+ case ButtonPress:
+ switch (e.xbutton.button) {
+ case 3:
+ exit (0);
+ break;
+ case 2:
+ stop = !stop ;
+ if (state == 5) state = 4 ;
+ else {
+ restart = 1;
+ stop = 0;
+ }
+ break;
+ default:
+ restart = 1 ;
+ stop = 0 ;
+ break;
+ }
+ break;
+
+ case ConfigureNotify:
+ restart = 1;
+ break;
+ case UnmapNotify:
+ stop = 1;
+ XClearWindow (dpy, win);
+ XSync (dpy, False);
+ break;
+ case Expose:
+ restart = 1;
+ break;
+ }
+ return(1);
+ }
+ return(0);
+}
+
+
+set_maze_sizes (width, height)
+ int width, height;
+{
+ maze_size_x = width / grid_width;
+ maze_size_y = height / grid_height;
+}
+
+
+initialize_maze() /* draw the surrounding wall and start/end squares */
+{
+ register int i, j, wall;
+
+ /* initialize all squares */
+ for ( i=0; i<maze_size_x; i++) {
+ for ( j=0; j<maze_size_y; j++) {
+ maze[i][j] = 0;
+ }
+ }
+
+ /* top wall */
+ for ( i=0; i<maze_size_x; i++ ) {
+ maze[i][0] |= WALL_TOP;
+ }
+
+ /* right wall */
+ for ( j=0; j<maze_size_y; j++ ) {
+ maze[maze_size_x-1][j] |= WALL_RIGHT;
+ }
+
+ /* bottom wall */
+ for ( i=0; i<maze_size_x; i++ ) {
+ maze[i][maze_size_y-1] |= WALL_BOTTOM;
+ }
+
+ /* left wall */
+ for ( j=0; j<maze_size_y; j++ ) {
+ maze[0][j] |= WALL_LEFT;
+ }
+
+ /* set start square */
+ wall = get_random(4);
+ switch (wall) {
+ case 0:
+ i = get_random(maze_size_x);
+ j = 0;
+ break;
+ case 1:
+ i = maze_size_x - 1;
+ j = get_random(maze_size_y);
+ break;
+ case 2:
+ i = get_random(maze_size_x);
+ j = maze_size_y - 1;
+ break;
+ case 3:
+ i = 0;
+ j = get_random(maze_size_y);
+ break;
+ }
+ maze[i][j] |= START_SQUARE;
+ maze[i][j] |= ( DOOR_IN_TOP >> wall );
+ maze[i][j] &= ~( WALL_TOP >> wall );
+ cur_sq_x = i;
+ cur_sq_y = j;
+ start_x = i;
+ start_y = j;
+ start_dir = wall;
+ sqnum = 0;
+
+ /* set end square */
+ wall = (wall + 2)%4;
+ switch (wall) {
+ case 0:
+ i = get_random(maze_size_x);
+ j = 0;
+ break;
+ case 1:
+ i = maze_size_x - 1;
+ j = get_random(maze_size_y);
+ break;
+ case 2:
+ i = get_random(maze_size_x);
+ j = maze_size_y - 1;
+ break;
+ case 3:
+ i = 0;
+ j = get_random(maze_size_y);
+ break;
+ }
+ maze[i][j] |= END_SQUARE;
+ maze[i][j] |= ( DOOR_OUT_TOP >> wall );
+ maze[i][j] &= ~( WALL_TOP >> wall );
+ end_x = i;
+ end_y = j;
+ end_dir = wall;
+
+ /* set logo */
+ if ((maze_size_x > 15) && (maze_size_y > 15))
+ {
+ int logow = 1 + logo_width / grid_width;
+ int logoh = 1 + logo_height / grid_height;
+ /* not closer than 3 grid units from a wall */
+ logo_x = get_random (maze_size_x - logow - 6) + 3;
+ logo_y = get_random (maze_size_y - logoh - 6) + 3;
+ for (i=0; i<logow; i++)
+ for (j=0; j<logoh; j++)
+ maze[logo_x + i][logo_y + j] |= DOOR_IN_TOP;
+ }
+ else
+ logo_y = logo_x = -1;
+}
+
+static int choose_door ();
+static int backup ();
+static void draw_wall ();
+static void draw_solid_square ();
+static void enter_square ();
+
+create_maze() /* create a maze layout given the intiialized maze */
+{
+ register int i, newdoor;
+
+ do {
+ move_list[sqnum].x = cur_sq_x;
+ move_list[sqnum].y = cur_sq_y;
+ move_list[sqnum].dir = newdoor;
+ while ( ( newdoor = choose_door() ) == -1 ) { /* pick a door */
+ if ( backup() == -1 ) { /* no more doors ... backup */
+ return; /* done ... return */
+ }
+ }
+
+ /* mark the out door */
+ maze[cur_sq_x][cur_sq_y] |= ( DOOR_OUT_TOP >> newdoor );
+
+ switch (newdoor) {
+ case 0: cur_sq_y--;
+ break;
+ case 1: cur_sq_x++;
+ break;
+ case 2: cur_sq_y++;
+ break;
+ case 3: cur_sq_x--;
+ break;
+ }
+ sqnum++;
+
+ /* mark the in door */
+ maze[cur_sq_x][cur_sq_y] |= ( DOOR_IN_TOP >> ((newdoor+2)%4) );
+
+ /* if end square set path length and save path */
+ if ( maze[cur_sq_x][cur_sq_y] & END_SQUARE ) {
+ path_length = sqnum;
+ for ( i=0; i<path_length; i++) {
+ save_path[i].x = move_list[i].x;
+ save_path[i].y = move_list[i].y;
+ save_path[i].dir = move_list[i].dir;
+ }
+ }
+
+ } while (1);
+
+}
+
+
+static int
+choose_door() /* pick a new path */
+{
+ int candidates[3];
+ register int num_candidates;
+
+ num_candidates = 0;
+
+ topwall:
+ /* top wall */
+ if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_TOP )
+ goto rightwall;
+ if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_TOP )
+ goto rightwall;
+ if ( maze[cur_sq_x][cur_sq_y] & WALL_TOP )
+ goto rightwall;
+ if ( maze[cur_sq_x][cur_sq_y - 1] & DOOR_IN_ANY ) {
+ maze[cur_sq_x][cur_sq_y] |= WALL_TOP;
+ maze[cur_sq_x][cur_sq_y - 1] |= WALL_BOTTOM;
+ draw_wall(cur_sq_x, cur_sq_y, 0);
+ goto rightwall;
+ }
+ candidates[num_candidates++] = 0;
+
+ rightwall:
+ /* right wall */
+ if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_RIGHT )
+ goto bottomwall;
+ if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_RIGHT )
+ goto bottomwall;
+ if ( maze[cur_sq_x][cur_sq_y] & WALL_RIGHT )
+ goto bottomwall;
+ if ( maze[cur_sq_x + 1][cur_sq_y] & DOOR_IN_ANY ) {
+ maze[cur_sq_x][cur_sq_y] |= WALL_RIGHT;
+ maze[cur_sq_x + 1][cur_sq_y] |= WALL_LEFT;
+ draw_wall(cur_sq_x, cur_sq_y, 1);
+ goto bottomwall;
+ }
+ candidates[num_candidates++] = 1;
+
+ bottomwall:
+ /* bottom wall */
+ if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_BOTTOM )
+ goto leftwall;
+ if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_BOTTOM )
+ goto leftwall;
+ if ( maze[cur_sq_x][cur_sq_y] & WALL_BOTTOM )
+ goto leftwall;
+ if ( maze[cur_sq_x][cur_sq_y + 1] & DOOR_IN_ANY ) {
+ maze[cur_sq_x][cur_sq_y] |= WALL_BOTTOM;
+ maze[cur_sq_x][cur_sq_y + 1] |= WALL_TOP;
+ draw_wall(cur_sq_x, cur_sq_y, 2);
+ goto leftwall;
+ }
+ candidates[num_candidates++] = 2;
+
+ leftwall:
+ /* left wall */
+ if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_LEFT )
+ goto donewall;
+ if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_LEFT )
+ goto donewall;
+ if ( maze[cur_sq_x][cur_sq_y] & WALL_LEFT )
+ goto donewall;
+ if ( maze[cur_sq_x - 1][cur_sq_y] & DOOR_IN_ANY ) {
+ maze[cur_sq_x][cur_sq_y] |= WALL_LEFT;
+ maze[cur_sq_x - 1][cur_sq_y] |= WALL_RIGHT;
+ draw_wall(cur_sq_x, cur_sq_y, 3);
+ goto donewall;
+ }
+ candidates[num_candidates++] = 3;
+
+ donewall:
+ if (num_candidates == 0)
+ return ( -1 );
+ if (num_candidates == 1)
+ return ( candidates[0] );
+ return ( candidates[ get_random(num_candidates) ] );
+
+}
+
+
+static int
+backup() /* back up a move */
+{
+ sqnum--;
+ cur_sq_x = move_list[sqnum].x;
+ cur_sq_y = move_list[sqnum].y;
+ return ( sqnum );
+}
+
+
+draw_maze_border() /* draw the maze outline */
+{
+ register int i, j;
+
+
+ for ( i=0; i<maze_size_x; i++) {
+ if ( maze[i][0] & WALL_TOP ) {
+ XDrawLine(dpy, win, gc,
+ border_x + grid_width * i,
+ border_y,
+ border_x + grid_width * (i+1) - 1,
+ border_y);
+ }
+ if ((maze[i][maze_size_y - 1] & WALL_BOTTOM)) {
+ XDrawLine(dpy, win, gc,
+ border_x + grid_width * i,
+ border_y + grid_height * (maze_size_y) - 1,
+ border_x + grid_width * (i+1) - 1,
+ border_y + grid_height * (maze_size_y) - 1);
+ }
+ }
+ for ( j=0; j<maze_size_y; j++) {
+ if ( maze[maze_size_x - 1][j] & WALL_RIGHT ) {
+ XDrawLine(dpy, win, gc,
+ border_x + grid_width * maze_size_x - 1,
+ border_y + grid_height * j,
+ border_x + grid_width * maze_size_x - 1,
+ border_y + grid_height * (j+1) - 1);
+ }
+ if ( maze[0][j] & WALL_LEFT ) {
+ XDrawLine(dpy, win, gc,
+ border_x,
+ border_y + grid_height * j,
+ border_x,
+ border_y + grid_height * (j+1) - 1);
+ }
+ }
+
+ if (logo_x != -1)
+ {
+ Window r;
+ int x, y;
+ unsigned int w, h, bw, d;
+ XGetGeometry (dpy, logo_map, &r, &x, &y, &w, &h, &bw, &d);
+ XCopyPlane (dpy, logo_map, win, logo_gc,
+ 0, 0, w, h,
+ border_x + 3 + grid_width * logo_x,
+ border_y + 3 + grid_height * logo_y, 1);
+ }
+ draw_solid_square (start_x, start_y, start_dir, tgc);
+ draw_solid_square (end_x, end_y, end_dir, tgc);
+}
+
+
+static void
+draw_wall(i, j, dir) /* draw a single wall */
+ int i, j, dir;
+{
+ switch (dir) {
+ case 0:
+ XDrawLine(dpy, win, gc,
+ border_x + grid_width * i,
+ border_y + grid_height * j,
+ border_x + grid_width * (i+1),
+ border_y + grid_height * j);
+ break;
+ case 1:
+ XDrawLine(dpy, win, gc,
+ border_x + grid_width * (i+1),
+ border_y + grid_height * j,
+ border_x + grid_width * (i+1),
+ border_y + grid_height * (j+1));
+ break;
+ case 2:
+ XDrawLine(dpy, win, gc,
+ border_x + grid_width * i,
+ border_y + grid_height * (j+1),
+ border_x + grid_width * (i+1),
+ border_y + grid_height * (j+1));
+ break;
+ case 3:
+ XDrawLine(dpy, win, gc,
+ border_x + grid_width * i,
+ border_y + grid_height * j,
+ border_x + grid_width * i,
+ border_y + grid_height * (j+1));
+ break;
+ }
+}
+
+int bw;
+
+static void
+draw_solid_square(i, j, dir, gc) /* draw a solid square in a square */
+ register int i, j, dir;
+ GC gc;
+{
+ switch (dir) {
+ case 0: XFillRectangle(dpy, win, gc,
+ border_x + bw + grid_width * i,
+ border_y - bw + grid_height * j,
+ grid_width - (bw+bw), grid_height);
+ break;
+ case 1: XFillRectangle(dpy, win, gc,
+ border_x + bw + grid_width * i,
+ border_y + bw + grid_height * j,
+ grid_width, grid_height - (bw+bw));
+ break;
+ case 2: XFillRectangle(dpy, win, gc,
+ border_x + bw + grid_width * i,
+ border_y + bw + grid_height * j,
+ grid_width - (bw+bw), grid_height);
+ break;
+ case 3: XFillRectangle(dpy, win, gc,
+ border_x - bw + grid_width * i,
+ border_y + bw + grid_height * j,
+ grid_width, grid_height - (bw+bw));
+ break;
+ }
+ XSync (dpy, False);
+}
+
+
+solve_maze() /* solve it with graphical feedback */
+{
+ int i;
+
+
+ /* plug up the surrounding wall */
+ maze[start_x][start_y] |= (WALL_TOP >> start_dir);
+ maze[end_x][end_y] |= (WALL_TOP >> end_dir);
+
+ /* initialize search path */
+ i = 0;
+ path[i].x = end_x;
+ path[i].y = end_y;
+ path[i].dir = -1;
+
+ /* do it */
+ while (1) {
+ if ( ++path[i].dir >= 4 ) {
+ i--;
+ draw_solid_square( (int)(path[i].x), (int)(path[i].y),
+ (int)(path[i].dir), cgc);
+ }
+ else if ( ! (maze[path[i].x][path[i].y] &
+ (WALL_TOP >> path[i].dir)) &&
+ ( (i == 0) || ( (path[i].dir !=
+ (int)(path[i-1].dir+2)%4) ) ) ) {
+ enter_square(i);
+ i++;
+ if ( maze[path[i].x][path[i].y] & START_SQUARE ) {
+ return;
+ }
+ }
+ if (check_events()) return;
+ /* Abort solve on expose - cheapo repaint strategy */
+ if (solve_delay) usleep (solve_delay);
+ }
+}
+
+
+static void
+enter_square(n) /* move into a neighboring square */
+ int n;
+{
+ draw_solid_square( (int)path[n].x, (int)path[n].y,
+ (int)path[n].dir, tgc);
+
+ path[n+1].dir = -1;
+ switch (path[n].dir) {
+ case 0: path[n+1].x = path[n].x;
+ path[n+1].y = path[n].y - 1;
+ break;
+ case 1: path[n+1].x = path[n].x + 1;
+ path[n+1].y = path[n].y;
+ break;
+ case 2: path[n+1].x = path[n].x;
+ path[n+1].y = path[n].y + 1;
+ break;
+ case 3: path[n+1].x = path[n].x - 1;
+ path[n+1].y = path[n].y;
+ break;
+ }
+}
+
+/* ----<eof> */
+
+
+/*
+ * jmr additions for Jamie Zawinski's <jwz@lucid.com> screensaver stuff,
+ * note that the code above this has probably been hacked about in some
+ * arbitrary way.
+ */
+
+char *progclass = "Maze";
+
+char *defaults[] = {
+ "*gridSize: 0",
+ "*background: black",
+ "*solveDelay: 5000",
+ "*preDelay: 2000000",
+ "*postDelay: 4000000",
+ "*liveColor: green",
+ "*deadColor: red",
+#ifdef XROGER
+ "*logoColor: red3",
+#endif
+ 0
+};
+
+XrmOptionDescRec options[] = {
+ { "-grid-size", ".gridSize", XrmoptionSepArg, 0 },
+ { "-solve-delay", ".solveDelay", XrmoptionSepArg, 0 },
+ { "-pre-delay", ".preDelay", XrmoptionSepArg, 0 },
+ { "-post-delay", ".postDelay", XrmoptionSepArg, 0 },
+ { "-live-color", ".liveColor", XrmoptionSepArg, 0 },
+ { "-dead-color", ".deadColor", XrmoptionSepArg, 0 }
+};
+
+int options_size = (sizeof(options)/sizeof(options[0]));
+
+void screenhack(display,window)
+ Display *display;
+ Window window;
+{
+ Pixmap gray;
+ int size, root;
+ XWindowAttributes xgwa;
+ unsigned long bg, fg, pfg, pbg, lfg;
+
+ size = get_integer_resource ("gridSize", "Dimension");
+ root = get_boolean_resource("root", "Boolean");
+ solve_delay = get_integer_resource ("solveDelay", "Integer");
+ pre_solve_delay = get_integer_resource ("preDelay", "Integer");
+ post_solve_delay = get_integer_resource ("postDelay", "Integer");
+
+ if (size < 2) size = 7 + (random () % 30);
+ grid_width = grid_height = size;
+ bw = (size > 6 ? 3 : (size-1)/2);
+
+ dpy = display; win = window; /* the maze stuff uses global variables */
+
+ XGetWindowAttributes (dpy, win, &xgwa);
+
+ x = 0;
+ y = 0;
+
+ set_maze_sizes (xgwa.width, xgwa.height);
+
+ if (! root)
+ XSelectInput (dpy, win, ExposureMask|ButtonPressMask|StructureNotifyMask);
+
+ gc = XCreateGC(dpy, win, 0, 0);
+ cgc = XCreateGC(dpy, win, 0, 0);
+ tgc = XCreateGC(dpy,win,0,0);
+ logo_gc = XCreateGC(dpy, win, 0, 0);
+
+ gray = XCreateBitmapFromData (dpy,win,gray1_bits,gray1_width,gray1_height);
+
+ bg = get_pixel_resource ("background","Background", dpy, xgwa.colormap);
+ fg = get_pixel_resource ("foreground","Foreground", dpy, xgwa.colormap);
+ lfg = get_pixel_resource ("logoColor", "Foreground", dpy, xgwa.colormap);
+ pfg = get_pixel_resource ("liveColor", "Foreground", dpy, xgwa.colormap);
+ pbg = get_pixel_resource ("deadColor", "Foreground", dpy, xgwa.colormap);
+ if (mono_p) lfg = pfg = fg;
+
+ if (lfg == bg)
+ lfg = ((bg == WhitePixel (dpy, DefaultScreen (dpy)))
+ ? BlackPixel (dpy, DefaultScreen (dpy))
+ : WhitePixel (dpy, DefaultScreen (dpy)));
+
+ XSetForeground (dpy, gc, fg);
+ XSetBackground (dpy, gc, bg);
+ XSetForeground (dpy, cgc, pbg);
+ XSetBackground (dpy, cgc, bg);
+ XSetForeground (dpy, tgc, pfg);
+ XSetBackground (dpy, tgc, bg);
+ XSetForeground (dpy, logo_gc, lfg);
+ XSetBackground (dpy, logo_gc, bg);
+
+ XSetStipple (dpy, cgc, gray);
+ XSetFillStyle (dpy, cgc, FillOpaqueStippled);
+
+#ifdef XROGER
+ {
+ int w, h;
+ XGCValues gcv;
+ GC draw_gc, erase_gc;
+ extern void skull ();
+ /* round up to grid size */
+ w = ((logo_width / grid_width) + 1) * grid_width;
+ h = ((logo_height / grid_height) + 1) * grid_height;
+ logo_map = XCreatePixmap (dpy, win, w, h, 1);
+ gcv.foreground = 1L;
+ draw_gc = XCreateGC (dpy, logo_map, GCForeground, &gcv);
+ gcv.foreground = 0L;
+ erase_gc= XCreateGC (dpy, logo_map, GCForeground, &gcv);
+ XFillRectangle (dpy, logo_map, erase_gc, 0, 0, w, h);
+ skull (dpy, logo_map, draw_gc, erase_gc, 5, 0, w-10, h-10);
+ XFreeGC (dpy, draw_gc);
+ XFreeGC (dpy, erase_gc);
+ }
+#else
+ if (!(logo_map = XCreateBitmapFromData (dpy, win, logo_bits,
+ logo_width, logo_height)))
+ {
+ fprintf (stderr, "Can't create logo pixmap\n");
+ exit (1);
+ }
+#endif
+ XMapRaised(dpy, win);
+ srandom(getpid());
+
+ restart = root;
+
+ while (1) { /* primary execution loop [ rhess ] */
+ if (check_events()) continue ;
+ if (restart || stop) goto pop;
+ switch (state) {
+ case 1:
+ initialize_maze();
+ break;
+ case 2:
+ XClearWindow(dpy, win);
+ draw_maze_border();
+ break;
+ case 3:
+ create_maze();
+ break;
+ case 4:
+ XSync (dpy, False);
+ usleep (pre_solve_delay);
+ break;
+ case 5:
+ solve_maze();
+ break;
+ case 6:
+ XSync (dpy, False);
+ usleep (post_solve_delay);
+ state = 0 ;
+ break;
+ default:
+ abort ();
+ }
+ ++state;
+ pop:
+ if (restart)
+ {
+ static XWindowAttributes wattr;
+ restart = 0;
+ stop = 0;
+ state = 1;
+ XGetWindowAttributes (dpy, win, &wattr);
+ set_maze_sizes (wattr.width, wattr.height);
+ XClearWindow (dpy, win);
+ XSync (dpy, False);
+ }
+ }
+}
--- /dev/null
+.TH XScreenSaver 1 "7-mar-93" "X Version 11"
+.SH NAME
+maze \- an automated X11 demo repeatedly creating and solving a random maze
+.SH SYNOPSIS
+.B maze
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-grid\-size \fIpixels\fP] [\-live\-color \fIcolor\fP] [\-dead\-color \fIcolor\fP] [\-solve\-delay \fIusecs\fP] [\-pre\-delay \fIusecs\fP] [\-post\-delay \fIusecs\fP]
+.SH DESCRIPTION
+The \fImaze\fP program creates a "random" maze and then solves it with
+graphical feedback.
+.SH OPTIONS
+.I maze
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-grid\-size pixels
+The size of each block of the maze, in pixels; default is 0, meaning
+pick a random grid size.
+.TP 8
+.B \-live\-color color
+The color of the path.
+.TP 8
+.B \-dead\-color color
+The color of the failed path (it is also stippled with a 50% pattern.)
+.TP 8
+.B \-solve\-delay integer
+Delay (in microseconds) between each step of the solution path.
+Default 5000, or about 1/200th second.
+.TP 8
+.B \-pre\-delay integer
+Delay (in microseconds) between generating a maze and starting to solve it.
+Default 2000000 (2 seconds.)
+.TP 8
+.B \-post\-delay integer
+Delay (in microseconds) after solving a maze and before generating a new one.
+Default 4000000 (4 seconds.)
+.PP
+Clicking the mouse in the maze window controls it.
+.IP "\fBLeftButton\fP"
+Clears the window and restarts maze.
+.IP "\fBMiddleButton\fP"
+Pause or unpause the program.
+.IP "\fBRightButton\fP"
+Exit.
+.SH BUGS
+Expose events force a restart of maze.
+
+Mouse actions are based on "raw" values (Button1, Button2 and Button3)
+instead of using the pointer map.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+.PP
+Copyright \(co 1988 by Sun Microsystems, Inc. Mountain View, CA.
+.PP
+All Rights Reserved
+.PP
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted, provided that
+the above copyright notice appear in all copies and that both that copyright
+notice and this permission notice appear in supporting documentation, and that
+the names of Sun or MIT not be used in advertising or publicity pertaining to
+distribution of the software without specific prior written permission. Sun
+and M.I.T. make no representations about the suitability of this software for
+any purpose. It is provided "as is" without any express or implied warranty.
+.PP
+SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN
+NO EVENT SHALL SUN BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.SH AUTHOR(s)
+.nf
+Jim Randell [ XScreenSaver version ] jmr@mddjmr.fc.hp.com
+ HPLabs, Bristol
+Richard Hess [ X11 extensions ] {...}!uunet!cimshop!rhess
+ Consilium, Mountain View, CA
+Dave Lemke [ X11 version ] lemke@sun.COM
+ Sun MicroSystems, Mountain View, CA
+Martin Weiss [ SunView version ]
+ Sun MicroSystems, Mountain View, CA
+.fi
--- /dev/null
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+/* Make a little guy with a big nose and a hat wanter around the screen,
+ spewing out messages. Derived from xnlock by Dan Heller <argv@sun.com>.
+ */
+
+#include "screenhack.h"
+#include <stdio.h>
+
+#if __STDC__
+extern FILE *popen (const char *, const char *);
+extern int pclose (FILE *);
+#endif
+
+#define Pixel unsigned long
+
+#define font_height(font) (font->ascent + font->descent)
+#define FONT_NAME "-*-times-*-*-*-*-18-*-*-*-*-*-*-*"
+
+static Display *dpy;
+static Window window;
+static int Width, Height;
+static GC fg_gc, bg_gc, text_fg_gc, text_bg_gc;
+static char *words, *get_words();
+static int x, y;
+static XFontStruct *font;
+static char *def_words = "I'm out running around.";
+static void init_images(), walk(), talk();
+static int think();
+static unsigned long interval, look();
+static Pixmap left0, left1, right0, right1;
+static Pixmap left_front, right_front, front, down;
+
+static char *program, *orig_program, *filename, *text;
+
+#define FROM_ARGV 1
+#define FROM_PROGRAM 2
+#define FROM_FILE 3
+#define FROM_RESRC 4
+static int getwordsfrom;
+
+#define IS_MOVING 1
+#define GET_PASSWD 2
+static int state; /* indicates states: walking or getting passwd */
+
+static void (*next_fn) ();
+
+#include "noses/nose.0.left"
+#include "noses/nose.1.left"
+#include "noses/nose.0.right"
+#include "noses/nose.1.right"
+#include "noses/nose.left.front"
+#include "noses/nose.right.front"
+#include "noses/nose.front"
+#include "noses/nose.down"
+
+static void
+init_images ()
+{
+ static Pixmap *images[] = {
+ &left0, &left1, &right0, &right1,
+ &left_front, &right_front, &front, &down
+ };
+ static unsigned char *bits[] = {
+ nose_0_left_bits, nose_1_left_bits, nose_0_right_bits,
+ nose_1_right_bits, nose_left_front_bits, nose_right_front_bits,
+ nose_front_bits, nose_down_bits
+ };
+ int i;
+
+ for (i = 0; i < sizeof (images) / sizeof (images[0]); i++)
+ if (!(*images[i] =
+ XCreatePixmapFromBitmapData(dpy, window,
+ (char *) bits[i], 64, 64, 1, 0, 1)))
+ {
+ fprintf (stderr, "%s: Can't load nose images", progname);
+ exit (1);
+ }
+}
+
+#define LEFT 001
+#define RIGHT 002
+#define DOWN 004
+#define UP 010
+#define FRONT 020
+#define X_INCR 3
+#define Y_INCR 2
+
+static void
+move()
+{
+ static int length,
+ dir;
+
+ if (!length)
+ {
+ register int tries = 0;
+ dir = 0;
+ if ((random() & 1) && think())
+ {
+ talk(0); /* sets timeout to itself */
+ return;
+ }
+ if (!(random() % 3) && (interval = look()))
+ {
+ next_fn = move;
+ return;
+ }
+ interval = 20 + random() % 100;
+ do
+ {
+ if (!tries)
+ length = Width / 100 + random() % 90, tries = 8;
+ else
+ tries--;
+ switch (random() % 8)
+ {
+ case 0:
+ if (x - X_INCR * length >= 5)
+ dir = LEFT;
+ break;
+ case 1:
+ if (x + X_INCR * length <= Width - 70)
+ dir = RIGHT;
+ break;
+ case 2:
+ if (y - (Y_INCR * length) >= 5)
+ dir = UP, interval = 40;
+ break;
+ case 3:
+ if (y + Y_INCR * length <= Height - 70)
+ dir = DOWN, interval = 20;
+ break;
+ case 4:
+ if (x - X_INCR * length >= 5 && y - (Y_INCR * length) >= 5)
+ dir = (LEFT | UP);
+ break;
+ case 5:
+ if (x + X_INCR * length <= Width - 70 &&
+ y - Y_INCR * length >= 5)
+ dir = (RIGHT | UP);
+ break;
+ case 6:
+ if (x - X_INCR * length >= 5 &&
+ y + Y_INCR * length <= Height - 70)
+ dir = (LEFT | DOWN);
+ break;
+ case 7:
+ if (x + X_INCR * length <= Width - 70 &&
+ y + Y_INCR * length <= Height - 70)
+ dir = (RIGHT | DOWN);
+ break;
+ default:
+ /* No Defaults */
+ break;
+ }
+ } while (!dir);
+ }
+ walk(dir);
+ --length;
+ next_fn = move;
+}
+
+static void
+walk(dir)
+ register int dir;
+{
+ register int incr = 0;
+ static int lastdir;
+ static int up = 1;
+ static Pixmap frame;
+
+ if (dir & (LEFT | RIGHT))
+ { /* left/right movement (mabye up/down too) */
+ up = -up; /* bouncing effect (even if hit a wall) */
+ if (dir & LEFT)
+ {
+ incr = X_INCR;
+ frame = (up < 0) ? left0 : left1;
+ }
+ else
+ {
+ incr = -X_INCR;
+ frame = (up < 0) ? right0 : right1;
+ }
+ if ((lastdir == FRONT || lastdir == DOWN) && dir & UP)
+ {
+
+ /*
+ * workaround silly bug that leaves screen dust when guy is
+ * facing forward or down and moves up-left/right.
+ */
+ XCopyPlane(dpy, frame, window, fg_gc, 0, 0, 64, 64, x, y, 1L);
+ XFlush(dpy);
+ }
+ /* note that maybe neither UP nor DOWN is set! */
+ if (dir & UP && y > Y_INCR)
+ y -= Y_INCR;
+ else if (dir & DOWN && y < Height - 64)
+ y += Y_INCR;
+ }
+ /* Explicit up/down movement only (no left/right) */
+ else if (dir == UP)
+ XCopyPlane(dpy, front, window, fg_gc,
+ 0, 0, 64, 64, x, y -= Y_INCR, 1L);
+ else if (dir == DOWN)
+ XCopyPlane(dpy, down, window, fg_gc,
+ 0, 0, 64, 64, x, y += Y_INCR, 1L);
+ else if (dir == FRONT && frame != front)
+ {
+ if (up > 0)
+ up = -up;
+ if (lastdir & LEFT)
+ frame = left_front;
+ else if (lastdir & RIGHT)
+ frame = right_front;
+ else
+ frame = front;
+ XCopyPlane(dpy, frame, window, fg_gc, 0, 0, 64, 64, x, y, 1L);
+ }
+ if (dir & LEFT)
+ while (--incr >= 0)
+ {
+ XCopyPlane(dpy, frame, window, fg_gc,
+ 0, 0, 64, 64, --x, y + up, 1L);
+ XFlush(dpy);
+ }
+ else if (dir & RIGHT)
+ while (++incr <= 0)
+ {
+ XCopyPlane(dpy, frame, window, fg_gc,
+ 0, 0, 64, 64, ++x, y + up, 1L);
+ XFlush(dpy);
+ }
+ lastdir = dir;
+}
+
+static int
+think()
+{
+ if (random() & 1)
+ walk(FRONT);
+ if (random() & 1)
+ {
+ if (getwordsfrom == FROM_PROGRAM)
+ words = get_words(0, (char **) 0);
+ return 1;
+ }
+ return 0;
+}
+
+#define MAXLINES 40
+
+static void
+talk(force_erase)
+ int force_erase;
+{
+ int width = 0,
+ height,
+ Z,
+ total = 0;
+ static int X,
+ Y,
+ talking;
+ static struct
+ {
+ int x,
+ y,
+ width,
+ height;
+ } s_rect;
+ register char *p,
+ *p2;
+ char buf[BUFSIZ],
+ args[MAXLINES][256];
+
+ /* clear what we've written */
+ if (talking || force_erase)
+ {
+ if (!talking)
+ return;
+ XFillRectangle(dpy, window, bg_gc, s_rect.x - 5, s_rect.y - 5,
+ s_rect.width + 10, s_rect.height + 10);
+ talking = 0;
+ if (!force_erase)
+ next_fn = move;
+ interval = 0;
+ {
+ /* might as well check the window for size changes now... */
+ XWindowAttributes xgwa;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ Width = xgwa.width + 2;
+ Height = xgwa.height + 2;
+ }
+ return;
+ }
+ talking = 1;
+ walk(FRONT);
+ p = strcpy(buf, words);
+
+ if (!(p2 = index(p, '\n')) || !p2[1])
+ {
+ total = strlen (words);
+ strcpy (args[0], words);
+ width = XTextWidth(font, words, total);
+ height = 0;
+ }
+ else
+ /* p2 now points to the first '\n' */
+ for (height = 0; p; height++)
+ {
+ int w;
+ *p2 = 0;
+ if ((w = XTextWidth(font, p, p2 - p)) > width)
+ width = w;
+ total += p2 - p; /* total chars; count to determine reading
+ * time */
+ (void) strcpy(args[height], p);
+ if (height == MAXLINES - 1)
+ {
+ puts("Message too long!");
+ break;
+ }
+ p = p2 + 1;
+ if (!(p2 = index(p, '\n')))
+ break;
+ }
+ height++;
+
+ /*
+ * Figure out the height and width in pixels (height, width) extend the
+ * new box by 15 pixels on the sides (30 total) top and bottom.
+ */
+ s_rect.width = width + 30;
+ s_rect.height = height * font_height(font) + 30;
+ if (x - s_rect.width - 10 < 5)
+ s_rect.x = 5;
+ else if ((s_rect.x = x + 32 - (s_rect.width + 15) / 2)
+ + s_rect.width + 15 > Width - 5)
+ s_rect.x = Width - 15 - s_rect.width;
+ if (y - s_rect.height - 10 < 5)
+ s_rect.y = y + 64 + 5;
+ else
+ s_rect.y = y - 5 - s_rect.height;
+
+ XFillRectangle(dpy, window, text_bg_gc,
+ s_rect.x, s_rect.y, s_rect.width, s_rect.height);
+
+ /* make a box that's 5 pixels thick. Then add a thin box inside it */
+ XSetLineAttributes(dpy, text_fg_gc, 5, 0, 0, 0);
+ XDrawRectangle(dpy, window, text_fg_gc,
+ s_rect.x, s_rect.y, s_rect.width - 1, s_rect.height - 1);
+ XSetLineAttributes(dpy, text_fg_gc, 0, 0, 0, 0);
+ XDrawRectangle(dpy, window, text_fg_gc,
+ s_rect.x + 7, s_rect.y + 7, s_rect.width - 15, s_rect.height - 15);
+
+ X = 15;
+ Y = 15 + font_height(font);
+
+ /* now print each string in reverse order (start at bottom of box) */
+ for (Z = 0; Z < height; Z++)
+ {
+ XDrawString(dpy, window, text_fg_gc, s_rect.x + X, s_rect.y + Y,
+ args[Z], strlen(args[Z]));
+ Y += font_height(font);
+ }
+ interval = (total / 15) * 1000;
+ if (interval < 2000) interval = 2000;
+ next_fn = talk;
+}
+
+static unsigned long
+look()
+{
+ if (random() % 3)
+ {
+ XCopyPlane(dpy, (random() & 1) ? down : front, window, fg_gc,
+ 0, 0, 64, 64, x, y, 1L);
+ return 1000L;
+ }
+ if (!(random() % 5))
+ return 0;
+ if (random() % 3)
+ {
+ XCopyPlane(dpy, (random() & 1) ? left_front : right_front,
+ window, fg_gc, 0, 0, 64, 64, x, y, 1L);
+ return 1000L;
+ }
+ if (!(random() % 5))
+ return 0;
+ XCopyPlane(dpy, (random() & 1) ? left0 : right0, window, fg_gc,
+ 0, 0, 64, 64, x, y, 1L);
+ return 1000L;
+}
+
+
+static void
+init_words()
+{
+ char *mode = get_string_resource ("mode", "Mode");
+
+ program = get_string_resource ("program", "Program");
+ filename = get_string_resource ("filename", "Filename");
+ text = get_string_resource ("text", "Text");
+
+ if (program) /* get stderr on stdout, so it shows up on the window */
+ {
+ orig_program = program;
+ program = (char *) malloc (strlen (program) + 10);
+ strcpy (program, "( ");
+ strcat (program, orig_program);
+ strcat (program, " ) 2>&1");
+ }
+
+ if (!mode || !strcmp (mode, "program"))
+ getwordsfrom = FROM_PROGRAM;
+ else if (!strcmp (mode, "file"))
+ getwordsfrom = FROM_FILE;
+ else if (!strcmp (mode, "string"))
+ getwordsfrom = FROM_RESRC;
+ else
+ {
+ fprintf (stderr,
+ "%s: mode must be program, file, or string, not %s\n",
+ progname, mode);
+ exit (1);
+ }
+
+ if (getwordsfrom == FROM_PROGRAM && !program)
+ {
+ fprintf (stderr, "%s: no program specified.\n", progname);
+ exit (1);
+ }
+ if (getwordsfrom == FROM_FILE && !filename)
+ {
+ fprintf (stderr, "%s: no file specified.\n", progname);
+ exit (1);
+ }
+
+ words = get_words();
+}
+
+static char *
+get_words()
+{
+ FILE *pp;
+ static char buf[BUFSIZ];
+ register char *p = buf;
+
+ buf[0] = '\0';
+
+ switch (getwordsfrom)
+ {
+ case FROM_PROGRAM:
+ if (pp = popen(program, "r"))
+ {
+ while (fgets(p, sizeof(buf) - strlen(buf), pp))
+ {
+ if (strlen(buf) + 1 < sizeof(buf))
+ p = buf + strlen(buf);
+ else
+ break;
+ }
+ (void) pclose(pp);
+ if (! buf[0])
+ sprintf (buf, "\"%s\" produced no output!", orig_program);
+ p = buf;
+ }
+ else
+ {
+ perror(program);
+ p = def_words;
+ }
+ break;
+ case FROM_FILE:
+ if (pp = fopen(filename, "r"))
+ {
+ while (fgets(p, sizeof(buf) - strlen(buf), pp))
+ {
+ if (strlen(buf) + 1 < sizeof(buf))
+ p = buf + strlen(buf);
+ else
+ break;
+ }
+ (void) fclose(pp);
+ if (! buf[0])
+ sprintf (buf, "file \"%s\" is empty!", filename);
+ p = buf;
+ }
+ else
+ {
+ sprintf (buf, "couldn't read file \"%s\"!", filename);
+ p = buf;
+ }
+ break;
+ case FROM_RESRC:
+ p = text;
+ break;
+ default:
+ p = def_words;
+ break;
+ }
+
+ if (!p || *p == '\0')
+ p = def_words;
+ return p;
+}
+
+
+\f
+char *progclass = "Noseguy";
+
+char *defaults [] = {
+ "*background: black",
+ "*foreground: white",
+ "*mode: program",
+ "*program: fortune -s",
+ "noseguy.font: -*-new century schoolbook-*-r-*-*-*-180-*-*-*-*-*-*",
+ 0
+};
+
+XrmOptionDescRec options [] = {
+ { "-mode", ".mode", XrmoptionSepArg, 0 },
+ { "-program", ".program", XrmoptionSepArg, 0 },
+ { "-text", ".text", XrmoptionSepArg, 0 },
+ { "-filename", ".filename", XrmoptionSepArg, 0 },
+ { "-font", ".font", XrmoptionSepArg, 0 },
+ { "-text-foreground", ".textForeground", XrmoptionSepArg, 0 },
+ { "-text-background", ".textBackground", XrmoptionSepArg, 0 }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+
+static void
+noseguy_init (d, w)
+ Display *d;
+ Window w;
+{
+ Pixel fg, bg, text_fg, text_bg;
+ XWindowAttributes xgwa;
+ Colormap cmap;
+ char *fontname = get_string_resource ("font", "Font");
+ char **list;
+ int foo, i;
+ XGCValues gcvalues;
+ dpy = d;
+ window = w;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ Width = xgwa.width + 2;
+ Height = xgwa.height + 2;
+ cmap = xgwa.colormap;
+
+ init_words();
+ init_images();
+
+ if (!fontname || !(font = XLoadQueryFont(dpy, fontname)))
+ {
+ list = XListFonts(dpy, FONT_NAME, 32767, &foo);
+ for (i = 0; i < foo; i++)
+ if (font = XLoadQueryFont(dpy, list[i]))
+ break;
+ if (!font)
+ {
+ fprintf (stderr, "%s: Can't find a large font.", progname);
+ exit (1);
+ }
+ XFreeFontNames(list);
+ }
+
+ fg = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+ bg = get_pixel_resource ("background", "Background", dpy, cmap);
+ text_fg = get_pixel_resource ("textForeground", "Foreground", dpy, cmap);
+ text_bg = get_pixel_resource ("textBackground", "Background", dpy, cmap);
+ /* notice when unspecified */
+ if (! get_string_resource ("textForeground", "Foreground"))
+ text_fg = bg;
+ if (! get_string_resource ("textBackground", "Background"))
+ text_bg = fg;
+
+ gcvalues.font = font->fid;
+ gcvalues.graphics_exposures = False;
+ gcvalues.foreground = fg;
+ gcvalues.background = bg;
+ fg_gc = XCreateGC (dpy, window,
+ GCForeground|GCBackground|GCGraphicsExposures|GCFont,
+ &gcvalues);
+ gcvalues.foreground = bg;
+ gcvalues.background = fg;
+ bg_gc = XCreateGC (dpy, window,
+ GCForeground|GCBackground|GCGraphicsExposures|GCFont,
+ &gcvalues);
+ gcvalues.foreground = text_fg;
+ gcvalues.background = text_bg;
+ text_fg_gc = XCreateGC (dpy, window,
+ GCForeground|GCBackground|GCGraphicsExposures|GCFont,
+ &gcvalues);
+ gcvalues.foreground = text_bg;
+ gcvalues.background = text_fg;
+ text_bg_gc = XCreateGC (dpy, window,
+ GCForeground|GCBackground|GCGraphicsExposures|GCFont,
+ &gcvalues);
+ x = Width / 2;
+ y = Height / 2;
+ state = IS_MOVING;
+}
+
+void
+screenhack (d, w)
+ Display *d;
+ Window w;
+{
+ noseguy_init (d, w);
+ next_fn = move;
+ while (1)
+ {
+ next_fn (0);
+ XSync (dpy, True);
+ usleep (interval * 1000);
+ }
+}
+
--- /dev/null
+.TH XScreenSaver 1 "13-aug-92" "X Version 11"
+.SH NAME
+noseguy - a little guy with a big nose wanders around being witty
+.SH SYNOPSIS
+.B noseguy
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-text-foreground \fIcolor\fP] [\-text-background \fIcolor\fP] [\-font \fIfont\fP] [\-window] [\-root] [\-mode \fImode\fP] [\-program \fIprogram\fP] [\-filename \file\fP] [\-text \fItext\fP]
+.SH DESCRIPTION
+A little man with a big nose and a hat runs around spewing out messages to
+the screen. This code (and its bitmaps) were extracted from the \fIxnlock\fP
+program.
+.SH OPTIONS
+.I noseguy
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-font font
+The font used for the messages.
+.TP 8
+.B \-mode program | file | string
+In \fIprogram\fP mode, the messages are gotten by running a program.
+The program used is controlled by the \fI\-program\fP option, and
+the \fI.program\fP resource.
+
+In \fIfilename\fP mode, the message used is the contents of a file.
+The file used is controlled by the \fI\-file\fP option, and
+the \fI.filename\fP resource.
+
+In \fIstring\fP mode, the message is whatever was specified on the
+command line as the \fI\-text\fP option, or in the resource database
+as the \fI.text\fP resource.
+.TP 8
+.B \-program " program"
+If \fImode\fP is \fIprogram\fP (the default), then this program will be
+run periodically, and its output will be the text of the messages. The
+default program is \fI"fortune -s"\fP, but \fIyow\fP is also a good choice.
+.TP 8
+.B \-filename file
+If \fImode\fP is \fIfile\fP, then the contents of this file will be used
+for all messages.
+.TP 8
+.B \-text string
+If \fImode\fP is \fIstring\fP, then this text will be used for all messages.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR xnlock (1)
+.SH COPYRIGHT
+Copyright 1985, 1990 by Dan Heller <argv@sun.com>.
+.SH AUTHOR
+Dan Heller <argv@sun.com>, 1985.
+
+Ability to run standalone or with \fIxscreensaver\fP added by
+Jamie Zawinski <jwz@lucid.com>, 13-aug-92.
--- /dev/null
+#define nose_0_left_width 64
+#define nose_0_left_height 64
+static unsigned char nose_0_left_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,
+ 0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
+ 0x40,0x00,0x00,0x04,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
+ 0x08,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x20,0x00,
+ 0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0xf0,0x03,0x00,0x00,0x80,0x00,
+ 0x00,0x00,0x0e,0x0c,0x00,0x00,0x80,0x01,0x00,0x00,0x03,0x30,0x00,0x00,0x00,
+ 0x01,0x00,0x80,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x40,0x00,0xc0,0x00,0x00,
+ 0x00,0x02,0x00,0x20,0x00,0x80,0x00,0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00,
+ 0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x08,0x00,0x00,
+ 0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,
+ 0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,
+ 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,
+ 0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,
+ 0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x01,0x00,0x00,
+ 0x18,0x00,0x20,0x00,0x00,0x01,0x00,0x00,0x08,0x00,0x40,0x00,0x80,0x00,0x00,
+ 0x00,0x08,0x00,0x80,0x00,0x40,0x00,0x00,0x00,0x0c,0x00,0x00,0x01,0x20,0x00,
+ 0x00,0x00,0x04,0x00,0x00,0x06,0x18,0x00,0x00,0x00,0x06,0x00,0x00,0xf8,0x07,
+ 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x0f,0x00,0x00,0x00,
+ 0x00,0xff,0x00,0x04,0x10,0x00,0x00,0x00,0xc0,0x00,0x03,0x03,0x10,0x00,0x00,
+ 0x00,0x30,0x00,0x0c,0x01,0x20,0x00,0x00,0x00,0x08,0x00,0x98,0x00,0x20,0x00,
+ 0x00,0x00,0x0c,0x03,0x60,0x00,0x20,0x00,0x00,0x00,0xc2,0x00,0xc0,0x00,0x20,
+ 0x00,0x00,0x00,0x42,0x00,0x80,0x00,0x20,0x00,0x00,0x00,0x21,0x00,0x00,0x01,
+ 0x20,0x00,0x00,0x00,0x21,0x00,0x00,0x01,0x20,0x00,0x00,0x00,0x21,0x00,0x00,
+ 0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x01,0x00,
+ 0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x02,
+ 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x20,0x00,0x00,0x00,
+ 0x18,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x10,0x00,0x00,
+ 0x00,0xc0,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00};
--- /dev/null
+#define nose_0_right_width 64
+#define nose_0_right_height 64
+static unsigned char nose_0_right_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x20,0x00,
+ 0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,
+ 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,
+ 0x20,0x00,0x00,0x02,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,
+ 0x04,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x10,0x00,
+ 0x00,0xfc,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x01,0x00,0x00,0xc0,0x0f,
+ 0x00,0x00,0x80,0x01,0x00,0x00,0x30,0x70,0x00,0x00,0x80,0x00,0x00,0x00,0x0c,
+ 0xc0,0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x40,0x00,0x00,0x00,
+ 0x03,0x00,0x02,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x20,0x00,0x00,
+ 0x00,0x00,0x00,0x08,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x00,
+ 0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,
+ 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,
+ 0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,
+ 0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,
+ 0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x18,0x00,0x00,0x80,0x00,
+ 0x00,0x08,0x00,0x10,0x00,0x00,0x80,0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00,
+ 0x01,0x00,0x02,0x00,0x30,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x20,0x00,0x00,
+ 0x00,0x04,0x80,0x00,0x00,0x60,0x00,0x00,0x00,0x18,0x60,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0xe0,0x1f,0x00,0x00,0x80,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x1f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x08,0x20,0x00,0xff,0x00,0x00,0x00,0x00,0x08,0xc0,0xc0,0x00,0x03,0x00,
+ 0x00,0x00,0x04,0x80,0x30,0x00,0x0c,0x00,0x00,0x00,0x04,0x00,0x19,0x00,0x10,
+ 0x00,0x00,0x00,0x04,0x00,0x06,0xc0,0x30,0x00,0x00,0x00,0x04,0x00,0x03,0x00,
+ 0x43,0x00,0x00,0x00,0x04,0x00,0x01,0x00,0x42,0x00,0x00,0x00,0x04,0x80,0x00,
+ 0x00,0x84,0x00,0x00,0x00,0x04,0x80,0x00,0x00,0x84,0x00,0x00,0x00,0x04,0x00,
+ 0x00,0x00,0x84,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x02,
+ 0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,
+ 0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x20,0x00,0x00,
+ 0x00,0x04,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x0e,0x00,
+ 0x00,0x00,0xf0,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00};
--- /dev/null
+#define nose_1_left_width 64
+#define nose_1_left_height 64
+static unsigned char nose_1_left_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,
+ 0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
+ 0x40,0x00,0x00,0x04,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
+ 0x08,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x20,0x00,
+ 0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0xf0,0x03,0x00,0x00,0x80,0x00,
+ 0x00,0x00,0x0e,0x0c,0x00,0x00,0x80,0x01,0x00,0x00,0x03,0x30,0x00,0x00,0x00,
+ 0x01,0x00,0x80,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x40,0x00,0xc0,0x00,0x00,
+ 0x00,0x02,0x00,0x20,0x00,0x80,0x00,0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00,
+ 0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x08,0x00,0x00,
+ 0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,
+ 0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,
+ 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,
+ 0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,
+ 0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x01,0x00,0x00,
+ 0x18,0x00,0x10,0x00,0x00,0x01,0x00,0x00,0x08,0x00,0x20,0x00,0x80,0x00,0x00,
+ 0x00,0x08,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x0c,0x00,0x80,0x00,0x20,0x00,
+ 0x00,0x00,0xe4,0x00,0x00,0x03,0x18,0x00,0x00,0x00,0x26,0x03,0x00,0xfc,0x07,
+ 0x00,0x00,0x00,0x12,0x0c,0x00,0x00,0xf8,0xff,0xff,0xff,0x11,0x10,0x80,0x1f,
+ 0x00,0x00,0x00,0x00,0x08,0x20,0x60,0x60,0xc0,0x07,0x00,0x00,0x04,0x40,0x10,
+ 0xc0,0x20,0x08,0x00,0x1f,0x02,0x40,0x08,0x00,0x21,0x10,0xc0,0x60,0x02,0x40,
+ 0x04,0x00,0x12,0x20,0x20,0x80,0x02,0x20,0xc2,0x00,0x14,0x40,0x18,0x00,0x03,
+ 0x20,0x22,0x00,0x0c,0x80,0x04,0x03,0x02,0x10,0x12,0x00,0x08,0x80,0x86,0x00,
+ 0x04,0x10,0x12,0x00,0x10,0x80,0x42,0x00,0x18,0x08,0x12,0x00,0x10,0x40,0x42,
+ 0x00,0x00,0x04,0x02,0x00,0x20,0x40,0x42,0x00,0x00,0x04,0x02,0x00,0x00,0x20,
+ 0x42,0x00,0x00,0x02,0x04,0x00,0x00,0x20,0x02,0x00,0x00,0x01,0x04,0x00,0x00,
+ 0x20,0x02,0x00,0x00,0x01,0x08,0x00,0x00,0x20,0x04,0x00,0x80,0x00,0x10,0x00,
+ 0x00,0x20,0x0c,0x00,0x80,0x00,0x60,0x00,0x00,0x10,0x08,0x00,0x40,0x00,0x80,
+ 0xff,0xff,0x0f,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0x0f,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00};
--- /dev/null
+#define nose_1_right_width 64
+#define nose_1_right_height 64
+static unsigned char nose_1_right_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x20,0x00,
+ 0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,
+ 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,
+ 0x20,0x00,0x00,0x02,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,
+ 0x04,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x10,0x00,
+ 0x00,0xfc,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x01,0x00,0x00,0xc0,0x0f,
+ 0x00,0x00,0x80,0x01,0x00,0x00,0x30,0x70,0x00,0x00,0x80,0x00,0x00,0x00,0x0c,
+ 0xc0,0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x40,0x00,0x00,0x00,
+ 0x03,0x00,0x02,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x20,0x00,0x00,
+ 0x00,0x00,0x00,0x08,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x00,
+ 0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,
+ 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,
+ 0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,
+ 0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,
+ 0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x18,0x00,0x00,0x80,0x00,
+ 0x00,0x08,0x00,0x10,0x00,0x00,0x80,0x00,0x00,0x08,0x00,0x10,0x00,0x00,0x00,
+ 0x01,0x00,0x04,0x00,0x30,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x27,0x00,0x00,
+ 0x00,0x04,0x00,0x01,0xc0,0x64,0x00,0x00,0x00,0x18,0xc0,0x00,0x30,0x48,0x00,
+ 0x00,0x00,0xe0,0x3f,0x00,0x08,0x88,0xff,0xff,0xff,0x1f,0x00,0x00,0x04,0x10,
+ 0x00,0x00,0x00,0x00,0xf8,0x01,0x02,0x20,0x00,0x00,0xe0,0x03,0x06,0x06,0x02,
+ 0x40,0xf8,0x00,0x10,0x04,0x03,0x08,0x02,0x40,0x06,0x03,0x08,0x84,0x00,0x10,
+ 0x04,0x40,0x01,0x04,0x04,0x48,0x00,0x20,0x04,0xc0,0x00,0x18,0x02,0x28,0x00,
+ 0x43,0x08,0x40,0xc0,0x20,0x01,0x30,0x00,0x44,0x08,0x20,0x00,0x61,0x01,0x10,
+ 0x00,0x48,0x10,0x18,0x00,0x42,0x01,0x08,0x00,0x48,0x20,0x00,0x00,0x42,0x02,
+ 0x08,0x00,0x48,0x20,0x00,0x00,0x42,0x02,0x04,0x00,0x40,0x40,0x00,0x00,0x42,
+ 0x04,0x00,0x00,0x40,0x80,0x00,0x00,0x40,0x04,0x00,0x00,0x20,0x80,0x00,0x00,
+ 0x40,0x04,0x00,0x00,0x20,0x00,0x01,0x00,0x20,0x04,0x00,0x00,0x10,0x00,0x01,
+ 0x00,0x30,0x04,0x00,0x00,0x08,0x00,0x02,0x00,0x10,0x08,0x00,0x00,0x06,0x00,
+ 0x0c,0x00,0x0c,0xf0,0xff,0xff,0x01,0x00,0xf0,0xff,0x03,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00};
--- /dev/null
+#define nose_down_width 64
+#define nose_down_height 64
+static unsigned char nose_down_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xfc,0xff,0x01,0x00,0x00,0x00,0x00,0xc0,0x03,0x00,0x1e,0x00,
+ 0x00,0x00,0x00,0x38,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,
+ 0x03,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x40,0x00,0x00,0x00,
+ 0x00,0x08,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x10,0x00,0x80,
+ 0x1f,0x00,0x40,0x00,0x00,0x08,0x00,0x60,0x60,0x00,0x80,0x00,0x00,0x08,0x00,
+ 0x10,0x80,0x00,0x80,0x00,0x00,0x04,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x04,
+ 0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x18,0x80,0x01,0x00,0x02,0x00,
+ 0x02,0x00,0x68,0x60,0x01,0x00,0x02,0x00,0x02,0x00,0x88,0x1f,0x01,0x00,0x02,
+ 0x00,0x02,0x00,0x08,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x10,0x80,0x00,0x00,
+ 0x03,0x00,0x06,0x00,0x60,0x60,0x00,0x80,0x02,0x00,0x0c,0x00,0x80,0x1f,0x00,
+ 0x40,0x01,0x00,0x14,0x00,0x00,0x00,0x00,0x20,0x01,0x00,0x28,0x00,0x00,0x00,
+ 0x00,0x90,0x00,0x00,0x50,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0xa0,0x01,0x00,
+ 0x00,0x00,0x26,0x00,0x00,0x40,0x1e,0x00,0x00,0xc0,0x11,0x00,0x00,0x80,0xe1,
+ 0x03,0x00,0x3c,0x0c,0x00,0x00,0x00,0x0e,0xfc,0xff,0x83,0x03,0x00,0x00,0x00,
+ 0xf0,0x01,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x0f,0x00,0x00,0x00,
+ 0x00,0x80,0x03,0x00,0x0c,0x00,0x00,0x00,0x00,0x80,0x02,0x00,0x14,0x00,0x00,
+ 0x00,0x00,0x60,0x04,0x00,0x12,0x00,0x00,0xc0,0x7f,0x10,0x04,0x00,0x22,0xe0,
+ 0x01,0x70,0xc0,0x18,0x08,0x00,0x61,0x1c,0x06,0x10,0x00,0x0f,0x30,0xc0,0x80,
+ 0x07,0x08,0x08,0x00,0x06,0xc0,0x3f,0x80,0x01,0x08,0x08,0x00,0x18,0x00,0x02,
+ 0xc0,0x00,0x10,0x04,0x00,0x30,0x00,0x05,0x30,0x00,0x10,0x04,0x00,0x00,0x80,
+ 0x08,0x18,0x00,0x20,0x04,0x00,0x00,0x80,0x08,0x00,0x00,0x20,0x04,0x00,0x00,
+ 0x40,0x10,0x00,0x00,0x20,0x24,0x00,0x00,0x40,0x10,0x00,0x00,0x22,0x24,0x00,
+ 0x00,0x40,0x10,0x00,0x00,0x22,0x44,0x00,0x00,0x40,0x10,0x00,0x00,0x11,0x84,
+ 0x01,0x00,0xc0,0x18,0x00,0xc0,0x10,0x08,0x00,0x00,0x80,0x08,0x00,0x00,0x08,
+ 0x30,0x00,0x00,0x80,0x08,0x00,0x00,0x04,0xe0,0xff,0xff,0xff,0xf8,0xff,0xff,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00};
--- /dev/null
+#define nose_front_width 64
+#define nose_front_height 64
+static unsigned char nose_front_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,
+ 0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
+ 0x40,0x00,0x00,0x04,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
+ 0x08,0x00,0xc0,0x1f,0x00,0x20,0x00,0x00,0x08,0x00,0x30,0x60,0x00,0x20,0x00,
+ 0x00,0xf8,0xff,0x0f,0x80,0xff,0x3f,0x00,0x00,0x00,0x02,0x02,0x00,0x82,0x00,
+ 0x00,0x00,0x00,0x03,0x01,0x00,0x84,0x01,0x00,0x00,0x00,0x81,0x00,0x00,0x08,
+ 0x01,0x00,0x00,0x80,0x80,0x00,0x00,0x08,0x02,0x00,0x00,0x80,0x40,0x00,0x00,
+ 0x10,0x02,0x00,0x00,0x40,0x40,0x00,0x00,0x10,0x04,0x00,0x00,0x40,0x20,0x00,
+ 0x00,0x20,0x04,0x00,0x00,0x60,0x20,0x00,0x00,0x20,0x0c,0x00,0x00,0x20,0x20,
+ 0x00,0x00,0x20,0x08,0x00,0x00,0x20,0x20,0x00,0x00,0x20,0x08,0x00,0x00,0x10,
+ 0x20,0x00,0x00,0x20,0x10,0x00,0x00,0x10,0x20,0x00,0x00,0x20,0x10,0x00,0x00,
+ 0x10,0x20,0x00,0x00,0x20,0x10,0x00,0x00,0x10,0x40,0x00,0x00,0x10,0x10,0x00,
+ 0x00,0x10,0x40,0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x80,0x00,0x00,0x08,0x10,
+ 0x00,0x00,0x10,0x80,0x00,0x00,0x08,0x10,0x00,0x00,0x30,0x00,0x01,0x00,0x04,
+ 0x18,0x00,0x00,0x20,0x00,0x02,0x00,0x02,0x08,0x00,0x00,0x20,0x00,0x0c,0x80,
+ 0x01,0x08,0x00,0x00,0x60,0x00,0x30,0x60,0x00,0x0c,0x00,0x00,0x40,0x00,0xc0,
+ 0x1f,0x00,0x04,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x01,
+ 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0f,0xc0,0x0f,0x00,0x00,0x00,
+ 0x00,0x40,0x10,0x20,0x10,0x00,0x00,0x00,0x00,0x20,0x60,0x30,0x20,0x00,0x00,
+ 0x00,0x00,0x20,0xc0,0x18,0x20,0x00,0x00,0xc0,0x7f,0x10,0x80,0x0d,0x40,0xe0,
+ 0x01,0x70,0xc0,0x18,0x00,0x05,0x40,0x1c,0x06,0x10,0x00,0x0f,0x00,0x05,0x80,
+ 0x07,0x08,0x08,0x00,0x06,0x00,0x05,0x80,0x01,0x08,0x08,0x00,0x18,0x00,0x05,
+ 0xc0,0x00,0x10,0x04,0x00,0x30,0x00,0x05,0x30,0x00,0x10,0x04,0x00,0x00,0x80,
+ 0x08,0x18,0x00,0x20,0x04,0x00,0x00,0x80,0x08,0x00,0x00,0x20,0x04,0x00,0x00,
+ 0x40,0x10,0x00,0x00,0x20,0x24,0x00,0x00,0x40,0x10,0x00,0x00,0x22,0x24,0x00,
+ 0x00,0x40,0x10,0x00,0x00,0x22,0x44,0x00,0x00,0x40,0x10,0x00,0x00,0x11,0x84,
+ 0x01,0x00,0xc0,0x18,0x00,0xc0,0x10,0x08,0x00,0x00,0x80,0x08,0x00,0x00,0x08,
+ 0x30,0x00,0x00,0x80,0x08,0x00,0x00,0x04,0xe0,0xff,0xff,0xff,0xf8,0xff,0xff,
+ 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00};
--- /dev/null
+#define nose_left_front_width 64
+#define nose_left_front_height 64
+static unsigned char nose_left_front_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x40,0x00,
+ 0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,
+ 0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
+ 0x40,0x00,0x00,0x04,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,
+ 0x08,0x00,0xe0,0x0f,0x00,0x20,0x00,0x00,0x08,0x00,0x18,0x30,0x00,0x20,0x00,
+ 0x00,0xf8,0xff,0x07,0xc0,0xff,0x3f,0x00,0x00,0x00,0x02,0x01,0x00,0x81,0x00,
+ 0x00,0x00,0x00,0x83,0x00,0x00,0x82,0x01,0x00,0x00,0x00,0x41,0x00,0x00,0x04,
+ 0x01,0x00,0x00,0x80,0x40,0x00,0x00,0x04,0x02,0x00,0x00,0x80,0x20,0x00,0x00,
+ 0x08,0x02,0x00,0x00,0x40,0x20,0x00,0x00,0x08,0x04,0x00,0x00,0x40,0x10,0x00,
+ 0x00,0x10,0x04,0x00,0x00,0x60,0x10,0x00,0x00,0x10,0x0c,0x00,0x00,0x20,0x10,
+ 0x00,0x00,0x10,0x08,0x00,0x00,0x30,0x10,0x00,0x00,0x10,0x08,0x00,0x00,0x10,
+ 0x10,0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x10,0x00,0x00,
+ 0x10,0x10,0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x20,0x00,0x00,0x08,0x10,0x00,
+ 0x00,0x10,0x20,0x00,0x00,0x08,0x10,0x00,0x00,0x10,0x40,0x00,0x00,0x04,0x10,
+ 0x00,0x00,0x30,0x40,0x00,0x00,0x04,0x10,0x00,0x00,0x20,0x80,0x00,0x00,0x02,
+ 0x18,0x00,0x00,0x20,0x00,0x01,0x00,0x01,0x08,0x00,0x00,0x60,0x00,0x06,0xc0,
+ 0x00,0x08,0x00,0x00,0x80,0x00,0x18,0x30,0x00,0x0c,0x00,0x00,0x80,0x00,0xe0,
+ 0x0f,0x00,0x04,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x01,
+ 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x0f,0x00,0x00,0x00,
+ 0x00,0xff,0x00,0x04,0x10,0x00,0x00,0x00,0xe0,0x00,0x07,0x02,0x10,0x00,0x00,
+ 0x00,0x30,0x00,0x8c,0x01,0x20,0x00,0x00,0x00,0x0c,0x00,0x90,0x00,0x20,0x00,
+ 0x00,0x00,0x04,0x03,0x60,0x00,0x20,0x00,0x00,0x00,0xc2,0x00,0xc0,0x00,0x20,
+ 0x00,0x00,0x00,0x42,0x00,0x00,0x01,0x20,0x00,0x00,0x00,0x21,0x00,0x00,0x02,
+ 0x20,0x00,0x00,0x00,0x21,0x00,0x00,0x06,0x20,0x00,0x00,0x00,0x21,0x00,0x00,
+ 0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x03,0x00,
+ 0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x02,
+ 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x20,0x00,0x00,0x00,
+ 0x18,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x10,0x00,0x00,
+ 0x00,0xc0,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00};
--- /dev/null
+#define nose_right_front_width 64
+#define nose_right_front_height 64
+static unsigned char nose_right_front_bits[] = {
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x20,0x00,
+ 0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,
+ 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,
+ 0x20,0x00,0x00,0x02,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,
+ 0x04,0x00,0xf0,0x07,0x00,0x10,0x00,0x00,0x04,0x00,0x0c,0x18,0x00,0x10,0x00,
+ 0x00,0xfc,0xff,0x03,0xe0,0xff,0x1f,0x00,0x00,0x00,0x81,0x00,0x80,0x40,0x00,
+ 0x00,0x00,0x80,0x41,0x00,0x00,0xc1,0x00,0x00,0x00,0x80,0x20,0x00,0x00,0x82,
+ 0x00,0x00,0x00,0x40,0x20,0x00,0x00,0x02,0x01,0x00,0x00,0x40,0x10,0x00,0x00,
+ 0x04,0x01,0x00,0x00,0x20,0x10,0x00,0x00,0x04,0x02,0x00,0x00,0x20,0x08,0x00,
+ 0x00,0x08,0x02,0x00,0x00,0x30,0x08,0x00,0x00,0x08,0x06,0x00,0x00,0x10,0x08,
+ 0x00,0x00,0x08,0x04,0x00,0x00,0x10,0x08,0x00,0x00,0x08,0x0c,0x00,0x00,0x08,
+ 0x08,0x00,0x00,0x08,0x08,0x00,0x00,0x08,0x08,0x00,0x00,0x08,0x08,0x00,0x00,
+ 0x08,0x08,0x00,0x00,0x08,0x08,0x00,0x00,0x08,0x10,0x00,0x00,0x04,0x08,0x00,
+ 0x00,0x08,0x10,0x00,0x00,0x04,0x08,0x00,0x00,0x08,0x20,0x00,0x00,0x02,0x08,
+ 0x00,0x00,0x08,0x20,0x00,0x00,0x02,0x0c,0x00,0x00,0x18,0x40,0x00,0x00,0x01,
+ 0x04,0x00,0x00,0x10,0x80,0x00,0x80,0x00,0x04,0x00,0x00,0x10,0x00,0x03,0x60,
+ 0x00,0x06,0x00,0x00,0x30,0x00,0x0c,0x18,0x00,0x01,0x00,0x00,0x20,0x00,0xf0,
+ 0x07,0x00,0x01,0x00,0x00,0x60,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x40,0x00,
+ 0x00,0x00,0x80,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x1f,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x08,0x20,0x00,0xff,0x00,0x00,0x00,0x00,0x08,0x40,0xe0,0x00,0x07,0x00,
+ 0x00,0x00,0x04,0x80,0x31,0x00,0x0c,0x00,0x00,0x00,0x04,0x00,0x09,0x00,0x30,
+ 0x00,0x00,0x00,0x04,0x00,0x06,0xc0,0x20,0x00,0x00,0x00,0x04,0x00,0x03,0x00,
+ 0x43,0x00,0x00,0x00,0x04,0x80,0x00,0x00,0x42,0x00,0x00,0x00,0x04,0x40,0x00,
+ 0x00,0x84,0x00,0x00,0x00,0x04,0x60,0x00,0x00,0x84,0x00,0x00,0x00,0x04,0x00,
+ 0x00,0x00,0x84,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x02,
+ 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,
+ 0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x20,0x00,0x00,
+ 0x00,0x04,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x0e,0x00,
+ 0x00,0x00,0xf0,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00};
--- /dev/null
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+/* Draw some fireworks. Inspired from TI Explorer Lisp code by
+ John S. Pezaris <pz@hx.lcs.mit.edu>
+ */
+
+#include "screenhack.h"
+
+struct projectile {
+ int x, y; /* position */
+ int dx, dy; /* velocity */
+ int decay;
+ int size;
+ int fuse;
+ Bool primary;
+ Bool dead;
+ XColor color;
+ struct projectile *next_free;
+};
+
+static struct projectile *projectiles, *free_projectiles;
+
+static struct projectile *
+get_projectile ()
+{
+ struct projectile *p;
+ if (free_projectiles)
+ {
+ p = free_projectiles;
+ free_projectiles = p->next_free;
+ p->next_free = 0;
+ p->dead = False;
+ return p;
+ }
+ else
+ return 0;
+}
+
+static void
+free_projectile (p)
+ struct projectile *p;
+{
+ p->next_free = free_projectiles;
+ free_projectiles = p;
+ p->dead = True;
+}
+
+static void
+launch (xlim, ylim, g, dpy, cmap)
+ int xlim, ylim, g;
+ Display *dpy;
+ Colormap cmap;
+{
+ struct projectile *p = get_projectile ();
+ int x, dx, xxx;
+ if (! p) return;
+
+ do {
+ x = (random () % xlim);
+ dx = 30000 - (random () % 60000);
+ xxx = x + (dx * 200);
+ } while (xxx <= 0 || xxx >= xlim);
+
+ p->x = x;
+ p->y = ylim;
+ p->dx = dx;
+ p->size = 8000;
+ p->decay = 0;
+ p->dy = (random () % 4000) - 13000;
+ p->fuse = ((((random () % 500) + 500) * abs (p->dy / g)) / 1000);
+ p->primary = True;
+
+ if (! mono_p)
+ {
+ hsv_to_rgb (random () % 360, 1.0, 1.0,
+ &p->color.red, &p->color.green, &p->color.blue);
+ p->color.flags = DoRed | DoGreen | DoBlue;
+ if (!XAllocColor (dpy, cmap, &p->color))
+ {
+ p->color.pixel = WhitePixel (dpy, DefaultScreen (dpy));
+ p->color.red = p->color.green = p->color.blue = 0;
+ }
+ }
+}
+
+static struct projectile *
+shrapnel (parent, dpy, cmap)
+ struct projectile *parent;
+ Display *dpy;
+ Colormap cmap;
+{
+ struct projectile *p = get_projectile ();
+ if (! p) return 0;
+ p->x = parent->x;
+ p->y = parent->y;
+ p->dx = (random () % 5000) - 2500 + parent->dx;
+ p->dy = (random () % 5000) - 2500 + parent->dy;
+ p->decay = (random () % 50) - 60;
+ p->size = 6000;
+ p->fuse = 0;
+ p->primary = False;
+
+ p->color = parent->color;
+ if (! mono_p)
+ XAllocColor (dpy, cmap, &p->color); /* dup the lock */
+
+ return p;
+}
+
+static GC draw_gc, erase_gc;
+static unsigned int default_fg_pixel;
+
+static int how_many, frequency, scatter;
+
+static Colormap
+init_pyro (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ int i;
+ Colormap cmap;
+ XGCValues gcv;
+ XWindowAttributes xgwa;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ cmap = xgwa.colormap;
+ how_many = get_integer_resource ("count", "Integer");
+ frequency = get_integer_resource ("frequency", "Integer");
+ scatter = get_integer_resource ("scatter", "Integer");
+ if (how_many <= 0) how_many = 100;
+ if (frequency <= 0) frequency = 30;
+ if (scatter <= 0) scatter = 20;
+ projectiles = 0;
+ free_projectiles = 0;
+ projectiles = (struct projectile *)
+ calloc (how_many, sizeof (struct projectile));
+ for (i = 0; i < how_many; i++)
+ free_projectile (&projectiles [i]);
+ gcv.foreground = default_fg_pixel =
+ get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+ draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+ gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
+ erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+ XClearWindow (dpy, window);
+ return cmap;
+}
+
+static void
+pyro (dpy, window, cmap)
+ Display *dpy;
+ Window window;
+ Colormap cmap;
+{
+ XWindowAttributes xgwa;
+ static int xlim, ylim, real_xlim, real_ylim;
+ int g = 100;
+ int i;
+
+ if ((random () % frequency) == 0)
+ {
+ XGetWindowAttributes (dpy, window, &xgwa);
+ real_xlim = xgwa.width;
+ real_ylim = xgwa.height;
+ xlim = real_xlim * 1000;
+ ylim = real_ylim * 1000;
+ launch (xlim, ylim, g, dpy, cmap);
+ }
+
+ XSync (dpy, True);
+ usleep (10000);
+
+ for (i = 0; i < how_many; i++)
+ {
+ struct projectile *p = &projectiles [i];
+ int old_x, old_y, old_size;
+ int size, x, y;
+ if (p->dead) continue;
+ old_x = p->x >> 10;
+ old_y = p->y >> 10;
+ old_size = p->size >> 10;
+ size = (p->size += p->decay) >> 10;
+ x = (p->x += p->dx) >> 10;
+ y = (p->y += p->dy) >> 10;
+ p->dy += (p->size >> 6);
+ if (p->primary) p->fuse--;
+
+ /* erase old one */
+ XFillRectangle (dpy, window, erase_gc, old_x, old_y,
+ old_size, old_size);
+
+ if ((p->primary ? (p->fuse > 0) : (p->size > 0)) &&
+ x < real_xlim &&
+ y < real_ylim &&
+ x > 0 &&
+ y > 0)
+ {
+ if (mono_p || p->primary)
+ XSetForeground (dpy, draw_gc, default_fg_pixel);
+ else
+ XSetForeground (dpy, draw_gc, p->color.pixel);
+
+ if (p->primary)
+ XFillArc (dpy, window, draw_gc, x, y, size, size, 0, 360*64);
+ else
+ XFillRectangle (dpy, window, draw_gc, x, y, size, size);
+ }
+ else
+ {
+ free_projectile (p);
+ if (! mono_p) XFreeColors (dpy, cmap, &p->color.pixel, 1, 0);
+ }
+
+ if (p->primary && p->fuse <= 0)
+ {
+ int i = (random () % scatter) + (scatter/2);
+ while (i--)
+ shrapnel (p, dpy, cmap);
+ }
+ }
+}
+
+\f
+char *progclass = "Pyro";
+
+char *defaults [] = {
+ "*background: black",
+ "*foreground: white",
+ "*count: 100",
+ "*frequency: 30",
+ "*scatter: 20",
+ "*geometry: 800x500",
+ 0
+};
+
+XrmOptionDescRec options [] = {
+ { "-count", ".count", XrmoptionSepArg, 0 },
+ { "-frequency", ".frequency", XrmoptionSepArg, 0 },
+ { "-scatter", ".scatter", XrmoptionSepArg, 0 }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ Colormap cmap = init_pyro (dpy, window);
+ while (1)
+ pyro (dpy, window, cmap);
+}
--- /dev/null
+.TH XScreenSaver 1 "13-aug-92" "X Version 11"
+.SH NAME
+pyro - simulate fireworks
+.SH SYNOPSIS
+.B pyro
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-count \fIinteger\fP] [\-frequency \fIinteger\fP] [\-scatter \fIinteger\fP]
+.SH DESCRIPTION
+The \fIpyro\fP program simulates fireworks, in a way similar to a Macintosh
+program of the same name.
+.SH OPTIONS
+.I pyro
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-count integer
+How many particles should be allowed on the screen at once. Default 100.
+.TP 8
+.B \-frequency integer
+How often new missiles should launch. Default 30.
+.TP 8
+.B \-scatter integer
+How many particles should appear when a missile explodes. Default 20.
+The actual number used is between \fIN\fP and \fIN+(N/2)\fP.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1992 by Jamie Zawinski. Permission to use, copy, modify,
+distribute, and sell this software and its documentation for any purpose is
+hereby granted without fee, provided that the above copyright notice appear
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation. No representations are made about the
+suitability of this software for any purpose. It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@lucid.com>, 13-aug-92.
--- /dev/null
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#include "screenhack.h"
+#include <stdio.h>
+
+struct qpoint {
+ int x, y;
+ int dx, dy;
+};
+
+struct qline {
+ struct qpoint p1, p2;
+ XColor color;
+ Bool dead;
+};
+
+struct qix {
+ int id;
+ int fp;
+ int nlines;
+ struct qline *lines;
+};
+
+static GC draw_gc, erase_gc;
+static unsigned int default_fg_pixel;
+static int maxx, maxy, max_spread, max_size, color_shift;
+static Bool random_p, solid_p, xor_p, transparent_p;
+static int delay;
+static int count;
+static Colormap cmap;
+static unsigned long base_pixel;
+
+static GC *gcs[2];
+
+static void
+get_geom (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ XWindowAttributes xgwa;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ maxx = xgwa.width;
+ maxy = xgwa.height;
+}
+
+static struct qix *
+init_one_qix (dpy, window, nlines)
+ Display *dpy;
+ Window window;
+ int nlines;
+{
+ int i;
+ struct qix *qix = (struct qix *) calloc (1, sizeof (struct qix));
+ qix->nlines = nlines;
+ qix->lines = (struct qline *) calloc (qix->nlines, sizeof (struct qline));
+
+ if (!mono_p && !transparent_p)
+ {
+ hsv_to_rgb (random () % 360, frand (1.0), frand (0.5) + 0.5,
+ &qix->lines[0].color.red, &qix->lines[0].color.green,
+ &qix->lines[0].color.blue);
+ if (!XAllocColor (dpy, cmap, &qix->lines[0].color))
+ {
+ qix->lines[0].color.pixel = default_fg_pixel;
+ if (!XQueryColor (dpy, cmap, &qix->lines[0].color))
+ abort ();
+ if (!XAllocColor (dpy, cmap, &qix->lines[0].color))
+ abort ();
+ }
+ }
+ qix->lines[0].p1.x = random () % maxx;
+ qix->lines[0].p1.y = random () % maxy;
+ if (max_size == 0)
+ {
+ qix->lines[0].p2.x = random () % maxx;
+ qix->lines[0].p2.y = random () % maxy;
+ }
+ else
+ {
+ qix->lines[0].p2.x = qix->lines[0].p1.x + (random () % (max_size/2));
+ qix->lines[0].p2.y = qix->lines[0].p1.y + (random () % (max_size/2));
+ if (qix->lines[0].p2.x > maxx) qix->lines[0].p2.x = maxx;
+ if (qix->lines[0].p2.y > maxy) qix->lines[0].p2.y = maxy;
+ }
+ qix->lines[0].p1.dx = (random () % (max_spread + 1)) - (max_spread / 2);
+ qix->lines[0].p1.dy = (random () % (max_spread + 1)) - (max_spread / 2);
+ qix->lines[0].p2.dx = (random () % (max_spread + 1)) - (max_spread / 2);
+ qix->lines[0].p2.dy = (random () % (max_spread + 1)) - (max_spread / 2);
+ qix->lines[0].dead = True;
+ for (i = 1; i < qix->nlines; i++)
+ {
+ qix->lines[i] = qix->lines[0];
+ if (!mono_p && !transparent_p)
+ if (!XAllocColor (dpy, cmap, &qix->lines[i].color))
+ abort ();
+ }
+ return qix;
+}
+
+/* I don't believe this fucking language doesn't have builtin exponentiation.
+ I further can't believe that the fucking ^ character means fucking XOR!! */
+static int i_exp(i,j)
+ int i, j;
+{
+ int k = 1;
+ while (j--) k *= i;
+ return k;
+}
+
+
+static void
+merge_colors (argc, argv, into_color, mask, increment_p)
+ int argc;
+ XColor **argv;
+ XColor *into_color;
+ int mask;
+ Bool increment_p;
+{
+ int j;
+ *into_color = *argv [0];
+ into_color->pixel |= mask;
+#define SHORT_INC(x,y) (x = ((((x)+(y)) > 0xFFFF) ? 0xFFFF : ((x)+(y))))
+#define SHORT_DEC(x,y) (x = ((((x)-(y)) < 0) ? 0 : ((x)-(y))))
+ for (j = 1; j < argc; j++)
+ if (increment_p)
+ {
+ SHORT_INC (into_color->red, argv[j]->red);
+ SHORT_INC (into_color->green, argv[j]->green);
+ SHORT_INC (into_color->blue, argv[j]->blue);
+ }
+ else
+ {
+ SHORT_DEC (into_color->red, argv[j]->red);
+ SHORT_DEC (into_color->green, argv[j]->green);
+ SHORT_DEC (into_color->blue, argv[j]->blue);
+ }
+#undef SHORT_INC
+#undef SHORT_DEC
+}
+
+/* fill in all the permutations of colors that XAllocColorCells() has
+ allocated for us. Thanks Ron, you're an additive kind of guy. */
+static void
+permute_colors (pcolors, colors, count, plane_masks, increment_p)
+ XColor *pcolors, *colors;
+ int count;
+ unsigned long *plane_masks;
+ Bool increment_p;
+{
+ int out = 0;
+ int max = i_exp (2, count);
+ if (count > 31) abort ();
+ for (out = 1; out < max; out++)
+ {
+ XColor *argv [32];
+ int this_mask = 0;
+ int argc = 0;
+ int bit;
+ for (bit = 0; bit < 32; bit++)
+ if (out & (1<<bit))
+ {
+ argv [argc++] = &pcolors [bit];
+ this_mask |= plane_masks [bit];
+ }
+ merge_colors (argc, argv, &colors [out-1], this_mask, increment_p);
+ }
+}
+
+
+static struct qix **
+init_qix (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ int nlines;
+ struct qix **qixes;
+ XGCValues gcv;
+ XWindowAttributes xgwa;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ cmap = xgwa.colormap;
+ count = get_integer_resource ("count", "Integer");
+ if (count <= 0) count = 1;
+ nlines = get_integer_resource ("segments", "Integer");
+ if (nlines <= 0) nlines = 20;
+ get_geom (dpy, window);
+ max_spread = get_integer_resource ("spread", "Integer");
+ if (max_spread <= 0) max_spread = 10;
+ max_size = get_integer_resource ("size", "Integer");
+ if (max_size < 0) max_size = 0;
+ random_p = get_boolean_resource ("random", "Boolean");
+ solid_p = get_boolean_resource ("solid", "Boolean");
+ xor_p = get_boolean_resource ("xor", "Boolean");
+ transparent_p = get_boolean_resource ("transparent", "Boolean");
+ delay = get_integer_resource ("delay", "Integer");
+ color_shift = get_integer_resource ("colorShift", "Integer");
+ if (color_shift < 0 || color_shift >= 360) color_shift = 5;
+ if (delay < 0) delay = 0;
+
+ if (count == 1 && transparent_p)
+ transparent_p = False; /* it's a no-op */
+
+ if (transparent_p && CellsOfScreen (DefaultScreenOfDisplay (dpy)) <= 2)
+ {
+ fprintf (stderr, "%s: -transparent only works on color displays.\n",
+ progname);
+ transparent_p = False;
+ }
+
+ if (xor_p && !transparent_p)
+ mono_p = True;
+
+ gcs[0] = gcs[1] = 0;
+ gcv.foreground = default_fg_pixel =
+ get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+
+ if (transparent_p)
+ {
+ Bool increment_p = get_boolean_resource ("additive", "Boolean");
+ unsigned long plane_masks [32];
+ XColor *pcolors, *colors;
+ int nplanes = count;
+ int i, total_colors;
+
+ /* permutations would be harder if the number of planes didn't fit
+ in an int. Who has >32-bit displays anyway... */
+ if (nplanes > 31) nplanes = 31;
+
+ while (nplanes > 1 &&
+ !XAllocColorCells (dpy, cmap, False, plane_masks, nplanes,
+ &base_pixel, 1))
+ nplanes--;
+
+ if (nplanes <= 1)
+ {
+ fprintf (stderr,
+ "%s: couldn't allocate any color planes; turning -transparent off.\n",
+ progname);
+ transparent_p = False;
+ if (xor_p)
+ goto NON_TRANSPARENT_XOR;
+ else
+ goto NON_TRANSPARENT;
+ }
+ else if (nplanes != count)
+ {
+ fprintf (stderr,
+ "%s: only allocated %d color planes (instead of %d).\n",
+ progname, nplanes, count);
+ count = nplanes;
+ }
+
+ gcs[0] = (GC *) malloc (count * sizeof (GC));
+ gcs[1] = xor_p ? gcs[0] : (GC *) malloc (count * sizeof (GC));
+ total_colors = i_exp (2, count);
+ pcolors = (XColor *) calloc (count, sizeof (XColor));
+ colors = (XColor *) calloc (total_colors, sizeof (XColor));
+ for (i = 0; i < count; i++)
+ {
+ gcv.plane_mask = plane_masks [i];
+ gcv.foreground = ~0;
+ if (xor_p)
+ {
+ gcv.function = GXxor;
+ gcs [0][i] = XCreateGC (dpy, window,
+ GCForeground|GCFunction|GCPlaneMask,
+ &gcv);
+ }
+ else
+ {
+ gcs [0][i] = XCreateGC (dpy, window, GCForeground|GCPlaneMask,
+ &gcv);
+ gcv.foreground = 0;
+ gcs [1][i] = XCreateGC (dpy, window, GCForeground|GCPlaneMask,
+ &gcv);
+ }
+
+ /* pick the "primary" (not in that sense) colors.
+ If we are in subtractive mode, pick higher intensities. */
+ hsv_to_rgb (random () % 360, frand (1.0),
+ frand (0.5) + (increment_p ? 0.2 : 0.5),
+ &pcolors[i].red, &pcolors[i].green, &pcolors[i].blue);
+
+ pcolors [i].flags = DoRed | DoGreen | DoBlue;
+ pcolors [i].pixel = base_pixel | plane_masks [i];
+ }
+ permute_colors (pcolors, colors, count, plane_masks, increment_p);
+ /* clone the default background of the window into our "base" pixel */
+ colors [total_colors - 1].pixel =
+ get_pixel_resource ("background", "Background", dpy, cmap);
+ XQueryColor (dpy, cmap, &colors [total_colors - 1]);
+ colors [total_colors - 1].pixel = base_pixel;
+ XStoreColors (dpy, cmap, colors, total_colors);
+ XSetWindowBackground (dpy, window, base_pixel);
+ XClearWindow (dpy, window);
+ }
+ else if (xor_p)
+ {
+ NON_TRANSPARENT_XOR:
+ gcv.function = GXxor;
+ gcv.foreground =
+ (default_fg_pixel ^ get_pixel_resource ("background", "Background",
+ dpy, cmap));
+ draw_gc = erase_gc = XCreateGC(dpy,window,GCForeground|GCFunction,&gcv);
+ }
+ else
+ {
+ NON_TRANSPARENT:
+ draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+ gcv.foreground = get_pixel_resource ("background", "Background",
+ dpy, cmap);
+ erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+ }
+
+ qixes = (struct qix **) malloc ((count + 1) * sizeof (struct qix *));
+ qixes [count] = 0;
+ while (count--)
+ {
+ qixes [count] = init_one_qix (dpy, window, nlines);
+ qixes [count]->id = count;
+ }
+ return qixes;
+}
+
+static void
+free_qline (dpy, window, cmap, qline, prev, qix)
+ Display *dpy;
+ Window window;
+ Colormap cmap;
+ struct qline *qline, *prev;
+ struct qix *qix;
+{
+ if (qline->dead || !prev)
+ ;
+ else if (solid_p)
+ {
+ XPoint points [4];
+ points [0].x = qline->p1.x; points [0].y = qline->p1.y;
+ points [1].x = qline->p2.x; points [1].y = qline->p2.y;
+ points [2].x = prev->p2.x; points [2].y = prev->p2.y;
+ points [3].x = prev->p1.x; points [3].y = prev->p1.y;
+ XFillPolygon (dpy, window, (transparent_p ? gcs[1][qix->id] : erase_gc),
+ points, 4, Complex, CoordModeOrigin);
+ }
+ else
+ XDrawLine (dpy, window, (transparent_p ? gcs[1][qix->id] : erase_gc),
+ qline->p1.x, qline->p1.y, qline->p2.x, qline->p2.y);
+
+ if (!mono_p && !transparent_p)
+ XFreeColors (dpy, cmap, &qline->color.pixel, 1, 0);
+
+ qline->dead = True;
+}
+
+static void
+add_qline (dpy, window, cmap, qline, prev_qline, qix)
+ Display *dpy;
+ Window window;
+ Colormap cmap;
+ struct qline *qline, *prev_qline;
+ struct qix *qix;
+{
+ *qline = *prev_qline;
+
+#define wiggle(point,delta,max) \
+ if (random_p) delta += (random () % 3) - 1; \
+ if (delta > max_spread) delta = max_spread; \
+ else if (delta < -max_spread) delta = -max_spread; \
+ point += delta; \
+ if (point < 0) point = 0, delta = -delta, point += delta<<1; \
+ else if (point > max) point = max, delta = -delta, point += delta<<1;
+
+ wiggle (qline->p1.x, qline->p1.dx, maxx);
+ wiggle (qline->p1.y, qline->p1.dy, maxy);
+ wiggle (qline->p2.x, qline->p2.dx, maxx);
+ wiggle (qline->p2.y, qline->p2.dy, maxy);
+
+ if (max_size)
+ {
+ if (qline->p1.x - qline->p2.x > max_size)
+ qline->p1.x = qline->p2.x + max_size
+ - (random_p ? random() % max_spread : 0);
+ else if (qline->p2.x - qline->p1.x > max_size)
+ qline->p2.x = qline->p1.x + max_size
+ - (random_p ? random() % max_spread : 0);
+ if (qline->p1.y - qline->p2.y > max_size)
+ qline->p1.y = qline->p2.y + max_size
+ - (random_p ? random() % max_spread : 0);
+ else if (qline->p2.y - qline->p1.y > max_size)
+ qline->p2.y = qline->p1.y + max_size
+ - (random_p ? random() % max_spread : 0);
+ }
+
+ if (!mono_p && !transparent_p)
+ {
+ cycle_hue (&qline->color, color_shift);
+ qline->color.flags = DoRed | DoGreen | DoBlue;
+ if (!XAllocColor (dpy, cmap, &qline->color))
+ {
+ qline->color = prev_qline->color;
+ if (!XAllocColor (dpy, cmap, &qline->color))
+ abort (); /* same color should work */
+ }
+ XSetForeground (dpy, draw_gc, qline->color.pixel);
+ }
+ if (! solid_p)
+ XDrawLine (dpy, window, (transparent_p ? gcs[0][qix->id] : draw_gc),
+ qline->p1.x, qline->p1.y, qline->p2.x, qline->p2.y);
+ else if (!prev_qline->dead)
+ {
+ XPoint points [4];
+ points [0].x = qline->p1.x; points [0].y = qline->p1.y;
+ points [1].x = qline->p2.x; points [1].y = qline->p2.y;
+ points [2].x = prev_qline->p2.x; points [2].y = prev_qline->p2.y;
+ points [3].x = prev_qline->p1.x; points [3].y = prev_qline->p1.y;
+ XFillPolygon (dpy, window, (transparent_p ? gcs[0][qix->id] : draw_gc),
+ points, 4, Complex, CoordModeOrigin);
+ }
+
+ qline->dead = False;
+}
+
+static void
+qix1 (dpy, window, qix)
+ Display *dpy;
+ Window window;
+ struct qix *qix;
+{
+ int ofp = qix->fp - 1;
+ static int gtick = 0;
+ if (gtick++ == 500)
+ get_geom (dpy, window), gtick = 0;
+ if (ofp < 0) ofp = qix->nlines - 1;
+ free_qline (dpy, window, cmap, &qix->lines [qix->fp],
+ &qix->lines[(qix->fp + 1) % qix->nlines], qix);
+ add_qline (dpy, window, cmap, &qix->lines[qix->fp], &qix->lines[ofp], qix);
+ if ((++qix->fp) >= qix->nlines)
+ qix->fp = 0;
+}
+
+\f
+char *progclass = "Qix";
+
+char *defaults [] = {
+ "*background: black",
+ "*foreground: white",
+ "*count: 1",
+ "*segments: 50",
+ "*spread: 8",
+ "*size: 0",
+ "*colorShift: 3",
+ "*solid: false",
+ "*delay: 10000",
+ "*random: true",
+ "*xor: false",
+ "*transparent:false",
+ "*additive: true",
+ 0
+};
+
+XrmOptionDescRec options [] = {
+ { "-count", ".count", XrmoptionSepArg, 0 },
+ { "-segments", ".segments", XrmoptionSepArg, 0 },
+ { "-spread", ".spread", XrmoptionSepArg, 0 },
+ { "-size", ".size", XrmoptionSepArg, 0 },
+ { "-delay", ".delay", XrmoptionSepArg, 0 },
+ { "-color-shift", ".colorShift", XrmoptionSepArg, 0 },
+ { "-random", ".random", XrmoptionNoArg, "true" },
+ { "-linear", ".random", XrmoptionNoArg, "false" },
+ { "-solid", ".solid", XrmoptionNoArg, "true" },
+ { "-hollow", ".solid", XrmoptionNoArg, "false" },
+ { "-xor", ".xor", XrmoptionNoArg, "true" },
+ { "-no-xor", ".xor", XrmoptionNoArg, "false" },
+ { "-transparent", ".transparent", XrmoptionNoArg, "true" },
+ { "-non-transparent", ".transparent", XrmoptionNoArg, "false" },
+ { "-additive", ".additive", XrmoptionNoArg, "true" },
+ { "-subtractive", ".additive", XrmoptionNoArg, "false" },
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ struct qix **q1 = init_qix (dpy, window);
+ struct qix **qn;
+ while (1)
+ for (qn = q1; *qn; qn++)
+ {
+ qix1 (dpy, window, *qn);
+ XSync (dpy, True);
+ if (delay) usleep (delay);
+ }
+}
--- /dev/null
+.TH XScreenSaver 1 "9-dec-92" "X Version 11"
+.SH NAME
+qix - bounce colored lines around a window
+.SH SYNOPSIS
+.B qix
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-segments \fIint\fP] [\-spread \fIpixels\fP] [\-size \fIpixels\fP] [\-count \fIint\fP] [\-color-shift \fIdegrees\fP] [\-delay \fIusecs\fP] [\-random] [\-linear] [\-solid] [\-hollow] [\-xor] [\-no\-xor] [\-transparent] [\-non\-transparent] [\-additive] [\-subtractive]
+.SH DESCRIPTION
+The \fIqix\fP program bounces a series of line segments around its window.
+This is truly the swiss army chainsaw of qix programs. If you know of one
+with more display modes, I want to know about it.
+.SH OPTIONS
+.I qix
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-segments integer
+How many line segments should be drawn. Default 50.
+.TP 8
+.B \-spread integer
+How far apart the endpoints of one segment should be from the next.
+Default 8.
+.TP 8
+.B \-size integer
+The maximum distance one endpoint of a segment is allowed to be from
+the opposite end of that segment. Default 0, meaning unlimited.
+.TP 8
+.B \-count integer
+How many qixes to draw. Default 1.
+.TP 8
+.B \-color\-shift degrees
+If on a color display, the color of the line segments will cycle through
+the spectrum. This specifies how far the hue of each segment should be
+from the next, in degrees on the HSV wheel. Default 3.
+.TP 8
+.B \-delay microseconds
+How much of a delay should be introduced between steps of the animation.
+Default 25000, or about 0.025 seconds.
+.TP 8
+.B \-random
+The \fIqix\fP will wander around the screen semi-randomly. This is the
+default.
+.TP 8
+.B \-linear
+The opposite of \fI\-random\fP: the \fIqix\fP will travel in straight lines
+until it reaches a wall, and then it will bounce.
+.TP 8
+.B \-solid
+If this is specified, then the area between the line segments will be filled
+in with the appropriate color, instead of the \fIqix\fP simply being composed
+of one-pixel-wide line segments. This option looks really good in color.
+.TP 8
+.B \-hollow
+The opposite of \fI\-solid\fP; this is the default.
+.TP 8
+.B \-xor
+If this is specified, then qix segments will be drawn and erased with xor,
+instead of being drawn in some color and erased in the background color.
+This implies \fI\-mono\fP, in that only two colors can be used.
+.TP 8
+.B \-transparent
+If this is specified, and \fI\-count\fP is greater than 1, then each qix
+will be drawn in one color, and when they overlap, the colors will be mixed.
+This only works on \fBPseudoColor\fP displays. This looks best in
+conjuction with \fI\-solid\fP.
+.TP 8
+.B \-non\-transparent
+Turns off \fI\-transparent\fP.
+.TP 8
+.B \-additive
+If \fI\-transparent\fP is specified, then this option means that the colors
+will be mixed using an additive color model, as if the qixes were projected
+light. This is the default.
+.TP 8
+.B \-subtractive
+If \fI\-transparent\fP is specified, then this option means that the
+colors will be mixed using a subtractive color model, as if the qixes were
+translucent filters.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1992 by Jamie Zawinski. Permission to use, copy, modify,
+distribute, and sell this software and its documentation for any purpose is
+hereby granted without fee, provided that the above copyright notice appear
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation. No representations are made about the
+suitability of this software for any purpose. It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@lucid.com>, 13-aug-92.
--- /dev/null
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+/* Flying through an asteroid field. Based on TI Explorer Lisp code by
+ John Nguyen <johnn@hx.lcs.mit.edu>
+ */
+
+#include "screenhack.h"
+#include <stdio.h>
+#include <math.h>
+#if __STDC__
+#include <values.h>
+#endif
+
+#define MIN_DEPTH 2 /* rocks disappar when they get this close */
+#define MAX_DEPTH 60 /* this is where rocks appear */
+#define MAX_WIDTH 100 /* how big (in pixels) rocks are at depth 1 */
+#define DEPTH_SCALE 100 /* how many ticks there are between depths */
+#define SIN_RESOLUTION 1000
+
+/* there's not much point in the above being user-customizable, but those
+ numbers might want to be tweaked for displays with an order of magnitude
+ higher resolution or compute power.
+ */
+
+static double sins [SIN_RESOLUTION];
+static double coss [SIN_RESOLUTION];
+static double depths [(MAX_DEPTH + 1) * DEPTH_SCALE];
+
+static Display *dpy;
+static Window window;
+static int width, height, midx, midy;
+static GC draw_gc, erase_gc;
+static Bool rotate_p ;
+
+static int speed;
+
+struct rock {
+ int real_size;
+ int r;
+ int theta;
+ int depth;
+ int size, x, y;
+};
+
+static struct rock *rocks;
+static int nrocks;
+static Pixmap pixmaps [MAX_WIDTH];
+static int delay;
+
+static void rock_reset(), rock_tick(), rock_compute(), rock_draw();
+static void init_pixmaps(), init_rocks(), tick_rocks(), rocks_once();
+
+
+static void
+rock_reset (rock)
+ struct rock *rock;
+{
+ rock->real_size = MAX_WIDTH;
+ rock->r = (SIN_RESOLUTION * 0.7) + (random () % (30 * SIN_RESOLUTION));
+ rock->theta = random () % SIN_RESOLUTION;
+ rock->depth = MAX_DEPTH * DEPTH_SCALE;
+ rock_compute (rock);
+ rock_draw (rock, True);
+}
+
+static void
+rock_tick (rock, d)
+ struct rock *rock;
+ int d;
+{
+ if (rock->depth > 0)
+ {
+ rock_draw (rock, False);
+ rock->depth -= speed;
+ if (rotate_p)
+ {
+ rock->theta = (rock->theta + d) % SIN_RESOLUTION;
+ }
+ while (rock->theta < 0)
+ rock->theta += SIN_RESOLUTION;
+ if (rock->depth < (MIN_DEPTH * DEPTH_SCALE))
+ rock->depth = 0;
+ else
+ {
+ rock_compute (rock);
+ rock_draw (rock, True);
+ }
+ }
+ else if ((random () % 40) == 0)
+ rock_reset (rock);
+}
+
+static void
+rock_compute (rock)
+ struct rock *rock;
+{
+ double factor = depths [rock->depth];
+ rock->size = (int) ((rock->real_size * factor) + 0.5);
+ rock->x = midx + (coss [rock->theta] * rock->r * factor);
+ rock->y = midy + (sins [rock->theta] * rock->r * factor);
+}
+
+static void
+rock_draw (rock, draw_p)
+ struct rock *rock;
+ Bool draw_p;
+{
+ GC gc = draw_p ? draw_gc : erase_gc;
+ if (rock->x <= 0 || rock->y <= 0 || rock->x >= width || rock->y >= height)
+ {
+ /* this means that if a rock were to go off the screen at 12:00, but
+ would have been visible at 3:00, it won't come back once the observer
+ rotates around so that the rock would have been visible again.
+ Oh well.
+ */
+ rock->depth = 0;
+ return;
+ }
+ if (rock->size <= 1)
+ XDrawPoint (dpy, window, gc, rock->x, rock->y);
+ else if (rock->size <= 3 || !draw_p)
+ XFillRectangle (dpy, window, gc,
+ rock->x - rock->size/2, rock->y - rock->size/2,
+ rock->size, rock->size);
+ else if (rock->size < MAX_WIDTH)
+ XCopyPlane (dpy, pixmaps [rock->size], window, gc,
+ 0, 0, rock->size, rock->size,
+ rock->x - rock->size/2, rock->y - rock->size/2,
+ 1);
+ else
+ abort ();
+}
+
+
+static void
+init_pixmaps (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ int i;
+ XGCValues gcv;
+ GC fg_gc = 0, bg_gc;
+ pixmaps [0] = pixmaps [1] = 0;
+ for (i = MIN_DEPTH; i < MAX_WIDTH; i++)
+ {
+ int w = (1+(i/32))<<5; /* server might be faster if word-aligned */
+ int h = i;
+ Pixmap p = XCreatePixmap (dpy, window, w, h, 1);
+ XPoint points [7];
+ pixmaps [i] = p;
+ if (! p)
+ {
+ fprintf (stderr, "%s: couldn't allocate pixmaps", progname);
+ exit (1);
+ }
+ if (! fg_gc)
+ { /* must use drawable of pixmap, not window (fmh) */
+ gcv.foreground = 1;
+ fg_gc = XCreateGC (dpy, p, GCForeground, &gcv);
+ gcv.foreground = 0;
+ bg_gc = XCreateGC (dpy, p, GCForeground, &gcv);
+ }
+ XFillRectangle (dpy, p, bg_gc, 0, 0, w, h);
+ points [0].x = i * 0.15; points [0].y = i * 0.85;
+ points [1].x = i * 0.00; points [1].y = i * 0.20;
+ points [2].x = i * 0.30; points [2].y = i * 0.00;
+ points [3].x = i * 0.40; points [3].y = i * 0.10;
+ points [4].x = i * 0.90; points [4].y = i * 0.10;
+ points [5].x = i * 1.00; points [5].y = i * 0.55;
+ points [6].x = i * 0.45; points [6].y = i * 1.00;
+ XFillPolygon (dpy, p, fg_gc, points, 7, Nonconvex, CoordModeOrigin);
+ }
+ XFreeGC (dpy, fg_gc);
+ XFreeGC (dpy, bg_gc);
+}
+
+
+static void
+init_rocks (d, w)
+ Display *d;
+ Window w;
+{
+ int i;
+ XGCValues gcv;
+ Colormap cmap;
+ XWindowAttributes xgwa;
+ unsigned int fg, bg;
+ dpy = d;
+ window = w;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ cmap = xgwa.colormap;
+ delay = get_integer_resource ("delay", "Integer");
+ if (delay < 0) delay = 0;
+ speed = get_integer_resource ("speed", "Integer");
+ if (speed < 1) speed = 1;
+ if (speed > 100) speed = 100;
+ rotate_p = get_boolean_resource ("rotate", "Boolean");
+ fg = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+ bg = get_pixel_resource ("background", "Background", dpy, cmap);
+ gcv.foreground = fg;
+ gcv.background = bg;
+ draw_gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
+ gcv.foreground = bg;
+ gcv.background = fg;
+ erase_gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
+
+ for (i = 0; i < SIN_RESOLUTION; i++)
+ {
+ sins [i] = sin ((((double) i) / (SIN_RESOLUTION / 2)) * M_PI);
+ coss [i] = cos ((((double) i) / (SIN_RESOLUTION / 2)) * M_PI);
+ }
+ /* we actually only need i/speed of these, but wtf */
+ for (i = 1; i < (sizeof (depths) / sizeof (depths[0])); i++)
+ depths [i] = atan (((double) 0.5) / (((double) i) / DEPTH_SCALE));
+ depths [0] = M_PI/2; /* avoid division by 0 */
+
+ nrocks = get_integer_resource ("count", "Count");
+ if (nrocks < 1) nrocks = 1;
+ rocks = (struct rock *) calloc (nrocks, sizeof (struct rock));
+ init_pixmaps (dpy, window);
+ XClearWindow (dpy, window);
+}
+
+
+static void
+tick_rocks (d)
+ int d;
+{
+ int i;
+ for (i = 0; i < nrocks; i++)
+ rock_tick (&rocks [i], d);
+}
+
+static void
+rocks_once ()
+{
+ static int current_delta = 0; /* observer Z rotation */
+ static int window_tick = 50;
+
+ if (window_tick++ == 50)
+ {
+ XWindowAttributes xgwa;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ window_tick = 0;
+ width = xgwa.width;
+ height = xgwa.height;
+ midx = width/2;
+ midy = height/2;
+ }
+
+ if ((random () % 50) == 0)
+ {
+ int d = current_delta;
+ int new_delta = ((random () % 11) - 5);
+ if ((random () % 10) == 0)
+ new_delta *= 5;
+
+ while (d == current_delta)
+ {
+ int i;
+ for (i = 0; i < 3; i++)
+ tick_rocks (d);
+ if (current_delta < new_delta) d++;
+ else d--;
+ }
+ current_delta = new_delta;
+ }
+ tick_rocks (current_delta);
+}
+
+\f
+char *progclass = "Rocks";
+
+char *defaults [] = {
+ "*background: black",
+ "*foreground: white",
+ "*count: 100",
+ "*delay: 50000",
+ "*speed: 100",
+ "*rotate: true",
+ 0
+};
+
+XrmOptionDescRec options [] = {
+ { "-count", ".count", XrmoptionSepArg, 0 },
+ { "-norotate", ".rotate", XrmoptionNoArg, "false" },
+ { "-delay", ".delay", XrmoptionSepArg, 0 },
+ { "-speed", ".speed", XrmoptionSepArg, 0 }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ init_rocks (dpy, window);
+ while (1)
+ {
+ rocks_once ();
+ XSync (dpy, True);
+ if (delay) usleep (delay);
+ }
+}
--- /dev/null
+.TH XScreenSaver 1 "13-aug-92" "X Version 11"
+.SH NAME
+rocks - animation of flying through an asteroid field
+.SH SYNOPSIS
+.B rocks
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-count \fIinteger\fP] [\-delay \fIusecs\fP] [\-speed \fIinteger\fP] [\-norotate]
+.SH DESCRIPTION
+The \fIrocks\fP program draws an animation of an asteroid field moving past
+the observer (or vice versa). Sometimes the observer picks up spin on Z axis.
+.SH OPTIONS
+.I rocks
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-count integer
+Maximum number of rocks to draw on the screen at once. Default 100.
+.TP 8
+.B \-speed integer
+A measure of the speed with which the observer and the rocks pass each other,
+from 1 to 100. Default 100, meaning ``very fast.'' If you're on a slow
+display connection (the animation looks jerky) then try making this number
+smaller, and/or decreasing the number of rocks.
+.TP 8
+.B \-delay microseconds
+Number of microseconds to delay between each frame. Default 50000, meaning
+about 1/20th second. Compare and contrast with \fI\-speed\fP, above.
+.TP 8
+.B \-norotate
+Don't rotate the observer; just fly straight through the field.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH BUGS
+There should be an option to display doppler shift (a gravity rainbow.)
+
+Speed of rotation should be settable.
+
+Default speed of rotation should be relative to forward velocity.
+.SH COPYRIGHT
+Copyright \(co 1992 by Jamie Zawinski. Permission to use, copy, modify,
+distribute, and sell this software and its documentation for any purpose is
+hereby granted without fee, provided that the above copyright notice appear
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation. No representations are made about the
+suitability of this software for any purpose. It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Based on Lisp Machine code copyright 1988 John Nguyen <johnn@hx.lcs.mit.edu>.
+
+Ported to C and X by Jamie Zawinski <jwz@lucid.com>, 13-aug-92.
--- /dev/null
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#include "screenhack.h"
+
+static GC draw_gc, erase_gc;
+static unsigned int default_fg_pixel;
+static int iterations, offset;
+static Bool xsym, ysym;
+
+static void
+init_rorschach (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ XGCValues gcv;
+ Colormap cmap;
+ XWindowAttributes xgwa;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ cmap = xgwa.colormap;
+ gcv.foreground = default_fg_pixel =
+ get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+ draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+ gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
+ erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+ iterations = get_integer_resource ("iterations", "Integer");
+ offset = get_integer_resource ("offset", "Integer");
+ if (offset <= 0) offset = 3;
+ if (iterations < 10) iterations = 10;
+ xsym = get_boolean_resource ("xsymmetry", "Symmetry");
+ ysym = get_boolean_resource ("ysymmetry", "Symmetry");
+}
+
+static void
+hurm (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ Colormap cmap;
+ XWindowAttributes xgwa;
+ int xlim, ylim, x, y, i, got_color = 0;
+ XPoint points [4];
+ XColor color;
+ XClearWindow (dpy, window);
+ XGetWindowAttributes (dpy, window, &xgwa);
+ xlim = xgwa.width;
+ ylim = xgwa.height;
+ cmap = xgwa.colormap;
+
+ if (! mono_p)
+ hsv_to_rgb (random()%360, 1.0, 1.0, &color.red, &color.green, &color.blue);
+ if ((!mono_p) && (got_color = XAllocColor (dpy, cmap, &color)))
+ XSetForeground (dpy, draw_gc, color.pixel);
+ else
+ XSetForeground (dpy, draw_gc, default_fg_pixel);
+
+ x = xlim/2;
+ y = ylim/2;
+ for (i = 0; i < iterations; i++)
+ {
+ int j = 0;
+ x += ((random () % (1 + (offset << 1))) - offset);
+ y += ((random () % (1 + (offset << 1))) - offset);
+ points [j].x = x;
+ points [j].y = y;
+ j++;
+ if (xsym)
+ {
+ points [j].x = xlim - x;
+ points [j].y = y;
+ j++;
+ }
+ if (ysym)
+ {
+ points [j].x = x;
+ points [j].y = ylim - y;
+ j++;
+ }
+ if (xsym && ysym)
+ {
+ points [j].x = xlim - x;
+ points [j].y = ylim - y;
+ j++;
+ }
+ XDrawPoints (dpy, window, draw_gc, points, j, CoordModeOrigin);
+ XSync (dpy, True);
+ }
+ sleep (5);
+ for (i = 0; i < (ylim >> 1); i++)
+ {
+ int y = (random () % ylim);
+ XDrawLine (dpy, window, erase_gc, 0, y, xlim, y);
+ XFlush (dpy);
+ if ((i % 50) == 0)
+ usleep (10000);
+ }
+ XClearWindow (dpy, window);
+ if (got_color) XFreeColors (dpy, cmap, &color.pixel, 1, 0);
+ XSync (dpy, True);
+ sleep (1);
+}
+
+\f
+char *progclass = "Rorschach";
+
+char *defaults [] = {
+ "*background: black",
+ "*foreground: white",
+ "*xsymmetry: true",
+ "*ysymmetry: false",
+ "*iterations: 4000",
+ "*offset: 4",
+ 0
+};
+
+XrmOptionDescRec options [] = {
+ { "-iterations", ".iterations", XrmoptionSepArg, 0 },
+ { "-offset", ".offset", XrmoptionSepArg, 0 },
+ { "-xsymmetry", ".xsymmetry", XrmoptionNoArg, "true" },
+ { "-ysymmetry", ".ysymmetry", XrmoptionNoArg, "true" }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ init_rorschach (dpy, window);
+ while (1)
+ hurm (dpy, window);
+}
--- /dev/null
+.TH XScreenSaver 1 "13-aug-92" "X Version 11"
+.SH NAME
+rorschach - simulate ink-blot patterns
+.SH SYNOPSIS
+.B rorschach
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-iterations \fIinteger\fP] [\-offset \fIinteger\fP] [\-xsymmetry] [\-ysymmetry]
+.SH DESCRIPTION
+The \fIrorschach\fP program draws random patterns reminiscent of the
+psychological test of same name.
+.SH OPTIONS
+.I rorschach
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono
+If on a color display, pretend we're on a monochrome display.
+.TP 8
+.B \-iterations integer
+How many dots should be drawn each time. Default 4000.
+.TP 8
+.B \-offset integer
+How far apart the dots should be. Default 4 pixels.
+.TP 8
+.B \-xsymmetry
+Whether the images should be horizontally symmetrical. Default true.
+.TP 8
+.B \-ysymmetry
+Whether the images should be vertically symmetrical. Default false.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH BUGS
+May call your sanity into question.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1992 by Jamie Zawinski. Permission to use, copy, modify,
+distribute, and sell this software and its documentation for any purpose is
+hereby granted without fee, provided that the above copyright notice appear
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation. No representations are made about the
+suitability of this software for any purpose. It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@lucid.com>, 13-aug-92.
--- /dev/null
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * And remember: X Windows is to graphics hacking as roman numerals are to
+ * the square root of pi.
+ */
+
+/* This file contains simple code to open a window or draw on the root.
+ The idea being that, when writing a graphics hack, you can just link
+ with this .o to get all of the uninteresting junk out of the way.
+
+ - create a procedure `screenhack(dpy, window)'
+
+ - create a variable `char *progclass' which names this program's
+ resource class.
+
+ - create a variable `char defaults []' for the default resources.
+
+ - create a variable `XrmOptionDescRec options []' for the command-line,
+ and `int options_size' which is `XtNumber (options)'.
+
+ And that's it...
+ */
+
+#include "version.h"
+
+#include <stdio.h>
+#include <X11/Intrinsic.h>
+#include <X11/IntrinsicP.h>
+#include <X11/CoreP.h>
+#include <X11/Xmu/Error.h>
+#include "screenhack.h"
+
+char *progname;
+XrmDatabase db;
+Bool mono_p;
+
+
+static XrmOptionDescRec default_options [] = {
+ { "-root", ".root", XrmoptionNoArg, "True" },
+ { "-window", ".root", XrmoptionNoArg, "False" },
+ { "-mono", ".mono", XrmoptionNoArg, "True" },
+ { "-install", ".installColormap", XrmoptionNoArg, "True" }
+};
+
+static char *default_defaults[] = {
+ "*root: false",
+ "*geometry: 500x500", /* this should be .geometry, but nooooo... */
+ "*mono: false",
+ "*installColormap: false",
+ 0
+};
+
+static XrmOptionDescRec *merged_options;
+static int merged_options_size;
+static char **merged_defaults;
+
+static void
+merge_options ()
+{
+ int options_sizeof = options_size * sizeof (options[0]);
+ int defaults_size;
+ merged_options_size = XtNumber (default_options) + options_size;
+ merged_options = (XrmOptionDescRec *)
+ malloc (sizeof (default_options) + options_sizeof);
+ bcopy (options, merged_options, options_sizeof);
+ bcopy (default_options, merged_options + options_size,
+ sizeof (default_options));
+
+ for (defaults_size = 0; defaults [defaults_size]; defaults_size++);
+ merged_defaults = (char **)
+ malloc (sizeof (default_defaults) + (defaults_size * sizeof (char *)));
+ bcopy (default_defaults, merged_defaults, sizeof (default_defaults));
+ bcopy (defaults, merged_defaults - 1 +
+ (sizeof (default_defaults) / sizeof (default_defaults[0])),
+ ((defaults_size + 1) * sizeof (defaults[0])));
+}
+
+\f
+/* Make the X errors print out the name of this program, so we have some
+ clue which one has a bug when they die under the screensaver.
+ */
+
+static int
+screenhack_ehandler (dpy, error)
+ Display *dpy;
+ XErrorEvent *error;
+{
+ fprintf (stderr, "\nX error in %s:\n", progname);
+ if (XmuPrintDefaultErrorMessage (dpy, error, stderr))
+ exit (-1);
+ else
+ fprintf (stderr, " (nonfatal.)\n");
+ return 0;
+}
+
+static Bool
+MapNotify_event_p (dpy, event, window)
+ Display *dpy;
+ XEvent *event;
+ XPointer window;
+{
+ return (event->xany.type == MapNotify &&
+ event->xvisibility.window == (Window) window);
+}
+
+
+void
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ XtAppContext app;
+ Widget toplevel;
+ Display *dpy;
+ Window window;
+ Colormap cmap;
+ Bool root_p;
+ XEvent event;
+
+ merge_options ();
+ toplevel = XtAppInitialize (&app, progclass, merged_options,
+ merged_options_size, &argc, argv,
+ merged_defaults, 0, 0);
+ dpy = XtDisplay (toplevel);
+ db = XtDatabase (dpy);
+ XtGetApplicationNameAndClass (dpy, &progname, &progclass);
+ XSetErrorHandler (screenhack_ehandler);
+ if (argc > 1)
+ {
+ int i;
+ int x = 18;
+ int end = 78;
+ fprintf (stderr, "%s: unrecognised option \"%s\"\n", progname, argv[1]);
+ fprintf (stderr, "Options include: ");
+ for (i = 0; i < merged_options_size; i++)
+ {
+ char *sw = merged_options [i].option;
+ Bool argp = (merged_options [i].argKind == XrmoptionSepArg);
+ int size = strlen (sw) + (argp ? 6 : 0) + 2;
+ if (x + size >= end)
+ {
+ fprintf (stderr, "\n\t\t ");
+ x = 18;
+ }
+ x += size;
+ fprintf (stderr, "%s", sw);
+ if (argp) fprintf (stderr, " <arg>");
+ if (i != merged_options_size - 1) fprintf (stderr, ", ");
+ }
+ fprintf (stderr, ".\n");
+ exit (1);
+ }
+
+ mono_p = get_boolean_resource ("mono", "Boolean");
+ if (CellsOfScreen (DefaultScreenOfDisplay (dpy)) <= 2)
+ mono_p = True;
+
+ root_p = get_boolean_resource ("root", "Boolean");
+ if (root_p)
+ {
+ XWindowAttributes xgwa;
+ window = RootWindowOfScreen (XtScreen (toplevel));
+ XtDestroyWidget (toplevel);
+ XGetWindowAttributes (dpy, window, &xgwa);
+ cmap = xgwa.colormap;
+ }
+ else
+ {
+ XtRealizeWidget (toplevel);
+ window = XtWindow (toplevel);
+ if (get_boolean_resource ("installColormap", "InstallColormap"))
+ {
+ cmap = XCreateColormap (dpy, window,
+ DefaultVisualOfScreen (XtScreen (toplevel)),
+ AllocNone);
+ XSetWindowColormap (dpy, window, cmap);
+ }
+ else
+ cmap = DefaultColormap (dpy, DefaultScreen (dpy));
+ }
+ if (!get_boolean_resource ("dontClearWindow", "Boolean")) /* kludge-o-rama */
+ {
+ XSetWindowBackground (dpy, window,
+ get_pixel_resource ("background", "Background",
+ dpy, cmap));
+ XClearWindow (dpy, window);
+ }
+
+ if (!root_p && toplevel->core.mapped_when_managed)
+ /* wait for it to be mapped */
+ XIfEvent (dpy, &event, MapNotify_event_p, (XPointer) window);
+
+ XSync (dpy, False);
+ srandom ((int) time ((time_t *) 0));
+ screenhack (dpy, window);
+}
--- /dev/null
+
+#if 0
+ * Found in Don Hopkin`s .plan file:
+ *
+ * The color situation is a total flying circus. The X approach to
+ * device independence is to treat everything like a MicroVax framebuffer
+ * on acid. A truely portable X application is required to act like the
+ * persistent customer in the Monty Python ``Cheese Shop'' sketch. Even
+ * the simplest applications must answer many difficult questions, like:
+ *
+ * WHAT IS YOUR DISPLAY?
+ * display = XOpenDisplay("unix:0");
+ * WHAT IS YOUR ROOT?
+ * root = RootWindow(display, DefaultScreen(display));
+ * AND WHAT IS YOUR WINDOW?
+ * win = XCreateSimpleWindow(display, root, 0, 0, 256, 256, 1,
+ * BlackPixel(display, DefaultScreen(display)),
+ * WhitePixel(display, DefaultScreen(display)))
+ * OH ALL RIGHT, YOU CAN GO ON.
+ *
+ * WHAT IS YOUR DISPLAY?
+ * display = XOpenDisplay("unix:0");
+ * WHAT IS YOUR COLORMAP?
+ * cmap = DefaultColormap(display, DefaultScreen(display));
+ * AND WHAT IS YOUR FAVORITE COLOR?
+ * favorite_color = 0; /* Black. */
+ * /* Whoops! No, I mean: */
+ * favorite_color = BlackPixel(display, DefaultScreen(display));
+ * /* AAAYYYYEEEEE!! (client dumps core & falls into the chasm) */
+ *
+ * WHAT IS YOUR DISPLAY?
+ * display = XOpenDisplay("unix:0");
+ * WHAT IS YOUR VISUAL?
+ * struct XVisualInfo vinfo;
+ * if (XMatchVisualInfo(display, DefaultScreen(display),
+ * 8, PseudoColor, &vinfo) != 0)
+ * visual = vinfo.visual;
+ * AND WHAT IS THE NET SPEED VELOCITY OF AN XConfigureWindow REQUEST?
+ * /* Is that a SubStructureRedirectMask or a ResizeRedirectMask? */
+ * WHAT??! HOW AM I SUPPOSED TO KNOW THAT?
+ * AAAAUUUGGGHHH!!!! (server dumps core & falls into the chasm)
+ *
+#endif /* 0 */
+
+#ifndef _SCREENHACK_H_
+#define _SCREENHACK_H_
+
+#if __STDC__
+#include <stdlib.h>
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/Xresource.h>
+#include <X11/Xos.h>
+#include "vroot.h"
+
+extern Bool mono_p;
+extern char *progname;
+extern char *progclass;
+extern XrmDatabase db;
+extern XrmOptionDescRec options [];
+extern int options_size;
+extern char *defaults [];
+
+#if __STDC__
+
+# define bcopy(from,to,size) memcpy((to),(from),(size))
+# define bzero(addr,size) memset((addr),0,(size))
+
+# if defined(SVR4) || defined(SYSV)
+extern int rand (void);
+extern void srand (unsigned int);
+# define random() rand()
+# define srandom(i) srand((unsigned int)(i))
+# else /* !totally-losing-SYSV */
+extern long random (void);
+extern void srandom (int);
+# endif /* !totally-losing-SYSV */
+#endif /* __STDC__ */
+
+#if __STDC__
+# define P(x)x
+#else
+# define P(x)()
+#endif
+
+extern void screenhack P((Display*,Window));
+
+#define usleep screenhack_usleep
+
+extern void screenhack_usleep P((unsigned long));
+extern char *get_string_resource P((char*,char*));
+extern Bool get_boolean_resource P((char*,char*));
+extern int get_integer_resource P((char*,char*));
+extern double get_float_resource P((char*,char*));
+extern unsigned int get_pixel_resource P((char*,char*,Display*,Colormap));
+extern unsigned int get_minutes_resource P((char*,char*));
+extern unsigned int get_seconds_resource P((char*,char*));
+
+extern Visual *get_visual_resource P((Display *, char *, char *));
+extern int get_visual_depth P((Display *, Visual *));
+
+void hsv_to_rgb P((int,double,double,unsigned short*,
+ unsigned short*,unsigned short*));
+void rgb_to_hsv P((unsigned short,unsigned short,unsigned short,
+ int*,double*,double*));
+void cycle_hue P((XColor*,int));
+
+void make_color_ramp P((int h1, double s1, double v1,
+ int h2, double s2, double v2,
+ XColor *pixels, int npixels));
+
+static double _frand_tmp_;
+#define frand(f) \
+ (_frand_tmp_ = (((double) random()) / \
+ (((double) ((unsigned int)~0)) / ((double) (f+f)))), \
+ _frand_tmp_ < 0 ? -_frand_tmp_ : _frand_tmp_)
+
+#undef P
+#endif /* _SCREENHACK_H_ */
--- /dev/null
+/* xscreensaver, Copyright (c) 1992, 1993 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#include "screenhack.h"
+
+static int grid_size;
+static int pix_inc;
+static int hole_x, hole_y;
+static int bitmap_w, bitmap_h;
+static int xoff, yoff;
+static int grid_w, grid_h;
+static int delay, delay2;
+static GC gc;
+
+static Bool
+MapNotify_event_p (dpy, event, window)
+ Display *dpy;
+ XEvent *event;
+ XPointer window;
+{
+ return (event->xany.type == MapNotify &&
+ event->xvisibility.window == (Window) window);
+}
+
+
+static Bool
+screensaver_window_p (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ Atom type;
+ int format;
+ unsigned long nitems, bytesafter;
+ char *version;
+ Pixmap pixmap;
+ if (XGetWindowProperty (dpy, window,
+ XInternAtom (dpy, "_SCREENSAVER_VERSION", False),
+ 0, 1, False, XA_STRING,
+ &type, &format, &nitems, &bytesafter,
+ (unsigned char **) &version)
+ == Success
+ && type != None)
+ return True;
+ return False;
+}
+
+static void
+init_slide (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ int i;
+ XEvent event;
+ XGCValues gcv;
+ XWindowAttributes xgwa;
+ int border;
+ int root_p;
+ unsigned long fg;
+ Pixmap pixmap = 0;
+ Drawable d;
+ Colormap cmap;
+
+ XGetWindowAttributes (dpy, window, &xgwa);
+ cmap = xgwa.colormap;
+
+ delay = get_integer_resource ("delay", "Integer");
+ delay2 = get_integer_resource ("delay2", "Integer");
+ grid_size = get_integer_resource ("gridSize", "Integer");
+ pix_inc = get_integer_resource ("pixelIncrement", "Integer");
+ border = get_integer_resource ("internalBorderWidth", "InternalBorderWidth");
+ fg = get_pixel_resource ("background", "Background", dpy, cmap);
+ root_p = get_boolean_resource ("root", "Boolean");
+
+ if (delay < 0) delay = 0;
+ if (delay2 < 0) delay2 = 0;
+ if (pix_inc < 1) pix_inc = 1;
+ if (grid_size < 1) grid_size = 1;
+
+ gcv.foreground = fg;
+ gcv.function = GXcopy;
+ gcv.subwindow_mode = IncludeInferiors;
+ gc = XCreateGC (dpy, window, GCForeground |GCFunction | GCSubwindowMode,
+ &gcv);
+
+ if (screensaver_window_p (dpy, window))
+ {
+ /* note: this assumes vroot.h didn't encapsulate the XRootWindowOfScreen
+ function, only the RootWindowOfScreen macro... */
+ Window real_root = XRootWindowOfScreen (DefaultScreenOfDisplay (dpy));
+
+ XSetWindowBackgroundPixmap (dpy, window, None);
+
+ /* prevent random viewer of the screen saver (locker) from messing
+ with windows. We don't check whether it succeeded, because what
+ are our options, really... */
+ XGrabPointer (dpy, real_root, True, ButtonPressMask|ButtonReleaseMask,
+ GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
+ XGrabKeyboard (dpy, real_root, True, GrabModeSync, GrabModeAsync,
+ CurrentTime);
+
+ XUnmapWindow (dpy, window);
+ XSync (dpy, True);
+ sleep (5); /* wait for everyone to swap in and handle exposes... */
+ XMapWindow (dpy, window);
+
+ XUngrabPointer (dpy, CurrentTime);
+ XUngrabKeyboard (dpy, CurrentTime);
+
+ XSync (dpy, True);
+ }
+ else if (root_p)
+ {
+ pixmap = XCreatePixmap(dpy, window, xgwa.width, xgwa.height, xgwa.depth);
+ XCopyArea (dpy, RootWindowOfScreen (xgwa.screen), pixmap, gc,
+ xgwa.x, xgwa.y, xgwa.width, xgwa.height, 0, 0);
+ XSetWindowBackgroundPixmap (dpy, window, pixmap);
+ }
+ else
+ {
+ XSetWindowBackgroundPixmap (dpy, window, None);
+ XMapWindow (dpy, window);
+ XFlush (dpy);
+ XIfEvent (dpy, &event, MapNotify_event_p, (XPointer) window);
+ XSync (dpy, True);
+ }
+
+ XGetWindowAttributes (dpy, window, &xgwa);
+ bitmap_w = xgwa.width;
+ bitmap_h = xgwa.height;
+
+ grid_w = bitmap_w / grid_size;
+ grid_h = bitmap_h / grid_size;
+ hole_x = random () % grid_w;
+ hole_y = random () % grid_h;
+ xoff = (bitmap_w - (grid_w * grid_size)) / 2;
+ yoff = (bitmap_h - (grid_h * grid_size)) / 2;
+
+ d = (pixmap ? pixmap : window);
+
+ if (border)
+ {
+ int i;
+ for (i = 0; i <= bitmap_w; i += grid_size)
+ XFillRectangle (dpy, d, gc, xoff+i-border/2, yoff, border, bitmap_h);
+ for (i = 0; i <= bitmap_h; i += grid_size)
+ XFillRectangle (dpy, d, gc, xoff, yoff+i-border/2, bitmap_w, border);
+ }
+
+ if (xoff)
+ {
+ XFillRectangle (dpy, d, gc, 0, 0, xoff, bitmap_h);
+ XFillRectangle (dpy, d, gc, bitmap_w - xoff, 0, xoff, bitmap_h);
+ }
+ if (yoff)
+ {
+ XFillRectangle (dpy, d, gc, 0, 0, bitmap_w, yoff);
+ XFillRectangle (dpy, d, gc, 0, bitmap_h - yoff, bitmap_w, yoff);
+ }
+
+ if (pixmap) XClearWindow (dpy, window);
+ XSync (dpy, True);
+ if (delay2) usleep (delay2 * 2);
+ for (i = 0; i < grid_size; i += pix_inc)
+ {
+ XPoint points [3];
+ points[0].x = xoff + grid_size * hole_x;
+ points[0].y = yoff + grid_size * hole_y;
+ points[1].x = points[0].x + grid_size;
+ points[1].y = points[0].y;
+ points[2].x = points[0].x;
+ points[2].y = points[0].y + i;
+ XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
+
+ points[1].x = points[0].x;
+ points[1].y = points[0].y + grid_size;
+ points[2].x = points[0].x + i;
+ points[2].y = points[0].y + grid_size;
+ XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
+
+ points[0].x = points[1].x + grid_size;
+ points[0].y = points[1].y;
+ points[2].x = points[0].x;
+ points[2].y = points[0].y - i;
+ XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
+
+ points[1].x = points[0].x;
+ points[1].y = points[0].y - grid_size;
+ points[2].x = points[1].x - i;
+ points[2].y = points[1].y;
+ XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
+
+ XSync (dpy, True);
+ if (delay) usleep (delay);
+ }
+
+ XFillRectangle (dpy, window, gc,
+ xoff + grid_size * hole_x,
+ yoff + grid_size * hole_y,
+ grid_size, grid_size);
+}
+
+static void
+slide1 (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ /* this code is a total kludge, but who cares, it works... */
+ int i, x, y, ix, iy, dx, dy, dir, w, h, size, inc;
+ static int last = -1;
+ do {
+ dir = random () % 4;
+ switch (dir)
+ {
+ case 0: dx = 0, dy = 1; break;
+ case 1: dx = -1, dy = 0; break;
+ case 2: dx = 0, dy = -1; break;
+ case 3: dx = 1, dy = 0; break;
+ }
+ } while (dir == last ||
+ hole_x + dx < 0 || hole_x + dx >= grid_w ||
+ hole_y + dy < 0 || hole_y + dy >= grid_h);
+ if (grid_w > 1 && grid_h > 1)
+ last = (dir == 0 ? 2 : dir == 2 ? 0 : dir == 1 ? 3 : 1);
+
+ switch (dir)
+ {
+ case 0: size = 1 + (random()%(grid_h - hole_y - 1)); h = size; w = 1; break;
+ case 1: size = 1 + (random()%hole_x); w = size; h = 1; break;
+ case 2: size = 1 + (random()%hole_y); h = size; w = 1; break;
+ case 3: size = 1 + (random()%(grid_w - hole_x - 1)); w = size; h = 1; break;
+ }
+
+ if (dx == -1) hole_x -= (size - 1);
+ else if (dy == -1) hole_y -= (size - 1);
+
+ ix = x = xoff + (hole_x + dx) * grid_size;
+ iy = y = yoff + (hole_y + dy) * grid_size;
+ inc = pix_inc;
+ for (i = 0; i < grid_size; i += inc)
+ {
+ if (inc + i > grid_size)
+ inc = grid_size - i;
+ XCopyArea (dpy, window, window, gc, x, y, grid_size * w, grid_size * h,
+ x - dx * inc, y - dy * inc);
+ x -= dx * inc;
+ y -= dy * inc;
+ switch (dir)
+ {
+ case 0: XFillRectangle (dpy, window, gc,
+ ix, y + grid_size * h, grid_size * w, iy - y);
+ break;
+ case 1: XFillRectangle (dpy, window, gc, ix, iy, x - ix, grid_size * h);
+ break;
+ case 2: XFillRectangle (dpy, window, gc, ix, iy, grid_size * w, y - iy);
+ break;
+ case 3: XFillRectangle (dpy, window, gc,
+ x + grid_size * w, iy, ix - x, grid_size * h);
+ break;
+ }
+
+ XSync (dpy, True);
+ if (delay) usleep (delay);
+ }
+ switch (dir)
+ {
+ case 0: hole_y += size; break;
+ case 1: hole_x--; break;
+ case 2: hole_y--; break;
+ case 3: hole_x += size; break;
+ }
+}
+
+\f
+char *progclass = "SlidePuzzle";
+
+char *defaults [] = {
+ "SlidePuzzle.mappedWhenManaged:false",
+ "SlidePuzzle.dontClearWindow: true",
+ "*background: black",
+ "*gridSize: 70",
+ "*pixelIncrement: 10",
+ "*internalBorderWidth: 1",
+ "*delay: 50000",
+ "*delay2: 1000000",
+ 0
+};
+
+XrmOptionDescRec options [] = {
+ { "-grid-size", ".gridSize", XrmoptionSepArg, 0 },
+ { "-ibw", ".internalBorderWidth", XrmoptionSepArg, 0 },
+ { "-increment", ".pixelIncrement", XrmoptionSepArg, 0 },
+ { "-delay", ".delay", XrmoptionSepArg, 0 },
+ { "-delay2", ".delay2", XrmoptionSepArg, 0 },
+};
+
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+void
+screenhack (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ init_slide (dpy, window);
+ while (1)
+ {
+ slide1 (dpy, window);
+ if (delay2) usleep (delay2);
+ }
+}
--- /dev/null
+.TH XScreenSaver 1 "3-dec-92" "X Version 11"
+.SH NAME
+slidescreen - permute the screen image like an 8-puzzle
+.SH SYNOPSIS
+.B slidescreen
+[\-display \fIhost:display.screen\fP] [\-background \fIcolor\fP] [\-grid-size \fIpixels\fP] [\-ibw \fIpixels\fP] [\-increment \fIpixels\fP] [\-delay \fIusecs\fP] [\-delay2 \fIusecs\fP] [\-window] [\-root]
+.SH DESCRIPTION
+The \fIslidescreen\fP program takes an image of the screen, divides it into
+a grid, deletes a random square of that grid, and then randomly slides
+one of the neighbors of this "hole" into the hole (and repeat.)
+.SH OPTIONS
+.I slidescreen
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-grid-size pixels
+The size of the grid cells. Default 70 pixels.
+.TP 8
+.B \-ibw pixels
+The size of the "gutter" between grid cells. Default 1 pixel.
+.TP 8
+.B \-increment pixels
+How many pixels by which a piece should be moved when sliding to a new
+location. Default 10 pixels.
+.TP 8
+.B \-delay microseconds
+How much of a delay should be introduced between steps of the animation of
+the motion of each segment. Default 50000, which is 0.05 seconds. This
+is closely related to the \fI\-increment\fP parameter.
+.TP 8
+.B \-delay microseconds
+How much of a delay should be introduced between the end of the motion of
+one segment and the beginning of the motion of another. Default 1000000,
+which isone second.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1992 by Jamie Zawinski. Permission to use, copy, modify,
+distribute, and sell this software and its documentation for any purpose is
+hereby granted without fee, provided that the above copyright notice appear
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation. No representations are made about the
+suitability of this software for any purpose. It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@lucid.com>, 3-dec-92.
--- /dev/null
+/*****************************************************************************/
+/** Copyright 1991 by Andreas Stolcke **/
+/** Copyright 1990 by Solbourne Computer Inc. **/
+/** Longmont, Colorado **/
+/** **/
+/** All Rights Reserved **/
+/** **/
+/** Permission to use, copy, modify, and distribute this software and **/
+/** its documentation for any purpose and without fee is hereby **/
+/** granted, provided that the above copyright notice appear in all **/
+/** copies and that both that copyright notice and this permis- **/
+/** sion notice appear in supporting documentation, and that the **/
+/** name of Solbourne not be used in advertising **/
+/** in publicity pertaining to distribution of the software without **/
+/** specific, written prior permission. **/
+/** **/
+/** ANDREAS STOLCKE AND SOLBOURNE COMPUTER INC. DISCLAIMS ALL WARRANTIES **/
+/** WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF **/
+/** MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ANDREAS STOLCKE **/
+/** OR SOLBOURNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL **/
+/** DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/
+/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/
+/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/
+/** OR PERFORMANCE OF THIS SOFTWARE. **/
+/*****************************************************************************/
+/*
+ * vroot.h -- Virtual Root Window handling header file
+ *
+ * This header file redefines the X11 macros RootWindow and DefaultRootWindow,
+ * making them look for a virtual root window as provided by certain `virtual'
+ * window managers like swm and tvtwm. If none is found, the ordinary root
+ * window is returned, thus retaining backward compatibility with standard
+ * window managers.
+ * The function implementing the virtual root lookup remembers the result of
+ * its last invocation to avoid overhead in the case of repeated calls
+ * on the same display and screen arguments.
+ * The lookup code itself is taken from Tom LaStrange's ssetroot program.
+ *
+ * Most simple root window changing X programs can be converted to using
+ * virtual roots by just including
+ *
+ * #include <X11/vroot.h>
+ *
+ * after all the X11 header files. It has been tested on such popular
+ * X clients as xphoon, xfroot, xloadimage, and xaqua.
+ * It also works with the core clients xprop, xwininfo, xwd, and editres
+ * (and is necessary to get those clients working under tvtwm).
+ * It does NOT work with xsetroot; get the xsetroot replacement included in
+ * the tvtwm distribution instead.
+ *
+ * Andreas Stolcke <stolcke@ICSI.Berkeley.EDU>, 9/7/90
+ * - replaced all NULL's with properly cast 0's, 5/6/91
+ * - free children list (suggested by Mark Martin <mmm@cetia.fr>), 5/16/91
+ * - include X11/Xlib.h and support RootWindowOfScreen, too 9/17/91
+ */
+
+#ifndef _VROOT_H_
+#define _VROOT_H_
+
+#if !defined(lint) && !defined(SABER)
+static char vroot_rcsid[] = "$Id: vroot.h,v 1.4 1991/09/30 19:23:16 stolcke Exp stolcke $";
+#endif
+
+#include <X11/X.h>
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+
+static Window
+VirtualRootWindowOfScreen(screen)
+ Screen *screen;
+{
+ static Screen *save_screen = (Screen *)0;
+ static Window root = (Window)0;
+
+ if (screen != save_screen) {
+ Display *dpy = DisplayOfScreen(screen);
+ Atom __SWM_VROOT = None;
+ int i;
+ Window rootReturn, parentReturn, *children;
+ unsigned int numChildren;
+
+ root = RootWindowOfScreen(screen);
+
+ /* go look for a virtual root */
+ __SWM_VROOT = XInternAtom(dpy, "__SWM_VROOT", False);
+ if (XQueryTree(dpy, root, &rootReturn, &parentReturn,
+ &children, &numChildren)) {
+ for (i = 0; i < numChildren; i++) {
+ Atom actual_type;
+ int actual_format;
+ unsigned long nitems, bytesafter;
+ Window *newRoot = (Window *)0;
+
+ if (XGetWindowProperty(dpy, children[i],
+ __SWM_VROOT, 0, 1, False, XA_WINDOW,
+ &actual_type, &actual_format,
+ &nitems, &bytesafter,
+ (unsigned char **) &newRoot) == Success
+ && newRoot) {
+ root = *newRoot;
+ break;
+ }
+ }
+ if (children)
+ XFree((char *)children);
+ }
+
+ save_screen = screen;
+ }
+
+ return root;
+}
+
+#undef RootWindowOfScreen
+#define RootWindowOfScreen(s) VirtualRootWindowOfScreen(s)
+
+#undef RootWindow
+#define RootWindow(dpy,screen) VirtualRootWindowOfScreen(ScreenOfDisplay(dpy,screen))
+
+#undef DefaultRootWindow
+#define DefaultRootWindow(dpy) VirtualRootWindowOfScreen(DefaultScreenOfDisplay(dpy))
+
+#endif /* _VROOT_H_ */
--- /dev/null
+/*
+** Helpful definitions for porting xlock modes to xscreensaver.
+** by Charles Hannum, mycroft@ai.mit.edu
+**
+** for xlock 2.3 and xscreensaver 1.2, 28AUG92
+**
+**
+** To use, just copy the appropriate file from xlock, add a target
+** for it in the Imakefile, and do the following:
+**
+** 1) If you include math.h, make sure it is before xlock.h.
+** 2) Make sure the first thing you do in initfoo() is to call
+** XGetWindowAttributes. This is what actually sets up the
+** colormap and whatnot.
+** 3) Add an appropriate PROGRAM() line at the end of the .c file.
+** The information you need for this comes from xlock's file
+** resource.c.
+**
+** That's about all there is to it.
+**
+** As an added bonus, if you put an empty definition of PROGRAM() in
+** xlock's xlock.h, you can now use the code with either xlock or
+** xscreensaver.
+**
+**
+** If you make any improvements to this code, please send them to me!
+** It could certainly use some more work.
+*/
+
+#include "screenhack.h"
+
+#define MAXSCREENS 1
+
+static GC gc;
+static unsigned long *pixels = 0, fg_pixel, bg_pixel;
+static int npixels;
+static Colormap cmap;
+
+static int batchcount;
+static unsigned int delay;
+static double saturation;
+
+typedef struct {
+ GC gc;
+ int npixels;
+ u_long *pixels;
+} perscreen;
+
+static perscreen Scr[MAXSCREENS];
+static Display *dsp;
+
+static int screen = 0;
+
+static void
+My_XGetWindowAttributes (dpy, win, xgwa)
+ Display *dpy;
+ Window win;
+ XWindowAttributes *xgwa;
+{
+ XGetWindowAttributes (dpy, win, xgwa);
+
+ if (! pixels) {
+ XGCValues gcv;
+ XColor color;
+ int n;
+ int i, shift;
+
+ cmap = xgwa->colormap;
+
+ i = get_integer_resource ("ncolors", "Integer");
+ if (i <= 2) i = 2, mono_p = True;
+ shift = 360 / i;
+ pixels = (unsigned long *) calloc (i, sizeof (unsigned long));
+ fg_pixel = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+ bg_pixel = get_pixel_resource ("background", "Background", dpy, cmap);
+ if (! mono_p) {
+ for (npixels = 0; npixels < i; npixels++) {
+ hsv_to_rgb ((360*npixels)/i, saturation, 1.0, &color.red, &color.green, &color.blue);
+ if (! XAllocColor (dpy, cmap, &color))
+ break;
+ pixels[npixels] = color.pixel;
+ }
+ }
+ n = get_integer_resource ("delay", "Usecs");
+ if (n >= 0) delay = n;
+ n = get_integer_resource ("count", "Integer");
+ if (n > 0) batchcount = n;
+
+ gcv.foreground = fg_pixel;
+ gcv.background = bg_pixel;
+ gc = XCreateGC (dpy, win, GCForeground|GCBackground, &gcv);
+
+ XClearWindow (dpy, win);
+
+ Scr[screen].gc = gc;
+ Scr[screen].npixels = npixels;
+ Scr[screen].pixels = pixels;
+ }
+}
+
+#define XGetWindowAttributes(a,b,c) My_XGetWindowAttributes(a,b,c)
+
+#undef BlackPixel
+#define BlackPixel(a,b) bg_pixel
+#undef WhitePixel
+#define WhitePixel(a,b) fg_pixel
+#define mono mono_p
+
+#define seconds() time((time_t*)0)
+
+char *defaults[] = {
+ "*background: black",
+ "*foreground: white",
+ "*ncolors: 64",
+ "*delay: -1",
+ 0
+};
+
+XrmOptionDescRec options[] = {
+ {"-count", ".count", XrmoptionSepArg, 0},
+ {"-ncolors", ".ncolors", XrmoptionSepArg, 0},
+ {"-delay", ".delay", XrmoptionSepArg, 0},
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+#define PROGRAM(Y,Z,D,B,S) \
+char *progclass = Y; \
+ \
+void screenhack (dpy, window) \
+ Display *dpy; \
+ Window window; \
+{ \
+ batchcount = B; \
+ delay = D; \
+ saturation = S; \
+ dsp = dpy; \
+ \
+ while (1) { \
+ init##Z (window); \
+ for (;;) { \
+ draw##Z (window); \
+ XSync (dpy, True); \
+ if (delay) usleep (delay); \
+ } \
+ } \
+}
--- /dev/null
+/* xscreensaver, Copyright (c) 1991-1993 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#include "screenhack.h"
+
+char *progclass = "XRoger";
+
+char *defaults [] = {
+ "*background: black",
+ "*foreground: red",
+ "*delay: 5",
+ 0
+};
+
+XrmOptionDescRec options [] = {
+ { "-delay", ".delay", XrmoptionSepArg, 0 }
+};
+int options_size = (sizeof (options) / sizeof (options[0]));
+
+#if __STDC__
+extern void skull (Display *, Window, GC, GC, int, int, int, int);
+#endif
+
+void
+screenhack (dpy, window)
+ Display *dpy;
+ Window window;
+{
+ double delta = 0.005;
+ XGCValues gcv;
+ Colormap cmap;
+ GC draw_gc, erase_gc;
+ unsigned int fg;
+ XColor color, color2;
+ int delay = get_integer_resource ("delay", "Integer");
+ XWindowAttributes xgwa;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ cmap = xgwa.colormap;
+ gcv.foreground = get_pixel_resource ("background", "Background", dpy, cmap);
+ erase_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+ fg = get_pixel_resource ("foreground", "Foreground", dpy, cmap);
+ if (fg == gcv.foreground)
+ fg = ((gcv.foreground == WhitePixel (dpy, DefaultScreen (dpy)))
+ ? BlackPixel (dpy, DefaultScreen (dpy))
+ : WhitePixel (dpy, DefaultScreen (dpy)));
+ gcv.foreground = fg;
+ draw_gc = XCreateGC (dpy, window, GCForeground, &gcv);
+ color.pixel = gcv.foreground;
+ XQueryColor (dpy, cmap, &color);
+ while (1)
+ {
+ int w, h, ww, hh, x, y;
+ time_t start_time;
+ XWindowAttributes xgwa;
+ XGetWindowAttributes (dpy, window, &xgwa);
+ w = xgwa.width;
+ h = xgwa.height;
+
+ ww = 100 + random () % (w - 100);
+ hh = 100 + random () % (h - 100);
+ if (ww < 10) ww = 50;
+ if (hh < 10) hh = 50;
+ if (ww < hh) hh = ww;
+ else ww = hh;
+ x = random () % (w - ww);
+ y = random () % (h - hh);
+ XClearWindow (dpy, window);
+ skull (dpy, window, draw_gc, erase_gc, x, y, ww, hh);
+ XSync (dpy, True);
+ start_time = time ((time_t *) 0);
+ if (mono_p)
+ sleep (delay);
+ else
+ while (start_time + delay > time ((time_t *) 0))
+ {
+ int h;
+ double s, v;
+ color2 = color;
+ rgb_to_hsv (color2.red, color2.green, color2.blue, &h, &s, &v);
+ v += delta;
+ if (v >= 1.0) v = 1.0, delta = -delta;
+ if (v <= 0.7) v = 0.7, delta = -delta;
+ hsv_to_rgb (h, s, v, &color2.red, &color2.green, &color2.blue);
+ if (XAllocColor (dpy, cmap, &color2))
+ {
+ XSetForeground (dpy, draw_gc, color.pixel);
+ XFreeColors (dpy, cmap, &color.pixel, 1, 0);
+ }
+ color = color2;
+ usleep (20000);
+ }
+ }
+}
--- /dev/null
+.TH XScreenSaver 1 "22-mar-93" "X Version 11"
+.SH NAME
+xroger - throbbing X logo, of a sort
+.SH SYNOPSIS
+.B xroger
+[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono]
+.SH DESCRIPTION
+The \fIxroger\fP program displays a replacement for the X logo with a more
+accurate Look and Feel.
+.SH OPTIONS
+.I xroger
+accepts the following options:
+.TP 8
+.B \-window
+Draw on a newly-created window. This is the default.
+.TP 8
+.B \-root
+Draw on the root window.
+.TP 8
+.B \-mono
+If on a color display, pretend we're on a monochrome display.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1)
+.SH COPYRIGHT
+Copyright \(co 1992, 1993 by Jamie Zawinski. Permission to use, copy, modify,
+distribute, and sell this software and its documentation for any purpose is
+hereby granted without fee, provided fnord that the above copyright notice
+appear in all copies and that both that copyright notice and this permission
+notice appear in supporting documentation. No representations are made about
+the suitability of fnord this software for any purpose. It is provided "as
+is" without express or fnord implied warranty.
+.SH AUTHOR
+Jamie Zawinski <jwz@lucid.com>, 13-aug-92.
--- /dev/null
+From mrapple@quack.kfu.com Mon Apr 26 18:31:07 1993
+Newsgroups: alt.hackers
+From: mrapple@quack.kfu.com (Nick Sayer)
+Subject: screenblank and xautolock living in harmony
+Organization: The Duck Pond public unix: +1 408 249 9630, log in as 'guest'.
+Date: 23 Apr 1993 19:26:57 UTC
+
+
+I have a Sun and use xinit to start X. This presented a problem.
+If I use xautolock or xscreensaver to save the screen, then after
+a period of inactivity screenblank would turn the video off despite
+'xset s off'. If I didn't run screenblank, then who would take care of
+the display when X wasn't running?
+
+The hack that saved the day was to include this in .xinitrc:
+
+(
+
+while true ; do
+sleep 360
+touch /dev/console
+done
+
+) &
+killblank=$!
+
+[start up all the clients, etc, etc. Wait for the window manager
+to die, then ]
+
+kill $killblank
+
+The result is that screenblank is kept safely out of the way when X
+is running and left to do its job otherwise.
+
+Yes, I know using XDM would solve this problem.
+
+No, I'm probably not the first to think of this.
+
+You're welcome.
+
+--
+Nick Sayer <mrapple@quack.kfu.com> | "Dear Sexy Nickers. I don't half fancy
+N6QQQ @ N0ARY.#NOCAL.CA.USA.NOAM | you. Meet me at the lift at 5:30 and
++1 408 249 9630, log in as 'guest' | we'll get it together."
+PGP 2.2 public key via finger | -- Mr. Lucas
+
--- /dev/null
+/*
+ * Imakefile file for xscreensaver, Copyright (c) 1993 Jamie Zawinski.
+ *
+ * You should not need to edit this file; edit ../config.h instead.
+ *
+ */
+
+#include "../config.h"
+
+#ifdef NO_SELECT
+ DEFINES = -DNO_SELECT
+#endif
+ SRCS = fade.c hsv.c resources.c spline.c usleep.c xroger.c
+ OBJS = fade.o hsv.o resources.o spline.o usleep.o xroger.o
+ TARFILES = README Imakefile ad2c $(SRCS) spline.h version.h
+
+all:: $(OBJS)
+
+echo_tarfiles:
+ @echo $(TARFILES)
--- /dev/null
+
+This directory contains various utilities that are used both by the
+screensaver driver and by the demo programs; for example, a portable
+implementation of usleep(), and code for manipulating color maps.
+
+If you have compilation problems, check the parameters in ../config.h.
--- /dev/null
+#!/bin/sh
+#
+# ad2c : Convert app-defaults file to C strings decls.
+#
+# George Ferguson, ferguson@cs.rcohester.edu, 12 Nov 1990.
+# 19 Mar 1991 : gf
+# Made it self-contained.
+# 6 Jan 1992 : mycroft@gnu.ai.mit.edu (Charles Hannum)
+# Removed use of "-n" and ":read" label since Gnu and
+# IBM sed print pattern space on "n" command. Still works
+# with Sun sed, of course.
+# 7 Jan 1992: matthew@sunpix.East.Sun.COM (Matthew Stier)
+# Escape quotes after escaping backslashes.
+#
+
+sed '
+/^!/d
+/^$/d
+s/\\/\\\\/g
+s/\\$//g
+s/"/\\"/g
+s/^/"/
+: test
+/\\$/b slash
+s/$/",/
+p
+d
+: slash
+n
+/^!/d
+/^$/d
+s/"/\\"/g
+s/\\\\/\\/g
+s/\\n/\\\\n/g
+s/\\t/\\\\t/g
+s/\\f/\\\\f/g
+s/\\b/\\\\b/g
+b test' "$@"
--- /dev/null
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#if __STDC__
+# include <stdlib.h>
+#endif
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xos.h>
+
+#if __STDC__
+# define bcopy(from,to,size) memcpy((to),(from),(size))
+# define bzero(addr,size) memset((addr),0,(size))
+extern void screenhack_usleep (unsigned long);
+#else
+extern void screenhack_usleep ();
+#endif
+
+#define usleep screenhack_usleep
+
+#define MAX_COLORS 4096
+static XColor orig_colors [MAX_COLORS];
+static XColor current_colors [MAX_COLORS];
+static int ncolors;
+
+Colormap
+copy_colormap (dpy, cmap, into_cmap)
+ Display *dpy;
+ Colormap cmap, into_cmap;
+{
+ int i;
+ ncolors = CellsOfScreen (DefaultScreenOfDisplay (dpy));
+ if (ncolors <= 2 || ncolors > MAX_COLORS)
+ return 0;
+ if (! into_cmap)
+ into_cmap = XCreateColormap (dpy, RootWindow (dpy, DefaultScreen (dpy)),
+ DefaultVisual (dpy, DefaultScreen (dpy)),
+ AllocAll);
+ if (! cmap)
+ cmap = DefaultColormap (dpy, DefaultScreen (dpy));
+ for (i = 0; i < ncolors; i++)
+ orig_colors [i].pixel = i;
+ XQueryColors (dpy, cmap, orig_colors, ncolors);
+ XStoreColors (dpy, into_cmap, orig_colors, ncolors);
+ return into_cmap;
+}
+
+void
+blacken_colormap (dpy, cmap)
+ Display *dpy;
+ Colormap cmap;
+{
+ int i;
+ for (i = 0; i < ncolors; i++)
+ {
+ current_colors [i].pixel = i;
+ current_colors [i].red = current_colors [i].green =
+ current_colors [i].blue = 0;
+ }
+ XStoreColors (dpy, cmap, current_colors, ncolors);
+}
+
+
+void
+fade_colormap (dpy, cmap, cmap2, seconds, ticks, out_p)
+ Display *dpy;
+ Colormap cmap, cmap2;
+ int seconds, ticks;
+ Bool out_p;
+{
+ int i;
+ int steps = seconds * ticks;
+ XEvent dummy_event;
+
+ if (! cmap2)
+ return;
+
+ for (i = 0; i < ncolors; i++)
+ orig_colors [i].pixel = i;
+ XQueryColors (dpy, cmap, orig_colors, ncolors);
+ bcopy (orig_colors, current_colors, ncolors * sizeof (XColor));
+
+ for (i = (out_p ? steps : 0);
+ (out_p ? i > 0 : i < steps);
+ (out_p ? i-- : i++))
+ {
+ int j;
+ for (j = 0; j < ncolors; j++)
+ {
+ current_colors[j].red = orig_colors[j].red * i / steps;
+ current_colors[j].green = orig_colors[j].green * i / steps;
+ current_colors[j].blue = orig_colors[j].blue * i / steps;
+ }
+ XStoreColors (dpy, cmap2, current_colors, ncolors);
+ XSync (dpy, False);
+
+ /* If there is user activity, bug out.
+ We put the event back so that the calling code can notice it too.
+ It would be better to not remove it at all, but that's harder
+ because Xlib has such a non-design for this kind of crap, and
+ in this application it doesn't matter if the events end up out
+ of order, so in the grand unix tradition we say "fuck it" and
+ do something that mostly works for the time being.
+ */
+ if (XCheckMaskEvent (dpy, (KeyPressMask | KeyReleaseMask |
+ ButtonPressMask | ButtonReleaseMask |
+ PointerMotionMask),
+ &dummy_event))
+ {
+ XPutBackEvent (dpy, &dummy_event);
+ return;
+ }
+
+ usleep (1000000 / (ticks * 2)); /* the 2 is a hack... */
+ }
+}
+
+#if 0
+
+\f
+char *progclass = "foo";
+
+char *defaults [] = {
+ 0
+};
+
+XrmOptionDescRec options [] = {0};
+int options_size = 0;
+
+void
+screenhack (dpy, w)
+ Display *dpy;
+ Window w;
+{
+ Colormap cmap = DefaultColormap (dpy, DefaultScreen (dpy));
+ Colormap cmap2 = copy_colormap (dpy, cmap, 0);
+
+ int seconds = 1;
+ int ticks = 30 * seconds;
+ int delay = 1;
+
+ while (1)
+ {
+ XSync (dpy, False);
+ XGrabServer (dpy);
+ XInstallColormap (dpy, cmap2);
+ fade_colormap (dpy, cmap, cmap2, seconds, ticks, True);
+ if (delay) sleep (delay);
+ fade_colormap (dpy, cmap, cmap2, seconds, ticks, False);
+ XInstallColormap (dpy, cmap);
+ XUngrabServer (dpy);
+ XSync (dpy, False);
+ if (delay) sleep (delay);
+ }
+}
+
+#endif
--- /dev/null
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+/* This file contains some utility routines for randomly picking the colors
+ to hack the screen with.
+ */
+
+#include <X11/Xlib.h>
+
+void
+hsv_to_rgb (h,s,v, r,g,b)
+ int h; /* 0 - 360 */
+ double s, v; /* 0.0 - 1.0 */
+ unsigned short *r, *g, *b; /* 0 - 65535 */
+{
+ double H, S, V, R, G, B;
+ double p1, p2, p3;
+ double f;
+ int i;
+ S = s; V = v;
+ H = (h % 360) / 60.0;
+ i = H;
+ f = H - i;
+ p1 = V * (1 - S);
+ p2 = V * (1 - (S * f));
+ p3 = V * (1 - (S * (1 - f)));
+ if (i == 0) { R = V; G = p3; B = p1; }
+ else if (i == 1) { R = p2; G = V; B = p1; }
+ else if (i == 2) { R = p1; G = V; B = p3; }
+ else if (i == 3) { R = p1; G = p2; B = V; }
+ else if (i == 4) { R = p3; G = p1; B = V; }
+ else { R = V; G = p1; B = p2; }
+ *r = R * 65535;
+ *g = G * 65535;
+ *b = B * 65535;
+}
+
+void
+rgb_to_hsv (r,g,b, h,s,v)
+ unsigned short r, g, b; /* 0 - 65535 */
+ int *h; /* 0 - 360 */
+ double *s, *v; /* 0.0 - 1.0 */
+{
+ double R, G, B, H, S, V;
+ double cmax, cmin;
+ double cmm;
+ int imax;
+ R = ((double) r) / 65535.0;
+ G = ((double) g) / 65535.0;
+ B = ((double) b) / 65535.0;
+ cmax = R; cmin = G; imax = 1;
+ if ( cmax < G ) { cmax = G; cmin = R; imax = 2; }
+ if ( cmax < B ) { cmax = B; imax = 3; }
+ if ( cmin > B ) { cmin = B; }
+ cmm = cmax - cmin;
+ V = cmax;
+ if (cmm == 0)
+ S = H = 0;
+ else
+ {
+ S = cmm / cmax;
+ if (imax == 1) H = (G - B) / cmm;
+ else if (imax == 2) H = 2.0 + (B - R) / cmm;
+ else if (imax == 3) H = 4.0 + (R - G) / cmm;
+ if (H < 0) H += 6.0;
+ }
+ *h = (H * 60.0);
+ *s = S;
+ *v = V;
+}
+
+
+void
+make_color_ramp (h1, s1, v1, h2, s2, v2,
+ pixels, npixels)
+ int h1, h2; /* 0 - 360 */
+ double s1, s2, v1, v2; /* 0.0 - 1.0 */
+ XColor *pixels;
+ int npixels;
+{
+ int dh = (h2 - h1) / npixels;
+ double ds = (s2 - s1) / npixels;
+ double dv = (v2 - v1) / npixels;
+ int i;
+ for (i = 0; i < npixels; i++)
+ hsv_to_rgb ((h1 += dh), (s1 += ds), (v1 += dv),
+ &pixels [i].red, &pixels [i].green, &pixels [i].blue);
+}
+
+
+void
+cycle_hue (color, degrees)
+ XColor *color;
+ int degrees;
+{
+ int h;
+ double s, v;
+ rgb_to_hsv (color->red, color->green, color->blue,
+ &h, &s, &v);
+ h = (h + degrees) % 360;
+ hsv_to_rgb (h, s, v, &color->red, &color->green, &color->blue);
+}
--- /dev/null
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#if __STDC__
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xresource.h>
+
+/* Resource functions. Assumes: */
+
+extern char *progname;
+extern char *progclass;
+extern XrmDatabase db;
+
+#ifndef isupper
+# define isupper(c) ((c) >= 'A' && (c) <= 'Z')
+#endif
+#ifndef _tolower
+# define _tolower(c) ((c) - 'A' + 'a')
+#endif
+
+char *
+get_string_resource (res_name, res_class)
+ char *res_name, *res_class;
+{
+ XrmValue value;
+ char *type;
+ char full_name [1024], full_class [1024];
+ strcpy (full_name, progname);
+ strcat (full_name, ".");
+ strcat (full_name, res_name);
+ strcpy (full_class, progclass);
+ strcat (full_class, ".");
+ strcat (full_class, res_class);
+ if (XrmGetResource (db, full_name, full_class, &type, &value))
+ {
+ char *str = (char *) malloc (value.size + 1);
+ strncpy (str, (char *) value.addr, value.size);
+ str [value.size] = 0;
+ return str;
+ }
+ return 0;
+}
+
+Bool
+get_boolean_resource (res_name, res_class)
+ char *res_name, *res_class;
+{
+ char *tmp, buf [100];
+ char *s = get_string_resource (res_name, res_class);
+ char *os = s;
+ if (! s) return 0;
+ for (tmp = buf; *s; s++)
+ *tmp++ = isupper (*s) ? _tolower (*s) : *s;
+ *tmp = 0;
+ free (os);
+
+ if (!strcmp (buf, "on") || !strcmp (buf, "true") || !strcmp (buf, "yes"))
+ return 1;
+ if (!strcmp (buf,"off") || !strcmp (buf, "false") || !strcmp (buf,"no"))
+ return 0;
+ fprintf (stderr, "%s: %s must be boolean, not %s.\n",
+ progname, res_class, buf);
+ return 0;
+}
+
+int
+get_integer_resource (res_name, res_class)
+ char *res_name, *res_class;
+{
+ int val;
+ char c, *s = get_string_resource (res_name, res_class);
+ if (!s) return 0;
+ if (1 == sscanf (s, " %d %c", &val, &c))
+ {
+ free (s);
+ return val;
+ }
+ fprintf (stderr, "%s: %s must be an integer, not %s.\n",
+ progname, res_name, s);
+ free (s);
+ return 0;
+}
+
+double
+get_float_resource (res_name, res_class)
+ char *res_name, *res_class;
+{
+ double val;
+ char c, *s = get_string_resource (res_name, res_class);
+ if (! s) return 0.0;
+ if (1 == sscanf (s, " %lf %c", &val, &c))
+ {
+ free (s);
+ return val;
+ }
+ fprintf (stderr, "%s: %s must be a float, not %s.\n",
+ progname, res_name, s);
+ free (s);
+ return 0.0;
+}
+
+
+unsigned int
+get_pixel_resource (res_name, res_class, dpy, cmap)
+ char *res_name, *res_class;
+ Display *dpy;
+ Colormap cmap;
+{
+ XColor color;
+ char *s = get_string_resource (res_name, res_class);
+ if (!s) goto DEFAULT;
+
+ if (! XParseColor (dpy, cmap, s, &color))
+ {
+ fprintf (stderr, "%s: can't parse color %s\n", progname, s);
+ goto DEFAULT;
+ }
+ if (! XAllocColor (dpy, cmap, &color))
+ {
+ fprintf (stderr, "%s: couldn't allocate color %s\n", progname, s);
+ goto DEFAULT;
+ }
+ free (s);
+ return color.pixel;
+ DEFAULT:
+ if (s) free (s);
+ return (strcmp (res_class, "Background")
+ ? WhitePixel (dpy, DefaultScreen (dpy))
+ : BlackPixel (dpy, DefaultScreen (dpy)));
+}
+
+
+int
+parse_time (string, seconds_default_p, silent_p)
+ char *string;
+ Bool seconds_default_p, silent_p;
+{
+ unsigned int h, m, s;
+ char c;
+ if (3 == sscanf (string, " %u : %2u : %2u %c", &h, &m, &s, &c))
+ ;
+ else if (2 == sscanf (string, " : %2u : %2u %c", &m, &s, &c) ||
+ 2 == sscanf (string, " %u : %2u %c", &m, &s, &c))
+ h = 0;
+ else if (1 == sscanf (string, " : %2u %c", &s, &c))
+ h = m = 0;
+ else if (1 == sscanf (string, " %u %c",
+ (seconds_default_p ? &s : &m), &c))
+ {
+ h = 0;
+ if (seconds_default_p) m = 0;
+ else s = 0;
+ }
+ else
+ {
+ if (! silent_p)
+ fprintf (stderr, "%s: invalid time interval specification \"%s\".\n",
+ progname, string);
+ return -1;
+ }
+ if (s >= 60 && (h != 0 || m != 0))
+ {
+ if (! silent_p)
+ fprintf (stderr, "%s: seconds > 59 in \"%s\".\n", progname, string);
+ return -1;
+ }
+ if (m >= 60 && h > 0)
+ {
+ if (! silent_p)
+ fprintf (stderr, "%s: minutes > 59 in \"%s\".\n", progname, string);
+ return -1;
+ }
+ return ((h * 60 * 60) + (m * 60) + s);
+}
+
+static unsigned int
+get_time_resource (res_name, res_class, sec_p)
+ char *res_name, *res_class;
+ Bool sec_p;
+{
+ int val;
+ char *s = get_string_resource (res_name, res_class);
+ if (!s) return 0;
+ val = parse_time (s, sec_p, False);
+ free (s);
+ return (val < 0 ? 0 : val);
+}
+
+unsigned int
+get_seconds_resource (res_name, res_class)
+ char *res_name, *res_class;
+{
+ return get_time_resource (res_name, res_class, True);
+}
+
+unsigned int
+get_minutes_resource (res_name, res_class)
+ char *res_name, *res_class;
+{
+ return get_time_resource (res_name, res_class, False);
+}
--- /dev/null
+#include <stdio.h>
+#include "spline.h"
+#if __STDC__
+#include <stdlib.h>
+#endif
+#include <math.h>
+
+/* Lifted from InterViews */
+#define SMOOTHNESS 1.0
+
+static void
+no_more_memory ()
+{
+ fprintf (stderr, "No more memory\n");
+ exit (1);
+}
+
+spline*
+make_spline (size)
+ u_int size;
+{
+ spline* s = (spline*)calloc (1, sizeof (spline));
+ if (!s)
+ no_more_memory ();
+ s->n_controls = size;
+ s->control_x = (double*)calloc (s->n_controls, sizeof (double));
+ s->control_y = (double*)calloc (s->n_controls, sizeof (double));
+
+ s->n_points = 0;
+ s->allocated_points = s->n_controls;
+ s->points = (XPoint*)calloc (s->allocated_points, sizeof (XPoint));
+
+ if (!s->control_x || !s->control_y || !s->points)
+ no_more_memory ();
+
+ return s;
+}
+
+static void
+grow_spline_points (s)
+ spline* s;
+{
+ s->allocated_points *= 2;
+ s->points =
+ (XPoint*)realloc (s->points, s->allocated_points * sizeof (XPoint));
+
+ if (!s->points)
+ no_more_memory ();
+}
+
+static void
+mid_point (x0, y0, x1, y1, mx, my)
+ double x0, y0, x1, y1, *mx, *my;
+{
+ *mx = (x0 + x1) / 2.0;
+ *my = (y0 + y1) / 2.0;
+}
+
+static void
+third_point (x0, y0, x1, y1, tx, ty)
+ double x0, y0, x1, y1, *tx, *ty;
+{
+ *tx = (2 * x0 + x1) / 3.0;
+ *ty = (2 * y0 + y1) / 3.0;
+}
+
+static int
+can_approx_with_line (x0, y0, x2, y2, x3, y3)
+ double x0, y0, x2, y2, x3, y3;
+{
+ double triangle_area, side_squared, dx, dy;
+
+ triangle_area = x0 * y2 - x2 * y0 + x2 * y3 - x3 * y2 + x3 * y0 - x0 * y3;
+ /* actually 4 times the area. */
+ triangle_area *= triangle_area;
+ dx = x3 - x0;
+ dy = y3 - y0;
+ side_squared = dx * dx + dy * dy;
+ return triangle_area <= SMOOTHNESS * side_squared;
+}
+
+static void
+add_line (s, x0, y0, x1, y1)
+ spline* s;
+ double x0, y0, x1, y1;
+{
+ if (s->n_points >= s->allocated_points)
+ grow_spline_points (s);
+
+ if (s->n_points == 0)
+ {
+ s->points [s->n_points].x = x0;
+ s->points [s->n_points].y = y0;
+ s->n_points += 1;
+ }
+ s->points [s->n_points].x = x1;
+ s->points [s->n_points].y = y1;
+ s->n_points += 1;
+}
+
+static void
+add_bezier_arc (s, x0, y0, x1, y1, x2, y2, x3, y3)
+ spline* s;
+ double x0, y0, x1, y1, x2, y2, x3, y3;
+{
+ double midx01, midx12, midx23, midlsegx, midrsegx, cx,
+ midy01, midy12, midy23, midlsegy, midrsegy, cy;
+
+ mid_point (x0, y0, x1, y1, &midx01, &midy01);
+ mid_point (x1, y1, x2, y2, &midx12, &midy12);
+ mid_point (x2, y2, x3, y3, &midx23, &midy23);
+ mid_point (midx01, midy01, midx12, midy12, &midlsegx, &midlsegy);
+ mid_point (midx12, midy12, midx23, midy23, &midrsegx, &midrsegy);
+ mid_point (midlsegx, midlsegy, midrsegx, midrsegy, &cx, &cy);
+
+ if (can_approx_with_line (x0, y0, midlsegx, midlsegy, cx, cy))
+ add_line (s, x0, y0, cx, cy);
+ else if ((midx01 != x1) || (midy01 != y1) || (midlsegx != x2)
+ || (midlsegy != y2) || (cx != x3) || (cy != y3))
+ add_bezier_arc (s, x0, y0, midx01, midy01, midlsegx, midlsegy, cx, cy);
+
+ if (can_approx_with_line (cx, cy, midx23, midy23, x3, y3))
+ add_line (s, cx, cy, x3, y3);
+ else if ((cx != x0) || (cy != y0) || (midrsegx != x1) || (midrsegy != y1)
+ || (midx23 != x2) || (midy23 != y2))
+ add_bezier_arc (s, cx, cy, midrsegx, midrsegy, midx23, midy23, x3, y3);
+}
+
+static void
+calc_section (s, cminus1x, cminus1y, cx, cy, cplus1x, cplus1y,
+ cplus2x, cplus2y)
+ spline* s;
+ double cminus1x, cminus1y, cx, cy, cplus1x, cplus1y, cplus2x, cplus2y;
+{
+ double p0x, p1x, p2x, p3x, tempx,
+ p0y, p1y, p2y, p3y, tempy;
+
+ third_point (cx, cy, cplus1x, cplus1y, &p1x, &p1y);
+ third_point (cplus1x, cplus1y, cx, cy, &p2x, &p2y);
+ third_point (cx, cy, cminus1x, cminus1y, &tempx, &tempy);
+ mid_point (tempx, tempy, p1x, p1y, &p0x, &p0y);
+ third_point (cplus1x, cplus1y, cplus2x, cplus2y, &tempx, &tempy);
+ mid_point (tempx, tempy, p2x, p2y, &p3x, &p3y);
+ add_bezier_arc (s, p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y);
+}
+
+void
+compute_spline (s)
+ spline* s;
+{
+ int i;
+ s->n_points = 0;
+
+ if (s->n_controls < 3)
+ return;
+
+ calc_section (s, s->control_x [0], s->control_y [0], s->control_x [0],
+ s->control_y [0], s->control_x [0], s->control_y [0],
+ s->control_x [1], s->control_y [1]);
+ calc_section (s, s->control_x [0], s->control_y [0], s->control_x [0],
+ s->control_y [0], s->control_x [1], s->control_y [1],
+ s->control_x [2], s->control_y [2]);
+
+ for (i = 1; i < s->n_controls - 2; i++)
+ calc_section (s, s->control_x [i - 1], s->control_y [i - 1],
+ s->control_x [i], s->control_y [i],
+ s->control_x [i + 1], s->control_y [i + 1],
+ s->control_x [i + 2], s->control_y [i + 2]);
+
+ calc_section (s, s->control_x [i - 1], s->control_y [i - 1],
+ s->control_x [i], s->control_y [i],
+ s->control_x [i + 1], s->control_y [i + 1],
+ s->control_x [i + 1], s->control_y [i + 1]);
+ calc_section (s, s->control_x [i], s->control_y [i],
+ s->control_x [i + 1], s->control_y [i + 1],
+ s->control_x [i + 1], s->control_y [i + 1],
+ s->control_x [i + 1], s->control_y [i + 1]);
+}
+
+void
+compute_closed_spline (s)
+ spline *s;
+{
+ int i;
+ s->n_points = 0;
+
+ if (s->n_controls < 3)
+ return;
+
+ calc_section (s,
+ s->control_x [s->n_controls - 1],
+ s->control_y [s->n_controls - 1],
+ s->control_x [0], s->control_y [0],
+ s->control_x [1], s->control_y [1],
+ s->control_x [2], s->control_y [2]);
+
+ for (i = 1; i < s->n_controls - 2; i++)
+ calc_section (s, s->control_x [i - 1], s->control_y [i - 1],
+ s->control_x [i], s->control_y [i],
+ s->control_x [i + 1], s->control_y [i + 1],
+ s->control_x [i + 2], s->control_y [i + 2]);
+
+ calc_section (s, s->control_x [i - 1], s->control_y [i - 1],
+ s->control_x [i], s->control_y [i],
+ s->control_x [i + 1], s->control_y [i + 1],
+ s->control_x [0], s->control_y [0]);
+ calc_section (s, s->control_x [i], s->control_y [i],
+ s->control_x [i + 1], s->control_y [i + 1],
+ s->control_x [0], s->control_y [0],
+ s->control_x [1], s->control_y [1]);
+}
+
+void
+just_fill_spline (s)
+ spline *s;
+{
+ int i;
+
+ while (s->allocated_points < s->n_controls + 1)
+ grow_spline_points (s);
+
+ for (i = 0; i < s->n_controls; i++)
+ {
+ s->points [i].x = s->control_x [i];
+ s->points [i].y = s->control_y [i];
+ }
+ s->points [s->n_controls].x = s->control_x [0];
+ s->points [s->n_controls].y = s->control_y [0];
+ s->n_points = s->n_controls + 1;
+}
+
+void
+append_spline_points (s1, s2)
+ spline *s1, *s2;
+{
+ int i;
+ while (s1->allocated_points < s1->n_points + s2->n_points)
+ grow_spline_points (s1);
+ for (i = s1->n_points; i < s1->n_points + s2->n_points; i++)
+ {
+ s1->points [i].x = s2->points [i - s1->n_points].x;
+ s1->points [i].y = s2->points [i - s1->n_points].y;
+ }
+ s1->n_points = s1->n_points + s2->n_points;
+}
+
+void
+spline_bounding_box (s, rectangle_out)
+ spline* s;
+ XRectangle* rectangle_out;
+{
+ int min_x;
+ int max_x;
+ int min_y;
+ int max_y;
+ int i;
+
+ if (s->n_points == 0)
+ {
+ rectangle_out->x = 0;
+ rectangle_out->y = 0;
+ rectangle_out->width = 0;
+ rectangle_out->height = 0;
+ }
+
+ min_x = s->points [0].x;
+ max_x = min_x;
+ min_y = s->points [0].y;
+ max_y = min_y;
+
+ for (i = 1; i < s->n_points; i++)
+ {
+ if (s->points [i].x < min_x)
+ min_x = s->points [i].x;
+ if (s->points [i].x > max_x)
+ max_x = s->points [i].x;
+ if (s->points [i].y < min_y)
+ min_y = s->points [i].y;
+ if (s->points [i].y > max_y)
+ max_y = s->points [i].y;
+ }
+ rectangle_out->x = min_x;
+ rectangle_out->y = min_y;
+ rectangle_out->width = max_x - min_x;
+ rectangle_out->height = max_y - min_y;
+}
--- /dev/null
+#ifndef _SPLINE_H_
+#define _SPLINE_H_
+
+#include <X11/Xlib.h>
+
+#if __STDC__
+# define P(x)x
+#else
+# define P(x)()
+#endif
+
+typedef struct _spline
+{
+ /* input */
+ u_int n_controls;
+ double* control_x;
+ double* control_y;
+
+ /* output */
+ u_int n_points;
+ XPoint* points;
+ u_int allocated_points;
+} spline;
+
+spline* make_spline P((u_int size));
+void compute_spline P((spline* s));
+void compute_closed_spline P((spline* s));
+void just_fill_spline P((spline* s));
+void append_spline_points P((spline* s1, spline* s2));
+void spline_bounding_box P((spline* s, XRectangle* rectangle_out));
+
+#undef P
+#endif /* _SPLINE_H_ */
--- /dev/null
+/* xscreensaver, Copyright (c) 1992 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#if __STDC__
+#include <stdlib.h>
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/Xos.h> /* lazy way out */
+
+/* usleep() doesn't exist everywhere, and select() is faster anyway.
+ */
+
+#ifndef VMS
+
+#ifdef NO_SELECT
+ /* If you don't have select() or usleep(), I guess you lose...
+ Maybe you have napms() instead? Let me know.
+ */
+void
+screenhack_usleep (usecs)
+ unsigned long usecs;
+{
+ usleep (usecs);
+}
+
+#else /* ! NO_SELECT */
+
+void
+screenhack_usleep (usecs)
+ unsigned long usecs;
+{
+ struct timeval tv;
+ tv.tv_sec = usecs / 1000000L;
+ tv.tv_usec = usecs % 1000000L;
+ (void) select (0, 0, 0, 0, &tv);
+}
+
+#endif /* ! NO_SELECT */
+
+#else /* VMS */
+
+#define SEC_DELTA "0000 00:00:01.00"
+#define TICK_DELTA "0000 00:00:00.08"
+static int bin_sec_delta[2], bin_tick_delta[2], deltas_set = 0;
+
+static void
+set_deltas ()
+{
+ int status;
+ extern int SYS$BINTIM ();
+ $DESCRIPTOR (str_sec_delta, SEC_DELTA);
+ $DESCRIPTOR (str_tick_delta, TICK_DELTA);
+ if (!deltas_set)
+ {
+ status = SYS$BINTIM (&str_sec_delta, &bin_sec_delta);
+ if (!(status & 1))
+ {
+ fprintf (stderr, "%s: cannot convert delta time ", progname);
+ fprintf (stderr, SEC_DELTA);
+ fprintf (stderr, "; status code = %d\n", status);
+ exit (status);
+ }
+ status = SYS$BINTIM (&str_tick_delta, &bin_tick_delta);
+ if (!(status & 1))
+ {
+ fprintf (stderr, "%s: cannot convert delta time ", progname);
+ fprintf (stderr, TICK_DELTA);
+ fprintf (stderr, "; status code = %d\n", status);
+ exit (status);
+ }
+ deltas_set = 1;
+ }
+}
+
+void
+screenhack_usleep (usecs)
+ unsigned long usecs;
+{
+ int status, *bin_delta;
+ extern int SYS$SCHWDK (), SYS$HIBER ();
+
+ if (!deltas_set) set_deltas ();
+ bin_delta = (usecs == TICK_INTERVAL) ? &bin_tick_delta : &bin_sec_delta;
+ status = SYS$SCHDWK (0, 0, bin_delta, 0);
+ if ((status & 1)) (void) SYS$HIBER ();
+}
+
+#endif /*VMS */
--- /dev/null
+static char *screensaver_id =
+ "@(#)xscreensaver 1.17, by Jamie Zawinski (jwz@lucid.com)";
--- /dev/null
+/* xscreensaver, Copyright (c) 1991-1993 Jamie Zawinski <jwz@lucid.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. No representations are made about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ */
+
+#include <X11/Xlib.h>
+
+static void
+crossbones (dpy, window, draw_gc, x, y, w, h)
+ Display *dpy;
+ Window window;
+ GC draw_gc;
+ int x, y, w, h;
+{
+ double xscale = w / 440.0;
+ double yscale = h / 216.0;
+ XPoint points [6];
+ points [0].x = x + xscale * 20;
+ points [0].y = y + yscale * 10;
+ points [1].x = x + xscale * 120;
+ points [1].y = y + yscale * 10;
+ points [2].x = x + xscale * 243;
+ points [2].y = y + yscale * 93;
+ points [3].x = x + xscale * 57;
+ points [3].y = y + yscale * 210;
+ points [4].x = x + xscale * 20;
+ points [4].y = y + yscale * 210;
+ points [5].x = x + xscale * 175;
+ points [5].y = y + yscale * 113;
+ XFillPolygon (dpy, window, draw_gc, points, 6, Complex, CoordModeOrigin);
+ points [0].x = x + xscale * 197;
+ points [0].y = y + yscale * 127;
+ points [1].x = x + xscale * 384;
+ points [1].y = y + yscale * 10;
+ points [2].x = x + xscale * 420;
+ points [2].y = y + yscale * 10;
+ points [3].x = x + xscale * 265;
+ points [3].y = y + yscale * 108;
+ points [4].x = x + xscale * 420;
+ points [4].y = y + yscale * 210;
+ points [5].x = x + xscale * 320;
+ points [5].y = y + yscale * 210;
+ XFillPolygon (dpy, window, draw_gc, points, 6, Complex, CoordModeOrigin);
+}
+
+
+void
+skull (dpy, window, draw_gc, erase_gc, x, y, w, h)
+ Display *dpy;
+ Window window;
+ GC draw_gc, erase_gc;
+ int x, y, w, h;
+{
+ XPoint points [3];
+ crossbones (dpy, window, draw_gc, x, y+h/2, w, h/2);
+ x += w/100;
+ y += h/15;
+ XFillArc (dpy, window, draw_gc, (int) (x + (w * 0.3)), y, w/2, h/2,
+ -40*64, 260*64);
+ XFillRectangle (dpy, window, draw_gc, (int) (x + (w * 0.35)), y + h/5,
+ (int) (w * 0.4), h/5);
+ XFillRectangle (dpy, window, draw_gc, (int) (x + (w * 0.375)),
+ (int) (y + (h * 0.425)), w / 20, h / 20);
+ XFillRectangle (dpy, window, draw_gc, (int) (x + (w * 0.495)),
+ (int) (y + (h * 0.425)), w / 20, h / 20);
+ XFillRectangle (dpy, window, draw_gc, (int) (x + (w * 0.555)),
+ (int) (y + (h * 0.425)), w / 20, h / 20);
+ XFillRectangle (dpy, window, draw_gc, (int) (x + (w * 0.675)),
+ (int) (y + (h * 0.425)), w / 20, h / 20);
+ points [0].x = x + (w * 0.435);
+ points [0].y = y + (h * 0.425);
+ points [1].x = x + (w * 0.485);
+ points [1].y = points [0].y;
+ points [2].x = (points [0].x + points [1].x) / 2;
+ points [2].y = points [0].y + h/10;
+ XFillPolygon (dpy, window, draw_gc, points, 3, Complex, CoordModeOrigin);
+ points [0].x = x + (w * 0.615);
+ points [1].x = x + (w * 0.665);
+ points [2].x = (points [0].x + points [1].x) / 2;
+ XFillPolygon (dpy, window, draw_gc, points, 3, Complex, CoordModeOrigin);
+ points [0].x = x + (w * 0.52);
+ points [0].y = y + (h * 0.35);
+ points [1].x = points [0].x - (w * 0.05);
+ points [1].y = points [0].y;
+ points [2].x = points [0].x;
+ points [2].y = points [0].y - (w * 0.10);
+ XFillPolygon (dpy, window, erase_gc, points, 3, Complex, CoordModeOrigin);
+ points [0].x = x + (w * 0.57);
+ points [1].x = x + (w * 0.62);
+ points [2].x = points [0].x;
+ XFillPolygon (dpy, window, erase_gc, points, 3, Complex, CoordModeOrigin);
+ XFillArc (dpy, window, erase_gc, x + ((int) (w * 0.375)), y + h/7,
+ w/10, h/10, 0, 360*64);
+ XFillArc (dpy, window, erase_gc, x + ((int) (w * 0.615)), y + h/7,
+ w/10, h/10, 0, 360*64);
+}