argv@island.uu.net (Dan Heller) (08/18/89)
Submitted-by: uunet!umd5.umd.edu!jonnyg (Jon Greenblatt) Posting-number: Volume 4, Issue 91 Archive-name: aquarium/part01 This is a color/monocrome living aquarium program. The original author is unknown. The command line parsing needs to be fixed but other than that things seem to be in good shape. After unarchiving this and setting up the Makefile, type "make unshar" to uncompress the bitmap file. JonnyG. # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by rover.umd.edu!jonnyg on Wed Aug 16 10:53:04 EDT 1989 # Contents: FIRST.README Imakefile Makefile xfish.c echo x - FIRST.README sed 's/^@//' > "FIRST.README" <<'@//E*O*F FIRST.README//' Ported from X10R4 to X11R3 by Jonathan Roger Greenblatt (jonnyg@rover.umd.edu) 8/10/89 Original Author of the X10 version is Unknown. XAquarium =========== XAquarium is an X Windows application which creates a full-screen background window complete with color fish and translucent bubbles. This program is not to be confused with the older 'xfish' which featured small monochrome fish on a monochrome background. On the contrary. XAquarium features highly detailed fish in living color, translucent bubbles, and a full color background. With that confusion removed, the program will be referred to as 'XFish' from this point forward. Scientific Note: Research has shown that a moving aquarium background creates a soothing and relaxing atmosphere, thereby reducing the stresses associated with day-to-day workstation usage. A corresponding increase in productivity should result, although this is yet to be shown. XFish Creation -------------- The package includes four files ... * FIRST.README (this file) * Makefile (makefile for complete compilation) * xfish.c (application code) * xfishy.c (fairly large file containing pixmaps and bitmaps) After unpacking the shell archive, running 'make' is all that is required to compile XFish. XFish Usage ----------- usage: xfish [-b limit][-c color][-f limit][-i mult][-r rate][-s][host:display] XFish is designed to run efficiently on defaults alone, but like any good X program, command line options are provided ... * -b specifies the bubble limit (default = 32) * -c specifies the background color (default = MediumAquamarine) * -f specifies the fish limit (default = 2, for historical reasons) * -i specifies the increment multipler (default = 1.0) * -r specifies the update rate (default = 1.0 seconds) * -s activates secure mode, raising the window for use with xsecure * host:display is the standard X server specifier as well as ~/.Xdefault options for all of the above ... * xfish.BubbleLimit: 32 * xfish.Color: MediumAquamarine * xfish.FishLimit: 2 * xfish.IncMult: 1.0 * xfish.Rate: 1.0 * xfish.Secure: No A few notes on XFish performance ... * Bubbles are something of a CPU drain. Overall performance can be improved by using low bubble limits. If the bubbles appear to be flashing, try fewer bubbles, or turn off bubbles using -b0. * Off-screen display memory is used for fish if available. This results in astonishing performance gains. For this reason, fish are not much of a CPU drain, and higher fish limits can easily be used. * Changing the update rate is the most effective way to control impact on system performance. The default of 1 second results in less than a 10% CPU usage on a single user 350. Higher values may be desirable on more burdened system. * A zero update rate using -r0 creates some great looking displays. Try 'xfish -r0 -f0' and 'xfish -r0 -b0 -f8' (the latter really shows off the capabilities of the Topcat board, and is simply astounding on the Catseye board). * Decreasing the increment multiplier, using -i 0.1 for example, is especially useful in conjunction with a zero update rate. If you prefer '911 Turbo' fish, use a multiplier of greater than one. * The aquarium window obscures most of the root window. A one pixel border is provided around the window to allow quick access to the root window. An alternative, which proves very useful with the secure option, is to iconize the aquarium (until ready to xsecBure). * Sending SIGUSR1 (16) to the XFish process (using 'kill -16 <pid>') will toggle the raise-lower mode. Using this technique, xsecure can be started without the need to restart XFish. XFish Enhancements ------------------ XFish was intended to be run as a background window, and as such it was designed to minimize CPU impact. Although enhancement requests will be cheerfully accepted, it is unlikely that features will be added to the detriment of overall performance. On the other hand, any recommendations which could benefit overall performance will be utilized. @//E*O*F FIRST.README// chmod u=r,g=r,o=r FIRST.README echo x - Imakefile sed 's/^@//' > "Imakefile" <<'@//E*O*F Imakefile//' INCLUDES = -I. -I$(TOP) -I$(TOP)/X11 LOCAL_LIBRARIES = $(XLIB) SYS_LIBRARIES = -lm SRCS = xfish.c xfishy.c OBJS = xfish.o xfishy.o ComplexProgramTarget(xfish) # Make the export sharchive. shar: xaqua.shar xaqua.shar: xaqua.shar1 xaqua.shar2 xaqua.shar1: FIRST.README Imakefile Makefile xfish.c shar FIRST.README Imakefile Makefile xfish.c >xaqua.shar1 xfishy.c.Z: xfishy.c compress -c xfishy.c >xfishy.c.Z xfishy.c.Z.uu: xfishy.c.Z uuencode xfishy.c.Z xfishy.c.Z >xfishy.c.Z.uu xaqua.shar2: xfishy.c.Z.uu shar xfishy.c.Z.uu >xaqua.shar2 # Unpack the compressed, uuencoded, shared bitmap. unshar: uudecode xfishy.c.Z.uu uncompress xfishy.c.Z # Make the export tarchive. tar: xaqua.tar.Z xaqua.tar.Z: xaqua.tar rm -f xaqua.tar.Z compress xaqua.tar xaqua.tar: FIRST.README Imakefile Makefile xfish.c xfishy.c tar chf xaqua.tar FIRST.README Imakefile Makefile xfish.c xfishy.c @//E*O*F Imakefile// chmod u=r,g=r,o=r Imakefile echo x - Makefile sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//' # Makefile generated by imake - do not edit! # $XConsortium: imake.c,v 1.37 88/10/08 20:08:30 jim Exp $ ########################################################################### # X Window System Makefile generated from template file Imake.tmpl # $XConsortium: Imake.tmpl,v 1.91 88/10/23 22:37:10 jim Exp $ # # Do not change the body of the imake template file. Server-specific # parameters may be set in the appropriate .macros file; site-specific # parameters (but shared by all servers) may be set in site.def. If you # make any changes, you'll need to rebuild the makefiles using # "make World" (at best) or "make Makefile; make Makefiles" (at least) in # the top level directory. # # If your C preprocessor doesn't define any unique symbols, you'll need # to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing # "make Makefile", "make Makefiles", or "make World"). # # If you absolutely can't get imake to work, you'll need to set the # variables at the top of each Makefile as well as the dependencies at the # bottom (makedepend will do this automatically). # ########################################################################### # platform-specific configuration parameters - edit Rt.macros to change # platform: $XConsortium: Rt.macros,v 1.47 88/10/25 18:39:43 keith Exp $ # platform: $XConsortium: IBM.macros,v 1.22 88/10/25 18:39:31 keith Exp $ AS = as CPP = /lib/cpp LD = ld LINT = lint MAKE = make INSTALL = install TAGS = ctags RM = rm -f MV = mv LS = ls CP = cp STD_CPP_DEFINES = STD_DEFINES = BOOTSTRAPCFLAGS = CC = hc LDCOMBINEFLAGS = -X -r LN = ln -s RANLIB = ranlib RANLIBINSTFLAGS = -t AR = ar cq LINTOPTS = -axz LINTLIBFLAG = -C PCC = pcc ########################################################################### # site-specific configuration parameters - edit site.def to change # site: $XConsortium: site.def,v 1.16 88/10/12 10:30:24 jim Exp $ ########################################################################### # definitions common to all Makefiles - do not edit SHELL = /bin/sh DESTDIR = USRLIBDIR = $(DESTDIR)/usr/lib BINDIR = $(DESTDIR)/usr/bin/X11 INCDIR = $(DESTDIR)/usr/include/X11 ADMDIR = $(DESTDIR)/usr/adm LIBDIR = $(USRLIBDIR)/X11 LINTLIBDIR = $(USRLIBDIR)/lint FONTDIR = $(LIBDIR)/fonts XINITDIR = $(LIBDIR)/xinit XDMDIR = $(LIBDIR)/xdm UWMDIR = $(LIBDIR)/uwm AWMDIR = $(LIBDIR)/awm TWMDIR = $(LIBDIR)/twm MANPATH = $(DESTDIR)/usr/man MANSOURCEPATH = $(MANPATH)/man MANDIR = $(MANSOURCEPATH)n LIBMANDIR = $(MANSOURCEPATH)3 XAPPLOADDIR = $(LIBDIR)/app-defaults INSTBINFLAGS = -m 0755 INSTUIDFLAGS = -m 4755 INSTLIBFLAGS = -m 0664 INSTINCFLAGS = -m 0444 INSTMANFLAGS = -m 0444 INSTAPPFLAGS = -m 0444 INSTKMEMFLAGS = -m 4755 FCFLAGS = -t CDEBUGFLAGS = -O PATHSEP = / DEPEND = $(DEPENDSRC)/makedepend IMAKE = $(IMAKESRC)/imake RGB = $(RGBSRC)/rgb FC = $(BDFTOSNFSRC)/bdftosnf MKFONTDIR = $(MKFONTDIRSRC)/mkfontdir MKDIRHIER = $(SCRIPTSSRC)/mkdirhier.sh CFLAGS = $(CDEBUGFLAGS) $(INCLUDES) $(STD_DEFINES) $(DEFINES) LINTFLAGS = $(LINTOPTS) $(INCLUDES) $(STD_DEFINES) $(DEFINES) -DLINT LDFLAGS = $(CDEBUGFLAGS) $(SYS_LIBRARIES) $(SYSAUX_LIBRARIES) TOP = ./../../.. CLIENTSRC = $(TOP)/clients DEMOSRC = $(TOP)/demos LIBSRC = $(TOP)/lib FONTSRC = $(TOP)/fonts INCLUDESRC = $(TOP)/X11 SERVERSRC = $(TOP)/server UTILSRC = $(TOP)/util SCRIPTSSRC = $(UTILSRC)/scripts EXAMPLESRC = $(TOP)/examples CONTRIBSRC = $(TOP)/contrib DOCSRC = $(TOP)/doc RGBSRC = $(TOP)/rgb DEPENDSRC = $(UTILSRC)/makedepend IMAKESRC = $(UTILSRC)/imake IRULESRC = $(UTILSRC)/imake.includes XLIBSRC = $(LIBSRC)/X XMUSRC = $(LIBSRC)/Xmu TOOLKITSRC = $(LIBSRC)/Xt AWIDGETSRC = $(LIBSRC)/Xaw OLDXLIBSRC = $(LIBSRC)/oldX BDFTOSNFSRC = $(FONTSRC)/bdftosnf MKFONTDIRSRC = $(FONTSRC)/mkfontdir EXTENSIONSRC = $(TOP)/extensions EXTENSIONLIB = $(EXTENSIONSRC)/lib/libXext.a XLIB = $(XLIBSRC)/libX11.a XMULIB = $(XMUSRC)/libXmu.a OLDXLIB = $(OLDXLIBSRC)/liboldX.a XTOOLLIB = $(TOOLKITSRC)/libXt.a XAWLIB = $(AWIDGETSRC)/libXaw.a LINTXLIB = $(XLIBSRC)/llib-lX11.ln LINTXMU = $(XMUSRC)/llib-lXmu.ln LINTXTOOL = $(TOOLKITSRC)/llib-lXt.ln LINTXAW = $(AWIDGETSRC)/llib-lXaw.ln INCLUDES = -I$(TOP) MACROFILE = Rt.macros ICONFIGFILES = $(IRULESRC)/Imake.tmpl \ $(IRULESRC)/$(MACROFILE) $(IRULESRC)/site.def IMAKE_DEFINES = IMAKE_CMD = $(NEWTOP)$(IMAKE) -TImake.tmpl -I$(NEWTOP)$(IRULESRC) \ -s Makefile $(IMAKE_DEFINES) RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a \ .emacs_* tags TAGS make.log MakeOut ########################################################################### # rules: $XConsortium: Imake.rules,v 1.71 88/10/23 22:46:34 jim Exp $ ########################################################################### # start of Imakefile INCLUDES = -I. -I$(TOP) -I$(TOP)/X11 LOCAL_LIBRARIES = $(XLIB) SYS_LIBRARIES = -lm SRCS = xfish.c xfishy.c OBJS = xfish.o xfishy.o PROGRAM = xfish all:: xfish xfish: $(OBJS) $(LOCAL_LIBRARIES) $(RM) $@ $(CC) -o $@ $(OBJS) $(LOCAL_LIBRARIES) $(LDFLAGS) $(SYSLAST_LIBRARIES) relink:: $(RM) $(PROGRAM) $(MAKE) $(MFLAGS) $(PROGRAM) install:: xfish $(INSTALL) -c $(INSTALLFLAGS) xfish $(BINDIR) install.man:: xfish.man $(INSTALL) -c $(INSTMANFLAGS) xfish.man $(MANDIR)/xfish.n depend:: $(DEPEND) depend:: $(DEPEND) -s "# DO NOT DELETE" -- $(CFLAGS) -- $(SRCS) $(DEPEND): @echo "making $@"; \ cd $(DEPENDSRC); $(MAKE) clean:: $(RM) $(PROGRAM) # Make the export sharchive. shar: xaqua.shar xaqua.shar: xaqua.shar1 xaqua.shar2 xaqua.shar1: FIRST.README Imakefile Makefile xfish.c shar FIRST.README Imakefile Makefile xfish.c >xaqua.shar1 xfishy.c.Z: xfishy.c compress -c xfishy.c >xfishy.c.Z xfishy.c.Z.uu: xfishy.c.Z uuencode xfishy.c.Z xfishy.c.Z >xfishy.c.Z.uu xaqua.shar2: xfishy.c.Z.uu shar xfishy.c.Z.uu >xaqua.shar2 # Unpack the compressed, uuencoded, shared bitmap. unshar: uudecode xfishy.c.Z.uu uncompress xfishy.c.Z # Make the export tarchive. tar: xaqua.tar.Z xaqua.tar.Z: xaqua.tar rm -f xaqua.tar.Z compress xaqua.tar xaqua.tar: FIRST.README Imakefile Makefile xfish.c xfishy.c tar chf xaqua.tar FIRST.README Imakefile Makefile xfish.c xfishy.c ########################################################################### # Imake.tmpl common rules for all Makefiles - do not edit emptyrule:: clean:: $(RM_CMD) \#* Makefile:: $(IMAKE) Makefile:: Imakefile \ $(IRULESRC)/Imake.tmpl \ $(IRULESRC)/Imake.rules \ $(IRULESRC)/site.def \ $(IRULESRC)/$(MACROFILE) -@if [ -f Makefile ]; then \ echo "$(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \ $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \ else exit 0; fi $(IMAKE_CMD) -DTOPDIR=$(TOP) $(IMAKE): @echo "making $@"; \ cd $(IMAKESRC); $(MAKE) BOOTSTRAPCFLAGS=$(BOOTSTRAPCFLAGS) tags:: $(TAGS) -w *.[ch] $(TAGS) -xw *.[ch] > TAGS ########################################################################### # empty rules for directories that do not have SUBDIRS - do not edit install:: @echo "install done" install.man:: @echo "install.man done" Makefiles:: ########################################################################### # dependencies generated by makedepend # DO NOT DELETE xfish.o: /usr/include/sys/time.h /usr/include/sys/time.h /usr/include/stdio.h xfish.o: /usr/include/signal.h ./../../../X11/Xlib.h /usr/include/sys/types.h xfish.o: ./../../../X11/X.h ./../../../X11/Xutil.h xfishy.o: ./../../../X11/Xlib.h /usr/include/sys/types.h ./../../../X11/X.h @//E*O*F Makefile// chmod u=rw,g=rw,o=rw Makefile echo x - xfish.c sed 's/^@//' > "xfish.c" <<'@//E*O*F xfish.c//' static char ident[] = "@(#)$Header: XFish release 3, revision 1, 11 Aug 1989 $"; /* * Original Author Unknow. * 8/10/88 - Ported from X10 to X11R3 by: Jonathan Greenblatt (jonnyg@rover.umd.edu) * Cleaned up by Dave Lemke (lemke@sun.com) * Ported to monocrome by Jonathan Greenblatt (jonnyg@rover.umd.edu) TODO: Parameter parsing needs to be redone. */ #ifndef HPUX #include <sys/time.h> #else #include <time.h> #endif #include <stdio.h> #include <signal.h> #include <X11/Xlib.h> #include <X11/Xutil.h> /* constants are based on rand(3C) returning an integer between 0 and 32767 */ #ifndef HPUX #define RAND_I_1_16 134217728 #define RAND_F_1_8 268435455.875 #define RAND_I_1_4 536870911 #define RAND_I_1_2 1073741823 #define RAND_I_3_4 1610612735 #define RAND_F_MAX 2147483647.0 #else #define RAND_I_1_16 2048 #define RAND_F_1_8 4096.0 #define RAND_I_1_4 8096 #define RAND_I_1_2 16384 #define RAND_I_3_4 24575 #define RAND_F_MAX 32767.0 #endif /* externals for pixmap and bimaps from xfishy.c */ extern int rwidth, rheight, rcolors, rback, rreds[], rgreens[], rblues[]; extern short xfishRaster[]; extern unsigned char xbBits[9][8]; extern char fish_bits[], fishl_bits[]; int mono; /* typedefs for bubble and fish structures, also caddr_t (not used in X.h) */ typedef struct { int x, y, s, i; } bubble; typedef struct { int x, y, d, i; } fish; typedef unsigned char *caddrt; /* bubble increment and yes check tables */ int binc[] = {0, 64, 56, 48, 40, 32, 24, 16, 8}; char *yess[] = {"yes", "Yes", "YES", "on", "On", "ON"}; char *pname, /* program name from argv[0] */ sname[64], /* host:display specification */ cname[64]; /* colorname specification */ int blimit = 32, /* bubble limit */ flimit = 2, /* fish limit */ pmode = 1, /* pop mode, (1 for lower, 0 for raise) */ width, /* width of initial window in pixels */ height, /* height of initial window in pixels */ screen; /* Default screen of this display */ Init_B, *cmap; /* Initialize bubbles with random y value */ double rate = 1.0, /* update interval in seconds */ smooth = 1.0; /* smoothness increment multiplier */ bubble *binfo; /* bubble info structures, allocated * dynamically */ fish *finfo; /* fish info structures, allocated dynamically */ Display *Dpy; XImage *xfish[3]; /* fish pixmaps (1 is left-fish, 2 is * right-fish) */ Pixmap pfish[3] = {0, 0, 0}; Pixmap xbubbles[9]; /* bubbles bitmaps (1 to 8, by size in pixels)*/ Window wid; /* aqaurium window */ unsigned long white, black,bcolor; Colormap colormap; GC gc, bgc; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Output desired error message and exit. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void msgdie(message) char *message; { fprintf(stderr, "%s: %s\n", pname, message); exit(1); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Set up program defaults, get X defaults, parse command line using getopts. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void parse(argc, argv) int argc; char **argv; { int c, i; char *p; extern int optind; extern char *optarg; extern double atof(); pname = argv[0]; strcpy(sname, getenv("DISPLAY")); strcpy(cname, "MediumAquamarine"); if ((p = XGetDefault(Dpy, pname, "BubbleLimit")) != NULL) blimit = atoi(p); if ((p = XGetDefault(Dpy, pname, "Color")) != NULL) strcpy(cname, p); if ((p = XGetDefault(Dpy, pname, "FishLimit")) != NULL) flimit = atoi(p); if ((p = XGetDefault(Dpy, pname, "IncMult")) != NULL) smooth = atof(p); if ((p = XGetDefault(Dpy, pname, "Rate")) != NULL) rate = atof(p); if ((p = XGetDefault(Dpy, pname, "Secure")) != NULL) for (i = 0; i < 6; i++) if (strcmp(p, yess[i]) == 0) pmode = 0; while ((c = getopt(argc, argv, "b:c:f:i:r:s")) != EOF) { switch (c) { case 'b': blimit = atoi(optarg); break; case 'c': strcpy(cname, optarg); break; case 'f': flimit = atoi(optarg); break; case 'i': smooth = atof(optarg); break; case 'r': rate = atof(optarg); break; case 's': pmode = 0; break; case '?': fprintf(stderr, "usage: %s [-b limit][-c color][-f limit][-i mult][-r rate][-s][host:display]\n", pname); exit(1); } } if (optind < argc) strcpy(sname, argv[optind]); } putfish(f) fish *f; { if (pfish[f->d]) XCopyArea(Dpy, pfish[f->d], wid, gc, 0, 0, rwidth, rheight, f->x, f->y); else XPutImage(Dpy, wid, gc, xfish[f->d], 0, 0, f->x, f->y, rwidth, rheight); } putbubble(b, s, c) bubble *b; int s; unsigned long c; { XGCValues gcv; gcv.foreground = c; gcv.clip_mask = xbubbles[s]; gcv.clip_x_origin = b->x; gcv.clip_y_origin = b->y; XChangeGC(Dpy, bgc, GCForeground | GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv); XFillRectangle(Dpy, wid, bgc, b->x, b->y, s, s); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Initialize colormap for background color and required fish colors. The fish colors are coded in xfishy.c as a trio of tables. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void init_colormap() { int i; XColor hdef, edef; extern char *malloc(); colormap = XDefaultColormap(Dpy, screen); if (colormap == NULL) return; cmap = (int *) malloc((rcolors + 1) * sizeof(int)); if (!mono) { XAllocNamedColor(Dpy, colormap, cname, &hdef, &edef); cmap[0] = hdef.pixel; for (i = 0; i < rcolors; i++) { hdef.red = rreds[i]; hdef.green = rgreens[i]; hdef.blue = rblues[i]; XAllocColor(Dpy, colormap, &hdef); cmap[i + 1] = hdef.pixel; } bcolor = white; } else { for (i = 0; i < (rcolors+1); i++) cmap[i] = black; cmap[0] = cmap[rback] = white; bcolor = black; } cmap[rback] = cmap[0]; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Calibrate the pixmaps and bimaps. The left-fish data is coded in xfishy.c, this is transformed to create the right-fish. The eight bubbles are coded in xfishy.c as a two dimensional array. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void init_pixmap() { register caddrt p, q, x1, x2; register int i, j; extern char *malloc(); j = rwidth * rheight; x1 = p = (caddrt) xfishRaster; for (i = 0; i < j; i++, p++) *p = cmap[*p]; x2 = (caddrt) malloc(rwidth * rheight); for (i = 0; i < rheight; i++) { p = x1 + i * rwidth; q = x2 + (i + 1) * rwidth - 1; for (j = 0; j < rwidth; j++) *q-- = *p++; } xfish[1] = XCreateImage(Dpy, DefaultVisual(Dpy, screen), 8, ZPixmap, 0, x1, rwidth, rheight, 8, rwidth); xfish[2] = XCreateImage(Dpy, DefaultVisual(Dpy, screen), 8, ZPixmap, 0, x2, rwidth, rheight, 8, rwidth); if (!mono) { /* Color Dislay */ i = DisplayPlanes(Dpy, screen); pfish[1] = XCreatePixmap(Dpy, wid, rwidth, rheight, i); if (pfish[1]) pfish[2] = XCreatePixmap(Dpy, wid, rwidth, rheight, i); if (pfish[1]) XPutImage(Dpy, pfish[1], gc, xfish[1], 0, 0, 0, 0, rwidth, rheight); if (pfish[2]) XPutImage(Dpy, pfish[2], gc, xfish[2], 0, 0, 0, 0, rwidth, rheight); if (pfish[1]) XDestroyImage(xfish[1]); if (pfish[2]) XDestroyImage(xfish[2]); xfish[1] = XCreateImage(Dpy, DefaultVisual(Dpy, screen), 8, ZPixmap, 0, x1, rwidth, rheight, 8, rwidth); xfish[2] = XCreateImage(Dpy, DefaultVisual(Dpy, screen), 8, ZPixmap, 0, x2, rwidth, rheight, 8, rwidth); } else { /* Mono Display */ pfish[1] = XCreateBitmapFromData(Dpy,wid,fish_bits,rwidth,rheight); pfish[2] = XCreateBitmapFromData(Dpy,wid,fishl_bits,rwidth,rheight); } for (i = 1; i <= 8; i++) xbubbles[i] = XCreateBitmapFromData(Dpy, wid, xbBits[i], i, i); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Toggle secure mode on receipt of signal * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ toggle_secure() { pmode = !pmode; if (pmode) XLowerWindow(Dpy, wid); else XRaiseWindow(Dpy, wid); XFlush(Dpy); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Initialize signal so that SIGUSR1 causes secure mode to toggle. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void init_signals() { struct sigvec vec; vec.sv_handler = toggle_secure; vec.sv_mask = 0; vec.sv_onstack = 0; #ifndef HPUX sigvec(SIGUSR1, &vec, &vec); #else sigvector(SIGUSR1, &vec, &vec); #endif } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Variety of initialization calls, including getting the window up and running. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void initialize() { XWindowAttributes winfo; XSetWindowAttributes attr; XGCValues vals; extern char *malloc(); XSizeHints xsh; XGetWindowAttributes(Dpy, DefaultRootWindow(Dpy), &winfo); width = winfo.width; height = winfo.height; init_colormap(); attr.override_redirect = True; attr.background_pixel = cmap[0]; wid = XCreateWindow(Dpy, DefaultRootWindow(Dpy), 1, 1, width - 2, height - 2, 0, CopyFromParent, CopyFromParent, CopyFromParent, CWBackPixel | CWOverrideRedirect, &attr); if (!wid) msgdie("XCreateWindow failed"); vals.foreground = vals.background = cmap[0]; vals.graphics_exposures = False; gc = XCreateGC(Dpy, wid, GCForeground | GCBackground | GCGraphicsExposures, &vals); bgc = XCreateGC(Dpy, wid, GCForeground | GCBackground | GCGraphicsExposures, &vals); init_pixmap(); init_signals(); XStoreName(Dpy, wid, pname); xsh.flags = USSize | USPosition | PPosition | PSize; xsh.x = xsh.y = 0; xsh.width = width; xsh.height = height; XSetNormalHints(Dpy, wid, &xsh); XMapWindow(Dpy, wid); binfo = (bubble *) malloc(blimit * sizeof(bubble)); finfo = (fish *) malloc(flimit * sizeof(fish)); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Create a new bubble. Placement along the x axis is random, as is the size of the bubble. Increment value is determined by speed. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void new_bubble(b0) bubble *b0; { register int s; register bubble *b = b0; b->x = width * (rand() / RAND_F_MAX); if (Init_B) b->y = (height / 16) * (rand() / RAND_I_1_16 + 1) - 1; else b->y = height - 1; b->s = s = 1.0 + rand() / RAND_F_1_8; if ((b->i = smooth * height / (float) binc[s]) == 0) b->i = 1; putbubble(b, s, bcolor); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Erase old bubbles, move and draw new bubbles. Random left-right factor can move bubble one size-unit in either direction. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void step_bubbles() { register int i, j, s; register bubble *b; for (i = 0; i < blimit; i++) { b = &binfo[i]; s = b->s; /* clear */ if (b->y > 0) putbubble(b, s, cmap[0]); if ((b->y -= b->i) > 0) { j = rand(); if (j < RAND_I_1_4) b->x -= s; else if (j > RAND_I_3_4) b->x += s; putbubble(b, s, bcolor); } else { if (rand() < RAND_I_1_4) new_bubble(b); } } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Fish collision detection. The specified fish is checked against all other fish for overlap. The xt parameter specifies the x axis tolerance for overlap. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ int collide_fish(f0, xt) fish *f0; int xt; { int i, j; register fish *f = f0; for (i = 0; i < flimit; i++) { if (&finfo[i] != f) { j = finfo[i].y - f->y; if ((j > -rheight) && (j < rheight)) { j = finfo[i].x - f->x; if ((j > -xt) && (j < xt)) return (1); } } } return (0); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Create a new fish. Placement along the y axis is random, as is the side from which the fish appears. Direction is determined from side. Increment is also random. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void new_fish(f0) fish *f0; { int i, collide; fish *f = f0; for (i = 0, collide = 1; (i < 16) && (collide); i++) { f->y = (height - rheight) * (rand() / RAND_F_MAX); if ((f->i = smooth * width / (8.0 * (1.0 + rand() / RAND_F_1_8))) == 0) f->i = 1; if (rand() < RAND_I_1_2) { f->d = 1; f->x = width; } else { f->d = 2; f->x = -rwidth; } collide = collide_fish(f, 2 * rwidth); } if (!collide) putfish(f); else f->d = 0; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Move all the fish. Clearing old fish is accomplished by masking only the exposed areas of the old fish. Random up-down factor can move fish 1/4 a fish height in either direction, if no collisions are caused. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void move_fish() { register int i, j, x, y, ofx, ofy, done; register fish *f; for (i = 0; i < flimit; i++) { f = &finfo[i]; if (f->d) { ofx = f->x; ofy = f->y; if (f->d == 1) { done = ((f->x -= f->i) < -rwidth); x = f->x + rwidth; } else if (f->d == 2) { done = ((f->x += f->i) > width); x = f->x - f->i; } if (!collide_fish(f, rwidth)) { if (!done) { j = rand(); if (j < RAND_I_1_4) y = f->i / 4; else if (j > RAND_I_3_4) y = f->i / -4; else y = 0; if (y) { f->y += y; if (collide_fish(f, rwidth)) { f->y -= y; y = 0; } else { if (y > 0) { j = f->y - y; } else { j = f->y + rheight; y *= -1; } } } putfish(f); XClearArea(Dpy, wid, x, ofy, f->i, rheight, 0); if (y) XClearArea(Dpy, wid, ofx, j, rwidth, y, 0); } else { XClearArea(Dpy, wid, x, f->y, f->i, rheight, 0); new_fish(f); } } else { if ((f->d = 3 - f->d) == 1) { f->x = f->x - 2 * f->i; x = f->x + rwidth; } else { f->x = f->x + 2 * f->i; x = f->x - f->i; } putfish(f); XClearArea(Dpy, wid, x, f->y, f->i, rheight, 0); } } else { new_fish(f); } } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Higher-resolution sleep * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void high_res_sleep(seconds) double seconds; { int fds = 0; struct timeval timeout; timeout.tv_sec = seconds; timeout.tv_usec = (seconds - timeout.tv_sec) * 1000000.0; select(0, &fds, &fds, &fds, &timeout); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void main(argc, argv) int argc; char **argv; { int i; XEvent ev; if ((Dpy = XOpenDisplay("")) == 0) msgdie("XOpenDisplay failed"); screen = DefaultScreen(Dpy); if (DisplayPlanes(Dpy,screen) < 4) mono = 1; else mono = 0; white = WhitePixel(Dpy, screen); black = BlackPixel(Dpy, screen); parse(argc, argv); initialize(); srand((unsigned) getpid()); Init_B = 1; for (i = 0; i < blimit; i++) new_bubble(&binfo[i]); for (i = 0; i < flimit; i++) new_fish(&finfo[i]); if (pmode) XLowerWindow(Dpy, wid); else XRaiseWindow(Dpy, wid); XFlush(Dpy); Init_B = 0; for (;;) { if (XPending(Dpy)) XNextEvent(Dpy, &ev); high_res_sleep(rate); move_fish(); step_bubbles(); if (pmode) XLowerWindow(Dpy, wid); else XRaiseWindow(Dpy, wid); } } @//E*O*F xfish.c// chmod u=r,g=r,o=r xfish.c exit 0