From 0a1527cc01e9894017614b7c36b838b2b6914ba9 Mon Sep 17 00:00:00 2001 From: Zygo Blaxell Date: Mon, 2 Mar 2009 00:42:18 -0500 Subject: [PATCH] ftp://ftp.ntnu.no/old/pub/X11/R5contrib/xscreensaver-1.17.tar.gz -rw-r--r-- 1 zblaxell zblaxell 108551 Feb 27 14:00 xscreensaver-1.17.tar.gz db81f5a260a152f79d884bcf855c7cf287e32b0f xscreensaver-1.17.tar.gz --- Imakefile | 44 ++ README | 77 +++ config.h | 77 +++ driver/.gdbinit | 25 + driver/Imakefile | 111 ++++ driver/README | 6 + driver/XScreenSaver.ad | 149 ++++++ driver/demo.c | 591 +++++++++++++++++++++ driver/dialogs.c | 741 ++++++++++++++++++++++++++ driver/dialogs.xd | 569 ++++++++++++++++++++ driver/lock.c | 525 +++++++++++++++++++ driver/subprocs.c | 575 ++++++++++++++++++++ driver/timers.c | 351 +++++++++++++ driver/visual.c | 160 ++++++ driver/windows.c | 611 ++++++++++++++++++++++ driver/xscreensaver-command.c | 150 ++++++ driver/xscreensaver-command.man | 110 ++++ driver/xscreensaver.c | 896 ++++++++++++++++++++++++++++++++ driver/xscreensaver.h | 55 ++ driver/xscreensaver.man | 442 ++++++++++++++++ hacks/.gdbinit | 3 + hacks/Imakefile | 57 ++ hacks/README | 9 + hacks/attraction.c | 608 ++++++++++++++++++++++ hacks/attraction.man | 132 +++++ hacks/blitspin.c | 191 +++++++ hacks/blitspin.man | 68 +++ hacks/greynetic.c | 166 ++++++ hacks/greynetic.man | 45 ++ hacks/halo.c | 342 ++++++++++++ hacks/halo.man | 54 ++ hacks/helix.c | 211 ++++++++ hacks/helix.man | 43 ++ hacks/hopalong.c | 236 +++++++++ hacks/hopalong.man | 62 +++ hacks/hypercube.c | 334 ++++++++++++ hacks/hypercube.man | 86 +++ hacks/imsmap.c | 439 ++++++++++++++++ hacks/imsmap.man | 56 ++ hacks/maze.c | 781 ++++++++++++++++++++++++++++ hacks/maze.man | 97 ++++ hacks/noseguy.c | 630 ++++++++++++++++++++++ hacks/noseguy.man | 67 +++ hacks/noses/nose.0.left | 38 ++ hacks/noses/nose.0.right | 38 ++ hacks/noses/nose.1.left | 38 ++ hacks/noses/nose.1.right | 38 ++ hacks/noses/nose.down | 38 ++ hacks/noses/nose.front | 38 ++ hacks/noses/nose.left.front | 38 ++ hacks/noses/nose.right.front | 38 ++ hacks/pyro.c | 258 +++++++++ hacks/pyro.man | 53 ++ hacks/qix.c | 503 ++++++++++++++++++ hacks/qix.man | 107 ++++ hacks/rocks.c | 313 +++++++++++ hacks/rocks.man | 64 +++ hacks/rorschach.c | 140 +++++ hacks/rorschach.man | 57 ++ hacks/screenhack.c | 204 ++++++++ hacks/screenhack.h | 120 +++++ hacks/slidescreen.c | 317 +++++++++++ hacks/slidescreen.man | 61 +++ hacks/vroot.h | 123 +++++ hacks/xlock.h | 146 ++++++ hacks/xroger-hack.c | 101 ++++ hacks/xroger.man | 43 ++ screenblank.txt | 46 ++ utils/Imakefile | 20 + utils/README | 6 + utils/ad2c | 38 ++ utils/fade.c | 166 ++++++ utils/hsv.c | 110 ++++ utils/resources.c | 214 ++++++++ utils/spline.c | 286 ++++++++++ utils/spline.h | 33 ++ utils/usleep.c | 97 ++++ utils/version.h | 2 + utils/xroger.c | 102 ++++ 79 files changed, 15016 insertions(+) create mode 100644 Imakefile create mode 100644 README create mode 100644 config.h create mode 100644 driver/.gdbinit create mode 100644 driver/Imakefile create mode 100644 driver/README create mode 100644 driver/XScreenSaver.ad create mode 100644 driver/demo.c create mode 100644 driver/dialogs.c create mode 100644 driver/dialogs.xd create mode 100644 driver/lock.c create mode 100644 driver/subprocs.c create mode 100644 driver/timers.c create mode 100644 driver/visual.c create mode 100644 driver/windows.c create mode 100644 driver/xscreensaver-command.c create mode 100644 driver/xscreensaver-command.man create mode 100644 driver/xscreensaver.c create mode 100644 driver/xscreensaver.h create mode 100644 driver/xscreensaver.man create mode 100644 hacks/.gdbinit create mode 100644 hacks/Imakefile create mode 100644 hacks/README create mode 100644 hacks/attraction.c create mode 100644 hacks/attraction.man create mode 100644 hacks/blitspin.c create mode 100644 hacks/blitspin.man create mode 100644 hacks/greynetic.c create mode 100644 hacks/greynetic.man create mode 100644 hacks/halo.c create mode 100644 hacks/halo.man create mode 100644 hacks/helix.c create mode 100644 hacks/helix.man create mode 100644 hacks/hopalong.c create mode 100644 hacks/hopalong.man create mode 100644 hacks/hypercube.c create mode 100644 hacks/hypercube.man create mode 100644 hacks/imsmap.c create mode 100644 hacks/imsmap.man create mode 100644 hacks/maze.c create mode 100644 hacks/maze.man create mode 100644 hacks/noseguy.c create mode 100644 hacks/noseguy.man create mode 100644 hacks/noses/nose.0.left create mode 100644 hacks/noses/nose.0.right create mode 100644 hacks/noses/nose.1.left create mode 100644 hacks/noses/nose.1.right create mode 100644 hacks/noses/nose.down create mode 100644 hacks/noses/nose.front create mode 100644 hacks/noses/nose.left.front create mode 100644 hacks/noses/nose.right.front create mode 100644 hacks/pyro.c create mode 100644 hacks/pyro.man create mode 100644 hacks/qix.c create mode 100644 hacks/qix.man create mode 100644 hacks/rocks.c create mode 100644 hacks/rocks.man create mode 100644 hacks/rorschach.c create mode 100644 hacks/rorschach.man create mode 100644 hacks/screenhack.c create mode 100644 hacks/screenhack.h create mode 100644 hacks/slidescreen.c create mode 100644 hacks/slidescreen.man create mode 100644 hacks/vroot.h create mode 100644 hacks/xlock.h create mode 100644 hacks/xroger-hack.c create mode 100644 hacks/xroger.man create mode 100644 screenblank.txt create mode 100644 utils/Imakefile create mode 100644 utils/README create mode 100755 utils/ad2c create mode 100644 utils/fade.c create mode 100644 utils/hsv.c create mode 100644 utils/resources.c create mode 100644 utils/spline.c create mode 100644 utils/spline.h create mode 100644 utils/usleep.c create mode 100644 utils/version.h create mode 100644 utils/xroger.c diff --git a/Imakefile b/Imakefile new file mode 100644 index 00000000..baa81b19 --- /dev/null +++ b/Imakefile @@ -0,0 +1,44 @@ +/* + * 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 diff --git a/README b/README new file mode 100644 index 00000000..2783d608 --- /dev/null +++ b/README @@ -0,0 +1,77 @@ + +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 + +[*] 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. diff --git a/config.h b/config.h new file mode 100644 index 00000000..6ec75c87 --- /dev/null +++ b/config.h @@ -0,0 +1,77 @@ +/* + * 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 diff --git a/driver/.gdbinit b/driver/.gdbinit new file mode 100644 index 00000000..67574593 --- /dev/null +++ b/driver/.gdbinit @@ -0,0 +1,25 @@ +# If you're debugging xscreensaver and you are running a virtual root window +# manager, you'd better let the process handle these signals: it remaps the +# virtual root window when they arrive. If you don't do this, your window +# manager will be hosed. +# +# Also, gdb copes badly with breakpoints in functions that are called on the +# other side of a fork(). The Trace/BPT traps cause the spawned process to +# die. +# +#handle 1 pass nostop +#handle 3 pass nostop +#handle 4 pass nostop +#handle 6 pass nostop +#handle 7 pass nostop +#handle 8 pass nostop +#handle 9 pass nostop +#handle 10 pass nostop +#handle 11 pass nostop +#handle 12 pass nostop +#handle 13 pass nostop +#handle 15 pass nostop +#handle 19 pass nostop +b exit +set args -verbose -idelay 0 -lock +#b purify_stop_here diff --git a/driver/Imakefile b/driver/Imakefile new file mode 100644 index 00000000..59eaf6f2 --- /dev/null +++ b/driver/Imakefile @@ -0,0 +1,111 @@ +/* + * 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 diff --git a/driver/README b/driver/README new file mode 100644 index 00000000..df64793b --- /dev/null +++ b/driver/README @@ -0,0 +1,6 @@ + +This directory contains the source for xscreensaver and xscreensaver-command, +the screensaver driver, and the program for externally controlling it. Some +stuff from the ../utils/ directory is used here as well. + +If you have compilation problems, check the parameters in ../config.h. diff --git a/driver/XScreenSaver.ad b/driver/XScreenSaver.ad new file mode 100644 index 00000000..8e2aae12 --- /dev/null +++ b/driver/XScreenSaver.ad @@ -0,0 +1,149 @@ +! 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 +*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 diff --git a/driver/demo.c b/driver/demo.c new file mode 100644 index 00000000..ec957243 --- /dev/null +++ b/driver/demo.c @@ -0,0 +1,591 @@ +/* xscreensaver, Copyright (c) 1993 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. + */ + +#include + +#if !__STDC__ +# define _NO_PROTO +#endif + +#include +#include +#include +#include + +#include "xscreensaver.h" +#include + +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); +} + + +/* 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); +} + + +/* 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; +} diff --git a/driver/dialogs.c b/driver/dialogs.c new file mode 100644 index 00000000..a1184e14 --- /dev/null +++ b/driver/dialogs.c @@ -0,0 +1,741 @@ + +/* +** Generated by X-Designer +*/ +/* +**LIBS: -lXm -lXt -lX11 +*/ + +#if !__STDC__ +# define _NO_PROTO +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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; +} + + diff --git a/driver/dialogs.xd b/driver/dialogs.xd new file mode 100644 index 00000000..6e563335 --- /dev/null +++ b/driver/dialogs.xd @@ -0,0 +1,569 @@ +module 'XScreenSaver' +applicationName = 'XScreenSaver'; +generateNameC = 'dialogs.c'; +generateNameUIL = ''; +generateNameResDB = 'dialogs.ad'; +generateUidFile = ''; +generateMask = 1507557; +useMask = 1; +value +object 'passwd_dialog' : XmDialogShell { + arguments { + name = 'passwdDialog'; + XmNtitle= 'XScreenSaver'; + XmNallowShellResize= true; + }; +object 'passwd_form' : XmForm { + arguments { + name = 'passwdForm'; + XmNautoUnmanage= false; + }; +object 'roger_label' : XmDrawnButton { + arguments { + name = 'rogerLabel'; + XmNwidth= 150; + }; +}; +object 'passwd_label1' : XmLabel { + arguments { + name = 'passwdLabel1'; + XmNlabelString= 'XScreenSaver %s'; + XmNalignment= 0; + }; +}; +object '' : XmLabel { + arguments { + name = 'passwdLabel2'; + XmNlabelString= 'This display is locked.'; + XmNalignment= 0; + }; +}; +object 'passwd_label3' : XmLabel { + arguments { + name = 'passwdLabel3'; + XmNlabelString= 'Please type %s\'s password to unlock it.'; + XmNalignment= 0; + }; +}; +object 'passwd_text' : XmTextField { + arguments { + name = 'passwdText'; + }; +}; +object '' : XmSeparator { + arguments { + }; +}; +object 'passwd_done' : XmPushButton { + arguments { + name = 'passwdDone'; + XmNlabelString= 'Done'; + }; +}; +object 'passwd_cancel' : XmPushButton { + arguments { + name = 'passwdCancel'; + XmNlabelString= 'Cancel'; + }; +}; + attachments { + attachment { + XmNrightAttachment = 0 0 0; + XmNleftAttachment = 1 0 4; + XmNbottomAttachment = 1 0 4; + XmNtopAttachment = 1 0 4; + }; + attachment { + XmNrightAttachment = 1 0 4; + XmNleftAttachment = 3 1 4; + XmNbottomAttachment = 3 3 4; + XmNtopAttachment = 1 0 4; + }; + attachment { + XmNrightAttachment = 1 0 4; + XmNleftAttachment = 3 1 4; + XmNbottomAttachment = 3 4 4; + XmNtopAttachment = 0 0 0; + }; + attachment { + XmNrightAttachment = 1 0 30; + XmNleftAttachment = 3 1 4; + XmNbottomAttachment = 3 5 4; + XmNtopAttachment = 0 0 0; + }; + attachment { + XmNrightAttachment = 1 0 4; + XmNleftAttachment = 3 1 4; + XmNbottomAttachment = 3 6 4; + XmNtopAttachment = 0 0 0; + }; + attachment { + XmNrightAttachment = 1 0 0; + XmNleftAttachment = 3 1 0; + XmNbottomAttachment = 3 7 4; + XmNtopAttachment = 0 0 0; + }; + attachment { + XmNrightAttachment = 0 0 0; + XmNleftAttachment = 3 1 4; + XmNbottomAttachment = 1 0 4; + XmNtopAttachment = 0 0 0; + }; + attachment { + XmNrightAttachment = 0 0 0; + XmNleftAttachment = 3 7 4; + XmNbottomAttachment = 1 0 4; + XmNtopAttachment = 0 0 0; + }; + }; +}; +}; +object 'resources_dialog' : XmDialogShell { + arguments { + name = 'resourcesDialog'; + XmNtitle= 'XScreenSaver'; + XmNallowShellResize= true; + }; +object 'resources_form' : XmForm { + arguments { + name = 'resourcesForm'; + XmNautoUnmanage= false; + }; +object '' : XmLabel { + arguments { + name = 'resourcesLabel'; + XmNlabelString= 'XScreenSaver Parameters'; + }; +}; +object '' : XmSeparator { + arguments { + }; +}; +object '' : XmLabel { + arguments { + name = 'timeoutLabel'; + XmNlabelString= 'Timeout Minutes'; + XmNalignment= * 2; + }; +}; +object '' : XmLabel { + arguments { + name = 'cycleLabel'; + XmNlabelString= 'Cycle Seconds'; + XmNalignment= * 2; + }; +}; +object '' : XmLabel { + arguments { + name = 'fadeSecondsLabel'; + XmNlabelString= 'Fade Seconds'; + XmNalignment= * 2; + }; +}; +object '' : XmLabel { + arguments { + name = 'fadeTicksLabel'; + XmNlabelString= 'Fade Ticks'; + XmNalignment= * 2; + }; +}; +object '' : XmLabel { + arguments { + name = 'lockLabel'; + XmNlabelString= 'Lock Timeout'; + XmNalignment= * 2; + }; +}; +object '' : XmLabel { + arguments { + name = 'passwdLabel'; + XmNlabelString= 'Password Timeout'; + XmNalignment= * 2; + }; +}; +object 'timeout_text' : XmTextField { + arguments { + name = 'timeoutText'; + XmNcolumns= 5; + }; +}; +object 'cycle_text' : XmTextField { + arguments { + name = 'cycleText'; + XmNcolumns= 5; + }; +}; +object 'fade_text' : XmTextField { + arguments { + name = 'fadeSecondsText'; + XmNcolumns= 5; + }; +}; +object 'ticks_text' : XmTextField { + arguments { + name = 'fadeTicksText'; + XmNcolumns= 5; + }; +}; +object 'lock_time_text' : XmTextField { + arguments { + name = 'passwdText'; + XmNcolumns= 5; + }; +}; +object 'passwd_time_text' : XmTextField { + arguments { + name = 'lockText'; + XmNcolumns= 5; + }; +}; +object 'verbose_toggle' : XmToggleButton { + arguments { + name = 'verboseToggle'; + XmNlabelString= 'Verbose'; + XmNalignment= * 0; + }; +}; +object 'cmap_toggle' : XmToggleButton { + arguments { + name = 'cmapToggle'; + XmNlabelString= 'Install Colormap'; + XmNalignment= * 0; + }; +}; +object 'fade_toggle' : XmToggleButton { + arguments { + name = 'fadeToggle'; + XmNlabelString= 'Fade Colormap'; + XmNalignment= * 0; + }; +}; +object 'unfade_toggle' : XmToggleButton { + arguments { + name = 'unfadeToggle'; + XmNlabelString= 'Unfade Colormap'; + XmNalignment= * 0; + }; +}; +object 'lock_toggle' : XmToggleButton { + arguments { + name = 'lockToggle'; + XmNlabelString= 'Require Password'; + XmNalignment= * 0; + }; +}; +object '' : XmSeparator { + arguments { + }; +}; +object 'res_done' : XmPushButton { + arguments { + name = 'resourcesDone'; + XmNlabelString= 'Done'; + }; +}; +object 'res_cancel' : XmPushButton { + arguments { + name = 'resourcesCancel'; + XmNlabelString= 'Cancel'; + }; +}; + attachments { + attachment { + XmNrightAttachment = 1 0 4; + XmNleftAttachment = 1 0 4; + XmNtopAttachment = 1 0 4; + }; + attachment { + XmNrightAttachment = 1 0 0; + XmNleftAttachment = 1 0 0; + XmNbottomAttachment = 0 0 0; + XmNtopAttachment = 3 1 4; + }; + attachment { + XmNrightAttachment = 3 9 4; + XmNleftAttachment = 1 0 20; + XmNbottomAttachment = 4 9; + XmNtopAttachment = 3 2 4; + }; + attachment { + XmNrightAttachment = 3 10 4; + XmNleftAttachment = 1 0 20; + XmNbottomAttachment = 4 10 0; + XmNtopAttachment = 4 10 0; + }; + attachment { + XmNrightAttachment = 3 11 4; + XmNleftAttachment = 1 0 20; + XmNbottomAttachment = 4 11 0; + XmNtopAttachment = 4 11 0; + }; + attachment { + XmNrightAttachment = 3 12 4; + XmNleftAttachment = 1 0 20; + XmNbottomAttachment = 4 12 0; + XmNtopAttachment = 4 12 0; + }; + attachment { + XmNrightAttachment = 3 13 4; + XmNleftAttachment = 1 0 19; + XmNbottomAttachment = 4 13 0; + XmNtopAttachment = 4 13 0; + }; + attachment { + XmNrightAttachment = 3 14 4; + XmNleftAttachment = 1 0 14; + XmNbottomAttachment = 4 14 0; + XmNtopAttachment = 4 14 0; + }; + attachment { + XmNrightAttachment = 0 0 0; + XmNleftAttachment = 1 0 141; + XmNbottomAttachment = 0 0 0; + XmNtopAttachment = 3 2 4; + }; + attachment { + XmNrightAttachment = 0 0 0; + XmNleftAttachment = 4 9 0; + XmNbottomAttachment = 0 0 0; + XmNtopAttachment = 3 9 2; + }; + attachment { + XmNrightAttachment = 0 0 0; + XmNleftAttachment = 4 10 0; + XmNbottomAttachment = 0 0 0; + XmNtopAttachment = 3 10 2; + }; + attachment { + XmNrightAttachment = 0 0 0; + XmNleftAttachment = 4 11 0; + XmNbottomAttachment = 0 0 0; + XmNtopAttachment = 3 11 2; + }; + attachment { + XmNrightAttachment = 0 0 0; + XmNleftAttachment = 4 12 0; + XmNbottomAttachment = 0 0 0; + XmNtopAttachment = 3 12 2; + }; + attachment { + XmNrightAttachment = 0 0 0; + XmNleftAttachment = 4 13 0; + XmNbottomAttachment = 0 0 0; + XmNtopAttachment = 3 13 4; + }; + attachment { + XmNrightAttachment = 1 0 20; + XmNleftAttachment = 3 9 20; + XmNbottomAttachment = 4 9 0; + XmNtopAttachment = 3 2 4; + }; + attachment { + XmNrightAttachment = 1 0 20; + XmNleftAttachment = 4 15 0; + XmNbottomAttachment = 4 10 0; + XmNtopAttachment = 4 10 0; + }; + attachment { + XmNrightAttachment = 1 0 20; + XmNleftAttachment = 4 16 0; + XmNbottomAttachment = 4 11 0; + XmNtopAttachment = 4 11 0; + }; + attachment { + XmNrightAttachment = 1 0 20; + XmNleftAttachment = 4 17 0; + XmNbottomAttachment = 4 12 0; + XmNtopAttachment = 4 12 0; + }; + attachment { + XmNrightAttachment = 1 0 20; + XmNleftAttachment = 4 18 0; + XmNbottomAttachment = 4 13 0; + XmNtopAttachment = 4 13 0; + }; + attachment { + XmNrightAttachment = 1 0; + XmNleftAttachment = 1 0; + XmNbottomAttachment = 3 21 4; + XmNtopAttachment = 3 14 0; + }; + attachment { + XmNrightAttachment = 0 0 0; + XmNleftAttachment = 1 0 4; + XmNbottomAttachment = 1 0 4; + XmNtopAttachment = 0 0 0; + }; + attachment { + XmNrightAttachment = 0 0 0; + XmNleftAttachment = 3 21 4; + XmNbottomAttachment = 1 0 4; + XmNtopAttachment = 0 0 0; + }; + }; +}; +}; +object 'demo_dialog' : XmDialogShell { + arguments { + name = 'demoDialog'; + XmNtitle= 'XScreenSaver'; + XmNmaxWidth= 500; + XmNallowShellResize= true; + }; +object 'demo_form' : XmForm { + arguments { + name = 'demoForm'; + XmNautoUnmanage= false; + }; +object 'label1' : XmLabel { + arguments { + name = 'label1'; + XmNlabelString= 'XScreenSaver %s'; + }; +}; +object 'label2' : XmLabel { + arguments { + name = 'label2'; + XmNlabelString= 'Copyright © 1991-1993 by Jamie Zawinski '; + }; +}; +object 'text_area' : XmScrolledList { + arguments { + name = 'textArea'; + }; +object '' : XmScrollBar { + arguments { + name = 'ListhScrollBar'; + }; +}; +object '' : XmScrollBar { + arguments { + name = 'ListvScrollBar'; + }; +}; +object 'demo_list' : XmList { + arguments { + name = 'demoList'; + XmNvisibleItemCount= 10; + XmNautomaticSelection= true; + XmNlistSizePolicy= 2; + }; +}; +}; +object 'text_line' : XmTextField { + arguments { + name = 'textLine'; + }; +}; +object 'vline' : XmSeparator { + arguments { + name = 'vline'; + }; +}; +object 'next' : XmPushButton { + arguments { + name = 'next'; + XmNlabelString= 'Run Next'; + }; +}; +object 'prev' : XmPushButton { + arguments { + name = 'prev'; + XmNlabelString= 'Run Previous'; + }; +}; +object 'edit' : XmPushButton { + arguments { + name = 'edit'; + XmNlabelString= 'Edit Parameters'; + }; +}; +object 'done' : XmPushButton { + arguments { + name = 'done'; + XmNlabelString= 'Exit Demo Mode'; + }; +}; +object 'restart' : XmPushButton { + arguments { + name = 'restart'; + XmNlabelString= 'Restart Screen Saver'; + }; +}; +object 'spacer' : XmLabel { + arguments { + name = 'spacer'; + XmNlabelString= * ' '; + }; +}; + attachments { + attachment { + XmNrightAttachment = 1 0 4; + XmNleftAttachment = 1 0 4; + XmNbottomAttachment = 0 0 0; + XmNtopAttachment = 1 0 5; + }; + attachment { + XmNrightAttachment = 1 0 4; + XmNleftAttachment = 1 0 4; + XmNbottomAttachment = 0 0 0; + XmNtopAttachment = 3 1 4; + }; + attachment { + XmNrightAttachment = 1 0 4; + XmNleftAttachment = 1 0 4; + XmNbottomAttachment = 3 4 4; + XmNtopAttachment = 3 2 4; + }; + attachment { + XmNrightAttachment = 1 0 4; + XmNleftAttachment = 1 0 4; + XmNbottomAttachment = 3 5 4; + XmNtopAttachment = 0 0 0; + }; + attachment { + XmNrightAttachment = 1 0 4; + XmNleftAttachment = 1 0 4; + XmNbottomAttachment = 3 6 4; + XmNtopAttachment = 0 0 0; + }; + attachment { + XmNrightAttachment = 0 0 0; + XmNleftAttachment = 1 0 3; + XmNbottomAttachment = 1 0 4; + XmNtopAttachment = 0 0 0; + }; + attachment { + XmNrightAttachment = 0 0 0; + XmNleftAttachment = 3 6 4; + XmNbottomAttachment = 1 0 4; + XmNtopAttachment = 4 6 0; + }; + attachment { + XmNrightAttachment = 0 0 0; + XmNleftAttachment = 3 7 4; + XmNbottomAttachment = 1 0 4; + XmNtopAttachment = 4 7 0; + }; + attachment { + XmNrightAttachment = 0 0 0; + XmNleftAttachment = 3 8 4; + XmNbottomAttachment = 1 0 4; + XmNtopAttachment = 4 8 0; + }; + attachment { + XmNrightAttachment = 0 0 0; + XmNleftAttachment = 3 9 4; + XmNbottomAttachment = 1 0 4; + XmNtopAttachment = 4 9 0; + }; + attachment { + XmNrightAttachment = 1 0 4; + XmNleftAttachment = 3 10 4; + XmNbottomAttachment = 1 0 4; + XmNtopAttachment = 4 10 0; + }; + }; +}; +}; +end module; diff --git a/driver/lock.c b/driver/lock.c new file mode 100644 index 00000000..48b2f526 --- /dev/null +++ b/driver/lock.c @@ -0,0 +1,525 @@ +/* xscreensaver, Copyright (c) 1993 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. + */ + +#if __STDC__ +#include +#include +#include +#endif + +#include +#include + +#include + +#if !__STDC__ +# define _NO_PROTO +#endif + +#include +#include +#include + +#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[] = "\ +BackSpace: backspace()\n\ +Delete: backspace()\n\ +CtrlH: backspace()\n\ +CtrlU: kill_line()\n\ +CtrlX: kill_line()\n\ +CtrlJ: done()\n\ +CtrlM: done()\n\ +: keypress()\n\ +"; +#else +static char translations[] = ":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 */ diff --git a/driver/subprocs.c b/driver/subprocs.c new file mode 100644 index 00000000..e6a28127 --- /dev/null +++ b/driver/subprocs.c @@ -0,0 +1,575 @@ +/* xscreensaver, Copyright (c) 1991-1993 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. + */ + +#if __STDC__ +#include +#include +#include +#endif + +#include + +#include /* not used for much... */ + +#ifndef ESRCH +#include +#endif + +#include /* sys/resource.h needs this for timeval */ +#include /* for setpriority() and PRIO_PROCESS */ +#include /* for waitpid() and associated macros */ +#include /* for the signal names */ + +extern char **environ; /* why isn't this in some header file? */ + +#ifndef NO_SETUID +#include /* for getpwnam() and struct passwd */ +#include /* 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); +} + + +/* 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 (); +} + + +/* 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 */ diff --git a/driver/timers.c b/driver/timers.c new file mode 100644 index 00000000..64117cea --- /dev/null +++ b/driver/timers.c @@ -0,0 +1,351 @@ +/* xscreensaver, Copyright (c) 1991-1993 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. + */ + +#include +#include +#include +#include +#include + +#ifdef HAVE_XIDLE +#include +#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; +} diff --git a/driver/visual.c b/driver/visual.c new file mode 100644 index 00000000..b4ca9720 --- /dev/null +++ b/driver/visual.c @@ -0,0 +1,160 @@ +/* xscreensaver, Copyright (c) 1993 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. + */ + +/* 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 +#endif + +#include +#include +#include + +#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); +} diff --git a/driver/windows.c b/driver/windows.c new file mode 100644 index 00000000..1e4b22df --- /dev/null +++ b/driver/windows.c @@ -0,0 +1,611 @@ +/* xscreensaver, Copyright (c) 1991-1993 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. + */ + +#include +#include +#include +#include +#include +#include + +#include /* 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")); + } +} + + +/* 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); +} + + +/* 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 +} + + +/* 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 +} diff --git a/driver/xscreensaver-command.c b/driver/xscreensaver-command.c new file mode 100644 index 00000000..cf76a6f7 --- /dev/null +++ b/driver/xscreensaver-command.c @@ -0,0 +1,150 @@ +/* xscreensaver-command, Copyright (c) 1991-1993 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. + */ + +#include "version.h" +#include +#include +#include +#include +#if __STDC__ +# include +#endif + +#ifdef _VROOT_H_ +ERROR! you must not include vroot.h in this file +#endif + +static char *screensaver_version; +static char *usage = "usage: %s -\n\ +\n\ + This program provides external control of a running xscreensaver process.\n\ + Version %s, copyright (c) 1991-1993 Jamie Zawinski .\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); +} diff --git a/driver/xscreensaver-command.man b/driver/xscreensaver-command.man new file mode 100644 index 00000000..92b0b2bb --- /dev/null +++ b/driver/xscreensaver-command.man @@ -0,0 +1,110 @@ +.de EX \"Begin example +.ne 5 +.if n .sp 1 +.if t .sp .5 +.nf +.in +.5i +.. +.de EE +.fi +.in -.5i +.if n .sp 1 +.if t .sp .5 +.. +.TH XScreenSaver 1 "22-mar-93" "X Version 11" +.SH NAME +xscreensaver-command - control a running xscreensaver process +.SH SYNOPSIS +.B xscreensaver-command +[\-activate] [\-deactivate] [\-cycle] [\-next] [\-prev] [\-exit] [\-restart] [\-demo] [\-lock] +.SH DESCRIPTION +The \fIxscreensaver\-command\fP program controls a running \fIxscreensaver\fP +process by sending it client-messages. +.SH OPTIONS +.I xscreensaver-command +accepts the following options: +.TP 8 +.B \-activate +Tell the screensaver to turn on immediately (that is, pretend that the +user been idle for long enough.) It will turn off as soon as there is +any user activity, as usual. + +It is useful to run this from a menu; you may wish to run it as +.EX +sleep 5 ; xscreensaver-command -activate +.EE +to be sure that you have time to remove your hand from the mouse before +the screensaver comes on. +.TP 8 +.B \-deactivate +Tell the screensaver to turn off, as if there had been user activity. +If locking is enabled, then the screensaver will prompt for a password +as usual. +.TP 8 +.B \-cycle +Tell the screensaver to change which graphics hack it is running, just +as if the ``cycle'' timer had expired. +.TP 8 +.B \-next +This is like either \fI\-activate\fP or \fI\-cycle\fP, depending on which is +more appropriate, except that the screenhack that will be run is the next +one in the list of programs, instead of a randomly-chosen one. This option +is good for looking at a demo of each of the screensavers currently available. +You might want to put this on a menu. +.TP 8 +.B \-prev +This is like \fI\-next\fP, but cycles in the other direction. +.TP 8 +.B \-demo +Cause the screensaver to enter its interactive demo mode, if it has been +compiled with support for it. +.TP 8 +.B \-lock +Like \fI\-activate\fP, but a password will be required before the screensaver +turns off, even if the screensaver's \fIlock\fP resource is false. The +display will be locked immediately even if the screensaver's \fIlockTimeout\fP +resource is non-zero. +.TP 8 +.B \-exit +Causes the screensaver process to exit gracefully. This is a slightly +safer way to kill the screensaver than by using \fIkill\fP. + +Never use \fIkill -9\fP with \fIxscreensaver\fP while the screensaver is +active. If you are using a virtual root window manager, that can leave +things in an inconsistent state, and you may need to restart your window +manager to repair the damage. +.TP 8 +.B \-restart +Causes the screensaver process to exit and then restart with the same command +line arguments. This is a good way of causing the screensaver to re-read the +resource database. + +If the screensaver is run from \fIxdm(1)\fP (that is, it is already running +before you log in) then you may want to issue the ``restart'' command from +one of your startup scripts, so that the screensaver gets your resource +settings instead of the default ones. +.SH ENVIRONMENT +.PP +.TP 8 +.B DISPLAY +to get the default host and display number. +.TP 8 +.B PATH +to find the executable to restart. +.SH "SEE ALSO" +.BR X (1), +.BR xscreensaver (1) +.SH BUGS +Diagnostics are reported on the \fBstderr\fP of the \fIxscreensaver\fP +process, not this process, so the caller of \fIxscreensaver-command\fP +may not see the error messages. +.SH COPYRIGHT +Copyright \(co 1992, 1993 by Jamie Zawinski. Permission to use, copy, modify, +distribute, and sell this software and its documentation for any purpose is +hereby granted without fee, provided that the above copyright notice appear +in all copies and that both that copyright notice and this permission notice +appear in supporting documentation. No representations are made about the +suitability of this software for any purpose. It is provided "as is" without +express or implied warranty. +.SH AUTHOR +Jamie Zawinski , 13-aug-92. diff --git a/driver/xscreensaver.c b/driver/xscreensaver.c new file mode 100644 index 00000000..54aee1dc --- /dev/null +++ b/driver/xscreensaver.c @@ -0,0 +1,896 @@ +/* xscreensaver, Copyright (c) 1991-1993 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. + */ + +#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 +#include +#endif + +#include +#include +#include +#include +#include + +#ifdef HAVE_XIDLE +#include +#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 + + +#ifdef NO_DEMO_MODE +# define demo_mode() abort() +#else +extern void demo_mode P((void)); +#endif + +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 .\n\ +The standard Xt command-line options are accepted; other options include:\n\ +\n\ + -timeout when the screensaver should activate\n\ + -cycle how long to let each hack run\n\ + -idelay 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 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 .\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 ()); + } + } +} + + + +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; +} diff --git a/driver/xscreensaver.h b/driver/xscreensaver.h new file mode 100644 index 00000000..7bdc7762 --- /dev/null +++ b/driver/xscreensaver.h @@ -0,0 +1,55 @@ +/* xscreensaver, Copyright (c) 1993 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. + */ + +#if __STDC__ +# include +# include +#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)); diff --git a/driver/xscreensaver.man b/driver/xscreensaver.man new file mode 100644 index 00000000..a524d02e --- /dev/null +++ b/driver/xscreensaver.man @@ -0,0 +1,442 @@ +.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 , 13-aug-92. +Please let me know if you find any bugs or make any improvements. + +Thanks to David Wojtowicz for implementing \fIlockTimeout\fP. diff --git a/hacks/.gdbinit b/hacks/.gdbinit new file mode 100644 index 00000000..0bd01420 --- /dev/null +++ b/hacks/.gdbinit @@ -0,0 +1,3 @@ +b exit +b abort +set args -geom =700x700+0+0 diff --git a/hacks/Imakefile b/hacks/Imakefile new file mode 100644 index 00000000..daf08f38 --- /dev/null +++ b/hacks/Imakefile @@ -0,0 +1,57 @@ +/* + * 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) diff --git a/hacks/README b/hacks/README new file mode 100644 index 00000000..c5ebcd64 --- /dev/null +++ b/hacks/README @@ -0,0 +1,9 @@ + +This directory contains various graphics hacks. These are independent from +the xscreensaver program (in the ../driver/ directory) but some of them use +the utility functions found in the ../utils/ directory. + +If you have compilation problems, check the parameters in ../config.h. + +The file xlock.h makes it really easy to turn `xlock' modules into standalone +programs that can be used with xscreensaver; check it out. diff --git a/hacks/attraction.c b/hacks/attraction.c new file mode 100644 index 00000000..d178b214 --- /dev/null +++ b/hacks/attraction.c @@ -0,0 +1,608 @@ +/* xscreensaver, Copyright (c) 1992 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. + */ + +/* 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 . + + 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 +#include +#if __STDC__ +#include +#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); +} + + +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); + } +} diff --git a/hacks/attraction.man b/hacks/attraction.man new file mode 100644 index 00000000..daa69391 --- /dev/null +++ b/hacks/attraction.man @@ -0,0 +1,132 @@ +.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 , 13-aug-92. diff --git a/hacks/blitspin.c b/hacks/blitspin.c new file mode 100644 index 00000000..a532e296 --- /dev/null +++ b/hacks/blitspin.c @@ -0,0 +1,191 @@ +/* xscreensaver, Copyright (c) 1992 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. + */ + +/* 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 +#include + +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)<<(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); +} + + +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); + } +} diff --git a/hacks/blitspin.man b/hacks/blitspin.man new file mode 100644 index 00000000..aac00a46 --- /dev/null +++ b/hacks/blitspin.man @@ -0,0 +1,68 @@ +.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 , 17-aug-92. + +Based on SmallTalk code which appeared in the August 1981 issue of Byte +magazine. diff --git a/hacks/greynetic.c b/hacks/greynetic.c new file mode 100644 index 00000000..79e89c69 --- /dev/null +++ b/hacks/greynetic.c @@ -0,0 +1,166 @@ +/* xscreensaver, Copyright (c) 1992 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. + */ + +#include "screenhack.h" + +#define NBITS 12 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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); +} + + +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); + } +} diff --git a/hacks/greynetic.man b/hacks/greynetic.man new file mode 100644 index 00000000..62bc532a --- /dev/null +++ b/hacks/greynetic.man @@ -0,0 +1,45 @@ +.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 , 13-aug-92. diff --git a/hacks/halo.c b/hacks/halo.c new file mode 100644 index 00000000..08db7894 --- /dev/null +++ b/hacks/halo.c @@ -0,0 +1,342 @@ +/* xscreensaver, Copyright (c) 1993 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. + */ + +/* 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); +} + + +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); +} diff --git a/hacks/halo.man b/hacks/halo.man new file mode 100644 index 00000000..b0f8f6c7 --- /dev/null +++ b/hacks/halo.man @@ -0,0 +1,54 @@ +.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 , 6-jul-93. diff --git a/hacks/helix.c b/hacks/helix.c new file mode 100644 index 00000000..9e6d905b --- /dev/null +++ b/hacks/helix.c @@ -0,0 +1,211 @@ +/* xscreensaver, Copyright (c) 1992 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. + */ + +#include "screenhack.h" +#include +#if __STDC__ +#include +#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); +} + + +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); +} diff --git a/hacks/helix.man b/hacks/helix.man new file mode 100644 index 00000000..c2622666 --- /dev/null +++ b/hacks/helix.man @@ -0,0 +1,43 @@ +.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 , 13-aug-92. diff --git a/hacks/hopalong.c b/hacks/hopalong.c new file mode 100644 index 00000000..8a3943a3 --- /dev/null +++ b/hacks/hopalong.c @@ -0,0 +1,236 @@ +/* xscreensaver, Copyright (c) 1992 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. + */ + +/* 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 + +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); + } +} + + +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); + } +} diff --git a/hacks/hopalong.man b/hacks/hopalong.man new file mode 100644 index 00000000..0167356b --- /dev/null +++ b/hacks/hopalong.man @@ -0,0 +1,62 @@ +.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 , 23-mar-88. + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 13-aug-92. diff --git a/hacks/hypercube.c b/hacks/hypercube.c new file mode 100644 index 00000000..c58906e4 --- /dev/null +++ b/hacks/hypercube.c @@ -0,0 +1,334 @@ +/* xscreensaver, Copyright (c) 1992 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. + * + * This code derived from TI Explorer Lisp code by Joe Keane, Fritz Mueller, + * and Jamie Zawinski. + */ + +#include "screenhack.h" +#include + +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 */ +# 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); + } +} + + +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); +} diff --git a/hacks/hypercube.man b/hacks/hypercube.man new file mode 100644 index 00000000..544ed970 --- /dev/null +++ b/hacks/hypercube.man @@ -0,0 +1,86 @@ +.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 , 6-dec-92. diff --git a/hacks/imsmap.c b/hacks/imsmap.c new file mode 100644 index 00000000..8c36bccb --- /dev/null +++ b/hacks/imsmap.c @@ -0,0 +1,439 @@ +/* imsmap, Copyright (c) 1992 Juergen Nickelsen + * 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 +#include + +#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); + } + } +} diff --git a/hacks/imsmap.man b/hacks/imsmap.man new file mode 100644 index 00000000..164faff0 --- /dev/null +++ b/hacks/imsmap.man @@ -0,0 +1,56 @@ +.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 , 23-aug-92. + +Hacked on by Jamie Zawinski , 24-aug-92. diff --git a/hacks/maze.c b/hacks/maze.c new file mode 100644 index 00000000..abaf4e96 --- /dev/null +++ b/hacks/maze.c @@ -0,0 +1,781 @@ +/****************************************************************************** + * [ maze ] ... + * + * modified: [ 3-7-93 ] Jamie Zawinski + * added the XRoger logo, cleaned up resources, made + * grid size a parameter. + * modified: [ 3-3-93 ] Jim Randell + * 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 +#include +#include +#include + +#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 +# 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> 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> 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> 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; + } +} + +/* ---- */ + + +/* + * jmr additions for Jamie Zawinski's 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); + } + } +} diff --git a/hacks/maze.man b/hacks/maze.man new file mode 100644 index 00000000..10d0cea0 --- /dev/null +++ b/hacks/maze.man @@ -0,0 +1,97 @@ +.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 diff --git a/hacks/noseguy.c b/hacks/noseguy.c new file mode 100644 index 00000000..4707d422 --- /dev/null +++ b/hacks/noseguy.c @@ -0,0 +1,630 @@ +/* xscreensaver, Copyright (c) 1992 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. + */ + +/* Make a little guy with a big nose and a hat wanter around the screen, + spewing out messages. Derived from xnlock by Dan Heller . + */ + +#include "screenhack.h" +#include + +#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; +} + + + +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); + } +} + diff --git a/hacks/noseguy.man b/hacks/noseguy.man new file mode 100644 index 00000000..bd731a79 --- /dev/null +++ b/hacks/noseguy.man @@ -0,0 +1,67 @@ +.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 . +.SH AUTHOR +Dan Heller , 1985. + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 13-aug-92. diff --git a/hacks/noses/nose.0.left b/hacks/noses/nose.0.left new file mode 100644 index 00000000..cb3d1528 --- /dev/null +++ b/hacks/noses/nose.0.left @@ -0,0 +1,38 @@ +#define nose_0_left_width 64 +#define nose_0_left_height 64 +static unsigned char nose_0_left_bits[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x40,0x00, + 0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40, + 0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00, + 0x40,0x00,0x00,0x04,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00, + 0x08,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x20,0x00, + 0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0xf0,0x03,0x00,0x00,0x80,0x00, + 0x00,0x00,0x0e,0x0c,0x00,0x00,0x80,0x01,0x00,0x00,0x03,0x30,0x00,0x00,0x00, + 0x01,0x00,0x80,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x40,0x00,0xc0,0x00,0x00, + 0x00,0x02,0x00,0x20,0x00,0x80,0x00,0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00, + 0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x08,0x00,0x00, + 0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00, + 0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08, + 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00, + 0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10, + 0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x01,0x00,0x00, + 0x18,0x00,0x20,0x00,0x00,0x01,0x00,0x00,0x08,0x00,0x40,0x00,0x80,0x00,0x00, + 0x00,0x08,0x00,0x80,0x00,0x40,0x00,0x00,0x00,0x0c,0x00,0x00,0x01,0x20,0x00, + 0x00,0x00,0x04,0x00,0x00,0x06,0x18,0x00,0x00,0x00,0x06,0x00,0x00,0xf8,0x07, + 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x0f,0x00,0x00,0x00, + 0x00,0xff,0x00,0x04,0x10,0x00,0x00,0x00,0xc0,0x00,0x03,0x03,0x10,0x00,0x00, + 0x00,0x30,0x00,0x0c,0x01,0x20,0x00,0x00,0x00,0x08,0x00,0x98,0x00,0x20,0x00, + 0x00,0x00,0x0c,0x03,0x60,0x00,0x20,0x00,0x00,0x00,0xc2,0x00,0xc0,0x00,0x20, + 0x00,0x00,0x00,0x42,0x00,0x80,0x00,0x20,0x00,0x00,0x00,0x21,0x00,0x00,0x01, + 0x20,0x00,0x00,0x00,0x21,0x00,0x00,0x01,0x20,0x00,0x00,0x00,0x21,0x00,0x00, + 0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x01,0x00, + 0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x02, + 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x20,0x00,0x00,0x00, + 0x18,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x10,0x00,0x00, + 0x00,0xc0,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00}; diff --git a/hacks/noses/nose.0.right b/hacks/noses/nose.0.right new file mode 100644 index 00000000..f387baa7 --- /dev/null +++ b/hacks/noses/nose.0.right @@ -0,0 +1,38 @@ +#define nose_0_right_width 64 +#define nose_0_right_height 64 +static unsigned char nose_0_right_bits[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x20,0x00, + 0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20, + 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00, + 0x20,0x00,0x00,0x02,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0x1f,0x00,0x00, + 0x04,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x10,0x00, + 0x00,0xfc,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x01,0x00,0x00,0xc0,0x0f, + 0x00,0x00,0x80,0x01,0x00,0x00,0x30,0x70,0x00,0x00,0x80,0x00,0x00,0x00,0x0c, + 0xc0,0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x40,0x00,0x00,0x00, + 0x03,0x00,0x02,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x20,0x00,0x00, + 0x00,0x00,0x00,0x08,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x00, + 0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08, + 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00, + 0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10, + 0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00, + 0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x18,0x00,0x00,0x80,0x00, + 0x00,0x08,0x00,0x10,0x00,0x00,0x80,0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00, + 0x01,0x00,0x02,0x00,0x30,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x20,0x00,0x00, + 0x00,0x04,0x80,0x00,0x00,0x60,0x00,0x00,0x00,0x18,0x60,0x00,0x00,0x40,0x00, + 0x00,0x00,0xe0,0x1f,0x00,0x00,0x80,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x1f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x08,0x20,0x00,0xff,0x00,0x00,0x00,0x00,0x08,0xc0,0xc0,0x00,0x03,0x00, + 0x00,0x00,0x04,0x80,0x30,0x00,0x0c,0x00,0x00,0x00,0x04,0x00,0x19,0x00,0x10, + 0x00,0x00,0x00,0x04,0x00,0x06,0xc0,0x30,0x00,0x00,0x00,0x04,0x00,0x03,0x00, + 0x43,0x00,0x00,0x00,0x04,0x00,0x01,0x00,0x42,0x00,0x00,0x00,0x04,0x80,0x00, + 0x00,0x84,0x00,0x00,0x00,0x04,0x80,0x00,0x00,0x84,0x00,0x00,0x00,0x04,0x00, + 0x00,0x00,0x84,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x02, + 0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x20,0x00,0x00, + 0x00,0x04,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x0e,0x00, + 0x00,0x00,0xf0,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00}; diff --git a/hacks/noses/nose.1.left b/hacks/noses/nose.1.left new file mode 100644 index 00000000..8a6b8295 --- /dev/null +++ b/hacks/noses/nose.1.left @@ -0,0 +1,38 @@ +#define nose_1_left_width 64 +#define nose_1_left_height 64 +static unsigned char nose_1_left_bits[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x40,0x00, + 0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40, + 0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00, + 0x40,0x00,0x00,0x04,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00, + 0x08,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x20,0x00, + 0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0xf0,0x03,0x00,0x00,0x80,0x00, + 0x00,0x00,0x0e,0x0c,0x00,0x00,0x80,0x01,0x00,0x00,0x03,0x30,0x00,0x00,0x00, + 0x01,0x00,0x80,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x40,0x00,0xc0,0x00,0x00, + 0x00,0x02,0x00,0x20,0x00,0x80,0x00,0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00, + 0x00,0x00,0x04,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x08,0x00,0x00, + 0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00, + 0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08, + 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00, + 0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10, + 0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x01,0x00,0x00, + 0x18,0x00,0x10,0x00,0x00,0x01,0x00,0x00,0x08,0x00,0x20,0x00,0x80,0x00,0x00, + 0x00,0x08,0x00,0x40,0x00,0x40,0x00,0x00,0x00,0x0c,0x00,0x80,0x00,0x20,0x00, + 0x00,0x00,0xe4,0x00,0x00,0x03,0x18,0x00,0x00,0x00,0x26,0x03,0x00,0xfc,0x07, + 0x00,0x00,0x00,0x12,0x0c,0x00,0x00,0xf8,0xff,0xff,0xff,0x11,0x10,0x80,0x1f, + 0x00,0x00,0x00,0x00,0x08,0x20,0x60,0x60,0xc0,0x07,0x00,0x00,0x04,0x40,0x10, + 0xc0,0x20,0x08,0x00,0x1f,0x02,0x40,0x08,0x00,0x21,0x10,0xc0,0x60,0x02,0x40, + 0x04,0x00,0x12,0x20,0x20,0x80,0x02,0x20,0xc2,0x00,0x14,0x40,0x18,0x00,0x03, + 0x20,0x22,0x00,0x0c,0x80,0x04,0x03,0x02,0x10,0x12,0x00,0x08,0x80,0x86,0x00, + 0x04,0x10,0x12,0x00,0x10,0x80,0x42,0x00,0x18,0x08,0x12,0x00,0x10,0x40,0x42, + 0x00,0x00,0x04,0x02,0x00,0x20,0x40,0x42,0x00,0x00,0x04,0x02,0x00,0x00,0x20, + 0x42,0x00,0x00,0x02,0x04,0x00,0x00,0x20,0x02,0x00,0x00,0x01,0x04,0x00,0x00, + 0x20,0x02,0x00,0x00,0x01,0x08,0x00,0x00,0x20,0x04,0x00,0x80,0x00,0x10,0x00, + 0x00,0x20,0x0c,0x00,0x80,0x00,0x60,0x00,0x00,0x10,0x08,0x00,0x40,0x00,0x80, + 0xff,0xff,0x0f,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0x0f,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00}; diff --git a/hacks/noses/nose.1.right b/hacks/noses/nose.1.right new file mode 100644 index 00000000..f7c8962c --- /dev/null +++ b/hacks/noses/nose.1.right @@ -0,0 +1,38 @@ +#define nose_1_right_width 64 +#define nose_1_right_height 64 +static unsigned char nose_1_right_bits[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x20,0x00, + 0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20, + 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00, + 0x20,0x00,0x00,0x02,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0x1f,0x00,0x00, + 0x04,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x10,0x00, + 0x00,0xfc,0xff,0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0x01,0x00,0x00,0xc0,0x0f, + 0x00,0x00,0x80,0x01,0x00,0x00,0x30,0x70,0x00,0x00,0x80,0x00,0x00,0x00,0x0c, + 0xc0,0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x40,0x00,0x00,0x00, + 0x03,0x00,0x02,0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x20,0x00,0x00, + 0x00,0x00,0x00,0x08,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x00, + 0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08, + 0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00, + 0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10, + 0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00, + 0x10,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x18,0x00,0x00,0x80,0x00, + 0x00,0x08,0x00,0x10,0x00,0x00,0x80,0x00,0x00,0x08,0x00,0x10,0x00,0x00,0x00, + 0x01,0x00,0x04,0x00,0x30,0x00,0x00,0x00,0x02,0x00,0x02,0x00,0x27,0x00,0x00, + 0x00,0x04,0x00,0x01,0xc0,0x64,0x00,0x00,0x00,0x18,0xc0,0x00,0x30,0x48,0x00, + 0x00,0x00,0xe0,0x3f,0x00,0x08,0x88,0xff,0xff,0xff,0x1f,0x00,0x00,0x04,0x10, + 0x00,0x00,0x00,0x00,0xf8,0x01,0x02,0x20,0x00,0x00,0xe0,0x03,0x06,0x06,0x02, + 0x40,0xf8,0x00,0x10,0x04,0x03,0x08,0x02,0x40,0x06,0x03,0x08,0x84,0x00,0x10, + 0x04,0x40,0x01,0x04,0x04,0x48,0x00,0x20,0x04,0xc0,0x00,0x18,0x02,0x28,0x00, + 0x43,0x08,0x40,0xc0,0x20,0x01,0x30,0x00,0x44,0x08,0x20,0x00,0x61,0x01,0x10, + 0x00,0x48,0x10,0x18,0x00,0x42,0x01,0x08,0x00,0x48,0x20,0x00,0x00,0x42,0x02, + 0x08,0x00,0x48,0x20,0x00,0x00,0x42,0x02,0x04,0x00,0x40,0x40,0x00,0x00,0x42, + 0x04,0x00,0x00,0x40,0x80,0x00,0x00,0x40,0x04,0x00,0x00,0x20,0x80,0x00,0x00, + 0x40,0x04,0x00,0x00,0x20,0x00,0x01,0x00,0x20,0x04,0x00,0x00,0x10,0x00,0x01, + 0x00,0x30,0x04,0x00,0x00,0x08,0x00,0x02,0x00,0x10,0x08,0x00,0x00,0x06,0x00, + 0x0c,0x00,0x0c,0xf0,0xff,0xff,0x01,0x00,0xf0,0xff,0x03,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00}; diff --git a/hacks/noses/nose.down b/hacks/noses/nose.down new file mode 100644 index 00000000..e8bdba4f --- /dev/null +++ b/hacks/noses/nose.down @@ -0,0 +1,38 @@ +#define nose_down_width 64 +#define nose_down_height 64 +static unsigned char nose_down_bits[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xfc,0xff,0x01,0x00,0x00,0x00,0x00,0xc0,0x03,0x00,0x1e,0x00, + 0x00,0x00,0x00,0x38,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00, + 0x03,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x04,0x00,0x00,0x40,0x00,0x00,0x00, + 0x00,0x08,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x10,0x00,0x80, + 0x1f,0x00,0x40,0x00,0x00,0x08,0x00,0x60,0x60,0x00,0x80,0x00,0x00,0x08,0x00, + 0x10,0x80,0x00,0x80,0x00,0x00,0x04,0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x04, + 0x00,0x08,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x18,0x80,0x01,0x00,0x02,0x00, + 0x02,0x00,0x68,0x60,0x01,0x00,0x02,0x00,0x02,0x00,0x88,0x1f,0x01,0x00,0x02, + 0x00,0x02,0x00,0x08,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x10,0x80,0x00,0x00, + 0x03,0x00,0x06,0x00,0x60,0x60,0x00,0x80,0x02,0x00,0x0c,0x00,0x80,0x1f,0x00, + 0x40,0x01,0x00,0x14,0x00,0x00,0x00,0x00,0x20,0x01,0x00,0x28,0x00,0x00,0x00, + 0x00,0x90,0x00,0x00,0x50,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0xa0,0x01,0x00, + 0x00,0x00,0x26,0x00,0x00,0x40,0x1e,0x00,0x00,0xc0,0x11,0x00,0x00,0x80,0xe1, + 0x03,0x00,0x3c,0x0c,0x00,0x00,0x00,0x0e,0xfc,0xff,0x83,0x03,0x00,0x00,0x00, + 0xf0,0x01,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0xfe,0xff,0x0f,0x00,0x00,0x00, + 0x00,0x80,0x03,0x00,0x0c,0x00,0x00,0x00,0x00,0x80,0x02,0x00,0x14,0x00,0x00, + 0x00,0x00,0x60,0x04,0x00,0x12,0x00,0x00,0xc0,0x7f,0x10,0x04,0x00,0x22,0xe0, + 0x01,0x70,0xc0,0x18,0x08,0x00,0x61,0x1c,0x06,0x10,0x00,0x0f,0x30,0xc0,0x80, + 0x07,0x08,0x08,0x00,0x06,0xc0,0x3f,0x80,0x01,0x08,0x08,0x00,0x18,0x00,0x02, + 0xc0,0x00,0x10,0x04,0x00,0x30,0x00,0x05,0x30,0x00,0x10,0x04,0x00,0x00,0x80, + 0x08,0x18,0x00,0x20,0x04,0x00,0x00,0x80,0x08,0x00,0x00,0x20,0x04,0x00,0x00, + 0x40,0x10,0x00,0x00,0x20,0x24,0x00,0x00,0x40,0x10,0x00,0x00,0x22,0x24,0x00, + 0x00,0x40,0x10,0x00,0x00,0x22,0x44,0x00,0x00,0x40,0x10,0x00,0x00,0x11,0x84, + 0x01,0x00,0xc0,0x18,0x00,0xc0,0x10,0x08,0x00,0x00,0x80,0x08,0x00,0x00,0x08, + 0x30,0x00,0x00,0x80,0x08,0x00,0x00,0x04,0xe0,0xff,0xff,0xff,0xf8,0xff,0xff, + 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00}; diff --git a/hacks/noses/nose.front b/hacks/noses/nose.front new file mode 100644 index 00000000..64b82015 --- /dev/null +++ b/hacks/noses/nose.front @@ -0,0 +1,38 @@ +#define nose_front_width 64 +#define nose_front_height 64 +static unsigned char nose_front_bits[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x40,0x00, + 0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40, + 0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00, + 0x40,0x00,0x00,0x04,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00, + 0x08,0x00,0xc0,0x1f,0x00,0x20,0x00,0x00,0x08,0x00,0x30,0x60,0x00,0x20,0x00, + 0x00,0xf8,0xff,0x0f,0x80,0xff,0x3f,0x00,0x00,0x00,0x02,0x02,0x00,0x82,0x00, + 0x00,0x00,0x00,0x03,0x01,0x00,0x84,0x01,0x00,0x00,0x00,0x81,0x00,0x00,0x08, + 0x01,0x00,0x00,0x80,0x80,0x00,0x00,0x08,0x02,0x00,0x00,0x80,0x40,0x00,0x00, + 0x10,0x02,0x00,0x00,0x40,0x40,0x00,0x00,0x10,0x04,0x00,0x00,0x40,0x20,0x00, + 0x00,0x20,0x04,0x00,0x00,0x60,0x20,0x00,0x00,0x20,0x0c,0x00,0x00,0x20,0x20, + 0x00,0x00,0x20,0x08,0x00,0x00,0x20,0x20,0x00,0x00,0x20,0x08,0x00,0x00,0x10, + 0x20,0x00,0x00,0x20,0x10,0x00,0x00,0x10,0x20,0x00,0x00,0x20,0x10,0x00,0x00, + 0x10,0x20,0x00,0x00,0x20,0x10,0x00,0x00,0x10,0x40,0x00,0x00,0x10,0x10,0x00, + 0x00,0x10,0x40,0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x80,0x00,0x00,0x08,0x10, + 0x00,0x00,0x10,0x80,0x00,0x00,0x08,0x10,0x00,0x00,0x30,0x00,0x01,0x00,0x04, + 0x18,0x00,0x00,0x20,0x00,0x02,0x00,0x02,0x08,0x00,0x00,0x20,0x00,0x0c,0x80, + 0x01,0x08,0x00,0x00,0x60,0x00,0x30,0x60,0x00,0x0c,0x00,0x00,0x40,0x00,0xc0, + 0x1f,0x00,0x04,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0f,0xc0,0x0f,0x00,0x00,0x00, + 0x00,0x40,0x10,0x20,0x10,0x00,0x00,0x00,0x00,0x20,0x60,0x30,0x20,0x00,0x00, + 0x00,0x00,0x20,0xc0,0x18,0x20,0x00,0x00,0xc0,0x7f,0x10,0x80,0x0d,0x40,0xe0, + 0x01,0x70,0xc0,0x18,0x00,0x05,0x40,0x1c,0x06,0x10,0x00,0x0f,0x00,0x05,0x80, + 0x07,0x08,0x08,0x00,0x06,0x00,0x05,0x80,0x01,0x08,0x08,0x00,0x18,0x00,0x05, + 0xc0,0x00,0x10,0x04,0x00,0x30,0x00,0x05,0x30,0x00,0x10,0x04,0x00,0x00,0x80, + 0x08,0x18,0x00,0x20,0x04,0x00,0x00,0x80,0x08,0x00,0x00,0x20,0x04,0x00,0x00, + 0x40,0x10,0x00,0x00,0x20,0x24,0x00,0x00,0x40,0x10,0x00,0x00,0x22,0x24,0x00, + 0x00,0x40,0x10,0x00,0x00,0x22,0x44,0x00,0x00,0x40,0x10,0x00,0x00,0x11,0x84, + 0x01,0x00,0xc0,0x18,0x00,0xc0,0x10,0x08,0x00,0x00,0x80,0x08,0x00,0x00,0x08, + 0x30,0x00,0x00,0x80,0x08,0x00,0x00,0x04,0xe0,0xff,0xff,0xff,0xf8,0xff,0xff, + 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00}; diff --git a/hacks/noses/nose.left.front b/hacks/noses/nose.left.front new file mode 100644 index 00000000..3a871eaa --- /dev/null +++ b/hacks/noses/nose.left.front @@ -0,0 +1,38 @@ +#define nose_left_front_width 64 +#define nose_left_front_height 64 +static unsigned char nose_left_front_bits[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x40,0x00, + 0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40, + 0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x04,0x00,0x00,0x00,0x00, + 0x40,0x00,0x00,0x04,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0x3f,0x00,0x00, + 0x08,0x00,0xe0,0x0f,0x00,0x20,0x00,0x00,0x08,0x00,0x18,0x30,0x00,0x20,0x00, + 0x00,0xf8,0xff,0x07,0xc0,0xff,0x3f,0x00,0x00,0x00,0x02,0x01,0x00,0x81,0x00, + 0x00,0x00,0x00,0x83,0x00,0x00,0x82,0x01,0x00,0x00,0x00,0x41,0x00,0x00,0x04, + 0x01,0x00,0x00,0x80,0x40,0x00,0x00,0x04,0x02,0x00,0x00,0x80,0x20,0x00,0x00, + 0x08,0x02,0x00,0x00,0x40,0x20,0x00,0x00,0x08,0x04,0x00,0x00,0x40,0x10,0x00, + 0x00,0x10,0x04,0x00,0x00,0x60,0x10,0x00,0x00,0x10,0x0c,0x00,0x00,0x20,0x10, + 0x00,0x00,0x10,0x08,0x00,0x00,0x30,0x10,0x00,0x00,0x10,0x08,0x00,0x00,0x10, + 0x10,0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x10,0x00,0x00, + 0x10,0x10,0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x20,0x00,0x00,0x08,0x10,0x00, + 0x00,0x10,0x20,0x00,0x00,0x08,0x10,0x00,0x00,0x10,0x40,0x00,0x00,0x04,0x10, + 0x00,0x00,0x30,0x40,0x00,0x00,0x04,0x10,0x00,0x00,0x20,0x80,0x00,0x00,0x02, + 0x18,0x00,0x00,0x20,0x00,0x01,0x00,0x01,0x08,0x00,0x00,0x60,0x00,0x06,0xc0, + 0x00,0x08,0x00,0x00,0x80,0x00,0x18,0x30,0x00,0x0c,0x00,0x00,0x80,0x00,0xe0, + 0x0f,0x00,0x04,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0x01,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x0f,0x00,0x00,0x00, + 0x00,0xff,0x00,0x04,0x10,0x00,0x00,0x00,0xe0,0x00,0x07,0x02,0x10,0x00,0x00, + 0x00,0x30,0x00,0x8c,0x01,0x20,0x00,0x00,0x00,0x0c,0x00,0x90,0x00,0x20,0x00, + 0x00,0x00,0x04,0x03,0x60,0x00,0x20,0x00,0x00,0x00,0xc2,0x00,0xc0,0x00,0x20, + 0x00,0x00,0x00,0x42,0x00,0x00,0x01,0x20,0x00,0x00,0x00,0x21,0x00,0x00,0x02, + 0x20,0x00,0x00,0x00,0x21,0x00,0x00,0x06,0x20,0x00,0x00,0x00,0x21,0x00,0x00, + 0x00,0x20,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x03,0x00, + 0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x02, + 0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x20,0x00,0x00,0x00, + 0x18,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x10,0x00,0x00, + 0x00,0xc0,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00}; diff --git a/hacks/noses/nose.right.front b/hacks/noses/nose.right.front new file mode 100644 index 00000000..f8214174 --- /dev/null +++ b/hacks/noses/nose.right.front @@ -0,0 +1,38 @@ +#define nose_right_front_width 64 +#define nose_right_front_height 64 +static unsigned char nose_right_front_bits[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x20,0x00, + 0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20, + 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x00, + 0x20,0x00,0x00,0x02,0x00,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0x1f,0x00,0x00, + 0x04,0x00,0xf0,0x07,0x00,0x10,0x00,0x00,0x04,0x00,0x0c,0x18,0x00,0x10,0x00, + 0x00,0xfc,0xff,0x03,0xe0,0xff,0x1f,0x00,0x00,0x00,0x81,0x00,0x80,0x40,0x00, + 0x00,0x00,0x80,0x41,0x00,0x00,0xc1,0x00,0x00,0x00,0x80,0x20,0x00,0x00,0x82, + 0x00,0x00,0x00,0x40,0x20,0x00,0x00,0x02,0x01,0x00,0x00,0x40,0x10,0x00,0x00, + 0x04,0x01,0x00,0x00,0x20,0x10,0x00,0x00,0x04,0x02,0x00,0x00,0x20,0x08,0x00, + 0x00,0x08,0x02,0x00,0x00,0x30,0x08,0x00,0x00,0x08,0x06,0x00,0x00,0x10,0x08, + 0x00,0x00,0x08,0x04,0x00,0x00,0x10,0x08,0x00,0x00,0x08,0x0c,0x00,0x00,0x08, + 0x08,0x00,0x00,0x08,0x08,0x00,0x00,0x08,0x08,0x00,0x00,0x08,0x08,0x00,0x00, + 0x08,0x08,0x00,0x00,0x08,0x08,0x00,0x00,0x08,0x10,0x00,0x00,0x04,0x08,0x00, + 0x00,0x08,0x10,0x00,0x00,0x04,0x08,0x00,0x00,0x08,0x20,0x00,0x00,0x02,0x08, + 0x00,0x00,0x08,0x20,0x00,0x00,0x02,0x0c,0x00,0x00,0x18,0x40,0x00,0x00,0x01, + 0x04,0x00,0x00,0x10,0x80,0x00,0x80,0x00,0x04,0x00,0x00,0x10,0x00,0x03,0x60, + 0x00,0x06,0x00,0x00,0x30,0x00,0x0c,0x18,0x00,0x01,0x00,0x00,0x20,0x00,0xf0, + 0x07,0x00,0x01,0x00,0x00,0x60,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0x40,0x00, + 0x00,0x00,0x80,0x00,0x00,0x00,0x80,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0x1f,0x00,0x00,0x00,0x00,0x00, + 0x00,0x08,0x20,0x00,0xff,0x00,0x00,0x00,0x00,0x08,0x40,0xe0,0x00,0x07,0x00, + 0x00,0x00,0x04,0x80,0x31,0x00,0x0c,0x00,0x00,0x00,0x04,0x00,0x09,0x00,0x30, + 0x00,0x00,0x00,0x04,0x00,0x06,0xc0,0x20,0x00,0x00,0x00,0x04,0x00,0x03,0x00, + 0x43,0x00,0x00,0x00,0x04,0x80,0x00,0x00,0x42,0x00,0x00,0x00,0x04,0x40,0x00, + 0x00,0x84,0x00,0x00,0x00,0x04,0x60,0x00,0x00,0x84,0x00,0x00,0x00,0x04,0x00, + 0x00,0x00,0x84,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x02, + 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x20,0x00,0x00, + 0x00,0x04,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x0e,0x00, + 0x00,0x00,0xf0,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00}; diff --git a/hacks/pyro.c b/hacks/pyro.c new file mode 100644 index 00000000..69b0e060 --- /dev/null +++ b/hacks/pyro.c @@ -0,0 +1,258 @@ +/* xscreensaver, Copyright (c) 1992 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. + */ + +/* Draw some fireworks. Inspired from TI Explorer Lisp code by + John S. Pezaris + */ + +#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); + } + } +} + + +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); +} diff --git a/hacks/pyro.man b/hacks/pyro.man new file mode 100644 index 00000000..e92adb38 --- /dev/null +++ b/hacks/pyro.man @@ -0,0 +1,53 @@ +.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 , 13-aug-92. diff --git a/hacks/qix.c b/hacks/qix.c new file mode 100644 index 00000000..7c70574a --- /dev/null +++ b/hacks/qix.c @@ -0,0 +1,503 @@ +/* xscreensaver, Copyright (c) 1992 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. + */ + +#include "screenhack.h" +#include + +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<= 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; +} + + +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); + } +} diff --git a/hacks/qix.man b/hacks/qix.man new file mode 100644 index 00000000..54f9f431 --- /dev/null +++ b/hacks/qix.man @@ -0,0 +1,107 @@ +.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 , 13-aug-92. diff --git a/hacks/rocks.c b/hacks/rocks.c new file mode 100644 index 00000000..e97e6df3 --- /dev/null +++ b/hacks/rocks.c @@ -0,0 +1,313 @@ +/* xscreensaver, Copyright (c) 1992 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. + */ + +/* Flying through an asteroid field. Based on TI Explorer Lisp code by + John Nguyen + */ + +#include "screenhack.h" +#include +#include +#if __STDC__ +#include +#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); +} + + +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); + } +} diff --git a/hacks/rocks.man b/hacks/rocks.man new file mode 100644 index 00000000..5eb4b03b --- /dev/null +++ b/hacks/rocks.man @@ -0,0 +1,64 @@ +.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 . + +Ported to C and X by Jamie Zawinski , 13-aug-92. diff --git a/hacks/rorschach.c b/hacks/rorschach.c new file mode 100644 index 00000000..5c556159 --- /dev/null +++ b/hacks/rorschach.c @@ -0,0 +1,140 @@ +/* xscreensaver, Copyright (c) 1992 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. + */ + +#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); +} + + +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); +} diff --git a/hacks/rorschach.man b/hacks/rorschach.man new file mode 100644 index 00000000..fd63db9d --- /dev/null +++ b/hacks/rorschach.man @@ -0,0 +1,57 @@ +.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 , 13-aug-92. diff --git a/hacks/screenhack.c b/hacks/screenhack.c new file mode 100644 index 00000000..0bbd4be2 --- /dev/null +++ b/hacks/screenhack.c @@ -0,0 +1,204 @@ +/* xscreensaver, Copyright (c) 1992 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. + * + * 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 +#include +#include +#include +#include +#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]))); +} + + +/* 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, " "); + 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); +} diff --git a/hacks/screenhack.h b/hacks/screenhack.h new file mode 100644 index 00000000..4cfc8f05 --- /dev/null +++ b/hacks/screenhack.h @@ -0,0 +1,120 @@ + +#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 +#endif + +#include +#include +#include +#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_ */ diff --git a/hacks/slidescreen.c b/hacks/slidescreen.c new file mode 100644 index 00000000..37ca4d15 --- /dev/null +++ b/hacks/slidescreen.c @@ -0,0 +1,317 @@ +/* xscreensaver, Copyright (c) 1992, 1993 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. + */ + +#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; + } +} + + +char *progclass = "SlidePuzzle"; + +char *defaults [] = { + "SlidePuzzle.mappedWhenManaged:false", + "SlidePuzzle.dontClearWindow: true", + "*background: black", + "*gridSize: 70", + "*pixelIncrement: 10", + "*internalBorderWidth: 1", + "*delay: 50000", + "*delay2: 1000000", + 0 +}; + +XrmOptionDescRec options [] = { + { "-grid-size", ".gridSize", XrmoptionSepArg, 0 }, + { "-ibw", ".internalBorderWidth", XrmoptionSepArg, 0 }, + { "-increment", ".pixelIncrement", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-delay2", ".delay2", XrmoptionSepArg, 0 }, +}; + +int options_size = (sizeof (options) / sizeof (options[0])); + +void +screenhack (dpy, window) + Display *dpy; + Window window; +{ + init_slide (dpy, window); + while (1) + { + slide1 (dpy, window); + if (delay2) usleep (delay2); + } +} diff --git a/hacks/slidescreen.man b/hacks/slidescreen.man new file mode 100644 index 00000000..1573c862 --- /dev/null +++ b/hacks/slidescreen.man @@ -0,0 +1,61 @@ +.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 , 3-dec-92. diff --git a/hacks/vroot.h b/hacks/vroot.h new file mode 100644 index 00000000..a00e7065 --- /dev/null +++ b/hacks/vroot.h @@ -0,0 +1,123 @@ +/*****************************************************************************/ +/** Copyright 1991 by Andreas Stolcke **/ +/** Copyright 1990 by Solbourne Computer Inc. **/ +/** Longmont, Colorado **/ +/** **/ +/** All Rights Reserved **/ +/** **/ +/** Permission to use, copy, modify, and distribute this software and **/ +/** its documentation for any purpose and without fee is hereby **/ +/** granted, provided that the above copyright notice appear in all **/ +/** copies and that both that copyright notice and this permis- **/ +/** sion notice appear in supporting documentation, and that the **/ +/** name of Solbourne not be used in advertising **/ +/** in publicity pertaining to distribution of the software without **/ +/** specific, written prior permission. **/ +/** **/ +/** ANDREAS STOLCKE AND SOLBOURNE COMPUTER INC. DISCLAIMS ALL WARRANTIES **/ +/** WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF **/ +/** MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ANDREAS STOLCKE **/ +/** OR SOLBOURNE BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL **/ +/** DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ +/** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ +/** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ +/** OR PERFORMANCE OF THIS SOFTWARE. **/ +/*****************************************************************************/ +/* + * vroot.h -- Virtual Root Window handling header file + * + * This header file redefines the X11 macros RootWindow and DefaultRootWindow, + * making them look for a virtual root window as provided by certain `virtual' + * window managers like swm and tvtwm. If none is found, the ordinary root + * window is returned, thus retaining backward compatibility with standard + * window managers. + * The function implementing the virtual root lookup remembers the result of + * its last invocation to avoid overhead in the case of repeated calls + * on the same display and screen arguments. + * The lookup code itself is taken from Tom LaStrange's ssetroot program. + * + * Most simple root window changing X programs can be converted to using + * virtual roots by just including + * + * #include + * + * 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 , 9/7/90 + * - replaced all NULL's with properly cast 0's, 5/6/91 + * - free children list (suggested by Mark Martin ), 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 +#include +#include + +static Window +VirtualRootWindowOfScreen(screen) + Screen *screen; +{ + static Screen *save_screen = (Screen *)0; + static Window root = (Window)0; + + if (screen != save_screen) { + Display *dpy = DisplayOfScreen(screen); + Atom __SWM_VROOT = None; + int i; + Window rootReturn, parentReturn, *children; + unsigned int numChildren; + + root = RootWindowOfScreen(screen); + + /* go look for a virtual root */ + __SWM_VROOT = XInternAtom(dpy, "__SWM_VROOT", False); + if (XQueryTree(dpy, root, &rootReturn, &parentReturn, + &children, &numChildren)) { + for (i = 0; i < numChildren; i++) { + Atom actual_type; + int actual_format; + unsigned long nitems, bytesafter; + Window *newRoot = (Window *)0; + + if (XGetWindowProperty(dpy, children[i], + __SWM_VROOT, 0, 1, False, XA_WINDOW, + &actual_type, &actual_format, + &nitems, &bytesafter, + (unsigned char **) &newRoot) == Success + && newRoot) { + root = *newRoot; + break; + } + } + if (children) + XFree((char *)children); + } + + save_screen = screen; + } + + return root; +} + +#undef RootWindowOfScreen +#define RootWindowOfScreen(s) VirtualRootWindowOfScreen(s) + +#undef RootWindow +#define RootWindow(dpy,screen) VirtualRootWindowOfScreen(ScreenOfDisplay(dpy,screen)) + +#undef DefaultRootWindow +#define DefaultRootWindow(dpy) VirtualRootWindowOfScreen(DefaultScreenOfDisplay(dpy)) + +#endif /* _VROOT_H_ */ diff --git a/hacks/xlock.h b/hacks/xlock.h new file mode 100644 index 00000000..a53a99a9 --- /dev/null +++ b/hacks/xlock.h @@ -0,0 +1,146 @@ +/* +** 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); \ + } \ + } \ +} diff --git a/hacks/xroger-hack.c b/hacks/xroger-hack.c new file mode 100644 index 00000000..d2bc0316 --- /dev/null +++ b/hacks/xroger-hack.c @@ -0,0 +1,101 @@ +/* xscreensaver, Copyright (c) 1991-1993 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. + */ + +#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); + } + } +} diff --git a/hacks/xroger.man b/hacks/xroger.man new file mode 100644 index 00000000..7661ec46 --- /dev/null +++ b/hacks/xroger.man @@ -0,0 +1,43 @@ +.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 , 13-aug-92. diff --git a/screenblank.txt b/screenblank.txt new file mode 100644 index 00000000..17621585 --- /dev/null +++ b/screenblank.txt @@ -0,0 +1,46 @@ +From mrapple@quack.kfu.com Mon Apr 26 18:31:07 1993 +Newsgroups: alt.hackers +From: mrapple@quack.kfu.com (Nick Sayer) +Subject: screenblank and xautolock living in harmony +Organization: The Duck Pond public unix: +1 408 249 9630, log in as 'guest'. +Date: 23 Apr 1993 19:26:57 UTC + + +I have a Sun and use xinit to start X. This presented a problem. +If I use xautolock or xscreensaver to save the screen, then after +a period of inactivity screenblank would turn the video off despite +'xset s off'. If I didn't run screenblank, then who would take care of +the display when X wasn't running? + +The hack that saved the day was to include this in .xinitrc: + +( + +while true ; do +sleep 360 +touch /dev/console +done + +) & +killblank=$! + +[start up all the clients, etc, etc. Wait for the window manager +to die, then ] + +kill $killblank + +The result is that screenblank is kept safely out of the way when X +is running and left to do its job otherwise. + +Yes, I know using XDM would solve this problem. + +No, I'm probably not the first to think of this. + +You're welcome. + +-- +Nick Sayer | "Dear Sexy Nickers. I don't half fancy +N6QQQ @ N0ARY.#NOCAL.CA.USA.NOAM | you. Meet me at the lift at 5:30 and ++1 408 249 9630, log in as 'guest' | we'll get it together." +PGP 2.2 public key via finger | -- Mr. Lucas + diff --git a/utils/Imakefile b/utils/Imakefile new file mode 100644 index 00000000..87c1ca33 --- /dev/null +++ b/utils/Imakefile @@ -0,0 +1,20 @@ +/* + * 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) diff --git a/utils/README b/utils/README new file mode 100644 index 00000000..2f5bc119 --- /dev/null +++ b/utils/README @@ -0,0 +1,6 @@ + +This directory contains various utilities that are used both by the +screensaver driver and by the demo programs; for example, a portable +implementation of usleep(), and code for manipulating color maps. + +If you have compilation problems, check the parameters in ../config.h. diff --git a/utils/ad2c b/utils/ad2c new file mode 100755 index 00000000..1435e554 --- /dev/null +++ b/utils/ad2c @@ -0,0 +1,38 @@ +#!/bin/sh +# +# ad2c : Convert app-defaults file to C strings decls. +# +# George Ferguson, ferguson@cs.rcohester.edu, 12 Nov 1990. +# 19 Mar 1991 : gf +# Made it self-contained. +# 6 Jan 1992 : mycroft@gnu.ai.mit.edu (Charles Hannum) +# Removed use of "-n" and ":read" label since Gnu and +# IBM sed print pattern space on "n" command. Still works +# with Sun sed, of course. +# 7 Jan 1992: matthew@sunpix.East.Sun.COM (Matthew Stier) +# Escape quotes after escaping backslashes. +# + +sed ' +/^!/d +/^$/d +s/\\/\\\\/g +s/\\$//g +s/"/\\"/g +s/^/"/ +: test +/\\$/b slash +s/$/",/ +p +d +: slash +n +/^!/d +/^$/d +s/"/\\"/g +s/\\\\/\\/g +s/\\n/\\\\n/g +s/\\t/\\\\t/g +s/\\f/\\\\f/g +s/\\b/\\\\b/g +b test' "$@" diff --git a/utils/fade.c b/utils/fade.c new file mode 100644 index 00000000..2fbb2e97 --- /dev/null +++ b/utils/fade.c @@ -0,0 +1,166 @@ +/* xscreensaver, Copyright (c) 1992 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. + */ + +#if __STDC__ +# include +#endif + +#include +#include +#include + +#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 + + +char *progclass = "foo"; + +char *defaults [] = { + 0 +}; + +XrmOptionDescRec options [] = {0}; +int options_size = 0; + +void +screenhack (dpy, w) + Display *dpy; + Window w; +{ + Colormap cmap = DefaultColormap (dpy, DefaultScreen (dpy)); + Colormap cmap2 = copy_colormap (dpy, cmap, 0); + + int seconds = 1; + int ticks = 30 * seconds; + int delay = 1; + + while (1) + { + XSync (dpy, False); + XGrabServer (dpy); + XInstallColormap (dpy, cmap2); + fade_colormap (dpy, cmap, cmap2, seconds, ticks, True); + if (delay) sleep (delay); + fade_colormap (dpy, cmap, cmap2, seconds, ticks, False); + XInstallColormap (dpy, cmap); + XUngrabServer (dpy); + XSync (dpy, False); + if (delay) sleep (delay); + } +} + +#endif diff --git a/utils/hsv.c b/utils/hsv.c new file mode 100644 index 00000000..bf508f3d --- /dev/null +++ b/utils/hsv.c @@ -0,0 +1,110 @@ +/* xscreensaver, Copyright (c) 1992 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. + */ + +/* This file contains some utility routines for randomly picking the colors + to hack the screen with. + */ + +#include + +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); +} diff --git a/utils/resources.c b/utils/resources.c new file mode 100644 index 00000000..771e20f1 --- /dev/null +++ b/utils/resources.c @@ -0,0 +1,214 @@ +/* xscreensaver, Copyright (c) 1992 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. + */ + +#if __STDC__ +#include +#include +#endif + +#include +#include +#include + +/* 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); +} diff --git a/utils/spline.c b/utils/spline.c new file mode 100644 index 00000000..ed5a224a --- /dev/null +++ b/utils/spline.c @@ -0,0 +1,286 @@ +#include +#include "spline.h" +#if __STDC__ +#include +#endif +#include + +/* 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; +} diff --git a/utils/spline.h b/utils/spline.h new file mode 100644 index 00000000..c0c4d7fd --- /dev/null +++ b/utils/spline.h @@ -0,0 +1,33 @@ +#ifndef _SPLINE_H_ +#define _SPLINE_H_ + +#include + +#if __STDC__ +# define P(x)x +#else +# define P(x)() +#endif + +typedef struct _spline +{ + /* input */ + u_int n_controls; + double* control_x; + double* control_y; + + /* output */ + u_int n_points; + XPoint* points; + u_int allocated_points; +} spline; + +spline* make_spline P((u_int size)); +void compute_spline P((spline* s)); +void compute_closed_spline P((spline* s)); +void just_fill_spline P((spline* s)); +void append_spline_points P((spline* s1, spline* s2)); +void spline_bounding_box P((spline* s, XRectangle* rectangle_out)); + +#undef P +#endif /* _SPLINE_H_ */ diff --git a/utils/usleep.c b/utils/usleep.c new file mode 100644 index 00000000..2529d57f --- /dev/null +++ b/utils/usleep.c @@ -0,0 +1,97 @@ +/* xscreensaver, Copyright (c) 1992 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. + */ + +#if __STDC__ +#include +#endif + +#include +#include /* lazy way out */ + +/* usleep() doesn't exist everywhere, and select() is faster anyway. + */ + +#ifndef VMS + +#ifdef NO_SELECT + /* If you don't have select() or usleep(), I guess you lose... + Maybe you have napms() instead? Let me know. + */ +void +screenhack_usleep (usecs) + unsigned long usecs; +{ + usleep (usecs); +} + +#else /* ! NO_SELECT */ + +void +screenhack_usleep (usecs) + unsigned long usecs; +{ + struct timeval tv; + tv.tv_sec = usecs / 1000000L; + tv.tv_usec = usecs % 1000000L; + (void) select (0, 0, 0, 0, &tv); +} + +#endif /* ! NO_SELECT */ + +#else /* VMS */ + +#define SEC_DELTA "0000 00:00:01.00" +#define TICK_DELTA "0000 00:00:00.08" +static int bin_sec_delta[2], bin_tick_delta[2], deltas_set = 0; + +static void +set_deltas () +{ + int status; + extern int SYS$BINTIM (); + $DESCRIPTOR (str_sec_delta, SEC_DELTA); + $DESCRIPTOR (str_tick_delta, TICK_DELTA); + if (!deltas_set) + { + status = SYS$BINTIM (&str_sec_delta, &bin_sec_delta); + if (!(status & 1)) + { + fprintf (stderr, "%s: cannot convert delta time ", progname); + fprintf (stderr, SEC_DELTA); + fprintf (stderr, "; status code = %d\n", status); + exit (status); + } + status = SYS$BINTIM (&str_tick_delta, &bin_tick_delta); + if (!(status & 1)) + { + fprintf (stderr, "%s: cannot convert delta time ", progname); + fprintf (stderr, TICK_DELTA); + fprintf (stderr, "; status code = %d\n", status); + exit (status); + } + deltas_set = 1; + } +} + +void +screenhack_usleep (usecs) + unsigned long usecs; +{ + int status, *bin_delta; + extern int SYS$SCHWDK (), SYS$HIBER (); + + if (!deltas_set) set_deltas (); + bin_delta = (usecs == TICK_INTERVAL) ? &bin_tick_delta : &bin_sec_delta; + status = SYS$SCHDWK (0, 0, bin_delta, 0); + if ((status & 1)) (void) SYS$HIBER (); +} + +#endif /*VMS */ diff --git a/utils/version.h b/utils/version.h new file mode 100644 index 00000000..867367a3 --- /dev/null +++ b/utils/version.h @@ -0,0 +1,2 @@ +static char *screensaver_id = + "@(#)xscreensaver 1.17, by Jamie Zawinski (jwz@lucid.com)"; diff --git a/utils/xroger.c b/utils/xroger.c new file mode 100644 index 00000000..31b6cbf2 --- /dev/null +++ b/utils/xroger.c @@ -0,0 +1,102 @@ +/* xscreensaver, Copyright (c) 1991-1993 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. + */ + +#include + +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); +} -- 2.30.2