From: Zygo Blaxell Date: Thu, 26 Feb 2009 21:07:24 +0000 (-0500) Subject: http://archive.debian.org/debian/dists/bo/main/source/x11/xscreensaver_1.27.orig... X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2Fxscreensaver_1.27.orig;p=xscreensaver http://archive.debian.org/debian/dists/bo/main/source/x11/xscreensaver_1.27.orig.tar.gz -rw-r--r-- 1 zblaxell zblaxell 253337 Oct 12 1996 xscreensaver_1.27.orig.tar.gz f3ee25d7dfc92209f70e6d6f9329ed7f2bdcc777 xscreensaver_1.27.orig.tar.gz --- 7f10ffc69d8bbe8cf0d2c0d7da61a04c3a03bf68 diff --git a/Imakefile b/Imakefile new file mode 100644 index 00000000..d7ec7c62 --- /dev/null +++ b/Imakefile @@ -0,0 +1,53 @@ +/* + * Imakefile file for xscreensaver, Copyright (c) 1991-1994 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 = tar + COMPRESS = compress + COMPRESS_EXT = Z +/**/# COMPRESS = gzip --verbose --best +/**/# COMPRESS_EXT = gz + +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) $@ BINDIR=$(BINDIR) XAPPLOADDIR=$(XAPPLOADDIR) + cd driver ; $(MAKE) $@ BINDIR=$(BINDIR) XAPPLOADDIR=$(XAPPLOADDIR) + cd hacks ; $(MAKE) $@ BINDIR=$(BINDIR) XAPPLOADDIR=$(XAPPLOADDIR) + +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][0-9]*\).*/xscreensaver-\1/p' utils/version.h` ; \ + rm -f $$NAME ; ln -s . $$NAME ; \ + FILES= ; \ + for subdir in driver utils hacks ; do \ + cd $$subdir ; \ + FILES="$$FILES `make echo_tarfiles \ + | grep -v '^make\[' \ + | sed \"s|^|$$subdir/|g;s| | $$subdir/|g\" \ + ` "; \ + cd .. ; done ; \ + echo creating tar file $${NAME}.tar.$(COMPRESS_EXT)... ; \ + $(TAR) -vchf - \ + `echo $(TARFILES) $$FILES | sed "s|^|$$NAME/|g; s| | $$NAME/|g" ` \ + | $(COMPRESS) > $${NAME}.tar.$(COMPRESS_EXT) ; \ + rm $$NAME diff --git a/README b/README new file mode 100644 index 00000000..3a755b33 --- /dev/null +++ b/README @@ -0,0 +1,140 @@ + +To build: + + - read the comments in `config.h' and edit it as appropriate + - xmkmf ; make + - make install 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, MIT-SCREEN-SAVER, and/or SGI SCREEN_SAVER server extensions +will be used if you have them. + +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. + pedal - Draws a different kind of spirally pattern. + 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. + decayscreen - A melting effect. + halo - Random circular patterns. + pyro - Fireworks. Looks a lot like the version in xlock. + hopalong - Fractals. I snarfed this code from xlock. + flame - Fractals. Also 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. + lmorph - morphing line drawings. + bubbles - condensation forms on your monitor, then pops. + +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 -p8 -faces -sleep 1 - 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) + xtacy -root - various eye candy + +You can get all of these from the contrib directory on ftp.x.org. If you +know of (or write) any other interesting programs that can be used as +screensavers, please let me know! + +The latest version of xscreensaver is always ftpable from ftp.x.org. You can +also get it from my web page at http://www.netscape.com/people/jwz/. + + -- Jamie Zawinski + + +Changes since 1.26: Added support for SGI SCREEN_SAVER extension. + Made `fade' and `unfade' work on 8-bit SGIs. + Made the dialog boxes more Motify. + Added `bubbles' hack. +Changes since 1.25: Added `lmorph' hack. + Added viscosity and mouse-control to attraction. + Fixed possible bad color choices in qix and attraction. + Added ramp-mode to halo. + Added a new RNG, which is faster and more portable + than using the RNG in libc. + Made locking work on SCO. + Various other minor tweaks that I don't remember. +Changes since 1.24: Made it capture the stdout/stderr of its subprocesses + and present them on the screensaver window itself. + Made demo mode work correctly with non-default visuals + and color maps, instead of always using the defaults. + Added -visual argument to all included screenhacks. + Support for the R6 MIT-SCREEN-SAVER server extension. + Made the demo mode list scroll properly. + Added `pedal' hack. +Changes since 1.23: Fixed some private-colormap oddities in slidescreen, + decayscreen, and xroger. Fixed apparent conservation- + of-mass problem in pyro; made the shrapnel round. +Changes since 1.22: Minor tweaks for IRIX5; fixed locking race condition. +Changes since 1.21: Minor tweaks for X11R6. + Fixes for non-default visuals. +Changes since 1.20: Fixed bug in color blitspin; added default image. + Added diagnostics to noseguy. Fixed off-by-one + error in flame. Added some missing casts. +Changes since 1.18: Added `flame' hack. + Fixed a minor Motif dialog text field bug. + Fixed yet another XPointer-not-defined-in-R4 bug. +Changes since 1.17: Added support for shadow password files. + Fixed some Motif-related locking bugs. + Added diagnostics when locking is disabled. + Made blitspin able to use the XPM library. + Added `decayscreen' hack. +Changes since 1.16: Added `halo' hack. +Changes since 1.15: Portability fixes. +Changes since 1.14: Broke the driver up into more source files. + Moved the hacks into their own directory. + Made all `time' parameters accept the 00:00:00 syntax, + so that even the parameters which are normally read as + minutes can be specified in seconds. + Added colormap cycling to `imsmap'. + Made hyper work with K&R compilers. +Changes since 1.13: Added `orbit' option to `attraction' hack. + Added `lock-timeout' option. + Cleaned up options of `maze' hack. +Changes since 1.8: Added demo mode, and locking. + Added `maze' hack. + Added `norotate' option to `rocks' hack. diff --git a/config.h b/config.h new file mode 100644 index 00000000..6230a79a --- /dev/null +++ b/config.h @@ -0,0 +1,167 @@ +/* Config file for xscreensaver, Copyright (c) 1991-1996 Jamie Zawinski. + * This file is included by the various Imakefiles. + */ + +/* Uncomment the following line if you have the XPM library installed. + * Some of the demos can make use of this if it is available. + */ +#define HAVE_XPM + + +/* 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. + * But other than that, it will work fine. + */ +/* #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.) If you need to do this, please let me + * know. + * + * I'm told that locking doesn't work for sites which run AFS. I don't know + * anything about how one codes authentication for AFS; if you do, please let + * me know... + */ +/* #define NO_LOCKING */ + + +/* Select supported server extensions. + * There are three distinct server extensions which are useful with + * XScreenSaver: XIDLE, MIT-SCREEN-SAVER, and SCREEN_SAVER. + * + * The XIDLE extension resides in .../contrib/extensions/xidle/ on the X11R5 + * contrib tape. This extension lets the client get accurate idle-time + * information from the X server in a potentially more reliable way than by + * simply watching for keyboard and mouse activity. However, the XIDLE + * extension has apparently not been ported to X11R6. + * + * The SCREEN_SAVER extension is found (as far as I know) only in the SGI + * X server, and it exists in all releases since (at least) Irix 5. The + * relevant header file is /usr/include/X11/extensions/XScreenSaver.h. + * + * The similarly-named MIT-SCREEN-SAVER extension came into existence long + * after the SGI SCREEN_SAVER extension was already in use, and resides in + * .../contrib/extensions/screensaver/ on the X11R6 contrib tape. It is + * also found in certain recent X servers built in to NCD X terminals. + * + * The MIT extension does basically the same thing that the XIDLE extension + * does, but there are two things wrong with it: first, because of the way + * the extension was designed, the `fade' option to XScreenSaver will be + * uglier: just before the screen fades out, there will be an unattractive + * flicker to black, because this extension blanks the screen *before* + * telling us that it is time to do so. Second, this extension is known to + * be buggy; on the systems I use, it works, but some people have reported + * X server crashes as a result of using it. XScreenSaver uses this + * extension rather conservatively, because when I tried to use any of its + * more complicated features, I could get it to crash the server at the + * drop of a hat. + * + * In short, the MIT-SCREEN-SAVER extension is a piece of junk. The older + * SGI SCREEN_SAVER extension works great, as does XIDLE. It would be nice + * If those two existed on more systems, that is, would be adopted by the + * X Consortium in favor of their inferior "not-invented-here" entry. + */ + +/* Uncomment the following line if you have the XIDLE extension installed. + * If you have the XIDLE extension, this is recommended. (You have this + * extension if the file /usr/include/X11/extensions/xidle.h exists.) + * Turning on this flag lets XScreenSaver work better with servers which + * support this extension; but it will still work with servers which do not + * suport it, so it's a good idea to compile in support for it if you can. + */ +/* #define HAVE_XIDLE_EXTENSION */ + +/* Uncomment the following line if you have the MIT-SCREEN-SAVER extension + * installed. This is NOT RECOMMENDED. See the caveats about this extension, + * above. (It's available if the file /usr/include/X11/extensions/scrnsaver.h + * exists.) + */ +/* #define HAVE_MIT_SAVER_EXTENSION */ + + +/* Use the following line if you have the SGI SCREEN_SAVER extension; the + * default below should be correct (use it if and only if running on an SGI.) + * Compiling in support for this extension is recommended, if possible. + */ +#ifdef SGIArchitecture +# define HAVE_SGI_SAVER_EXTENSION +#endif + + +/* Uncomment the following line if your system doesn't have the select() + * system call. If you need to do this, please let me know. (I don't really + * think that any such systems exist in this day and age...) + */ +/* #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 */ + + +/* Uncomment the following line if your system uses `shadow' passwords, + * that is, the passwords live in /etc/shadow instead of /etc/passwd, + * and one reads them with getspnam() instead of getpwnam(). (Note that + * SCO systems do some random other thing; others might as well. See the + * ifdefs in driver/lock.c if you're having trouble related to reading + * passwords.) + */ +/* #define HAVE_SHADOW */ + + +/* You may need to edit these to correspond to where Motif is installed, + * if your site has Motif installed in a nonstandard place. + */ +#ifndef NO_MOTIF + MOTIFINCLUDES = -I/usr/local/include/ + MOTIFLDOPTIONS = -L/usr/local/lib/ + 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 your system needs this, and the default below is not correct, + please let me know.) + */ +#if defined(HPArchitecture) || defined(AIXArchitecture) || defined(HAVE_SHADOW) || defined(NetBSDArchitecture) +# 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 + +/* It seems that some versions of Sun's dynamic X libraries are broken; if + you get link errors about _get_wmShellWidgetClass being undefined, try + adding -Bstatic to the link command. + */ diff --git a/driver/.gdbinit b/driver/.gdbinit new file mode 100644 index 00000000..ab329236 --- /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 -sync -verbose -idelay 0 +#b purify_stop_here diff --git a/driver/Imakefile b/driver/Imakefile new file mode 100644 index 00000000..722d284a --- /dev/null +++ b/driver/Imakefile @@ -0,0 +1,162 @@ +/* + * Imakefile file for xscreensaver, Copyright (c) 1993-1996 Jamie Zawinski. + * + * You should not need to edit this file; edit ../config.h instead. + * + */ + +#include "../config.h" + +/* #### If anyone ever finishes the Athena locking code, remove this. */ +#if defined(NO_MOTIF) && !defined(NO_LOCKING) +# define NO_LOCKING +#endif + +#ifdef NO_LOCKING +# undef INSTALL_SETUID +#endif + +#ifdef HAVE_XIDLE_EXTENSION +# define XIDLE_DEF -DHAVE_XIDLE_EXTENSION +#else +# define XIDLE_DEF +#endif + +#ifdef HAVE_MIT_SAVER_EXTENSION +# define MIT_SAVER_DEF -DHAVE_MIT_SAVER_EXTENSION +#else +# define MIT_SAVER_DEF +#endif + +#ifdef HAVE_SGI_SAVER_EXTENSION +# define SGI_SAVER_DEF -DHAVE_SGI_SAVER_EXTENSION +#else +# define SGI_SAVER_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 HAVE_SHADOW +# define SHADOW_DEF -DHAVE_SHADOW +#else +# define SHADOW_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 MIT_SAVER_DEF SGI_SAVER_DEF MOTIF_DEF LOCKING_DEF SHADOW_DEF R5ISMS + SAVERLIBS = $(XMULIB) $(XTOOLLIB) $(EXTENSIONLIB) $(XLIB) + COMMLIBS = $(XLIB) + UTIL_SRCS = $(UTILS)/resources.c $(UTILS)/fade.c $(UTILS)/visual.c $(UTILS)/usleep.c $(UTILS)/yarandom.c + UTIL_OBJS = $(UTILS)/resources.o $(UTILS)/fade.o $(UTILS)/visual.o $(UTILS)/usleep.o $(UTILS)/yarandom.o + DBOX_SRCS = dialogs.c demo.c + DBOX_OBJS = dialogs.o demo.o + LOCK_SRCS = lock.c + LOCK_OBJS = lock.o + SAVERSRCS = xscreensaver.c timers.c subprocs.c windows.c stderr.c + SAVEROBJS = xscreensaver.o timers.o subprocs.o windows.o stderr.o + SRCS1 = $(SAVERSRCS) MOTIF_SRC $(LOCK_SRCS) $(UTIL_SRCS) + OBJS1 = $(SAVEROBJS) MOTIF_OBJ $(LOCK_OBJS) $(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) $(LOCK_SRCS) \ + $(COMMSRCS) xscreensaver.h XScreenSaver.ad dialogs.xd \ + $(MEN) .gdbinit + +#if defined(HPArchitecture) && !defined(NO_LOCKING) +EXTRA_LIBRARIES = -lXhp11 /* for XHPDisableReset() */ +#endif + +#if defined(NetBSDArchitecture) && !defined(NO_LOCKING) +EXTRA_LIBRARIES = -lcrypt +#endif + +#if defined(i386ScoArchitecture) +EXTRA_LIBRARIES = -lintl -lprot -lx -lcrypt_i +#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), $(HP_NULL_STR)) + +#ifdef INSTALL_SETUID +#undef InstallProgram +#define InstallProgram(p,d) InstallProgramWithFlags(p,d,$(HP_NULL_STR)) +#endif + +ComplexProgramTarget_2(xscreensaver-command,$(COMMLIBS),$(HP_NULL_STR)) + +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 + + +#if defined(SparcArchitecture) || defined(SGIArchitecture) +# undef UsePurify +# define UsePurify +#endif + +#ifdef UsePurify + PURIFY = purify + PURIFYOPTIONS = + +# undef PurifyProgramTarget +# define PurifyProgramTarget(program,deplist,linklist) @@\ +program.pure: deplist @@\ + RemoveTargetProgram($@) @@\ + $(CCENVSETUP) $(PURIFY) $(PURIFYOPTIONS) $(CC) \ + -o $@ $(LDOPTIONS) linklist $(EXTRA_LOAD_FLAGS) + +PurifyProgramTarget(xscreensaver,$(OBJS1),$(OBJS1) MOTIF_LIB $(SAVERLIBS)) + +#endif /* Purify */ 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..01401a4b --- /dev/null +++ b/driver/XScreenSaver.ad @@ -0,0 +1,214 @@ +! app-defaults file for XScreenSaver by Jamie Zawinski. +! See "man xscreensaver" for more info. If you don't have that, +! see http://www.netscape.com/people/jwz/ to get the latest version. + +*timeout: 10 +*cycle: 10 +*lockTimeout: 0 +*passwdTimeout: 30 +*nice: 10 +*lock: False +*verbose: False +*fade: True +*unfade: False +*fadeSeconds: 1 +*fadeTicks: 75 + +*captureStderr: True +*captureStdout: True +*textForeground: Yellow +*textBackground: Black +*font: *-medium-r-*-140-*-m-* + +! Turning on "installColormap" interacts erratically with twm and tvtwm, +! but seems to work fine with mwm and olwm. Try it and see. +! +*installColormap: True + + +! Any program which can draw on the root window will work as a screensaver. +! The following three resources enumerate them. + +*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\ + pedal -root \n\ + rorschach -root -offset 7 \n\ + hopalong -root \n\ + greynetic -root \n\ + xroger -root \n\ + imsmap -root \n\ + slidescreen -root \n\ + decayscreen -root \n\ + hypercube -root \n\ + halo -root \n\ + maze -root \n\ + flame -root \n\ + lmorph -root \n + +! Programs on this list are run only for monochrome screens. +! (These are in addition to those listed in "*programs".) +*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. +! (These are in addition to those listed in "*programs".) +*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 black \n\ + bubbles -root \n + + +! Some other programs that you might want to track down (these work as +! XScreenSaver helpers, but are not distributed with it): +! +! xdaliclock -root -builtin2 \n\ +! xswarm -r 2>&- \n\ +! xwave -root \n\ +! xbouncebits ... \n\ +! ico -r -faces -sleep 1 -obj ico \n\ +! xsplinefun \n\ +! kaleid -root \n\ +! xfishtank -c black -d -r 2 \n\ +! xtacy -root -delay 100 -gravity \n\ + + +! To display a slideshow of images, add commands like this to *programs: +! +! xv -root -rmode 5 image-1.gif -quit +! xv -root -rmode 5 image-2.gif -quit +! xv -root -rmode 5 image-3.gif -quit +! ...and so on... +! +! however, for this to work, you must also have started the screensaver so +! that it uses the default colormap (the "-no-install" command-line option, or +! the "installColormap: False" resource) because when XV is running in "-root" +! mode, it always assumes that the default colormap is being used, rather than +! examining the window it is drawing on to see what colormap it has. + + +! Some SGI GL programs work with XScreenSaver; most don't. +! +! Bongo works fine: +! +! /usr/demos/bin/bongo -wbongo +! +! ElectroPaint sort-of works; XScreenSaver will launch it, and it will run +! properly, but when it's time to turn off the screensaver, you need to hit +! the Escape key, rather than just moving the mouse. Apparently GL programs +! are able to intercept the keyboard even when X has the keyboard grabbed! +! +! /usr/demos/bin/ep +! +! None of the other GL demos I've tried worked, because none of them seem to +! have command-line options that will make them take up the whole screen; so +! all you get is a miniscule 100x100 image, which is worthless. This is a +! shame, since many of those demos would make fine screensavers. +! +! If anyone who understands how "haven" works would like to send me the code +! necessary to do what it does, I would be much obliged. + + + +!============================================================================= +! +! You probably don't want to change anything after this point. +! +!============================================================================= + + +! 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-1996 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 + +*passwdDialog.title: Password +*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 are only used if no server +! extension is in use. +! +*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..4d4a7b07 --- /dev/null +++ b/driver/demo.c @@ -0,0 +1,691 @@ +/* xscreensaver, Copyright (c) 1993-1996 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 + +#ifdef HAVE_MIT_SAVER_EXTENSION +extern int mit_saver_ext_event_number; +extern Window server_mit_saver_window; +#endif /* HAVE_MIT_SAVER_EXTENSION */ + +#ifdef HAVE_SGI_SAVER_EXTENSION +/* extern int sgi_saver_ext_event_number; */ +#endif /* HAVE_SGI_SAVER_EXTENSION */ + +extern Bool use_mit_saver_extension; +extern Bool use_sgi_saver_extension; + +extern Time timeout, cycle, lock_timeout; +#ifndef NO_LOCKING +extern Time passwd_timeout; +#endif +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)); + +static void focus_fuckus P((Widget dialog)); +static void text_cb P((Widget button, XtPointer, XtPointer)); + +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 +ensure_selected_item_visible (list) + Widget list; +{ + int *pos_list = 0; + int pos_count = 0; + if (XmListGetSelectedPos (list, &pos_list, &pos_count) && pos_count > 0) + { + int top = -2; + int visible = 0; + XtVaGetValues (list, + XmNtopItemPosition, &top, + XmNvisibleItemCount, &visible, + 0); + if (pos_list[0] >= top + visible) + { + int pos = pos_list[0] - visible + 1; + if (pos < 0) pos = 0; + XmListSetPos (list, pos); + } + else if (pos_list[0] < top) + { + XmListSetPos (list, pos_list[0]); + } + } + if (pos_list) + XtFree ((char *) pos_list); +} + +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); + } + ensure_selected_item_visible (demo_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); + } + ensure_selected_item_visible (demo_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 that 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; + 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, + (XtPointer) hacks); + XtAddCallback (demo_list, XmNdefaultActionCallback, select_cb, + (XtPointer) 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, (XtPointer) 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); + + /* Throttle the timeouts to minimum sane values. */ + if (res.timeout < 5) res.timeout = 5; + if (res.cycle < 2) res.cycle = 2; + if (res.passwd_time < 10) res.passwd_time = 10; + + timeout = res.timeout * 1000; + cycle = res.cycle * 1000; + lock_timeout = res.lock_time * 1000; +#ifndef NO_LOCKING + passwd_timeout = res.passwd_time * 1000; +#endif + 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; + +#if defined(HAVE_MIT_SAVER_EXTENSION) || defined(HAVE_SGI_SAVER_EXTENSION) + if (use_mit_saver_extension || use_sgi_saver_extension) + { + /* Need to set the server timeout to the new one the user has picked. + */ + int server_timeout, server_interval, prefer_blank, allow_exp; + XGetScreenSaver (dpy, &server_timeout, &server_interval, + &prefer_blank, &allow_exp); + if (server_timeout != (timeout / 1000)) + { + server_timeout = (timeout / 1000); + if (verbose_p) + fprintf (stderr, + "%s: configuring server for saver timeout of %d seconds.\n", + progname, server_timeout); + /* Leave all other parameters the same. */ + XSetScreenSaver (dpy, server_timeout, server_interval, + prefer_blank, allow_exp); + } + } +#endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */ +} + + +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), \ + (XtPointer) (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; +#ifndef NO_LOCKING + res.passwd_time = passwd_timeout / 1000; +#endif + 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_extension; +extern Bool use_mit_saver_extension; +extern Bool use_sgi_saver_extension; +extern Time notice_events_timeout; + +extern char **screenhacks; +extern char *demo_hack; + +extern void notice_events_timer P((XtPointer closure, XtIntervalId *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: + if (!use_xidle_extension && + !use_mit_saver_extension && + !use_sgi_saver_extension) + { + XtAppAddTimeOut (app, notice_events_timeout, notice_events_timer, + (XtPointer) event.xcreatewindow.window); +#ifdef DEBUG_TIMERS + if (verbose_p) + printf ("%s: starting notice_events_timer for 0x%X (%lu)\n", + progname, + (unsigned int) event.xcreatewindow.window, + notice_events_timeout); +#endif /* DEBUG_TIMERS */ + } + break; + + case ButtonPress: + case ButtonRelease: + if (!XtWindowToWidget (dpy, event.xbutton.window)) + raise_screenhack_dialog (); + /* fall through */ + + default: +#ifdef HAVE_MIT_SAVER_EXTENSION + if (event.type == mit_saver_ext_event_number) + { + /* Get the "real" server window out of the way as soon + as possible. */ + if (server_mit_saver_window && + window_exists_p (dpy, server_mit_saver_window)) + XUnmapWindow (dpy, server_mit_saver_window); + } + else +#endif /* HAVE_MIT_SAVER_EXTENSION */ + + 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); + /* raise_screenhack_dialog(); */ +} + +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..1fe9a45d --- /dev/null +++ b/driver/dialogs.c @@ -0,0 +1,676 @@ +/* xscreensaver, Copyright (c) 1993-1996 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. + */ + +/* The code in this file started off its life as the output of XDesigner, + but I've since hacked it by hand... It's a mess, avert your eyes. + */ + + +#if !__STDC__ +# define _NO_PROTO +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +extern Visual *visual; +extern int visual_depth; +extern Colormap cmap; + + +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; + + +void +create_passwd_dialog( parent ) +Widget parent; +{ + Widget shell; + Widget form1; + Widget roger; + Widget dialog; + Widget form2; + Widget label1, label2, label3; + Widget text; + Widget ok, cancel; + Widget w; + + shell = XmCreateDialogShell (parent, "passwdDialog", 0, 0); + + form1 = XmCreateForm (shell, "form", 0, 0); + + roger = XmCreateDrawnButton (form1, "rogerLabel", 0, 0); + + dialog = XmCreateSelectionBox (form1, "passwdForm", 0, 0); + + form2 = XmCreateForm ( dialog, "form", 0, 0); + label1 = XmCreateLabel ( form2, "passwdLabel1", 0, 0); + label2 = XmCreateLabel ( form2, "passwdLabel2", 0, 0); + label3 = XmCreateLabel ( form2, "passwdLabel3", 0, 0); + + text = XmSelectionBoxGetChild (dialog, XmDIALOG_TEXT); + ok = XmSelectionBoxGetChild (dialog, XmDIALOG_OK_BUTTON); + cancel = XmSelectionBoxGetChild (dialog, XmDIALOG_CANCEL_BUTTON); + + w = XmSelectionBoxGetChild (dialog, XmDIALOG_LIST_LABEL); + if (w) XtUnmanageChild (w); + w = XmSelectionBoxGetChild (dialog, XmDIALOG_LIST); + if (w) XtUnmanageChild (XtParent(w)); + w = XmSelectionBoxGetChild (dialog, XmDIALOG_SELECTION_LABEL); + if (w) XtUnmanageChild (w); + w = XmSelectionBoxGetChild (dialog, XmDIALOG_SEPARATOR); + if (w) XtUnmanageChild (w); + w = XmSelectionBoxGetChild (dialog, XmDIALOG_APPLY_BUTTON); + if (w) XtUnmanageChild (w); + w = XmSelectionBoxGetChild (dialog, XmDIALOG_HELP_BUTTON); + if (w) XtUnmanageChild (w); + + XtVaSetValues(label1, + XmNtopAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_NONE, + 0); + XtVaSetValues(label2, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, label1, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_NONE, + 0); + XtVaSetValues(label3, + XmNtopAttachment, XmATTACH_WIDGET, + XmNtopWidget, label2, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, + 0); + + XtVaSetValues(roger, + XmNsensitive, FALSE, + XmNtopAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_FORM, + XmNrightAttachment, XmATTACH_NONE, + XmNbottomAttachment, XmATTACH_FORM, + 0); + XtVaSetValues(dialog, + XmNtopAttachment, XmATTACH_FORM, + XmNleftAttachment, XmATTACH_WIDGET, + XmNleftWidget, roger, + XmNrightAttachment, XmATTACH_FORM, + XmNbottomAttachment, XmATTACH_FORM, + 0); + + XtManageChild(label1); + XtManageChild(label2); + XtManageChild(label3); + + XtManageChild(form2); + XtManageChild(text); + XtManageChild(ok); + XtManageChild(cancel); + + XtManageChild(roger); + XtManageChild(dialog); + + { + Dimension w = 0, h = 0; + XtRealizeWidget(form1); + XtVaGetValues(roger, XmNwidth, &w, XmNheight, &h, 0); + if (w == h) + ; + else if (w > h) + XtVaSetValues(roger, XmNwidth, w, XmNheight, w, 0); + else + XtVaSetValues(roger, XmNwidth, h, XmNheight, h, 0); + } + + passwd_dialog = shell; + passwd_form = form1; + roger_label = roger; + passwd_label1 = label1; + passwd_label3 = label3; + passwd_text = text; + passwd_done = ok; + passwd_cancel = cancel; +} + + + +void +create_resources_dialog( parent ) +Widget parent; +{ + Widget children[22]; /* Children to manage */ + Arg al[64]; /* Arg List */ + register int ac = 0; /* Arg Count */ + Widget widget12; + Widget widget13; + Widget widget14; + Widget widget15; + Widget widget16; + Widget widget17; + Widget widget18; + Widget widget48; + Widget widget29; + + Widget real_dialog; + Widget w; + + + ac = 0; + XtSetArg (al[ac], XmNvisual, visual); ac++; + XtSetArg (al[ac], XmNcolormap, cmap); ac++; + XtSetArg (al[ac], XmNdepth, visual_depth); ac++; + + real_dialog = XmCreatePromptDialog (parent, "resourcesForm", al, ac); + resources_dialog = XtParent(real_dialog); + + w = XmSelectionBoxGetChild (real_dialog, XmDIALOG_SEPARATOR); + if (w) XtUnmanageChild (w); + w = XmSelectionBoxGetChild (real_dialog, XmDIALOG_TEXT); + if (w) XtUnmanageChild (w); + w = XmSelectionBoxGetChild (real_dialog, XmDIALOG_SELECTION_LABEL); + if (w) XtUnmanageChild (w); + w = XmSelectionBoxGetChild (real_dialog, XmDIALOG_HELP_BUTTON); + if (w) XtUnmanageChild (w); + + ac = 0; + XtSetArg (al [ac], XmNtopAttachment, XmATTACH_FORM); ac++; + XtSetArg (al [ac], XmNbottomAttachment, XmATTACH_FORM); ac++; + XtSetArg (al [ac], XmNleftAttachment, XmATTACH_FORM); ac++; + XtSetArg (al [ac], XmNrightAttachment, XmATTACH_FORM); ac++; + resources_form = XmCreateForm (real_dialog, "form", al, ac); + XtManageChild (resources_form); + + ac = 0; + + 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 = XmSelectionBoxGetChild (real_dialog, XmDIALOG_OK_BUTTON); + res_cancel = XmSelectionBoxGetChild (real_dialog, XmDIALOG_CANCEL_BUTTON); + + 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_FORM); ac++; + XtSetArg(al[ac], XmNbottomOffset, 4); ac++; + + XtSetArg(al[ac], XmNleftAttachment, XmATTACH_FORM); ac++; + XtSetArg(al[ac], XmNrightAttachment, XmATTACH_FORM); ac++; + XtSetValues ( widget29,al, ac ); + ac = 0; + + + + 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; + + XtManageChildren(children, ac); + ac = 0; + + resources_form = real_dialog; +} + + + +void +create_demo_dialog( parent ) +Widget parent; +{ + Widget children[11]; /* Children to manage */ + Arg al[64]; /* Arg List */ + register int ac = 0; /* Arg Count */ + XmString xmstrings[15]; /* temporary storage for XmStrings */ + + Widget real_dialog; + Widget w; + + + ac = 0; + XtSetArg (al[ac], XmNvisual, visual); ac++; + XtSetArg (al[ac], XmNcolormap, cmap); ac++; + XtSetArg (al[ac], XmNdepth, visual_depth); ac++; + + + real_dialog = XmCreatePromptDialog (parent, "demoForm", al, ac); + demo_dialog = XtParent(real_dialog); + + w = XmSelectionBoxGetChild (real_dialog, XmDIALOG_SEPARATOR); + if (w) XtUnmanageChild (w); + w = XmSelectionBoxGetChild (real_dialog, XmDIALOG_TEXT); + if (w) XtUnmanageChild (w); + w = XmSelectionBoxGetChild (real_dialog, XmDIALOG_SELECTION_LABEL); + if (w) XtUnmanageChild (w); + w = XmSelectionBoxGetChild (real_dialog, XmDIALOG_OK_BUTTON); + if (w) XtUnmanageChild (w); + w = XmSelectionBoxGetChild (real_dialog, XmDIALOG_CANCEL_BUTTON); + if (w) XtUnmanageChild (w); + w = XmSelectionBoxGetChild (real_dialog, XmDIALOG_HELP_BUTTON); + if (w) XtUnmanageChild (w); + + ac = 0; + XtSetArg (al [ac], XmNtopAttachment, XmATTACH_FORM); ac++; + XtSetArg (al [ac], XmNbottomAttachment, XmATTACH_FORM); ac++; + XtSetArg (al [ac], XmNleftAttachment, XmATTACH_FORM); ac++; + XtSetArg (al [ac], XmNrightAttachment, XmATTACH_FORM); ac++; + demo_form = XmCreateForm (real_dialog, "form", al, ac); + XtManageChild (demo_form); + + 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 ); + + ac = 0; + text_line = XmSelectionBoxGetChild (real_dialog, XmDIALOG_TEXT); + XtManageChild(text_line); + + next = XmCreatePushButton ( real_dialog, "next", al, ac ); + prev = XmCreatePushButton ( real_dialog, "prev", al, ac ); + edit = XmCreatePushButton ( real_dialog, "edit", al, ac ); + done = XmCreatePushButton ( real_dialog, "done", al, ac ); + restart = XmCreatePushButton ( real_dialog, "restart", al, ac ); + XtManageChild(next); + XtManageChild(prev); + XtManageChild(edit); + XtManageChild(done); + XtManageChild(restart); + + 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_FORM); 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 ); + + XtManageChild(demo_list); + XtManageChild(label1); + XtManageChild(label2); + + demo_form = real_dialog; +} diff --git a/driver/dialogs.xd b/driver/dialogs.xd new file mode 100644 index 00000000..ad1f6da0 --- /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-1994 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..3fe3a1c2 --- /dev/null +++ b/driver/lock.c @@ -0,0 +1,693 @@ +/* xscreensaver, Copyright (c) 1993-1995 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 anyone ever finishes the Athena locking code, remove this. + But until then, locking requires Motif. + */ +#if defined(NO_MOTIF) && !defined(NO_LOCKING) +# define NO_LOCKING +#endif + + +#ifndef NO_LOCKING + +#if __STDC__ +#include +#include +#include +#endif + +#ifdef HAVE_SHADOW +#include +#endif + +#include +#include + +#include + +#include "xscreensaver.h" + +extern char *screensaver_version; +extern char *progname; +extern XtAppContext app; +extern Bool verbose_p; + +#ifdef SCO +/* SCO has some kind of goofy, nonstandard security crap. This stuff was + donated by one of their victims, I mean users, Didier Poirot . + */ +# include +# include +# include +#endif + +#if !__STDC__ +# define _NO_PROTO +#endif + +#ifdef NO_MOTIF + +# include +# include +# include + +#else /* Motif */ + +# include +# include +# include + +#endif /* Motif */ + +Time passwd_timeout; + +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 P((Widget)); +extern void ungrab_keyboard_and_mouse P((void)); + +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]; + +#ifdef HAVE_SHADOW +# define PWTYPE struct spwd * +# define PWSLOT sp_pwdp +# define GETPW getspnam +#else +# define PWTYPE struct passwd * +# define PWSLOT pw_passwd +# define GETPW getpwnam +#endif + +#ifdef SCO +# define PRPWTYPE struct pr_passwd * +# define GETPRPW getprpwnam +#endif + +Bool +lock_init () +{ + Bool ok = True; + char *u; + PWTYPE p = GETPW ("root"); + +#ifdef SCO + PRPWTYPE prpwd = GETPRPW ("root"); + if (prpwd && *prpwd->ufld.fd_encrypt) + strcpy (root_passwd, prpwd->ufld.fd_encrypt); +#else /* !SCO */ + if (p && p->PWSLOT && p->PWSLOT[0] != '*') + strcpy (root_passwd, p->PWSLOT); +#endif /* !SCO */ + else + { + fprintf (stderr, "%s: couldn't get root's password\n", progname); + strcpy (root_passwd, "*"); + } + + /* It has been reported that getlogin() returns the wrong user id on some + very old SGI systems... */ + u = (char *) getlogin (); + if (u) + { +#ifdef SCO + prpwd = GETPRPW (u); +#endif /* SCO */ + p = GETPW (u); + } + else + { + /* getlogin() fails if not attached to a terminal; + in that case, use getpwuid(). */ + struct passwd *p2 = getpwuid (getuid ()); + u = p2->pw_name; +#ifdef HAVE_SHADOW + p = GETPW (u); +#else + p = p2; +#endif + } + +#ifdef SCO + if (prpwd && *prpwd->ufld.fd_encrypt) + strcpy (user_passwd, prpwd->ufld.fd_encrypt); +#else /* !SCO */ + if (p && p->PWSLOT && + /* p->PWSLOT[0] != '*' */ /* sensible */ + (strlen (p->PWSLOT) > 4) /* solaris */ + ) + strcpy (user_passwd, p->PWSLOT); +#endif /* !SCO */ + else + { + fprintf (stderr, "%s: couldn't get password of \"%s\"\n", progname, u); + strcpy (user_passwd, "*"); + ok = False; + } + return ok; +} + + + +#if defined(NO_MOTIF) || (XmVersion >= 1002) + /* The `destroy' bug apears to be fixed as of Motif 1.2.1, but + the `verify-callback' bug is still present. */ +# define DESTROY_WORKS +#endif + +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; +} + +#if !defined(NO_MOTIF) && defined(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. + + #### Update: Motif 1.2.1 also loses, but in a different way: it + #### writes beyond the end of a malloc'ed block in ModifyVerify(). + #### Probably this block is the text field's text. + */ + +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 +text_field_set_string (widget, text, position) + Widget widget; + char *text; + int position; +{ +#ifdef NO_MOTIF + XawTextBlock block; + block.firstPos = 0; + block.length = strlen (text); + block.ptr = text; + block.format = 0; + XawTextReplace (widget, 0, -1, &block); + XawTextSetInsertionPoint (widget, position); +#else /* !NO_MOTIF */ + XmTextFieldSetString (widget, text); + XmTextFieldSetInsertionPosition (widget, position); +#endif /* !NO_MOTIF */ +} + + +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] = '*'; + + text_field_set_string (passwd_text, s, 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] = '*'; + + text_field_set_string (passwd_text, s, 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)); + text_field_set_string (passwd_text, "", 0); +} + +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 || NO_MOTIF */ + +static void +format_into_label (widget, string) + Widget widget; + char *string; +{ + char *label; + char buf [255]; + Arg av[10]; + int ac = 0; + +#ifdef NO_MOTIF + XtSetArg (av [ac], XtNlabel, &label); ac++; + XtGetValues (widget, av, ac); +#else /* Motif */ + XmString xm_label = 0; + XmString new_xm_label; + XtSetArg (av [ac], XmNlabelString, &xm_label); ac++; + XtGetValues (widget, av, ac); + XmStringGetLtoR (xm_label, XmSTRING_DEFAULT_CHARSET, &label); +#endif /* Motif */ + + if (!label || !strcmp (label, XtName (widget))) + strcpy (buf, "ERROR: RESOURCES ARE NOT INSTALLED CORRECTLY"); + else + sprintf (buf, label, string); + + ac = 0; + +#ifdef NO_MOTIF + XtSetArg (av [ac], XtNlabel, buf); ac++; +#else /* Motif */ + new_xm_label = XmStringCreate (buf, XmSTRING_DEFAULT_CHARSET); + XtSetArg (av [ac], XmNlabelString, new_xm_label); ac++; +#endif /* Motif */ + + XtSetValues (widget, av, ac); +#ifndef NO_MOTIF + XmStringFree (new_xm_label); +#endif + 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], XtNforeground, &fg); ac++; + XtSetArg (av [ac], XtNbackground, &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); +} + +#ifdef NO_MOTIF + +static void +make_passwd_dialog (parent) + Widget parent; +{ + abort (); /* #### */ +} + +#else /* Motif */ + +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 + +#if !defined(NO_MOTIF) && (XmVersion >= 1002) + /* The focus stuff changed around; this didn't exist in 1.1.5. */ + XtVaSetValues (passwd_form, XmNinitialFocus, passwd_text, 0); +#endif + + /* Another random thing necessary in 1.2.1 but not 1.1.5... */ + XtVaSetValues (roger_label, XmNborderWidth, 2, 0); + + pw = getpwuid (getuid ()); + format_into_label (passwd_label3, (pw->pw_name ? pw->pw_name : "???")); + format_into_label (passwd_label1, screensaver_version); +} + +#endif /* Motif */ + +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 (XtParent(passwd_done)); + 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, ts, bs; + Dimension w = 0, h = 0; + XtVaGetValues(XtParent(passwd_done), + XmNwidth, &w, + 0); + XtVaGetValues(passwd_done, + XmNheight, &h, + XmNy, &y, + XtNforeground, &fg, + XtNbackground, &bg, + XmNtopShadowColor, &ts, + XmNbottomShadowColor, &bs, + 0); + + if (ts != bg && ts != fg) + fg = ts; + if (bs != bg && bs != fg) + fg = bs; + + d = h / 2; + if (d & 1) d++; + + x = (w / 2); + + x -= d/2; + y += d/2; + + 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, + (XtTimerCallbackProc) 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; + text_field_set_string (passwd_text, "", 0); + + 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)) + XMapRaised (dpy, XtWindow (passwd_dialog)); +#endif + + pop_up_dialog_box (passwd_dialog, passwd_form, 2); + XtManageChild (passwd_form); + +#if !defined(NO_MOTIF) && (XmVersion < 1002) + /* The focus stuff changed around; this causes problems in 1.2.1 + but is necessary in 1.1.5. */ + XmProcessTraversal (passwd_text, XmTRAVERSE_CURRENT); +#endif + + passwd_idle_timer_tick = passwd_timeout / 1000; + id = XtAppAddTimeOut (app, 1000, (XtTimerCallbackProc) passwd_idle_timer, 0); + + + XGrabServer (dpy); /* ############ DANGER! */ + + /* this call to ungrab used to be in main_loop() - see comment in + xscreensaver.c around line 696. */ + ungrab_keyboard_and_mouse (); + + 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 (); + } +#ifndef NO_MOTIF + XmProcessTraversal (passwd_cancel, 0); /* turn off I-beam */ +#endif + if (lose) + { + text_field_set_string (passwd_text, lose, strlen (lose) + 1); + passwd_idle_timer_tick = 1; + id = XtAppAddTimeOut (app, 3000, + (XtTimerCallbackProc) 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)); + text_field_set_string (passwd_text, "", 0); + XtSetKeyboardFocus (parent, None); + +#ifdef 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/stderr.c b/driver/stderr.c new file mode 100644 index 00000000..7d5fc136 --- /dev/null +++ b/driver/stderr.c @@ -0,0 +1,328 @@ +/* xscreensaver, Copyright (c) 1991-1995 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. + */ + +/* stderr hackery - Why Unix Sucks, reason number 32767. + */ + +#if __STDC__ +#include +#include +#endif + +#include +#include +#include + +#include + +#include "xscreensaver.h" + +extern XtAppContext app; +extern Colormap cmap; +extern Window screensaver_window; + +extern char *get_string_resource P((char *, char *)); +extern Bool get_boolean_resource P((char *, char *)); +extern unsigned int get_pixel_resource P((char *, char *, + Display *, Colormap)); + +static char stderr_buffer [1024]; +static char *stderr_tail = 0; +static time_t stderr_last_read = 0; +static XtIntervalId stderr_popup_timer = 0; + +FILE *real_stderr = 0; +FILE *real_stdout = 0; + +static int text_x = 0; +static int text_y = 0; + +void +reset_stderr () +{ + text_x = text_y = 0; +} + +static void +print_stderr (string) + char *string; +{ + int h_border = 20; + int v_border = 20; + static int line_height; + static XFontStruct *font = 0; + static GC gc = 0; + char *head = string; + char *tail; + + /* In verbose mode, copy it to stderr as well. */ + if (verbose_p) + fprintf (real_stderr, "%s", string); + + if (! gc) + { + XGCValues gcv; + Pixel fg, bg; + char *font_name = get_string_resource ("font", "Font"); + if (!font_name) font_name = "fixed"; + font = XLoadQueryFont (dpy, font_name); + if (! font) font = XLoadQueryFont (dpy, "fixed"); + line_height = font->ascent + font->descent; + fg = get_pixel_resource ("textForeground", "Foreground", dpy, cmap); + bg = get_pixel_resource ("textBackground", "Background", dpy, cmap); + gcv.font = font->fid; + gcv.foreground = fg; + gcv.background = bg; + gc = XCreateGC (dpy, screensaver_window, + (GCFont | GCForeground | GCBackground), &gcv); + } + + for (tail = string; *tail; tail++) + { + if (*tail == '\n' || *tail == '\r') + { + int maxy = HeightOfScreen (screen) - v_border - v_border; + if (tail != head) + XDrawImageString (dpy, screensaver_window, gc, + text_x + h_border, + text_y + v_border + font->ascent, + head, tail - head); + text_x = 0; + text_y += line_height; + head = tail + 1; + if (*tail == '\r' && *head == '\n') + head++, tail++; + + if (text_y > maxy - line_height) + { +#if 0 + text_y = 0; +#else + int offset = line_height * 5; + XCopyArea (dpy, screensaver_window, screensaver_window, gc, + 0, v_border + offset, + WidthOfScreen (screen), + (HeightOfScreen (screen) - v_border - v_border + - offset), + 0, v_border); + XClearArea (dpy, screensaver_window, + 0, HeightOfScreen (screen) - v_border - offset, + WidthOfScreen (screen), offset, False); + text_y -= offset; +#endif + } + } + } + if (tail != head) + { + int direction, ascent, descent; + XCharStruct overall; + XDrawImageString (dpy, screensaver_window, gc, + text_x + h_border, text_y + v_border + font->ascent, + head, tail - head); + XTextExtents (font, tail, tail - head, + &direction, &ascent, &descent, &overall); + text_x += overall.width; + } +} + + +static void +stderr_popup_timer_fn (closure, id) + XtPointer closure; + XtIntervalId *id; +{ + char *s = stderr_buffer; + if (*s) + { + /* If too much data was printed, then something has gone haywire, + so truncate it. */ + char *trailer = "\n\n<< stderr diagnostics have been truncated >>\n\n"; + int max = sizeof (stderr_buffer) - strlen (trailer) - 5; + if (strlen (s) > max) + strcpy (s + max, trailer); + /* Now show the user. */ + print_stderr (s); + } + + stderr_tail = stderr_buffer; + stderr_popup_timer = 0; +} + + +static void +stderr_callback (closure, fd, id) + XtPointer closure; + int *fd; + XtIntervalId *id; +{ + char *s; + int left; + int size; + int read_this_time = 0; + + if (stderr_tail == 0) + stderr_tail = stderr_buffer; + + left = ((sizeof (stderr_buffer) - 2) - (stderr_tail - stderr_buffer)); + + s = stderr_tail; + *s = 0; + + /* Read as much data from the fd as we can, up to our buffer size. */ + if (left > 0) + { + while ((size = read (*fd, (void *) s, left)) > 0) + { + left -= size; + s += size; + read_this_time += size; + } + *s = 0; + } + else + { + char buf2 [1024]; + /* The buffer is full; flush the rest of it. */ + while (read (*fd, (void *) buf2, sizeof (buf2)) > 0) + ; + } + + stderr_tail = s; + stderr_last_read = time ((time_t *) 0); + + /* Now we have read some data that we would like to put up in a dialog + box. But more data may still be coming in - so don't pop up the + dialog right now, but instead, start a timer that will pop it up + a second from now. Should more data come in in the meantime, we + will be called again, and will reset that timer again. So the + dialog will only pop up when a second has elapsed with no new data + being written to stderr. + + However, if the buffer is full (meaning lots of data has been written) + then we don't reset the timer. + */ + if (read_this_time > 0) + { + if (stderr_popup_timer) + XtRemoveTimeOut (stderr_popup_timer); + + stderr_popup_timer = + XtAppAddTimeOut (app, 1 * 1000, stderr_popup_timer_fn, 0); + } +} + +void +initialize_stderr () +{ + static Boolean done = False; + int fds [2]; + int in, out; + int new_stdout, new_stderr; + int stdout_fd = 1; + int stderr_fd = 2; + int flags; + Boolean stderr_dialog_p = get_boolean_resource ("captureStderr", "Boolean"); + Boolean stdout_dialog_p = get_boolean_resource ("captureStdout", "Boolean"); + + real_stderr = stderr; + real_stdout = stdout; + + if (!stderr_dialog_p && !stdout_dialog_p) + return; + + if (done) return; + done = True; + + if (pipe (fds)) + { + perror ("error creating pipe:"); + return; + } + + in = fds [0]; + out = fds [1]; + +# ifdef O_NONBLOCK + flags = O_NONBLOCK; +# else +# ifdef O_NDELAY + flags = O_NDELAY; +# else + ERROR!! neither O_NONBLOCK nor O_NDELAY are defined. +# endif +# endif + + /* Set both sides of the pipe to nonblocking - this is so that + our reads (in stderr_callback) will terminate, and so that + out writes (in the client programs) will silently fail when + the pipe is full, instead of hosing the program. */ + if (fcntl (in, F_SETFL, flags) != 0) + { + perror ("fcntl:"); + return; + } + if (fcntl (out, F_SETFL, flags) != 0) + { + perror ("fcntl:"); + return; + } + + if (stderr_dialog_p) + { + FILE *new_stderr_file; + new_stderr = dup (stderr_fd); + if (new_stderr < 0) + { + perror ("could not dup() a stderr:"); + return; + } + if (! (new_stderr_file = fdopen (new_stderr, "w"))) + { + perror ("could not fdopen() the new stderr:"); + return; + } + real_stderr = new_stderr_file; + + close (stderr_fd); + if (dup2 (out, stderr_fd) < 0) + { + perror ("could not dup() a new stderr:"); + return; + } + } + + if (stdout_dialog_p) + { + FILE *new_stdout_file; + new_stdout = dup (stdout_fd); + if (new_stdout < 0) + { + perror ("could not dup() a stdout:"); + return; + } + if (! (new_stdout_file = fdopen (new_stdout, "w"))) + { + perror ("could not fdopen() the new stdout:"); + return; + } + real_stdout = new_stdout_file; + + close (stdout_fd); + if (dup2 (out, stdout_fd) < 0) + { + perror ("could not dup() a new stdout:"); + return; + } + } + + XtAppAddInput (app, in, (XtPointer) XtInputReadMask, stderr_callback, 0); +} diff --git a/driver/subprocs.c b/driver/subprocs.c new file mode 100644 index 00000000..689bbb01 --- /dev/null +++ b/driver/subprocs.c @@ -0,0 +1,639 @@ +/* xscreensaver, Copyright (c) 1991, 1992, 1993, 1995 + * 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 would really like some error messages to show up on the screensaver window + itself when subprocs die, or when we can't launch them. If the process + produces output, but does not actually die, I would like that output to go + to the appropriate stdout/stderr as they do now. X and Unix conspire to + make this incredibly difficult. + + - Not all systems have SIGIO, so we can't necessarily be signalled when a + process dies, so we'd have to poll it with wait() or something awful like + that, which would mean the main thread waking up more often than it does + now. + + - We can't tell the difference between a process dying, and a process not + being launched correctly (for example, not being on $PATH) partly because + of the contortions we need to go through with /bin/sh in order to launch + it. + + - We can't do X stuff from signal handlers, so we'd need to set a flag, + save the error message, and notice that flag in the main thread. The + problem is that the main thread is probably sleeping, waiting for the + next X event, so to do this we'd have to register a pipe FD or something, + and write to it when something loses. + + - We could assume that any output produced by a subproc indicates an error, + and blast that across the screen. This means we'd need to use popen() + instead of forking and execing /bin/sh to run it for us. Possibly this + would work, but see comment in exec_screenhack() about getting pids. + I think we could do the "exec " trick with popen() but would SIGIO get + delivered correctly? Who knows. (We could register the pipe-FD with + Xt, and handle output on it with a callback.) + + - For the simple case of the programs not being on $PATH, we could just + search $PATH before launching the shell, but that seems hardly worth the + effort... And it's broken!! Why should we have to duplicate half the + work of the shell? (Because it's Unix, that's why! Bend over.) + */ + +#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 + +#include "yarandom.h" +#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; +char *nolock_reason = 0; +int nice_inferior = 0; + +extern Bool demo_mode_p; + +static void +#if __STDC__ +exec_screenhack (char *command) +#else +exec_screenhack (command) + char *command; +#endif +{ + 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. + + (Actually, Clint Wong points out that process groups + might be used to take care of this problem; this may be worth considering + some day, except that, 1: this code works now, so why fix it, and 2: from + what I've seen in Emacs, dealing with process groups isn't especially + portable.) + */ + 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(SVR4) || 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 that 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 +#if __STDC__ +await_child_death (Bool killed) +#else +await_child_death (killed) + Bool killed; +#endif +{ + 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; + /* One might assume that exiting with non-0 means something went + wrong. But that loser xswarm exits with the code that it was + killed with, so it *always* exits abnormally. Treat abnormal + exits as "normal" (don't mention them) if we've just killed + the subprocess. But mention them if they happen on their own. + */ + if (exit_status != 0 && (verbose_p || (! killed))) + fprintf (stderr, + "%s: %schild pid %d (%s) exited abnormally (code %d).\n", + progname, (verbose_p ? "## " : ""), + 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; + /* Locking can't work when running as root, because we have no way of + knowing what the user id of the logged in user is (so we don't know + whose password to prompt for.) + */ + locking_disabled_p = True; + nolock_reason = "running as root"; + p = getpwnam ("nobody"); + 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; + nolock_reason = hack_uid_buf; + sprintf (nolock_reason, "running as %s", p->pw_name); + } + } +#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..41b71258 --- /dev/null +++ b/driver/timers.c @@ -0,0 +1,526 @@ +/* xscreensaver, Copyright (c) 1991-1996 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. + */ + +/* #define DEBUG_TIMERS */ + +#include +#include +#include +#include +#include + +#ifdef HAVE_XIDLE_EXTENSION +#include +#endif /* HAVE_XIDLE_EXTENSION */ + +#ifdef HAVE_MIT_SAVER_EXTENSION +#include +extern int mit_saver_ext_event_number; +extern Window server_mit_saver_window; +#endif /* HAVE_MIT_SAVER_EXTENSION */ + +#ifdef HAVE_SGI_SAVER_EXTENSION +#include +extern int sgi_saver_ext_event_number; +#endif /* HAVE_SGI_SAVER_EXTENSION */ + +#include "xscreensaver.h" + +#if __STDC__ +# define P(x)x +#else +#define P(x)() +#endif + +extern XtAppContext app; + +Time cycle; +Time timeout; +Time pointer_timeout; +Time notice_events_timeout; + +extern Bool use_xidle_extension; +extern Bool use_mit_saver_extension; +extern Bool use_sgi_saver_extension; +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 when we have no server extensions */ +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 +#if __STDC__ +notice_events (Window window, Bool top_p) +#else +notice_events (window, top_p) + Window window; + Bool top_p; +#endif +{ + 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%lX\n", progname, + (unsigned long) 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 == BadMatch || + error->error_code == BadDrawable) + return 0; + XmuPrintDefaultErrorMessage (dpy, error, stderr); + exit (1); +} + +void +notice_events_timer (closure, timer) + XtPointer closure; + XtIntervalId *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, + (XtTimerCallbackProc) cycle_timer, 0); + +#ifdef DEBUG_TIMERS + if (verbose_p) + printf ("%s: starting cycle_timer (%ld, %ld)\n", + progname, how_long, cycle_id); +#endif +} + + +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 P((void)) +{ + if (use_mit_saver_extension || use_sgi_saver_extension) + return; + +#ifdef DEBUG_TIMERS + if (verbose_p) + printf ("%s: restarting idle_timer (%ld, %ld)\n", + progname, timeout, timer_id); +#endif + XtRemoveTimeOut (timer_id); + timer_id = XtAppAddTimeOut (app, timeout, + (XtTimerCallbackProc) idle_timer, 0); + if (cycle_id) abort (); + +#ifdef DEBUG_TIMERS + if (verbose_p) + printf ("%s: starting idle_timer (%ld, %ld)\n", + progname, timeout, timer_id); +#endif + + last_activity_time = time ((time_t *) 0); +} + +/* When we aren't using a server extension, 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; + + if (use_xidle_extension || + use_mit_saver_extension || + use_sgi_saver_extension) + abort (); + + *timerP = XtAppAddTimeOut (app, pointer_timeout, + (XtTimerCallbackProc) 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) + { + if (!use_mit_saver_extension && !use_sgi_saver_extension) + { + /* Wake up periodically to ask the server if we are idle. */ + timer_id = XtAppAddTimeOut (app, timeout, + (XtTimerCallbackProc) idle_timer, 0); +#ifdef DEBUG_TIMERS + if (verbose_p) + printf ("%s: starting idle_timer (%ld, %ld)\n", + progname, timeout, timer_id); +#endif + } + + if (!use_xidle_extension && + !use_mit_saver_extension && + !use_sgi_saver_extension) + /* 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_EXTENSION + if (use_xidle_extension) + { + if (! XGetIdleTime (dpy, &idle)) + { + fprintf (stderr, "%s: %sXGetIdleTime() failed.\n", + progname, (verbose_p ? "## " : "")); + exit (1); + } + } + else +#endif /* HAVE_XIDLE_EXTENSION */ +#ifdef HAVE_MIT_SAVER_EXTENSION + if (use_mit_saver_extension) + { + /* We don't need to do anything in this case - the synthetic + event isn't necessary, as we get sent specific events + to wake us up. */ + idle = 0; + } + else +#endif /* HAVE_MIT_SAVER_EXTENSION */ +#ifdef HAVE_SGI_SAVER_EXTENSION + if (use_sgi_saver_extension) + { + /* We don't need to do anything in this case - the synthetic + event isn't necessary, as we get sent specific events + to wake us up. */ + idle = 0; + } + else +#endif /* HAVE_SGI_SAVER_EXTENSION */ + { + idle = 1000 * (last_activity_time - time ((time_t *) 0)); + } + + if (idle >= timeout) + goto DONE; + else if (!use_mit_saver_extension && !use_sgi_saver_extension) + { + timer_id = XtAppAddTimeOut (app, timeout - idle, + (XtTimerCallbackProc) idle_timer, + 0); +#ifdef DEBUG_TIMERS + if (verbose_p) + printf ("%s: starting idle_timer (%ld, %ld)\n", + progname, timeout - idle, timer_id); +#endif /* DEBUG_TIMERS */ + } + } + break; + + case ClientMessage: + if (handle_clientmessage (&event, until_idle_p)) + goto DONE; + break; + + case CreateNotify: + if (!use_xidle_extension && + !use_mit_saver_extension && + !use_sgi_saver_extension) + { + XtAppAddTimeOut (app, notice_events_timeout, + (XtTimerCallbackProc) notice_events_timer, + (XtPointer) event.xcreatewindow.window); +#ifdef DEBUG_TIMERS + if (verbose_p) + printf ("%s: starting notice_events_timer for 0x%X (%lu)\n", + progname, + (unsigned int) event.xcreatewindow.window, + notice_events_timeout); +#endif /* DEBUG_TIMERS */ + } + 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, + (unsigned int) event.xkey.window, timestring ()); + } +#endif + + /* We got a user event */ + if (!until_idle_p) + goto DONE; + else + reset_timers (); + break; + + default: + +#ifdef HAVE_MIT_SAVER_EXTENSION + if (event.type == mit_saver_ext_event_number) + { + XScreenSaverNotifyEvent *sevent = + (XScreenSaverNotifyEvent *) &event; + if (sevent->state == ScreenSaverOn) + { +# ifdef DEBUG_TIMERS + if (verbose_p) + printf ("%s: ScreenSaverOn event received at %s\n", + progname, timestring ()); +# endif /* DEBUG_TIMERS */ + + /* Get the "real" server window out of the way as soon + as possible. */ + if (server_mit_saver_window && + window_exists_p (dpy, server_mit_saver_window)) + XUnmapWindow (dpy, server_mit_saver_window); + + if (sevent->kind != ScreenSaverExternal) + { +# ifdef DEBUG_TIMERS + fprintf (stderr, + "%s: ScreenSaverOn event wasn't of type External!\n", + progname); +# endif /* DEBUG_TIMERS */ + } + + if (until_idle_p) + goto DONE; + } + else if (sevent->state == ScreenSaverOff) + { +# ifdef DEBUG_TIMERS + if (verbose_p) + printf ("%s: ScreenSaverOff event received at %s\n", + progname, timestring ()); +# endif /* DEBUG_TIMERS */ + if (!until_idle_p) + goto DONE; + } +# ifdef DEBUG_TIMERS + else if (verbose_p) + printf ("%s: unknown MIT-SCREEN-SAVER event received at %s\n", + progname, timestring ()); +# endif /* DEBUG_TIMERS */ + } + else + +#endif /* HAVE_MIT_SAVER_EXTENSION */ + + +#ifdef HAVE_SGI_SAVER_EXTENSION + if (event.type == (sgi_saver_ext_event_number + ScreenSaverStart)) + { +# ifdef DEBUG_TIMERS + if (verbose_p) + printf ("%s: ScreenSaverStart event received at %s\n", + progname, timestring ()); +# endif /* DEBUG_TIMERS */ + + if (until_idle_p) + goto DONE; + } + else if (event.type == (sgi_saver_ext_event_number + ScreenSaverEnd)) + { +# ifdef DEBUG_TIMERS + if (verbose_p) + printf ("%s: ScreenSaverEnd event received at %s\n", + progname, timestring ()); +# endif /* DEBUG_TIMERS */ + if (!until_idle_p) + goto DONE; + } + else +#endif /* HAVE_SGI_SAVER_EXTENSION */ + + 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/windows.c b/driver/windows.c new file mode 100644 index 00000000..fa782b42 --- /dev/null +++ b/driver/windows.c @@ -0,0 +1,833 @@ +/* xscreensaver, Copyright (c) 1991-1996 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" + +#ifdef HAVE_MIT_SAVER_EXTENSION +#include +#endif /* HAVE_MIT_SAVER_EXTENSION */ + +#ifdef HAVE_SGI_SAVER_EXTENSION +#include +#endif /* HAVE_SGI_SAVER_EXTENSION */ + +extern Bool use_mit_saver_extension; +extern Bool use_sgi_saver_extension; + +#if __STDC__ +extern int kill (pid_t, int); /* signal() is in sys/signal.h... */ +#endif /* __STDC__ */ + +extern Time timeout; + +extern Bool lock_p, demo_mode_p; + +Atom XA_VROOT, XA_XSETROOT_ID; +Atom XA_SCREENSAVER_VERSION, XA_SCREENSAVER_ID; + +#if __STDC__ +extern void describe_visual (FILE *, Display *, Visual *); +extern void reset_stderr (void); +#endif + +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; + +#ifdef HAVE_MIT_SAVER_EXTENSION +Window server_mit_saver_window = 0; +#endif /* HAVE_MIT_SAVER_EXTENSION */ + +#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 P((void)) +{ + 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 P((void)) +{ + 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 server_timeout, server_interval, prefer_blank, allow_exp; + /* Turn off the server builtin saver if it is now running. */ + XForceScreenSaver (dpy, ScreenSaverReset); + XGetScreenSaver (dpy, &server_timeout, &server_interval, + &prefer_blank, &allow_exp); + +#if defined(HAVE_MIT_SAVER_EXTENSION) || defined(HAVE_SGI_SAVER_EXTENSION) + if (use_mit_saver_extension || use_sgi_saver_extension) + { + /* Override the values specified with "xset" with our own parameters. */ + allow_exp = True; + server_interval = 0; + server_timeout = (timeout / 1000); + + /* The SGI extension won't give us events unless blanking is on. + I think (unsure right now) that the MIT extension is the opposite. */ + prefer_blank = (use_sgi_saver_extension ? True : False); + + if (verbose_p) + fprintf (stderr, + "%s: configuring server for saver timeout of %d seconds.\n", + progname, server_timeout); + XSetScreenSaver (dpy, server_timeout, server_interval, + prefer_blank, allow_exp); + } + else +#endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */ + if (server_timeout != 0) + { + server_timeout = 0; + XSetScreenSaver (dpy, server_timeout, server_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 +#if __STDC__ +store_vroot_property (Window win, Window value) +#else +store_vroot_property (win, value) + Window win, value; +#endif +{ +#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 +#if __STDC__ +remove_vroot_property (Window win) +#else +remove_vroot_property (win) + Window win; +#endif +{ +#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 P((void)) +{ + 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%lX).\n", + progname, *dataP); + XKillClient (dpy, *dataP); + } + else + fprintf (stderr, "%s: %sdeleted unrecognised _XSETROOT_ID property: \n\ + %lu, %lu; type: %lu, format: %d, nitems: %lu, bytesafter %ld\n", + progname, (verbose_p ? "## " : ""), + (unsigned long) dataP, (dataP ? *dataP : 0), type, + format, nitems, bytesafter); + } +} + + +static void handle_signals P((Bool on_p)); + +static void +save_real_vroot P((void)) +{ + 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 P((void)) +{ + if (verbose_p && real_vroot) + printf ("%s: restoring __SWM_VROOT property on the real vroot (0x%lx).\n", + progname, (unsigned long) 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 +#if __STDC__ +catch_signal (int sig, char *signame, Bool on_p) +#else +catch_signal (sig, signame, on_p) + int sig; + char *signame; + Bool on_p; +#endif +{ + 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); +#ifdef SIGSYS + catch_signal (SIGSYS, "SIGSYS", on_p); +#endif + 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 */ + +Bool +window_exists_p (dpy, window) + Display *dpy; + Window window; +{ + int (*old_handler) (); + XWindowAttributes xgwa; + xgwa.screen = 0; + old_handler = XSetErrorHandler (BadWindow_ehandler); + XGetWindowAttributes (dpy, window, &xgwa); + XSync (dpy, False); + XSetErrorHandler (old_handler); + return (xgwa.screen != 0); +} + +void +initialize_screensaver_window P((void)) +{ + /* 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]; + + reset_stderr (); + + black.red = black.green = black.blue = 0; + + if (cmap == DefaultColormapOfScreen (screen)) + cmap = 0; + + if (install_cmap_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 | + CWBackPixel | CWBackingPixel | CWBorderPixel); + attrs.override_redirect = True; + + /* When use_mit_saver_extension or use_sgi_saver_extension is true, we won't + actually be reading these events during normal operation; but we still + need to see Button events for demo-mode to work properly. + */ + attrs.event_mask = (KeyPressMask | KeyReleaseMask | + ButtonPressMask | ButtonReleaseMask | + PointerMotionMask); + + attrs.backing_store = NotUseful; + attrs.colormap = cmap; + attrs.background_pixel = black_pixel; + attrs.backing_pixel = black_pixel; + attrs.border_pixel = black_pixel; + +#if 0 + if (demo_mode_p || lock_p) width = width / 2; /* #### */ +#endif + + if (screensaver_window || !verbose_p) + ; + else if (visual == DefaultVisualOfScreen (screen)) + { + fprintf (stderr, "%s: using default visual ", progname); + describe_visual (stderr, dpy, visual); + } + else + { + fprintf (stderr, "%s: using visual: ", progname); + describe_visual (stderr, dpy, visual); + fprintf (stderr, "%s: default visual: ", progname); + describe_visual (stderr, dpy, DefaultVisualOfScreen (screen)); + } + +#ifdef HAVE_MIT_SAVER_EXTENSION + if (use_mit_saver_extension) + { + XScreenSaverInfo *info; + Window root = RootWindowOfScreen (screen); + + /* This call sets the server screensaver timeouts to what we think + they should be (based on the resources and args xscreensaver was + started with.) It's important that we do this to sync back up + with the server - if we have turned on prematurely, as by an + ACTIVATE ClientMessage, then the server may decide to activate + the screensaver while it's already active. That's ok for us, + since we would know to ignore that ScreenSaverActivate event, + but a side effect of this would be that the server would map its + saver window (which we then hide again right away) meaning that + the bits currently on the screen get blown away. Ugly. */ +#if 0 + /* #### Ok, that doesn't work - when we tell the server that the + screensaver is "off" it sends us a Deactivate event, which is + sensible... but causes the saver to never come on. Hmm. */ + disable_builtin_screensaver (); +#endif /* 0 */ + +#if 0 + /* #### The MIT-SCREEN-SAVER extension gives us access to the + window that the server itself uses for saving the screen. + However, using this window in any way, in particular, calling + XScreenSaverSetAttributes() as below, tends to make the X server + crash. So fuck it, let's try and get along without using it... + + It's also inconvenient to use this window because it doesn't + always exist (though the ID is constant.) So to use this + window, we'd have to reimplement the ACTIVATE ClientMessage to + tell the *server* to tell *us* to turn on, to cause the window + to get created at the right time. Gag. */ + XScreenSaverSetAttributes (dpy, root, + 0, 0, width, height, 0, + visual_depth, InputOutput, visual, + attrmask, &attrs); + XSync (dpy, False); +#endif /* 0 */ + + info = XScreenSaverAllocInfo (); + XScreenSaverQueryInfo (dpy, root, info); + server_mit_saver_window = info->window; + if (! server_mit_saver_window) abort (); + XFree (info); + } +#endif /* HAVE_MIT_SAVER_EXTENSION */ + + 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); + } + +#ifdef HAVE_MIT_SAVER_EXTENSION + if (!use_mit_saver_extension || + window_exists_p (dpy, screensaver_window)) + /* When using the MIT-SCREEN-SAVER extension, the window pointed to + by screensaver_window only exists while the saver is active. + So we must be careful to only try and manipulate it while it + exists... + */ +#endif /* HAVE_MIT_SAVER_EXTENSION */ + { + 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)); + + 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); + if (verbose_p) fprintf (stderr, "%s: fading... ", progname); + 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, True); + if (verbose_p) fprintf (stderr, "fading done.\n"); + XClearWindow (dpy, screensaver_window); + XMapRaised (dpy, screensaver_window); + +#ifdef HAVE_MIT_SAVER_EXTENSION + if (server_mit_saver_window && + window_exists_p (dpy, server_mit_saver_window)) + XUnmapWindow (dpy, server_mit_saver_window); +#endif /* HAVE_MIT_SAVER_EXTENSION */ + + /* Once the saver window is up, restore the colormap. + (The "black" pixels of the two colormaps are compatible.) */ + XInstallColormap (dpy, cmap); + if (grabbed == GrabSuccess) + XUngrabPointer (dpy, CurrentTime); + XUngrabServer (dpy); + } + else + { + XClearWindow (dpy, screensaver_window); + XMapRaised (dpy, screensaver_window); +#ifdef HAVE_MIT_SAVER_EXTENSION + if (server_mit_saver_window && + window_exists_p (dpy, server_mit_saver_window)) + XUnmapWindow (dpy, server_mit_saver_window); +#endif /* HAVE_MIT_SAVER_EXTENSION */ + } + + if (install_cmap_p) + XInstallColormap (dpy, cmap); +} + +#ifdef __hpux + /* Calls to XHPDisableReset and XHPEnableReset must be balanced, + or BadAccess errors occur. */ +static Bool hp_locked_p = False; +#endif /* __hpux */ + +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 && !hp_locked_p) + XHPDisableReset (dpy); /* turn off C-Sh-Reset */ + hp_locked_p = True; +#endif +} + +void +unblank_screen () +{ + if (unfade_p && !demo_mode_p) + { + int grabbed; + Colormap default_map = DefaultColormapOfScreen (screen); + blacken_colormap (dpy, cmap2); + if (verbose_p) fprintf (stderr, "%s: unfading... ", progname); + 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, True); + XInstallColormap (dpy, default_map); + if (verbose_p) fprintf (stderr, "unfading done.\n"); + if (grabbed == GrabSuccess) + XUngrabPointer (dpy, CurrentTime); + XUngrabServer (dpy); + } + else + { + if (install_cmap_p) + { + XClearWindow (dpy, screensaver_window); /* avoid technicolor */ + XInstallColormap (dpy, DefaultColormapOfScreen (screen)); + } + XUnmapWindow (dpy, screensaver_window); + } + + + /* If the focus window does has a non-default colormap, then install + that colormap as well. (On SGIs, this will cause both the root map + and the focus map to be installed simultaniously. It'd be nice to + pick up the other colormaps that had been installed, too; perhaps + XListInstalledColormaps could be used for that?) + */ + { + Window focus = 0; + int revert_to; + XGetInputFocus (dpy, &focus, &revert_to); + if (focus && focus != PointerRoot && focus != None) + { + XWindowAttributes xgwa; + Colormap default_map = DefaultColormapOfScreen (screen); + xgwa.colormap = 0; + XGetWindowAttributes (dpy, focus, &xgwa); + if (xgwa.colormap && + xgwa.colormap != default_map) + XInstallColormap (dpy, xgwa.colormap); + } + } + + + kill_xsetroot_data (); + ungrab_keyboard_and_mouse (); + restore_real_vroot (); + +#ifdef __hpux + if (lock_p && hp_locked_p) + XHPEnableReset (dpy); /* turn C-Sh-Reset back on */ + hp_locked_p = False; +#endif +} diff --git a/driver/xscreensaver-command.c b/driver/xscreensaver-command.c new file mode 100644 index 00000000..d0aced94 --- /dev/null +++ b/driver/xscreensaver-command.c @@ -0,0 +1,151 @@ +/* xscreensaver-command, Copyright (c) 1991-1995 + * 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-1994 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\n", 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 = (char *) 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..06e88cbf --- /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..b0811c3e --- /dev/null +++ b/driver/xscreensaver.c @@ -0,0 +1,1183 @@ +/* xscreensaver, Copyright (c) 1991-1996 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 in one of three different ways: periodically + * checking with the XIdle server extension; selecting key and mouse events + * on (nearly) all windows; or by waiting for the MIT-SCREEN-SAVER extension + * to send us a "you are idle" event. + * + * Then, we map a full screen black window (or, in the case of the + * MIT-SCREEN-SAVER extension, use the one it gave us.) + * + * 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, MIT-SCREEN-SAVER, or SGI SCREEN_SAVER + * extensions, 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 one of the extensions, so install + * one of them if the description above sounds just too flaky to live. It + * is, but those are your choices. + * + * A third idle-detection option could be implemented (but is not): when + * running on the console display ($DISPLAY is `localhost`:0) and we're on a + * machine where /dev/tty and /dev/mouse have reasonable last-modification + * times, we could just stat() those. But the incremental benefit of + * implementing this is really small, so forget I said anything. + * + * 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 a server extension, 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 +#include + +#ifdef HAVE_XIDLE_EXTENSION +#include +#endif /* HAVE_XIDLE_EXTENSION */ + +#ifdef HAVE_MIT_SAVER_EXTENSION +#include +#endif /* HAVE_MIT_SAVER_EXTENSION */ + +#ifdef HAVE_SGI_SAVER_EXTENSION +#include +#endif /* HAVE_SGI_SAVER_EXTENSION */ + +#include "yarandom.h" +#include "xscreensaver.h" + +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, XtIntervalId *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)); + +extern void initialize_stderr P((void)); + +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; +#ifndef NO_LOCKING +extern Time passwd_timeout; +#endif +extern Time pointer_timeout; +extern Time notice_events_timeout; +extern XtIntervalId lock_id, cycle_id; + +Bool use_xidle_extension; +Bool use_mit_saver_extension; +Bool use_sgi_saver_extension; +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 char *nolock_reason; +extern Bool demo_mode_p; +extern Bool dbox_up_p; +extern int next_mode_p; + +#ifdef HAVE_MIT_SAVER_EXTENSION +int mit_saver_ext_event_number = 0; +int mit_saver_ext_error_number = 0; +#endif /* HAVE_MIT_SAVER_EXTENSION */ + +#ifdef HAVE_SGI_SAVER_EXTENSION +int sgi_saver_ext_event_number = 0; +int sgi_saver_ext_error_number = 0; +#endif /* HAVE_SGI_SAVER_EXTENSION */ + +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; +#endif + + +#ifdef NO_DEMO_MODE +# define demo_mode() abort() +#else +extern void demo_mode P((void)); +#endif + +static XrmOptionDescRec options [] = { + { "-timeout", ".timeout", XrmoptionSepArg, 0 }, + { "-cycle", ".cycle", XrmoptionSepArg, 0 }, + { "-idelay", ".initialDelay", XrmoptionSepArg, 0 }, + { "-nice", ".nice", XrmoptionSepArg, 0 }, + { "-visual", ".visualID", XrmoptionSepArg, 0 }, + { "-lock-timeout", ".lockTimeout", XrmoptionSepArg, 0 }, + { "-install", ".installColormap", XrmoptionNoArg, "on" }, + { "-no-install", ".installColormap", XrmoptionNoArg, "off" }, + { "-verbose", ".verbose", XrmoptionNoArg, "on" }, + { "-silent", ".verbose", XrmoptionNoArg, "off" }, + { "-xidle-extension", ".xidleExtension", XrmoptionNoArg, "on" }, + { "-no-xidle-extension", ".xidleExtension", XrmoptionNoArg, "off" }, + { "-mit-extension", ".mitSaverExtension",XrmoptionNoArg, "on" }, + { "-no-mit-extension", ".mitSaverExtension",XrmoptionNoArg, "off" }, + { "-sgi-extension", ".sgiSaverExtension",XrmoptionNoArg, "on" }, + { "-no-sgi-extension", ".sgiSaverExtension",XrmoptionNoArg, "off" }, + { "-lock", ".lock", XrmoptionNoArg, "on" }, + { "-no-lock", ".lock", XrmoptionNoArg, "off" } +}; + +static char *defaults[] = { +#include "XScreenSaver.ad.h" + 0 +}; + +static void +do_help P((void)) +{ + printf ("\ +xscreensaver %s, copyright (c) 1991-1996 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\ + -visual Which X visual to run on.\n\ + -demo Enter interactive demo mode on startup.\n\ + -install Install a private colormap.\n\ + -no-install Don't.\n\ + -verbose Be loud.\n\ + -silent Don't.\n\ + -xidle-extension Use the R5 XIdle server extension.\n\ + -no-xidle-extension Don't.\n\ + -mit-extension Use the R6 MIT_SCREEN_SAVER server extension.\n\ + -no-mit-extension Don't.\n\ + -sgi-extension Use the SGI SCREEN-SAVER server extension.\n\ + -no-sgi-extension 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 +#if !defined(HAVE_XIDLE_EXTENSION) && !defined(HAVE_MIT_SAVER_EXTENSION) && !defined(HAVE_SGI_SAVER_EXTENSION) + printf ("Support for the XIDLE, SCREEN_SAVER, and MIT-SCREEN-SAVER server\ + extensions\nwas not enabled at compile-time.\n"); +#endif /* !HAVE_XIDLE_EXTENSION && !HAVE_MIT_SAVER_EXTENSION && !HAVE_SGI_SAVER_EXTENSION */ + + fflush (stdout); + exit (1); +} + + +static void +get_screenhacks P((void)) +{ + 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 P((void)) +{ + /* Note: we can't use the resource ".visual" because Xt is SO FUCKED. */ + visual = get_visual_resource (dpy, "visualID", "VisualID"); + 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"); + pointer_timeout = 1000 * get_seconds_resource ("pointerPollTime", "Time"); + notice_events_timeout = 1000 * get_seconds_resource ("windowCreationTimeout", + "Time"); +#ifndef NO_LOCKING + passwd_timeout = 1000 * get_seconds_resource ("passwdTimeout", "Time"); + if (passwd_timeout == 0) passwd_timeout = 30000; +#endif + if (timeout < 10000) timeout = 10000; + if (cycle != 0 && cycle < 2000) cycle = 2000; + 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; + nolock_reason = "not compiled with locking support"; + 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 (%s).\n", progname, + (verbose_p ? "## " : ""), nolock_reason); + lock_p = False; + } +#endif /* ! NO_LOCKING */ + + /* don't set use_xidle_extension unless it is explicitly specified */ + if (get_string_resource ("xidleExtension", "Boolean")) + use_xidle_extension = get_boolean_resource ("xidleExtension", "Boolean"); + else +#ifdef HAVE_XIDLE_EXTENSION /* pick a default */ + use_xidle_extension = True; +#else /* !HAVE_XIDLE_EXTENSION */ + use_xidle_extension = False; +#endif /* !HAVE_XIDLE_EXTENSION */ + + /* don't set use_saver_extension unless it is explicitly specified */ + if (get_string_resource ("mitSaverExtension", "Boolean")) + use_mit_saver_extension = get_boolean_resource ("mitSaverExtension", + "Boolean"); + else +#ifdef HAVE_MIT_SAVER_EXTENSION /* pick a default */ + use_mit_saver_extension = True; +#else /* !HAVE_MIT_SAVER_EXTENSION */ + use_mit_saver_extension = False; +#endif /* !HAVE_MIT_SAVER_EXTENSION */ + + /* don't set use_saver_extension unless it is explicitly specified */ + if (get_string_resource ("sgiSaverExtension", "Boolean")) + use_sgi_saver_extension = get_boolean_resource ("sgiSaverExtension", + "Boolean"); + else +#ifdef HAVE_SGI_SAVER_EXTENSION /* pick a default */ + use_sgi_saver_extension = True; +#else /* !HAVE_SGI_SAVER_EXTENSION */ + use_sgi_saver_extension = False; +#endif /* !HAVE_SGI_SAVER_EXTENSION */ + + get_screenhacks (); +} + +char * +timestring P((void)) +{ + 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 P((int argc, char **argv)); +static void main_loop P((void)); + +void +main (argc, argv) + int argc; + char **argv; +{ + initialize (argc, argv); + main_loop (); +} + + +static int +saver_ehandler (dpy, error) + Display *dpy; + XErrorEvent *error; +{ + fprintf (real_stderr, "\nX error in %s:\n", progname); + if (XmuPrintDefaultErrorMessage (dpy, error, real_stderr)) + exit (-1); + else + fprintf (real_stderr, " (nonfatal.)\n"); + return 0; +} + +static void +#if __STDC__ +initialize_connection (int argc, char **argv) +#else +initialize_connection (argc, argv) + int argc; + char **argv; +#endif +{ + 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); +} + +#ifdef HAVE_MIT_SAVER_EXTENSION + +static int +ignore_all_errors_ehandler (dpy, error) + Display *dpy; + XErrorEvent *error; +{ + return 0; +} + +static void +init_mit_saver_extension () +{ + XID kill_id; + Atom kill_type; + Window root = RootWindowOfScreen (screen); + Pixmap blank_pix = XCreatePixmap (dpy, root, 1, 1, 1); + + /* Kill off the old MIT-SCREEN-SAVER client if there is one. + This tends to generate X errors, though (possibly due to a bug + in the server extension itself?) so just ignore errors here. */ + if (XScreenSaverGetRegistered (dpy, XScreenNumberOfScreen (screen), + &kill_id, &kill_type) + && kill_id != blank_pix) + { + int (*old_handler) (); + old_handler = XSetErrorHandler (ignore_all_errors_ehandler); + XKillClient (dpy, kill_id); + XSync (dpy, False); + XSetErrorHandler (old_handler); + } + + XScreenSaverSelectInput (dpy, root, ScreenSaverNotifyMask); + + XScreenSaverRegister (dpy, XScreenNumberOfScreen (screen), + (XID) blank_pix, XA_PIXMAP); +} +#endif /* HAVE_MIT_SAVER_EXTENSION */ + + +#ifdef HAVE_SGI_SAVER_EXTENSION + +static void +init_sgi_saver_extension () +{ + if (! XScreenSaverEnable (dpy, XScreenNumberOfScreen(screen))) + { + fprintf (stderr, + "%s: %sSGI SCREEN_SAVER extension exists, but can't be initialized;\n\ + perhaps some other screensaver program is already running?\n", + progname, (verbose_p ? "## " : "")); + use_sgi_saver_extension = False; + } +} + +#endif /* HAVE_SGI_SAVER_EXTENSION */ + + +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; + nolock_reason = "not compiled with locking support"; +#else + locking_disabled_p = False; + +#ifdef SCO + set_auth_parameters(argc, argv); +#endif + + if (! lock_init ()) /* before hack_uid() for proper permissions */ + { + locking_disabled_p = True; + nolock_reason = "error getting password"; + } +#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 (); + + if (verbose_p) + printf ("\ +%s %s, copyright (c) 1991-1996 by Jamie Zawinski .\n\ + pid = %d.\n", progname, screensaver_version, getpid ()); + ensure_no_screensaver_running (); + + demo_mode_p = initial_demo_mode_p; + screensaver_window = 0; + cursor = 0; + srandom ((int) time ((time_t *) 0)); + cycle_id = 0; + lock_id = 0; + locked_p = False; + + if (use_sgi_saver_extension) + { +#ifdef HAVE_SGI_SAVER_EXTENSION + if (! XScreenSaverQueryExtension (dpy, + &sgi_saver_ext_event_number, + &sgi_saver_ext_error_number)) + { + fprintf (stderr, + "%s: %sdisplay %s does not support the SGI SCREEN_SAVER extension.\n", + progname, (verbose_p ? "## " : ""), DisplayString (dpy)); + use_sgi_saver_extension = False; + } + else if (use_mit_saver_extension) + { + fprintf (stderr, "%s: %sSGI SCREEN_SAVER extension used instead\ + of MIT-SCREEN-SAVER extension.\n", + progname, (verbose_p ? "## " : "")); + use_mit_saver_extension = False; + } + else if (use_xidle_extension) + { + fprintf (stderr, + "%s: %sSGI SCREEN_SAVER extension used instead of XIDLE extension.\n", + progname, (verbose_p ? "## " : "")); + use_xidle_extension = False; + } +#else /* !HAVE_MIT_SAVER_EXTENSION */ + fprintf (stderr, + "%s: %snot compiled with support for the SGI SCREEN_SAVER extension.\n", + progname, (verbose_p ? "## " : "")); + use_sgi_saver_extension = False; +#endif /* !HAVE_SGI_SAVER_EXTENSION */ + } + + if (use_mit_saver_extension) + { +#ifdef HAVE_MIT_SAVER_EXTENSION + if (! XScreenSaverQueryExtension (dpy, + &mit_saver_ext_event_number, + &mit_saver_ext_error_number)) + { + fprintf (stderr, + "%s: %sdisplay %s does not support the MIT-SCREEN-SAVER extension.\n", + progname, (verbose_p ? "## " : ""), DisplayString (dpy)); + use_mit_saver_extension = False; + } + else if (use_xidle_extension) + { + fprintf (stderr, + "%s: %sMIT-SCREEN-SAVER extension used instead of XIDLE extension.\n", + progname, (verbose_p ? "## " : "")); + use_xidle_extension = False; + } +#else /* !HAVE_MIT_SAVER_EXTENSION */ + fprintf (stderr, + "%s: %snot compiled with support for the MIT-SCREEN-SAVER extension.\n", + progname, (verbose_p ? "## " : "")); + use_mit_saver_extension = False; +#endif /* !HAVE_MIT_SAVER_EXTENSION */ + } + + if (use_xidle_extension) + { +#ifdef HAVE_XIDLE_EXTENSION + int first_event, first_error; + if (! XidleQueryExtension (dpy, &first_event, &first_error)) + { + fprintf (stderr, + "%s: %sdisplay %s does not support the XIdle extension.\n", + progname, (verbose_p ? "## " : ""), DisplayString (dpy)); + use_xidle_extension = False; + } +#else /* !HAVE_XIDLE_EXTENSION */ + fprintf (stderr, "%s: %snot compiled with support for XIdle.\n", + progname, (verbose_p ? "## " : "")); + use_xidle_extension = False; +#endif /* !HAVE_XIDLE_EXTENSION */ + } + + /* Call this only after having probed for presence of desired extension. */ + initialize_screensaver_window (); + + init_sigchld (); + + disable_builtin_screensaver (); + +#ifdef HAVE_MIT_SAVER_EXTENSION + if (use_mit_saver_extension) + init_mit_saver_extension (); +#endif /* HAVE_MIT_SAVER_EXTENSION */ + +#ifdef HAVE_SGI_SAVER_EXTENSION + if (use_sgi_saver_extension) + init_sgi_saver_extension (); +#endif /* HAVE_SGI_SAVER_EXTENSION */ + + if (verbose_p && use_mit_saver_extension) + fprintf (stderr, "%s: using MIT-SCREEN-SAVER server extension.\n", + progname); + if (verbose_p && use_sgi_saver_extension) + fprintf (stderr, "%s: using SGI SCREEN_SAVER server extension.\n", + progname); + if (verbose_p && use_xidle_extension) + fprintf (stderr, "%s: using XIdle server extension.\n", + progname); + + initialize_stderr (); + XSetErrorHandler (saver_ehandler); + + if (initial_demo_mode_p) + /* If the user wants demo mode, don't wait around before doing it. */ + initial_delay = 0; + + if (!use_xidle_extension && + !use_mit_saver_extension && + !use_sgi_saver_extension) + { + if (initial_delay) + { + if (verbose_p) + { + printf ("%s: waiting for %d second%s...", progname, + (int) 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, + (XtTimerCallbackProc)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, + (XtTimerCallbackProc) + 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; + + /* We used to ungrab the keyboard here, before calling unlock_p() + to pop up the dialog box. This left the keyboard ungrabbed + for a small window, during an insecure state. Bennett Todd + was seeing the bahavior that, when the load was high, he could + actually get characters through to a shell under the saver + window (he accidentally typed his password there...) + + So the ungrab has been moved down into pop_passwd_dialog() + just after the server is grabbed, closing this window + entirely. + */ + /* 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); + + /* I think this grab is now redundant, but it shouldn't hurt. */ + 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 = 0; + 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); + return False; + } + if (event->xclient.format != 32) + { + fprintf (stderr, "%s: %sClientMessage of format %d received, not 32\n", + progname, (verbose_p ? "## " : ""), event->xclient.format); + return False; + } + type = event->xclient.data.l[0]; + if (type == XA_ACTIVATE) + { + if (until_idle_p) + { + if (verbose_p) + printf ("%s: ACTIVATE ClientMessage received.\n", progname); + if (use_mit_saver_extension || use_sgi_saver_extension) + { + XForceScreenSaver (dpy, ScreenSaverActive); + return False; + } + else + { + 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); + if (use_mit_saver_extension || use_sgi_saver_extension) + { + XForceScreenSaver (dpy, ScreenSaverReset); + return False; + } + else + { + 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) + { + if (use_mit_saver_extension || use_sgi_saver_extension) + { + XForceScreenSaver (dpy, ScreenSaverActive); + return False; + } + else + { + return True; + } + } + } +#endif + } + else + { + char *str; + str = (type ? XGetAtomName(dpy, type) : 0); + 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 ? "## " : ""), + (unsigned int) 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..9b933347 --- /dev/null +++ b/driver/xscreensaver.h @@ -0,0 +1,70 @@ +/* xscreensaver, Copyright (c) 1993-1996 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 + +#if __STDC__ +# define P(x)x +#else +# define P(x)() +# ifndef const +# define const /**/ +# endif +#endif + +#ifdef NO_MOTIF +# define NO_DEMO_MODE + + /* #### If anyone ever finishes the Athena locking code, remove this. + Until then, Locking requires Motif. */ +# 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 FILE *real_stderr; +extern FILE *real_stdout; + +extern void initialize_screensaver_window P((void)); +extern void raise_window P((Bool inhibit_fade, Bool between_hacks_p)); +extern void blank_screen P((void)); +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,Bool)); +extern void blacken_colormap P((Display *, Colormap)); + +extern int BadWindow_ehandler P((Display *dpy, XErrorEvent *error)); + +extern char *timestring P((void)); +extern Bool window_exists_p P((Display *dpy, Window window)); diff --git a/driver/xscreensaver.man b/driver/xscreensaver.man new file mode 100644 index 00000000..7ebf76c3 --- /dev/null +++ b/driver/xscreensaver.man @@ -0,0 +1,567 @@ +.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 "6-Jan-95" "X Version 11" +.SH NAME +xscreensaver - graphics hack and screen locker, launched when the user is idle +.SH SYNOPSIS +.B xscreensaver +[\-display \fIhost:display.screen\fP] [\-timeout \fIint\fP] [\-cycle \fIint\fP] [\-nice \fIint\fP] [\-verbose] [\-silent] [\-lock] [\-no\-lock] [\-lock\-timeout \fIint\fP] [\-demo] [\-visual \fIvisual\fP] [\-install] [\-no\-install] [\-xidle\-extension] [\-no\-xidle\-extension] [\-sgi\-extension] [\-no\-sgi\-extension] [\-mit\-extension] [\-no\-mit\-extension] [\-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\-extension +Use the \fBXIDLE\fP server extension to decide whether the user is idle. +This is the default if \fIxscreensaver\fP has been compiled with support +for this extension. On X11R4 or X11R5 systems, 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\-extension +Don't use the \fBXIDLE\fP server extension. +.TP 8 +.B \-sgi\-extension +Use the SGI \fBSCREEN_SAVER\fP server extension to decide whether the user +is idle. This is the default if \fIxscreensaver\fP has been compiled with +support for this extension. On SGI systems, the \fBSCREEN_SAVER\fP +method is faster and more reliable than what will be done otherwise, so use +it if you can. +.TP 8 +.B \-no\-sgi\-extension +Don't use the SGI \fBSCREEN_SAVER\fP server extension. +.TP 8 +.B \-mit\-extension +Use the \fBMIT\-SCREEN\-SAVER\fP server extension to decide whether the user +is idle. This is the default if \fIxscreensaver\fP has been compiled with +support for this extension. This extension is flaky, so it's use is not +really recommended. +.TP 8 +.B \-no\-mit\-extension +Don't use the \fBMIT\-SCREEN\-SAVER\fP server extension. +.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 \-visual \fIvisual\fP +Specify which visual to use. Legal values are: +.RS 8 +.TP 8 +.B best +Use the visual which supports the most writable color cells; this is +the default. +.TP 8 +.B default +Use the screen's default visual (the visual of the root window.) This is +not necessarily the most colorful visual, which is why it is not the default. +.TP 8 +.I class +One of \fBStaticGray\fP, \fBStaticColor\fP, \fBTrueColor\fP, \fBGrayScale\fP, +\fBPseudoColor\fP, or \fBDirectColor\fP. Selects the deepest visual of +the given class. +.TP 8 +.I number +A number (decimal or hex) is interpreted as a visual id number, as reported +by the +.BR xdpyinfo (1) +program; in this way you can select a shallower visual if desired. +.RE +.TP 8 +.B \-no\-install +Use the default colormap. This is the default. +.TP 8 +.B \-install +Install a private colormap while the screensaver is on, so that the graphics +hacks can get as many colors as possible. +.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) +Same as the \fI\-install\fP command-line option. 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 visualID \fR(class \fBVisualID\fP) +Same as the \fI\-visual\fP command-line option. Default \fBbest\fP. +.TP 8 +.B captureStderr \fR(class \fBBoolean\fP) +Whether \fIxscreensaver\fP should redirect its standard-error stream to the +window itself. Since its nature is to take over the screen, you would not +normally see error messages generated by the screensaver or the programs it +runs; this resource will cause the output of all relevant programs to be +drawn on the screensaver window itself instead of written to the controlling +terminal of the screensaver driver process. Default: True. +.TP 8 +.B captureStdout \fR(class \fBBoolean\fP) +Like \fBcaptureStderr\fP but for the standard-output stream. Default: True. +.TP 8 +.B font \fR(class \fBFont\fP) +The font used for the stdout/stderr text, if \fBcaptureStdout\fP or +\fBcaptureStderr\fP are true. Default \fB*\-medium\-r\-*\-140\-*\-m\-*\fP +(a 14 point fixed-width font.) +.TP 8 +.B textForeground \fR(class \fBForeground\fP) +The foreground color used for the stdout/stderr text, if \fBcaptureStdout\fP +or \fBcaptureStderr\fP are true. Default: Yellow. +.TP 8 +.B textBackground \fR(class \fBBackground\fP) +The background color used for the stdout/stderr text, if \fBcaptureStdout\fP +or \fBcaptureStderr\fP are true. Default: Black. +.TP 8 +.B programs \fR(class \fBPrograms\fP) +The graphics hacks which \fIxscreensaver\fP runs when the user is idle, +in addition to those specified in colorPrograms or monoPrograms (as +appropriate.) 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 +.RS 4 +\fBNOTE: this means that if you want to completely replace the list of +programs which xscreensaver runs, you must set at least \fItwo\fP, +possibly \fIthree\fP resources. It is not enough to just set +the \fBprograms\fP resource -- you must also set \fBcolorPrograms\fP +or \fBmonoPrograms\fP or both.\fP +.RE +.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 server extensions are 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 server extensions are 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 server extensions are 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 +(If your system does not seem to be executing the \fIXsetup\fP file, you +may need to configure it to do so -- the traditional way to do this is +to make that file the value of the \fIDisplayManager*setup\fP resource +in the \fIxdm-config\fP file. See the man page for +.BR xdm (1) +for more details.) +.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 decayscreen (1), +.BR hypercube (1), +.BR flame (1), +.BR bubbles (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 think you have changed the \fBprograms\fP resource but the +screensaver is ignoring it, you are confused -- you need to set +the \fBcolorPrograms\fP and/or \fBmonoPrograms\fP resources as well. +(This is not a bug, but I mention it here because people think that +it is with great regularity.) +.PP +If you are not making use of one of the server extensions (\fBXIDLE\fP, +\fBSCREEN_SAVER\fP, or \fBMIT-SCREEN-SAVER\fP), then it is possible, in rare +situations, for \fIxscreensaver\fP to interfere with event propagation and make +another X program malfunction. For this to occur, that other application +would need to \fInot\fP select \fBKeyPress\fP events on its non-leaf windows +within the first 30 seconds of their existence, but then select for them later. +In this case, that client \fImight\fP fail to receive those events. +This isn't very likely, since programs generally select a constant set +of events immediately after creating their windows and then don't change +them, but this is the reason that it's a good idea to install and use one +of the server extensions instead, to work around this shortcoming in the +X protocol. +.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 can run multiple screensaver processes, one for +each screen. This interacts poorly with locking. In an ideal world, the +screensaver would save (and lock) both screens simultaniously, and any activity +would restore both screens. It would be nice if one could run different hacks +on each screen simultaniously. However, I don't have access to a multi-headed +workstation, so it would be hard for me to implement something like this. +.PP +If you don't have Motif, you can't compile with support for locking or +demo mode. +.PP +Locking doesn't work if the screensaver is launched by \fIxdm\fP. +The reason for this is that when it is launched by \fIxdm\fP, the +screensaver process is owned by some standard user id (such as \fIroot\fP +or \fIdaemon\fP) instead of the user who is logged in on the console. +In order for the screensaver to prompt for the password of the person +who had logged in from \fIxdm\fP, it would need to know who that user was, +and there is no reliable and safe way to figure that out. (And even if +there was, there would be some other security issues here as well.) + +So if you want to use it as a locker, you must start it with your user id. +If it has already been started by \fIxdm\fP, you can kill it with +\fBxscreensaver-command -exit\fP, and then start it again as you. +.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 +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. (If the screen goes white instead of +black, this is probably why.) 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 +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. +.PP +When using the \fBMIT-SCREEN-SAVER\fP extension in conjunction with +the \fBfade\fP option, you may notice an unattractive flicker just before +the fade begins. This is because the server maps a black window just before +it tells the \fIxscreensaver\fP process to activate. The \fIxscreensaver\fP +process immediately unmaps that window, but this results in a flicker. I +haven't figured a way to get around this; it seems to be a fundamental +property of the (mis-) design of this server extension. +.PP +There need to be a lot more graphics hacks. In particular, there should be +a simulation of a Lavalite (tm). +.SH UPGRADES +The latest version can always be found at http://www.netscape.com/people/jwz/. +There is also usually an up-to-date copy at ftp://ftp.x.org/. +.SH COPYRIGHT +Copyright \(co 1992, 1993, 1994, 1995, 1996 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. + +Thanks to Martin Kraemer for adding support for shadow passwords and +locking-disabled diagnostics. 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..e9e6ed87 --- /dev/null +++ b/hacks/Imakefile @@ -0,0 +1,84 @@ +/* + * Imakefile file for xscreensaver, Copyright (c) 1993, 1995 Jamie Zawinski. + * + * You should not need to edit this file; edit ../config.h instead. + * + */ + +#include "../config.h" + +#ifdef HAVE_XPM + /* Yeah, this means that all hacks link against libXpm even though only + one hack actually uses it. It doesn't matter: it's a library. */ +# define XPMDEFS -DHAVE_XPM +# define XPMLIB -lXpm +#else +# define XPMDEFS +# define XPMLIB +#endif + + STAR = * + UTILS = ../utils + INCLUDES = -I$(UTILS) + DEFINES = R5ISMS XPMDEFS +LOCAL_LIBRARIES = $(XMULIB) $(XTOOLLIB) XPMLIB $(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 decayscreen.c maze.c hypercube.c \ + halo.c flame.c pedal.c lmorph.c \ + bubbles.c bubbles.h bubbles_default.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 \ + decayscreen.man maze.man hypercube.man halo.man flame.man \ + pedal.man lmorph.man \ + bubbles.man bubbles.README + TARFILES = README Imakefile screenhack.c $(HACKS) screenhack.h \ + vroot.h xlock.h default.xbm $(MEN) .gdbinit \ + noses/nose.$(STAR) \ + bubbles-tools/bubbles$(STAR) \ + bubbles-tools/xpm$(STAR) \ + bubbles-sources/$(STAR).pov \ + bubbles-samples/$(STAR).bub.gz + +all:: + +echo_tarfiles: + @echo $(TARFILES) + +#define ScreenhackTarget(p,ps,deps) @@\ +all:: p @@\ +p: deps screenhack.h ps.o $(DEPLIBS) @@\ + RemoveTargetProgram($@) @@\ + $(CCENVSETUP) \ + $(CC) -o $@ $(LDOPTIONS) deps ps.o $(LOCAL_LIBRARIES) $(LDLIBS) @@\ + @@\ +InstallProgram(p,$(BINDIR)) @@\ +InstallManPage(p,$(MANDIR)) @@\ +clean:: @@\ + $(RM) p + +HOBJS=screenhack.o $(UTILS)/resources.o $(UTILS)/visual.o \ + $(UTILS)/usleep.o $(UTILS)/yarandom.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) $(UTILS)/grabscreen.o) +ScreenhackTarget (decayscreen, decayscreen, $(HOBJS) $(UTILS)/grabscreen.o) +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) +ScreenhackTarget (flame, flame, $(HOBJS) $(UTILS)/hsv.o) +ScreenhackTarget (pedal, pedal, $(HOBJS) $(UTILS)/hsv.o) +ScreenhackTarget (lmorph, lmorph, $(HOBJS)) +ScreenhackTarget (bubbles, bubbles, bubbles_default.o $(HOBJS)) 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..8e3f188f --- /dev/null +++ b/hacks/attraction.c @@ -0,0 +1,685 @@ +/* xscreensaver, Copyright (c) 1992, 1995 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 . Mouse control and + viscosity added by "Philip Edward Cutone, III" . + + 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. + + Philip sez: + > An even normal viscosity (rather than the thresholded version to + > bleed excess energy) is also not interesting. + + unless you make about 200 points.... set the viscosity to about .8 + and drag the mouse through it. it makes a nice wave which travels + through the field. + */ + +#include +#include +#include "screenhack.h" +#include "spline.h" + +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; + +/*flip mods for mouse interaction*/ +static Bool mouse_p; +int mouse_x, mouse_y, mouse_mass, root_x, root_y; +static float viscosity; + +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; + + /*flip mods for mouse interaction*/ + mouse_p = get_boolean_resource ("mouse", "Boolean"); + mouse_mass = get_integer_resource ("mouseSize", "Integer"); + mouse_mass = mouse_mass * mouse_mass *10; + + viscosity = get_float_resource ("viscosity", "Float"); + + 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; + XQueryColor (dpy, cmap, &color); + 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; + float x_dist, y_dist, dist, dist2; + *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); + } + } + + if (mouse_p) + { + x_dist = mouse_x - balls [i].x; + y_dist = mouse_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 = ((mouse_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; + + /*flip mods for mouse interaction*/ + Window root1, child1; + int mask; + if (mouse_p) + { + XQueryPointer(dpy, window, &root1, &child1, + &root_x, &root_y, &mouse_x, &mouse_y, &mask); + } + + 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; + } + else if (viscosity != 1) + { + balls[i].vx *= viscosity; + } + + if (balls[i].vy > 10) + { + balls[i].vy *= 0.9; + balls[i].dy = 0; + } + else if (viscosity != 1) + { + balls[i].vy *= viscosity; + } + + 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, desired; + 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 (); + } + + desired = color2; + if (XAllocColor (dpy, cmap, &color2)) + { + /* XAllocColor returns the actual RGB that the hardware let us + allocate. Restore the requested values into the XColor struct + so that limited-resolution hardware doesn't cause cycle_hue to + get "stuck". */ + color2.red = desired.red; + color2.green = desired.green; + color2.blue = desired.blue; + } + else + { + 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 [] = { + "Attraction.background: black", /* to placate SGI */ + "Attraction.foreground: white", + "*mode: balls", + "*points: 0", + "*size: 0", + "*threshold: 100", + "*delay: 10000", + "*glow: false", + "*mouseSize: 10", + "*mouse: false", + "*viscosity: 1", + "*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 }, + { "-mouse-size", ".mouseSize", XrmoptionSepArg, 0 }, + { "-mouse", ".mouse", XrmoptionNoArg, "true" }, + { "-nomouse", ".mouse", XrmoptionNoArg, "false" }, + { "-viscosity", ".viscosity", 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..e3f94243 --- /dev/null +++ b/hacks/attraction.man @@ -0,0 +1,179 @@ +.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 "14-Dec-95" "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] [\-install] [\-visual \fIvisual\fP] [\-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] [\-viscosity \fIfloat\fP] [\-mouse] [\-no-mouse] [\-mouse-size] +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +Specify which visual to use. Legal values are the name of a visual class, +or the id number (decimal or hex) of a specific visual. +.TP 8 +.B \-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. +.TP 8 +.B \-viscosity float +This sets the viscosity of the hypothetical fluid through which the control +points move; the default is 1, meaning no resistance. Values higher than 1 +aren't interesting; lower values cause less motion. + +One interesting thing to try is +.EX +attraction -viscosity 0.8 -points 75 \\ + -mouse -geometry =500x500 +.EE +Give it a few seconds to settle down into a stable clump, and then move +the mouse through it to make "waves". +.TP 8 +.B \-mouse +This will cause the mouse to be considered a control point; it will not be +drawn, but it will influence the other points, so you can wave the mouse +and influence the images being created. +.TP 8 +.B \-no-mouse +Turns off \fB\-mouse\fP. +.TP 8 +.B \-mouse-size integer +In \fB\-mouse\fP mode, this sets the mass of the mouse (analagously to the +\fB\-size\fP parameter.) +.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. + +Viscosity and mouse support by Philip Edward Cutone, III. diff --git a/hacks/blitspin.c b/hacks/blitspin.c new file mode 100644 index 00000000..9a72b302 --- /dev/null +++ b/hacks/blitspin.c @@ -0,0 +1,279 @@ +/* xscreensaver, Copyright (c) 1992-1996 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 + (and preferably in parallel), 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 + +#ifdef HAVE_XPM +# include +# ifndef PIXEL_ALREADY_TYPEDEFED +# define PIXEL_ALREADY_TYPEDEFED /* Sigh, Xmu/Drawing.h needs this... */ +# endif +#endif + +#include + +#include "default.xbm" + +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 int depth; +static unsigned int fg, bg; + +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 +read_bitmap (bitmap_name, widthP, heightP) + char *bitmap_name; + int *widthP, *heightP; +{ +#ifdef HAVE_XPM + XpmAttributes xpmattrs; + int result; + xpmattrs.valuemask = 0; + bitmap = 0; + +#ifdef XpmCloseness + xpmattrs.valuemask |= XpmCloseness; + xpmattrs.closeness = 40000; +#endif + + result = XpmReadFileToPixmap (dpy, window, bitmap_name, &bitmap, 0, + &xpmattrs); + switch (result) + { + case XpmColorError: + fprintf (stderr, "%s: warning: xpm color substitution performed\n", + progname); + /* fall through */ + case XpmSuccess: + *widthP = xpmattrs.width; + *heightP = xpmattrs.height; + break; + case XpmFileInvalid: + case XpmOpenFailed: + bitmap = 0; + break; + case XpmColorFailed: + fprintf (stderr, "%s: xpm: color allocation failed\n", progname); + exit (-1); + case XpmNoMemory: + fprintf (stderr, "%s: xpm: out of memory\n", progname); + exit (-1); + default: + fprintf (stderr, "%s: xpm: unknown error code %d\n", progname, result); + exit (-1); + } + if (! bitmap) +#endif + { + int xh, yh; + Pixmap b2; + bitmap = XmuLocateBitmapFile (DefaultScreenOfDisplay (dpy), bitmap_name, + 0, 0, widthP, heightP, &xh, &yh); + if (! bitmap) + { + fprintf (stderr, "%s: couldn't find bitmap %s\n", progname, + bitmap_name); + exit (1); + } + b2 = XmuCreatePixmapFromBitmap (dpy, window, bitmap, *widthP, *heightP, + depth, fg, bg); + XFreePixmap (dpy, bitmap); + bitmap = b2; + } +} + +static void +init () +{ + XWindowAttributes xgwa; + Colormap cmap; + XGCValues gcv; + int width, height; + unsigned int real_size; + char *bitmap_name; + int i; + + XGetWindowAttributes (dpy, window, &xgwa); + cmap = xgwa.colormap; + depth = xgwa.depth; + + fg = get_pixel_resource ("foreground", "Foreground", dpy, cmap); + bg = get_pixel_resource ("background", "Background", dpy, cmap); + 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 || !*bitmap_name) + bitmap_name = "(default)"; + + if (!strcmp (bitmap_name, "(default)")) + { + width = logo_width; + height = logo_height; + bitmap = XCreatePixmapFromBitmapData (dpy, window, (char *) logo_bits, + width, height, fg, bg, depth); + } + else + { + read_bitmap (bitmap_name, &width, &height); + } + + 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, depth); + temp = XCreatePixmap (dpy, window, size, size, depth); + mask = XCreatePixmap (dpy, window, size, size, depth); + gcv.foreground = (depth == 1 ? 1 : (~0)); + 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); + + gcv.foreground = gcv.background = bg; + gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv); + /* Clear self to the background color (not to 0, which CLR does.) */ + XFillRectangle (dpy, self, gc, 0, 0, size, size); + XSetForeground (dpy, gc, fg); + + XCopyArea (dpy, bitmap, self, CPY, 0, 0, width, height, + (size - width)>>1, (size - height)>>1); +} + +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; + } +#ifdef HAVE_XPM + if (depth != 1) + XCopyArea (dpy, pixmap, window, gc, 0, 0, size, size, + (xgwa.width-size)>>1, (xgwa.height-size)>>1); + else +#endif + 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 [] = { + "BlitSpin.background: black", /* to placate SGI */ + "BlitSpin.foreground: white", + "*delay: 500000", + "*delay2: 500000", + "*bitmap: (default)", + 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..4198883d --- /dev/null +++ b/hacks/blitspin.man @@ -0,0 +1,77 @@ +.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] [\-install] [\-visual \fIvisual\fP] [\-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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +Specify which visual to use. Legal values are the name of a visual class, +or the id number (decimal or hex) of a specific visual. +.TP 8 +.B \-bitmap \fIfilename\fP +The file name of a bitmap to rotate. It need not be square: it +will be padded with the background color. If unspecified or the +string \fI(default)\fP, a builtin bitmap is used. + +If support for the \fIXPM\fP library was enabled at compile-time, +the specified file may be in \fIXPM\fP format as well as \fIXBM\fP, and +thus may be a color image. + +The \fB*bitmapFilePath\fP resource will be searched if the bitmap +name is not a fully-qualified pathname. +.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. +.SH ENVIRONMENT +.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 , 17-aug-92. + +Based on SmallTalk code which appeared in the August 1981 issue of Byte +magazine. diff --git a/hacks/bubbles-samples/blood.bub.gz b/hacks/bubbles-samples/blood.bub.gz new file mode 100644 index 00000000..b98e8558 Binary files /dev/null and b/hacks/bubbles-samples/blood.bub.gz differ diff --git a/hacks/bubbles-samples/blue.bub.gz b/hacks/bubbles-samples/blue.bub.gz new file mode 100644 index 00000000..f656079c Binary files /dev/null and b/hacks/bubbles-samples/blue.bub.gz differ diff --git a/hacks/bubbles-samples/jade.bub.gz b/hacks/bubbles-samples/jade.bub.gz new file mode 100644 index 00000000..48424f08 Binary files /dev/null and b/hacks/bubbles-samples/jade.bub.gz differ diff --git a/hacks/bubbles-sources/blood.pov b/hacks/bubbles-sources/blood.pov new file mode 100644 index 00000000..8166f4ea --- /dev/null +++ b/hacks/bubbles-sources/blood.pov @@ -0,0 +1,24 @@ +#include "colors.inc" +#include "shapes.inc" +#include "textures.inc" + +/* The following make the field of view as wide as it is high + * Thus, you should have the -W and -H command line options + * equal to each other. */ +camera { + location <5.8, 0, 0> + up <0, 1, 0> + right <1, 0, 0> + look_at <0, 0, 0> +} + +sphere { + <0,0,0>, 2.5 + texture { Blood_Marble + scale <2, 2, 2> + rotate <0, 20, 0> } + finish { Dull } +} + +light_source {<6, 1, 0> color White} +/* light_source {<6.1, 1, 0> color White} */ diff --git a/hacks/bubbles-sources/blue.pov b/hacks/bubbles-sources/blue.pov new file mode 100644 index 00000000..86d1ff8d --- /dev/null +++ b/hacks/bubbles-sources/blue.pov @@ -0,0 +1,22 @@ +#include "colors.inc" +#include "shapes.inc" +#include "textures.inc" + +/* The following make the field of view as wide as it is high + * Thus, you should have the -W and -H command line options + * equal to each other. */ +camera { + location <5.8, 0, 0> + up <0, 1, 0> + right <1, 0, 0> + look_at <0, 0, 0> +} + +sphere { + <0,0,0>, 2.5 + texture { Blue_Agate + scale <0.7, 0.7, 0.7> } + finish { phong 1 } +} + +light_source {<6, 1, 0> color White} diff --git a/hacks/bubbles-sources/glass.pov b/hacks/bubbles-sources/glass.pov new file mode 100644 index 00000000..c1897714 --- /dev/null +++ b/hacks/bubbles-sources/glass.pov @@ -0,0 +1,27 @@ +#include "colors.inc" +#include "shapes.inc" +#include "textures.inc" + +/* The following make the field of view as wide as it is high + * Thus, you should have the -W and -H command line options + * equal to each other. */ +camera { + location <5.8, 0, 0> + up <0, 1, 0> + right <1, 0, 0> + look_at <0, 0, 0> +} + +sphere { + <0,0,0>, 2.5 + texture { Glass + scale <0.7, 0.7, 0.7> + rotate y*clock + normal {bumps 0.4 scale 0.1} + finish { Shiny } +# finish { phong 0.4 } + } +} + +light_source {<6, 7, 0> color White} +light_source {<6.1, 1, 0> color Blue} diff --git a/hacks/bubbles-sources/jade.pov b/hacks/bubbles-sources/jade.pov new file mode 100644 index 00000000..7c1cb023 --- /dev/null +++ b/hacks/bubbles-sources/jade.pov @@ -0,0 +1,24 @@ +#include "colors.inc" +#include "shapes.inc" +#include "textures.inc" + +/* The following make the field of view as wide as it is high + * Thus, you should have the -W and -H command line options + * equal to each other. */ +camera { + location <5.8, 0, 0> + up <0, 1, 0> + right <1, 0, 0> + look_at <0, 0, 0> +} + +sphere { + <0,0,0>, 2.5 + texture { Jade + scale <0.7, 0.7, 0.7> + rotate y*clock } + finish { phong 0.4 } +} + +light_source {<6, 1, 0> color White} +light_source {<6.1, 1, 0> color White} diff --git a/hacks/bubbles-tools/bubblestodefault b/hacks/bubbles-tools/bubblestodefault new file mode 100755 index 00000000..3ad718b8 --- /dev/null +++ b/hacks/bubbles-tools/bubblestodefault @@ -0,0 +1,115 @@ +#!/usr/bin/perl +# +# $Id: bubblestodefault,v 1.1 1996/09/08 01:35:51 jwz Exp $ +# +#---------------------------------------------------------------------------- +# Copyright (C) 1995-1996 James Macnicol +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +#----------------------------------------------------------------------------- +# +# Contact me (J.Macnicol@student.anu.edu.au) if you have problems. +# +# [ The moral of this story is use a version of rm which safely backs up +# files when you delete them in case you do something stupid like +# "rm * xpm" which trashed all the scripts in this directory so I had +# to write them again. Grrrrrr..... ] +# +#----------------------------------------------------------------------------- +# +# This script takes a set of XPM files (from povbubbles, for example) +# whose names are listed in file with extension .names (of same format +# as output by povbubbles) and puts them together into a file which can +# be used in place of the source file bubbles_default.c which comes with +# bubbles/xscreensaver. +# +# To use it, provide as an argument the base-name of the .names file, +# i.e. if you ran povbubbles on the file foo.pov by typing "povbubbles foo" +# then this created a file "foo.names" so you can now make a new +# bubbles_default.c by typing "bubblestodefault foo". +# + +sub die_help { + print STDERR "Usage: $0 [-help] base-name\n"; + print STDERR " -help gives this message.\n"; + print STDERR " base-name is the name of the file used to generate\n"; + print STDERR " the XPM files, e.g. if you invoked povbubbles with\n"; + print STDERR " \"povbubbles foo\"\n"; + print STDERR " then you should invoke $0 with\n"; + die(" \"$0 foo\"\n"); +} + +sub die_usage { + die "Usage: $0 [-help] base-name\n"; +} + +$infile = undef; + +# Process command line arguments +while ($op = shift) { + if ($op eq "-help") { + &die_help; + } else { + $infile = $op; + # Ignore further arguments + break; + } +} +if ($infile eq undef) { + &die_usage; +} + +$namesfile = $infile . ".names"; + +if (! -f $namesfile) { + die("File list $namesfile doesn't exist\n"); +} + +if (-f "bubbles_default.c") { + print "Backing up bubbles_default.c...\n"; + system("mv -f bubbles_default.c bubbles_default.c.bak"); +} + +open(OUT, ">bubbles_default.c") || die("Couldn't open bubbles_default.c\n"); +print OUT "#include \n"; +print OUT "#include \"bubbles.h\"\n"; +print OUT "\n"; +print OUT "#ifndef NO_DEFAULT_BUBBLE\n"; +print OUT "\n"; + +open(NAMES, $namesfile) || die ("Couldn't open $namesfile\n"); +$numbubbles = 0; +while () { + if (/\s*(\S+)\:(\S+)\s*/) { + $filename = $1; + $xpmname = $2; + $xpmlist = $xpmlist . $xpmname . ", "; + open(CAT, $filename) || die("Couldn't open file $filename listed in\ +$namesfile\n"); + while () { + print OUT; + } + close(CAT); + $numbubbles++; + } else { + print STDERR "Can't understand the line \"$_\"\n"; + print STDERR " in $namesfile. Ignoring...\n"; + } +} +print OUT "char **default_bubbles[] = {$xpmlist"; +print OUT "(char **)0};\n"; +print OUT "\n"; +print OUT "int num_default_bubbles = $numbubbles;\n"; +print OUT "\n"; +print OUT "#endif /* NO_DEFAULT_BUBBLE */\n"; + +close(NAMES); +close(OUT); diff --git a/hacks/bubbles-tools/bubblestofile b/hacks/bubbles-tools/bubblestofile new file mode 100755 index 00000000..4eaf5c9b --- /dev/null +++ b/hacks/bubbles-tools/bubblestofile @@ -0,0 +1,107 @@ +#!/usr/bin/perl +# +# $Id: bubblestofile,v 1.1 1996/09/08 01:35:52 jwz Exp $ +# +#---------------------------------------------------------------------------- +# Copyright (C) 1995-1996 James Macnicol +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +#----------------------------------------------------------------------------- +# +# Contact me (J.Macnicol@student.anu.edu.au) if you have problems. +# +# [ The moral of this story is use a version of rm which safely backs up +# files when you delete them in case you do something stupid like +# "rm * xpm" which trashed all the scripts in this directory so I had +# to write them again. Grrrrrr..... ] +# +#----------------------------------------------------------------------------- +# +# This script takes a set of XPM files (from povbubbles, for example) +# whose names are listed in file with extension .names (of same format +# as output by povbubbles) and puts them together into a file which can +# loaded with the -file option or place in a directory suitable for +# use with the -directory option to bubbles. Note that neither of these +# options are available if you have just compiled bubbles as provided. +# You must edit bubbles.h to enable these. Files generated by this script +# have by default the extension ".bub". +# +# To use it, provide as an argument the base-name of the .names file, +# i.e. if you ran povbubbles on the file foo.pov by typing "povbubbles foo" +# then this created a file "foo.names" so you can now make the loadable file +# "foo.bub" by typing "bubblestofile foo". +# + +sub die_help { + print STDERR "Usage: $0 [-help] base-name\n"; + print STDERR " -help\n"; + print STDERR " gives this message.\n"; + print STDERR " base-name is the name of the file used to generate\n"; + print STDERR " the XPM files, e.g. if you invoked povbubbles with\n"; + print STDERR " \"povbubbles foo\"\n"; + print STDERR " then you should invoke $0 with\n"; + die(" \"$0 foo\"\n"); +} + +sub die_usage { + die "Usage: $0 [-help] base-name\n"; +} + +$infile = undef; + +# Process command line arguments +while ($op = shift) { + if ($op eq "-help") { + &die_help; + } else { + $infile = $op; + # Ignore further arguments + break; + } +} +if ($infile eq undef) { + &die_usage; +} + +$namesfile = $infile . ".names"; +$outfile = $infile . ".bub"; + +if (! -f $namesfile) { + die("File list $namesfile doesn't exist\n"); +} + +if (-f $outfile) { + print "Backing up $outfile\n"; + system("mv -f $outfile $outfile.bak"); +} + +open(OUT, ">$outfile") || die("Couldn't open $outfile\n"); +open(NAMES, $namesfile) || die ("Couldn't open $namesfile\n"); +$numbubbles = 0; +while () { + if (/\s*(\S+)\:(\S+)\s*/) { + $filename = $1; + $xpmname = $2; + open(CAT, $filename) || die("Couldn't open file $filename listed in\ +$namesfile\n"); + while () { + print OUT; + } + close(CAT); + } else { + print STDERR "Can't understand the line \"$_\"\n"; + print STDERR " in $namesfile. Ignoring...\n"; + } +} +close(NAMES); +close(OUT); + + diff --git a/hacks/bubbles-tools/xpm2default b/hacks/bubbles-tools/xpm2default new file mode 100755 index 00000000..b4236089 --- /dev/null +++ b/hacks/bubbles-tools/xpm2default @@ -0,0 +1,51 @@ +#!/usr/bin/perl +#---------------------------------------------------------------------------- +# Copyright (C) 1995-1996 James Macnicol +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 1, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +#----------------------------------------------------------------------------- +# +# Prints to the stdout a file suitable for use as bubbles_default.c for the +# bubbles screensaver (i.e. the default bubble which is compiled into the +# executable). A list of XPMs is expected as input, e.g. output from the +# pov2xpm script in this directory. +# +# Remember to change the path to your perl executable at the top of the +# script if it is wrong. +# +# Examples of usage: +# +# pov2xpm sample.pov | xpm2default > bubbles_default.c +# +# A new set of bubbles is first created with pov2xpm then passed to this +# script which places the C wrapper around the data and finally dumps the +# output into bubbles_default.c. +# +# xpm2default < sample.xpm > bubbles_default.c +# +# Same as the previous example except the XPM data came from a file rather +# than a pipe. +# +$numargs = @ARGV; +print "#include \"bubbles.h\"\n"; +print "\n"; +print "#ifndef NO_DEFAULT_BUBBLE\n"; +print "\n"; +print "char *default_ball_data[] = {\n"; +while () { + chop; + s/"/\\"/g; + print "\"$_\",\n"; +} +print "(char *)0\n"; +print "};\n"; +print "\n"; +print "#endif\n"; diff --git a/hacks/bubbles.README b/hacks/bubbles.README new file mode 100644 index 00000000..b82d8080 --- /dev/null +++ b/hacks/bubbles.README @@ -0,0 +1,86 @@ +First of all, you should read and possibly change the options in +bubbles.h. Things should work without you having to change anything. + +Most of the stuff below is of no use to you if you do not have the +XPM library and thus cannot use rendered bubbles. The same goes for +monochrome displays, whether you have XPM or not. + +The most interesting #define here is BUBBLES_IO. If this is set then +the -file and -directory options become available to you, which means +that you can use bubbles with the program other than just the one that +is used by default (see below). The problem is that there is code in +the routines that implement this which arenot portable across the +various flavours of UNIX. Therefore, this #define is not set out of +the box. Chances are that it will work for you fine, however. I have +personally seen it work under Linux 1.3.x and Solaris 2.x. IRIX has +problems, from what I hear. If you do need to hack the code in order +to get these features to work, please send e-mail to the address at +the bottom of this file and detail your changes. They will be +incorporated in a future release. + +If you are compiling with the XPM library you have the option of +putting in or leaving out a "default" bubble in your binary, i.e. if +no -file or -directory options are specified on the command line then +this bubble will be used. Things are setup to include this by +default, so that people can happily run the program without there +being any compulsory options. If you use very large bubbles or are +low on memory you might like to take the option of not compiling in +the default bubble and thus saving some space should you wish to use +more than one bubble (to make life more interesting, or whatever). +This can be done by removing the comments around #define +NO_DEFAULT_BUBBLE in bubbles.h. + +If you are hacking the bubbles code then you might like to switch on +extra checks and messages with the DEBUG flag in bubbles.h, but +otherwise you can leave it commented out. The sanity checks enables +there will slow things down. + +There are also some configuration options to help you compile and run +bubbles properly. These are explained in bubbles.h. All changes +affecting portability will end up in here. If you need to change +anything to get bubbles to compile on your system, please tell me what +they are. + +Apart from the source files, there are also some other directories +here which contain things you might use if loading bubbles at runtime +or developing new ones : + + +bubbles-tools/ + Contains several perl scripts to help you make new +sets of bubbles easily. povbubbles runs povray on a scene description +file and outputs a series of XPM files which you can then postprocess +if need be. To turn these files into a new instance of the default +bubble source file bubbles_default.c, use the script bubblestodefault. +To put all the files together into a single file which can be loaded +with the -file or -directory options (if available), use the script +bubblestofile. + + Read the comments at the top of each script to find out more. + +bubbles-samples/ + This directory contains some compressed bubbles +files which can be used with the -directory option (or the -file +option on individual files there). The files will be automatically +uncompressed before use. + +bubbles-sources/ + The povray sources used to make some of the bubbles +in the bubbles-samples directory. You can use these as templates for +making new bubbles. + + +I'm not much good with povray so the examples are probably pretty +boring. If you make some nice bubbles yourself, I'd like to see them. +Send your _sources_ to J.Macnicol@student.anu.edu.au (please don't +fill my inbox with XPM files, there is a limit on the amount of +waiting e-mail I can have). + + +Enjoy. + + +-- +James Macnicol +e-mail: J.Macnicol@student.anu.edu.au +http://goblet.anu.edu.au/~m9305357/home.html diff --git a/hacks/bubbles.c b/hacks/bubbles.c new file mode 100644 index 00000000..2033130c --- /dev/null +++ b/hacks/bubbles.c @@ -0,0 +1,1902 @@ +/* bubbles.c - frying pan / soft drink in a glass simulation */ + +/*$Id: bubbles.c,v 1.1 1996/09/08 01:35:40 jwz Exp $*/ + +/* + * Copyright (C) 1995-1996 James Macnicol + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/* + * I got my original inspiration for this by looking at the bottom of a + * frying pan while something was cooking and watching the little bubbles + * coming off the bottom of the pan as the oil was boiling joining together + * to form bigger bubbles and finally to *pop* and disappear. I had some + * time on my hands so I wrote this little xscreensaver module to imitate + * it. Now that it's done it reminds me more of the bubbles you get in + * a glass of fizzy soft drink..... + * + * The problem seemed to be that the position/size etc. of all the bubbles + * on the screen had to be remembered and searched through to find when + * bubbles hit each other and combined. To do this more efficiently, the + * window/screen is divided up into a square mesh of side length mesh_length + * and separate lists of bubbles contained in each cell of the mesh are + * kept. Only the cells in the immediate vicinity of the bubble in question + * are searched. This should make things more efficient although the whole + * thing seems to use up too much CPU, but then I'm using an ancient PC so + * perhaps it's not surprising . + * (Six months after I wrote the above I now have a Pentium with PCI graphics + * and things are _much_ nicer.) + * + * Author: James Macnicol + * Internet E-mail : J.Macnicol@student.anu.edu.au + */ + +#include "bubbles.h" + +#ifdef BUBBLES_IO +#include +#include +#include +#endif /* BUBBLES_IO */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "screenhack.h" +#include "../utils/yarandom.h" + +#ifdef HAVE_XPM +#include +#endif + +/* + * Public variables + */ + +#ifndef NO_DEFAULT_BUBBLE +extern int num_default_bubbles; +extern char **default_bubbles[]; +#endif /* NO_DEFAULT_BUBBLE */ + +char *progclass = "Bubbles"; + +char *defaults [] = { + "*background: black", + "*foreground: white", + "*simple: false", + "*broken: false", + "*delay: 2000", +#ifdef BUBBLES_IO + "*file: (default)", + "*directory: (default)", +#endif /* BUBBLES_IO */ + "*quiet: false", + "*nodelay: false", + "*3D: false", + "*geometry: 400x300", + 0 +}; + +XrmOptionDescRec options [] = { + { "-simple", ".simple", XrmoptionNoArg, "true" }, +#ifdef HAVE_XPM + { "-broken", ".broken", XrmoptionNoArg, "true" }, +#endif /* HAVE_XPM */ + { "-quiet", ".quiet", XrmoptionNoArg, "true" }, + { "-nodelay", ".nodelay", XrmoptionNoArg, "true" }, + { "-3D", ".3D", XrmoptionNoArg, "true" }, +#ifdef BUBBLES_IO + { "-file", ".file", XrmoptionSepArg, 0 }, + { "-directory", ".directory", XrmoptionSepArg, 0 }, +#endif /* BUBBLES_IO */ + { "-delay", ".delay", XrmoptionSepArg, 0 } +}; +int options_size = (sizeof (options) / sizeof (options[0])); + +/* + * Private variables + */ + +static Bubble **mesh; +static int mesh_length; +static int mesh_width; +static int mesh_height; +static int mesh_cells; + +static int **adjacent_list; + +static int screen_width; +static int screen_height; +static int screen_depth; +static unsigned int default_fg_pixel, default_bg_pixel; +/* + * I know it's not elegant to save this stuff in global variables + * but we need it for the signal handler. + */ +static Display *defdsp; +static Window defwin; +static Colormap defcmap; + +/* For simple mode only */ +static int bubble_min_radius; +static int bubble_max_radius; +static long *bubble_areas; +static GC draw_gc, erase_gc; + +#ifdef HAVE_XPM +static int num_bubble_pixmaps; +static Bubble_Step **step_pixmaps; +#ifdef BUBBLES_IO +static char *pixmap_file; +#endif /* BUBBLES_IO */ +static int use_default_bubble; +#endif /* HAVE_XPM */ + +/* Options stuff */ +#ifdef HAVE_XPM +static Bool simple = False; +#else +static Bool simple = True; +#endif +static Bool broken = False; +static Bool quiet = False; +static Bool threed = False; +static int delay; + +/* + * To prevent forward references, some stuff is up here + */ + +static long +calc_bubble_area(r) + int r; +/* Calculate the area of a bubble of radius r */ +{ +#ifdef DEBUG + printf("%d %g\n", r, + 10.0 * PI * (double)r * (double)r * (double)r); +#endif /* DEBUG */ + if (threed) + return (long)(10.0 * PI * (double)r * (double)r * (double)r); + else + return (long)(10.0 * PI * (double)r * (double)r); +} + +static void * +xmalloc(size) + size_t size; +/* Safe malloc */ +{ + void *ret; + + if ((ret = malloc(size)) == NULL) { + fprintf(stderr, "%s: out of memory\n", progname); + exit(1); + } + return ret; +} + +#ifdef DEBUG +static void +die_bad_bubble(bb) + Bubble *bb; +/* This is for use with GDB */ +{ + fprintf(stderr, "Bad bubble detected at 0x%x!\n", (int)bb); + exit(1); +} +#endif + +static int +null_bubble(bb) + Bubble *bb; +/* Returns true if the pointer passed is NULL. If not then this checks to +see if the bubble is valid (i.e. the (x,y) position is valid and the magic +number is set correctly. This only a sanity check for debugging and is +turned off if DEBUG isn't set. */ +{ + if (bb == (Bubble *)NULL) + return 1; +#ifdef DEBUG + if ((bb->cell_index < 0) || (bb->cell_index > mesh_cells)) { + fprintf(stderr, "cell_index = %d\n", bb->cell_index); + die_bad_bubble(bb); + } + if (bb->magic != BUBBLE_MAGIC) { + fprintf(stderr, "Magic = %d\n", bb->magic); + die_bad_bubble(bb); + } + if (simple) { + if ((bb->x < 0) || (bb->x > screen_width) || + (bb->y < 0) || (bb->y > screen_height) || + (bb->radius < bubble_min_radius) || (bb->radius > + bubble_max_radius)) { + fprintf(stderr, + "radius = %d, x = %d, y = %d, magic = %d, \ +cell index = %d\n", bb->radius, bb->x, bb->y, bb->magic, bb->cell_index); + die_bad_bubble(bb); + } +#ifdef HAVE_XPM + } else { + if ((bb->x < 0) || (bb->x > screen_width) || + (bb->y < 0) || (bb->y > screen_height) || + (bb->radius < step_pixmaps[0]->radius) || + (bb->radius > step_pixmaps[num_bubble_pixmaps-1]->radius)) { + fprintf(stderr, + "radius = %d, x = %d, y = %d, magic = %d, \ +cell index = %d\n", bb->radius, bb->x, bb->y, bb->magic, bb->cell_index); + die_bad_bubble(bb); + } +#endif /* HAVE_XPM */ + } +#endif /* DEBUG */ + return 0; +} + +#ifdef DEBUG +static void +print_bubble_list(bb) + Bubble *bb; +/* Print list of where all the bubbles are. For debugging purposes only. */ +{ + if (! null_bubble(bb)) { + printf(" (%d, %d) %d\n", bb->x, bb->y, bb->radius); + print_bubble_list(bb->next); + } +} +#endif /* DEBUG */ + +static void +add_bubble_to_list(list, bb) + Bubble **list; + Bubble *bb; +/* Take a pointer to a list of bubbles and stick bb at the head of the + list. */ +{ + Bubble *head = *list; + + if (null_bubble(head)) { + bb->prev = (Bubble *)NULL; + bb->next = (Bubble *)NULL; + } else { + bb->next = head; + bb->prev = (Bubble *)NULL; + head->prev = bb; + } + *list = bb; +} + + +/* + * Mesh stuff + */ + + +static void +init_mesh() +/* Setup the mesh of bubbles */ +{ + int i; + + mesh = (Bubble **)xmalloc(mesh_cells * sizeof(Bubble *)); + for (i = 0; i < mesh_cells; i++) + mesh[i] = (Bubble *)NULL; +} + +static int +cell_to_mesh(x, y) + int x; + int y; +/* convert cell coordinates to mesh index */ +{ +#ifdef DEBUG + if ((x < 0) || (y < 0)) { + fprintf(stderr, "cell_to_mesh: x = %d, y = %d\n", x, y); + exit(1); + } +#endif + return ((mesh_width * y) + x); +} + +static void +mesh_to_cell(mi, cx, cy) + int mi; + int *cx; + int *cy; +/* convert mesh index into cell coordinates */ +{ + *cx = mi % mesh_width; + *cy = mi / mesh_width; +} + +static int +pixel_to_mesh(x, y) + int x; + int y; +/* convert screen coordinates into mesh index */ +{ + return cell_to_mesh((x / mesh_length), (y / mesh_length)); +} + +static int +verify_mesh_index(x, y) + int x; + int y; +/* check to see if (x,y) is in the mesh */ +{ + if ((x < 0) || (y < 0) || (x >= mesh_width) || (y >= mesh_height)) + return (-1); + return (cell_to_mesh(x, y)); +} + +#ifdef DEBUG +static void +print_adjacents(adj) + int *adj; +/* Print a list of the cells calculated above. For debugging only. */ +{ + int i; + + printf("("); + for (i = 0; i < 8; i++) + printf("%d ", adj[i]); + printf(")\n"); +} +#endif /* DEBUG */ + +static void +add_to_mesh(bb) + Bubble *bb; +/* Add the given bubble to the mesh by sticking it on the front of the +list. bb is already allocated so no need to malloc() anything, just +adjust pointers. */ +{ +#ifdef DEBUG + if (null_bubble(bb)) { + fprintf(stderr, "Bad bubble passed to add_to_mesh()!\n"); + exit(1); + } +#endif /* DEBUG */ + + add_bubble_to_list(&mesh[bb->cell_index], bb); +} + +#ifdef DEBUG +static void +print_mesh() +/* Print the contents of the mesh */ +{ + int i; + + for (i = 0; i < mesh_cells; i++) { + if (! null_bubble(mesh[i])) { + printf("Mesh cell %d\n", i); + print_bubble_list(mesh[i]); + } + } +} + +static void +valid_mesh() +/* Check to see if the mesh is Okay. For debugging only. */ +{ + int i; + Bubble *b; + + for (i = 0; i < mesh_cells; i++) { + b = mesh[i]; + while (! null_bubble(b)) + b = b->next; + } +} + +static int +total_bubbles() +/* Count how many bubbles there are in total. For debugging only. */ +{ + int rv = 0; + int i; + Bubble *b; + + for (i = 0; i < mesh_cells; i++) { + b = mesh[i]; + while (! null_bubble(b)) { + rv++; + b = b->next; + } + } + + return rv; +} +#endif /* DEBUG */ + +static void +calculate_adjacent_list() +/* Calculate the list of cells adjacent to a particular cell for use + later. */ +{ + int i; + int ix, iy; + + adjacent_list = (int **)xmalloc(mesh_cells * sizeof(int *)); + for (i = 0; i < mesh_cells; i++) { + adjacent_list[i] = (int *)xmalloc(9 * sizeof(int)); + mesh_to_cell(i, &ix, &iy); + adjacent_list[i][0] = verify_mesh_index(--ix, --iy); + adjacent_list[i][1] = verify_mesh_index(++ix, iy); + adjacent_list[i][2] = verify_mesh_index(++ix, iy); + adjacent_list[i][3] = verify_mesh_index(ix, ++iy); + adjacent_list[i][4] = verify_mesh_index(ix, ++iy); + adjacent_list[i][5] = verify_mesh_index(--ix, iy); + adjacent_list[i][6] = verify_mesh_index(--ix, iy); + adjacent_list[i][7] = verify_mesh_index(ix, --iy); + adjacent_list[i][8] = i; + } +} + +static void +adjust_areas() +/* Adjust areas of bubbles so we don't get overflow in weighted_mean() */ +{ + double maxvalue; + long maxarea; + long factor; + int i; + +#ifdef HAVE_XPM + if (simple) + maxarea = bubble_areas[bubble_max_radius+1]; + else + maxarea = step_pixmaps[num_bubble_pixmaps]->area; +#else + maxarea = bubble_areas[bubble_max_radius+1]; +#endif /* HAVE_XPM */ + maxvalue = (double)screen_width * 2.0 * (double)maxarea; + factor = (long)ceil(maxvalue / (double)LONG_MAX); + if (factor > 1) { + /* Overflow will occur in weighted_mean(). We must divide areas + each by factor so it will never do so. */ +#ifdef HAVE_XPM + if (simple) { + for (i = bubble_min_radius; i <= bubble_max_radius+1; i++) { + bubble_areas[i] /= factor; + if (bubble_areas[i] == 0) + bubble_areas[i] = 1; + } + } else { + for (i = 0; i <= num_bubble_pixmaps; i++) { +#ifdef DEBUG + printf("area = %ld", step_pixmaps[i]->area); +#endif /* DEBUG */ + step_pixmaps[i]->area /= factor; + if (step_pixmaps[i]->area == 0) + step_pixmaps[i]->area = 1; +#ifdef DEBUG + printf("-> %ld\n", step_pixmaps[i]->area); +#endif /* DEBUG */ + } + } +#else + for (i = bubble_min_radius; i <= bubble_max_radius+1; i++) { + bubble_areas[i] /= factor; + if (bubble_areas[i] == 0) + bubble_areas[i] = 1; + } +#endif /* HAVE_XPM */ + } +#ifdef DEBUG + printf("maxarea = %ld\n", maxarea); + printf("maxvalue = %g\n", maxvalue); + printf("LONG_MAX = %ld\n", LONG_MAX); + printf("factor = %ld\n", factor); +#endif /* DEBUG */ +} + +/* + * Bubbles stuff + */ + +static Bubble * +new_bubble() +/* Add a new bubble at some random position on the screen of the smallest +size. */ +{ + Bubble *rv = (Bubble *)xmalloc(sizeof(Bubble)); + + /* Can't use null_bubble() here since magic number hasn't been set */ + if (rv == (Bubble *)NULL) { + fprintf(stderr, "Ran out of memory!\n"); + exit(1); + } + + if (simple) { + rv->radius = bubble_min_radius; + rv->area = bubble_areas[bubble_min_radius]; +#ifdef HAVE_XPM + } else { + rv->step = 0; + rv->radius = step_pixmaps[0]->radius; + rv->area = step_pixmaps[0]->area; +#endif /* HAVE_XPM */ + } + rv->visible = 0; + rv->magic = BUBBLE_MAGIC; + rv->x = ya_random() % screen_width; + rv->y = ya_random() % screen_height; + rv->cell_index = pixel_to_mesh(rv->x, rv->y); + + return rv; +} + +static void +show_bubble(bb) + Bubble *bb; +/* paint the bubble on the screen */ +{ + if (null_bubble(bb)) { + fprintf(stderr, "NULL bubble passed to show_bubble\n"); + exit(1); + } + + if (! bb->visible) { + bb->visible = 1; + + if (simple) { + XDrawArc(defdsp, defwin, draw_gc, (bb->x - bb->radius), + (bb->y - bb->radius), bb->radius*2, bb->radius*2, 0, + 360*64); + } else { +#ifdef HAVE_XPM + XSetClipOrigin(defdsp, step_pixmaps[bb->step]->draw_gc, + (bb->x - bb->radius), + (bb->y - bb->radius)); + + XCopyArea(defdsp, step_pixmaps[bb->step]->ball, defwin, + step_pixmaps[bb->step]->draw_gc, + 0, 0, (bb->radius * 2), + (bb->radius * 2), + (bb->x - bb->radius), + (bb->y - bb->radius)); +#endif /* HAVE_XPM */ + } + } +} + +static void +hide_bubble(bb) + Bubble *bb; +/* erase the bubble */ +{ + if (null_bubble(bb)) { + fprintf(stderr, "NULL bubble passed to hide_bubble\n"); + exit(1); + } + + if (bb->visible) { + bb->visible = 0; + + if (simple) { + XDrawArc(defdsp, defwin, erase_gc, (bb->x - bb->radius), + (bb->y - bb->radius), bb->radius*2, bb->radius*2, 0, + 360*64); + } else { +#ifdef HAVE_XPM + if (! broken) { + XSetClipOrigin(defdsp, step_pixmaps[bb->step]->erase_gc, + (bb->x - bb->radius), (bb->y - bb->radius)); + + XFillRectangle(defdsp, defwin, step_pixmaps[bb->step]->erase_gc, + (bb->x - bb->radius), + (bb->y - bb->radius), + (bb->radius * 2), + (bb->radius * 2)); + } +#endif /* HAVE_XPM */ + } + } +} + +static void +delete_bubble_in_mesh(bb, keep_bubble) + Bubble *bb; + int keep_bubble; +/* Delete an individual bubble, adjusting list of bubbles around it. + If keep_bubble is true then the bubble isn't actually deleted. We + use this to allow bubbles to change mesh cells without reallocating, + (it needs this when two bubbles collide and the centre position is + recalculated, and this may stray over a mesh boundary). */ +{ + if ((!null_bubble(bb->prev)) && (!null_bubble(bb->next))) { + bb->prev->next = bb->next; + bb->next->prev = bb->prev; + } else if ((!null_bubble(bb->prev)) && + (null_bubble(bb->next))) { + bb->prev->next = (Bubble *)NULL; + bb->next = mesh[bb->cell_index]; + } else if ((null_bubble(bb->prev)) && + (!null_bubble(bb->next))) { + bb->next->prev = (Bubble *)NULL; + mesh[bb->cell_index] = bb->next; + bb->next = mesh[bb->cell_index]; + } else { + /* Only item on list */ + mesh[bb->cell_index] = (Bubble *)NULL; + } + if (! keep_bubble) + free(bb); +} + +static unsigned long +ulongsqrint(x) + int x; +/* Saves ugly inline code */ +{ + return ((unsigned long)x * (unsigned long)x); +} + +static Bubble * +get_closest_bubble(bb) + Bubble *bb; +/* Find the closest bubble touching the this bubble, NULL if none are + touching. */ +{ + Bubble *rv = (Bubble *)NULL; + Bubble *tmp; + unsigned long separation2, touchdist2; + int dx, dy; + unsigned long closest2 = ULONG_MAX; + int i; + +#ifdef DEBUG + if (null_bubble(bb)) { + fprintf(stderr, "NULL pointer 0x%x passed to get_closest_bubble()!", + (int)bb); + exit(1); + } +#endif /* DEBUG */ + + for (i = 0; i < 9; i++) { + /* There is a bug here where bb->cell_index is negaitve.. */ +#ifdef DEBUG + if ((bb->cell_index < 0) || (bb->cell_index >= mesh_cells)) { + fprintf(stderr, "bb->cell_index = %d\n", bb->cell_index); + exit(1); + } +#endif /* DEBUG */ +/* printf("%d,", bb->cell_index); */ + if (adjacent_list[bb->cell_index][i] != -1) { + tmp = mesh[adjacent_list[bb->cell_index][i]]; + while (! null_bubble(tmp)) { + if (tmp != bb) { + dx = tmp->x - bb->x; + dy = tmp->y - bb->y; + separation2 = ulongsqrint(dx) + ulongsqrint(dy); + /* Add extra leeway so circles _never_ overlap */ + touchdist2 = ulongsqrint(tmp->radius + bb->radius + 2); + if ((separation2 <= touchdist2) && (separation2 < + closest2)) { + rv = tmp; + closest2 = separation2; + } + } + tmp = tmp->next; + } + } + } + + return rv; +} + +#ifdef DEBUG +static void +ldr_barf() +{ +} +#endif /* DEBUG */ + +static long +long_div_round(num, dem) + long num; + long dem; +{ + long divvie, moddo; + +#ifdef DEBUG + if ((num < 0) || (dem < 0)) { + fprintf(stderr, "long_div_round: %ld, %ld\n", num, dem); + ldr_barf(); + exit(1); + } +#endif /* DEBUG */ + + divvie = num / dem; + moddo = num % dem; + if (moddo > (dem / 2)) + ++divvie; + +#ifdef DEBUG + if ((divvie < 0) || (moddo < 0)) { + fprintf(stderr, "long_div_round: %ld, %ld\n", divvie, moddo); + ldr_barf(); + exit(1); + } +#endif /* DEBUG */ + + return divvie; +} + +static int +weighted_mean(n1, n2, w1, w2) + int n1; + int n2; + long w1; + long w2; +/* Mean of n1 and n2 respectively weighted by weights w1 and w2. */ +{ +#ifdef DEBUG + if ((w1 <= 0) || (w2 <= 0)) { + fprintf(stderr, "Bad weights passed to weighted_mean() - \ +(%d, %d, %ld, %ld)!\n", n1, n2, w1, w2); + exit(1); + } +#endif /* DEBUG */ + return ((int)long_div_round((long)n1 * w1 + (long)n2 * w2, + w1 + w2)); +} + +static int +bubble_eat(diner, food) + Bubble *diner; + Bubble *food; +/* The diner eats the food. Returns true (1) if the diner still exists */ +{ + int i; + int newmi; + +#ifdef DEBUG + if ((null_bubble(diner)) || (null_bubble(food))) { + fprintf(stderr, "Bad bubbles passed to bubble_eat()!\n"); + exit(1); + } +#endif /* DEBUG */ + + /* We hide the diner even in the case that it doesn't grow so that + if the food overlaps its boundary it is replaced. This could + probably be solved by letting bubbles eat others which are close + but not quite touching. It's probably worth it, too, since we + would then not have to redraw bubbles which don't change in + size. */ + + hide_bubble(diner); + hide_bubble(food); + diner->x = weighted_mean(diner->x, food->x, diner->area, food->area); + diner->y = weighted_mean(diner->y, food->y, diner->area, food->area); + newmi = pixel_to_mesh(diner->x, diner->y); + diner->area += food->area; + delete_bubble_in_mesh(food, DELETE_BUBBLE); + + if ((simple) && (diner->area > bubble_areas[bubble_max_radius])) { + delete_bubble_in_mesh(diner, DELETE_BUBBLE); + return 0; + } +#ifdef HAVE_XPM + if ((! simple) && (diner->area > + step_pixmaps[num_bubble_pixmaps]->area)) { + delete_bubble_in_mesh(diner, DELETE_BUBBLE); + return 0; + } +#endif /* HAVE_XPM */ + + if (simple) { + if (diner->area > bubble_areas[diner->radius + 1]) { + /* Move the bubble to a new radius */ + i = diner->radius; + while (diner->area > bubble_areas[i+1]) + ++i; + diner->radius = i; + } + show_bubble(diner); +#ifdef HAVE_XPM + } else { + if (diner->area > step_pixmaps[diner->step+1]->area) { + i = diner->step; + while (diner->area > step_pixmaps[i+1]->area) + ++i; + diner->step = i; + diner->radius = step_pixmaps[diner->step]->radius; + } + show_bubble(diner); +#endif /* HAVE_XPM */ + } + + /* Now adjust locations and cells if need be */ + if (newmi != diner->cell_index) { + delete_bubble_in_mesh(diner, KEEP_BUBBLE); + diner->cell_index = newmi; + add_to_mesh(diner); + } + + return 1; +} + +static int +merge_bubbles(b1, b2) + Bubble *b1; + Bubble *b2; +/* These two bubbles merge into one. If the first one wins out return +1 else return 2. If there is no winner (it explodes) then return 0 */ +{ + int b1size, b2size; + + b1size = b1->area; + b2size = b2->area; + +#ifdef DEBUG + if ((null_bubble(b1) || null_bubble(b2))) { + fprintf(stderr, "NULL bubble passed to merge_bubbles()!\n"); + exit(1); + } +#endif /* DEBUG */ + + if (b1 == b2) { + hide_bubble(b1); + delete_bubble_in_mesh(b1, DELETE_BUBBLE); + return 0; + } + + if (b1size > b2size) { + switch (bubble_eat(b1, b2)) { + case 0: + return 0; + break; + case 1: + return 1; + break; + default: + break; + } + } else if (b1size < b2size) { + switch (bubble_eat(b2, b1)) { + case 0: + return 0; + break; + case 1: + return 2; + break; + default: + break; + } + } else { + if ((ya_random() % 2) == 0) { + switch (bubble_eat(b1, b2)) { + case 0: + return 0; + break; + case 1: + return 1; + break; + default: + break; + } + } else { + switch (bubble_eat(b2, b1)) { + case 0: + return 0; + break; + case 1: + return 2; + break; + default: + break; + } + } + } + fprintf(stderr, "An error occurred in merge_bubbles()\n"); + exit(1); +} + +static void +insert_new_bubble(tmp) + Bubble *tmp; +/* Calculates which bubbles are eaten when a new bubble tmp is + inserted. This is called recursively in case when a bubble grows + it eats others. Careful to pick out disappearing bubbles. */ +{ + Bubble *nextbub; + Bubble *touch; + +#ifdef DEBUG + if (null_bubble(tmp)) { + fprintf(stderr, "Bad bubble passed to insert_new_bubble()!\n"); + exit(1); + } +#endif /* DEBUG */ + + nextbub = tmp; + touch = get_closest_bubble(nextbub); + while (! null_bubble(touch)) { + switch (merge_bubbles(nextbub, touch)) { + case 2: + /* touch ate nextbub and survived */ + nextbub = touch; + break; + case 1: + /* nextbub ate touch and survived */ + break; + case 0: + /* somebody ate someone else but they exploded */ + nextbub = (Bubble *)NULL; + break; + default: + /* something went wrong */ + fprintf(stderr, "Error occurred in insert_new_bubble()\n"); + exit(1); + } + /* Check to see if there are any other bubbles still in the area + and if we need to do this all over again for them. */ + if (! null_bubble(nextbub)) + touch = get_closest_bubble(nextbub); + else + touch = (Bubble *)NULL; + } +} + +#ifdef DEBUG +static int +get_length_of_bubble_list(bb) + Bubble *bb; +{ + Bubble *tmp = bb; + int rv = 0; + + while (! null_bubble(tmp)) { + rv++; + tmp = tmp->next; + } + + return rv; +} +#endif /* DEBUG */ + +/* + * Pixmap stuff used regardless of whether file I/O is available. Must + * still check for XPM, though! + */ + +#ifdef HAVE_XPM + +static void +free_pixmaps() +/* Free resources associated with XPM */ +{ + int i; + +#ifdef DEBUG + if (simple) { + fprintf(stderr, "free_pixmaps() called in simple mode\n"); + exit(1); + } + printf("free_pixmaps()\n"); +#endif /* DEBUG */ + + for(i = 0; i < (num_bubble_pixmaps - 1); i++) { + XFreePixmap(defdsp, step_pixmaps[i]->ball); + XFreePixmap(defdsp, step_pixmaps[i]->shape_mask); + XFreeGC(defdsp, step_pixmaps[i]->draw_gc); + XFreeGC(defdsp, step_pixmaps[i]->erase_gc); + XFreeColors(defdsp, defcmap, step_pixmaps[i]->xpmattrs.pixels, + step_pixmaps[i]->xpmattrs.npixels, 0); + XpmFreeAttributes(&step_pixmaps[i]->xpmattrs); + } +} + +static void +onintr(a) + int a; +/* This gets called when SIGINT or SIGTERM is received */ +{ + free_pixmaps(); + exit(0); +} + +#ifdef DEBUG +static void +onsegv(a) + int a; +/* Called when SEGV detected. Hmmmmm.... */ +{ + fflush(stdout); + fprintf(stderr, "SEGV detected! : %d\n", a); + exit(1); +} +#endif /* DEBUG */ + + +/* + * Pixmaps without file I/O (but do have XPM) + */ + +static void +pixmap_sort(head, numelems) + Bubble_Step **head; + int numelems; +/* Couldn't get qsort to work right with this so I wrote my own. This puts +the numelems length array with first element at head into order of radius. +*/ +{ + Bubble_Step tmp; + Bubble_Step *least = 0; + int minradius = INT_MAX; + int i; + + for (i = 0; i < numelems; i++) { + if (head[i]->radius < minradius) { + least = head[i]; + minradius = head[i]->radius; + } + } + if (*head != least) { + memcpy(&tmp, least, sizeof(Bubble_Step)); + memcpy(least, *head, sizeof(Bubble_Step)); + memcpy(*head, &tmp, sizeof(Bubble_Step)); + } + + if (numelems > 2) + pixmap_sort(&head[1], numelems-1); +} + +static int +extrapolate(i1, i2) + int i1; + int i2; +{ + return (i2 + (i2 - i1)); +} + +static void +make_pixmap_array(list) + Bubble_Step *list; +/* From a linked list of bubbles construct the array step_pixmaps */ +{ + Bubble_Step *tmp = list; + int ind; +#ifdef DEBUG + int prevrad = -1; +#endif + + if (list == (Bubble_Step *)NULL) { + fprintf(stderr, "NULL list passed to make_pixmap_array\n"); + exit(1); + } + + num_bubble_pixmaps = 1; + while(tmp->next != (Bubble_Step *)NULL) { + tmp = tmp->next; + ++num_bubble_pixmaps; + } + + if (num_bubble_pixmaps < 2) { + fprintf(stderr, "Must be at least two bubbles in file\n"); + exit(1); + } + + step_pixmaps = (Bubble_Step **)xmalloc((num_bubble_pixmaps + 1) * + sizeof(Bubble_Step *)); + + /* Copy them blindly into the array for sorting. */ + ind = 0; + tmp = list; + do { + step_pixmaps[ind++] = tmp; + tmp = tmp->next; + } while(tmp != (Bubble_Step *)NULL); + + /* We make another bubble beyond the ones with pixmaps so that the final + bubble hangs around and doesn't pop immediately. It's radius and area + are found by extrapolating from the largest two bubbles with pixmaps. */ + + step_pixmaps[num_bubble_pixmaps] = + (Bubble_Step *)xmalloc(sizeof(Bubble_Step)); + step_pixmaps[num_bubble_pixmaps]->radius = INT_MAX; + + pixmap_sort(step_pixmaps, (num_bubble_pixmaps + 1)); + +#ifdef DEBUG + if (step_pixmaps[num_bubble_pixmaps]->radius != INT_MAX) { + fprintf(stderr, "pixmap_sort() screwed up make_pixmap_array\n"); + } +#endif /* DEBUG */ + + step_pixmaps[num_bubble_pixmaps]->radius = + extrapolate(step_pixmaps[num_bubble_pixmaps-2]->radius, + step_pixmaps[num_bubble_pixmaps-1]->radius); + step_pixmaps[num_bubble_pixmaps]->area = + calc_bubble_area(step_pixmaps[num_bubble_pixmaps]->radius); + + +#ifdef DEBUG + /* Now check for correct order */ + for (ind = 0; ind < num_bubble_pixmaps; ind++) { + if (prevrad > 0) { + if (step_pixmaps[ind]->radius < prevrad) { + fprintf(stderr, "Pixmaps not in ascending order of radius\n"); + exit(1); + } + } + prevrad = step_pixmaps[ind]->radius; + } +#endif /* DEBUG */ +} + +#ifndef NO_DEFAULT_BUBBLE +static void +make_pixmap_from_default(pixmap_data, bl) + char **pixmap_data; + Bubble_Step *bl; +/* Read pixmap data which has been compiled into the program and a pointer + to which has been passed. + + This is virtually copied verbatim from make_pixmap_from_file() above and +changes made to either should be propagated onwards! */ +{ + int result; + XGCValues gcv; + +#ifdef DEBUG + if (pixmap_data == (char **)0) { + fprintf(stderr, "make_pixmap_from_default(): NULL passed\n"); + exit(1); + } +#endif + + if (bl == (Bubble_Step *)NULL) { + fprintf(stderr, "NULL pointer passed to make_pixmap()\n"); + exit(1); + } + + bl->xpmattrs.closeness = 40000; + bl->xpmattrs.valuemask = XpmColormap | XpmCloseness; + bl->xpmattrs.colormap = defcmap; + + /* This is the only line which is different from make_pixmap_from_file() */ + result = XpmCreatePixmapFromData(defdsp, defwin, pixmap_data, &bl->ball, + &bl->shape_mask, &bl->xpmattrs); + + switch(result) { + case XpmColorError: + fprintf(stderr, "xpm: color substitution performed\n"); + /* fall through */ + case XpmSuccess: + bl->radius = MAX(bl->xpmattrs.width, bl->xpmattrs.height) / 2; + bl->area = calc_bubble_area(bl->radius); + break; + case XpmColorFailed: + fprintf(stderr, "xpm: color allocation failed\n"); + exit(1); + case XpmNoMemory: + fprintf(stderr, "xpm: out of memory\n"); + exit(1); + default: + fprintf(stderr, "xpm: unknown error code %d\n", result); + exit(1); + } + + gcv.plane_mask = AllPlanes; + gcv.foreground = default_fg_pixel; + gcv.function = GXcopy; + bl->draw_gc = XCreateGC (defdsp, defwin, GCForeground, &gcv); + XSetClipMask(defdsp, bl->draw_gc, bl->shape_mask); + + gcv.foreground = default_bg_pixel; + gcv.function = GXcopy; + bl->erase_gc = XCreateGC (defdsp, defwin, GCForeground, &gcv); + XSetClipMask(defdsp, bl->erase_gc, bl->shape_mask); +} + +static void +default_to_pixmaps(void) +/* Make pixmaps out of default ball data stored in bubbles_default.c */ +{ + int i; + Bubble_Step *pixmap_list = (Bubble_Step *)NULL; + Bubble_Step *newpix, *tmppix; + char **pixpt; + + /* Make sure pixmaps are freed when program is terminated */ + /* This is when I hit ^C */ + if (signal(SIGINT, SIG_IGN) != SIG_IGN) + signal(SIGINT, onintr); + /* xscreensaver sends SIGTERM */ + if (signal(SIGTERM, SIG_IGN) != SIG_IGN) + signal(SIGTERM, onintr); +#ifdef DEBUG + if (signal(SIGSEGV, SIG_IGN) != SIG_IGN) { + printf("Setting signal handler for SIGSEGV\n"); + signal(SIGSEGV, onsegv); + } else { + printf("Didn't set signal hanlder for SIGSEGV\n"); + } +#endif /* DEBUG */ + + for (i = 0; i < num_default_bubbles; i++) { + pixpt = default_bubbles[i]; + newpix = (Bubble_Step *)xmalloc(sizeof(Bubble_Step)); + make_pixmap_from_default(pixpt, newpix); + /* Now add to list */ + if (pixmap_list == (Bubble_Step *)NULL) { + pixmap_list = newpix; + } else { + tmppix = pixmap_list; + while (tmppix->next != (Bubble_Step *)NULL) + tmppix = tmppix->next; + tmppix->next = newpix; + } + newpix->next = (Bubble_Step *)NULL; + } + + /* Finally construct step_pixmaps[] */ + make_pixmap_array(pixmap_list); +} + +#endif /* NO_DEFAULT_BUBBLE */ + +#endif /* HAVE_XPM */ + +/* + * File I/O stuff + */ + +#ifdef BUBBLES_IO + +static DIR * +my_opendir(name) + char *name; +/* Like opendir() but checks for things so we don't have to do it multiple +times in the code. */ +{ + DIR *rv; + + if (name == (char *)NULL) { + fprintf(stderr, "NULL directory name\n"); + return (DIR *)NULL; + } + + if ((rv = opendir(name)) == NULL) { + perror(name); + return (DIR *)NULL; + } + + return rv; +} + +static int +regular_file(name) + char *name; +/* Check to see if we can use the named file. This was broken under Linux +1.3.45 but seems to be okay under 1.3.54. The parameter "name" was being +trashed if the file didn't exist. Yeah, I know 1.3.x are development +kernels.... +*/ +{ + int fd; + + if ((fd = open(name, O_RDONLY)) == -1) { + perror(name); + return 0; + } else { + close(fd); + return 1; + } +} + +static char * +get_random_name(dir) + char *dir; +/* Pick an appropriate file at random out of the files in the directory dir */ +{ + STRUCT_DIRENT *dp; + DIR *dfd; + int numentries = 0; + int entnum; + int x; + char buf[PATH_BUF_SIZE]; + char *rv; + + if ((dfd = my_opendir(dir)) == (DIR *)NULL) + return (char *)NULL; + + while ((dp = readdir(dfd)) != NULL) { + if ((strcmp(DIRENT_NAME, ".") == 0) || (strcmp(DIRENT_NAME, "..") == 0)) + continue; + if ((strlen(dir)+strlen(DIRENT_NAME)+2) > 1024) { + fprintf(stderr, "name %s/%s too long\n", dir, DIRENT_NAME); + continue; + } + if (sprintf(buf, "%s/%s", dir, DIRENT_NAME) > (PATH_BUF_SIZE-1)) { + fprintf(stderr, "path buffer overflowed in get_random_name()\n"); + continue; + } + if (regular_file(buf)) + ++numentries; + } + closedir(dfd); + if (numentries == 0) { + fprintf(stderr, "No suitable files found in %s\n", dir); + return (char *)NULL; + } + entnum = ya_random() % numentries; + x = 0; + + if ((dfd = my_opendir(dir)) == (DIR *)NULL) + return (char *)NULL; + while ((dp = readdir(dfd)) != NULL) { + if ((strcmp(DIRENT_NAME, ".") == 0) || (strcmp(DIRENT_NAME, "..") == 0)) + continue; + if ((strlen(dir)+strlen(DIRENT_NAME)+2) > 1024) { + /* We warned about this previously */ + continue; + } + if (sprintf(buf, "%s/%s", dir, DIRENT_NAME) > (PATH_BUF_SIZE-1)) { + fprintf(stderr, "path buffer overflowed in get_random_name()\n"); + continue; + } + if (regular_file(buf)) { + if (x == entnum) { + rv = (char *)xmalloc(1024 * sizeof(char)); + strcpy(rv, buf); + closedir(dfd); + return rv; + } + ++x; + } + } + /* We've screwed up if we reach here - someone must have deleted all the + files while we were counting them... */ + fprintf(stderr, "get_random_name(): Oops!\n"); + exit(1); +} + +static int +read_line(fd, buf, bufsize) + int fd; + char **buf; + int bufsize; +/* A line is read from fd until a '\n' is found or EOF is reached. (*buf) +is initially of length bufsize and is extended by bufsize chars if need +be (for as many times as it takes). */ +{ + char x; + int pos = 0; + int size = bufsize; + int rv; + char *newbuf; + + while (1) { + rv = read(fd, &x, 1); + if (rv == -1) { + perror("read_line(): "); + return IO_ERROR; + } else if (rv == 0) { + (*buf)[pos] = '\0'; + return EOF_REACHED; + } else if (x == '\n') { + (*buf)[pos] = '\0'; + return LINE_READ; + } else { + (*buf)[pos++] = x; + if (pos == (size - 1)) { + /* We've come to the end of the space */ + newbuf = (char *)xmalloc((size+bufsize) * sizeof(char)); + strncpy(newbuf, *buf, (size - 1)); + free(*buf); + *buf = newbuf; + size += bufsize; + } + } + } +} + +static int +create_temp_file(name) + char **name; +/* Create a temporary file in /tmp and return a filedescriptor to it */ +{ + int rv; + + if (*name != (char *)NULL) + free(*name); + + if ((*name = tempnam("/tmp", "abxdfes")) == (char *)NULL) { + fprintf(stderr, "Couldn't make new temporary file\n"); + exit(1); + } +/* printf("Temp file created : %s\n", *name); */ + if ((rv = creat(*name, 0644)) == -1) { + fprintf(stderr, "Couldn't open temporary file\n"); + exit(1); + } + + return rv; +} + + +#ifdef BUBBLES_IO +static void +make_pixmap_from_file(fname, bl) + char *fname; + Bubble_Step *bl; +/* Read the pixmap in file fname into structure bl which must already + be allocated. */ +{ + int result; + XGCValues gcv; + + if (bl == (Bubble_Step *)NULL) { + fprintf(stderr, "NULL pointer passed to make_pixmap()\n"); + exit(1); + } + + bl->xpmattrs.closeness = 40000; + bl->xpmattrs.valuemask = XpmColormap | XpmCloseness; + bl->xpmattrs.colormap = defcmap; + + result = XpmReadFileToPixmap(defdsp, defwin, fname, &bl->ball, + &bl->shape_mask, &bl->xpmattrs); + + switch(result) { + case XpmColorError: + fprintf(stderr, "xpm: color substitution performed\n"); + /* fall through */ + case XpmSuccess: + bl->radius = MAX(bl->xpmattrs.width, bl->xpmattrs.height) / 2; + bl->area = calc_bubble_area(bl->radius); + break; + case XpmColorFailed: + fprintf(stderr, "xpm: color allocation failed\n"); + exit(1); + case XpmNoMemory: + fprintf(stderr, "xpm: out of memory\n"); + exit(1); + default: + fprintf(stderr, "xpm: unknown error code %d\n", result); + exit(1); + } + + gcv.plane_mask = AllPlanes; + gcv.foreground = default_fg_pixel; + gcv.function = GXcopy; + bl->draw_gc = XCreateGC (defdsp, defwin, GCForeground, &gcv); + XSetClipMask(defdsp, bl->draw_gc, bl->shape_mask); + + gcv.foreground = default_bg_pixel; + gcv.function = GXcopy; + bl->erase_gc = XCreateGC (defdsp, defwin, GCForeground, &gcv); + XSetClipMask(defdsp, bl->erase_gc, bl->shape_mask); +} +#endif /* BUBBLES_IO */ + +static void +read_file_to_pixmaps(fname) + char *fname; +/* Read the pixmaps contained in the file fname into memory. THESE SHOULD +BE UNCOMPRESSED AND READY TO GO! */ +{ + int fd, tmpfd=0, rv; + int inxpm = 0; + int xpmseen = 0; + char *buf = (char *)NULL; + char *tmpname = (char *)NULL; + Bubble_Step *pixmap_list = (Bubble_Step *)NULL; + Bubble_Step *newpix, *tmppix; + + /* We first create a linked list of pixmaps before allocating + memory for the array */ + + if ((fd = open(fname, O_RDONLY)) == -1) { + fprintf(stderr, "Couldn't open %s\n", fname); + exit(1); + } + + /* Make sure pixmaps are freed when program is terminated */ + /* This is when I hit ^C */ + if (signal(SIGINT, SIG_IGN) != SIG_IGN) + signal(SIGINT, onintr); + /* xscreensaver sends SIGTERM */ + if (signal(SIGTERM, SIG_IGN) != SIG_IGN) + signal(SIGTERM, onintr); +#ifdef DEBUG + if (signal(SIGSEGV, SIGN_IGN) != SIG_IGN) + signal(SIGSEGV, onsegv); +#endif /* DEBUG */ + + while (1) { + if (inxpm == 2) + break; + + buf = (char *)malloc(READ_LINE_BUF_SIZE * sizeof(char)); + + switch ((rv = read_line(fd, &buf, READ_LINE_BUF_SIZE))) { + case IO_ERROR: + fprintf(stderr, "An I/O error occurred\n"); + exit(1); + case EOF_REACHED: + if (inxpm) { + fprintf(stderr, "EOF occurred inside an XPM block\n"); + exit(1); + } else + inxpm = 2; + break; + case LINE_READ: + if (inxpm) { + if (strncmp("};", buf, 2) == 0) { + inxpm = 0; + write(tmpfd, buf, strlen(buf)); + write(tmpfd, "\n", 1); + close(tmpfd); + /* Now process the tmpfile */ + newpix = (Bubble_Step *)xmalloc(sizeof(Bubble_Step)); + make_pixmap_from_file(tmpname, newpix); + /* Now add to list */ + if (pixmap_list == (Bubble_Step *)NULL) { + pixmap_list = newpix; + } else { + tmppix = pixmap_list; + while (tmppix->next != (Bubble_Step *)NULL) + tmppix = tmppix->next; + tmppix->next = newpix; + } + newpix->next = (Bubble_Step *)NULL; + unlink(tmpname); + } else { + write(tmpfd, buf, strlen(buf)); + write(tmpfd, "\n", 1); + } + } else { + if (strncmp("/* XPM */", buf, 9) == 0) { + tmpfd = create_temp_file(&tmpname); +/* This proves XPM's performance is kinda pathetic */ +#ifdef DEBUG + printf("New XPM detected : %s, fd=%d\n", tmpname, tmpfd); +#endif /* DEBUG */ + inxpm = 1; + xpmseen = 1; + } + write(tmpfd, buf, strlen(buf)); + write(tmpfd, "\n", 1); + } + break; + default: + fprintf(stderr, "read_line returned unknown code %d\n", rv); + exit(1); + } + + free(buf); + } + + close(fd); + if (buf != (char *)NULL) + free(buf); + if (tmpname != (char *)NULL) + free(tmpname); + + if (! xpmseen) { + fprintf(stderr, "There was no XPM data in the file %s\n", fname); + exit(1); + } + + /* Finally construct step_pixmaps[] */ + make_pixmap_array(pixmap_list); +} + +static void +shell_exec(command) + char *command; +/* Forks a shell to execute "command" then waits for command to finish */ +{ + int pid, status, wval; + + switch(pid=fork()) { + case 0: + if (execlp(BOURNESH, BOURNESH, "-c", command, (char *)NULL) == -1) { + fprintf(stderr, "Couldn't exec shell %s\n", BOURNESH); + exit(1); + } + /* fall through if execlp() fails */ + case -1: + /* Couldn't fork */ + perror(progname); + exit(1); + default: + while ((wval = wait(&status)) != pid) + if (wval == -1) { + perror(progname); + exit(1); + } + } +} + +static void +uncompress_file(current, namebuf) + char *current; + char *namebuf; +/* If the file current is compressed (i.e. its name ends in .gz or .Z, +no check is made to see if it is actually a compressed file...) then a +new temporary file is created for it and it is decompressed into there, +returning the name of the file to namebuf, else current is returned in +namebuf */ +{ + int fd; + char *tname = (char *)NULL; + char argbuf[COMMAND_BUF_SIZE]; + + if (((strlen(current) >=4) && + (strncmp(¤t[strlen(current)-3], ".gz", 3) == 0)) || + ((strlen(current) >=3) && + (strncmp(¤t[strlen(current)-2], ".Z", 2) == 0))) { + fd = create_temp_file(&tname); + /* close immediately but don't unlink so we should have a zero length + file in /tmp which we can append to */ + close(fd); + if (sprintf(argbuf, "%s -dc %s > %s", GZIP, current, tname) > + (COMMAND_BUF_SIZE-1)) { + fprintf(stderr, "command buffer overflowed in uncompress_file()\n"); + exit(1); + } + shell_exec(argbuf); + strcpy(namebuf, tname); + } else { + strcpy(namebuf, current); + } + return; +} + +#endif /* BUBBLES_IO */ + +/* + * Main stuff + */ + + +static void +get_resources(dpy) + Display *dpy; +/* Get the appropriate X resources and warn about any inconsistencies. */ +{ + Bool nodelay; +#ifdef BUBBLES_IO +#ifdef HAVE_XPM + char *dirname; +#else + char *foo, *bar; +#endif /* HAVE_XPM */ +#endif /* BUBBLES_IO */ + + threed = get_boolean_resource("3D", "Boolean"); + quiet = get_boolean_resource("quiet", "Boolean"); + simple = get_boolean_resource("simple", "Boolean"); + /* Forbid rendered bubbles on monochrome displays */ + if ((mono_p) && (! simple)) { + if (! quiet) + fprintf(stderr, "Rendered bubbles not supported on monochrome \ +displays\n"); + simple = True; + } + delay = get_integer_resource("delay", "Integer"); + nodelay = get_boolean_resource("nodelay", "Boolean"); + if (nodelay) + delay = 0; + if (delay < 0) + delay = 0; + + default_fg_pixel = get_pixel_resource ("foreground", "Foreground", dpy, + DefaultColormap(dpy, + DefaultScreen(dpy))); + default_bg_pixel = get_pixel_resource ("background", "Background", dpy, + DefaultColormap(dpy, + DefaultScreen(dpy))); + + if (simple) { + /* This is easy */ + broken = get_boolean_resource("broken", "Boolean"); + if (broken) + if (! quiet) + fprintf(stderr, "-broken not available in simple mode\n"); + } else { +#ifndef HAVE_XPM + simple = 1; +#else + broken = get_boolean_resource("broken", "Boolean"); +#ifdef BUBBLES_IO + pixmap_file = get_string_resource("file", "File"); + dirname = get_string_resource("directory", "Directory"); +#ifdef NO_DEFAULT_BUBBLE + /* Must specify -file or -directory if no default bubble compiled in */ + if (strcmp(pixmap_file, "(default)") != 0) { + } else if (strcmp(dirname, "(default)") != 0) { + if ((pixmap_file = get_random_name(dirname)) == (char *)NULL) { + /* Die if we can't open directory - make it consistent with -file + when it fails, rather than falling back to default. */ + exit(1); + } + } else { + fprintf(stderr, "No default bubble compiled in - use -file or \ +-directory\n"); + exit(1); + } +#else + if (strcmp(pixmap_file, "(default)") != 0) { + } else if (strcmp(dirname, "(default)") != 0) { + if ((pixmap_file = get_random_name(dirname)) == (char *)NULL) { + exit(1); + } + } else { + /* Use default bubble */ + use_default_bubble = 1; + } +#endif /* NO_DEFAULT_BUBBLE */ +#else + use_default_bubble = 1; +#endif /* BUBBLES_IO */ +#endif /* HAVE_XPM */ + } +} + +static void +init_bubbles (dpy, window) + Display *dpy; + Window window; +{ + XGCValues gcv; + XWindowAttributes xgwa; + int i; +#ifdef BUBBLES_IO + char uncompressed[1024]; +#endif /* BUBBLES_IO */ + + defdsp = dpy; + defwin = window; + + ya_rand_init(0); + + get_resources(dpy); + + XGetWindowAttributes (dpy, window, &xgwa); + +#ifdef DEBUG + printf("sizof(int) on this platform is %d\n", sizeof(int)); + printf("sizof(long) on this platform is %d\n", sizeof(long)); +#endif /* DEBUG */ + + screen_width = xgwa.width; + screen_height = xgwa.height; + screen_depth = xgwa.depth; + defcmap = xgwa.colormap; + + if (simple) { + /* These are pretty much plucked out of the air */ + bubble_min_radius = (int)(0.006*(double)(MIN(screen_width, + screen_height))); + bubble_max_radius = (int)(0.045*(double)(MIN(screen_width, + screen_height))); + /* Some trivial values */ + if (bubble_min_radius < 1) + bubble_min_radius = 1; + if (bubble_max_radius <= bubble_min_radius) + bubble_max_radius = bubble_min_radius + 1; + + mesh_length = (2 * bubble_max_radius) + 3; + + /* store area of each bubble of certain radius as number of 1/10s of + a pixel area. PI is defined in */ + bubble_areas = (long *)xmalloc((bubble_max_radius + 2) * sizeof(int)); + for (i = 0; i < bubble_min_radius; i++) + bubble_areas[i] = 0; + for (i = bubble_min_radius; i <= (bubble_max_radius+1); i++) + bubble_areas[i] = calc_bubble_area(i); + + mesh_length = (2 * bubble_max_radius) + 3; + } else { +#ifndef HAVE_XPM + fprintf(stderr, "Bug: simple mode code not set but HAVE_XPM not \ +defined\n"); + exit(1); +#else + /* Make sure all #ifdef sort of things have been taken care of in + get_resources(). */ + if (use_default_bubble) { +#ifdef NO_DEFAULT_BUBBLE + fprintf(stderr, "Bug: use_default_bubble and NO_DEFAULT_BUBBLE both \ +defined\n"); + exit(1); +#else + default_to_pixmaps(); +#endif /* NO_DEFAULT_BUBBLE */ + + /* Set mesh length */ + mesh_length = (2 * step_pixmaps[num_bubble_pixmaps-1]->radius) + 3; + } else { +#ifdef BUBBLES_IO + if (! regular_file(pixmap_file)) { + /* perror() in regular_file printed error message */ + exit(1); + } + uncompress_file(pixmap_file, uncompressed); + read_file_to_pixmaps(uncompressed); + if (strcmp(pixmap_file, uncompressed)) + unlink(uncompressed); + + mesh_length = (2 * step_pixmaps[num_bubble_pixmaps-1]->radius) + 3; +#else + fprintf(stderr, "Bug: use_default_bubble is not defined yet I/O is not \ +compiled in\n"); + exit(1); +#endif /* BUBBLES_IO */ + } +#endif /* HAVE_XPM */ + + /* Am I missing something in here??? */ + } + + mesh_width = (screen_width / mesh_length) + 1; + mesh_height = (screen_height / mesh_length) + 1; + mesh_cells = mesh_width * mesh_height; + init_mesh(); + + calculate_adjacent_list(); + + adjust_areas(); + + /* Graphics contexts for simple mode */ + if (simple) { + gcv.foreground = default_fg_pixel; + draw_gc = XCreateGC (dpy, window, GCForeground, &gcv); + gcv.foreground = default_bg_pixel; + erase_gc = XCreateGC (dpy, window, GCForeground, &gcv); + } + + XClearWindow (dpy, window); +} + +static void +bubbles (dpy, window) + Display *dpy; + Window window; +{ + Bubble *tmp; + + tmp = new_bubble(); + add_to_mesh(tmp); + insert_new_bubble(tmp); + + XSync (dpy, True); +} + + +void +screenhack (dpy, window) + Display *dpy; + Window window; +{ + init_bubbles (dpy, window); + while (1) { + bubbles (dpy, window); + if (delay) + usleep(delay); + } +} + diff --git a/hacks/bubbles.h b/hacks/bubbles.h new file mode 100644 index 00000000..43f19407 --- /dev/null +++ b/hacks/bubbles.h @@ -0,0 +1,217 @@ +/* bubbles.h - definitions for bubbles screensaver */ + +/* $Id: bubbles.h,v 1.1 1996/09/08 01:35:40 jwz Exp $ */ + +#ifndef _BUBBLES_H_ +#define _BUBBLES_H_ + +#ifdef HAVE_XPM +#include +#endif + +/*************************************************************************** + * Options you might like to change to affect the program's behaviour * + ***************************************************************************/ + +/* + * Uncommenting the following will enable support for reading bubbles from + * files (using the -file and -directory options to bubbles). This is + * disabled by default since such operations are inherently non-portable + * and we want the program to compile on as many systems as possible. + * + * If you uncomment this and you figure out how to get it working, please + * let me (J.Macnicol@student.anu.edu.au) know. Diffs against the standard + * distribution would be appreciated. Possible sources of problems are + * dirent and possibly the use of tmpnam(). + */ + +/* #define BUBBLES_IO */ + +/* + * The following only makes sense if BUBBLES_IO above is defined. + * + * Uncomment the following if you always want to use the -file or + * -directory options on the command line and never to use a default bubble + * compiled into the program. This way you would save memory and disk space + * since if you do use -file or -directory only one bubble will be loaded + * into memory at any one time (and remember the default bubble is really + * uncompressed, unlike bubbles in files which can be compressed). This + * is disabled by default only so people running the program for the first + * time with no knowldege of the command line options don't get error + * messages ;) + * + * NOTE: You will still need to have a bubbles_default.c file, else the + * build sequence will fail. Well constructed bubbles_default.c files + * have #ifdef's which simply exclude everything else in the file at + * compile time. The bubblestodefault script does this. + */ + +/* #define NO_DEFAULT_BUBBLE */ + +/* + * This turns on any debugging messages and sanity checks. Hopefully you + * won't need this :) It slows things down a bit, too. + * + * NOTE: If you uncomment this you will get some messages about unused + * functions when you compile. You can ignore these - they refer to + * convenient checking routines which simply aren't called but are left + * in case someone wants to use them. + */ + +/* #define DEBUG */ + +/*************************************************************************** + * Things you might need to change to get things working right * + ***************************************************************************/ + +/* + * Name of the gzip binary. You shouldn't need to change this unless it's + * not in your PATH when the program is run, in which case you will need to + * substitute the full path here. Keep the double quotes else things won't + * compile! + */ + +#define GZIP "gzip" + +/* + * Likewise for the Bourne shell. + */ + +#define BOURNESH "sh" + +/* + * The name of the directory entry structure is different under Linux + * (under which this code is being developed) than other systems. The case + * alternate form here is that given in Kernighan & Ritchie's C book (which + * must be authoratitive, no?) + * + * 04/07/96 : People will have to hack this to get it working on some + * systems. I believe it doesn't work on SGI, for example. + */ + +#ifdef _POSIX_SOURCE +#define STRUCT_DIRENT struct dirent +#else +#define STRUCT_DIRENT Dirent +#endif + +/* + * The naming of fields in struct dirent also seems to differ from system to + * system. This may have to be extended to make things truly portable. + * What we want here is the name field from a dirent struct pointed to + * by "dp". + * + * 04/07/96 : See above. This may need to be changed too. + */ + +#ifdef _POSIX_SOURCE +#define DIRENT_NAME dp->d_name +#else +#define DIRENT_NAME dp->name +#endif + +/* + * I don't know why this isn't defined. + */ +#ifdef linux +extern char *tempnam(char *, char *); +#endif + +/**************************************************************************** + * Buffer lengths and things you probably won't need to touch * + ****************************************************************************/ + +/* Maximum length of a full path name we can deal with */ +#define PATH_BUF_SIZE 1024 + +/* Size of string passed to shell as command */ +#define COMMAND_BUF_SIZE 2500 + +/* Size increments for read_line() buffers */ +#define READ_LINE_BUF_SIZE 24 + +/**************************************************************************** + * End of options * + ****************************************************************************/ + +/* Some machines define M_PI and not PI. If they don't define either, use +own own. Really, the accuracy of this is _not_ very important. */ +#ifndef PI +#define PI M_PI +#ifndef M_PI +#define M_PI 3.1415926535 +#endif +#endif + +/* for delete_bubble_in_mesh() */ +#define DELETE_BUBBLE 0 +#define KEEP_BUBBLE 1 + +/* Status codes for read_line */ +#define LINE_READ 0 +#define EOF_REACHED 1 +#define IO_ERROR 2 + +/* + * Magic number for Bubble struct, in case it's trashed when debugging code + * (which happened to me often.... :( + */ + +#define BUBBLE_MAGIC 5674 + +/* Useful macros */ +#define MAX(A, B) ((A) > (B) ? (A) : (B)) +#define MIN(A, B) ((A) < (B) ? (A) : (B)) + +/* How we represent bubbles */ +struct bub { + int radius; + int step; /* for rendered bubbles */ + long area; + int x; + int y; + int magic; + int cell_index; + int visible; + struct bub *next; + struct bub *prev; +}; + +typedef struct bub Bubble; + +/* + * How we represent pixmaps of rendered bubbles. Because the range of radii + * available may not be continuous, we call each a step (for the lack of a + * better name...) + */ + +#ifdef HAVE_XPM +struct bub_step { + int radius; + long area; + Pixmap ball, shape_mask; + GC draw_gc, erase_gc; + XpmAttributes xpmattrs; + struct bub_step *next; +}; + +typedef struct bub_step Bubble_Step; +#endif /* HAVE_XPM */ + +/* Make sure default bubble isn't compiled when we don't have XPM +Disable file I/O code too. */ +#ifndef HAVE_XPM +#define NO_DEFAULT_BUBBLE +#ifdef BUBBLES_IO +#undef BUBBLES_IO +#endif /* BUBBLES_IO */ +#endif /* HAVE_XPM */ + +/* Make sure default bubble is compiled in when we have XPM and no file I/O */ +#ifdef HAVE_XPM +#ifndef BUBBLES_IO +#undef NO_DEFAULT_BUBBLE +#endif /* BUBBLES_IO */ +#endif /* HAVE_XPM */ + +#endif /* _BUBBLES_H_ */ diff --git a/hacks/bubbles.man b/hacks/bubbles.man new file mode 100644 index 00000000..c9016e64 --- /dev/null +++ b/hacks/bubbles.man @@ -0,0 +1,142 @@ +.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 "14-Dec-95" "X Version 11" +.SH NAME +bubbles - frying pan / soft drink simulation +.SH SYNOPSIS +.B bubbles +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-simple] [\-broken] [\-3D] [\-file filename] [\-directory directoryname] +.SH DESCRIPTION +\fIBubbles\fP sprays lots of little random bubbles all over the window which +then grow until they reach their maximum size and go pop. The inspiration +for this was watching little globules of oil on the bottom of a frying pan +and it also looks a little like bubbles in fizzy soft drink. The default +mode uses fancy ray-traced bubbles but there is also a mode which just draws +circles in case the default mode is too taxing on your hardware. +.SH OPTIONS +Depending on how your +.I bubbles +was compiled, it accepts the following options: +.TP 8 +.B \-foreground +Colour of circles if \fI\-simple\fP mode is selected. +.TP 8 +.B \-background +Colour of window background. +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +Specify which visual to use. Legal values are the name of a visual class, +or the id number (decimal or hex) of a specific visual. +.TP 8 +.B \-delay microseconds +How much of a delay should be introduced between steps of the animation. +Default 1, or about 1 microsecond. Actually, this is the delay between each +group of 15 new bubbles since such a delay between each step results in a +very slow animation rate. +.TP 8 +.B \-nodelay +Same as \fI\-delay 0\fP. +.TP 8 +.B \-simple +Don't use the default fancy pixmap bubbles. Just draw circles instead. +This may give more bearable performance if your hardware wasn't made for +this sort of thing. +.TP 8 +.B \-broken +Don't hide bubbles when they pop. This was a bug during development +but the results were actually quite attractive. (This option is only +available if you have the XPM library available and the imake generated +Makefile has defined HAVE_XPM). +.TP 8 +.B \-3D +Normally, the simulation is done completely in two dimensions. When a +bubble swallows up another bubble, the areas of each are added to get +the area of the resulting bubble. This option changes the algorithm +to instead add volume (imagining each to be a sphere in 3D space). The +whole thing looks more realistic but I find it attracts attention to +the flickering of each bubble as they are move and are redrawn. Your +mileage may vary. +.TP 8 +.B \-file filename +Use the pixmap definitions in the given file, instead of the default (if +one is compiled in). This is ignored if \fI\-simple\fP is specified. If +the file is compressed (either with compress or gzip), it is decompressed +before use. (This option only works if you have XPM compiled into your +binary and you have compiled with BUBBLES_IO set in bubbles.h. This is +\fBnot\fP the default). +.TP 8 +.B \-directory directoryname +Similar to \fI-file\fP except the file is taken randomly from the +contents of the specified directory. (Again, this option is only available +if you have XPM and BUBBLES_IO was set when compiling. See above). +.TP 8 +.B \-quiet +Don't print messages explaining why one or several command line options +were ignored. This is disabled by default. +.SH NOTES +If you find the pace of things too slow, remember that there is a delay +even though you specify no \fI\-delay\fP option. Try using \fI\-nodelay\fP +although beware of the effects of irritation of other users if you're on a +shared system as you bleed their CPU time away. + +Some tools to assist in creation of new bubbles are included in the source +distribution. These can either be loaded with the \fI\-file\fP or +\fI\-directory\fP options (if available) or they can be used in place +of the distributed default bubble (bubble_default.c). +You might like to copy these scripts to a permanent location and +use them. Read bubbles.README. + +Rendered bubbles are not supported on monochrome displays. I'm not +convinced that small bubbles, even dithered properly are going to look +like anything more than a jumble of random dots. +.SH BUGS +There is a delay before something appears on the screen when using +rendered bubbles. The XPM library seems to take a \fBlong\fP time to make +pixmaps out of raw data. This can be irritating on slower systems. + +The movement of the bubbles looks jerky if an incomplete set of bubbles +is used. + +The hide/display algorithm could do with some work to avoid flickering +when \fI\-nodelay\fP is set. +.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 DISTRIBUTION POLICY +This work is Copyright \(co 1995, 1996 by James Macnicol. Distribution is +allowed under the terms of the GNU General Public License. Look at the +sources for the legalese. +.SH AUTHOR +James Macnicol . diff --git a/hacks/bubbles_default.c b/hacks/bubbles_default.c new file mode 100644 index 00000000..fe6be92b --- /dev/null +++ b/hacks/bubbles_default.c @@ -0,0 +1,2123 @@ +#include +#include "bubbles.h" + +#ifndef NO_DEFAULT_BUBBLE + +/* XPM */ +static char *glass1[] = { +/* width height ncolors chars_per_pixel */ +"10 10 61 2", +/* colors */ +"`` c None", +"`a c #27274E", +"`b c #29293F", +"`c c #2C2C63", +"`d c #353579", +"`e c #242447", +"`f c #222245", +"`g c #25253E", +"`h c #1C1C3F", +"`i c #2B2B47", +"`j c #252544", +"`k c #222251", +"`l c #323264", +"`m c #212146", +"`n c #37374B", +"`o c #22223D", +"`p c #252536", +"`q c #232337", +"`r c #34346C", +"`s c #303068", +"`t c #26264A", +"`u c #5D5D97", +"`v c #363674", +"`w c #2C2C6A", +"`x c #2E2E5B", +"`y c #242451", +"`z c #343464", +"a` c #3C3C6F", +"aa c #353572", +"ab c #38386B", +"ac c #242454", +"ad c #181831", +"ae c #28285B", +"af c #37377A", +"ag c #20203F", +"ah c #26265C", +"ai c #4C4C60", +"aj c #383874", +"ak c #333379", +"al c #444458", +"am c #272756", +"an c #32326E", +"ao c #30306C", +"ap c #40407F", +"aq c #292944", +"ar c #212150", +"as c #323271", +"at c #2D2D76", +"au c #21213F", +"av c #25255A", +"aw c #35356D", +"ax c #313169", +"ay c #2C2C6E", +"az c #18182C", +"b` c #232344", +"ba c #292961", +"bb c #202037", +"bc c #1C1C33", +"bd c #242452", +"be c #45456F", +"bf c #242455", +/* pixels */ +"``````aibebebeal````", +"`````n`zaw`ua``l`n``", +"```i`xab`wasaj`r`x`q", +"``auaean`daf`vao`c`t", +"```haxahayatakbaaeb`", +"``adbfav`wapao`sam`m", +"``azagaracaaae`k`fbc", +"````bb`ybd`aar`e`o``", +"```````paq`j`b`g````", +"````````````````````" +}; +/* XPM */ +static char *glass2[] = { +/* width height ncolors chars_per_pixel */ +"12 12 75 2", +/* colors */ +"`` c None", +"`a c #25254C", +"`b c #23234A", +"`c c #212148", +"`d c #2E2E62", +"`e c #29293F", +"`f c #272754", +"`g c #414188", +"`h c #20202C", +"`i c #2E2E68", +"`j c #242447", +"`k c #25253E", +"`l c #B9B9ED", +"`m c #6767A3", +"`n c #2B2B47", +"`o c #29295C", +"`p c #252544", +"`q c #29295F", +"`r c #1F1F3E", +"`s c #2F2F68", +"`t c #2D2D66", +"`u c #30305F", +"`v c #4C4C6D", +"`w c #2B2B53", +"`x c #2F2F6E", +"`y c #34346C", +"`z c #3B3B55", +"a` c #303068", +"aa c #2C2C64", +"ab c #26264A", +"ac c #5D5D97", +"ad c #363674", +"ae c #3C3C66", +"af c #252556", +"ag c #30306E", +"ah c #3E3E54", +"ai c #2C2C6A", +"aj c #4C4C68", +"ak c #20204A", +"al c #2E2E5B", +"am c #343464", +"an c #16162C", +"ao c #292938", +"ap c #333384", +"aq c #3C3C6F", +"ar c #1E1E37", +"as c #38386B", +"at c #242454", +"au c #31316E", +"av c #181831", +"aw c #232349", +"ax c #272739", +"ay c #23234C", +"az c #37377A", +"b` c #1E1E3D", +"ba c #313174", +"bb c #3C3C78", +"bc c #383874", +"bd c #1B1B33", +"be c #40407F", +"bf c #292944", +"bg c #212150", +"bh c #2D2D76", +"bi c #191937", +"bj c #313169", +"bk c #22224D", +"bl c #18182C", +"bm c #2D2D65", +"bn c #232344", +"bo c #292961", +"bp c #27275F", +"bq c #242452", +"br c #484868", +"bs c #262657", +"bt c #242455", +/* pixels */ +"`````````vajajajbr``````", +"````ahaeae`yacasaq`zah``", +"`````w`f`dagacbb`y`u`u``", +"```naybm`i`mbabcaaamawar", +"``bf`ua`adbpaz`gai`ial`j", +"``bnbgbjaz`xbhapboaa`uav", +"``b`aybtbcaube`x`s`tbqbd", +"``anbiakafbb`l`i`q`o`rbl", +"`````rakbkaf`wbsay`c`k``", +"````ao`pay`aatab`bar`h``", +"````````ax`e`n`kax``````", +"````````````````````````" +}; +/* XPM */ +static char *glass3[] = { +/* width height ncolors chars_per_pixel */ +"14 14 90 2", +/* colors */ +"`` c None", +"`a c #27274E", +"`b c #383858", +"`c c #2E2E62", +"`d c #292967", +"`e c #3535A1", +"`f c #272751", +"`g c #23234D", +"`h c #29293F", +"`i c #353579", +"`j c #272754", +"`k c #20202C", +"`l c #2E2E3D", +"`m c #242447", +"`n c #25253E", +"`o c #3E3E67", +"`p c #1C1C3F", +"`q c #6767A3", +"`r c #2B2B47", +"`s c #29295C", +"`t c #2B2B61", +"`u c #29295F", +"`v c #1F1F3E", +"`w c #2F2F68", +"`x c #2D2D66", +"`y c #222251", +"`z c #2D2D69", +"a` c #33335B", +"aa c #37374B", +"ab c #22223D", +"ac c #28285A", +"ad c #2B2B53", +"ae c #2C2C36", +"af c #424266", +"ag c #232337", +"ah c #525265", +"ai c #32326A", +"aj c #1B1B2F", +"ak c #303068", +"al c #232351", +"am c #363674", +"an c #3C3C66", +"ao c #252556", +"ap c #27275B", +"aq c #363663", +"ar c #4C4C68", +"as c #2E2E5B", +"at c #29294C", +"au c #27274A", +"av c #252548", +"aw c #16162C", +"ax c #292938", +"ay c #353572", +"az c #38386B", +"b` c #4C4C85", +"ba c #2F2F83", +"bb c #20203F", +"bc c #313174", +"bd c #333379", +"be c #444458", +"bf c #272756", +"bg c #47477C", +"bh c #32326E", +"bi c #1B1B33", +"bj c #30306C", +"bk c #40407F", +"bl c #23233E", +"bm c #141422", +"bn c #343473", +"bo c #2D2D76", +"bp c #2E2E6D", +"bq c #40406E", +"br c #21213F", +"bs c #8080BA", +"bt c #25255A", +"bu c #1B1B39", +"bv c #35356D", +"bw c #262651", +"bx c #18182C", +"by c #373786", +"bz c #2B2B63", +"c` c #202037", +"ca c #1C1C33", +"cb c #242452", +"cc c #484868", +"cd c #1F1F43", +"ce c #2C2C5D", +"cf c #3535DD", +"cg c #262657", +"ch c #242455", +/* pixels */ +"``````````arccaharcc````````", +"``````bea``obqbqbqanafaa````", +"`````ladaqbv`qbsbgai`ca``b``", +"````a`a`asaib`bhb`bhakasau``", +"``c``j`c`d`dbd`eb`am`wce`aca", +"``bxasaobt`ibdbycf`iay`u`abx", +"``bl`a`t`ubnbdbocfbcbt`cbwbu", +"``bi`fch`sbhbkbabp`z`u`w`gaj", +"``bm`a`a`u`xbjaibgbzcgbf`paw", +"````agbralazap`t`ucbacbbaj``", +"`````kbrcdcbcbcgbw`y`vab`k``", +"``````axbrauatav`r`m`n`n````", +"``````````ax`h`r`nae````````", +"````````````````````````````" +}; +/* XPM */ +static char *glass4[] = { +/* width height ncolors chars_per_pixel */ +"20 20 151 2", +/* colors */ +"`` c None", +"`a c #27274E", +"`b c #25254C", +"`c c #383858", +"`d c #23234A", +"`e c #212148", +"`f c #2E2E62", +"`g c #292967", +"`h c #3535A1", +"`i c #29293F", +"`j c #2C2C63", +"`k c #2A2A61", +"`l c #33334C", +"`m c #353579", +"`n c #272754", +"`o c #20202C", +"`p c #2E2E3D", +"`q c #2E2E68", +"`r c #242447", +"`s c #2C2C66", +"`t c #222245", +"`u c #181824", +"`v c #25253E", +"`w c #B9B9ED", +"`x c #1C1C3F", +"`y c #6767A3", +"`z c #2B2B47", +"a` c #272743", +"aa c #222248", +"ab c #292931", +"ac c #29295C", +"ad c #1D1D39", +"ae c #252544", +"af c #2B2B61", +"ag c #29295F", +"ah c #1F1F3E", +"ai c #2F2F68", +"aj c #2D2D66", +"ak c #30305F", +"al c #2C2C5B", +"am c #11111C", +"an c #262655", +"ao c #31316D", +"ap c #4C4C6D", +"aq c #222251", +"ar c #323264", +"as c #43436E", +"at c #212146", +"au c #37374B", +"av c #22223D", +"aw c #252536", +"ax c #1D1D42", +"ay c #2A2A5C", +"az c #28285A", +"b` c #2B2B53", +"ba c #333372", +"bb c #2F2F6E", +"bc c #2B2B3F", +"bd c #2C2C36", +"be c #232337", +"bf c #34346C", +"bg c #525265", +"bh c #32326A", +"bi c #303068", +"bj c #21214C", +"bk c #2C2C64", +"bl c #292957", +"bm c #232351", +"bn c #26264A", +"bo c #2F2F60", +"bp c #5D5D97", +"bq c #363674", +"br c #3C3C66", +"bs c #252556", +"bt c #30306E", +"bu c #414178", +"bv c #2C2C6A", +"bw c #20204A", +"bx c #2E2E5B", +"by c #29294C", +"bz c #242451", +"c` c #27274A", +"ca c #343464", +"cb c #4F4F64", +"cc c #252548", +"cd c #292938", +"ce c #333384", +"cf c #3C3C6F", +"cg c #353572", +"ch c #1E1E37", +"ci c #38386B", +"cj c #414156", +"ck c #242454", +"cl c #181831", +"cm c #232349", +"cn c #272739", +"co c #4C4C85", +"cp c #2F2F83", +"cq c #28285B", +"cr c #36366C", +"cs c #48486D", +"ct c #23234C", +"cu c #37377A", +"cv c #20203F", +"cw c #26265C", +"cx c #313174", +"cy c #4C4C60", +"cz c #27273F", +"d` c #3C3C78", +"da c #48485C", +"db c #383874", +"dc c #333379", +"dd c #444458", +"de c #272756", +"df c #32326E", +"dg c #1B1B33", +"dh c #1E1E2C", +"di c #30306C", +"dj c #40407F", +"dk c #292944", +"dl c #212150", +"dm c #141422", +"dn c #323271", +"do c #2D2D76", +"dp c #2E2E6D", +"dq c #21213F", +"dr c #8080BA", +"ds c #23232D", +"dt c #25255A", +"du c #35356D", +"dv c #191937", +"dw c #262651", +"dx c #313169", +"dy c #2C2C6E", +"dz c #22224D", +"e` c #18182C", +"ea c #373786", +"eb c #232344", +"ec c #2B2B63", +"ed c #292961", +"ee c #202037", +"ef c #1C1C33", +"eg c #242452", +"eh c #45456F", +"ei c #535380", +"ej c #1F1F43", +"ek c #2C2C5D", +"el c #3535DD", +"em c #262657", +"en c #393963", +"eo c #242455", +/* pixels */ +"``````````````cycyapbgcbcybg````````````", +"``````````dacycsehcsehapehcsddcj````````", +"````````au`cenbraseicibucicibrendd``````", +"``````auau`ccacidudrbpdrcfcrarakau`p````", +"`````p`lbx`nbhbfdxcobpcodjdu`sakalb`bd``", +"`````zbybxbocicgbvbbdn`ydbdfbfekbxbybe``", +"``dh`r`rbl`faidydndn`hd`dnbtecafakdwah`o", +"``dhdqejcqajdfcg`meacu`hbqdfdibi`jblbndh", +"``ch`rbxemaidudnbq`geldcbqdbdn`jafbxbnav", +"``dm`x`bdxdxcwbqdycpdocxdcbvedbkcqalebdg", +"```uccctdzbsag`qbqdpeacxbtaidiagekdwcvdm", +"``dmcl`xeoandtdfbv`wdjcediecbiaydectatch", +"``amdvcm`xaf`kagaodi`qdbbaecanazejdvdv`u", +"````e``xcvandlcqckdtcgagcq`qaqay`tbjef``", +"````dsclaxbwdzdebsckb`acegbjeg`eaaadds``", +"``````eeeeejbzanegdw`abmdl`b`rcnavaw````", +"````````eeczbc`b`dby`dbya``eae`iaw``````", +"``````````bdawa`dkc`aeae`i`i`vab````````", +"``````````````bd`pcdcdbdcdbd````````````", +"````````````````````````````````````````" +}; +/* XPM */ +static char *glass5[] = { +/* width height ncolors chars_per_pixel */ +"24 24 164 2", +/* colors */ +"`` c None", +"`a c #27274E", +"`b c #25254C", +"`c c #383858", +"`d c #23234A", +"`e c #212148", +"`f c #2E2E62", +"`g c #292967", +"`h c #3535A1", +"`i c #272751", +"`j c #23234D", +"`k c #29293F", +"`l c #2C2C63", +"`m c #2A2A61", +"`n c #33334C", +"`o c #272754", +"`p c #414188", +"`q c #20202C", +"`r c #2E2E3D", +"`s c #1C1C28", +"`t c #2E2E68", +"`u c #242447", +"`v c #2C2C66", +"`w c #181824", +"`x c #25253E", +"`y c #161622", +"`z c #B9B9ED", +"a` c #3E3E67", +"aa c #1C1C3F", +"ab c #6767A3", +"ac c #2B2B47", +"ad c #222248", +"ae c #292931", +"af c #29295C", +"ag c #252544", +"ah c #1E1E47", +"ai c #2B2B61", +"aj c #29295F", +"ak c #1F1F3E", +"al c #2F2F68", +"am c #2D2D66", +"an c #30305F", +"ao c #2C2C5B", +"ap c #11111C", +"aq c #262655", +"ar c #31316D", +"as c #4C4C6D", +"at c #323264", +"au c #2D2D69", +"av c #33335B", +"aw c #212146", +"ax c #37374B", +"ay c #22223D", +"az c #252536", +"b` c #1D1D42", +"ba c #28285A", +"bb c #2B2B53", +"bc c #333372", +"bd c #2F2F6E", +"be c #2C2C36", +"bf c #424266", +"bg c #232337", +"bh c #2F2FB0", +"bi c #34346C", +"bj c #525265", +"bk c #32326A", +"bl c #1B1B2F", +"bm c #3B3B55", +"bn c #303068", +"bo c #21214C", +"bp c #2C2C64", +"bq c #292957", +"br c #26264A", +"bs c #202044", +"bt c #5D5D97", +"bu c #2B2B5C", +"bv c #363674", +"bw c #3C3C66", +"bx c #252556", +"by c #30306E", +"bz c #3E3E54", +"c` c #2C2C6A", +"ca c #25252E", +"cb c #27275B", +"cc c #363663", +"cd c #4C4C68", +"ce c #20204A", +"cf c #2E2E5B", +"cg c #29294C", +"ch c #242451", +"ci c #27274A", +"cj c #343464", +"ck c #252548", +"cl c #16162C", +"cm c #292938", +"cn c #333384", +"co c #3C3C6F", +"cp c #353572", +"cq c #1E1E37", +"cr c #38386B", +"cs c #414156", +"ct c #242454", +"cu c #31316E", +"cv c #181831", +"cw c #232349", +"cx c #272739", +"cy c #4C4C85", +"cz c #2F2F83", +"d` c #28285B", +"da c #292952", +"db c #48486D", +"dc c #23234C", +"dd c #37377A", +"de c #1E1E3D", +"df c #26265C", +"dg c #313174", +"dh c #4C4C60", +"di c #27273F", +"dj c #3C3C78", +"dk c #48485C", +"dl c white", +"dm c #383874", +"dn c #333379", +"do c #444458", +"dp c #272756", +"dq c #1B1B33", +"dr c #1E1E2C", +"ds c #30306C", +"dt c #40407F", +"du c #292944", +"dv c #212150", +"dw c #23233E", +"dx c #343473", +"dy c #323271", +"dz c #2D2D76", +"e` c #2E2E6D", +"ea c #40406E", +"eb c #21213F", +"ec c #8080BA", +"ed c #23232D", +"ee c #25255A", +"ef c #35356D", +"eg c #191937", +"eh c #262651", +"ei c #313169", +"ej c #2C2C6E", +"ek c #22224D", +"el c #18182C", +"em c #373786", +"en c #2D2D65", +"eo c #232344", +"ep c #2B2B63", +"eq c #292961", +"er c #27275F", +"es c #1C1C33", +"et c #242452", +"eu c #45456F", +"ev c #484868", +"ew c #1F1F43", +"ex c #2C2C5D", +"ey c #3535DD", +"ez c #262657", +"f` c #393963", +"fa c #242455", +/* pixels */ +"``````````````````dkdhbjbjbjbjdh````````````````", +"``````````````csasascdevcdascddbevdh````````````", +"``````````dodobfa`dbeubfeueueacrbfbfcsax````````", +"````````bzcsbwf`bwcrbicobteccratcof`bmbzbz``````", +"```````n`navavanefcjbibt`zcrcobicratccf``nax````", +"``````acbbao`oat`fambycobtdldjbkbialan`can`n````", +"````dicg`icj`fbi`fefdyauarabbybiefbnaicfbbcg`x``", +"````ac`udcbqenbk`tdyabczdgdxdmdtbpcpcjeicwcgcq``", +"```wdq`acfaiefcpe`bydn`hcyeydmc`ambcef`fcf`u`y`s", +"```ydudaandfbnaubvdgerbhdd`h`pdyc`cu`tezcf`b`ubl", +"``elad`abqezbndmdsbccncnczeydnbvdmdxamep`fcgcv`w", +"```weoetdv`leidfdd`gbddzdzdncncneqeebpexan`ucvap", +"``elcwdaexehd`epaubd`hdz`hcz`gdycucueeba`oekcl`w", +"``eldebsdcbxfaeedmejcuemdtcnbdbyalafambuet`bdq`w", +"```yclakboce`fbx`mcper`veccyauei`mbncbaqdpdaesap", +"````clakegbsceetbxdsdjdt`zbt`tctajdvafahakayel``", +"````eldqdeebetboenepetezbnbxencb`lbaeteoaabldr``", +"``````blakb`ceetekambxctbbafezctdcbo`eew`xcq````", +"``````ed`qakbsawekchchchetd``jboceaddwcxesed````", +"````````cmazag`xdcek`bchctetbrci`deocqbg`q``````", +"```````````qbgayckaybr`uacek`beo`x`xazca````````", +"``````````````aecxdi`kagacag`xcxcxcm````````````", +"``````````````````ca`rcmbebebeae````````````````", +"````````````````````````````````````````````````" +}; +/* XPM */ +static char *glass6[] = { +/* width height ncolors chars_per_pixel */ +"30 30 181 2", +/* colors */ +"`` c None", +"`a c #27274E", +"`b c #25254C", +"`c c #383858", +"`d c #23234A", +"`e c #212148", +"`f c #2E2E62", +"`g c #3535A1", +"`h c #23234D", +"`i c #29293F", +"`j c #2C2C63", +"`k c #2A2A61", +"`l c #33334C", +"`m c #353579", +"`n c #272754", +"`o c #20202C", +"`p c #2E2E3D", +"`q c #1C1C28", +"`r c #2E2E68", +"`s c #242447", +"`t c #2C2C66", +"`u c #222245", +"`v c #181824", +"`w c #25253E", +"`x c #161622", +"`y c #B9B9ED", +"`z c #3E3E67", +"a` c #1C1C3F", +"aa c #6767A3", +"ab c #2B2B47", +"ac c #272743", +"ad c #292931", +"ae c #29295C", +"af c #1D1D39", +"ag c #252544", +"ah c #1E1E47", +"ai c #2B2B61", +"aj c #29295F", +"ak c #1F1F3E", +"al c #2F2F68", +"am c #2D2D66", +"an c #30305F", +"ao c #2C2C5B", +"ap c #11111C", +"aq c #262655", +"ar c #31316D", +"as c #4C4C6D", +"at c #222251", +"au c #323264", +"av c #2D2D69", +"aw c #33335B", +"ax c #43436E", +"ay c #2B2B67", +"az c #212146", +"b` c #37374B", +"ba c #22223D", +"bb c #252536", +"bc c #1D1D42", +"bd c #28285A", +"be c #2B2B53", +"bf c #333372", +"bg c #2F2F6E", +"bh c #2C2C36", +"bi c #424266", +"bj c #232337", +"bk c #2F2FB0", +"bl c #34346C", +"bm c #525265", +"bn c #32326A", +"bo c #1B1B2F", +"bp c #3B3B55", +"bq c #303068", +"br c #21214C", +"bs c #2C2C64", +"bt c #292957", +"bu c #232351", +"bv c #26264A", +"bw c #2F2F60", +"bx c #202044", +"by c #5D5D97", +"bz c #2B2B5C", +"c` c #363674", +"ca c #3C3C66", +"cb c #252556", +"cc c #30306E", +"cd c #3E3E54", +"ce c #414178", +"cf c #2C2C6A", +"cg c #2F2F4F", +"ch c #25252E", +"ci c #27275B", +"cj c #363663", +"ck c #4C4C68", +"cl c #20204A", +"cm c #2E2E5B", +"cn c #29294C", +"co c #242451", +"cp c #27274A", +"cq c #343464", +"cr c #4F4F64", +"cs c #252548", +"ct c #16162C", +"cu c #292938", +"cv c #333384", +"cw c #3C3C6F", +"cx c #353572", +"cy c #1E1E37", +"cz c #38386B", +"d` c #414156", +"da c #242454", +"db c #31316E", +"dc c #181831", +"dd c #232349", +"de c #272739", +"df c #393979", +"dg c #4C4C85", +"dh c #2F2F83", +"di c #28285B", +"dj c #292952", +"dk c #36366C", +"dl c #48486D", +"dm c #23234C", +"dn c #37377A", +"do c #20203F", +"dp c #1E1E3D", +"dq c #26265C", +"dr c #313174", +"ds c #4C4C60", +"dt c #27273F", +"du c #3C3C78", +"dv c #48485C", +"dw c white", +"dx c #383874", +"dy c #333379", +"dz c #444458", +"e` c #272756", +"ea c #47477C", +"eb c #32326E", +"ec c #1E1E2C", +"ed c #30306C", +"ee c #40407F", +"ef c #292944", +"eg c #212150", +"eh c #23233E", +"ei c #141422", +"ej c #343473", +"ek c #323271", +"el c #2D2D76", +"em c #2E2E6D", +"en c #40406E", +"eo c #21213F", +"ep c #272731", +"eq c #8080BA", +"er c #23232D", +"es c #25255A", +"et c #1B1B39", +"eu c #35356D", +"ev c #191937", +"ew c #262651", +"ex c #313169", +"ey c #2C2C6E", +"ez c #22224D", +"f` c #18182C", +"fa c #373786", +"fb c #2D2D65", +"fc c #232344", +"fd c #2B2B63", +"fe c #292961", +"ff c #27275F", +"fg c #202037", +"fh c #1C1C33", +"fi c #242452", +"fj c #45456F", +"fk c #484868", +"fl c #535380", +"fm c #1F1F43", +"fn c #2C2C5D", +"fo c #353573", +"fp c #262657", +"fq c #393963", +"fr c #242455", +/* pixels */ +"````````````````````````bmbmbmbmbmbmbm``````````````````````", +"``````````````````dscrasasascrckasasasfkckbm````````````````", +"````````````````dsdsdzbifjfjfjfjaxaxfjfjckdzdv``````````````", +"````````````d`dvfqdzenfkfjencaendlaxaxcabibi`zdvb```````````", +"``````````cd`zaw`cfqcacaceflczbydg`zencjcwca`cbpbpcd````````", +"````````d`cdb``cawcqczdkeubycwbyczdwcwczcqaucaawb`b`b```````", +"````````b``lcmcqaoczaublbndgeqdfeqczdgbn`jcmanfnawcg`l``````", +"``````cu`w`wcmcmcqblardxeu`yceareqdueualbleuexdjcmbeba`p````", +"````chabcg`acmbwbqczaiebcfdfdgekeqdudxebcxblbncmcm`ababjer``", +"`````o`aeodmaobdalbn`rcfdf`mdhdrdyeaejdubscxffbwbwdd`b`w`q``", +"````fhbadjcmbq`jcxcxekemeydr`gdy`geeekek`t`rexe`e``ndjdcdc``", +"```q`veocnbtdialbleb`rfo`medfadnelbkc`bffeedeufn`jcmfmbvfg`x", +"``ecbo`sbze`feaeayexavbgej`gbkdyeydhdudnemdbfdal`kfna``udc`v", +"```xeieodjbtfpexfbc`avekbg`gbkelfa`g`gdxcxcfdxamfpbtcpfcdoap", +"```vcya`btegex`kbldqdncfeycvdyelcv`gdycvfefeebaedianfmfcdc`q", +"``fhcyetahfncobdbs`tbncfdybgcf`gdhcfavavav`tfraifnbtbteteoei", +"```xdpaz`bbtcl`fesfbedfdekelbkdhaaavbgcf`jfe`fesbwez`bbxdcei", +"```xfhdcbx`hfratbresfdedcfee`meedffded`t`tbqdiaee``nazazdcap", +"`````vdp`sew`bbqaifpfpdbbsccdxdfekbyee`j`jdialbzfidmazafct``", +"`````vbodpevbcaqbdatcb`tfdamar`ydg`taicbaje`dadaahaketevbo``", +"`````qf`bjakdobdezegfbaidacibncxdgbddiajalatfibz`ubccyfh`q``", +"``````chbjbcbcfmbdaediatcbfpfpajfpdaesfpbudmco`h`eewfhf`````", +"`````````ocydp`waz`e`baqfiesfpdjfpfiaidacpewah`wafdpbb``````", +"````````chfgfgfmddcofibdfi`bfi`ada`hegbu`h`seodtbafhec``````", +"``````````cuepdo`wefdmfidd`b`hdae``bbvcn`dagakbabj`o````````", +"````````````erbbdeefcsefcpabezcp`habef`sbx`wehbber``````````", +"````````````````chbbba`ief`iacagabef`i`wba`wcu``````````````", +"``````````````````chbb`p`p`w`w`pcu`p`icucuch````````````````", +"````````````````````````adadcudeepadbh``````````````````````", +"````````````````````````````````````````````````````````````" +}; +/* XPM */ +static char *glass7[] = { +/* width height ncolors chars_per_pixel */ +"36 36 187 2", +/* colors */ +"`` c None", +"`a c #27274E", +"`b c #25254C", +"`c c #383858", +"`d c #23234A", +"`e c #212148", +"`f c #2E2E62", +"`g c #292967", +"`h c #3535A1", +"`i c #272751", +"`j c #23234D", +"`k c #29293F", +"`l c #2C2C63", +"`m c #2A2A61", +"`n c #33334C", +"`o c #353579", +"`p c #272754", +"`q c #414188", +"`r c #20202C", +"`s c #2E2E3D", +"`t c #1C1C28", +"`u c #2E2E68", +"`v c #242447", +"`w c #2C2C66", +"`x c #222245", +"`y c #181824", +"`z c #25253E", +"a` c #161622", +"aa c #B9B9ED", +"ab c #3E3E67", +"ac c #1C1C3F", +"ad c #6767A3", +"ae c #2B2B47", +"af c #272743", +"ag c #222248", +"ah c #292931", +"ai c #29295C", +"aj c #1D1D39", +"ak c #252544", +"al c #1E1E47", +"am c #2B2B61", +"an c #29295F", +"ao c #1F1F3E", +"ap c #2F2F68", +"aq c #2D2D66", +"ar c #30305F", +"as c #2C2C5B", +"at c #11111C", +"au c #262655", +"av c #31316D", +"aw c #4C4C6D", +"ax c #222251", +"ay c #323264", +"az c #2D2D69", +"b` c #33335B", +"ba c #43436E", +"bb c #2B2B67", +"bc c #212146", +"bd c #37374B", +"be c #22223D", +"bf c #252536", +"bg c #1D1D42", +"bh c #2A2A5C", +"bi c #28285A", +"bj c #2B2B53", +"bk c #333372", +"bl c #2F2F6E", +"bm c #2B2B3F", +"bn c #2C2C36", +"bo c #424266", +"bp c #232337", +"bq c #2F2FB0", +"br c #34346C", +"bs c #525265", +"bt c #32326A", +"bu c #1B1B2F", +"bv c #3B3B55", +"bw c #303068", +"bx c #21214C", +"by c #2C2C64", +"bz c #292957", +"c` c #232351", +"ca c #26264A", +"cb c #2F2F60", +"cc c #202044", +"cd c #5D5D97", +"ce c #2B2B5C", +"cf c #363674", +"cg c #3C3C66", +"ch c #252556", +"ci c #30306E", +"cj c #3E3E54", +"ck c #414178", +"cl c #2C2C6A", +"cm c #2F2F4F", +"cn c #25252E", +"co c #27275B", +"cp c #363663", +"cq c #4C4C68", +"cr c #20204A", +"cs c #2E2E5B", +"ct c #29294C", +"cu c #242451", +"cv c #27274A", +"cw c #343464", +"cx c #4F4F64", +"cy c #252548", +"cz c #16162C", +"d` c #292938", +"da c #333384", +"db c #3C3C6F", +"dc c #353572", +"dd c #1E1E37", +"de c #38386B", +"df c #414156", +"dg c #242454", +"dh c #31316E", +"di c #181831", +"dj c #232349", +"dk c #272739", +"dl c #393979", +"dm c #4C4C85", +"dn c #2F2F83", +"do c #28285B", +"dp c #292952", +"dq c #48486D", +"dr c #23234C", +"ds c #37377A", +"dt c #1E1E3D", +"du c #26265C", +"dv c #313174", +"dw c #4C4C60", +"dx c #27273F", +"dy c #3C3C78", +"dz c #48485C", +"e` c white", +"ea c #383874", +"eb c #333379", +"ec c #444458", +"ed c #272756", +"ee c #47477C", +"ef c #32326E", +"eg c #1B1B33", +"eh c #1E1E2C", +"ei c #30306C", +"ej c #40407F", +"ek c #292944", +"el c #212150", +"em c #23233E", +"en c #141422", +"eo c #343473", +"ep c #323271", +"eq c #2D2D76", +"er c #2E2E6D", +"es c #40406E", +"et c #21213F", +"eu c #272731", +"ev c #8080BA", +"ew c #23232D", +"ex c #25255A", +"ey c #1B1B39", +"ez c #35356D", +"f` c #191937", +"fa c #262651", +"fb c #313169", +"fc c #2C2C6E", +"fd c #22224D", +"fe c #18182C", +"ff c #373786", +"fg c #2D2D65", +"fh c #232344", +"fi c #2B2B63", +"fj c #292961", +"fk c #27275F", +"fl c #202037", +"fm c #1C1C33", +"fn c #242452", +"fo c #45456F", +"fp c #484868", +"fq c #535380", +"fr c #1F1F43", +"fs c #2C2C5D", +"ft c #3535DD", +"fu c #353573", +"fv c #262657", +"fw c #393963", +"fx c #242455", +/* pixels */ +"````````````````````````````````bsbsbsdwbs``````````````````````````````", +"````````````````````````dwbsdwcqcxbscqdwcqcxdzcxbs``````````````````````", +"````````````````````fpcxawcqawcqawawcqawfocqcqawfpcqcx``````````````````", +"``````````````````ececfpfpbofodqdqdqesbababadqfobafpeccj````````````````", +"``````````````dfeccjabcgesbobaabadcgabbaeefobaesbob`cgdfcjcj````````````", +"````````````cjdfbvcgfwfwcgcgesbrevdbcdeeesdedbfwdbcgcpbvbvdfcj``````````", +"``````````bdbvbvcg`ccpcwdecwayckcdeecddydcbrezdecpayfwb`ar`ncjbd````````", +"```````````saecmcscpcscwbwaqayeaevfqdyckbtdefbcpeicscbcscpb`cmae````````", +"`````````scvbjcmar`pcsfb`fbt`fcidmdecdcdefdyezaqbraz`farasasarek`s``````", +"``````bnaecmdjayb`fscsbwaqfbbwdyaacddheacdfudbfbbrbtfbaqbzcsdpafcmcn````", +"```````s`zbj`basfs`fbr`f`wdcepeqcfcdfue`dmdvcdbkbkbrfb`fbwbjcaaect`z````", +"`````taeaoccdrcsfdfgbwbr`ubb`oadebdndvebe`eadsejbyavfgcwbtcsdjbjaeddbf``", +"````eudidjbzdp`pbzbwbbefeperfjdabldadada`qcfdveofi`wfb`fay`ped`aeteg`k``", +"`````yflfadpcsfs`lbrdcav`wcfeoepdsda`qbqebdydsepfiaveabwbz`maybc`abufe``", +"````fmek`aararaiambwbyefcfcfbqfkeqejds`gft`qeofuclfkbw`ubibtcs`bcv`vfe``", +"```ydi`v`xdpbzamaxaqfkavererbkfffcfc`hdaeqdscffudcclbkfgapanayaodpczeg`t", +"``atbpao`adpbzdo`mfgbtepereperfcbqft`g`hffbqbkdlfucleiaqfbdg`bctfrfmfea`", +"```yetfh`xdpelfbfsfbaz`mdsci`gblffdneqftebda`hdafjfjfgbybwdgardr`xdia`at", +"``ateheycccredfsaxfgcibbeffjejdafc`g`heqblfjepclazazap`wfscbbz`jacfrflat", +"``atczey`v`afsacfsdgco`lbb`gebffereqft`qffdaer`wfgfifififjbzcu`i`adda`at", +"````a`dtcy`xdrcrexfxfvfgeabkbbdhffadejdndnblclepapdubhaqfvcefn`xdtegfe``", +"````a`dieybxfnbx`jfsfxfkfgfgdheoev`qdncdfcdlfjfi`wfiapcuchaubzaceydiat``", +"````atdifr`abz`bbzbranaifneifufidyckejepckffepfibyaianancu`bbgbgagegen``", +"````atczegeyf`bgascrcrelchanefdyfieaaa`qaq`uexduanbhfxaicecraoemajfea```", +"```````tfebedtccaled`dcoaqdoamdeaiandydyaifi`mfbaqfdfnbh`pagfrddfmfe````", +"```````t`reydidjagbzaxchanfnaianchch`lbhcoaichauc`chdoelbgbgbcegfm`r````", +"`````````reyaoacetcrfn`afd`ffvchc`fvbjaianfvco`bdrdgbz`e`vbe`zeyeg``````", +"```````````regacem`vccfnbxc`cu`jbifnfvcoc`bi`ich`adjac`xflajemew````````", +"``````````ewbpbpdtaobcbc`jchbic``ac``afafafnfd`jfncybcdxdkbedd`r````````", +"````````````d`ddbeakfh`kdrfd`b`b`jcudged`bcacvct`dcyccddewd``r``````````", +"``````````````eubndddxdxakaecvcaae`ecaagaecvafcabcfhbp`keucn````````````", +"``````````````````d`flem`z`s`v`kbc`bekaeagaeetafekd`bmbf````````````````", +"`````````````````````s`zdk`zae`kdxakaeekek`zekbfdkd`bn``````````````````", +"````````````````````````bnbmd`dkdk`sbndxd`bmbfbnah``````````````````````", +"````````````````````````````````cnbneu`sah``````````````````````````````", +"````````````````````````````````````````````````````````````````````````" +}; +/* XPM */ +static char *glass8[] = { +/* width height ncolors chars_per_pixel */ +"44 44 189 2", +/* colors */ +"`` c None", +"`a c #27274E", +"`b c #25254C", +"`c c #383858", +"`d c #23234A", +"`e c #212148", +"`f c #2E2E62", +"`g c #292967", +"`h c #3535A1", +"`i c #272751", +"`j c #23234D", +"`k c #29293F", +"`l c #2C2C63", +"`m c #2A2A61", +"`n c #33334C", +"`o c #353579", +"`p c #272754", +"`q c #414188", +"`r c #20202C", +"`s c #2E2E3D", +"`t c #1C1C28", +"`u c #2E2E68", +"`v c #242447", +"`w c #2C2C66", +"`x c #222245", +"`y c #181824", +"`z c #25253E", +"a` c #161622", +"aa c #B9B9ED", +"ab c #3E3E67", +"ac c #1C1C3F", +"ad c #6767A3", +"ae c #2B2B47", +"af c #272743", +"ag c #222248", +"ah c #292931", +"ai c #29295C", +"aj c #1D1D39", +"ak c #252544", +"al c #1E1E47", +"am c #2B2B61", +"an c #29295F", +"ao c #1F1F3E", +"ap c #2F2F68", +"aq c #2D2D66", +"ar c #30305F", +"as c #2C2C5B", +"at c #11111C", +"au c #262655", +"av c #31316D", +"aw c #4C4C6D", +"ax c #222251", +"ay c #323264", +"az c #2D2D69", +"b` c #33335B", +"ba c #43436E", +"bb c #2B2B67", +"bc c #212146", +"bd c #37374B", +"be c #22223D", +"bf c #252536", +"bg c #1D1D42", +"bh c #2A2A5C", +"bi c #28285A", +"bj c #2B2B53", +"bk c #333372", +"bl c #2F2F6E", +"bm c #2B2B3F", +"bn c #2C2C36", +"bo c #424266", +"bp c #232337", +"bq c #2F2FB0", +"br c #34346C", +"bs c #525265", +"bt c #32326A", +"bu c #1B1B2F", +"bv c #3B3B55", +"bw c #303068", +"bx c #21214C", +"by c #2C2C64", +"bz c #292957", +"c` c #232351", +"ca c #26264A", +"cb c #2F2F60", +"cc c #202044", +"cd c #5D5D97", +"ce c #2B2B5C", +"cf c #363674", +"cg c #3C3C66", +"ch c #252556", +"ci c #30306E", +"cj c #3E3E54", +"ck c #414178", +"cl c #2C2C6A", +"cm c #2F2F4F", +"cn c #25252E", +"co c #27275B", +"cp c #363663", +"cq c #4C4C68", +"cr c #20204A", +"cs c #2E2E5B", +"ct c #29294C", +"cu c #242451", +"cv c #27274A", +"cw c #343464", +"cx c #4F4F64", +"cy c #252548", +"cz c #16162C", +"d` c #292938", +"da c #333384", +"db c #3C3C6F", +"dc c #353572", +"dd c #1E1E37", +"de c #38386B", +"df c #414156", +"dg c #242454", +"dh c #31316E", +"di c #181831", +"dj c #232349", +"dk c #272739", +"dl c #393979", +"dm c #4C4C85", +"dn c #2F2F83", +"do c #28285B", +"dp c #292952", +"dq c #36366C", +"dr c #48486D", +"ds c #23234C", +"dt c #37377A", +"du c #20203F", +"dv c #1E1E3D", +"dw c #26265C", +"dx c #313174", +"dy c #4C4C60", +"dz c #27273F", +"e` c #3C3C78", +"ea c #48485C", +"eb c white", +"ec c #383874", +"ed c #333379", +"ee c #444458", +"ef c #272756", +"eg c #47477C", +"eh c #32326E", +"ei c #1B1B33", +"ej c #1E1E2C", +"ek c #30306C", +"el c #40407F", +"em c #292944", +"en c #212150", +"eo c #23233E", +"ep c #141422", +"eq c #343473", +"er c #323271", +"es c #2D2D76", +"et c #2E2E6D", +"eu c #40406E", +"ev c #21213F", +"ew c #272731", +"ex c #8080BA", +"ey c #23232D", +"ez c #25255A", +"f` c #1B1B39", +"fa c #35356D", +"fb c #191937", +"fc c #262651", +"fd c #313169", +"fe c #2C2C6E", +"ff c #22224D", +"fg c #18182C", +"fh c #373786", +"fi c #2D2D65", +"fj c #232344", +"fk c #2B2B63", +"fl c #292961", +"fm c #27275F", +"fn c #202037", +"fo c #1C1C33", +"fp c #242452", +"fq c #45456F", +"fr c #484868", +"fs c #535380", +"ft c #1F1F43", +"fu c #2C2C5D", +"fv c #3535DD", +"fw c #353573", +"fx c #262657", +"fy c #393963", +"fz c #242455", +/* pixels */ +"````````````````````````````````````````````bs``````````````````````````````````````````", +"````````````````````````````````dybseabsawbsbscxawcxbsdybs``````````````````````````````", +"````````````````````````````eedycqcqcqdrcxawcqawawawawfrfrcxcq``````````````````````````", +"````````````````````````eadyfrdybafrfqawawfqdrawawfrfrdrawcqeaeeee``````````````````````", +"````````````````````eeeebofrboawbofqdrbadrfqeufqfqbababafqfrbobobocjee``````````````````", +"``````````````````dfeebvfybvcgbaboeueueueuababfqdefqegeuabeufybocgdfeacj````````````````", +"````````````````bvbo`nfydffybocgcgdedbegfsfqeuegexeudbdqdedbdeabfybvcjdfcj``````````````", +"``````````````bdcjbvfyfyb`defyfydedbckexexebckdmaqdbdbdbayaydeaycpbvab`ccjbd````````````", +"`````````````s`ccjb`b`b`b`ardededeaydcexadckaddbdbaadqdqbrbtbrayb`cpb``c`ccm`n``````````", +"```````````n`n`ncmcsb`cpascpegfi`ucwbrcdcdebehaddbbrdmfaayaqcbb`arcscs`ccmb`ae`s````````", +"``````````aeafcmaeasfu`paraycbbtfd`lavecckegcdcdaaec`qfa`ufa`f`ubwarbzb`cscs`kbm````````", +"````````ewaectfjbzcsb`arcwbtdcapec`fdcaadmcd`ueqaddmekecav`fapbtecbwdparbjcmaoct`n``````", +"````````bddzcmbjdparcscb`fdbfdfidcdlcieqbbdlciebexeletegbwbk`ubtbwfufucsdpcm`zctbm``````", +"```````ycmdjdpctauaramefcsbwapehekereddleledcfdmdmdmerelecaqaqbrehcbbzarfc`vbjcyem`r````", +"``````bpaobefjccbzasenbw`ufafdblcl`oeldldnbqededdtcdbkdldlet`lekamcbbw`fbjauctdp`zfn````", +"`````yfoaj`bbzeodsfibhbrekavcfcletfldneddxeddadtdadmbkerercleh`ubwbwcbbzarbhdpfjdiei`t``", +"````atfoemfcdpbzasfi`ffadcekbkazeqerbkerdadtdmfhbqdldleddxfkfdapdcfdfcam`pbz`e`ifoepa```", +"````a`dd`v`bbzbjefdw`lbwbtehdceccf`hfeerbqfhedesbqfvdlcifwcifldhbrficbficsefcc`v`xajbp``", +"````fnfgeo`vfubzbwdwco`ufm`m`ucfbler`ofh`hfveddndnbqdldldtcffmbkbwapbwaiefaybgctczfgei``", +"`````yczacaodpbjayfxcobwapbkehdhblerdtdnfe`hbqfhbqfedtcfeqecaqeqbwfiapanbhbr`zdjbcaofo``", +"````atczf``bbzbzbhax`laqbwaqdhciblfeclfhfhdafmbqdabqdacidldtdhflcf`wby`fauef`vccakev`y``", +"``ata`fnagccbzenbhfiaifdehezdhdlet`geteddnbqesfvedbqesdndabbfmfmbtbyamfufuasbcccdidiepat", +"````fgfgao`dbg`e`falcobwfkfmdh`o`gcidnesdn`gdabqed`geteretblekazfk`u`fdocb`j`abgf`ev`y``", +"`````yeicv`v`b`pamfcbhfxfidwetazazdx`q`heted`qfveder`get`wciekehchcodgbhffefeffcczbu`y``", +"````epdvfjfj`acubzenanbifxbyaqci`w`gereleddnesehdnazdxbkcl`wfmfm`f`lfmayenau`bfceidia```", +"`````ybuev`xcc`j`pfzaxau`jezekcferblcifhfhdmdmdldtfmblekdhekaq`fbififzbzftbidudvdifgbu``", +"````atfgfoaobgal`pc`auamaxcoekapdcfwaqe`edeldnele`ekelfm`manapaqficubi`pdjfcacf`bgdvep``", +"`````ya`f`ag`bdpasbcfubraibifmfmdhcfanekdcdmdtdhflexblcifkbyfiaifian`pau`pagbgbceicza```", +"``````epdif`dubcefbgauenaxfmco`f`mecekfied`uavexfkbbaqfmdwanapcubifxffbgacftbef`di`y````", +"``````a`czbuf`ddddbcfffcfcdgdoancofdezbwecfkap`wehaifmbtfiandwaxenbibzagf`ccbpaj`t`y````", +"`````````yfoeyaceoevenfpffbx`mam`mbifpdwchapehaicocoamaibibtezfxdgfxeffjccfpeiddfg``````", +"````````ej`rdidvaobzalbzfp`mauchfpfkezfkau`f`fdechchchfzbic`axbxfpauff`ebg`pejej`t``````", +"```````````tf`f`ajal`zcrfpendsffaycochfzdgfzbjcoancofpdo`ben`affce`edjbcbebef`di````````", +"```````````t`rf`dvaoeobcdu`ece`bfpencucofxbic`auc`dgficuef`bbxffbg`ebedddvaobfew````````", +"````````````cnejbpaodvftdj`jcr`pcoen`j`jcu`ifcbifx`jc``jen`bbx`vccbe`z`zddddcn``````````", +"``````````````ewbpddfbddaccycr`dfp`jfpca`jcu`dc`cacv`dff`d`d`x`dft`z`zbeejcn````````````", +"````````````````fgfneoduembmfj`vag`act`bds`ac``j`j`acv`bbcagak`xdudvbpcn`t``````````````", +"``````````````````ewd`fnaeakemcyaecvdjaeaecrcvdsakaeakafcy`jao`zfnd`cn`t````````````````", +"````````````````````d`dkfndzd``zbm`v`k`b`ecvemaeca`vaedudz`zafew`kbfey``````````````````", +"````````````````````````bfdkd`dz`kafdzae`vemcyafakakaedzdzbed`dkcn``````````````````````", +"````````````````````````````ahdkbnbnbm`z`sdk`s`zd`bm`safd`bn`s``````````````````````````", +"````````````````````````````````bnbn`sd`d`dk`sbmbnah`s`sah``````````````````````````````", +"````````````````````````````````````````````cn``````````````````````````````````````````", +"````````````````````````````````````````````````````````````````````````````````````````" +}; +/* XPM */ +static char *glass9[] = { +/* width height ncolors chars_per_pixel */ +"50 50 188 2", +/* colors */ +"`` c None", +"`a c #27274E", +"`b c #25254C", +"`c c #383858", +"`d c #23234A", +"`e c #212148", +"`f c #2E2E62", +"`g c #292967", +"`h c #3535A1", +"`i c #272751", +"`j c #23234D", +"`k c #29293F", +"`l c #2C2C63", +"`m c #2A2A61", +"`n c #33334C", +"`o c #353579", +"`p c #272754", +"`q c #414188", +"`r c #20202C", +"`s c #2E2E3D", +"`t c #1C1C28", +"`u c #2E2E68", +"`v c #242447", +"`w c #2C2C66", +"`x c #222245", +"`y c #181824", +"`z c #25253E", +"a` c #161622", +"aa c #B9B9ED", +"ab c #3E3E67", +"ac c #1C1C3F", +"ad c #6767A3", +"ae c #2B2B47", +"af c #272743", +"ag c #222248", +"ah c #292931", +"ai c #29295C", +"aj c #1D1D39", +"ak c #252544", +"al c #1E1E47", +"am c #2B2B61", +"an c #29295F", +"ao c #1F1F3E", +"ap c #2F2F68", +"aq c #2D2D66", +"ar c #30305F", +"as c #2C2C5B", +"at c #11111C", +"au c #262655", +"av c #31316D", +"aw c #4C4C6D", +"ax c #222251", +"ay c #323264", +"az c #2D2D69", +"b` c #33335B", +"ba c #43436E", +"bb c #2B2B67", +"bc c #212146", +"bd c #37374B", +"be c #22223D", +"bf c #252536", +"bg c #1D1D42", +"bh c #2A2A5C", +"bi c #28285A", +"bj c #2B2B53", +"bk c #333372", +"bl c #2F2F6E", +"bm c #2B2B3F", +"bn c #2C2C36", +"bo c #424266", +"bp c #232337", +"bq c #2F2FB0", +"br c #34346C", +"bs c #525265", +"bt c #32326A", +"bu c #1B1B2F", +"bv c #3B3B55", +"bw c #303068", +"bx c #21214C", +"by c #292957", +"bz c #232351", +"c` c #26264A", +"ca c #2F2F60", +"cb c #202044", +"cc c #5D5D97", +"cd c #2B2B5C", +"ce c #363674", +"cf c #3C3C66", +"cg c #252556", +"ch c #30306E", +"ci c #3E3E54", +"cj c #414178", +"ck c #2C2C6A", +"cl c #2F2F4F", +"cm c #25252E", +"cn c #27275B", +"co c #363663", +"cp c #4C4C68", +"cq c #20204A", +"cr c #2E2E5B", +"cs c #29294C", +"ct c #242451", +"cu c #27274A", +"cv c #343464", +"cw c #4F4F64", +"cx c #252548", +"cy c #16162C", +"cz c #292938", +"d` c #333384", +"da c #3C3C6F", +"db c #353572", +"dc c #1E1E37", +"dd c #38386B", +"de c #414156", +"df c #242454", +"dg c #31316E", +"dh c #181831", +"di c #232349", +"dj c #272739", +"dk c #393979", +"dl c #4C4C85", +"dm c #2F2F83", +"dn c #28285B", +"do c #292952", +"dp c #36366C", +"dq c #48486D", +"dr c #23234C", +"ds c #37377A", +"dt c #20203F", +"du c #1E1E3D", +"dv c #26265C", +"dw c #313174", +"dx c #4C4C60", +"dy c #27273F", +"dz c #3C3C78", +"e` c #48485C", +"ea c white", +"eb c #383874", +"ec c #333379", +"ed c #444458", +"ee c #272756", +"ef c #47477C", +"eg c #32326E", +"eh c #1B1B33", +"ei c #1E1E2C", +"ej c #30306C", +"ek c #40407F", +"el c #292944", +"em c #212150", +"en c #23233E", +"eo c #141422", +"ep c #343473", +"eq c #323271", +"er c #2D2D76", +"es c #2E2E6D", +"et c #40406E", +"eu c #21213F", +"ev c #272731", +"ew c #8080BA", +"ex c #23232D", +"ey c #25255A", +"ez c #1B1B39", +"f` c #35356D", +"fa c #191937", +"fb c #262651", +"fc c #313169", +"fd c #2C2C6E", +"fe c #22224D", +"ff c #18182C", +"fg c #373786", +"fh c #2D2D65", +"fi c #232344", +"fj c #2B2B63", +"fk c #292961", +"fl c #27275F", +"fm c #202037", +"fn c #1C1C33", +"fo c #242452", +"fp c #45456F", +"fq c #484868", +"fr c #535380", +"fs c #1F1F43", +"ft c #2C2C5D", +"fu c #3535DD", +"fv c #353573", +"fw c #262657", +"fx c #393963", +"fy c #242455", +/* pixels */ +"````````````````````````````````````````````````````````````````````````````````````````````````````", +"``````````````````````````````````````e`bscwbscwbsbsbsbsbsbsbscw````````````````````````````````````", +"````````````````````````````````bse`bscpbse`awawcwbsbsdqawawbsdxdxcwcw``````````````````````````````", +"````````````````````````````e`eddxfqcwcpfqfqawawdqawdqawawfqcwawawfqfqe`cw``````````````````````````", +"````````````````````````cie`e`dxfqboboawfpfpdqfpbafpawfpdqbofpabdqfqfqedcfdee```````````````````````", +"``````````````````````edede`cifqbodqabfpfpbabobaccbabafpbaddbaetfpfqabbobobodee`````````````````````", +"````````````````````deedbvbvfxfxcfetboetfpcfewetddetetdaefetbaetabetbofxabcfedcici``````````````````", +"``````````````````bdedbd`cabdefxababfxddetddcccjefbacjeaetddddcfdpdaddababb``cdeedde````````````````", +"````````````````bvbdbvfx`cb`fxcfcffxdddaddefccaaeaefewbwdldadaddcoayddcvcfb``cbvbdbvci``````````````", +"```````````````s`cbvbdb`b`b`cocvdddaddayf`braadlfrccdldzewdddaebddfcbwayfxcfb``cbd`cbd`s````````````", +"````````````bd`sclclbjb`crb`arcofr`ubtbtfcdkaaewewdlcjdabtdabtcvddebayaycadoarb``c`n`ncl`s``````````", +"``````````bdbv`c`ccub`b`b`ascrdp`fcadzaqbwfjebcjeaccewaaccdlfrdlegbw`f`lcab`crcrcrclclelbpbd````````", +"``````````bnbmcuclclcrb``pararcv`ff`fcegf`dzewcjcjeqdleabkavf`fc`mbrcaegfcaycabjararcrae`sbm````````", +"````````evaedycragcacvb`apcrasbwf``faybtavekewaddleqdkccccdkbrdzfcavapbrfhf`biascac`bjcuel`kbf``````", +"````````aeae`vcldo`acrcacr`fbtddaqapebceckbleqdzdseqaaadekdwebdkavceapbrbt`fftamcrbybjaeclbpbp``````", +"```````rfnbeakdocubzarfw`faiarbraqegejbkcheqeqekd``oefekewdzchekbkaqfhbtbkapcrcacr`j`vdocbbpfn`t````", +"``````cz`zdoakbccbbyasdr`fap`uf`fcejck`obkdl`odmfudwecdwaadzbkdzdbaz`legaqftar`fcadofbdobjafdccm````", +"``````bfehdc`aeefifbftaiambw`gavbkblck`gckd`eqecec`hfgd`addsepbkfvfkapazavf`fw`fbycrcd`a`vehbubp````", +"`````tbuehdyfbasdocaapayayebebbteq`geqchfvdwecbqdkaddsfudwdzbkckdwfjbrapf`bwf`byfwbyasdr`iezbucy`t``", +"`````yfnfieu`bdi`abydn`mfcf`f`egdbavdbec`odwcefgecdsd`dmbqepceeqf`az`wejdbbrambi`lcdft`bcbc``va`ei``", +"````a`eoenfifsaycrbyfl`mfc`uan`webceebdmer`gdwbqdsdsdmdmbqekdkeccechckfkejegfhbiftarby`a`v`vfiffbu``", +"````fmcycxdidt`iardpdnemanavflejazeqesepcefgblerfud`fgfderfgdkdsdkdzfkeqbkapapbt`lctfceuas`vcydhfn``", +"````ehdheudtagbybjcabidnapapfcebejblchcheqer`hbqbqerbqfufgecdsebcedkbkbleqf`fjambicaaycu`vcxa`du`y``", +"````fnfndhdtbgdobybifocnbwameqckdgeqeqfdesfdfgfgdwflfddmfufudwch`odschflejebdvayby`pee`vcbacfndcbu``", +"````bube`vacfe`iembyfc`f`ufc`wdveqdkeqflfddwfudm`her`hd`fgbqecd`ecbbflfkfjapdvbwdnftas`jfifieh`yeo``", +"````ffehdhdhdrcqalft`jembtai`wfkdg`obbesbldmfddm`gecfud`dmbbdw`ochbl`ufkap`weganaiar`j`j`ddu`adhff``", +"````ffdcdrdtbj`a`pfhfebibh`legfkesapaqeq`obqbqfddkfu`hd`dwfkchdw`wcheq`ufjemfyaucdby`peectduezdhbu``", +"`````tfadhag`v`iee`fcqfweefleyanaqfjazazebfg`g`qfu`hadcher`q`h`gazdwaibbap`lfw`waybxct`aagcbeueofn``", +"````eoa`ffcbfididr`eaxeybzbhcgaqepdlbkckazeqds`qfueqfdblefeqdzchdg`wfheyamey`laibyalbiagdraodheheo``", +"````at`ydhdh`dfsal`pfyalfyemeyey`waqdgazckepbkdw`qekepecfjdmejflazfj`ubw`lbiftaxee`beecbcbbcdu`ta```", +"````a`a`a`ficbalcqeeauct`fcgdffyflejapds`wefdleradewegaaegeseqbr`lfl`u`megamamctfb`vfebc`deudceoat``", +"``````eofffacb`abyftcbbybtfcanfwaidvapepap`wegazdzdlek`uerfgepdgfj`laqdncn`mbyfoct`p`vbgacezdhbu````", +"```````yffdhfsficbeealbybxbiemcncnamflch`u`uccew`udgdlf``wdldbcgflanbweefycnaxeeacezfsdyfmdh`y`t````", +"```````teoeiezajdcdc`ealeeai`jaxaiamcgavaiew`ucc`w`mandzanebflfcamfldvbiemdffw`pfeezcbdcbpeh`yeo````", +"`````````tfffffmaoakdtalamfbdremfjamaiaidffraiddegdbfhancnbrdn`mamegfwaxfocgftct`x`efeezeifn`t``````", +"````````ex`tehbeezdubydialcdaxcnbidndfbhfwbweydf`mandfcgdvananfyfofycncgcnaxfoacbg`e`pfadueiex``````", +"```````````rbufndcajacfscbbycqfofodnaifhfyai`paxcnfweyddcg`pcgfwfofedifeaxbyalfs`j`kduehfmfm````````", +"```````````yeifndhbefsao`vaxbxbxcsfebyfwbzfybidfcgbjfwaidnambibybzbx`afocdbc`vfidtezajbueha`````````", +"`````````````y`r`rezduaocxficb`jfw`abz`jct`jdnfwbzfwdnaufofofw`afo`i`ddiducb`zdudcezdu`rex``````````", +"``````````````evbudjfmajcbagbcctbcfwcgaufoct`afofb`afodf`jbzemfobx`dfe`val`xczdjbebpdccm````````````", +"````````````````evcmezfneufsaoelcqcxctfeaufecsfectbxbzfeae`b`jdrc``b`x`ecb`zbpfmfmeiev``````````````", +"``````````````````ffbubpfiafafbmbc`vag`bc`csdr`j`bct`jfefbcxcx`j`xdificxacbeenbfev`t````````````````", +"````````````````````cmczczdy`zak`kcucucudrcuaecxc`cxdrcxaeelak`vc``jajakbpafbfbf`r``````````````````", +"``````````````````````cmczbpdjdc`kcxelaoelakagbc`aaeel`bbxakakeu`zdtbm`zdjbpevbf````````````````````", +"````````````````````````cmbfeibfbmeuel`kelelafelelakaeelaf`k`k`zdjbebm`zbncmah``````````````````````", +"````````````````````````````czbnczbp`zafbmaedyafelbmdy`zdybeczdjczbf`kbpex``````````````````````````", +"`````````````````````````````````sevdjbncz`zdj`sczcz`k`k`s`sdjbfahevbn``````````````````````````````", +"``````````````````````````````````````evah`sbncz`kev`sbnczbnczah````````````````````````````````````", +"````````````````````````````````````````````````````````````````````````````````````````````````````", +"````````````````````````````````````````````````````````````````````````````````````````````````````" +}; +/* XPM */ +static char *glass10[] = { +/* width height ncolors chars_per_pixel */ +"60 60 189 2", +/* colors */ +"`` c None", +"`a c #27274E", +"`b c #25254C", +"`c c #383858", +"`d c #23234A", +"`e c #212148", +"`f c #2E2E62", +"`g c #292967", +"`h c #3535A1", +"`i c #272751", +"`j c #23234D", +"`k c #29293F", +"`l c #2C2C63", +"`m c #2A2A61", +"`n c #33334C", +"`o c #353579", +"`p c #272754", +"`q c #414188", +"`r c #20202C", +"`s c #2E2E3D", +"`t c #1C1C28", +"`u c #2E2E68", +"`v c #242447", +"`w c #2C2C66", +"`x c #222245", +"`y c #181824", +"`z c #25253E", +"a` c #161622", +"aa c #B9B9ED", +"ab c #3E3E67", +"ac c #1C1C3F", +"ad c #6767A3", +"ae c #2B2B47", +"af c #272743", +"ag c #222248", +"ah c #292931", +"ai c #29295C", +"aj c #1D1D39", +"ak c #252544", +"al c #1E1E47", +"am c #2B2B61", +"an c #29295F", +"ao c #1F1F3E", +"ap c #2F2F68", +"aq c #2D2D66", +"ar c #30305F", +"as c #2C2C5B", +"at c #11111C", +"au c #262655", +"av c #31316D", +"aw c #4C4C6D", +"ax c #222251", +"ay c #323264", +"az c #2D2D69", +"b` c #33335B", +"ba c #43436E", +"bb c #2B2B67", +"bc c #212146", +"bd c #37374B", +"be c #22223D", +"bf c #252536", +"bg c #1D1D42", +"bh c #2A2A5C", +"bi c #28285A", +"bj c #2B2B53", +"bk c #333372", +"bl c #2F2F6E", +"bm c #2B2B3F", +"bn c #2C2C36", +"bo c #424266", +"bp c #232337", +"bq c #2F2FB0", +"br c #34346C", +"bs c #525265", +"bt c #32326A", +"bu c #1B1B2F", +"bv c #3B3B55", +"bw c #303068", +"bx c #21214C", +"by c #2C2C64", +"bz c #292957", +"c` c #232351", +"ca c #26264A", +"cb c #2F2F60", +"cc c #202044", +"cd c #5D5D97", +"ce c #2B2B5C", +"cf c #363674", +"cg c #3C3C66", +"ch c #252556", +"ci c #30306E", +"cj c #3E3E54", +"ck c #414178", +"cl c #2C2C6A", +"cm c #2F2F4F", +"cn c #25252E", +"co c #27275B", +"cp c #363663", +"cq c #4C4C68", +"cr c #20204A", +"cs c #2E2E5B", +"ct c #29294C", +"cu c #242451", +"cv c #27274A", +"cw c #343464", +"cx c #4F4F64", +"cy c #252548", +"cz c #16162C", +"d` c #292938", +"da c #333384", +"db c #3C3C6F", +"dc c #353572", +"dd c #1E1E37", +"de c #38386B", +"df c #414156", +"dg c #242454", +"dh c #31316E", +"di c #181831", +"dj c #232349", +"dk c #272739", +"dl c #393979", +"dm c #4C4C85", +"dn c #2F2F83", +"do c #28285B", +"dp c #292952", +"dq c #36366C", +"dr c #48486D", +"ds c #23234C", +"dt c #37377A", +"du c #20203F", +"dv c #1E1E3D", +"dw c #26265C", +"dx c #313174", +"dy c #4C4C60", +"dz c #27273F", +"e` c #3C3C78", +"ea c #48485C", +"eb c white", +"ec c #383874", +"ed c #333379", +"ee c #444458", +"ef c #272756", +"eg c #47477C", +"eh c #32326E", +"ei c #1B1B33", +"ej c #1E1E2C", +"ek c #30306C", +"el c #40407F", +"em c #292944", +"en c #212150", +"eo c #23233E", +"ep c #141422", +"eq c #343473", +"er c #323271", +"es c #2D2D76", +"et c #2E2E6D", +"eu c #40406E", +"ev c #21213F", +"ew c #272731", +"ex c #8080BA", +"ey c #23232D", +"ez c #25255A", +"f` c #1B1B39", +"fa c #35356D", +"fb c #191937", +"fc c #262651", +"fd c #313169", +"fe c #2C2C6E", +"ff c #22224D", +"fg c #18182C", +"fh c #373786", +"fi c #2D2D65", +"fj c #232344", +"fk c #2B2B63", +"fl c #292961", +"fm c #27275F", +"fn c #202037", +"fo c #1C1C33", +"fp c #242452", +"fq c #45456F", +"fr c #484868", +"fs c #535380", +"ft c #1F1F43", +"fu c #2C2C5D", +"fv c #3535DD", +"fw c #353573", +"fx c #262657", +"fy c #393963", +"fz c #242455", +/* pixels */ +"````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````", +"````````````````````````````````````````````````bsbsbsbsbsbsbsbsbsbsbscxbs``````````````````````````````````````````````", +"``````````````````````````````````````````dycxdydycxawawawbsbsbsawcxcxcqdycxcxbs````````````````````````````````````````", +"````````````````````````````````````dyeacxfrawcqawfrawcqcxawcqawawawawawawfrfrcxcqeabs``````````````````````````````````", +"````````````````````````````````dfeadydyawcqawawfrcqawawdrawcqawawfqawcqcqfrawawfrdyeaeadf``````````````````````````````", +"``````````````````````````````eadyeadyfreedrboawfqfqfqdrfqeufqawbaawbabofqeufqdrcqfreeboeadf````````````````````````````", +"``````````````````````````dydffrbocjfrfrdrfrfrfqfqbabofrfqfsbaeubafqfqcgeubafqdrbaabbobobocjeedf````````````````````````", +"````````````````````````dfeeeadffyboeecgeufrfreufqeueueucgbaeubadrdbbacdbaeucgbabocpboboabboeaeebd``````````````````````", +"``````````````````````bdbdcjbd`cfyeefybaabcgfyeubaabdmfseudbdefsaackdbeudebaeudedebocgbofyfycjcjeecj````````````````````", +"````````````````````cjdfabbvb`cg`cfyfyfycgabcgdeckbrfscddecdcddmdmfsabdeeucwcpdbdbcgcgcp`cbvbvcjbvbdcj``````````````````", +"``````````````````bdbddfbv`ccgfyb`cgcgcpfycwdedbdbcdadcdexexckcd`u`uegdedbdbaycpaydecpcpb`bvfybvbdcj`s`s````````````````", +"````````````````dfbdcjbvbd`c`c`cb`cpcwcgdededqayfabrcdexdbcdcdcddeexebbrdbecdedqcwfdaycpcgarb`b`bd`cbd`sbd``````````````", +"```````````````sbdbd`n`ncmcscsarcscwcpdbbtbwbwbtbrfaebexegexaddbdeeceldqbrbrdqbtbkaybt`fbjcscpb`b``ncmctbdbd````````````", +"``````````````aebd`c`ncmcsb`cwayascsdebraybwbrfdbtazdmdeexaddladexckdedmdme`btay`lcbcscwarasfucpb`cmcmae`nbd````````````", +"`````````````saeeo`nbjcmcsarar`paycsbtcb`fbrbtfkfdciecdmdqebcdaacddmece`elbrazfabr`f`wbwbtarbzcsascsarbjbm`kbn``````````", +"``````````ewd`ae`z`c`zbjcsb`cscscwcwbrbravbtecbrfackaadmckexavciexdme`bkfabtapanbr`ffabtfdbtdpcscsbjbjdpbeae`s`s````````", +"``````````ahcm`kcm`bdparaycsay`fcscsfdbrfibwbtbrfdeqcd`qdmelbkeldmexdmeqdce`faerdcapbtbwfa`waucscscvdpdpafcmae`n````````", +"````````cncmaeakcmct`adpcsarcbcbbwdqdeapamdcehcfclbldlbldmeqeradexade`esecelehehdc`ubrbrbtfucsbhcsas`actbecmbpbpey``````", +"````````ejbpeo`vctcv`abzb`ef`ffxfucbbwapbldcdheqetesdlfwdmescfcddmdmdmbkbleldldhaq`ubrfabtcbcsbtcs`pcccycm`veobe`t``````", +"`````````rae`aajevdjdsasas`jbifiapbrbtav`uapclcfdlad`odndnfvdxededexegeceqe`e`cfbybydcbrfmcwcbfdcbbjdjca`bcv`zdd`t``````", +"``````ej`rbu`vcvcv`vcyfcbzefbz`f`uclapfderfeerclerdldlerdada`hedfhe`aacferdtcfciazapfk`ubramcbfuararbzfc`zaeaofo`t`r````", +"``````bpfodibedsdp`jcs`abwbh`lfadccidcecerclet`gfe`hdxdx`hededdt`hdaelcfereterer`wbk`ubtfdbtef`fefcb`paudpbcdiczdi`y````", +"``````ejddddemfcbjefcscs`faycedcececapciazcieqbldterdxdnbqelcdfhfv`h`oe`ererdnetfkfdekfabwbtfubifxfcar`affdpf``yepfo````", +"`````tej`ycyevcuctftbzefdoaiapaqbrbrehfw`udcfwda`oerekfhfhdxdtdaes`hbqfwcferbkehflfkekcffabwfuco`lbzcsbzftbccaevfneja```", +"````atddddem`xaocscsar`pdwdwfibwapbyapeccfdlcf`hdnfmbl`hfhdtdt`hclfvbq`qfhdxbkcfcl`gfkehfa`ufufpamaycsaydjcc`v`vfoepat``", +"````ejfgbucy`vccceaseffdfldgai`ubbfzfdazazcfblereqdt`hdnbq`hedbqfedndndte`dtdtdletfmdhehfkapapbt`mdgfubzacdp`xf`dicz`y``", +"````budddi`x`vevdpcsbzcwfxai`mapfdflfaavblercibkcffhcl`gfvfvfvdadaedclcfcfdteqecdcfkercfav`lbt`famchfdcsbe`bcaczfjbefg``", +"````a`buepccevcrdpbzbzcbfxbifdfififacfekazereretblfe`hfhbqesesdnfh`h`hbq`hfwecdldcerclavecaqaqfifxbhbzbzcv`xfjfodufnat``", +"````atepbufodualfcdp`lauauchfi`lapek`gcicieretfecl`gfhed`hesfm`gfefvfvfvdxbl`oederetfm`wdlfkfxaybzau`d`j`xduf`fgdufga```", +"`````yepddfjacccbz`benamfd`f`mfdbr`mdwcidtcfclfmfebldadneddnesdadadx`hdaededdaclflfmflfmehbyaiaydofuarasftccfjdidiei`t``", +"````a``yczczfbbcbc`bacficucraqfdanfkflaz`oehbbesbldndxfefefeesfvbqbqdnbbdtedciciazaqfkazaz`ubw`laicbas`pdjcccc`advddat``", +"````fo`yddccf`fcalcefucbcufpbi`fbyav`wazbt`ucldxed`hblescldn`hbqdndncl`gazedazazazfw`wekfzanameffucbbzbxbz`jf`fbevbuep``", +"````at`yfbaccy`a`bdsceaiffbzbichfi`manekaq`uclbkcffheletfvesfh`hesdx`qclci`gfkapap`wekapezanfzaifubxeffcfc`bdubufgepat``", +"````a`czdvf`bcdv`bffbzbicrax`fbiezcofifiekbkfk`geredeserbqdndndtadfhazcfblfecl`u`laiflaq`f`lez`ucbdgff`j`bdpccdddiepep``", +"````atczdidvaocy`v`edsbcaxdwbxfzefchameqecdlbl`gazdh`qfhaaadelesfhdaflblbkblerazapfidwbhchaqdobibzalfp`pccbgdveiczepat``", +"````a`epfoczdi`dccac`jaufzcraxaubxdwez`wfkehekbbclbkelaa`obqeleddldafkdmekfm`wfk`wfibwfidobhaiaxef`j`pdsbcacbcaodiddat``", +"``````eifgczevccfbau`jefdgffbhamaxfxezfd`w`l`odl`udcbk`wdneldtegadaaazetdlfmanan`waqfkehfifpbic``p`dbzagftao`vdifbfg````", +"``````a``yfgdv`b`v`ifcbz`b`ibwbtamfxfxfmfxekdhcfby`lciehec`wdlaverapcdecelaz`lby`lfidofiap`mcefxfp`idsagbcagajeicza`````", +"``````ata`czfbdv`vdjceasac`ibiamfian`maifxanazehave`apekehap`uege`ecazcfbkekdwfkfifiauchefbiencuftbcdvfbfof`fbdi`y`y````", +"`````````yczbudvdvdvfbcubgfcaucrbicraxfzchco`wekfke`aqflav`uaa`udm`u`w`uamfzchfmanameffpdgaidgfpaldvaoevf``zfbfgbu``````", +"````````a``tejeif`ajddajdsccbz`pbi`jfpdoanfzanbtai`f`ufkfkdq`lanebexaidcfme`fafiancodgenenbiai`pcracccf`bpddbufg`t``````", +"`````````t`yfgfgbpacaoakdubgbiauffdsenanfidoamaidgcdcoezbtecdc`mdmanbifidoanan`uapfzaxfpfpbhcecr`xbcbgbxddbufoej`t``````", +"```````````t`yfoddaodidv`i`xaleffpc`chfxamchezaichezfmfzanbwanfpcb`famfkanfxfzezcoanbifxc`ffefacbgccacf`ddddej`t````````", +"```````````tcnfobpdvbgdvbgbxftefbibxaiaudofzaxfichanfxfpfxezananfxchdgefezfzfxcuc`crdsfpcubz`jft`eeofcfbfoejfg`r````````", +"````````````eyfgbudiaoajbgdvbecrfpfpff`bffefbwaichchdgdgbhdgbjbidoaicofxfpaicubxds`afpdgas`e`vduag`z`zajdibuey``````````", +"```````````````t`rbuddeodvft`zalbccr`ec``bc`auenfp`jezchfxaidpc`fxdgfpfiamfcdgfxcvcrfcfpalcr`zbeajf`dvajbfey````````````", +"```````````````rbfbpfofbbgdvaffjfjcc`jfxbxfcc``b`bdsbiau`jc`biaibifxfpfcch`afpc``d`d`vdvfjfj`zdvajfbdvbp`tcn````````````", +"````````````````cnfnfnbpfnaoftftdj`ecuftfpaubidgfp`j`bfcfpfc`afpdgc``jfpencuc``b`j`e`vcrevdkdzewbefnfobfej``````````````", +"``````````````````bffnfnajfodvddccftaf`e`b`jdgcuai`jcv`jc`fcdj`jbxcvcvdsdsbxbxdjcr`xbxdjft`z`zddbefnbf`r````````````````", +"````````````````````d`eyewbeduak`zfjemcads`dfp`jdj`b`bcu`jcudgfpefds`bcacacvctct`dagak`xaoddbeeybpfn`r``````````````````", +"``````````````````````eyfnbpdkdz`z`zbmakfj`bag`v`dctctctctem`d`ecvctaeaeafcu`v`ecc`zakafbp`kbpewbfew````````````````````", +"````````````````````````eyeybfbpdk`zemcvcyafemakcvcvaeaeffdjcvcv`j`vae`vemaf`vagcc`z`z`zeodkbfd`ey``````````````````````", +"``````````````````````````cnbnfobe`kbe`kevemdzfj`k`z`b`edjctaeaeemds`eaf`vevdzdjafemd`dk`zbfd`ey````````````````````````", +"``````````````````````````````bncneybf`kbeaf`kememem`kcvafemakaeaeakemem`kdk`z`kbebm`zd`d`ah````````````````````````````", +"````````````````````````````````ahcnewd`dk`z`zaeaf`kaf`k`vemaedzcvakak`z`kdzd`dkdkbmbfbnah``````````````````````````````", +"````````````````````````````````````cncnbf`z`sd``s`k`z`s`zbm`s`kd`d``s`s`k`kd`ahd`bncn``````````````````````````````````", +"``````````````````````````````````````````bnd``s`s`kbnd`d`bfd``kbnbnd`bnd`ewahbn````````````````````````````````````````", +"````````````````````````````````````````````````ahbnahbnd`ewdkbfewahahewbn``````````````````````````````````````````````", +"````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````", +"````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````" +}; +/* XPM */ +static char *glass11[] = { +/* width height ncolors chars_per_pixel */ +"72 72 189 2", +/* colors */ +"`` c None", +"`a c #27274E", +"`b c #25254C", +"`c c #383858", +"`d c #23234A", +"`e c #212148", +"`f c #2E2E62", +"`g c #292967", +"`h c #3535A1", +"`i c #272751", +"`j c #23234D", +"`k c #29293F", +"`l c #2C2C63", +"`m c #2A2A61", +"`n c #33334C", +"`o c #353579", +"`p c #272754", +"`q c #414188", +"`r c #20202C", +"`s c #2E2E3D", +"`t c #1C1C28", +"`u c #2E2E68", +"`v c #242447", +"`w c #2C2C66", +"`x c #222245", +"`y c #181824", +"`z c #25253E", +"a` c #161622", +"aa c #B9B9ED", +"ab c #3E3E67", +"ac c #1C1C3F", +"ad c #6767A3", +"ae c #2B2B47", +"af c #272743", +"ag c #222248", +"ah c #292931", +"ai c #29295C", +"aj c #1D1D39", +"ak c #252544", +"al c #1E1E47", +"am c #2B2B61", +"an c #29295F", +"ao c #1F1F3E", +"ap c #2F2F68", +"aq c #2D2D66", +"ar c #30305F", +"as c #2C2C5B", +"at c #11111C", +"au c #262655", +"av c #31316D", +"aw c #4C4C6D", +"ax c #222251", +"ay c #323264", +"az c #2D2D69", +"b` c #33335B", +"ba c #43436E", +"bb c #2B2B67", +"bc c #212146", +"bd c #37374B", +"be c #22223D", +"bf c #252536", +"bg c #1D1D42", +"bh c #2A2A5C", +"bi c #28285A", +"bj c #2B2B53", +"bk c #333372", +"bl c #2F2F6E", +"bm c #2B2B3F", +"bn c #2C2C36", +"bo c #424266", +"bp c #232337", +"bq c #2F2FB0", +"br c #34346C", +"bs c #525265", +"bt c #32326A", +"bu c #1B1B2F", +"bv c #3B3B55", +"bw c #303068", +"bx c #21214C", +"by c #2C2C64", +"bz c #292957", +"c` c #232351", +"ca c #26264A", +"cb c #2F2F60", +"cc c #202044", +"cd c #5D5D97", +"ce c #2B2B5C", +"cf c #363674", +"cg c #3C3C66", +"ch c #252556", +"ci c #30306E", +"cj c #3E3E54", +"ck c #414178", +"cl c #2C2C6A", +"cm c #2F2F4F", +"cn c #25252E", +"co c #27275B", +"cp c #363663", +"cq c #4C4C68", +"cr c #20204A", +"cs c #2E2E5B", +"ct c #29294C", +"cu c #242451", +"cv c #27274A", +"cw c #343464", +"cx c #4F4F64", +"cy c #252548", +"cz c #16162C", +"d` c #292938", +"da c #333384", +"db c #3C3C6F", +"dc c #353572", +"dd c #1E1E37", +"de c #38386B", +"df c #414156", +"dg c #242454", +"dh c #31316E", +"di c #181831", +"dj c #232349", +"dk c #272739", +"dl c #393979", +"dm c #4C4C85", +"dn c #2F2F83", +"do c #28285B", +"dp c #292952", +"dq c #36366C", +"dr c #48486D", +"ds c #23234C", +"dt c #37377A", +"du c #20203F", +"dv c #1E1E3D", +"dw c #26265C", +"dx c #313174", +"dy c #4C4C60", +"dz c #27273F", +"e` c #3C3C78", +"ea c #48485C", +"eb c white", +"ec c #383874", +"ed c #333379", +"ee c #444458", +"ef c #272756", +"eg c #47477C", +"eh c #32326E", +"ei c #1B1B33", +"ej c #1E1E2C", +"ek c #30306C", +"el c #40407F", +"em c #292944", +"en c #212150", +"eo c #23233E", +"ep c #141422", +"eq c #343473", +"er c #323271", +"es c #2D2D76", +"et c #2E2E6D", +"eu c #40406E", +"ev c #21213F", +"ew c #272731", +"ex c #8080BA", +"ey c #23232D", +"ez c #25255A", +"f` c #1B1B39", +"fa c #35356D", +"fb c #191937", +"fc c #262651", +"fd c #313169", +"fe c #2C2C6E", +"ff c #22224D", +"fg c #18182C", +"fh c #373786", +"fi c #2D2D65", +"fj c #232344", +"fk c #2B2B63", +"fl c #292961", +"fm c #27275F", +"fn c #202037", +"fo c #1C1C33", +"fp c #242452", +"fq c #45456F", +"fr c #484868", +"fs c #535380", +"ft c #1F1F43", +"fu c #2C2C5D", +"fv c #3535DD", +"fw c #353573", +"fx c #262657", +"fy c #393963", +"fz c #242455", +/* pixels */ +"````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````", +"``````````````````````````````````````````````````````````````bsbsbsbsbsbsdydybsbsea````````````````````````````````````````````````````````````", +"``````````````````````````````````````````````````````eabsbsdybsbsbsbsbsbscqcxbsbsbsbsbscxdy````````````````````````````````````````````````````", +"````````````````````````````````````````````````dydybsbsdycqcqdycxbsbsfrcqcxdyfrcqcxcxbseacxcxbsbs``````````````````````````````````````````````", +"````````````````````````````````````````````eaeaeafrcqawawawdrdrawcxawawcqcqawawawawawbscqfrfrdycxcxea``````````````````````````````````````````", +"````````````````````````````````````````frdfcxcqawcqcqawawfrcqdrawfrawawcqawawawfqawcqawcqdrawdrfrdycqdycx``````````````````````````````````````", +"````````````````````````````````````eeeaeaeadycqdffrboboawfqfqfqdrdrfqbabadrdrdrdrbobodrdrbaawdrdyfreaeaboeeee``````````````````````````````````", +"``````````````````````````````````eeeefreeeefrbofrfrbofrfqeudrbadrfqdrfqeubabababababafqdreufqfrbafrfreeeeeacjdf````````````````````````````````", +"``````````````````````````````eecjboeebocjboboababboabdrfsfqfqbabobobafqfqawdrfqawbaeueudrdebafrbocgbobobobodfdfcjbd````````````````````````````", +"````````````````````````````dfeeeedfcjbvab`ccgfyeuabboabbabaabdbadeucgdeabbabadbegfqfqfqbaeueueubobob`bocgcgdfeacjcjcj``````````````````````````", +"``````````````````````````cjbddfcjbv`ccgdffycgfqbofyfyabdbeuabfqexbaeueudefqexadckdbbadedebaabdedeeufyboabcpfycjdfdfeecj````````````````````````", +"````````````````````````cjcjdfdfbvb`cg`cfyfyfyfycgabcgdeeudbbregexdbdbadcddmegexeucgdedbdbayfydbdbabcgfycpb`bv`cbvcjdfbdcj``````````````````````", +"``````````````````````bdbdcjbvbvfy`c`cb`cpcgfyfyfycpdededbdeegexdmaaebexckaadm`ucddbdedbdbcwcpcpfddedeb`fyb`bvfycjcmbdcj`s`s````````````````````", +"````````````````````bd`nbvbvbv`ccg`c`ccscpcwcwcgdebrcwbraydqckdbcdegegcdcdade`btdcadbrdqfabrdebrcpbwaycpfyfyb``car`n`nbdcjbnbd``````````````````", +"```````````````````n`s`n`ncj`nb`b`b`b`b`b`arcpdqfabrbrcwaybtbrexadcddbadaae`dedeexaddbdqdebrdedbdededeayb`b`cpb`b`fy`n`c`ncmbdbd````````````````", +"```````````````````n`sbdaecmcmcscscscpcscscpcwfsbwfiaqfdaybtecadexaafsexe`exckdbbtecdedqfdaycpbrekcbcsaycb`icsaycpb`b``ncm`naebd````````````````", +"`````````````````scj`c`ccmctbjcsb`cparasascsdqayaybwecbwbrbrbbe`dee`ebadegcdexadegdbcdade`ecbrbwfk`ffuarcwarcscscscpcscmcmct`nd`bd``````````````", +"```````````````s`saecv`nbjaecmasarar`parcsayfdcb`fbrbtaq`fbtciecdmdbdeebcdebcdebehece`egfabtaqecbrcbazap`fayarcsas`casbjarcmem`n`sbn````````````", +"``````````````ew`s`zcv`nevcmbjcscsbzcscwaydedqbwavfafdfadcdcckadebcke`aaehdhadebe`dcehdcbtbran`fbr`fbrfibtayaybzbjarcsb`bjbjafbm`sae````````````", +"````````````bnaeae`kcmagdjfuaycsb``ffucscsbtbwdcaqfifdfabwave`exaaadcdcddh`oecadcddmfwapdbe`fdaqbrapbtbtfdecaqbhbzarcs`adpcmaf`zcmcncn``````````", +"````````````dz`n`kctcmct`idparcwaybw`farfubrdqbr`ffdfafaecekerdcfeazeleqavdmexaddmelcibkegbrbtbkfa`uehbwfifiambzfxcscs`abjbjakctcmcm`z``````````", +"``````````ey`saf`zafbjcv`befascsfuar`ffdbrde`faq`wdcdcbkerclesdlcfdmcdblfwcdebaddmdldxercdecbkavbkapbrbtfdbt`fcbbwcbbjbzcactaebectfn`zey````````", +"``````````a`bf`zcacvdpcv`icucscsbi`fefbhar`fbr`uekbrekcierdxdxdlcieleqes`odmelelexdmcfere`eldcetaqfibwfadcapcbcscsbtcsfcccakdp`vcv`zfncn````````", +"`````````tbpaecvao`vcccydsbzcsbzffaifiekbwbtbrap`uekbber`odladdteddndnbqdxeqedeqebeleceqdtelelerbyfkavdcfiancwarbtfdcsbjdjfcbjctaebpddbpbf``````", +"````````bf`rfodpevcv`vfjcybz`idpefbhayapetblapfdciblcleqeteqeldldxdxdadadaesdadtadcdcfereqdldcekapap`wflbwayamcbbhcbasasdp`pbjakcvfjfo`y`y``````", +"````````ewdddidvdj`abzagdpcu`p`lbzambwfdbbclehdcerfeetetflfedaedbldxdadndaeddada`qdmcfeqdxdheqblfkap`waqfddq`fdgaycs`pcsefef`afjeveieifo`k``````", +"```````ybfevei`zft`afubzcsas`fam`fbwfaecdcdcdccfetbbblcieretedesed`h`heldm`qdafvdndleceqercledetaqbrapbkfaayfabwbz`fbiascs`p`j`vftf`a`epbu`t````", +"```````y`ybufnaefc`bdpcucs`pfubw`lbwbrdqdcehavfw`wcfcfereqfwercidt`hdae``qdtbqbqeddle`cfdtdxercifk`uavavecbwbw`fbz`m`mefay`jbc`d`aaobua`fg`t````", +"``````epbuddcvfjefca`bdsbzbzbhezbyaqaqbrdqehecdcfddccfeqdaedblazdtfhfhdxdtdnfednfvfvcfdtererdcehfl`wfkbkfafaap`fcefifiasasfudjbc`bcadudda``t````", +"``````a`foeoemak`adparcsarefaidwamapbwapbyazeheccfeccfdxbqesfmblesbqeldtdtbq`g`hfvbq`q`qeqerfweqclbbfmdhbwfa`ufubifxbtarcscb`b`bcv`v`vfgfgbu````", +"````atejfgfgcy`v`bbcfuasef`ffiezchco`uazezezap`uekdlererereqeddadnfvfved`ofvesesbqfvdle`dleddtdlclfmfkerbr`mapfibtbi`lbzfufuccfccvccdvfg`yfoat``", +"`````yfodiaj`v`v`x`bdpcsbzdeamamaxfkaqehfm`wav`ueteretbkbkcffhdxfednfefv`hbqdadxesfedtfwcfdtfwe`dcflcldlbkfdfibtap`fanfpayasao`idpagczfneifg`t``", +"````atfgfofgagccao`abjasbzcbfufxbibtbwfdapecdlavekerblbkeqeqdaesfedafvdndn`hfvfv`hdxeddtdtcffwdlecdhcleqehbkaqaqfkfkco`f`fayafctdjcadiajdv`yfo``", +"````atejbpczaocc`aaldpbzbzfudoen`mbtfiambtbtereretererbletetfeesbq`hfv`g`gdn`hdafhdabqfvbkbkdldlfwerclfkekecaqaqfdfidgef`b`pctccftakfoajfgbua```", +"````ata`befofoft`daldp`p`laubzambi`lby`lehfm`gavciererclfe`g`gfhdtdxed`g`gesfmdnfvfvdndnetdxedblblazfmfmapec`mfzcbarc`bzbxfcaoccftf`fgbcepfgbu``", +"`````y`yevbefjdv`xfpdp`jenbifd`lfufkfdbtazdw`merdtdtci`g`gfebledfhesdnfeesdafvededfvdaed`hdadaclflfmflezfibtbycobwfudgfuarfuds`v`xaodidia`atat``", +"````atfgaobudif`acfp`ebxacfu`fc`fxfdfdan`mdw`gaz`ocfekcletesdndxfecletesdn`h`hfvfhedclfheqfherek`gbyazfm`uaz`ubtamanfucbceaufcccccducaevfoatat``", +"````atfoejfof`fbcc`jcrbheffufualaxamfiancifkbbciehekflcleleqdadxfedn`gbq`hfvesdnblfmflbberedcletazeqazehapfm`w`lfubzcbcsbzcr`jdpacf`ftdvfn`yat``", +"````atfgbufodjfjdudp`afpfu`l`jfcbiefdoapavfkfketazbyazbldxdt`hes`hesdxdx`h`hesdndaet`gazeler`wazdhdhcidhanbxezfzchbibh`p`pfceffffcf`czfodd`yat``", +"````atatczdif``b`v`v`afffu`facfcfubidgfmcoez`lapbbap`gbbedecfhedetdaesesfv`h`qcifhfhdadletfl`wekfianfkcifk`lfkchfl`lbzcrcufc`ift`aaodddda`buat``", +"````at`tdif`dvagcycc`iff`pefcraxfz`fbianezfkap`uehfw`ufl`gcieqcderfh`hdnedeqdcfedmazdldxdl`gazaq`lfmfmdwfi`l`lan`wfdfucrc`fp`b`d`daoddbufnatat``", +"``````fga`f`dvdvcycc`xffdsdscrchezcrfzeffxezfieqecdlbkfebbcidh`qfhfhad`qelfedndadnfkblcfclcierazapaqdwaibhchaqanfxcecealfpef`x`bdvf`eiczfg`y````", +"``````at`yeiczeiajftftac`j`pfpaxalaxefbxfzch`maqfkbkerazclblbkdmdtdaaaedexfvaddafe`udmblflfkazbbazaqfiaqanbiamanaxfpbzds`pfcbcccdvftaoei`yep````", +"``````a`a`didif`f`acbxalfp`pbxax`jcefufzfzfmfmbbfifkfibkdhaveqelexfv`qcddndmcdadfeekdl`hflanfkfm`wfdfkapapbhcuefchcuau`bbz`jacccf``vdidvat`y````", +"``````a`epfoczdv`baoacefbxbzcscr`pfi`fcochchezez`mavekdcecfmfmdmfa`wdlapexcdcddmaabbazes`wfd`lan`maqaibwehapcofiauauau`befalbcdp`ddvfodieiat````", +"````````ata`difbftao`a`bbzfu`bagbzfdbrfiandoaiaifp`wekeqfw`wfkeke`apckaqelecerfkckcdfherer`ufk`wbyaqaidoanamanbzcufx`b`pbgbcbgccagdieiczep``````", +"````````at`yfgf`difbctagbzascrbcefaubififx`lananezdo`mcidhapav`uelcddcecape`dcflfaekbkeqekdwcofkfiapaidgefchbic`ffalftaldvf`bpf`fbdidia`a```````", +"````````at`yczddeiaof`dvfb`jbgccasc`crbhcrfpenchchcoanekeh`we``wfkelececaaek`qcdaqfk`ufiezdgdwfman`lbhenfzfzaifpcealcraoaodueobeajdifg`ya```````", +"``````````a`bueibueiajajddddbcbgalbzfcbh`j`pfpdoaichchavapdodmbtbyad`mfkbydweccfckaielfmbybt`l`mcodwanaxaxenbifxbzdsbxf`ftacfndkajfofgfg````````", +"``````````a``teifgbubeftdvafccbgalamef`j`dbxcofkaqcodo`famdgdeanaidqanape``me`fiaianfk`m`mbwfdapaqfzffenfpc`bhfu`pftagagft`jddddfofofga`````````", +"````````````fg`tbueibpf`dvevfbevbgfpfpcrenbxaxamfiananfkbiaxfpezezfxfkecbwbifzch`mezfiamdocochfi`lcobibibzfpfpbzcufjevccac`efgbubu`tej``````````", +"`````````````tbu`rejf`aodidvdjfcagacbzbhaxdochfxanfzfpbiaichanbychchchbt`lfzbhezcofxaiaichchaufzc`fxch`jdoffenefbgalbgbcbccceiddfo`y`r``````````", +"```````````````rejeifodvdvajacbcccccdgbibxfpdgaufuezfz`manfzanfxaufp`fcodocoezchchenauchfxchefff`jagffbxenbzbi`dftbc`edz`df`buddbudd````````````", +"```````````````y`rbuf`diaoajacbgevevcrfpfpfp`afffffc`faqfxchchfzc`dgfxdgbjfxaiaiancofxfpcodg`bffds`adgbxbzbz`e`v`vftbeev`zajf`ddei`t````````````", +"`````````````````yfoeyfbaj`zajbgevakalbxcccu`e`b`bc`efbic`axaxchfxfpezchbjfcdodochfx`fanbzcuaufxcv`bfp`pef`e`eeoeoaof`f`ajdv`rfn`r``````````````", +"``````````````````cn`rejeidvacdveoak`vccccfffpbibx`ac``jcucu`jfxbifxfpfxfxfxcodgc`aybiai`i`jch`j`a`edjagacbc`x`zfnddajf`eodvey`t````````````````", +"``````````````````eybfej`rejfoaoevcccc`v`xbcc`c`fffpbicubxcucuffc`cu`pfcfpdgbhdoaucu`jcuffbxbx`bcr`efjagbcfjeodkeodkevddfobpcney````````````````", +"````````````````````eyejbpejbpdddvaoaodjbcagbcft`jefchfxbiauc``a`ac`c`fc`afcfccufcenfp`jfffp`jdsfpftcycrbcccdz`zdkbebebfddbf`r``````````````````", +"``````````````````````cnbpeyfofofodudd`eacdjafcr`d`dcufpffef`jca`bff`jfcbxcuc`dsaecv`d`jds`dcy`vag`xagbcfteo`zbpfnbpbfej`r`r````````````````````", +"````````````````````````d`bpddbfbebgak`zfj`z`kdsdsbxffff`bdj`b`b`jcucucudgcueffp`b`bcacacvcvctct`dagcyfjccevddeoeybpd`ej`r``````````````````````", +"``````````````````````````eyddbp`r`k`z`zdzem`kfjfj`b`d`vdjcyctctcactctcv`dcr`bcvctaeaecv`b`jfjdsccakcveoakbedz`zd`ahewah````````````````````````", +"````````````````````````````ewcnbnbndd`kdzfjdzemakemae`zcv`dcaaeaecy`e`acadsag`vaeaecvakaffjcacrbcajfj`zbp`z`kfnewewcn``````````````````````````", +"```````````````````````````````rewbfbp`z`zbedzafcyakembeafctcaak`d`v`acvaeae`dff`dag`baeakfj`zcy`zbm`z`z`k`zbfd`ahcn````````````````````````````", +"```````````````````````````````````sd`eyfnbmeobm`zdz`saf`v`k`kcvbcag`bcvemaeaecvagcyaecvevafaf`zem`zd`dkbmd`bfbf````````````````````````````````", +"````````````````````````````````````ahewfoewbf`k`z`zdz`zafemememcvaf`kdz`vafaeafakemembmbpafdkdkbp`k`zbp`seyah``````````````````````````````````", +"`````````````````````````````````````````sah`zewdk`z`zdzaeaf`kemdzakakaeae`kemakemeo`z`kemdkbfbpdk`kd`d`bn``````````````````````````````````````", +"````````````````````````````````````````````ahbnbf`zd`d``sbm`kdz`sdkdk`sae`k`zbmd``k`sbmdz`kbnah`s`sbn``````````````````````````````````````````", +"````````````````````````````````````````````````bncnbmbnd`dkdkdkdkbm`sbnbnbndzd`d``sbm`sbfd`bnewah``````````````````````````````````````````````", +"``````````````````````````````````````````````````````cnd``s`s`sahd`dkbmbnbn`sbnd`bnbn`newah````````````````````````````````````````````````````", +"``````````````````````````````````````````````````````````````ahcn`sbnahewbn`sewahbn````````````````````````````````````````````````````````````", +"````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````", +"````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````" +}; +char **default_bubbles[] = {glass1, glass2, glass3, glass4, glass5, glass6, glass7, glass8, glass9, glass10, glass11, (char **)0}; + +int num_default_bubbles = 11; + +#endif /* NO_DEFAULT_BUBBLE */ diff --git a/hacks/decayscreen.c b/hacks/decayscreen.c new file mode 100644 index 00000000..ce18a7ee --- /dev/null +++ b/hacks/decayscreen.c @@ -0,0 +1,146 @@ +/* xscreensaver, Copyright (c) 1992, 1993, 1994 + * 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. + */ + +/* decayscreen + * + * Based on slidescreen program from the xscreensaver application and the + * decay program for Sun framebuffers. This is the comment from the decay.c + * file: + + * decay.c + * find the screen bitmap for the console and make it "decay" by + * randomly shifting random rectangles by one pixelwidth at a time. + * + * by David Wald, 1988 + * rewritten by Natuerlich! + * based on a similar "utility" on the Apollo ring at Yale. + + * X version by + * + * Vivek Khera + * 5-AUG-1993 + */ + +#include "screenhack.h" + +static int sizex, sizey; +static int delay; +static GC gc; + +static void +init_decay (dpy, window) + Display *dpy; + Window window; +{ + XGCValues gcv; + XWindowAttributes xgwa; + int root_p; + Pixmap pixmap; + + delay = get_integer_resource ("delay", "Integer"); + root_p = get_boolean_resource ("root", "Boolean"); + + if (delay < 0) delay = 0; + + gcv.function = GXcopy; + gcv.subwindow_mode = IncludeInferiors; + gc = XCreateGC (dpy, window, GCForeground |GCFunction | GCSubwindowMode, + &gcv); + + XGetWindowAttributes (dpy, window, &xgwa); + sizex = xgwa.width; + sizey = xgwa.height; + + copy_default_colormap_contents (dpy, xgwa.colormap, xgwa.visual); + pixmap = grab_screen_image (dpy, window, root_p); +} + + +/* + * perform one iteration of decay + */ +static void +decay1 (dpy, window) + Display *dpy; + Window window; +{ + int left, top, width, height; + +#define nrnd(x) (random() % (x)) + + switch (random() % 8) { + case 0: /* move a block left */ + case 1: + left = nrnd(sizex - 1) + 1; + top = nrnd(sizey); + width = nrnd(sizex - left); + height = nrnd(sizey - top); + XCopyArea (dpy, window, window, gc, left, top, width, height, + left - 1, top); + break; + case 2: /* move a block right */ + case 3: + left = nrnd(sizex - 1); + top = nrnd(sizey); + width = nrnd(sizex - 1 - left); + height = nrnd(sizey - top); + XCopyArea (dpy, window, window, gc, left, top, width, height, + left + 1, top); + break; + case 4: /* move a block up */ + left = nrnd(sizex); + top = nrnd(sizey - 1) + 1; + width = nrnd(sizex - left); + height = nrnd(sizey - top); + XCopyArea (dpy, window, window, gc, left, top, width, height, + left, top - 1); + break; + default: /* move block down (biased to this) */ + left = nrnd(sizex); + top = nrnd(sizey - 1); + width = nrnd(sizex - left); + height = nrnd(sizey - 1 - top); + XCopyArea (dpy, window, window, gc, left, top, width, height, + left, top + 1); + break; + } + XSync (dpy, True); +#undef nrnd +} + + +char *progclass = "DecayScreen"; + +char *defaults [] = { + "DecayScreen.mappedWhenManaged:false", + "DecayScreen.dontClearWindow: true", + "*delay: 10", + 0 +}; + +XrmOptionDescRec options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, +}; + +int options_size = (sizeof (options) / sizeof (options[0])); + +void +screenhack (dpy, window) + Display *dpy; + Window window; +{ + init_decay (dpy, window); + while (1) { + decay1 (dpy, window); + if (delay) usleep (delay); + } +} diff --git a/hacks/decayscreen.man b/hacks/decayscreen.man new file mode 100644 index 00000000..007301bc --- /dev/null +++ b/hacks/decayscreen.man @@ -0,0 +1,53 @@ +.TH XScreenSaver 1 "05-aug-93" "X Version 11" +.SH NAME +decayscreen - make a screen meltdown. +.SH SYNOPSIS +.B decayscreen +[\-display \fIhost:display.screen\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-delay \fIusecs\fP] +.SH DESCRIPTION +The \fIdecayscreen\fP program creates a melting effect by randomly +shifting rectangles around the screen. +.SH OPTIONS +.I decayscreen +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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +Specify which visual to use. Legal values are the name of a visual class, +or the id number (decimal or hex) of a specific visual. +.TP 8 +.B \-delay \fImicroseconds\fP +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" +X(1), +xscreensaver(1) +.SH COPYRIGHT +Copyright 1992 by Vivek Khera. 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 +Vivek Khera , 05-Aug-93; based on code by David Wald, 1988. diff --git a/hacks/default.xbm b/hacks/default.xbm new file mode 100644 index 00000000..dcd2ff50 --- /dev/null +++ b/hacks/default.xbm @@ -0,0 +1,1686 @@ +#define logo_width 464 +#define logo_height 435 +static unsigned char logo_bits[] = { +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x60, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x60,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xf0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xf0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xf0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xf8,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xf8,0x01,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xf8,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xfc,0x01, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xfc,0x01,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xfc,0x03,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xfc,0x07,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xfe,0x07,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xfe,0x07,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xfe,0x07,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xff, +0x0f,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xff,0x0f,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0x80,0xff,0x0f,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x80,0xff,0x1f,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0x80,0xff,0x3f,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0x80,0xff,0x3f,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0x80,0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0, +0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0x7f, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0x7f,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xe0,0xff,0x7f,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xe0,0xff,0xff,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xf0,0xff,0xff,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xf0,0xff,0xff,0x01,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xf0,0xff,0xff,0x01,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff, +0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xf8,0xff,0xff,0x03, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0x03,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xfc,0xff,0xff,0x03,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xfc,0xff,0xff,0x07,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xfc,0xff,0xff,0x07,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xfe,0xff,0xff,0x07,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xfe, +0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xfe,0xff,0xff, +0x0f,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xff,0xff,0xff,0x0f,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x80,0xff,0xff,0xff,0x1f,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0x80,0xff,0xff,0xff,0x1f,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0x80,0xff,0xff,0xff,0x1f,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0x80,0xff,0xff,0xff,0x1f,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0, +0xff,0xff,0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff, +0xff,0x7f,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0xff,0x7f, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0xff,0x7f,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0xff,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xe0,0xff,0xff,0xff,0xff,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xf0,0xff,0xff,0xff,0xff,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xf0,0xff,0xff,0xff,0xff,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff, +0xff,0xff,0xff,0x01,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff,0xff,0xff, +0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xf8,0xff,0xff,0xff,0xff,0x03, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xf8,0xff,0xff,0xff,0xff,0x03,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xf8,0xff,0xff,0xff,0xff,0x03,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xf8,0xff,0xff,0xff,0xff,0x07,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xfc,0xff,0xdf,0xff,0xff,0x07,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xfe, +0xff,0xdf,0xff,0xff,0x07,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xfe,0xff,0x8f, +0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xfe,0xff,0x0f,0xff,0xff, +0x0f,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xfe,0xff,0x0f,0xff,0xff,0x0f,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xff,0xff,0x07,0xff,0xff,0x1f,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xff,0xff,0x07,0xff,0xff,0x1f,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0x80,0xff,0xff,0x07,0xfe,0xff,0x1f,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0, +0xff,0xff,0x03,0xfc,0xff,0x3f,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff, +0x03,0xfc,0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0x03,0xfc, +0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xe0,0xff,0xff,0x01,0xf8,0xff,0x7f, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xe0,0xff,0xff,0x01,0xf8,0xff,0x7f,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xe0,0xff,0xff,0,0xf0,0x03,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xe0,0xff,0xff,0,0xf0,0x03,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xe0,0xff,0x1f,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff, +0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xf0,0x07,0,0, +0x80,0xff,0x03,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xf8,0xff,0xff, +0xff,0xff,0x03,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xf8,0xff,0xff,0xff,0xff, +0x03,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xc0,0xff,0xff,0xff,0x03,0,0,0xe0,0xff,0x7f,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xfc,0xff,0xff,0,0,0,0,0,0xe0,0xff,0x07,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xe0,0xff, +0x7f,0xfe,0,0,0,0,0,0,0xfc,0x7f,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xfe,0xff,0x01,0xfe, +0x01,0,0,0,0,0,0xc0,0xff,0x03,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xfe,0xff,0x01,0xfe,0x01,0, +0,0,0,0,0xc0,0xff,0x03,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xf0,0xff,0x07,0,0xce,0x07,0,0,0, +0,0,0,0xfe,0x1f,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xfe,0x7f,0,0,0x87,0x1f,0,0,0,0,0, +0,0xc0,0xff,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xe0,0xff,0x07,0,0x80,0x03,0x3e,0,0,0,0,0,0,0, +0xfe,0x07,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xfc, +0x3f,0,0,0x80,0x03,0xf8,0,0,0,0,0,0,0,0xe0,0x3f, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xfc,0x3f,0, +0,0x80,0x03,0xf8,0,0,0,0,0,0,0,0xe0,0x3f,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0x80,0xff,0x07,0,0,0xc0, +0x01,0xe0,0x01,0,0,0,0,0,0,0,0xff,0x01,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xf0,0xff,0x7f,0,0,0xc0,0xfb,0xff, +0x0f,0,0,0,0,0,0,0,0xf0,0x0f,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xfe,0xff,0xff,0x07,0,0xc0,0xff,0xff,0x3f,0, +0,0,0,0,0,0,0x80,0xff,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0x80,0xff,0xc0,0xff,0x7f,0,0xe0,0xff,0xff,0x7f,0,0,0, +0,0,0,0,0,0xfe,0x01,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x80,0xff,0xc0,0xff,0x7f,0,0xe0,0xff,0xff,0x7f,0,0,0,0,0, +0,0,0,0xfe,0x01,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0,0x1f, +0,0xf8,0xff,0x0f,0xf0,0x0f,0xc0,0xff,0x01,0,0,0,0,0,0, +0,0xf0,0x0f,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xe0,0x0f,0,0, +0xff,0x7f,0xf0,0x01,0,0xf8,0x03,0,0,0,0,0,0,0,0xc0, +0x3f,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xf0,0x01,0,0,0x80,0xff, +0x7b,0,0,0xe0,0x07,0,0,0,0,0,0,0,0,0xfe,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xf8,0,0,0,0,0xfc,0x3f,0, +0,0x80,0x1f,0,0,0,0,0,0,0,0,0xf0,0x03,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xf8,0,0,0,0,0xfc,0x3f,0,0,0x80, +0x1f,0,0,0,0,0,0,0,0,0xf0,0x03,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0x3c,0,0,0,0,0xe0,0x7f,0,0,0,0x7e,0, +0,0,0,0,0,0,0,0xe0,0x0f,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0x3e,0,0,0,0,0,0xff,0x03,0,0,0x70,0,0,0, +0,0,0,0,0,0x80,0x3f,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0x80,0x0f, +0,0,0,0,0,0xf0,0x1f,0,0,0,0,0,0,0,0, +0,0,0,0,0xfc,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xc0,0x0f,0,0, +0,0,0,0,0xfe,0x01,0,0,0,0,0,0,0,0,0, +0,0,0xf0,0x01,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xc0,0x07,0,0,0,0, +0,0,0xf8,0x07,0,0,0,0,0,0,0,0,0,0,0, +0xe0,0x07,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xc0,0x07,0,0,0,0,0,0, +0xf8,0x07,0,0,0,0,0,0,0,0,0,0,0,0xe0,0x07, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xe0,0x03,0,0,0,0,0,0,0xe0,0x3f, +0,0,0,0,0,0,0,0,0,0,0,0x80,0x0f,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xf0,0x01,0,0,0,0,0,0,0x80,0xff,0,0, +0,0,0,0,0,0,0,0,0,0,0x3f,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xf8,0x01,0,0,0,0,0,0,0,0xfc,0x07,0,0,0, +0,0,0,0,0,0,0,0,0x7c,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xf8, +0,0,0,0xfe,0x03,0,0,0,0xf0,0x0f,0,0,0,0,0, +0,0,0,0,0,0,0xf8,0x01,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xf8,0,0, +0,0xfe,0x03,0,0,0,0xf0,0x0f,0,0,0,0,0,0,0, +0,0,0,0,0xf8,0x01,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xfc,0,0,0xf0,0xff, +0x1f,0,0,0,0x80,0x7f,0,0,0,0,0,0,0,0,0, +0,0,0xf0,0x03,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x3f,0,0,0xfc,0xff,0x7f,0, +0,0,0,0xfe,0x01,0,0,0,0,0,0,0,0,0,0, +0xc0,0x07,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0x80,0x1f,0,0,0xff,0x47,0x7f,0,0,0, +0,0xf8,0x0f,0,0,0,0,0,0,0,0,0,0,0x80,0x0f, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xf0,0x07,0x80,0xff,0xff,0x3f,0x7c,0,0,0,0,0xc0, +0xff,0,0,0,0,0,0,0,0,0,0,0,0x3e,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xf0,0x07,0x80,0xff,0xff,0x3f,0x7c,0,0,0,0,0xc0,0xff,0, +0,0,0,0,0,0,0,0,0,0,0x3e,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xfc, +0x03,0xc0,0xff,0xfe,0xff,0x7d,0,0,0,0,0x80,0xff,0x01,0,0, +0,0,0,0,0,0,0,0,0x7c,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0,0x40, +0,0,0xfe,0x7f,0,0,0,0,0x80,0xff,0x07,0,0,0,0, +0,0,0,0,0,0,0xf0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xf0,0x3f,0,0,0x80,0x03, +0xf8,0x3f,0,0,0,0,0x80,0xe7,0x1f,0,0,0,0,0,0, +0,0,0,0,0xf0,0x01,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xfe,0x0f,0,0,0xf0,0xff,0xff,0x1f, +0,0,0,0,0x80,0xc7,0x7f,0,0,0,0,0,0,0,0, +0,0,0xe0,0x03,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xfe,0x0f,0,0,0xf0,0xff,0xff,0x1f,0,0, +0,0,0x80,0xc7,0x7f,0,0,0,0,0,0,0,0,0,0, +0xe0,0x03,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xc0,0xff,0x03,0,0,0xf0,0xff,0xff,0x0f,0,0,0,0, +0xc0,0x0f,0xff,0x01,0,0,0,0,0,0,0,0,0,0xc0,0x07, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xf0,0x7f,0,0,0,0xc0,0xff,0xff,0x01,0,0,0,0,0xc0,0x0f, +0xfc,0x07,0,0,0,0,0,0,0,0,0,0x80,0x0f,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xff,0x0f, +0,0,0,0,0,0,0,0,0,0,0,0xc0,0x0f,0xf0,0x0f, +0,0,0,0,0,0,0,0,0,0,0x1f,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0x80,0xff,0x01,0,0, +0,0,0,0,0,0,0,0,0,0xe0,0x1f,0x80,0x3f,0,0, +0,0,0,0,0,0,0,0,0x1c,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xf8,0x0f,0,0,0,0,0, +0,0,0,0,0,0,0,0xf0,0x1c,0,0xfe,0x03,0,0,0, +0,0,0,0,0,0,0x78,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xf8,0x0f,0,0,0,0,0,0,0, +0,0,0,0,0,0xf0,0x1c,0,0xfe,0x03,0,0,0,0,0, +0,0,0,0,0x78,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xfe,0x01,0,0,0,0,0,0,0,0,0, +0,0,0,0x70,0x1c,0,0xf0,0x07,0,0,0,0,0,0,0, +0,0,0xf0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0x3f,0,0,0,0,0,0,0,0,0,0,0,0, +0,0x70,0x38,0,0xc0,0x1f,0,0,0,0,0,0,0,0,0, +0xe0,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x80, +0x0f,0,0,0,0,0,0,0,0,0,0,0,0,0,0x70, +0x78,0,0,0x7f,0,0,0,0,0,0,0,0,0,0xc0,0x03, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xc0,0x03,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x70,0x70,0, +0,0xfc,0,0,0,0,0,0,0,0,0,0xc0,0x07,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xc0,0x03,0,0,0, +0,0,0,0,0,0,0,0,0,0,0x70,0x70,0,0,0xfc, +0,0,0,0,0,0,0,0,0,0xc0,0x07,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xc0,0x01,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x38,0x70,0,0,0xfe,0x03,0xfe, +0x7f,0,0,0,0,0,0,0,0x0f,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xe0,0x01,0,0,0,0,0,0,0, +0,0,0,0,0,0,0x38,0xf0,0,0,0xfe,0x0f,0xff,0xff,0x01, +0,0,0,0,0,0,0x0f,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xe0,0x01,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x18,0xe0,0,0x80,0x9f,0xff,0x3f,0xfe,0x03,0,0, +0,0,0,0,0x0f,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xe0,0x01,0,0,0,0,0,0,0,0,0,0,0, +0,0,0x1c,0xe0,0,0x80,0x0f,0xff,0x07,0xc0,0x0f,0,0,0,0, +0,0,0x1e,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xe0,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x1c,0xe0,0,0x80,0x0f,0xff,0x07,0xc0,0x0f,0,0,0,0,0,0, +0x1e,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0,0xf1, +0x1f,0,0,0,0,0,0,0,0,0,0,0,0,0x0e,0xe0, +0,0xc0,0x07,0xfc,0x01,0,0x1f,0,0,0,0,0,0,0x3e,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xc0,0xe1,0xff,0, +0,0,0,0,0,0,0,0,0,0,0,0x0e,0xe0,0x01,0xe0, +0x03,0x60,0,0,0x38,0,0,0,0,0,0,0x3c,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xc0,0xc3,0xff,0x01,0,0, +0,0,0,0,0,0,0,0,0,0x07,0xc0,0x01,0xf0,0x01,0, +0xe0,0x03,0xf0,0,0,0,0,0,0,0x38,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x80,0x07,0xf0,0x03,0,0,0,0, +0,0,0,0,0,0,0,0x07,0xc0,0x03,0xf8,0,0,0xf8,0x1f, +0xe0,0,0,0,0,0,0,0x38,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0x80,0x07,0xf0,0x03,0,0,0,0,0,0, +0,0,0,0,0,0x07,0xc0,0x03,0xf8,0,0,0xf8,0x1f,0xe0,0, +0,0,0,0,0,0x38,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0x80,0x0f,0xc0,0x07,0,0,0,0,0,0,0,0, +0,0,0,0x07,0x80,0x03,0x78,0,0,0xf8,0x7f,0xe0,0x01,0,0, +0,0,0,0x78,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0x0f,0x80,0x0f,0,0,0,0,0,0,0,0,0,0, +0x80,0x03,0x80,0x03,0x3e,0,0,0x78,0x7e,0xc0,0x03,0,0,0,0, +0,0x78,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x1e,0x1c,0x0f,0,0,0,0,0,0,0,0,0,0,0x80,0xf3, +0x9f,0x03,0x1f,0,0,0,0xf0,0x80,0x03,0,0,0,0,0,0x70, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0x1e,0xfe, +0x0f,0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0x07, +0x0f,0,0,0,0xe0,0,0x07,0,0,0,0,0,0x70,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0x1e,0xfe,0x0f,0, +0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0x07,0x0f,0, +0,0,0xe0,0,0x07,0,0,0,0,0,0x70,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0x7c,0xfc,0x0f,0,0,0, +0,0,0,0,0,0,0,0xc0,0xff,0xff,0x87,0x07,0,0,0, +0xe0,0,0x07,0,0,0,0,0,0x70,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x7c,0xf8,0x0f,0,0,0,0,0, +0,0,0,0,0,0xc0,0x3f,0xf4,0xc7,0x07,0,0,0,0xe0,0, +0x07,0,0,0,0,0,0x70,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xf0,0x01,0,0,0,0,0,0,0,0, +0,0,0,0xe0,0x03,0x80,0xe7,0x01,0,0,0,0xe0,0,0x07,0, +0,0,0,0,0xe0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xf0,0x03,0,0,0,0,0,0,0,0,0,0, +0,0xe0,0,0,0xff,0x01,0,0,0,0xe0,0x80,0x07,0,0,0, +0,0,0xe0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xe0,0x03,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xff,0,0,0,0,0xf8,0x80,0x03,0,0,0,0,0, +0xe0,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xe0, +0x03,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xff,0,0,0,0,0xf8,0x80,0x03,0,0,0,0,0,0xe0,0x01, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x80,0x07,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0x7e,0, +0,0,0,0x7c,0xc0,0x01,0,0,0,0,0,0xe0,0x01,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0x1f,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0x3e,0,0x80,0x07, +0xe0,0x3f,0xe0,0x01,0,0,0,0,0,0xc0,0x01,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0x1f,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0x1e,0,0xc0,0xff,0xff,0x0f, +0xe0,0,0,0,0,0,0,0xc0,0x01,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x1e,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x1f,0,0xe0,0xff,0xff,0x03,0xe0,0, +0,0,0,0,0,0xc0,0x01,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0x1e,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0x1f,0,0xe0,0xff,0xff,0x03,0xe0,0,0,0, +0,0,0,0xc0,0x01,0,0,0,0,0,0,0,0,0,0, +0,0,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0x3f,0,0x1e,0,0,0,0,0,0,0,0,0,0,0, +0,0,0x80,0x07,0,0x80,0xff,0x7f,0,0xf8,0x01,0,0,0,0, +0,0xc0,0x01,0,0,0,0,0,0,0,0,0,0,0,0, +0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0x03,0x1e,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xc0,0x07,0,0,0,0,0,0xfc,0x07,0,0,0,0,0,0xc0, +0x01,0,0,0,0,0,0,0,0,0,0,0,0,0xe0,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x1e, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xe0,0x03, +0,0,0,0,0,0xfe,0x0f,0,0,0,0,0,0xc0,0x01,0, +0,0,0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x0f,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xf0,0x01,0,0, +0,0,0x80,0xcf,0x3f,0,0,0xfe,0x01,0,0xc0,0x01,0,0,0, +0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x0f,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xf0,0x01,0,0,0,0, +0x80,0xcf,0x3f,0,0,0xfe,0x01,0,0xc0,0x01,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x0f,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xf0,0,0,0,0,0,0xe0,0xe7, +0xff,0,0,0xfe,0x0f,0,0xc0,0xe1,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0x03,0,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0x03,0x0f,0,0,0,0,0,0,0,0, +0,0,0,0,0,0x7c,0,0,0,0,0xf0,0xff,0xf9,0xff,0x01, +0,0xe0,0x1f,0,0xc0,0xe1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0x03,0,0xf8,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0x03,0x0f,0,0,0,0,0,0,0,0,0,0, +0,0,0,0x7e,0,0,0,0xc0,0xff,0x7f,0xfe,0xe1,0x07,0,0xc0, +0xff,0,0xc0,0xe1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0x01,0,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0x03,0x07,0,0,0,0,0,0,0,0,0,0,0,0, +0,0x1e,0,0,0,0xfc,0xff,0x1f,0xff,0x81,0x0f,0,0x80,0xf1,0x03, +0xc0,0xe1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0,0, +0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03, +0x07,0,0,0,0,0,0,0,0,0,0,0,0,0,0x1e, +0,0,0,0xfc,0xff,0x1f,0xff,0x81,0x0f,0,0x80,0xf1,0x03,0xc0,0xe1, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0,0,0xc0,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x81,0x0f,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x1f,0,0, +0,0xff,0x3f,0x80,0xff,0,0x1f,0,0x80,0xc1,0x07,0xc0,0xe1,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0,0,0,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc1,0xff,0x3f,0,0, +0,0,0,0,0,0,0,0,0,0x80,0x0f,0,0x03,0xc0,0x3f, +0,0xe0,0x7f,0,0x7e,0,0x80,0x01,0x1f,0xe0,0xe1,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0,0,0,0xfc,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0xff,0xff,0x03,0,0,0, +0,0,0,0,0,0,0,0x80,0x0f,0x80,0x07,0xf0,0x07,0,0xf0, +0x3f,0,0xf8,0,0x80,0x01,0x3c,0xe0,0xe1,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0x03,0,0,0,0xf8,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0xff,0xff,0x7f,0,0,0,0,0, +0,0,0,0,0,0xc0,0x03,0x80,0xff,0xff,0x01,0,0xfc,0x1f,0, +0xf0,0x01,0xc0,0x01,0x38,0xe0,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0,0,0,0,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0x7f,0xf0,0,0xf8,0xff,0x07,0,0,0,0,0,0, +0,0,0,0xe0,0x03,0,0xfe,0x1f,0,0x80,0xbf,0x07,0,0x80,0x07, +0xc0,0x01,0xe0,0xf1,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f, +0,0,0,0,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0x7f,0xf0,0,0xf8,0xff,0x07,0,0,0,0,0,0,0,0, +0,0xe0,0x03,0,0xfe,0x1f,0,0x80,0xbf,0x07,0,0x80,0x07,0xc0,0x01, +0xe0,0xf1,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0,0, +0,0,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f, +0xf0,0,0,0xfe,0x7f,0,0,0,0,0,0,0,0,0,0xf0, +0x01,0,0xf8,0x03,0,0xc0,0xcf,0x03,0,0x80,0x1f,0xf0,0x01,0xe0,0x71, +0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0,0,0,0, +0,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xf0,0, +0,0xe0,0xff,0x03,0,0,0,0,0,0,0,0,0xf8,0,0, +0,0,0,0xe0,0xe7,0x03,0,0,0x7e,0xff,0,0xc0,0x73,0xf0,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0,0,0,0,0,0xfc, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xf0,0,0,0, +0xfc,0x1f,0,0,0,0,0,0,0,0,0x78,0,0,0,0, +0,0xf8,0xf3,0,0,0,0xfc,0x7f,0,0,0x7f,0xf0,0xff,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0,0,0,0,0,0,0xf0,0xff,0xff, +0xff,0x1f,0,0,0,0,0,0,0,0xf0,0,0,0,0xe0,0xff, +0,0,0,0,0,0,0,0,0x3c,0,0,0,0,0,0x7c, +0xf8,0,0,0,0xf8,0xff,0xff,0xff,0x7f,0xf0,0xff,0xff,0xff,0xff,0xff, +0xff,0xff,0xff,0x7f,0,0,0,0,0,0,0xf0,0xff,0xff,0xff,0x1f, +0,0,0,0,0,0,0,0xf0,0,0,0,0xe0,0xff,0,0, +0,0,0,0,0,0,0x3c,0,0,0,0,0,0x7c,0xf8,0, +0,0,0xf8,0xff,0xff,0xff,0x7f,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xff,0x7f,0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0x3f,0,0, +0,0,0,0,0,0x70,0,0,0,0x80,0xff,0x0f,0,0,0, +0,0,0,0,0x3e,0,0,0,0,0,0x7f,0x7c,0,0,0, +0xe0,0xff,0xff,0xff,0x7f,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f, +0,0,0,0,0,0,0x80,0xff,0xff,0xff,0xff,0,0,0,0, +0,0,0,0x78,0,0,0,0,0xfe,0x7f,0,0,0,0,0, +0,0,0x1e,0,0,0,0,0xc0,0x1f,0x3e,0,0,0,0xc0,0xff, +0xff,0xff,0x7f,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0,0, +0,0,0,0,0,0xff,0xff,0xff,0xff,0x01,0,0,0,0,0, +0,0x7c,0,0,0,0,0xf0,0xff,0x03,0,0,0,0,0,0, +0x0f,0,0,0,0,0xe0,0x07,0x1f,0,0,0,0x80,0x0f,0,0, +0x3c,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0,0,0,0, +0,0,0,0xfc,0xff,0xff,0xff,0x07,0,0,0,0,0,0,0x3c, +0,0,0,0,0,0xfe,0x0f,0,0,0,0,0,0,0x0f,0, +0,0,0,0xfc,0x83,0x0f,0,0,0,0,0x0f,0,0,0x38,0xf0, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0,0,0,0,0,0, +0,0xfc,0xff,0xff,0xff,0x07,0,0,0,0,0,0,0x3c,0,0, +0,0,0,0xfe,0x0f,0,0,0,0,0,0,0x0f,0,0,0, +0,0xfc,0x83,0x0f,0,0,0,0,0x0f,0,0,0x38,0xf0,0xff,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0x01,0,0,0,0,0,0,0,0xf0, +0xff,0xff,0xff,0x0f,0,0,0,0,0,0,0x1e,0,0,0,0xf8, +0xff,0xff,0x3f,0,0,0,0,0,0x80,0x07,0,0,0,0,0xff, +0x80,0x07,0,0,0,0,0x3e,0,0,0x38,0,0,0,0,0, +0xff,0xff,0xff,0x7f,0,0,0,0,0,0,0,0,0xc0,0xff,0xff, +0xff,0x7f,0,0,0,0,0,0,0x0f,0,0,0,0xff,0xff,0xff, +0xff,0x03,0,0,0,0,0xe0,0x01,0,0,0,0xe0,0x1f,0xe0,0x03, +0,0,0,0,0x78,0,0,0x1c,0,0,0,0,0xe0,0xff,0xff, +0xff,0x0f,0,0,0,0,0,0,0,0,0,0xff,0xff,0xff,0xff, +0,0,0,0,0,0x80,0x0f,0,0,0,0xff,0x3f,0xe0,0xff,0x0f, +0,0,0,0,0xf0,0x01,0,0,0,0xf8,0x07,0xf0,0x01,0,0, +0,0,0xf0,0x01,0,0x1e,0,0,0,0,0xf0,0xff,0xff,0xff,0x07, +0,0,0,0,0,0,0,0,0,0xfe,0xff,0xff,0xff,0x03,0, +0,0,0,0x80,0x07,0,0,0,0xe0,0xff,0x01,0xfe,0x3f,0,0, +0,0,0xf0,0,0,0,0,0xfe,0x01,0xf8,0,0,0,0,0, +0xc0,0x03,0,0x0e,0,0,0,0,0xfc,0xff,0xff,0xff,0x01,0,0, +0,0,0,0,0,0,0,0xfe,0xff,0xff,0xff,0x03,0,0,0, +0,0x80,0x07,0,0,0,0xe0,0xff,0x01,0xfe,0x3f,0,0,0,0, +0xf0,0,0,0,0,0xfe,0x01,0xf8,0,0,0,0,0,0xc0,0x03, +0,0x0e,0,0,0,0,0xfc,0xff,0xff,0xff,0x01,0,0,0,0, +0,0,0,0,0,0xf8,0xff,0xff,0xff,0x07,0,0,0,0,0x80, +0x07,0,0,0,0,0xf8,0x07,0xc0,0xff,0x01,0,0,0,0xf8,0, +0,0,0x80,0x7f,0,0x78,0,0,0,0,0,0xc0,0x0f,0,0x0e, +0,0,0,0,0xff,0xff,0xff,0xff,0,0,0,0,0,0,0, +0,0,0,0xf0,0xff,0xff,0xff,0x1f,0,0,0,0,0xc0,0xe3,0xff, +0xff,0,0,0xc0,0x1f,0x80,0xff,0x03,0,0,0,0x3c,0,0,0, +0xe0,0x1f,0,0x3e,0,0,0,0,0,0,0x0f,0,0x07,0,0, +0,0x80,0xff,0xff,0xff,0x1f,0,0,0,0,0,0,0,0,0, +0,0xc0,0xff,0xff,0xff,0x7f,0,0,0,0,0xc0,0xfb,0xff,0xff,0x0f, +0,0,0x3e,0x80,0xf3,0x1f,0,0,0,0x3e,0,0,0,0xf8,0x07, +0,0x1e,0,0,0,0,0,0,0x1e,0,0x07,0,0,0,0xe0, +0xff,0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,0,0, +0xff,0xff,0xff,0xff,0,0,0,0,0xc0,0xff,0xff,0xff,0xff,0,0, +0x7c,0xc0,0x81,0xff,0,0,0,0x1f,0,0,0,0xff,0x01,0,0x0f, +0,0,0,0,0,0,0x7c,0x80,0x07,0,0,0,0xf0,0xff,0xff, +0xff,0x03,0,0,0,0,0,0,0,0,0,0,0,0xfc,0xff, +0xff,0xff,0x03,0,0,0,0xc0,0x7f,0,0xe0,0xff,0x3f,0,0xf0,0xc0, +0x01,0xfe,0x03,0,0,0x0f,0,0,0xc0,0x7f,0,0xc0,0x07,0,0, +0,0,0,0,0xf0,0xc0,0x03,0,0,0,0xfc,0xff,0xff,0xff,0, +0,0,0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0xff, +0x03,0,0,0,0xc0,0x7f,0,0xe0,0xff,0x3f,0,0xf0,0xc0,0x01,0xfe, +0x03,0,0,0x0f,0,0,0xc0,0x7f,0,0xc0,0x07,0,0,0,0, +0,0,0xf0,0xc0,0x03,0,0,0,0xfc,0xff,0xff,0xff,0,0,0, +0,0,0,0,0,0,0,0,0,0xf8,0xff,0xff,0xff,0x07,0, +0,0,0xc0,0x0f,0,0,0xfc,0xff,0x03,0xc0,0xe3,0x01,0xf0,0x07,0, +0x80,0x07,0,0,0xf0,0x1f,0,0xc0,0x07,0,0,0,0,0,0, +0xf0,0xc1,0x01,0,0,0,0xff,0xff,0xff,0x7f,0,0,0,0,0, +0,0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0x1f,0,0,0, +0xc0,0x07,0,0,0,0xfc,0xff,0,0xf7,0,0,0x3f,0,0xc0,0x03, +0,0,0xff,0,0,0xe0,0x01,0,0,0,0,0,0,0xc0,0xe3, +0x01,0,0,0xc0,0xff,0xff,0xff,0x0f,0,0,0,0,0,0,0, +0,0,0,0,0,0x80,0xff,0xff,0xff,0xff,0,0,0,0xc0,0x01, +0,0,0,0xc0,0xff,0x07,0x7f,0,0,0xfc,0,0xe0,0x03,0,0xe0, +0x3f,0,0,0xf0,0x01,0,0,0,0,0,0,0x80,0xff,0,0, +0,0xf0,0xff,0xff,0xff,0x07,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xfe,0xff,0xff,0xff,0,0,0,0xc0,0x01,0,0, +0,0,0xfe,0x7f,0x7f,0,0,0xf8,0x01,0xe0,0x01,0,0xfc,0x07,0, +0,0xf8,0,0,0,0,0,0,0,0,0xff,0,0,0,0xfc, +0xff,0xff,0xff,0x01,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xfe,0xff,0xff,0xff,0,0,0,0xc0,0x01,0,0,0,0, +0xfe,0x7f,0x7f,0,0,0xf8,0x01,0xe0,0x01,0,0xfc,0x07,0,0,0xf8, +0,0,0,0,0,0,0,0,0xff,0,0,0,0xfc,0xff,0xff, +0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xfc,0xff,0xff,0xff,0x03,0,0,0xc0,0x03,0,0,0,0,0xe0,0xff, +0x3f,0,0,0xf0,0x07,0xf0,0,0,0xff,0x03,0,0,0x7c,0,0, +0,0,0,0,0,0,0x7e,0,0,0,0xff,0xff,0xff,0x7f,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff, +0xff,0xff,0x0f,0,0,0xc0,0x03,0,0,0,0,0,0xfe,0x3f,0, +0,0xc0,0x3f,0xf8,0,0xf8,0x3f,0,0,0,0x3c,0,0,0,0, +0,0,0,0,0x3c,0,0,0x80,0xff,0xff,0xff,0x3f,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0xff, +0x3f,0,0,0xc0,0x03,0,0,0,0,0,0xf0,0xff,0x0f,0,0, +0x7f,0x7c,0,0xfe,0x07,0,0,0,0x1e,0,0,0,0,0,0, +0,0,0x1e,0,0,0xe0,0xff,0xff,0xff,0x0f,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,0xff,0x7f,0, +0,0x80,0x07,0,0,0,0,0,0,0xff,0x7f,0,0,0xfc,0x3e, +0xe0,0x7f,0,0,0,0,0x1f,0,0,0,0,0,0,0,0, +0x1f,0,0,0xf8,0xff,0xff,0xff,0x03,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x80,0xff,0xff,0xff,0x7f,0,0,0x80, +0x07,0,0,0,0,0,0,0xff,0x7f,0,0,0xfc,0x3e,0xe0,0x7f, +0,0,0,0,0x1f,0,0,0,0,0,0,0,0,0x1f,0, +0,0xf8,0xff,0xff,0xff,0x03,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xfe,0xff,0xff,0xff,0x01,0,0x80,0x0f,0, +0,0,0,0,0,0xf0,0xff,0x1f,0,0xf0,0x1f,0xfe,0x0f,0,0, +0,0x80,0x0f,0,0,0,0,0,0,0,0,0x07,0,0,0xfc, +0xff,0xff,0xff,0x01,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xf8,0xff,0xff,0xff,0x03,0,0,0x0f,0,0,0, +0,0,0,0,0xfc,0xff,0x3f,0xc0,0xff,0xff,0,0,0,0,0xc0, +0x07,0,0,0,0,0,0,0,0x80,0x03,0,0,0xff,0xff,0xff, +0x3f,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xf0,0xff,0xff,0xff,0x0f,0,0,0x1e,0,0,0,0,0, +0,0,0,0xfe,0xff,0xff,0xff,0x1f,0,0,0,0,0xe0,0x03,0, +0,0,0,0,0,0,0xe0,0x03,0,0xc0,0xff,0xff,0xff,0x1f,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x80,0xff,0xff,0xff,0x7f,0,0,0x3c,0,0,0,0,0,0,0, +0,0,0xfc,0xff,0xff,0x03,0,0,0,0,0xf0,0x01,0,0,0, +0,0,0,0,0xf8,0,0,0xf8,0xff,0xff,0xff,0x03,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0x80,0xff, +0xff,0xff,0x7f,0,0,0x3c,0,0,0,0,0,0,0,0,0, +0xfc,0xff,0xff,0x03,0,0,0,0,0xf0,0x01,0,0,0,0,0, +0,0,0xf8,0,0,0xf8,0xff,0xff,0xff,0x03,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xfe,0xff,0xff, +0xff,0,0,0x78,0,0,0,0,0,0,0,0,0,0,0xf8, +0xff,0x1f,0,0,0,0,0xf0,0,0,0,0,0,0,0,0, +0x7c,0,0,0xfc,0xff,0xff,0xff,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0xff,0x03, +0,0xf0,0,0,0,0,0,0,0,0,0,0,0,0xfe,0x7f, +0,0,0,0,0x7c,0,0,0,0,0,0,0,0,0x3e,0, +0,0xff,0xff,0xff,0x7f,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xf0,0xff,0xff,0xff,0x07,0,0xe0, +0x01,0,0,0,0,0,0,0,0,0,0,0x7c,0xfe,0,0, +0,0,0x3c,0,0,0,0,0,0,0,0x80,0x1f,0,0xc0,0xff, +0xff,0xff,0x1f,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0x1f,0,0xc0,0x03,0, +0,0,0,0,0,0,0,0,0,0x78,0xf8,0x03,0,0,0, +0x1e,0,0,0,0,0,0,0,0xc0,0x07,0,0xe0,0xff,0xff,0xff, +0x07,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x80,0xff,0xff,0xff,0x7f,0,0x80,0x07,0,0,0, +0,0,0,0,0,0,0,0x70,0xe0,0x0f,0,0,0,0x0f,0, +0,0,0,0,0,0,0xf0,0x03,0,0xf8,0xff,0xff,0xff,0x03,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0x80,0xff,0xff,0xff,0x7f,0,0x80,0x07,0,0,0,0,0, +0,0,0,0,0,0x70,0xe0,0x0f,0,0,0,0x0f,0,0,0, +0,0,0,0,0xf0,0x03,0,0xf8,0xff,0xff,0xff,0x03,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xff,0xff,0xff,0xff,0,0x80,0x0f,0,0,0,0,0,0,0, +0,0,0,0x70,0,0x3f,0,0,0x80,0x0f,0,0,0,0,0, +0,0,0xf8,0x01,0,0xfe,0xff,0xff,0x7f,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xfc, +0xff,0xff,0xff,0x03,0,0x1f,0,0,0,0,0,0,0,0,0, +0,0x70,0,0xfe,0,0,0xc0,0x03,0,0,0,0,0,0,0, +0x7e,0,0x80,0xff,0xff,0xff,0x3f,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff,0xff, +0xff,0x0f,0,0x3e,0,0,0,0,0,0,0,0,0,0,0x70, +0,0xf8,0x01,0,0xc0,0x03,0,0,0,0,0,0,0,0x3e,0, +0xc0,0xff,0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0xff,0x3f, +0,0xf8,0,0,0,0,0,0,0,0,0,0,0x70,0,0x80, +0x0f,0,0xf0,0x01,0,0,0,0,0,0,0xc0,0x0f,0,0xf8,0xff, +0xff,0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0xff,0x3f,0,0xf8, +0,0,0,0,0,0,0,0,0,0,0x70,0,0x80,0x0f,0, +0xf0,0x01,0,0,0,0,0,0,0xc0,0x0f,0,0xf8,0xff,0xff,0xff, +0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xff,0xff,0xff,0xff,0,0xe0,0x01,0, +0,0,0,0,0,0,0,0,0x70,0,0,0x3e,0,0xf0,0, +0,0,0,0,0,0,0xe0,0x07,0,0xfe,0xff,0xff,0xff,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xfc,0xff,0xff,0xff,0x03,0xc0,0x03,0,0,0, +0,0,0,0,0,0,0x70,0,0,0xfc,0,0x78,0,0,0, +0,0,0,0,0xf8,0x01,0x80,0xff,0xff,0xff,0x3f,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xf0,0xff,0xff,0xff,0x0f,0xc0,0x07,0,0,0,0,0, +0,0,0,0,0x78,0,0,0xe0,0x03,0x3c,0,0,0,0,0, +0,0,0x7c,0,0xe0,0xff,0xff,0xff,0x0f,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xc0,0xff,0xff,0xff,0x1f,0,0x0f,0,0,0,0,0,0,0, +0,0,0x7c,0,0,0xc0,0x1f,0x1e,0,0,0,0,0,0,0, +0x3e,0,0xf0,0xff,0xff,0xff,0x03,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0, +0xff,0xff,0xff,0x1f,0,0x0f,0,0,0,0,0,0,0,0,0, +0x7c,0,0,0xc0,0x1f,0x1e,0,0,0,0,0,0,0,0x3e,0, +0xf0,0xff,0xff,0xff,0x03,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x80,0xff,0xff, +0xff,0x7f,0,0x1e,0,0,0,0,0,0,0,0,0,0x7c,0, +0,0,0x3f,0x0f,0,0,0,0,0,0,0x80,0x0f,0,0xfc,0xff, +0xff,0xff,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xfe,0xff,0xff,0xff, +0x01,0x7c,0,0,0,0,0,0,0,0,0,0x3c,0,0,0, +0xfc,0x0f,0,0,0,0,0,0,0xe0,0x07,0,0xff,0xff,0xff,0x3f, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0xff,0x03,0x78, +0,0,0,0,0,0,0,0,0,0x3c,0,0,0,0xf8,0x07, +0,0,0,0,0,0,0xf0,0x01,0xc0,0xff,0xff,0xff,0x1f,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xf0,0xff,0xff,0xff,0x07,0xf0,0x01,0, +0,0,0,0,0,0,0,0x1c,0,0,0,0xfc,0x03,0,0, +0,0,0,0,0xf8,0,0xf0,0xff,0xff,0xff,0x07,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xf0,0xff,0xff,0xff,0x07,0xf0,0x01,0,0,0, +0,0,0,0,0,0x1c,0,0,0,0xfc,0x03,0,0,0,0, +0,0,0xf8,0,0xf0,0xff,0xff,0xff,0x07,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xe0,0xff,0xff,0xff,0x1f,0xe0,0x03,0,0,0,0,0, +0,0,0,0x1c,0,0,0,0xfc,0x01,0,0,0,0,0,0, +0x7e,0,0xf8,0xff,0xff,0xff,0x01,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xff,0xff,0xff,0xff,0x80,0x0f,0,0,0,0,0,0,0, +0,0x1e,0,0,0,0xff,0,0,0,0,0,0,0x80,0x0f,0, +0xfe,0xff,0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xfc,0xff,0xff,0xff,0x01,0x1f,0,0,0,0,0,0,0,0,0x0e, +0,0,0x80,0x7f,0,0,0,0,0,0,0xc0,0x07,0x80,0xff,0xff, +0xff,0x0f,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xf8,0xff, +0xff,0xff,0x07,0x3e,0,0,0,0,0,0,0,0,0x0e,0,0, +0xc0,0x3f,0,0,0,0,0,0,0xf0,0x01,0xe0,0xff,0xff,0xff,0x07, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0xff,0xff, +0x0f,0x7c,0,0,0,0,0,0,0,0,0x0f,0,0,0xe0,0x3f, +0,0,0,0,0,0,0xf8,0x01,0xf8,0xff,0xff,0xff,0x01,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0x0f,0x7c, +0,0,0,0,0,0,0,0,0x0f,0,0,0xe0,0x3f,0,0, +0,0,0,0,0xf8,0x01,0xf8,0xff,0xff,0xff,0x01,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xc0,0xff,0xff,0xff,0x3f,0xf0,0,0, +0,0,0,0,0,0,0x0f,0,0,0xf0,0x1f,0,0,0,0, +0,0,0x7e,0,0xfc,0xff,0xff,0xff,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xfe,0xff,0xff,0x7f,0xe0,0x01,0,0,0, +0,0,0,0x80,0x07,0,0,0xfc,0x1f,0,0,0,0,0,0, +0x3e,0,0xff,0xff,0xff,0x3f,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xfc,0xff,0xff,0xff,0xe0,0x03,0,0,0,0,0, +0,0x80,0x07,0,0,0xfc,0x0f,0,0,0,0,0,0,0x1f,0xc0, +0xff,0xff,0xff,0x1f,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xf0,0xff,0xff,0xff,0xc1,0x07,0,0,0,0,0,0,0xc0, +0x03,0,0,0xfe,0x07,0,0,0,0,0,0xc0,0x0f,0xf0,0xff,0xff, +0xff,0x07,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xf0,0xff,0xff,0xff,0xc1,0x07,0,0,0,0,0,0,0xc0,0x03,0, +0,0xfe,0x07,0,0,0,0,0,0xc0,0x0f,0xf0,0xff,0xff,0xff,0x07, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff, +0xff,0xff,0x83,0x0f,0,0,0,0,0,0,0xc0,0x01,0,0,0xff, +0x07,0,0,0,0,0,0xc0,0x07,0xf8,0xff,0xff,0xff,0x03,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,0xff, +0x0f,0x1e,0,0,0,0,0,0,0xe0,0x01,0,0xc0,0xef,0x03,0, +0,0,0,0,0xe0,0x01,0xff,0xff,0xff,0x7f,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xfe,0xff,0xff,0x0f,0x1c, +0,0,0,0,0,0,0xf0,0,0,0xe0,0xf3,0x01,0,0,0, +0,0,0xf0,0x80,0xff,0xff,0xff,0x1f,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0x1f,0x38,0,0, +0,0,0,0,0x70,0,0,0xf0,0xf9,0,0,0,0,0,0, +0x78,0xe0,0xff,0xff,0xff,0x07,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xfc,0xff,0xff,0x1f,0x38,0,0,0,0, +0,0,0x70,0,0,0xf0,0xf9,0,0,0,0,0,0,0x78,0xe0, +0xff,0xff,0xff,0x07,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xf0,0xff,0xff,0x7f,0xf0,0,0,0,0,0,0, +0x78,0,0,0x78,0x7c,0,0,0,0,0,0,0x3c,0xf0,0xff,0xff, +0xff,0x03,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0x80,0xff,0xff,0xff,0xe0,0,0,0,0,0,0,0x78,0, +0,0x7e,0x7c,0,0,0,0,0,0,0x3c,0xf8,0xff,0xff,0xff,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xff,0xff,0xff,0xe0,0x01,0,0,0,0,0,0x3c,0,0,0x3e, +0x3e,0,0,0,0,0,0,0x1f,0xfe,0xff,0xff,0x7f,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xfe, +0xff,0xff,0xc1,0x03,0,0,0,0,0,0x3c,0,0,0x0f,0x1e,0, +0,0,0,0,0,0x0f,0xfe,0xff,0xff,0x1f,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xfe,0xff,0xff, +0xc1,0x03,0,0,0,0,0,0x3c,0,0,0x0f,0x1e,0,0,0, +0,0,0,0x0f,0xfe,0xff,0xff,0x1f,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0x83,0x07, +0,0,0,0,0,0x1e,0,0xc0,0x07,0x0f,0,0,0,0,0, +0x80,0x07,0xff,0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xf0,0xff,0xff,0x07,0x0f,0,0, +0,0,0,0x0f,0,0xe0,0x83,0x0f,0,0,0,0,0,0x80,0xc7, +0xff,0xff,0xff,0x01,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xc0,0xff,0xff,0x0f,0x0f,0,0,0,0, +0,0x07,0,0xf0,0x81,0x07,0,0,0,0,0,0xc0,0xc3,0xff,0xff, +0xff,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xff,0xff,0x1f,0x1c,0,0,0,0,0x80,0x03, +0,0x7c,0xc0,0x03,0,0,0,0,0,0xe0,0xe1,0xff,0xff,0x7f,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xfe,0xff,0x3f,0x3c,0,0,0,0,0xc0,0x03,0,0x3f, +0xe0,0x01,0,0,0,0,0,0xe0,0xe0,0xff,0xff,0x1f,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xfe,0xff,0x3f,0x3c,0,0,0,0,0xc0,0x03,0,0x3f,0xe0,0x01, +0,0,0,0,0,0xe0,0xe0,0xff,0xff,0x1f,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xf8, +0xff,0x3f,0x3c,0,0,0,0,0xe0,0x01,0x80,0x1f,0xe0,0x01,0,0, +0,0,0,0xf0,0xe0,0xff,0xff,0x07,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xf8,0xff,0x3f, +0x38,0,0,0,0,0xe0,0,0xe0,0x07,0xf0,0,0,0,0,0, +0,0x78,0xf8,0xff,0xff,0x01,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xf8,0xff,0x3f,0x38,0, +0,0,0,0xf0,0,0xf0,0x03,0x70,0,0,0,0,0,0,0x78, +0xf8,0xff,0xff,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xf8,0xff,0x3f,0x38,0,0,0, +0,0x70,0,0xfe,0,0x38,0,0,0,0,0,0,0x3c,0xfc,0xff, +0x3f,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xf8,0xff,0x3f,0x38,0,0,0,0,0x70, +0,0xfe,0,0x38,0,0,0,0,0,0,0x3c,0xfc,0xff,0x3f,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xf8,0xff,0x3f,0x38,0,0,0,0,0x38,0x80,0x3f, +0,0x3c,0,0,0,0,0,0,0x1c,0xfc,0xff,0x3f,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xfc,0xff,0x3f,0x38,0,0,0,0,0x1c,0xc0,0x0f,0,0x1c, +0,0,0,0,0,0,0x1e,0xfc,0xff,0x3f,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xfc,0xff,0x1f,0x38,0,0,0,0,0x1e,0xf0,0x03,0,0x1e,0,0, +0,0,0,0,0x1e,0xfc,0xff,0x3f,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xfe,0xff, +0x1f,0x38,0,0,0,0,0x0f,0x7f,0,0,0x0f,0,0,0,0, +0,0,0x0f,0xfc,0xff,0x3f,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xfe,0xff,0x1f,0x38, +0,0,0,0,0x0f,0x7f,0,0,0x0f,0,0,0,0,0,0, +0x0f,0xfc,0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xfe,0xff,0x1f,0x38,0,0, +0,0,0xe7,0x3f,0,0,0x07,0,0,0,0,0,0,0x0f,0xfc, +0xff,0x7f,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xff,0xff,0x0f,0x38,0,0,0,0x80, +0xfb,0x0f,0,0x80,0x03,0,0,0,0,0,0,0x07,0xfc,0xff,0x7f, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xff,0xff,0x07,0x38,0,0,0,0xc0,0xff,0x01, +0,0xc0,0x03,0,0,0,0,0,0x80,0x07,0xf8,0xff,0xff,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xff,0xff,0x07,0x38,0,0,0,0xe0,0x3f,0,0,0xc0, +0x01,0,0,0,0,0,0xc0,0x03,0xf8,0xff,0xff,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xff,0xff,0x07,0x38,0,0,0,0xe0,0x3f,0,0,0xc0,0x01,0, +0,0,0,0,0xc0,0x03,0xf8,0xff,0xff,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0x80,0xff, +0xff,0x07,0x38,0,0,0,0xe0,0x0f,0,0,0xe0,0,0,0,0, +0,0,0xc0,0x03,0xf8,0xff,0xff,0x01,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,0x03, +0x38,0,0,0,0xf0,0x03,0,0,0xf0,0,0,0,0,0,0, +0xe0,0x01,0xf8,0xff,0xff,0x01,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0x03,0x38,0, +0,0,0x70,0,0,0,0x70,0,0,0,0,0,0,0xe0,0x01, +0xf0,0xff,0xff,0x01,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xc0,0xff,0xff,0x01,0x38,0,0,0, +0,0,0,0,0x78,0,0,0,0,0,0,0xe0,0,0xf0,0xff, +0xff,0x03,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xe0,0xff,0xff,0,0x38,0,0,0,0,0, +0,0,0x38,0,0,0,0,0,0,0xf0,0,0xf0,0xff,0xff,0x03, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xe0,0xff,0xff,0,0x38,0,0,0,0,0,0,0, +0x38,0,0,0,0,0,0,0xf0,0,0xf0,0xff,0xff,0x03,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xe0,0xff,0xff,0,0x38,0,0,0,0,0,0,0,0x3c,0, +0,0,0,0,0,0xf0,0,0xe0,0xff,0xff,0x07,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xe0, +0xff,0xff,0,0x38,0,0,0,0,0,0,0,0x1e,0,0,0, +0,0,0,0x78,0,0xe0,0xff,0xff,0x07,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff,0x7f, +0,0x18,0,0,0,0,0,0,0,0x1e,0,0,0,0,0, +0,0x78,0,0xc0,0xff,0xff,0x0f,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xf0,0xff,0x7f,0,0x18, +0,0,0,0,0,0,0,0x0f,0,0,0,0,0,0,0x3c, +0,0xc0,0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xf0,0xff,0x7f,0,0x18,0,0, +0,0,0,0,0,0x0f,0,0,0,0,0,0,0x3c,0,0xc0, +0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xf8,0xff,0x7f,0,0x1c,0,0,0,0, +0,0,0x80,0x07,0,0,0,0,0,0,0x3c,0,0x80,0xff,0xff, +0x0f,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xf8,0xff,0x3f,0,0x1c,0,0,0,0,0,0, +0x80,0x07,0,0,0,0,0,0,0x1e,0,0x80,0xff,0xff,0x1f,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xfc,0xff,0x1f,0,0x1c,0,0,0,0,0,0,0xc0,0x03, +0,0,0,0,0,0,0x1e,0,0x80,0xff,0xff,0x1f,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xfc,0xff,0x1f,0,0x1c,0,0,0,0,0,0,0xc0,0x03,0,0, +0,0,0,0,0x1f,0,0,0xff,0xff,0x1f,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xfc,0xff, +0x1f,0,0x1c,0,0,0,0,0,0,0xc0,0x03,0,0,0,0, +0,0,0x1f,0,0,0xff,0xff,0x1f,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xfe,0xff,0x0f,0, +0x1c,0,0,0,0,0,0,0xe0,0x01,0,0,0,0,0,0, +0x0f,0,0,0xff,0xff,0x3f,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xfe,0xff,0x0f,0,0x1c,0, +0,0,0,0,0,0xe0,0,0,0,0,0,0,0,0x0f,0, +0,0xff,0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xfe,0xff,0x07,0,0x1c,0,0,0, +0,0,0,0xf0,0,0,0,0,0,0,0x80,0x07,0,0,0xfe, +0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xff,0xff,0x07,0,0x1e,0,0,0,0,0, +0,0x70,0,0,0,0,0,0,0x80,0x07,0,0,0xfe,0xff,0x7f, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xff,0xff,0x07,0,0x1e,0,0,0,0,0,0,0x70, +0,0,0,0,0,0,0x80,0x07,0,0,0xfe,0xff,0x7f,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xff,0xff,0x07,0,0x1e,0,0,0,0,0,0,0x78,0,0, +0,0,0,0,0x80,0x07,0,0,0xfc,0xff,0x7f,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0x80,0xff, +0xff,0x03,0,0x1e,0,0,0,0,0,0,0x38,0,0,0,0, +0,0,0x80,0x03,0,0,0xfc,0xff,0xff,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,0x03, +0,0x1e,0,0,0,0,0,0,0x3c,0,0,0,0,0,0, +0xc0,0x03,0,0,0xfc,0xff,0xff,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0x03,0,0x1e, +0,0,0,0,0,0,0x1e,0,0,0,0,0,0,0xc0,0x03, +0,0,0xf8,0xff,0xff,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xc0,0xff,0xff,0x03,0,0x1e,0,0, +0,0,0,0,0x1e,0,0,0,0,0,0,0xc0,0x03,0,0, +0xf8,0xff,0xff,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xc0,0xff,0xff,0x01,0,0x1e,0,0,0,0, +0,0,0x1e,0,0,0,0,0,0,0xc0,0x03,0,0,0xf8,0xff, +0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xe0,0xff,0xff,0x01,0,0x1c,0,0,0,0,0,0, +0x0f,0,0,0,0,0,0,0xc0,0x01,0,0,0xf0,0xff,0xff,0x01, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xe0,0xff,0xff,0,0,0x1c,0,0,0,0,0,0x80,0x07,0, +0,0,0,0,0,0xc0,0x01,0,0,0xf0,0xff,0xff,0x01,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xe0, +0xff,0xff,0,0,0x3c,0,0,0,0,0,0x80,0x07,0,0,0, +0,0,0,0xc0,0x01,0,0,0xf0,0xff,0xff,0x03,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff,0x7f, +0,0,0x3c,0,0,0,0,0,0x80,0x03,0,0,0,0,0, +0,0xc0,0x01,0,0,0xe0,0xff,0xff,0x03,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xf0,0xff,0x7f,0,0, +0x3c,0,0,0,0,0,0x80,0x03,0,0,0,0,0,0,0xc0, +0x01,0,0,0xe0,0xff,0xff,0x03,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xf0,0xff,0x7f,0,0,0x38,0, +0,0,0,0,0xc0,0x03,0,0,0,0,0,0,0xc0,0x01,0, +0,0xe0,0xff,0xff,0x03,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xf8,0xff,0x3f,0,0,0x38,0,0,0, +0,0,0xc0,0x01,0,0,0,0,0,0,0xc0,0x01,0,0,0xe0, +0xff,0xff,0x07,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xf8,0xff,0x3f,0,0,0x38,0,0,0,0,0, +0xe0,0x01,0,0,0,0,0,0,0xc0,0x01,0,0,0xc0,0xff,0xff, +0x07,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xfc,0xff,0x1f,0,0,0x38,0,0,0,0,0,0xe0,0, +0,0,0,0,0,0,0xc0,0x01,0,0,0xc0,0xff,0xff,0x07,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xfc,0xff,0x1f,0,0,0x38,0,0,0,0,0,0xe0,0,0,0, +0,0,0,0,0xc0,0x01,0,0,0xc0,0xff,0xff,0x07,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xfc,0xff, +0x1f,0,0,0x38,0,0,0,0,0,0xf0,0,0,0,0,0, +0,0,0xc0,0x01,0,0,0x80,0xff,0xff,0x0f,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xfc,0xff,0x1f,0, +0,0x38,0,0,0,0,0,0x78,0,0,0,0,0,0,0, +0xc0,0x03,0,0,0x80,0xff,0xff,0x0f,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xfe,0xff,0x0f,0,0,0x38, +0,0,0,0,0,0x78,0,0,0,0,0,0,0,0xc0,0x03, +0,0,0,0xff,0xff,0x1f,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xfe,0xff,0x0f,0,0,0x3c,0,0, +0,0,0,0x3c,0,0,0,0,0,0,0,0x80,0x07,0,0, +0,0xff,0xff,0x1f,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xfe,0xff,0x0f,0,0,0x3c,0,0,0,0, +0,0x3c,0,0,0,0,0,0,0,0x80,0x07,0,0,0,0xff, +0xff,0x1f,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xff,0x07,0,0,0xfc,0x3f,0,0,0,0,0,0x3e, +0,0,0,0,0,0,0,0x80,0x07,0,0,0,0xfe,0xff,0x1f, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0x0f,0,0xe0,0xff,0xff,0x3f,0,0,0,0,0,0x1e,0,0, +0,0,0,0,0,0,0x0f,0,0,0,0xfe,0xff,0x3f,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xfc,0xff,0xff,0xff,0x3f,0,0,0,0,0,0x0f,0,0,0,0, +0,0,0,0,0x0f,0,0,0,0xfe,0xff,0x3f,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0xff, +0xff,0x0f,0x3c,0,0,0,0,0,0x0f,0,0,0,0,0,0, +0,0,0x0e,0,0,0,0xfc,0xff,0x3f,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0x0f, +0x3c,0,0,0,0,0,0x0f,0,0,0,0,0,0,0,0, +0x0e,0,0,0,0xfc,0xff,0x3f,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0x01,0,0x38,0, +0,0,0,0x80,0x07,0,0,0,0,0,0,0,0,0x1e,0, +0,0,0xfc,0xff,0x7f,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xf0,0xff,0xff,0,0,0,0x38,0,0,0, +0,0x80,0x07,0,0,0,0,0,0,0,0,0x3c,0,0,0, +0xfc,0xff,0x7f,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xff,0xff,0x03,0,0,0,0x38,0,0,0,0,0xc0, +0x03,0,0,0,0,0,0,0,0,0x78,0,0,0,0xf8,0xff, +0x7f,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xfc,0xff,0x1f,0,0,0,0,0x78,0,0,0,0,0xc0,0x01,0, +0,0,0,0,0,0,0,0x70,0,0,0,0xf8,0xff,0xff,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff, +0x01,0,0,0,0,0x70,0,0,0,0,0xe0,0x01,0,0,0, +0,0,0,0,0,0xf0,0x01,0,0,0xf0,0xff,0xff,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0xff,0x01,0, +0,0,0,0x70,0,0,0,0,0xe0,0x01,0,0,0,0,0, +0,0,0,0xf0,0x01,0,0,0xf0,0xff,0xff,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xff,0xff,0x07,0,0xfe,0,0, +0,0x70,0,0,0,0,0xe0,0,0,0,0,0,0,0,0, +0,0xe0,0x03,0,0,0xf0,0xff,0xff,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xf0,0xff,0x1f,0,0xf8,0xff,0,0,0,0x70, +0,0,0,0,0xf0,0,0,0,0,0,0,0,0,0,0xc0, +0x03,0,0,0xf0,0xff,0xff,0x01,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xfe,0x7f,0,0xe0,0xff,0x7f,0,0,0,0x70,0,0, +0,0,0xf8,0,0,0,0,0,0,0,0,0,0x80,0x0f,0, +0,0xf0,0xff,0xff,0x01,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xe0,0xff,0x03,0,0xf0,0xff,0x3f,0,0,0,0x70,0,0,0,0, +0x78,0,0,0,0,0,0,0,0,0,0,0x1f,0,0,0xe0, +0xff,0xff,0x03,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xe0,0xff, +0x03,0,0xf0,0xff,0x3f,0,0,0,0x70,0,0,0,0,0x78,0, +0,0,0,0,0,0,0,0,0,0x1f,0,0,0xe0,0xff,0xff, +0x03,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xfc,0x7f,0,0, +0xf8,0xff,0x3f,0,0,0,0x70,0,0,0,0,0x78,0,0,0, +0,0,0,0,0,0,0,0x7c,0,0,0xe0,0xff,0xff,0x03,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x80,0xff,0x07,0,0,0xf8,0xff, +0x1f,0,0,0,0xe0,0,0,0,0,0x3c,0,0,0,0,0, +0,0,0,0,0,0xf8,0x01,0,0xe0,0xff,0xff,0x03,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xc0,0xff,0,0,0,0xfc,0xff,0x1f,0, +0,0,0xe0,0,0,0,0,0x3c,0,0,0,0,0,0,0, +0,0,0,0xe0,0x07,0,0xc0,0xff,0xff,0x03,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xc0,0x1f,0,0,0,0xfe,0xff,0x1f,0,0,0, +0xe0,0,0,0,0,0x3c,0,0,0x60,0,0,0,0,0,0, +0,0xc0,0x3f,0,0xc0,0xff,0xff,0x07,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xc0,0x1f,0,0,0,0xfe,0xff,0x1f,0,0,0,0xe0,0, +0,0,0,0x3c,0,0,0x60,0,0,0,0,0,0,0,0xc0, +0x3f,0,0xc0,0xff,0xff,0x07,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x80,0x03,0,0,0,0xfe,0xff,0x0f,0,0,0,0xe0,0,0,0, +0,0x3e,0,0,0x70,0,0,0,0,0,0,0,0,0xff,0x01, +0x80,0xff,0xff,0x07,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xfe,0xff,0x0f,0,0,0,0xe0,0,0,0,0,0x3f, +0,0,0x38,0,0,0,0,0,0,0,0,0xf8,0x3f,0x80,0xff, +0xff,0x0f,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xff,0xff,0x07,0,0,0,0xc0,0x01,0,0,0,0xff,0,0, +0x38,0,0,0,0,0,0,0,0,0xc0,0xff,0,0xfc,0xff,0x0f, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xff, +0xff,0x07,0,0,0,0xc0,0x01,0,0,0,0xf7,0x03,0,0x3c,0, +0,0,0,0,0,0,0,0,0xff,0x0f,0xc0,0xff,0x0f,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xff,0xff,0x07, +0,0,0,0xc0,0x01,0,0,0,0xf7,0x03,0,0x3c,0,0,0, +0,0,0,0,0,0,0xff,0x0f,0xc0,0xff,0x0f,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,0x03,0,0, +0,0xc0,0x01,0,0,0x80,0xe3,0x0f,0,0x3f,0,0,0,0,0, +0,0,0,0,0xf0,0x7f,0,0xf8,0x1f,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x80,0xff,0xff,0x03,0,0,0,0xc0, +0x01,0,0,0x80,0xe3,0xff,0xff,0x3f,0,0,0,0,0,0,0, +0,0,0x80,0xff,0x03,0x80,0x0f,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0x80,0xff,0xff,0x03,0,0,0,0xc0,0x01,0, +0,0x80,0xc3,0xff,0xff,0x3f,0,0,0,0,0,0,0,0,0, +0,0xfe,0x1f,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xc0,0xff,0xff,0x01,0,0,0,0xc0,0x01,0,0,0xc0, +0x01,0xff,0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0xe0, +0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xc0,0xff,0xff,0,0,0,0,0xc0,0x01,0,0,0xc0,0x01,0xfe, +0x7f,0x38,0,0,0,0,0,0,0,0,0,0,0,0xfe,0x1f, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0, +0xff,0xff,0,0,0,0,0xc0,0x01,0,0,0xc0,0x01,0xfe,0x7f,0x38, +0,0,0,0,0,0,0,0,0,0,0,0xfe,0x1f,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0xff, +0,0,0,0,0xc1,0x01,0,0,0xe0,0,0x3e,0,0x38,0,0, +0,0,0,0,0,0,0,0,0,0xf0,0xff,0x01,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0xff,0,0, +0,0x80,0xc3,0x01,0,0,0xe0,0,0x7c,0,0x3c,0,0,0,0, +0,0,0,0,0,0,0,0,0xff,0x7f,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xf0,0xff,0x7f,0,0,0,0xf0, +0xc3,0x01,0,0,0xf0,0,0xf0,0,0x3c,0,0,0,0,0,0, +0,0,0,0,0,0,0x80,0xff,0xff,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xf8,0xff,0x7f,0,0,0,0xf8,0xc3,0x01, +0,0,0xf0,0,0xe0,0x01,0x3c,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xe0,0xff,0xff,0x03,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xf8,0xff,0x7f,0,0,0,0xf8,0xc3,0x01,0,0, +0xf0,0,0xe0,0x01,0x3c,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xe0,0xff,0xff,0x03,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xf8,0xff,0x7f,0,0,0,0xff,0xc3,0x03,0,0,0x70,0, +0xc0,0x03,0x3c,0,0,0,0,0,0,0,0,0,0,0,0, +0,0x80,0xff,0xff,0xff,0x07,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xf8,0xff,0x3f,0,0,0x80,0xff,0xc3,0x03,0,0,0x70,0,0xc0,0x03, +0x3c,0,0,0,0,0,0,0,0,0,0,0,0xf0,0x01,0, +0xf0,0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xf8,0xff, +0x1f,0,0,0xe0,0xff,0xc3,0x03,0,0,0x78,0,0x80,0x07,0x3c,0, +0,0,0,0,0,0,0,0,0,0,0xf0,0x7f,0,0,0, +0xfc,0x0f,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xfc,0xff,0x1f,0, +0,0xf8,0xff,0xc3,0x03,0,0,0x78,0,0,0x0f,0x3c,0,0,0, +0,0,0,0,0,0,0,0,0xe0,0xff,0x0f,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xfc,0xff,0x1f,0,0,0xf8, +0xff,0xc3,0x03,0,0,0x78,0,0,0x0f,0x3c,0,0,0,0,0, +0,0,0,0,0,0,0xe0,0xff,0x0f,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xfc,0xff,0x0f,0,0,0xfe,0xff,0x83, +0x03,0,0,0x3c,0,0,0x1e,0x1c,0,0,0,0,0,0,0, +0,0xfc,0xff,0x01,0xe0,0xff,0xff,0x01,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xfe,0xff,0x0f,0,0x80,0xff,0xff,0x87,0x03,0, +0,0x3c,0,0,0x3c,0x1c,0,0,0,0,0,0,0xf8,0xff,0xff, +0xff,0xff,0xe1,0xff,0xff,0x03,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xfe,0xff,0x0f,0,0xc0,0xff,0xff,0x87,0x03,0,0,0x3c, +0,0,0x78,0x1c,0,0,0,0,0,0xfe,0xff,0xff,0xff,0xff,0xff, +0xe1,0xff,0xff,0x03,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xff,0xff,0x07,0,0xf8,0xff,0xff,0xc7,0x03,0,0,0x1c,0,0, +0xe0,0x1c,0,0,0,0x80,0xff,0xff,0xff,0x01,0,0,0,0xc0,0xff, +0xff,0x03,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xff, +0xff,0x07,0,0xf8,0xff,0xff,0xc7,0x03,0,0,0x1c,0,0,0xe0,0x1c, +0,0,0,0x80,0xff,0xff,0xff,0x01,0,0,0,0xc0,0xff,0xff,0x03, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xff,0xff,0x03, +0,0xfe,0xff,0xff,0xc7,0x03,0,0,0x1c,0,0,0xe0,0x1f,0,0, +0,0xf0,0xff,0xff,0,0,0,0,0,0x80,0xff,0xff,0x07,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,0x03,0,0xff, +0xff,0xff,0xc7,0x03,0,0,0x1c,0,0,0x80,0x1f,0,0,0,0xff, +0xff,0x03,0,0,0,0xfc,0x03,0x80,0xff,0xff,0x07,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x80,0xff,0xff,0x03,0xc0,0xff,0xff,0xff, +0xc7,0x03,0,0,0x1e,0,0,0,0x1f,0,0,0xf8,0xff,0x0f,0, +0x80,0xff,0xff,0xff,0x1f,0,0xff,0xff,0x07,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0x80,0xff,0xff,0x01,0xf0,0xff,0xff,0xff,0xc3,0x03, +0,0,0xfe,0xff,0,0,0x1f,0,0xe0,0xff,0x3f,0,0,0x80,0xff, +0xff,0xff,0x3f,0,0xff,0xff,0x07,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xc0,0xff,0xff,0x01,0xfc,0xff,0xff,0xff,0xc1,0x03,0,0, +0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0,0,0x80,0xff,0xff,0xff, +0x7f,0,0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xc0,0xff,0xff,0x01,0xfc,0xff,0xff,0xff,0xc1,0x03,0,0,0xfe,0xff, +0xff,0xff,0xff,0xff,0xff,0xff,0x01,0,0,0x80,0xff,0xff,0xff,0x7f,0, +0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xe0, +0xff,0xff,0x01,0xff,0xff,0xff,0xff,0x80,0x03,0,0,0xfe,0xff,0xff,0xff, +0xff,0xff,0xff,0x07,0,0,0,0,0xfe,0xff,0xff,0xff,0x01,0xfe,0xff, +0x1f,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0xff, +0x80,0xff,0xff,0xff,0x3f,0,0,0,0,0x7c,0,0,0xf5,0xff,0xff, +0x3f,0,0,0,0,0,0xfc,0xff,0xff,0xff,0x07,0xfe,0xff,0x1f,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0x7f,0xf0,0xff, +0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xf0,0xff,0xff,0xff,0x1f,0xfe,0xff,0x1f,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xf0,0xff,0x7f,0xf8,0xff,0xff,0xff, +0x03,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xc0,0xff,0xff,0xff,0x3f,0xfe,0xff,0x3f,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xf0,0xff,0x7f,0xf8,0xff,0xff,0xff,0x03,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xc0,0xff,0xff,0xff,0x3f,0xfe,0xff,0x3f,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xf0,0xff,0xff,0xff,0xff,0xff,0x7f,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xff, +0xff,0xff,0xff,0xfc,0xff,0x3f,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xf8,0xff,0xff,0xff,0xff,0xff,0x3f,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff, +0xff,0xff,0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xf8,0xff,0xff,0xff,0xff,0xff,0x0f,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xf0,0xff,0xff,0xff,0xff, +0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xfc,0xff, +0xff,0xff,0xff,0xff,0x03,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0xff,0xff,0x7f, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0xff, +0xff,0xff,0x03,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0xff,0xff,0x7f,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0xff,0xff,0xff, +0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x80,0xff,0xff,0xff,0xff,0xff,0x7f,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xfc,0xff,0xff,0xff,0xff,0x7f,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xfe,0xff,0xff,0xff,0xff,0xff,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xfe,0xff,0xff,0xff,0xff,0x3f,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xfc,0xff,0xff,0xff,0xff,0xff,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xfe,0xff,0xff,0xff,0xff,0x07,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xf0, +0xff,0xff,0xff,0xff,0xff,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xfe,0xff,0xff,0xff,0xff,0x07,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff,0xff, +0xff,0xff,0xff,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xfe, +0xff,0xff,0xff,0xff,0x03,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0xff, +0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xff,0xff,0xff, +0xff,0xff,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x80,0xff,0xff,0xff,0xff,0xff,0x01, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,0xff,0xff,0x3f, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xfe,0xff,0xff,0xff,0xff,0x01,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x80,0xff,0xff,0xff,0xff,0x1f,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xf8,0xff,0xff,0xff,0xff,0x03,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xc0,0xff,0xff,0xff,0xff,0x07,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xf0,0xff,0xff,0xff,0xff,0x03,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xc0,0xff,0xff,0xff,0xff,0x07,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xf0,0xff,0xff,0xff,0xff,0x03,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xc0,0xff,0xff,0xff,0xff,0x01,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0, +0xff,0xff,0xff,0xff,0x07,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0, +0xff,0xff,0xff,0xff,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x80,0xff,0xff, +0xff,0xff,0x07,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0xff, +0xff,0x1f,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xff,0xff,0xff,0xff, +0x07,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0x0f, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0xff,0x0f,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xe0,0xff,0xff,0xff,0x0f,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xfc,0xff,0xff,0xff,0x0f,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xf0,0xff,0xff,0xff,0x03,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xf8,0xff,0xff,0xff,0x0f,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xf0,0xff,0xff,0xff,0x01,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xe0,0xff,0xff,0xff,0x0f,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xf8,0xff,0xff,0x7f,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xc0,0xff,0xff,0xff,0x0f,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xf8,0xff,0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xff,0xff,0xff,0x1f,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xf8,0xff, +0xff,0x3f,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xff,0xff, +0xff,0x1f,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xf8,0xff,0xff,0x07, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0x3f, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xfc,0xff,0xff,0x03,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xf8,0xff,0xff,0x3f,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xfe,0xff,0xff,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xe0,0xff,0xff,0x3f,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xfe,0xff,0x3f,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0x80,0xff,0xff,0x3f,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xfe,0xff,0x3f,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0x80,0xff,0xff,0x3f,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xfe,0xff,0x0f,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xfe,0xff,0x7f,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xff, +0xff,0x07,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xfc,0xff,0x7f,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xff,0xff,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xf0,0xff, +0x7f,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0x80,0xff,0x3f,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xc0,0xff,0x7f,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x80,0xff,0x1f,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0x80,0xff,0xff,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0x80,0xff,0x1f,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x80,0xff,0xff,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xc0,0xff,0x03,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xfe,0xff,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xc0,0xff,0x01,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xfc,0xff,0x01,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0, +0x7f,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xf0,0xff,0x01,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xe0,0x1f,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xc0,0xff,0x01,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xe0,0x1f,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xc0,0xff, +0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xe0,0x0f,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0x80,0xff,0x01,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xf0,0x03,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xfe,0x03,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x78,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xf8,0x03,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0x18,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xf0,0x03,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x18,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xf0,0x03,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xc0,0x07,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0x07,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +}; diff --git a/hacks/flame.c b/hacks/flame.c new file mode 100644 index 00000000..3f98e3e3 --- /dev/null +++ b/hacks/flame.c @@ -0,0 +1,297 @@ +/* xscreensaver, Copyright (c) 1993, 1995 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 18-Oct-93. Original copyright reads: + * + * static char sccsid[] = "@(#)flame.c 1.4 91/09/27 XLOCK"; + * + * flame.c - recursive fractal cosmic flames. + * + * 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: + * 27-Jun-91: vary number of functions used. + * 24-Jun-91: fixed portability problem with integer mod (%). + * 06-Jun-91: Written. (received from Scott Graves, spot@cs.cmu.edu). + */ + +#include "screenhack.h" + +#define POINT_BUFFER_SIZE 10 +#define MAXLEV 4 + +static double f[2][3][MAXLEV]; /* three non-homogeneous transforms */ +static int max_total; +static int max_levels; +static int max_points; +static int cur_level; +static int snum; +static int anum; +static int num_points; +static int total_points; +static int pixcol; +static int npixels; +static unsigned long *pixels; +static XPoint points [POINT_BUFFER_SIZE]; +static GC gc; + +static int delay, delay2; +static int width, height; + +static short +halfrandom (mv) + int mv; +{ + static short lasthalf = 0; + unsigned long r; + + if (lasthalf) + { + r = lasthalf; + lasthalf = 0; + } + else + { + r = random (); + lasthalf = r >> 16; + } + return (r % mv); +} + + +static void +init_flame (dpy, window) + Display *dpy; + Window window; +{ + XGCValues gcv; + XWindowAttributes xgwa; + Colormap cmap; + XGetWindowAttributes (dpy, window, &xgwa); + width = xgwa.width; + height = xgwa.height; + cmap = xgwa.colormap; + + max_points = get_integer_resource ("iterations", "Integer"); + if (max_points <= 0) max_points = 100; + + max_levels = max_points; + + max_total = get_integer_resource ("points", "Integer"); + if (max_total <= 0) max_total = 10000; + + delay = get_integer_resource ("delay", "Integer"); + if (delay < 0) delay = 0; + delay2 = get_integer_resource ("delay2", "Integer"); + if (delay2 < 0) delay2 = 0; + + if (mono_p) + npixels = 0; + else + { + int i = get_integer_resource ("ncolors", "Integer"); + double saturation = 1.0; + double value = 1.0; + XColor color; + if (i <= 0) i = 128; + + pixels = (unsigned long *) malloc ((i+1) * sizeof (*pixels)); + for (npixels = 0; npixels < i; npixels++) + { + hsv_to_rgb ((360*npixels)/i, saturation, value, + &color.red, &color.green, &color.blue); + if (! XAllocColor (dpy, cmap, &color)) + break; + pixels [npixels] = color.pixel; + } + } + + gcv.foreground = get_pixel_resource ("foreground", "Foreground", dpy, cmap); + gcv.background = get_pixel_resource ("background", "Background", dpy, cmap); + + if (! mono_p) + { + pixcol = halfrandom (npixels); + gcv.foreground = (pixels [pixcol]); + } + + gc = XCreateGC (dpy, window, GCForeground | GCBackground, &gcv); +} + +static int +recurse (x, y, l, dpy, win) + register double x, y; + register int l; + Display *dpy; + Window win; +{ + int xp, yp, i; + double nx, ny; + + if (l == max_levels) + { + total_points++; + if (total_points > max_total) /* how long each fractal runs */ + return 0; + + if (x > -1.0 && x < 1.0 && y > -1.0 && y < 1.0) + { + xp = points[num_points].x = (int) ((width / 2) * (x + 1.0)); + yp = points[num_points].y = (int) ((height / 2) * (y + 1.0)); + num_points++; + if (num_points >= POINT_BUFFER_SIZE) + { + XDrawPoints (dpy, win, gc, points, num_points, CoordModeOrigin); + num_points = 0; + /* if (delay) usleep (delay); */ + /* XSync (dpy, True); */ + } + } + } + else + { + for (i = 0; i < snum; i++) + { + nx = f[0][0][i] * x + f[0][1][i] * y + f[0][2][i]; + ny = f[1][0][i] * x + f[1][1][i] * y + f[1][2][i]; + if (i < anum) + { + nx = sin(nx); + ny = sin(ny); + } + if (!recurse (nx, ny, l + 1, dpy, win)) + return 0; + } + } + return 1; +} + + +static void +flame (dpy, window) + Display *dpy; + Window window; +{ + int i, j, k; + static int alt = 0; + + if (!(cur_level++ % max_levels)) + { + if (delay2) usleep (delay2); + XClearWindow (dpy, window); + alt = !alt; + } + else + { + if (npixels > 2) + { + XSetForeground (dpy, gc, pixels [pixcol]); + if (--pixcol < 0) + pixcol = npixels - 1; + } + } + + /* number of functions */ + snum = 2 + (cur_level % (MAXLEV - 1)); + + /* how many of them are of alternate form */ + if (alt) + anum = 0; + else + anum = halfrandom (snum) + 2; + + /* 6 coefs per function */ + for (k = 0; k < snum; k++) + { + for (i = 0; i < 2; i++) + for (j = 0; j < 3; j++) + f[i][j][k] = ((double) (random() & 1023) / 512.0 - 1.0); + } + num_points = 0; + total_points = 0; + (void) recurse (0.0, 0.0, 0, dpy, window); + XDrawPoints (dpy, window, gc, points, num_points, CoordModeOrigin); + XSync (dpy, True); + if (delay) usleep (delay); +} + + +#ifdef __hpux +/* I don't understand why this is necessary, but I'm told that this program + does nothing at all on HP-sUX without it. + */ +#undef random +#undef srandom +#include +int matherr(x) + register struct exception *x; +{ + if (x->type == PLOSS) return 1; + else return 0; +} +#endif /* __hpux */ + + + +char *progclass = "Flame"; + +char *defaults [] = { + "Flame.background: black", /* to placate SGI */ + "Flame.foreground: white", + "*colors: 128", + "*iterations: 25", + "*delay: 50000", + "*delay2: 2000000", + "*points: 10000", + 0 +}; + +XrmOptionDescRec options [] = { + { "-ncolors", ".colors", XrmoptionSepArg, 0 }, + { "-iterations", ".iterations", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-delay2", ".delay2", XrmoptionSepArg, 0 }, + { "-points", ".points", XrmoptionSepArg, 0 } +}; +int options_size = (sizeof (options) / sizeof (options[0])); + +void +screenhack (dpy, window) + Display *dpy; + Window window; +{ + init_flame (dpy, window); + while (1) + flame (dpy, window); +} diff --git a/hacks/flame.man b/hacks/flame.man new file mode 100644 index 00000000..e5326818 --- /dev/null +++ b/hacks/flame.man @@ -0,0 +1,72 @@ +.TH XScreenSaver 1 "13-aug-92" "X Version 11" +.SH NAME +flame - draw weird cosmic fractals +.SH SYNOPSIS +.B flame +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-ncolors \fIinteger\fP] [\-iterations \fIinteger\fP] [\-points \fIinteger\fP] [\-delay \fImicroseconds\fP] [\-delay2 \fImicroseconds\fP] +.SH DESCRIPTION +The \fIflame\fP program generates colorful fractal displays. +.SH OPTIONS +.I flame +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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +Specify which visual to use. Legal values are the name of a visual class, +or the id number (decimal or hex) of a specific visual. +.TP 8 +.B \-ncolors \fIinteger\fP +How many colors should be used (if possible). Default 128. +The colors used cycle through the hue, making N stops around +the color wheel. +.TP 8 +.B \-iterations \fIinteger\fP +How many fractals to generate. Default 25. +.TP 8 +.B \-points \fIinteger\fP +How many pixels to draw for each fractal. Default 10000. +.TP 8 +.B \-delay \fImicroseconds\fP +How long we should wait between drawing each fractal. Default 50000, +or about 1/20th second. +.TP 8 +.B \-delay2 \fImicroseconds\fP +How long we should wait before clearing the screen when each run ends. +Default 2000000, or two seconds. +.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 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. +.SH AUTHOR +Scott Graves , 06-Jun-91.n + +Ability to run standalone or with \fIxscreensaver\fP added by +Jamie Zawinski , 18-Oct-93. diff --git a/hacks/greynetic.c b/hacks/greynetic.c new file mode 100644 index 00000000..4dd3f172 --- /dev/null +++ b/hacks/greynetic.c @@ -0,0 +1,166 @@ +/* xscreensaver, Copyright (c) 1992, 1995 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 [] = { + "Greynetic.background: black", /* to placate SGI */ + "Greynetic.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..86381123 --- /dev/null +++ b/hacks/greynetic.man @@ -0,0 +1,52 @@ +.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] [\-install] [\-visual \fIvisual\fP] [\-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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +Specify which visual to use. Legal values are the name of a visual class, +or the id number (decimal or hex) of a specific visual. +.TP 8 +.B \-delay \fImicroseconds\fP +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..d61e2ac3 --- /dev/null +++ b/hacks/halo.c @@ -0,0 +1,379 @@ +/* xscreensaver, Copyright (c) 1993, 1995 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... + + This would probably look good with shapes other than circles as well. + + */ + +#include "screenhack.h" +#include + +struct circle { + int x, y, radius; + int increment; + int dx, dy; +}; + +static enum color_mode { + seuss_mode, ramp_mode, random_mode +} cmode; + + +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 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; + char *mode_str = 0; + 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; + anim_p = get_boolean_resource ("animate", "Boolean"); + delay = get_integer_resource ("delay", "Integer"); + mode_str = get_string_resource ("colorMode", "ColorMode"); + if (! mode_str) cmode = random_mode; + else if (!strcmp (mode_str, "seuss")) cmode = seuss_mode; + else if (!strcmp (mode_str, "ramp")) cmode = ramp_mode; + else if (!strcmp (mode_str, "random")) cmode = random_mode; + else { + fprintf (stderr, + "%s: colorMode must be seuss, ramp, or random, not \"%s\"\n", + progname, mode_str); + exit (1); + } + + if (mono_p) cmode = seuss_mode; + if (cmode == random_mode) + cmode = ((random()&3) == 1) ? ramp_mode : seuss_mode; + + if (cmode == ramp_mode) + anim_p = False; /* This combo doesn't work right... */ + + if (mono_p) + { + fg_pixel = get_pixel_resource ("foreground","Foreground", dpy, cmap); + bg_pixel = get_pixel_resource ("background","Background", dpy, cmap); + } + else + { + int r = random() % 360; + int r2 = (random() % 180) + 45; + double fs, bs; + if (cmode == seuss_mode) + fs = 0.5, bs = 1.0; + else + fs = 1.0, bs = 0.1; + hsv_to_rgb (r, fs, 1.0, &fgc.red, &fgc.green, &fgc.blue); + hsv_to_rgb ((r+r2)%360, bs, 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 (cmode == seuss_mode) + 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 (cmode == seuss_mode) + { + 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 && + (cmode == seuss_mode || circles [0].increment < 0)) + XFillArc (dpy, + (cmode == seuss_mode ? pixmap : window), + (cmode == seuss_mode ? 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) + { + XColor d1, d2; + cycle_hue (&fgc, 10); + cycle_hue (&bgc, 10); + XFreeColors (dpy, cmap, &fgc.pixel, 1, 0); + XFreeColors (dpy, cmap, &bgc.pixel, 1, 0); + d1 = fgc; + d2 = bgc; + XAllocColor (dpy, cmap, &fgc); + XAllocColor (dpy, cmap, &bgc); + fgc.red = d1.red; fgc.green = d1.green; fgc.blue = d1.blue; + bgc.red = d2.red; bgc.green = d2.green; bgc.blue = d2.blue; + 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 (cmode != seuss_mode) + { + 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 [] = { + "Halo.background: black", /* to placate SGI */ + "Halo.foreground: white", + "*colorMode: random", + "*count: 0", + "*delay: 100000", + 0 +}; + +XrmOptionDescRec options [] = { + { "-count", ".count", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-animate", ".animate", XrmoptionNoArg, "True" }, + { "-mode", ".colorMode", XrmoptionSepArg, 0 } +}; +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..5239ab57 --- /dev/null +++ b/hacks/halo.man @@ -0,0 +1,68 @@ +.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] [\-install] [\-visual \fIvisual\fP] [\-count \fIint\fP] [\-delay \fIusecs\fP] [\-mode seuss | ramp | random ] [\-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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +Specify which visual to use. Legal values are the name of a visual class, +or the id number (decimal or hex) of a specific visual. +.TP 8 +.B \-count \fIinteger\fP +How many circles to draw. Default 0, meaning random. +.TP 8 +.B \-mode "seuss | ramp | random" +In \fIseuss\fP mode, alternating striped curves will be drawn. + +In \fIramp\fP mode, a color ramp will be drawn. + +\fIrandom\fP means pick the mode randomly. +.TP 8 +.B \-delay \fImicroseconds\fP +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..84c4fd8c --- /dev/null +++ b/hacks/helix.c @@ -0,0 +1,208 @@ +/* xscreensaver, Copyright (c) 1992, 1995 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 "screenhack.h" + +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 [] = { + "Helix.background: black", /* to placate SGI */ + 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..76c7cfef --- /dev/null +++ b/hacks/helix.man @@ -0,0 +1,50 @@ +.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] [\-install] [\-visual \fIvisual\fP] +.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. +.TP 8 +.B \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +Specify which visual to use. Legal values are the name of a visual class, +or the id number (decimal or hex) of a specific visual. +.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..2a91ecef --- /dev/null +++ b/hacks/hopalong.c @@ -0,0 +1,236 @@ +/* xscreensaver, Copyright (c) 1992, 1995 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 +#include "screenhack.h" + +static GC gc; +static int batchcount = 1000; + +static unsigned int *pixels = 0, fg_pixel, bg_pixel; +static int npixels; +static unsigned int delay; +static int timeout; + +typedef struct { + int centerx; + int centery; /* center of the screen */ + double a; + double b; + double c; + double i; + double j; /* hopalong parameters */ + int inc; + int pix; + long startTime; +} hopstruct; + +static hopstruct hop; +static XPoint *pointBuffer = 0; /* pointer for XDrawPoints */ + +static void +inithop(dsp,win) + Display *dsp; + Window win; +{ + double range; + XWindowAttributes xgwa; + hopstruct *hp = &hop; + XGCValues gcv; + Colormap cmap; + XGetWindowAttributes (dsp, win, &xgwa); + cmap = xgwa.colormap; + + if (! pixels) + { + XColor color; + int i = get_integer_resource ("ncolors", "Integer"); + int shift; + if (i <= 2) i = 2, mono_p = True; + shift = 360 / i; + pixels = (unsigned int *) calloc (i, sizeof (unsigned int)); + fg_pixel = get_pixel_resource ("foreground", "Foreground", dsp, cmap); + bg_pixel = get_pixel_resource ("background", "Background", dsp, cmap); + if (! mono_p) + { + hsv_to_rgb (random () % 360, 1.0, 1.0, + &color.red, &color.green, &color.blue); + for (npixels = 0; npixels < i; npixels++) + { + if (! XAllocColor (dsp, cmap, &color)) + break; + pixels[npixels] = color.pixel; + cycle_hue (&color, shift); + } + } + timeout = get_integer_resource ("timeout", "Seconds"); + if (timeout <= 0) timeout = 30; + delay = get_integer_resource ("delay", "Usecs"); + + gcv.foreground = fg_pixel; + gc = XCreateGC (dsp, win, GCForeground, &gcv); + } + + XClearWindow (dsp, win); + + hp->centerx = xgwa.width / 2; + hp->centery = xgwa.height / 2; + range = sqrt((double) hp->centerx * hp->centerx + + (double) hp->centery * hp->centery) / + (10.0 + random() % 10); + + hp->pix = 0; +#define frand0() (((double) random()) / ((unsigned int) (~0))) + hp->inc = (int) (frand0() * 200) - 100; + hp->a = frand0() * range - range / 2.0; + hp->b = frand0() * range - range / 2.0; + hp->c = frand0() * range - range / 2.0; + if (!(random() % 2)) + hp->c = 0.0; + + hp->i = hp->j = 0.0; + + if (!pointBuffer) + pointBuffer = (XPoint *) malloc(batchcount * sizeof(XPoint)); + + XSetForeground(dsp, gc, bg_pixel); + XFillRectangle(dsp, win, gc, 0, 0, + hp->centerx * 2, hp->centery * 2); + XSetForeground(dsp, gc, fg_pixel); + hp->startTime = time ((time_t *) 0); +} + + +static void +drawhop(dsp,win) + Display *dsp; + Window win; +{ + double oldj; + int k = batchcount; + XPoint *xp = pointBuffer; + hopstruct *hp = &hop; + + hp->inc++; + if (! mono_p) { + XSetForeground(dsp, gc, pixels[hp->pix]); + if (++hp->pix >= npixels) + hp->pix = 0; + } + while (k--) { + oldj = hp->j; + hp->j = hp->a - hp->i; + hp->i = oldj + (hp->i < 0 + ? sqrt(fabs(hp->b * (hp->i + hp->inc) - hp->c)) + : -sqrt(fabs(hp->b * (hp->i + hp->inc) - hp->c))); + xp->x = hp->centerx + (int) (hp->i + hp->j); + xp->y = hp->centery - (int) (hp->i - hp->j); + xp++; + } + XDrawPoints(dsp, win, gc, + pointBuffer, batchcount, CoordModeOrigin); + XSync (dsp, True); + if ((time ((time_t *) 0) - hp->startTime) > timeout) + { + int i; + XSetForeground(dsp, gc, bg_pixel); + for (i = 0; i < hp->centery; i++) + { + int y = (random () % (hp->centery << 1)); + XDrawLine (dsp, win, gc, 0, y, hp->centerx << 1, y); + XFlush (dsp); + if ((i % 50) == 0) + usleep (10000); + } + XClearWindow (dsp, win); + XFlush (dsp); + sleep (1); + inithop(dsp,win); + } +} + + +char *progclass = "Hopalong"; + +char *defaults [] = { + "Hopalong.background: black", /* to placate SGI */ + "Hopalong.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..d812c7b3 --- /dev/null +++ b/hacks/hopalong.man @@ -0,0 +1,69 @@ +.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] [\-install] [\-visual \fIvisual\fP] [\-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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +Specify which visual to use. Legal values are the name of a visual class, +or the id number (decimal or hex) of a specific visual. +.TP 8 +.B \-count \fIinteger\fP +How many pixels should be drawn before a color change. Default 1000. +.TP 8 +.B \-ncolors \fIinteger\fP +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 \fIseconds\fP +How many seconds we should generate for before clearing the screen +and starting over. Default 20. +.TP 8 +.B \-delay \fImicroseconds\fP +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..05574fb3 --- /dev/null +++ b/hacks/hypercube.c @@ -0,0 +1,334 @@ +/* xscreensaver, Copyright (c) 1992, 1995 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 +#include "screenhack.h" + +static Display *dpy; +static Window window; +static GC color0, color1, color2, color3, color4, color5, color6, color7; +static GC black; + +static int delay; + +static int observer_z; +static int x_offset, y_offset; +static int unit_pixels; + +struct point_state { + int old_x, old_y; + int new_x, new_y; + Bool same_p; +}; + +static void +move_line (state0, state1, gc) + struct point_state *state0, *state1; + GC gc; +{ + if (state0->same_p && state1->same_p) + return; + if (mono_p) + { + XDrawLine (dpy, window, black, + state0->old_x, state0->old_y, state1->old_x, state1->old_y); + XDrawLine (dpy, window, gc, + state0->new_x, state0->new_y, state1->new_x, state1->new_y); + } + else + { + XSegment segments [2]; + segments [0].x1 = state0->old_x; segments [0].y1 = state0->old_y; + segments [0].x2 = state1->old_x; segments [0].y2 = state1->old_y; + segments [1].x1 = state0->new_x; segments [1].y1 = state0->new_y; + segments [1].x2 = state1->new_x; segments [1].y2 = state1->new_y; + XDrawSegments (dpy, window, gc, segments, 2); + } +} + +static void +hyper (xy, xz, yz, xw, yw, zw) + double xy, xz, yz, xw, yw, zw; +{ + double cos_xy = cos (xy), sin_xy = sin (xy); + double cos_xz = cos (xz), sin_xz = sin (xz); + double cos_yz = cos (yz), sin_yz = sin (yz); + double cos_xw = cos (xw), sin_xw = sin (xw); + double cos_yw = cos (yw), sin_yw = sin (yw); + double cos_zw = cos (zw), sin_zw = sin (zw); + + double ax = 1.0, ay = 0.0, az = 0.0, aw = 0.0; + double bx = 0.0, by = 1.0, bz = 0.0, bw = 0.0; + double cx = 0.0, cy = 0.0, cz = 1.0, cw = 0.0; + double dx = 0.0, dy = 0.0, dz = 0.0, dw = 1.0; + + double _tmp0_, _tmp1_; + + struct point_state points [16]; + memset (points, 0, 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 [] = { + "Hypercube.background: black", /* to placate SGI */ + "Hypercube.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; + + 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..daa66899 --- /dev/null +++ b/hacks/hypercube.man @@ -0,0 +1,93 @@ +.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] [\-delay \fIusecs\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +Specify which visual to use. Legal values are the name of a visual class, +or the id number (decimal or hex) of a specific visual. +.TP 8 +.B \-delay \fImicroseconds\fP +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 \fIint\fP +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 \fIcolor\fP +.TP 8 +.B \-color1 \fIcolor\fP +.TP 8 +.B \-color2 \fIcolor\fP +.TP 8 +.B \-color3 \fIcolor\fP +.TP 8 +.B \-color4 \fIcolor\fP +.TP 8 +.B \-color5 \fIcolor\fP +.TP 8 +.B \-color6 \fIcolor\fP +.TP 8 +.B \-color7 \fIcolor\fP +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 \fIfloat\fP +.TP 8 +.B \-xy \fIfloat\fP +.TP 8 +.B \-xz \fIfloat\fP +.TP 8 +.B \-yw \fIfloat\fP +.TP 8 +.B \-yz \fIfloat\fP +.TP 8 +.B \-zw \fIfloat\fP +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..7a619b94 --- /dev/null +++ b/hacks/imsmap.c @@ -0,0 +1,437 @@ +/* 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 = 0; + double dshift = 0; + + 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 + { + XQueryColor (dsp, cmap, &fg_color); + XQueryColor (dsp, cmap, &bg_color); + fg_color.pixel = fg_pixel; + bg_color.pixel = bg_pixel; + } + 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 = (XColor *) 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 [] = { + "Imsmap.background: black", /* to placate SGI */ + "Imsmap.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..1badced3 --- /dev/null +++ b/hacks/imsmap.man @@ -0,0 +1,63 @@ +.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] [\-install] [\-visual \fIvisual\fP] [\-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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +Specify which visual to use. Legal values are the name of a visual class, +or the id number (decimal or hex) of a specific visual. +.TP 8 +.B \-ncolors \fIinteger\fP +How many colors to use. Default 50. +.TP 8 +.B \-timeout \fIinteger\fP +How long to delay between images. Default 10 seconds. +.TP 8 +.B \-iterations \fIinteger\fP +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/lmorph.c b/hacks/lmorph.c new file mode 100644 index 00000000..9672f962 --- /dev/null +++ b/hacks/lmorph.c @@ -0,0 +1,501 @@ + +/************************************************************************** + * + * FILE lmorph.c + * MODULE OF xscreensaver + * + * DESCRIPTION Bilinear interpolation for morphing line shapes. + * + * WRITTEN BY Sverre H. Huseby Glenn T. Lines + * Maridalsvn. 122, leil 101 Frysjavn. 3, 5. etg. + * N-0461 Oslo N-0883 Oslo + * Norway Norway + * + * Phone: +47 22 71 99 08 Phone: +47 22 23 71 99 + * E-mail: sverrehu@ifi.uio.no E-mail: gtl@si.sintef.no + * + * The original idea, and the bilinear interpolation + * mathematics used, emerged in the head of the wise + * Glenn Terje Lines. + * + * MODIFICATIONS march 1995 + * * Converted from an MS-Windows program to X Window. + * + **************************************************************************/ + +#include +#include +#include +#include +#include "screenhack.h" + +/************************************************************************** + * * + * P R I V A T E D A T A * + * * + **************************************************************************/ + +/* Define MARGINS to make some space around the figure */ +#define MARGINS /**/ + +#define MAXFIGS 20 +#define TWO_PI (2.0 * M_PI) +#define RND(x) (random() % (x)) +static int + cFig = 0, /* Number of figure arrays. */ + cPoint, /* Number of points in each array. */ + nWork, /* Current work array number. */ + nFrom, /* Current from array number. */ + nTo; /* Current to array number. */ +static long + delay; /* usecs to wait between updates. */ +static XPoint + *aWork[2], /* Working arrays. */ + *a[MAXFIGS], /* The figure arrays. */ + *aTmp, /* Used as source when interrupting morph */ + *aPrev, /* Previous points displayed. */ + *aCurr, /* The current points displayed. */ + *aFrom, /* Figure converting from. */ + *aTo; /* Figure converting to. */ +static double + gam, + maxGamma = 1.0, + delta_gam; +static GC + gcDraw, gcClear; +static Display + *dpy; +static Window + window; + + + +/************************************************************************** + * * + * P U B L I C D A T A * + * * + **************************************************************************/ + +char *progclass = "LMorph"; + +char *defaults [] = { + "LMorph.background: black", + "LMorph.foreground: green", + "*points: 150", + "*steps: 0", + "*delay: 50000", + 0 +}; + +XrmOptionDescRec options [] = { + { "-points", ".points", XrmoptionSepArg, 0 }, + { "-steps", ".steps", XrmoptionSepArg, 0 }, + { "-delay", ".delay", XrmoptionSepArg, 0 }, +}; +int options_size = (sizeof (options) / sizeof (options[0])); + + + +/************************************************************************** + * * + * P R I V A T E F U N C T I O N S * + * * + **************************************************************************/ + +static void *xmalloc(size) + size_t size; +{ + void *ret; + + if ((ret = malloc(size)) == NULL) { + fprintf(stderr, "lmorph: out of memory\n"); + exit(1); + } + return ret; +} + + + +static double frnd() +{ + /* + * Hm. for some reason the second line (using RAND_MAX) didn't + * work on some machines, so I always use the first. + */ +#undef RAND_MAX +#ifndef RAND_MAX + return (double) (random() & 0x7FFF) / 0x7FFF; +#else + return ((double) random()) / RAND_MAX; +#endif +} + + + +static void initPointArrays() +{ + XWindowAttributes wa; + int q, w, + mx, my, /* Max screen coordinates. */ + mp, /* Max point number. */ + s, rx, ry, + marginx, marginy; + double scalex, scaley; + + XGetWindowAttributes(dpy, window, &wa); + mx = wa.width - 1; + my = wa.height - 1; + mp = cPoint - 1; + + aWork[0] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); + aWork[1] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); + aTmp = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); + + + /* + * Figure 0 + */ + a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); + s = cPoint / 4; + for (q = 0; q < s; q++) { + a[cFig][q].x = ((double) q / s) * mx; + a[cFig][q].y = 0; + a[cFig][s + q].x = mx; + a[cFig][s + q].y = ((double) q / s) * my; + a[cFig][2 * s + q].x = mx - ((double) q / s) * mx; + a[cFig][2 * s + q].y = my; + a[cFig][3 * s + q].x = 0; + a[cFig][3 * s + q].y = my - ((double) q / s) * my; + } + for (q = 4 * s; q < cPoint; q++) + a[cFig][q].x = a[cFig][q].y = 0; + a[cFig][mp].x = a[cFig][0].x; + a[cFig][mp].y = a[cFig][0].y; + ++cFig; + + /* + * Figure 1 + */ + a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); + for (q = 0; q < cPoint; q++) { + a[cFig][q].x = ((double) q / cPoint) * mx; + a[cFig][q].y = (1.0 - sin(((double) q / mp) * TWO_PI)) * my / 2.0; + } + ++cFig; + + /* + * Figure 2 + */ + a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < cPoint; q++) { + a[cFig][q].x = mx / 2 + rx * sin(1 * TWO_PI * (double) q / mp); + a[cFig][q].y = my / 2 + ry * cos(3 * TWO_PI * (double) q / mp); + } + a[cFig][mp].x = a[cFig][0].x; + a[cFig][mp].y = a[cFig][0].y; + ++cFig; + + /* + * Figure 3 + */ + a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < cPoint; q++) { + a[cFig][q].x = mx / 2 + ry * sin(3 * TWO_PI * (double) q / mp); + a[cFig][q].y = my / 2 + ry * cos(1 * TWO_PI * (double) q / mp); + } + a[cFig][mp].x = a[cFig][0].x; + a[cFig][mp].y = a[cFig][0].y; + ++cFig; + + /* + * Figure 4 + */ + a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < cPoint; q++) { + a[cFig][q].x = mx / 2 + ry * (1 - 0.1 * frnd()) + * sin(TWO_PI * (double) q / mp); + a[cFig][q].y = my / 2 + ry * (1 - 0.1 * frnd()) + * cos(TWO_PI * (double) q / mp); + } + a[cFig][mp].x = a[cFig][0].x; + a[cFig][mp].y = a[cFig][0].y; + ++cFig; + + /* + * Figure 5 + */ + a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < cPoint; q++) { + a[cFig][q].x = mx / 2 + ry * (0.8 - 0.2 * sin(30 * TWO_PI * q / mp)) + * sin(TWO_PI * (double) q / mp); + a[cFig][q].y = my / 2 + ry * (0.8 - 0.2 * sin(30 * TWO_PI * q / mp)) + * cos(TWO_PI * (double) q / mp); + } + a[cFig][mp].x = a[cFig][0].x; + a[cFig][mp].y = a[cFig][0].y; + ++cFig; + + /* + * Figure 6 + */ + a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < cPoint; q++) { + a[cFig][q].x = mx / 2 + ry * sin(TWO_PI * (double) q / mp); + a[cFig][q].y = my / 2 + ry * cos(TWO_PI * (double) q / mp); + } + a[cFig][mp].x = a[cFig][0].x; + a[cFig][mp].y = a[cFig][0].y; + ++cFig; + + /* + * Figure 7 + */ + a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < cPoint; q++) { + a[cFig][q].x = mx / 2 + rx * cos(TWO_PI * (double) q / mp); + a[cFig][q].y = my / 2 + ry * sin(TWO_PI * (double) q / mp); + } + a[cFig][mp].x = a[cFig][0].x; + a[cFig][mp].y = a[cFig][0].y; + ++cFig; + + /* + * Figure 8 + */ + a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); + for (q = 0; q < cPoint; q++) { + a[cFig][q].x = ((double) q / mp) * mx; + a[cFig][q].y = (1.0 - cos(((double) q / mp) * 3 * TWO_PI)) * my / 2.0; + } + ++cFig; + + /* + * Figure 9 + */ + a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < cPoint; q++) { + a[cFig][q].x = mx / 2 + rx * sin(2 * TWO_PI * (double) q / mp); + a[cFig][q].y = my / 2 + ry * cos(3 * TWO_PI * (double) q / mp); + } + a[cFig][mp].x = a[cFig][0].x; + a[cFig][mp].y = a[cFig][0].y; + ++cFig; + + /* + * Figure 10 + */ + a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < cPoint; q++) { + a[cFig][q].x = mx / 2 + ry * sin(5 * TWO_PI * (double) q / mp) + * ((double) q / mp); + a[cFig][q].y = my / 2 + ry * cos(5 * TWO_PI * (double) q / mp) + * ((double) q / mp); + } + ++cFig; + + /* + * Figure 11 + */ + a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); + rx = mx / 2; + ry = my / 2; + for (q = 0; q < cPoint; q++) { + a[cFig][q].x = mx / 2 + ry * sin(6 * TWO_PI * (double) q / mp) + * ((double) q / mp); + a[cFig][q].y = my / 2 - ry * cos(6 * TWO_PI * (double) q / mp) + * ((double) q / mp); + } + ++cFig; + + /* + * Figure 12 + */ + a[cFig] = (XPoint *) xmalloc(cPoint * sizeof(XPoint)); + for (q = 0; q < cPoint; q++) { + a[cFig][q].x = ((double) q / mp) * mx; + a[cFig][q].y = (1.0 - sin(((double) q / mp) * 5 * TWO_PI)) * my / 2.0; + } + ++cFig; + +#ifdef MARGINS + /* + * Make some space around the figures. + */ + marginx = (mx + 1) / 10; + marginy = (my + 1) / 10; + scalex = (double) ((mx + 1) - 2.0 * marginx) / (mx + 1.0); + scaley = (double) ((my + 1) - 2.0 * marginy) / (my + 1.0); + for (q = 0; q < cFig; q++) + for (w = 0; w < cPoint; w++) { + a[q][w].x = marginx + a[q][w].x * scalex; + a[q][w].y = marginy + a[q][w].y * scaley; + } +#endif +} + + + +static void createPoints() +{ + int q; + XPoint *pa = aCurr, *pa1 = aFrom, *pa2 = aTo; + long lg, l1g; + + + lg = 8192L * gam, l1g = 8192L * (1.0 - gam); + for (q = 0; q < cPoint; q++) { + pa->x = (short) ((l1g * pa1->x + lg * pa2->x) / 8192L); + pa->y = (short) ((l1g * pa1->y + lg * pa2->y) / 8192L); + ++pa; + ++pa1; + ++pa2; + } +} + + +static void drawImage() +{ + register int q; + XPoint *old0, *old1, *new0, *new1; + + /* + * Problem: update the window without too much flickering. I do + * this by handling each linesegment separately. First remove a + * line, then draw the new line. The problem is that this leaves + * small black pixels on the figure. To fix this, I draw the + * entire figure using XDrawLines() afterwards. + */ + if (aPrev) { + old0 = aPrev; + old1 = aPrev + 1; + new0 = aCurr; + new1 = aCurr + 1; + for (q = cPoint - 1; q; q--) { + XDrawLine(dpy, window, gcClear, + old0->x, old0->y, old1->x, old1->y); + XDrawLine(dpy, window, gcDraw, + new0->x, new0->y, new1->x, new1->y); + ++old0; + ++old1; + ++new0; + ++new1; + } + } + XDrawLines(dpy, window, gcDraw, aCurr, cPoint, CoordModeOrigin); + XFlush(dpy); +} + +static void initLMorph() +{ + int steps; + XGCValues gcv; + XWindowAttributes wa; + Colormap cmap; + + cPoint = get_integer_resource("points", "Integer"); + steps = get_integer_resource("steps", "Integer"); + delay = get_integer_resource("delay", "Integer"); + + if (steps <= 0) + steps = (random() % 400) + 100; + + delta_gam = 1.0 / steps; + XGetWindowAttributes(dpy, window, &wa); + cmap = wa.colormap; + gcv.foreground = get_pixel_resource("foreground", "Foreground", dpy, cmap); + gcDraw = XCreateGC(dpy, window, GCForeground, &gcv); + XSetForeground(dpy, gcDraw, gcv.foreground); + gcv.foreground = get_pixel_resource("background", "Background", dpy, cmap); + gcClear = XCreateGC(dpy, window, GCForeground, &gcv); + XClearWindow(dpy, window); + + srandom(time(NULL)); + initPointArrays(); + aCurr = aWork[nWork = 0]; + aPrev = NULL; + gam = 2.0; + nTo = RND(cFig); +} + +static void animateLMorph() +{ + if (gam > maxGamma) { + gam = 0.0; + if (maxGamma == 1.0) { + nFrom = nTo; + aFrom = a[nFrom]; + } else { + memcpy(aTmp, aCurr, cPoint * sizeof(XPoint)); + aFrom = aTmp; + nFrom = -1; + } + do { + nTo = RND(cFig); + } while (nTo == nFrom); + aTo = a[nTo]; + if (RND(2)) { + /* + * Reverse the array to get more variation. + */ + int i1, i2; + XPoint p; + + for (i1 = 0, i2 = cPoint - 1; i1 < cPoint / 2; i1++, i2--) { + p = aTo[i1]; + aTo[i1] = aTo[i2]; + aTo[i2] = p; + } + } + /* + * It may be nice to interrupt the next run. + */ + if (RND(3) > 0) + maxGamma = 0.1 + 0.7 * (RND(1001) / 1000.0); + else + maxGamma = 1.0; + } + + createPoints(); + drawImage(); + aPrev = aCurr; + aCurr = aWork[nWork ^= 1]; + + gam += delta_gam; +} + + + +/************************************************************************** + * * + * P U B L I C F U N C T I O N S * + * * + **************************************************************************/ + +void screenhack(disp, win) + Display *disp; + Window win; +{ + dpy = disp; + window = win; + initLMorph(); + for (;;) { + animateLMorph(); + screenhack_usleep(delay); + } +} diff --git a/hacks/lmorph.man b/hacks/lmorph.man new file mode 100644 index 00000000..a631f24c --- /dev/null +++ b/hacks/lmorph.man @@ -0,0 +1,54 @@ +.TH LMORPH 1 "xscreensaver hack" +.SH NAME +lmorph \- morphing lines +.SH SYNOPSIS +.B lmorph +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-mono] [\-install] [\-visual \fIvisual\fP] [\-points \fIint\fP] [\-steps \fIint\fP] [\-delay \fIusecs\fP] +.SH DESCRIPTION +The \fIlmorph\fP program morphs between simple linedrawings using bilinear +interpolation. +.SH OPTIONS +.I lmorph +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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +Specify which visual to use. Legal values are the name of a visual class, +or the id number (decimal or hex) of a specific visual. +.TP 8 +.B \-points \fIinteger\fP +Number of points in each line drawing. Default is 150 points. +.TP 8 +.B \-steps \fIinteger\fP +Interpolation steps from one drawing to the next. Default is 0, which +means a random number between 100 and 500. +.TP 8 +.B \-delay \fImicroseconds\fP +How much of a delay should be introduced between steps of the animation. +Default 50000. +.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 +Sverre H. Huseby and Glenn T. Lines , +built on top of the screen saver routines by Jamie Zawinski . diff --git a/hacks/maze.c b/hacks/maze.c new file mode 100644 index 00000000..6d73796e --- /dev/null +++ b/hacks/maze.c @@ -0,0 +1,792 @@ +/****************************************************************************** + * [ maze ] ... + * + * modified: [ 8-11-95 ] Ed James + * added fill of dead-end box to solve_maze while loop. + * 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 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; + +static int +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); +} + + +static void +set_maze_sizes (width, height) + int width, height; +{ + maze_size_x = width / grid_width; + maze_size_y = height / grid_height; +} + + +static void +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 ) { + XFillRectangle(dpy, win, cgc, + border_x + bw + grid_width * (int)(path[i].x), + border_y + bw + grid_height * (int)(path[i].y), + grid_width - (bw+bw), grid_height - (bw+bw)); + 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[] = { + "Maze.background: black", /* to placate SGI */ + "Maze.foreground: white", /* to placate SGI */ + "*gridSize: 0", + "*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..f93a70f4 --- /dev/null +++ b/hacks/maze.man @@ -0,0 +1,107 @@ +.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] [\-install] [\-visual \fIvisual\fP] [\-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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +Specify which visual to use. Legal values are the name of a visual class, +or the id number (decimal or hex) of a specific visual. +.TP 8 +.B \-grid\-size \fIpixels\fP +The size of each block of the maze, in pixels; default is 0, meaning +pick a random grid size. +.TP 8 +.B \-live\-color \fIcolor\fP +The color of the path. +.TP 8 +.B \-dead\-color \fIcolor\fP +The color of the failed path (it is also stippled with a 50% pattern.) +.TP 8 +.B \-solve\-delay \fIinteger\fP +Delay (in microseconds) between each step of the solution path. +Default 5000, or about 1/200th second. +.TP 8 +.B \-pre\-delay \fIinteger\fP +Delay (in microseconds) between generating a maze and starting to solve it. +Default 2000000 (2 seconds.) +.TP 8 +.B \-post\-delay \fIinteger\fP +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. +.TP 16 +.B "LeftButton +Clears the window and restarts maze. +.TP 16 +.B MiddleButton +Pause or unpause the program. +.TP 16 +.B RightButton +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..713ee238 --- /dev/null +++ b/hacks/noseguy.c @@ -0,0 +1,654 @@ +/* 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 int first_time = 1; + +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); + else if (!first_time && + (strstr (buf, ": not found") || + strstr (buf, ": Not found"))) + switch (random () % 20) + { + case 1: strcat (buf, "( Get with the program, bub. )\n"); + break; + case 2: strcat (buf, + "( I blow my nose at you, you silly person! ) \n"); break; + case 3: strcat (buf, + "\nThe resource you want to\nset is `noseguy.program'\n"); + break; + case 4: + strcat(buf,"\nHelp!! Help!!\nAAAAAAGGGGHHH!! \n\n"); break; + case 5: strcpy (buf, "You have new mail.\n"); break; + case 6: + strcat(buf,"( Hello? Are you paying attention? )\n");break; + case 7: + strcat (buf, "sh: what kind of fool do you take me for? \n"); + break; + } + first_time = 0; + 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 [] = { + "Noseguy.background: black", /* to placate SGI */ + "Noseguy.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..fe18d8df --- /dev/null +++ b/hacks/noseguy.man @@ -0,0 +1,74 @@ +.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] [\-install] [\-visual \fIvisual\fP] [\-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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +Specify which visual to use. Legal values are the name of a visual class, +or the id number (decimal or hex) of a specific visual. +.TP 8 +.B \-font \fIfont\fP +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 \fIprogram\fP +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 \fIfile\fP +If \fImode\fP is \fIfile\fP, then the contents of this file will be used +for all messages. +.TP 8 +.B \-text \fIstring\fP +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/pedal.c b/hacks/pedal.c new file mode 100644 index 00000000..8cde8d53 --- /dev/null +++ b/hacks/pedal.c @@ -0,0 +1,404 @@ +/* + * pedal + * + * Based on a program for some old PDP-11 Graphics Display Processors + * at CMU. + * + * X version by + * + * Dale Moore + * 24-Jun-1994 + * + * Copyright \(co 1994, by Carnegie Mellon University. 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 implied + * warranty. + */ + +#include +#include +#include "screenhack.h" + +/* If MAXLINES is too big, we might not be able to get it + * to the X server in the 2byte length field. Must be less + * than 16k + */ +#define MAXLINES (16 * 1024) +#define MAXPOINTS MAXLINES +XPoint *points; + +/* + * If the pedal has only this many lines, it must be ugly and we dont + * want to see it. + */ +#define MINLINES 7 + +static int sizex, sizey; +static int delay; +static int fadedelay; +static int maxlines; +static GC gc; +static XColor foreground, background; +static Colormap cmap; + +static Bool fade_p; + + +/* + * Routine (Macro actually) + * mysin + * Description: + * Assume that degrees is .. oh 360... meaning that + * there are 360 degress in a circle. Then this function + * would return the sin of the angle in degrees. But lets + * say that they are really big degrees, with 4 big degrees + * the same as one regular degree. Then this routine + * would be called mysin(t, 90) and would return sin(t degrees * 4) + */ +#define mysin(t, degrees) sin(t * 2 * M_PI / (degrees)) +#define mycos(t, degrees) cos(t * 2 * M_PI / (degrees)) + +/* + * Macro: + * rand_range + * Description: + * Return a random number between a inclusive and b exclusive. + * rand (3, 6) returns 3 or 4 or 5, but not 6. + */ +#define rand_range(a, b) (a + random() % (b - a)) + + +static int gcd (m, n) + int m; + int n; +/* + * Greatest Common Divisor (also Greates common factor). + */ +{ + int r; + + for (;;) { + r = m % n; + if (r == 0) return (n); + m = n; + n = r; + } +} + +static int numlines (a, b, d) + int a; + int b; + int d; +/* + * Description: + * + * Given parameters a and b, how many lines will we have to draw? + * + * Algorithm: + * + * This algorithm assumes that r = sin (theta * a), where we + * evaluate theta on multiples of b. + * + * LCM (i, j) = i * j / GCD (i, j); + * + * So, at LCM (b, 360) we start over again. But since we + * got to LCM (b, 360) by steps of b, the number of lines is + * LCM (b, 360) / b. + * + * If a is odd, then at 180 we cross over and start the + * negative. Someone should write up an elegant way of proving + * this. Why? Because I'm not convinced of it myself. + * + */ +{ +#define odd(x) (x & 1) +#define even(x) (!odd(x)) + if ( odd(a) && odd(b) && even(d)) d /= 2; + return (d / gcd (d, b)); +#undef odd +} + +static int +compute_pedal(points, maxpoints) +XPoint *points; +int maxpoints; +/* + * Description: + * + * Basically, it's combination spirograph and string art. + * Instead of doing lines, we just use a complex polygon, + * and use an even/odd rule for filling in between. + * + * The spirograph, in mathematical terms is a polar + * plot of the form r = sin (theta * c); + * The string art of this is that we evaluate that + * function only on certain multiples of theta. That is + * we let theta advance in some random increment. And then + * we draw a straight line between those two adjacent points. + * + * Eventually, the lines will start repeating themselves + * if we've evaluated theta on some rational portion of the + * whole. + * + * The number of lines generated is limited to the + * ratio of the increment we put on theta to the whole. + * If we say that there are 360 degrees in a circle, then we + * will never have more than 360 lines. + * + * Return: + * + * The number of points. + * + */ +{ + int a, b, d; /* These describe a unique pedal */ + + double r; + int theta = 0; + XPoint *pp = points; + int count; + int numpoints; + + /* Just to make sure that this division is not done inside the loop */ + int h_width = sizex / 2, h_height = sizey / 2 ; + + for (;;) { + d = rand_range (MINLINES, maxlines); + + a = rand_range (1, d); + b = rand_range (1, d); + numpoints = numlines(a, b, d); + if (numpoints > MINLINES) break; + } + + /* it might be nice to try to move as much sin and cos computing + * (or at least the argument computing) out of the loop. + */ + for (count = numpoints; count-- ; ) + { + r = mysin (theta * a, d); + + /* Convert from polar to cartesian coordinates */ + /* We could round the results, but coercing seems just fine */ + pp->x = mysin (theta, d) * r * h_width + h_width; + pp->y = mycos (theta, d) * r * h_height + h_height; + + /* Advance index into array */ + pp++; + + /* Advance theta */ + theta += b; + theta %= d; + } + + return(numpoints); +} + +static void +init_pedal (dpy, window) + Display *dpy; + Window window; +{ + XGCValues gcv; + XWindowAttributes xgwa; + + fade_p = !mono_p; + + delay = get_integer_resource ("delay", "Integer"); + if (delay < 0) delay = 0; + + fadedelay = get_integer_resource ("fadedelay", "Integer"); + if (fadedelay < 0) fadedelay = 0; + + maxlines = get_integer_resource ("maxlines", "Integer"); + if (maxlines < MINLINES) maxlines = MINLINES; + else if (maxlines > MAXLINES) maxlines = MAXLINES; + + points = (XPoint *)malloc(sizeof(XPoint) * maxlines); + + XGetWindowAttributes (dpy, window, &xgwa); + sizex = xgwa.width; + sizey = xgwa.height; + + if ((xgwa.visual->class != GrayScale) && (xgwa.visual->class != PseudoColor)) + fade_p = False; + + cmap = xgwa.colormap; + + gcv.function = GXcopy; + gcv.subwindow_mode = IncludeInferiors; + gcv.foreground = get_pixel_resource ("foreground", "Foreground", dpy, cmap); + gcv.background = get_pixel_resource ("background", "Background", dpy, cmap); + gc = XCreateGC ( + dpy, + window, + GCForeground | GCBackground |GCFunction | GCSubwindowMode , + &gcv); + + if (fade_p) + { + int status; + foreground.pixel = gcv.foreground; + XQueryColor (dpy, cmap, &foreground); + + status = XAllocColorCells ( + dpy, + cmap, + 0, + NULL, + 0, + &foreground.pixel, + 1); + if (status) + { + XStoreColor ( dpy, cmap, &foreground); + XSetForeground (dpy, gc, foreground.pixel); + + background.pixel = gcv.background; + XQueryColor (dpy, cmap, &background); + } + else + { + /* If we cant allocate a color cell, then just forget the + * whole fade business. + */ + fade_p = False; + } + } +} + +static void +fade_foreground (dpy, cmap, from, to, steps) + Display *dpy; + Colormap cmap; + XColor from; + XColor to; + int steps; +/* + * This routine assumes that we have a writeable colormap. + * That means that the default colormap is not full, and that + * the visual class is PseudoColor or GrayScale. + */ +{ + int i; + XColor inbetween; + int udelay = fadedelay / (steps + 1); + + inbetween = foreground; + for (i = 0; i <= steps; i++ ) + { + inbetween.red = from.red + (to.red - from.red) * i / steps ; + inbetween.green = from.green + (to.green - from.green) * i / steps ; + inbetween.blue = from.blue + (to.blue - from.blue) * i / steps ; + XStoreColor (dpy, cmap, &inbetween); + /* If we don't sync, these can bunch up */ + XSync(dpy, 0); + usleep(udelay); + } +} + +static void +pedal (dpy, window) + Display *dpy; + Window window; +/* + * Since the XFillPolygon doesn't require that the last + * point == first point, the number of points is the same + * as the number of lines. We just let XFillPolygon supply + * the line from the last point to the first point. + * + */ +{ + int numpoints; + + numpoints = compute_pedal(points, maxlines); + + /* Fade out, make foreground the same as background */ + if (fade_p) + fade_foreground (dpy, cmap, foreground, background, 32); + + /* Clear the window of previous garbage */ + XClearWindow (dpy, window); + + XFillPolygon ( + dpy, + window, + gc, + points, + numpoints, + Complex, + CoordModeOrigin); + + /* Pick a new foreground color (added by jwz) */ + if (! mono_p) + { + XColor color; + hsv_to_rgb (random()%360, 1.0, 1.0, + &color.red, &color.green, &color.blue); + XSync(dpy, 0); + if (fade_p) + { + foreground.red = color.red; + foreground.green = color.green; + foreground.blue = color.blue; + XStoreColor (dpy, cmap, &foreground); + } + else if (XAllocColor (dpy, cmap, &color)) + { + XSetForeground (dpy, gc, color.pixel); + XFreeColors (dpy, cmap, &foreground.pixel, 1, 0); + foreground.red = color.red; + foreground.green = color.green; + foreground.blue = color.blue; + foreground.pixel = color.pixel; + } + XSync(dpy, 0); + } + + /* Fade in by bringing the foreground back from background */ + if (fade_p) + fade_foreground (dpy, cmap, background, foreground, 32); +} + + +char *progclass = "Pedal"; + +/* + * If we are trying to save the screen, the background + * should be dark. + */ +char *defaults [] = { + "Pedal.background: black", /* to placate SGI */ + "Pedal.foreground: white", + "*delay: 5", + "*fadedelay: 200000", + "*maxlines: 1000", + 0 +}; + +XrmOptionDescRec options [] = { + { "-delay", ".delay", XrmoptionSepArg, 0 }, + { "-fadedelay", ".fadedelay", XrmoptionSepArg, 0 }, + { "-maxlines", ".maxlines", XrmoptionSepArg, 0 }, + { "-foreground", ".foreground", XrmoptionSepArg, 0 }, + { "-background", ".background", XrmoptionSepArg, 0 }, +}; + +int options_size = (sizeof (options) / sizeof (options[0])); + +void +screenhack (dpy, window) + Display *dpy; + Window window; +{ + init_pedal (dpy, window); + for (;;) { + pedal (dpy, window); + XSync(dpy, 0); + if (delay) sleep (delay); + } +} diff --git a/hacks/pedal.man b/hacks/pedal.man new file mode 100644 index 00000000..7a0c3e5b --- /dev/null +++ b/hacks/pedal.man @@ -0,0 +1,62 @@ +.TH XScreenSaver 1 "24-Jun-94" "X Version 11" +.SH NAME +pedal - pretty geometric picture program +.SH SYNOPSIS +.B pedal +[\-display \fIhost:display.screen\fP] [\-foreground \fIcolor\fP] [\-background \fIcolor\fP] [\-window] [\-root] [\-delay \fIseconds\fP] [-maxlines \fInumber\fP] [-fadedelay \fIuseconds\fP] [-mono] [\-install] [\-visual \fIvisual\fP] +.SH DESCRIPTION +The \fIpedal\fP program displays pretty geometric pictures. +.SH OPTIONS +.I pedal +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 \-foreground \fIcolor\fP +The color for the foreground. Default is white. +.TP 8 +.B \-background \fIcolor\fP +The color for the background. Default is black. +.TP 8 +.B \-delay \fIseconds\fP +The number of seconds to pause between each picture. +.TP 8 +.B \-maxlines \fInumber\fP +The maximum number of lines in the drawing. Good values are +between 20 and 2000. Maximum value is 16K. +.TP 8 +.B \-fadedelay \fImicroseconds\fP +The number of micro seconds to take when fading in and out. +.TP 8 +.B \-mono +Don't do fading. Pretend we're on a monochrome display. +.PP +To make your X server grunt under load, and to impress your +friends, try \fIpedal -mono -delay 0 -maxlines 100\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 1994, by Carnegie Mellon University. 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 implied +warranty. +.SH AUTHOR +Dale Moore , 24-Jun-1994. diff --git a/hacks/pyro.c b/hacks/pyro.c new file mode 100644 index 00000000..996f7833 --- /dev/null +++ b/hacks/pyro.c @@ -0,0 +1,258 @@ +/* xscreensaver, Copyright (c) 1992, 1994 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 = (parent->size * 2) / 3; + 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)*/ (size > 2) + 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 [] = { + "Pyro.background: black", /* to placate SGI */ + "Pyro.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..8edb9669 --- /dev/null +++ b/hacks/pyro.man @@ -0,0 +1,60 @@ +.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] [\-install] [\-visual \fIvisual\fP] [\-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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +Specify which visual to use. Legal values are the name of a visual class, +or the id number (decimal or hex) of a specific visual. +.TP 8 +.B \-count \fIinteger\fP +How many particles should be allowed on the screen at once. Default 100. +.TP 8 +.B \-frequency \fIinteger\fP +How often new missiles should launch. Default 30. +.TP 8 +.B \-scatter \fIinteger\fP +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..c26e7367 --- /dev/null +++ b/hacks/qix.c @@ -0,0 +1,514 @@ +/* xscreensaver, Copyright (c) 1992, 1995 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; + XQueryColor (dpy, cmap, &qix->lines[0].color); + 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) + { + XColor desired; + cycle_hue (&qline->color, color_shift); + qline->color.flags = DoRed | DoGreen | DoBlue; + desired = qline->color; + if (XAllocColor (dpy, cmap, &qline->color)) + { + /* XAllocColor returns the actual RGB that the hardware let us + allocate. Restore the requested values into the XColor struct + so that limited-resolution hardware doesn't cause cycle_hue to + get "stuck". */ + qline->color.red = desired.red; + qline->color.green = desired.green; + qline->color.blue = desired.blue; + } + else + { + 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 [] = { + "Qix.background: black", /* to placate SGI */ + "Qix.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..816a55a3 --- /dev/null +++ b/hacks/qix.man @@ -0,0 +1,114 @@ +.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] [\-install] [\-visual \fIvisual\fP] [\-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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +Specify which visual to use. Legal values are the name of a visual class, +or the id number (decimal or hex) of a specific visual. +.TP 8 +.B \-segments \fIinteger\fP +How many line segments should be drawn. Default 50. +.TP 8 +.B \-spread \fIinteger\fP +How far apart the endpoints of one segment should be from the next. +Default 8. +.TP 8 +.B \-size \fIinteger\fP +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 \fIinteger\fP +How many qixes to draw. Default 1. +.TP 8 +.B \-color\-shift \fIdegrees\fP +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 \fImicroseconds\fP +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..4e9e901e --- /dev/null +++ b/hacks/rocks.c @@ -0,0 +1,310 @@ +/* xscreensaver, Copyright (c) 1992, 1995 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 +#include +#include "screenhack.h" + +#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 = 0; + 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 [] = { + "Rocks.background: black", /* to placate SGI */ + "Rocks.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..22256d3e --- /dev/null +++ b/hacks/rocks.man @@ -0,0 +1,71 @@ +.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] [\-install] [\-visual \fIvisual\fP] [\-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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +Specify which visual to use. Legal values are the name of a visual class, +or the id number (decimal or hex) of a specific visual. +.TP 8 +.B \-count \fIinteger\fP +Maximum number of rocks to draw on the screen at once. Default 100. +.TP 8 +.B \-speed \fIinteger\fP +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 \fImicroseconds\fP +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..bea709cd --- /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 [] = { + "Rorschach.background: black", /* to placate SGI */ + "Rorschach.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..4619f0ff --- /dev/null +++ b/hacks/rorschach.man @@ -0,0 +1,64 @@ +.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] [\-install] [\-visual \fIvisual\fP] [\-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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +Specify which visual to use. Legal values are the name of a visual class, +or the id number (decimal or hex) of a specific visual. +.TP 8 +.B \-iterations \fIinteger\fP +How many dots should be drawn each time. Default 4000. +.TP 8 +.B \-offset \fIinteger\fP +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..6c7a0300 --- /dev/null +++ b/hacks/screenhack.c @@ -0,0 +1,247 @@ +/* xscreensaver, Copyright (c) 1992, 1995 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 +#include +#include "screenhack.h" + +char *progname; +XrmDatabase db; +Bool mono_p; + +#if __STDC__ +# define P(x) x +#else +# define P(x)() +#endif + + +static XrmOptionDescRec default_options [] = { + { "-root", ".root", XrmoptionNoArg, "True" }, + { "-window", ".root", XrmoptionNoArg, "False" }, + { "-mono", ".mono", XrmoptionNoArg, "True" }, + { "-install", ".installColormap", XrmoptionNoArg, "True" }, + { "-visual", ".visualID", XrmoptionSepArg, 0 } +}; + +static char *default_defaults[] = { + "*root: false", + "*geometry: 500x500", /* this should be .geometry, but nooooo... */ + "*mono: false", + "*installColormap: false", + "*visualID: default", + 0 +}; + +static XrmOptionDescRec *merged_options; +static int merged_options_size; +static char **merged_defaults; + +static void +merge_options P((void)) +{ + 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); + memcpy (merged_options, options, options_sizeof); + memcpy (merged_options + options_size, default_options, + sizeof (default_options)); + + for (defaults_size = 0; defaults [defaults_size]; defaults_size++); + merged_defaults = (char **) + malloc (sizeof (default_defaults) + (defaults_size * sizeof (char *))); + memcpy (merged_defaults, default_defaults, sizeof (default_defaults)); + memcpy ((merged_defaults - 1 + + (sizeof (default_defaults) / sizeof (default_defaults[0]))), + defaults, ((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; + Visual *visual; + 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; + visual = xgwa.visual; + } + else + { + visual = get_visual_resource (dpy, "visualID", "VisualID"); + + XtVaSetValues (toplevel, XtNmappedWhenManaged, False, 0); + XtRealizeWidget (toplevel); + window = XtWindow (toplevel); + + if (visual != DefaultVisualOfScreen (XtScreen (toplevel))) + { + Arg av [20]; + int ac; + unsigned int bg, bd; + Widget new; + cmap = XCreateColormap (dpy, window, visual, AllocNone); + bg = get_pixel_resource ("background", "Background", dpy, cmap); + bd = get_pixel_resource ("borderColor", "Foreground", dpy, cmap); + ac = 0; + XtSetArg (av[ac], XtNvisual, visual); ac++; + XtSetArg (av[ac], XtNcolormap, cmap); ac++; + XtSetArg (av[ac], XtNdepth, get_visual_depth (dpy, visual)); ac++; + XtSetArg (av[ac], XtNbackground, (Pixel) bg); ac++; + XtSetArg (av[ac], XtNborderColor, (Pixel) bd); ac++; + new = XtAppCreateShell (progname, progclass, + topLevelShellWidgetClass, dpy, + av, ac); + XtDestroyWidget (toplevel); + toplevel = new; + } + else if (get_boolean_resource ("installColormap", "InstallColormap")) + { + cmap = XCreateColormap (dpy, window, + DefaultVisualOfScreen (XtScreen (toplevel)), + AllocNone); + XSetWindowColormap (dpy, window, cmap); + } + else + { + cmap = DefaultColormap (dpy, DefaultScreen (dpy)); + } + + XtPopup (toplevel, XtGrabNone); + window = XtWindow (toplevel); + } + + 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..9be43672 --- /dev/null +++ b/hacks/screenhack.h @@ -0,0 +1,139 @@ +/* xscreensaver, Copyright (c) 1992-1995 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. + */ + +/* Found in Don Hopkins' .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) + */ + +#ifndef _SCREENHACK_H_ +#define _SCREENHACK_H_ + +#if __STDC__ +#include +#endif + +#ifdef __hpux + /* Which of the ten billion standards does values.h belong to? + What systems always have it? */ +# 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 []; + +/* Screw it, we'll just use our own RNG. See xscreensaver/utils/yarandom.c. */ +#include "yarandom.h" + + +#undef P +#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 *)); + +extern void hsv_to_rgb P((int,double,double,unsigned short*, + unsigned short*,unsigned short*)); +extern void rgb_to_hsv P((unsigned short,unsigned short,unsigned short, + int*,double*,double*)); +extern void cycle_hue P((XColor*,int)); + +extern void make_color_ramp P((int h1, double s1, double v1, + int h2, double s2, double v2, + XColor *pixels, int npixels)); + +extern Pixmap grab_screen_image P((Display *dpy, Window window, int root_p)); +extern void copy_default_colormap_contents P((Display *dpy, Colormap to_cmap, + Visual *to_visual)); + +#if defined (__GNUC__) && (__GNUC__ >= 2) + /* Implement frand using GCC's statement-expression extension. */ + +# define frand(f) \ + ({ double tmp = (((double) random()) / \ + (((double) ((unsigned int)~0)) / ((double) (f+f)))); \ + tmp < 0 ? (-tmp) : tmp; }) + +#else /* not GCC2 - implement frand using a global variable.*/ + +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_) + +#endif /* not GCC2 */ + +#undef P +#endif /* _SCREENHACK_H_ */ diff --git a/hacks/slidescreen.c b/hacks/slidescreen.c new file mode 100644 index 00000000..6c8ccf71 --- /dev/null +++ b/hacks/slidescreen.c @@ -0,0 +1,253 @@ +/* xscreensaver, Copyright (c) 1992, 1993, 1994 + * 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 void +init_slide (dpy, window) + Display *dpy; + Window window; +{ + int i; + XGCValues gcv; + XWindowAttributes xgwa; + int border; + int root_p; + unsigned long fg; + Pixmap pixmap; + Drawable d; + Colormap cmap; + Visual *visual; + + XGetWindowAttributes (dpy, window, &xgwa); + cmap = xgwa.colormap; + visual = xgwa.visual; + + copy_default_colormap_contents (dpy, cmap, visual); + + 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, + /* Pixels always come out of default map. */ + XDefaultColormapOfScreen (xgwa.screen)); + 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); + + pixmap = grab_screen_image (dpy, window, root_p); + + 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; + default: abort (); + } + } 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; + default: abort (); + } + + 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..3d03dc50 --- /dev/null +++ b/hacks/slidescreen.man @@ -0,0 +1,68 @@ +.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] [\-install] [\-visual \fIvisual\fP] +.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 \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +Specify which visual to use. Legal values are the name of a visual class, +or the id number (decimal or hex) of a specific visual. +.TP 8 +.B \-grid-size \fIpixels\fP +The size of the grid cells. Default 70 pixels. +.TP 8 +.B \-ibw \fIpixels\fP +The size of the "gutter" between grid cells. Default 1 pixel. +.TP 8 +.B \-increment \fIpixels\fP +How many pixels by which a piece should be moved when sliding to a new +location. Default 10 pixels. +.TP 8 +.B \-delay \fImicroseconds\fP +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 \fImicroseconds\fP +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..e6d57646 --- /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.1 1994/08/25 22:04:24 jwz Exp $"; +#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..19e5fdab --- /dev/null +++ b/hacks/xlock.h @@ -0,0 +1,160 @@ +/* +** Helpful definitions for porting xlock modes to xscreensaver. +** by Charles Hannum, mycroft@ai.mit.edu +** +** for xlock 2.3 and xscreensaver 1.2, 28AUG92 +** +** +** Modified for xlockmore 3.0 by Anthony Thyssen +** on August 1995. +** +** 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 unsigned int cycles; +static double saturation; + +#ifndef min +#define min(a,b) ((a)<(b)?(a):(b)) +#endif + +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; + + n = get_integer_resource ("cycles", "Integer"); + if (n >= 0) cycles = 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", + "*count: -1", + "*cycles: -1", + 0 +}; + +XrmOptionDescRec options[] = { + {"-count", ".count", XrmoptionSepArg, 0}, + {"-ncolors", ".ncolors", XrmoptionSepArg, 0}, + {"-delay", ".delay", XrmoptionSepArg, 0}, + {"-cycles", ".cycles", XrmoptionSepArg, 0}, +}; +int options_size = (sizeof (options) / sizeof (options[0])); + +#define PROGRAM(Y,Z,D,B,C,S) \ +char *progclass = Y; \ + \ +void screenhack (dpy, window) \ + Display *dpy; \ + Window window; \ +{ \ + batchcount = B; \ + delay = D; \ + cycles = C; \ + saturation = S; \ + dsp = dpy; \ + \ + init##Z (window); \ + while (1) { \ + 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..615ade16 --- /dev/null +++ b/hacks/xroger-hack.c @@ -0,0 +1,103 @@ +/* xscreensaver, Copyright (c) 1991-1994 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 [] = { + "XRoger.background: black", + "XRoger.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, color3; + 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); + color3 = color2; + if (XAllocColor (dpy, cmap, &color3)) + { + XSetForeground (dpy, draw_gc, color3.pixel); + color2.pixel = color3.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..799f5005 --- /dev/null +++ b/hacks/xroger.man @@ -0,0 +1,52 @@ +.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] [\-install] [\-visual \fIvisual\fP] +.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. +.TP 8 +.B \-install +Install a private colormap for the window. +.TP 8 +.B \-visual \fIvisual\fP +Specify which visual to use. Legal values are the name of a visual class, +or the id number (decimal or hex) of a specific visual. +.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 +It should also drip blood while making a horrible screeching noise. +.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..5f61d60a --- /dev/null +++ b/utils/Imakefile @@ -0,0 +1,24 @@ +/* + * Imakefile file for xscreensaver, Copyright (c) 1993, 1995 Jamie Zawinski. + * + * You should not need to edit this file; edit ../config.h instead. + * + */ + +#include "../config.h" + +#ifdef NO_SELECT + DEFINES = R5ISMS -DNO_SELECT +#else + DEFINES = R5ISMS +#endif + SRCS = fade.c hsv.c resources.c spline.c usleep.c xroger.c \ + grabscreen.c visual.c yarandom.c + OBJS = fade.o hsv.o resources.o spline.o usleep.o xroger.o \ + grabscreen.o visual.o yarandom.o + TARFILES = README Imakefile ad2c $(SRCS) spline.h yarandom.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..de6ce0b9 --- /dev/null +++ b/utils/fade.c @@ -0,0 +1,224 @@ +/* xscreensaver, Copyright (c) 1992-1996 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 P(x)x +#else +# define P(x)() +#endif + +extern int get_visual_class P((Display *, Visual *)); +extern void screenhack_usleep P((unsigned long)); +#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; + Screen *screen = DefaultScreenOfDisplay (dpy); + Visual *visual = DefaultVisualOfScreen (screen); + Window window = RootWindowOfScreen (screen); + int vclass = get_visual_class (dpy, visual); + + ncolors = CellsOfScreen (screen); + + /* If this is a colormap on a mono visual, or one with insanely many + color cells, bug out. */ + if (ncolors <= 2 || ncolors > MAX_COLORS) + return 0; + /* If this is a non-writable visual, bug out. */ + if (vclass == StaticGray || vclass == StaticColor || vclass == TrueColor) + return 0; + + if (! into_cmap) + into_cmap = XCreateColormap (dpy, window, visual, 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); +} + + +/* The business with `install_p' and `extra_cmaps' is to fake out the SGI + 8-bit video hardware, which is capable of installing multiple (4) colormaps + simultaniously. We have to install multiple copies of the same set of + colors in order to fill up all the available slots in the hardware color + lookup table. + */ + +void +fade_colormap (dpy, cmap, cmap2, seconds, ticks, out_p, install_p) + Display *dpy; + Colormap cmap, cmap2; + int seconds, ticks; + Bool out_p; + Bool install_p; +{ + int i; + int steps = seconds * ticks; + XEvent dummy_event; + + Screen *screen = DefaultScreenOfDisplay (dpy); + Visual *visual = DefaultVisualOfScreen (screen); + Window window = RootWindowOfScreen (screen); + static Colormap extra_cmaps[4] = { 0, }; + int n_extra_cmaps = sizeof(extra_cmaps)/sizeof(*extra_cmaps); + + if (! cmap2) + return; + + for (i = 0; i < ncolors; i++) + orig_colors [i].pixel = i; + XQueryColors (dpy, cmap, orig_colors, ncolors); + memcpy (current_colors, orig_colors, ncolors * sizeof (XColor)); + + if (install_p) + for (i=0; i < n_extra_cmaps; i++) + if (!extra_cmaps[i]) + extra_cmaps[i] = XCreateColormap (dpy, window, visual, AllocAll); + + 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); + + if (install_p) + { + for (j=0; j < n_extra_cmaps; j++) + if (extra_cmaps[j]) + XStoreColors (dpy, extra_cmaps[j], current_colors, ncolors); + + for (j=0; j < n_extra_cmaps; j++) + if (extra_cmaps[j]) + XInstallColormap (dpy, extra_cmaps[j]); + XInstallColormap (dpy, cmap2); + } + + 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); + goto DONE; + } + + usleep (1000000 / (ticks * 2)); /* the 2 is a hack... */ + } + +DONE: + + if (install_p) + { + XInstallColormap (dpy, cmap2); +/* for (i=0; i < n_extra_cmaps; i++) + if (extra_cmaps[i]) + XFreeColormap (dpy, extra_cmaps[i]); + */ + } +} + + +#if 0 +#include "../hacks/screenhack.h" +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; + + XSynchronize (dpy, True); + + while (1) + { + XSync (dpy, False); +/* XGrabServer (dpy); */ + fprintf(stderr,"out..."); fflush(stderr); + XInstallColormap (dpy, cmap2); + fade_colormap (dpy, cmap, cmap2, seconds, ticks, True, True); + fprintf(stderr, "done.\n"); fflush(stderr); + if (delay) sleep (delay); + fprintf(stderr,"in..."); fflush(stderr); + fade_colormap (dpy, cmap, cmap2, seconds, ticks, False, True); + XInstallColormap (dpy, cmap); + fprintf(stderr, "done.\n"); fflush(stderr); + XUngrabServer (dpy); + XSync (dpy, False); + if (delay) sleep (delay); + } +} + +#endif diff --git a/utils/grabscreen.c b/utils/grabscreen.c new file mode 100644 index 00000000..692e42e1 --- /dev/null +++ b/utils/grabscreen.c @@ -0,0 +1,200 @@ +/* xscreensaver, Copyright (c) 1992, 1993, 1994 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 code for grabbing an image of the screen to hack its + bits. This is a little tricky, since doing this involves the need to tell + the difference between drawing on the actual root window, and on the fake + root window used by the screensaver, since at this level the illusion + breaks down... + */ + +#if __STDC__ +#include +#include +#endif + +#include +#include +#include + +static Bool +MapNotify_event_p (dpy, event, window) + Display *dpy; + XEvent *event; + XPointer window; +{ + return (event->xany.type == MapNotify && + event->xvisibility.window == (Window) window); +} + + +#if __STDC__ +static Bool screensaver_window_p (Display *, Window); +#endif + +static Bool +screensaver_window_p (dpy, window) + Display *dpy; + Window window; +{ + Atom type; + int format; + unsigned long nitems, bytesafter; + char *version; + 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; +} + +Pixmap +grab_screen_image (dpy, window, root_p) + Display *dpy; + Window window; + int root_p; +{ + Pixmap pixmap = 0; + XWindowAttributes xgwa; + + XGetWindowAttributes (dpy, window, &xgwa); + + 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... */ + XMapRaised (dpy, window); + + XUngrabPointer (dpy, CurrentTime); + XUngrabKeyboard (dpy, CurrentTime); + + XSync (dpy, True); + } + else if (root_p) + { + XGCValues gcv; + GC gc; + gcv.function = GXcopy; + gcv.subwindow_mode = IncludeInferiors; + gc = XCreateGC (dpy, window, GCFunction | GCSubwindowMode, &gcv); + 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); + XFreeGC (dpy, gc); + XSetWindowBackgroundPixmap (dpy, window, pixmap); + } + else + { + XEvent event; + XSetWindowBackgroundPixmap (dpy, window, None); + XMapWindow (dpy, window); + XFlush (dpy); + XIfEvent (dpy, &event, MapNotify_event_p, (XPointer) window); + XSync (dpy, True); + } + return pixmap; +} + + +/* When we are grabbing and manipulating a screen image, it's important that + we use the same colormap it originally had. So, if the screensaver was + started with -install, we need to copy the contents of the default colormap + into the screensaver's colormap. + */ +void +copy_default_colormap_contents (dpy, to_cmap, to_visual) + Display *dpy; + Colormap to_cmap; + Visual *to_visual; +{ + Screen *screen = DefaultScreenOfDisplay (dpy); + Visual *from_visual = DefaultVisualOfScreen (screen); + Colormap from_cmap = XDefaultColormapOfScreen (screen); + + XColor *old_colors, *new_colors; + unsigned long *pixels; + XVisualInfo vi_in, *vi_out; + int out_count; + int from_cells, to_cells, max_cells; + int requested; + int i; + + if (from_cmap == to_cmap) + return; + + vi_in.screen = XScreenNumberOfScreen (screen); + vi_in.visualid = XVisualIDFromVisual (from_visual); + vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask, + &vi_in, &out_count); + if (! vi_out) abort (); + from_cells = vi_out [0].colormap_size; + XFree ((char *) vi_out); + + vi_in.screen = XScreenNumberOfScreen (screen); + vi_in.visualid = XVisualIDFromVisual (to_visual); + vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask, + &vi_in, &out_count); + if (! vi_out) abort (); + to_cells = vi_out [0].colormap_size; + XFree ((char *) vi_out); + + max_cells = (from_cells > to_cells ? to_cells : from_cells); + + old_colors = (XColor *) calloc (sizeof (XColor), max_cells); + new_colors = (XColor *) calloc (sizeof (XColor), max_cells); + pixels = (unsigned long *) calloc (sizeof (unsigned long), max_cells); + for (i = 0; i < max_cells; i++) + old_colors[i].pixel = i; + XQueryColors (dpy, from_cmap, old_colors, max_cells); + + requested = max_cells; + while (requested > 0) + { + if (XAllocColorCells (dpy, to_cmap, False, 0, 0, pixels, requested)) + { + /* Got all the pixels we asked for. */ + for (i = 0; i < requested; i++) + new_colors[i] = old_colors [pixels[i]]; + XStoreColors (dpy, to_cmap, new_colors, requested); + } + else + { + /* We didn't get all/any of the pixels we asked for. This time, ask + for half as many. (If we do get all that we ask for, we ask for + the same number again next time, so we only do O(log(n)) server + roundtrips.) */ + requested = requested / 2; + } + } + + free (old_colors); + free (new_colors); + free (pixels); +} diff --git a/utils/hsv.c b/utils/hsv.c new file mode 100644 index 00000000..c5109120 --- /dev/null +++ b/utils/hsv.c @@ -0,0 +1,120 @@ +/* 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 +#if __STDC__ +hsv_to_rgb (int h, double s, double v, + unsigned short *r, unsigned short *g, unsigned short *b) +#else +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 */ +#endif +{ + 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 +#if __STDC__ +rgb_to_hsv (unsigned short r, unsigned short g, unsigned short b, + int *h, double *s, double *v) +#else +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 */ +#endif +{ + 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..02c499b3 --- /dev/null +++ b/utils/resources.c @@ -0,0 +1,221 @@ +/* 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; + +#if __STDC__ +char *get_string_resource (char *res_name, char *res_class); +int parse_time (char *string, Bool seconds_default_p, Bool silent_p); +static unsigned int get_time_resource (char *res_name, char *res_class, + Bool sec_p); +#endif + +#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..d242d63f --- /dev/null +++ b/utils/spline.c @@ -0,0 +1,331 @@ +/* + * Copyright (c) 1987, 1988, 1989 Stanford University + * + * 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, and that the name of Stanford not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Stanford makes no representations about + * the suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL STANFORD 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. + */ + +/* This code came with the InterViews distribution, and was translated + from C++ to C by Matthieu Devin some time in 1992. + */ + +#include +#include "spline.h" +#if __STDC__ +#include +#endif +#include + +/* Lifted from InterViews */ +#define SMOOTHNESS 1.0 + +#if __STDC__ +static void no_more_memory (void); +static void grow_spline_points (spline* s); +static void mid_point (double x0, double y0, double x1, double y1, + double *mx, double *my); +static int can_approx_with_line (double x0, double y0, double x2, + double y2, double x3, double y3); +static void add_line (spline* s, double x0, double y0, double x1, double y1); +static void add_bezier_arc (spline* s, + double x0, double y0, double x1, double y1, + double x2, double y2, double x3, double y3); +static void third_point (double x0, double y0, double x1, double y1, + double *tx, double *ty); +static void calc_section (spline* s, double cminus1x, double cminus1y, + double cx, double cy, double cplus1x, double cplus1y, + double cplus2x, double cplus2y); + +#endif + +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..a8a04d5e --- /dev/null +++ b/utils/spline.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1987, 1988, 1989 Stanford University + * + * 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, and that the name of Stanford not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Stanford makes no representations about + * the suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL STANFORD 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. + */ + +/* This code came with the InterViews distribution, and was translated + from C++ to C by Matthieu Devin some time in 1992. + */ + +#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..30e7f152 --- /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..b59e68f8 --- /dev/null +++ b/utils/version.h @@ -0,0 +1,2 @@ +static char *screensaver_id = + "@(#)xscreensaver 1.27, by Jamie Zawinski (jwz@netscape.com)"; diff --git a/utils/visual.c b/utils/visual.c new file mode 100644 index 00000000..cc8b5729 --- /dev/null +++ b/utils/visual.c @@ -0,0 +1,288 @@ +/* xscreensaver, Copyright (c) 1993, 1994, 1995 + * 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 biased in the direction of high color counts...) + */ + +#if __STDC__ +#include +#include +#include +#endif + +#include +#include +#include + +#if __STDC__ +# define P(x)x +#else +#define P(x)() +#endif + +#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 P((char *, char *)); + +static Visual *pick_best_visual P ((Screen *)); +static Visual *pick_best_visual_of_class P((Screen *, int)); +static Visual *id_to_visual P((Screen *, int)); +static int screen_number P((Screen *)); +static Visual *id_to_visual P((Screen *screen, int id)); +int get_visual_depth P((Display *dpy, Visual *visual)); + + +#define DEFAULT_VISUAL -1 +#define BEST_VISUAL -2 +#define SPECIFIC_VISUAL -3 + +Visual * +get_visual_resource (dpy, name, class) + Display *dpy; + char *name, *class; +{ + Screen *screen = DefaultScreenOfDisplay (dpy); + char c, *v = get_string_resource (name, class); + char *tmp; + int vclass; + unsigned long id; + + if (v) + for (tmp = v; *tmp; tmp++) + if (isupper (*tmp)) *tmp = _tolower (*tmp); + + if (!v) vclass = BEST_VISUAL; + else if (!strcmp (v, "default")) vclass = DEFAULT_VISUAL; + else if (!strcmp (v, "best")) vclass = BEST_VISUAL; + else if (!strcmp (v, "staticgray")) vclass = StaticGray; + else if (!strcmp (v, "staticcolor")) vclass = StaticColor; + else if (!strcmp (v, "truecolor")) vclass = TrueColor; + else if (!strcmp (v, "grayscale")) vclass = GrayScale; + else if (!strcmp (v, "pseudocolor")) vclass = PseudoColor; + else if (!strcmp (v, "directcolor")) vclass = DirectColor; + else if (1 == sscanf (v, " %ld %c", &id, &c)) vclass = SPECIFIC_VISUAL; + else if (1 == sscanf (v, " 0x%lx %c", &id, &c)) vclass = SPECIFIC_VISUAL; + else + { + fprintf (stderr, "%s: unrecognized visual \"%s\".\n", progname, v); + vclass = DEFAULT_VISUAL; + } + if (v) free (v); + + if (vclass == DEFAULT_VISUAL) + return DefaultVisualOfScreen (screen); + else if (vclass == BEST_VISUAL) + return pick_best_visual (screen); + else if (vclass == SPECIFIC_VISUAL) + { + Visual *visual = id_to_visual (screen, id); + if (visual) return visual; + fprintf (stderr, "%s: no visual with id 0x%x.\n", progname, + (unsigned int) id); + return DefaultVisualOfScreen (screen); + } + else + { + Visual *visual = pick_best_visual_of_class (screen, vclass); + if (visual) return visual; + fprintf (stderr, "%s: no visual of class %s.\n", progname, v); + return DefaultVisualOfScreen (screen); + } +} + +static Visual * +pick_best_visual (screen) + Screen *screen; +{ + /* The "best" visual is the one on which we can allocate the largest + range and number of colors. + + Therefore, a TrueColor visual which is at least 16 bits deep is best. + (The assumption here being that a TrueColor of less than 16 bits is + really just a PseudoColor visual with a pre-allocated color cube.) + + The next best thing is a PseudoColor visual of any type. After that + come the non-colormappable visuals, and non-color visuals. + */ + Display *dpy = DisplayOfScreen (screen); + Visual *visual; + if ((visual = pick_best_visual_of_class (screen, TrueColor)) && + get_visual_depth (dpy, visual) >= 16) + return visual; + if ((visual = pick_best_visual_of_class (screen, PseudoColor))) + return visual; + if ((visual = pick_best_visual_of_class (screen, TrueColor))) + return visual; + if ((visual = pick_best_visual_of_class (screen, DirectColor))) + return visual; + if ((visual = pick_best_visual_of_class (screen, GrayScale))) + return visual; + if ((visual = pick_best_visual_of_class (screen, StaticGray))) + return visual; + return DefaultVisualOfScreen (screen); +} + +static Visual * +pick_best_visual_of_class (screen, visual_class) + Screen *screen; + int visual_class; +{ + /* The best visual of a class is the one which on which we can allocate + the largest range and number of colors, which means the one with the + greatest depth and number of cells. + */ + Display *dpy = DisplayOfScreen (screen); + XVisualInfo vi_in, *vi_out; + int out_count; + + vi_in.class = visual_class; + vi_in.screen = screen_number (screen); + vi_out = XGetVisualInfo (dpy, (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++) + /* It's better if it's deeper, or if it's the same depth with + more cells (does that ever happen? Well, it could...) */ + if ((vi_out [i].depth > vi_out [best].depth) || + ((vi_out [i].depth == vi_out [best].depth) && + (vi_out [i].colormap_size > vi_out [best].colormap_size))) + best = i; + visual = vi_out [best].visual; + XFree ((char *) vi_out); + return visual; + } + else + return 0; +} + +static Visual * +id_to_visual (screen, id) + Screen *screen; + int id; +{ + Display *dpy = DisplayOfScreen (screen); + XVisualInfo vi_in, *vi_out; + int out_count; + vi_in.screen = screen_number (screen); + 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; +} + + +int +get_visual_class (dpy, visual) + Display *dpy; + Visual *visual; +{ + XVisualInfo vi_in, *vi_out; + int out_count, c; + vi_in.screen = DefaultScreen (dpy); + vi_in.visualid = XVisualIDFromVisual (visual); + vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask, + &vi_in, &out_count); + if (! vi_out) abort (); + c = vi_out [0].class; + XFree ((char *) vi_out); + return c; +} + +void +describe_visual (f, dpy, visual) + FILE *f; + Display *dpy; + Visual *visual; +{ + Screen *screen = DefaultScreenOfDisplay (dpy); + XVisualInfo vi_in, *vi_out; + int out_count; + vi_in.screen = screen_number (screen); + vi_in.visualid = XVisualIDFromVisual (visual); + vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask), + &vi_in, &out_count); + if (! vi_out) abort (); + fprintf (f, "0x%02x (%s depth: %2d, cmap: %3d)\n", + (unsigned int) vi_out->visualid, + (vi_out->class == StaticGray ? "StaticGray, " : + vi_out->class == StaticColor ? "StaticColor," : + vi_out->class == TrueColor ? "TrueColor, " : + vi_out->class == GrayScale ? "GrayScale, " : + vi_out->class == PseudoColor ? "PseudoColor," : + vi_out->class == DirectColor ? "DirectColor," : + "UNKNOWN: "), + vi_out->depth, vi_out->colormap_size /*, vi_out->bits_per_rgb*/); + XFree ((char *) vi_out); +} + +static int +screen_number (screen) + Screen *screen; +{ + Display *dpy = DisplayOfScreen (screen); + int i; + for (i = 0; i < ScreenCount (dpy); i++) + if (ScreenOfDisplay (dpy, i) == screen) + return i; + abort (); +} + +int +visual_cells (dpy, visual) + Display *dpy; + Visual *visual; +{ + XVisualInfo vi_in, *vi_out; + int out_count, c; + vi_in.screen = DefaultScreen (dpy); + vi_in.visualid = XVisualIDFromVisual (visual); + vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask, + &vi_in, &out_count); + if (! vi_out) abort (); + c = vi_out [0].colormap_size; + XFree ((char *) vi_out); + return c; +} diff --git a/utils/xroger.c b/utils/xroger.c new file mode 100644 index 00000000..039a97fc --- /dev/null +++ b/utils/xroger.c @@ -0,0 +1,106 @@ +/* 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 + +#if __STDC__ +static void crossbones (Display *, Window, GC, int x, int y, int w, int h); +#endif + +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); +} diff --git a/utils/yarandom.c b/utils/yarandom.c new file mode 100644 index 00000000..228b81ca --- /dev/null +++ b/utils/yarandom.c @@ -0,0 +1,72 @@ +/* ya_random -- Yet Another Random Number Generator. + + The unportable mess that is rand(), random(), drand48() and friends led me + to ask Phil Karlton what the Right Thing to Do was. + He responded with this. It is non-cryptographically secure, reasonably + random (more so than anything that is in any C library), and very fast. + + I don't understand how it works at all, but he says "look at Knuth, + Vol. 2 (original edition), page 26, Algorithm A. In this case n=55, + k=20 and m=2^32." + + So there you have it. + */ + +#include /* for getpid() */ +#include /* for gettimeofday() */ + + +/* The following 'random' numbers are taken from CRC, 18th Edition, page 622. + Each array element was taken from the corresponding line in the table, + except that a[0] was from line 100. 8s and 9s in the table were simply + skipped. The high order digit was taken mod 4. + */ +#define VectorSize 55 +static unsigned int a[VectorSize] = { + 035340171546, 010401501101, 022364657325, 024130436022, 002167303062, /* 5 */ + 037570375137, 037210607110, 016272055420, 023011770546, 017143426366, /* 10 */ + 014753657433, 021657231332, 023553406142, 004236526362, 010365611275, /* 14 */ + 007117336710, 011051276551, 002362132524, 001011540233, 012162531646, /* 20 */ + 007056762337, 006631245521, 014164542224, 032633236305, 023342700176, /* 25 */ + 002433062234, 015257225043, 026762051606, 000742573230, 005366042132, /* 30 */ + 012126416411, 000520471171, 000725646277, 020116577576, 025765742604, /* 35 */ + 007633473735, 015674255275, 017555634041, 006503154145, 021576344247, /* 40 */ + 014577627653, 002707523333, 034146376720, 030060227734, 013765414060, /* 45 */ + 036072251540, 007255221037, 024364674123, 006200353166, 010126373326, /* 50 */ + 015664104320, 016401041535, 016215305520, 033115351014, 017411670323 /* 55 */ +}; + +static int i1, i2; + +unsigned int ya_random() +{ + register int ret = a[i1] + a[i2]; + a[i1] = ret; + i1 = i1 >= VectorSize ? 0 : i1 + 1; + i2 = i2 >= VectorSize ? 0 : i2 + 1; + return ret; +} + +void ya_rand_init(seed) + register unsigned int seed; +{ + int i; + if (seed == 0) + { + struct timeval tp; + struct timezone tzp; + gettimeofday(&tp, &tzp); + /* ignore overflow */ + seed = (999*tp.tv_sec) + (1001*tp.tv_usec) + (1003 * getpid()); + } + + a[0] += seed; + for (i = 1; i < VectorSize; i++) + { + seed = a[i-1]*1001 + seed*999; + a[i] += seed; + } + + i1 = a[0] % VectorSize; + i2 = (i1 + 024) % VectorSize; +} diff --git a/utils/yarandom.h b/utils/yarandom.h new file mode 100644 index 00000000..53b22fd8 --- /dev/null +++ b/utils/yarandom.h @@ -0,0 +1,19 @@ +#undef random +#undef rand +#undef drand48 +#undef srandom +#undef srand +#undef srand48 + +#define random() ya_random() +#define srandom(i) ya_rand_init(0) + +#undef P +#if __STDC__ +# define P(x)x +#else +# define P(x)() +#endif + +extern unsigned int ya_random P((void)); +extern void ya_rand_init P((unsigned int));