[comp.sources.x] v03i016: a colorful kaleidoscopic display, version 3, Part01/01

mikew@wyse.wyse.com (Mike Wexler) (02/18/89)

Submitted-by: nathanm@hp-pcd.hp.com (Nathan Meyers)
Posting-number: Volume 3, Issue 16
Archive-name:  kaleid3/part01

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  README AUTHOR CHANGES Imakefile Makefile kaleid.1 kaleid.c
#   kalicon.h patchlevel.h
# Wrapped by mikew@wyse on Fri Feb 17 11:04:45 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(501 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XKaleid produces a colorful kaleidoscope display in an X11 window -- it
Xwas ported from an MS-DOS program written for the EGA/VGA display.
X
XFor connoisseurs of window managers, this program does two interesting
Xthings: 1) it creates and maintains a window icon, and 2) it observes
Xwindow manager sizing hints for its window icon.
X
XTo make on bsd systems:
X
X	make
X
XTo make on systems of SYSV descent (such as hp-ux):
X
X	make SYSV
X
X---------------------
XNathan Meyers
XHewlett-Packard
Xnathanm@hp-pcd.hp.com
END_OF_FILE
if test 501 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'AUTHOR' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'AUTHOR'\"
else
echo shar: Extracting \"'AUTHOR'\" \(369 characters\)
sed "s/^X//" >'AUTHOR' <<'END_OF_FILE'
XThis X11 implementation is based on a public-domain kaleidoscope program
Xby Judson D. McClendon of Sun Valley Systems (Birmingham, AL).
XPermission granted to author to port to X11 and publish.
X
XX11 kaleid program by Nathan Meyers of Hewlett-Packard (internet mail
Xaddress nathanm@hp-pcd.hp.com).  Permission granted to freely copy and
Xdistribute on a non-profit basis.
END_OF_FILE
if test 369 -ne `wc -c <'AUTHOR'`; then
    echo shar: \"'AUTHOR'\" unpacked with wrong size!
fi
# end of 'AUTHOR'
fi
if test -f 'CHANGES' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'CHANGES'\"
else
echo shar: Extracting \"'CHANGES'\" \(215 characters\)
sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
XX11 Kaleidoscope, patchlevel 3.  More enhancements since last submission:
X
X        -bstore
X        -clip
X        -colors
X        -qix
X        -refresh
X        enhanced root-window behavior
X
XA few bug-fixes as well.
END_OF_FILE
if test 215 -ne `wc -c <'CHANGES'`; then
    echo shar: \"'CHANGES'\" unpacked with wrong size!
fi
# end of 'CHANGES'
fi
if test -f 'Imakefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Imakefile'\"
else
echo shar: Extracting \"'Imakefile'\" \(84 characters\)
sed "s/^X//" >'Imakefile' <<'END_OF_FILE'
X      SYS_LIBRARIES = -lX11
XSimpleProgramTarget(kaleid)
XNormalLintTarget(kaleid.c)
X
END_OF_FILE
if test 84 -ne `wc -c <'Imakefile'`; then
    echo shar: \"'Imakefile'\" unpacked with wrong size!
fi
# end of 'Imakefile'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(6510 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# Makefile generated by imake - do not edit!
X# $XConsortium: imake.c,v 1.37 88/10/08 20:08:30 jim Exp $
X#
X# The cpp used on this machine replaces all newlines and multiple tabs and
X# spaces in a macro expansion with a single space.  Imake tries to compensate
X# for this, but is not always successful.
X#
X
X###########################################################################
X# X Window System Makefile generated from template file Imake.tmpl
X# $XConsortium: Imake.tmpl,v 1.91 88/10/23 22:37:10 jim Exp $
X#
X# Do not change the body of the imake template file.  Server-specific
X# parameters may be set in the appropriate .macros file; site-specific
X# parameters (but shared by all servers) may be set in site.def.  If you
X# make any changes, you'll need to rebuild the makefiles using
X# "make World" (at best) or "make Makefile; make Makefiles" (at least) in
X# the top level directory.
X#
X# If your C preprocessor doesn't define any unique symbols, you'll need
X# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
X# "make Makefile", "make Makefiles", or "make World").
X#
X# If you absolutely can't get imake to work, you'll need to set the
X# variables at the top of each Makefile as well as the dependencies at the
X# bottom (makedepend will do this automatically).
X#
X
X###########################################################################
X# platform-specific configuration parameters - edit Sun.macros to change
X
X# platform:  $XConsortium: Sun.macros,v 1.52 88/10/23 11:00:55 jim Exp $
X# operating system:   SunOS 3.4
X
XBOOTSTRAPCFLAGS =
X             AS = as
X             CC = cc
X            CPP = /lib/cpp
X             LD = ld
X           LINT = lint
X        INSTALL = install
X           TAGS = ctags
X             RM = rm -f
X             MV = mv
X             LN = ln -s
X         RANLIB = ranlib
XRANLIBINSTFLAGS = -t
X             AR = ar clq
X             LS = ls
X       LINTOPTS = -xz
X    LINTLIBFLAG = -C
X           MAKE = make
XSTD_CPP_DEFINES =
X    STD_DEFINES =
X
X###########################################################################
X# site-specific configuration parameters - edit site.def to change
X
X# site:  $XConsortium: site.def,v 1.16 88/10/12 10:30:24 jim Exp $
X
X###########################################################################
X# definitions common to all Makefiles - do not edit
X
X          SHELL =  /bin/sh
X
X        DESTDIR = /global
X      USRLIBDIR = $(DESTDIR)/lib
X         BINDIR = $(DESTDIR)/bin/X11
X         INCDIR = $(DESTDIR)/include
X         ADMDIR = $(DESTDIR)/usr/adm
X         LIBDIR = $(USRLIBDIR)/X11
X     LINTLIBDIR = $(USRLIBDIR)/lint
X        FONTDIR = $(LIBDIR)/fonts
X       XINITDIR = $(LIBDIR)/xinit
X         XDMDIR = $(LIBDIR)/xdm
X         UWMDIR = $(LIBDIR)/uwm
X         AWMDIR = $(LIBDIR)/awm
X         TWMDIR = $(LIBDIR)/twm
X          DTDIR = $(LIBDIR)/dt
X        MANPATH = /usr/man
X  MANSOURCEPATH = $(MANPATH)/man
X         MANDIR = $(MANSOURCEPATH)n
X      LIBMANDIR = $(MANSOURCEPATH)n3
X    XAPPLOADDIR = $(LIBDIR)/app-defaults
X
X   INSTBINFLAGS = -m 0755
X   INSTUIDFLAGS = -m 4755
X   INSTLIBFLAGS = -m 0664
X   INSTINCFLAGS = -m 0444
X   INSTMANFLAGS = -m 0444
X   INSTAPPFLAGS = -m 0444
X  INSTKMEMFLAGS = -m 4755
X        FCFLAGS = -t
X    CDEBUGFLAGS = -O
X
X        PATHSEP = /
X         DEPEND = $(BINDIR)/makedepend
X          IMAKE = $(BINDIR)/imake
X            RGB = $(LIBDIR)/rgb
X             FC = $(BINDIR)/bdftosnf
X      MKFONTDIR = $(BINDIR)/mkfontdir
X      MKDIRHIER = $(BINDIR)/mkdirhier.sh
X
X         CFLAGS = $(CDEBUGFLAGS) $(INCLUDES) $(STD_DEFINES) $(DEFINES)
X      LINTFLAGS = $(LINTOPTS) $(INCLUDES) $(STD_DEFINES) $(DEFINES) -DLINT
X        LDFLAGS = $(CDEBUGFLAGS) -L$(USRLIBDIR) $(SYS_LIBRARIES) $(SYSAUX_LIBRARIES)
X
X       IRULESRC = $(LIBDIR)/imake.includes
X
X   EXTENSIONLIB = $(USRLIBDIR)/libext.a
X           XLIB = $(USRLIBDIR)/libX11.a
X         XMULIB = $(USRLIBDIR)/libXmu.a
X        OLDXLIB = $(USRLIBDIR)/liboldX.a
X       XTOOLLIB = $(USRLIBDIR)/libXt.a
X         XAWLIB = $(USRLIBDIR)/libXaw.a
X       LINTXLIB = $(USRLIBDIR)/lint/llib-lX11.ln
X        LINTXMU = $(USRLIBDIR)/lint/llib-lXmu.ln
X      LINTXTOOL = $(USRLIBDIR)/lint/llib-lXt.ln
X        LINTXAW = $(USRLIBDIR)/lint/llib-lXaw.ln
X       INCLUDES = -I$(INCDIR)
X      MACROFILE = Sun.macros
X   ICONFIGFILES = $(IRULESRC)/Imake.tmpl \
X			$(IRULESRC)/$(MACROFILE) $(IRULESRC)/site.def
X  IMAKE_DEFINES =
X      IMAKE_CMD = $(NEWTOP)$(IMAKE) -TImake.tmpl -I$(NEWTOP)$(IRULESRC) \
X			-s Makefile $(IMAKE_DEFINES)
X         RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a \
X			.emacs_* tags TAGS make.log MakeOut
X
X###########################################################################
X# rules:  $XConsortium: Imake.rules,v 1.71 88/10/23 22:46:34 jim Exp $
X
X###########################################################################
X# start of Imakefile
X
X      SYS_LIBRARIES = -lX11
X
X OBJS = kaleid.o
X SRCS = kaleid.c
X
X PROGRAM = kaleid
X
Xall:: kaleid
X
Xkaleid: $(OBJS) $(LOCAL_LIBRARIES)
X	$(RM) $@
X	$(CC) -o $@ $(OBJS) $(LOCAL_LIBRARIES) $(LDFLAGS) $(SYSLAST_LIBRARIES)
X
Xrelink::
X	$(RM) $(PROGRAM)
X	$(MAKE) $(MFLAGS) $(PROGRAM)
X
Xinstall:: kaleid
X	$(INSTALL) -c $(INSTALLFLAGS) kaleid $(BINDIR)
X
Xinstall.man:: kaleid.man
X	$(INSTALL) -c $(INSTMANFLAGS) kaleid.man $(MANDIR)/kaleid.n
X
Xdepend:: $(DEPEND)
X
Xdepend::
X	$(DEPEND) -s "# DO NOT DELETE" -- $(CFLAGS) -- $(SRCS)
X
X$(DEPEND):
X	@echo "making $@"; \
X	cd $(DEPENDSRC); $(MAKE)
X
Xclean::
X	$(RM) $(PROGRAM)
X
Xlint:
X	$(LINT) $(LINTFLAGS) kaleid.c $(LINTLIBS)
Xlint1:
X	$(LINT) $(LINTFLAGS) $(FILE) $(LINTLIBS)
X
X###########################################################################
X# Imake.tmpl common rules for all Makefiles - do not edit
X
Xemptyrule::
X
Xclean::
X	$(RM_CMD) \#*
X
XMakefile:: $(IMAKE)
X
XMakefile:: Imakefile \
X	$(IRULESRC)/Imake.tmpl \
X	$(IRULESRC)/Imake.rules \
X	$(IRULESRC)/site.def \
X	$(IRULESRC)/$(MACROFILE)
X	-@if [ -f Makefile ]; then \
X	echo "$(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \
X	$(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
X	else exit 0; fi
X	$(IMAKE_CMD) -DTOPDIR=$(TOP)
X
X$(IMAKE):
X	@echo "making $@"; \
X	cd $(IMAKESRC); $(MAKE) BOOTSTRAPCFLAGS=$(BOOTSTRAPCFLAGS)
X
Xtags::
X	$(TAGS) -w *.[ch]
X	$(TAGS) -xw *.[ch] > TAGS
X
X###########################################################################
X# empty rules for directories that do not have SUBDIRS - do not edit
X
Xinstall::
X	@echo "install done"
X
Xinstall.man::
X	@echo "install.man done"
X
XMakefiles::
X
X###########################################################################
X# dependencies generated by makedepend
X
END_OF_FILE
if test 6510 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'kaleid.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'kaleid.1'\"
else
echo shar: Extracting \"'kaleid.1'\" \(6290 characters\)
sed "s/^X//" >'kaleid.1' <<'END_OF_FILE'
X.TH KALEID 1
X.PD
X.ad b
X.SH NAME
Xkaleid \- X11 Kaleidoscope Display
X.SH SYNOPSIS
X.TP \w'\fBkaleid\fR 'u
X\fBkaleid\fR
X[\|\fB-bd\fR border\|] [\|\fB-bg\fR background\|]
X[\|\fB-bstore\fR\|]
X[\|\fB-bw\fR borderwidth\|]
X[\|\fB-clip\fR x,y,w,h\|[\|,x,y,w,h\|[\|,...\|]\|]\|]
X[\|\fB-colors\fR color1\|[\|,color2\|[\|,...\|]\|]\|]
X[\|\fB-delay\fR msec\|] [\|\fB-display\fR displayname\|]
X[\|\fB-geometry\fR geometry\|] [\|\fB-icondelay\fR msec\|] [\|\fB-iconic\fR\|]
X[\|\fB-mono\fR\|] [\|\fB-mult\fR number\|] [\|\fB-qix\fR\|] [\|\fB-r\fR\|]
X[\|\fB-randomcolor\fR\|] [\|\fB-refresh\fR\|]
X.SH HP-UX COMPATIBILITY
X.TP 10
XOrigin:
XUser Contributed
X.SH DESCRIPTION
X.I Kaleid
Xruns a colorful kaleidoscope display in an X11 window.  The 16-color
Xpalette is chosen to approximate the default palette found on EGA and
XVGA displays.
X.PP
XWith window managers that support icon windows (such as \fIuwm\fR), the
X\fIkaleid\fR icon is a small kaleidoscope window that runs a slow
Xkaleidoscope display (see \fB-icondelay\fR option, below).
X.PP
XOptions:
X.TP .5i
X.B -bd
XSpecify border color; defaults to white.
X.TP
X.B -bg
XSpecify background color; defaults to black.
X.TP
X.B -bstore
XEnable backing store on \fIkaleid\fR windows.
X.TP
X.B -bw
XSpecify border width in pixels; defaults to 2.
X.TP
X.B -clip
XSpecify clipping rectangles to be used in the \fIkaleid\fR window(s).
XYou can specify one or more clipping rectangles by x, y, width, and
Xheight \fIin floating-point coordinates\fR.  The values specified are
Xscaled to the window size, and can range from 0.0 to 1.0.  So ``-clip
X0,0,1,1'' specifies the entire window, while ``-clip
X0,0,.5,.5,.5,.5,.5,.5'' specifies the upper-left and lower-right
Xquadrants of the window.  Note that \fIkaleid\fR does \fInot\fR check
Xfor reasonable values, nor does it check for violation of X's
Xrequirement that clipping rectangles not overlap.
X.TP
X.B -colors
XSpecify up to 16 colors to use instead of the default palette.  This
Xoption is overridden by the \fB-randomcolors\fR option.  Example of
Xsyntax: ``-colors red,green''.  If a color is specified that does
Xnot exist in the server's rgb database, color allocation will silently
Xfail.
X.TP
X.B -delay
XSpecify a delay (in msec) to be performed between drawing each set of
Xlines \(em can be used to avoid swamping the X11 server.  Defaults to 10
X(100 when \fB-r\fR option, below, is used).
X.TP
X.B -display
XSpecify display on which to run; defaults to contents of DISPLAY
Xenvironment variable.
X.TP
X.B -geometry
XSpecify window geometry; defaults to =300x300+0+0.
X.TP
X.B -icondelay
XSpecify the delay to be used when drawing to the \fIkaleid\fR icon.
XDefaults to 100 msec.
X.TP
X.B -iconic
XCause \fIkaleid\fR to come up in the iconic state.
X.TP
X.B -mono
XForce \fIkaleid\fR to run in monochrome mode (default behavior on
Xa monochrome display).
X.TP
X.B -mult
XRun specified number of \fIkaleid\fR windows.  Each window is a
Xtop-level window with an associated icon.  See the note on WINDOW
XMANAGER INTERACTIONS (below) for details on where the multiple windows
Xget mapped.
X.TP
X.B -qix
XRun a completely different ``Qix''-type drawing algorithm instead of
Xkaleidoscope.
X.TP
X.B -r
XRun \fIkaleid\fR in the root window.  This option causes \fIkaleid\fR to
Xignore all options irrelevant to running in the root window, with one
Xexception: the geometry string is interpreted in a strange and
Xdifferent manner.  The width and height are interpreted as number of
Xhorizontal and vertical sections into which the root window is divided.
XFor example, a geometry specification of =3x2 will result in six
Xkaleidoscope patterns laid out in a 3x2 array in the root window.
X.TP
X.B -randomcolor
XInstead of the standard palette, use a randomly-generated palette that
Xis randomly changed at times during \fIkaleid\fR's execution.  This
Xoption causes kaleid to allocate read/write color cells instead of
Xread-only color cells, and will not work on a display whose default
Xvisual type is StaticColor, StaticGray, or TrueColor.
X.TP
X.B -refresh
XIf an obscured portion a window containing a \fIkaleid\fR display is
Xexposed, refresh the window.  This results in redrawing everything that
Xhas been drawn since the last time the window was cleared.
X.SH NOTE
XSpecifying a delay (icondelay) value of 0 will cause \fIkaleid\fR to
Xdraw into its window (icon) at top speed, bogging down your server and,
Xif \fIkaleid\fR is run remotely, your network.  The default delay value
Xwas chosen to work well on a fast CPU with a fast X server -- it is
Xprobably too low for many systems.
X.PP
XIf \fIkaleid\fR and the server are running on the same CPU, running
X\fIkaleid\fR with a higher nice (nice(1)) value will usually produce
Xgood results without 1) swamping the server, and 2) requiring you to
Ximpose an unpleasantly long delay.
X.SH AUTHORSHIP
XThere have been many different kaleidoscope programs for many different
Xflavors of computers and PCs over the years.  The kaleidoscope algorithm
Xin \fIkaleid\fR was derived from the public-domain kaleidoscope program
Xfor IBM PCs by Judson D. McClendon (Sun Valley Systems, 329 37th Court
XN.E., Birmingham, AL, 35215, CompuServe address [74415,1003]).  X11
X\fIkaleid\fR was written by Nathan Meyers of Hewlett-Packard
X(nathanm@hp-pcd.hp.com).
X.SH WINDOW MANAGER INTERACTIONS
XSome window managers do not appear to cope very well with window icons,
Xresulting in strange icon behavior.  \fIUwm\fR does not suffer from this
Xproblem, although problems can occur when changing window managers (to
Xor from \fIuwm\fR) during execution of \fIkaleid\fR.
X.PP
XOn window managers that support window icons and that specify icon
Xsizing hints, \fIkaleid\fR will respect the icon sizing hints, creating
Xthe largest permissible icon.  Without icon sizing hints, the default
Xicon size is 64x64.
X.PP
X\fIKaleid\fR maps all of its top-level windows to =+0+0 unless
Xoverridden by a geometry string, and all of its icon windows to =+0+0.
XWhere the windows and icons actually \fIend up\fR is a function of how
Xyour window manager handles placement of windows and icons.  \fIUwm\fR,
Xfor example, will request manual window placement for each top-level
Xwindow if a geometry string is not specified, but will leave all icons
Xmapped at =+0+0.  Conversely, with window managers that maintain
Xgalleries or grids of icons, multiple \fIkaleid\fR icons can be
Xspectacular.
END_OF_FILE
if test 6290 -ne `wc -c <'kaleid.1'`; then
    echo shar: \"'kaleid.1'\" unpacked with wrong size!
fi
# end of 'kaleid.1'
fi
if test -f 'kaleid.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'kaleid.c'\"
else
echo shar: Extracting \"'kaleid.c'\" \(32418 characters\)
sed "s/^X//" >'kaleid.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include <X11/X.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <X11/Xos.h>
X#include "kalicon.h"
X#include <signal.h>
X
X/*
X
X  KALEIDOSCOPE (X11 Version)
X
X  By Nathan Meyers, nathanm@hp-pcd.hp.com.
X
X  Based on a kaleidoscope algorithm from a PC-based program by:
X    Judson D. McClendon (Compuserve: [74415,1003])
X
X*/
X
Xchar *progname;
X
Xchar *strchr();
Xchar *calloc();
X
X/* Approximation of CGA/EGA/VGA colors -- (out of standard order) */
Xunsigned long colors[][3] = { { 0x0000, 0x0000, 0x0000 },    /* black */
X			      { 0xffff, 0xffff, 0xffff },    /* bright white */
X			      { 0xaaaa, 0x0000, 0x0000 },    /* red */
X			      { 0x0000, 0xaaaa, 0x0000 },    /* green */
X			      { 0x0000, 0x0000, 0xaaaa },    /* blue */
X			      { 0x0000, 0xaaaa, 0xaaaa },    /* cyan */
X			      { 0xaaaa, 0x0000, 0xaaaa },    /* magenta */
X			      { 0xffff, 0xffff, 0x5555 },    /* yellow */
X			      { 0xaaaa, 0x5555, 0x0000 },    /* brown */
X			      { 0xaaaa, 0xaaaa, 0xaaaa },    /* white  */
X			      { 0x5555, 0x5555, 0x5555 },    /* dark grey */
X			      { 0x5555, 0x5555, 0xffff },    /* light blue */
X			      { 0x5555, 0xffff, 0x5555 },    /* light green */
X			      { 0x5555, 0xffff, 0xffff },    /* light cyan */
X			      { 0xffff, 0x5555, 0x5555 },    /* light red */
X			      { 0xffff, 0x5555, 0xffff } };  /* light magenta */
X
X#define NCOLORS 16
X
Xstatic char *what = "@(#)kaleid.c $Revision: 1.98 $";
X
XDisplay *display;
Xint screen;
XWindow *window;
Xint nwindows=1, nvisible=0;
Xunsigned long palette[NCOLORS];
XGC *window_gcs;
Xint nclips = 0;
XXRectangle *cliplist;
Xstruct fclip {
X  double x, y, width, height;
X} *clips;
X
Xint *visible;
Xint *CX, *CY, *M;
Xint *OX, *OY;
Xint *X1, *Y1, *X2, *Y2, *XV1, *YV1, *XV2, *YV2;
Xint *XA, *YA, *XB, *YB, *XC, *YC, *XD, *YD;
Xint qix = 0;
Xint D[] = { 2, 4, 4, 4, 4, 2, -2, -4, -4, -4, -4, -2, 2, 4, 4, 4, 4, 2 };
Xstruct timeval *schedule;
Xlong *intervals;
Xint *refreshcount, *itercount;
Xunsigned short (*randomseed)[3], (*randombase)[3];
Xint numcolors=NCOLORS;
Xint dynamic_colors=0;
Xlong refresh=0L;
Xlong rndm();
Xint rootx=1, rooty=1;
Xint ww, wh;
Xint doroot = 0;
Xint killed = 0;
Xchar *ucolors = NULL;
X
Xvoid sighandler()
X{
X  killed=1;
X  return;
X}
X
Xvoid refreshrootquit()
X{
X  XClearWindow(display,RootWindow(display,screen));
X  XSync(display,0);
X  exit(0);
X}
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X  unsigned long bgcolor, bdcolor;
X  int bwidth = 2;
X  XSizeHints size_hints;
X  XIconSize icon_size_hints, *icon_size_list;
X  int numsizes, currsize;
X  XWMHints wm_hints;
X  char *displayname = NULL, *background = NULL, *border = NULL;
X  char *geomstring = NULL;
X  XColor screen_in_out, visual_def_return, exact_def_return;
X  XEvent event;
X  int iconic=0, bstore=0;
X  long delayvalue = -1L, icondelay=100L;
X  char *clipcoords = NULL;
X  int monochrome=0;
X  int o_argc = argc;
X  char **o_argv = argv;
X  int i,j;
X  long time();
X  char *basename;
X  long atol();
X
X  progname = argv[0];
X
X  if ((basename=strrchr(progname,'/'))!=NULL) basename++;
X  else basename=progname;
X
X  while (--argc>0) {
X    char *option = (*++argv);
X    if (!strcmp(option,"-delay")) {
X      if (--argc==0) usage();
X      delayvalue = atol(*++argv);
X      if (delayvalue<0L) delayvalue = 0L;
X    }
X    else if (!strcmp(option,"-qix")) {
X      qix=1;
X    }
X    else if (!strcmp(option,"-mono")) {
X      monochrome=1;
X    }
X    else if (!strcmp(option,"-randomcolor")) {
X      dynamic_colors = 1;
X    }
X    else if (!strcmp(option,"-display")) {
X      if (--argc==0) usage();
X      displayname = (*++argv);
X    }
X    else if (strchr(option,':')) {
X      displayname = option;
X    }
X    else if (!strcmp(option,"-bg")) {
X      if (--argc==0) usage();
X      background = (*++argv);
X    }
X    else if (!strcmp(option,"-bd")) {
X      if (--argc==0) usage();
X      border = (*++argv);
X    }
X    else if (!strcmp(option,"-bstore")) {
X      bstore = 1;
X    }
X    else if (!strcmp(option,"-bw")) {
X      if (--argc==0) usage();
X      bwidth = atoi(*++argv);
X      if (bwidth<0) bwidth = 0;
X    }
X    else if (!strcmp(option,"-colors")) {
X      if (--argc==0) usage();
X      ucolors = (*++argv);
X    }
X    else if (!strcmp(option,"-clip")) {
X      if (--argc==0) usage();
X      clipcoords = (*++argv);
X    }
X    else if (!strcmp(option,"-icondelay")) {
X      if (--argc==0) usage();
X      icondelay = atol(*++argv);
X      if (icondelay<0L) icondelay = 0L;
X    }
X    else if (!strcmp(option,"-iconic")) {
X      iconic = 1;
X    }
X    else if (!strcmp(option,"-geometry")) {
X      if (--argc==0) usage();
X      geomstring = (*++argv);
X    }
X    else if (*option=='=') {
X      geomstring = option;
X    }
X    else if (!strcmp(option,"-mult")) {
X      if (--argc==0) usage();
X      nwindows = atoi(*++argv);
X      if (nwindows<1) nwindows = 1;
X    }
X    else if (!strcmp(option,"-r")) {
X      doroot = 1;
X    }
X    else if (!strcmp(option,"-refresh")) {
X      refresh = ExposureMask;
X    }
X    else if (!strcmp(option,"-root")) {
X      doroot = 1;
X    }
X    else usage();
X  }
X
Xif (monochrome) dynamic_colors = 0;
X
X  if (delayvalue == -1L) delayvalue = doroot ? 100L : 10L;
X
X  display = XOpenDisplay(displayname);
X  if (display==NULL) {
X    (void)fprintf(stderr,
X	          (displayname==NULL) ?
X	          "%s: Failed to open display.\n" :
X	          "%s: Failed to open display %s.\n",
X	          progname,displayname);
X    exit(1);
X  }
X  screen = DefaultScreen(display);
X
X  srand48(time((long *)NULL));
X
X  if (background == NULL ||
X      XAllocNamedColor(display,
X		       DefaultColormap(display,screen),
X		       background,
X		       &visual_def_return,
X		       &exact_def_return)==False)
X    bgcolor = BlackPixel(display,screen);
X  else bgcolor = exact_def_return.pixel;
X
X  if (border==NULL ||
X      XAllocNamedColor(display,
X		       DefaultColormap(display,screen),
X		       border,
X		       &visual_def_return,
X		       &exact_def_return)==False)
X   bdcolor = WhitePixel(display,screen);
X  else bdcolor = exact_def_return.pixel;
X
X  if (clipcoords != NULL) {
X    char *temp = clipcoords;
X    char *calloc();
X    double strtod();
X    int commacount = 0;
X    int len;
X    while (*temp != '\0') commacount += (*(temp++) == ',') ? 1 : 0;
X    if ((commacount & 0x3) != 3) usage();
X    nclips = (commacount >> 2) + 1;
X    clips = (struct fclip *)calloc(nclips, sizeof(struct fclip));
X    cliplist = (XRectangle *)calloc(nclips, sizeof(XRectangle));
X    if (clips == NULL || cliplist == NULL) {
X      fprintf(stderr,"%s: calloc() failed\n",progname);
X      exit(1);
X    }
X    for (i=0; i<nclips; i++) {
X      clips[i].x = strtod(clipcoords, &temp);
X      if (temp == clipcoords) usage();
X      clipcoords = strchr(temp, ',') + 1;
X      clips[i].y = strtod(clipcoords, &temp);
X      if (temp == clipcoords) usage();
X      clipcoords = strchr(temp, ',') + 1;
X      clips[i].width = strtod(clipcoords, &temp);
X      if (temp == clipcoords) usage();
X      clipcoords = strchr(temp, ',') + 1;
X      clips[i].height = strtod(clipcoords, &temp);
X      if (temp == clipcoords) usage();
X      clipcoords = strchr(temp, ',') + 1;
X    }
X  }
X
X  if (!monochrome && DisplayCells(display,screen) > 2) {
X    if (dynamic_colors) {
X      for (numcolors=NCOLORS; numcolors>=2; numcolors--) {
X	if (XAllocColorCells(display,DefaultColormap(display,screen),
X			     0, (unsigned long *)NULL, 0,
X			     palette, (unsigned int)numcolors) == True) {
X	  randomize_colors();
X	  break;
X	}
X      }
X      if (numcolors < 2) fatalerror("Cannot allocate R/W color cells",NULL);
X    }
X    else if (ucolors != NULL) {
X      int thiscolor;
X      numcolors = 0;
X      for (thiscolor=0; thiscolor<NCOLORS; thiscolor++) {
X	char *comma=strchr(ucolors,',');
X
X	if (comma != NULL) *comma='\0';
X	if (XAllocNamedColor(display,
X		             DefaultColormap(display,screen),
X		             ucolors,
X		             &visual_def_return,
X		             &exact_def_return) == True)
X          palette[numcolors++] = exact_def_return.pixel;
X	if (comma == NULL) break;
X	ucolors = comma + 1;
X      }
X      if (numcolors < 1) fatalerror("Cannot allocate colors",NULL);
X    }
X    else {
X      int thiscolor;
X      numcolors = 0;
X      for (thiscolor=0; thiscolor<NCOLORS; thiscolor++) {
X        screen_in_out.flags = DoRed | DoGreen | DoBlue;
X        screen_in_out.red = colors[thiscolor][0];
X        screen_in_out.green = colors[thiscolor][1];
X        screen_in_out.blue = colors[thiscolor][2];
X        if (XAllocColor(display, DefaultColormap(display,screen),
X		        &screen_in_out)==True)
X          palette[numcolors++] = screen_in_out.pixel;
X      }
X      if (numcolors < 2) fatalerror("Cannot allocate colors",NULL);
X    }
X  }
X  else {
X    numcolors=2;
X    palette[0] = WhitePixel(display,screen);
X    palette[1] = BlackPixel(display,screen);
X  }
X
X  size_hints.x = 0;
X  size_hints.y = 0;
X  size_hints.width = 300;
X  size_hints.height = 300;
X
X  size_hints.flags = PPosition | PSize;
X  if (geomstring!=NULL) {
X    int result;
X    result = XParseGeometry(geomstring,&size_hints.x,&size_hints.y,
X		            &size_hints.width,&size_hints.height);
X    if (result & XNegative)
X      size_hints.x += DisplayWidth(display,screen)
X		    - size_hints.width
X		    - bwidth*2;
X    if (result & YNegative)
X      size_hints.y += DisplayHeight(display,screen)
X		    - size_hints.height
X		    - bwidth*2;
X    if (result & XValue || result & YValue) {
X      size_hints.flags |= USPosition;
X      size_hints.flags &= ~PPosition;
X    }
X    if (result & WidthValue || result & HeightValue) {
X      size_hints.flags |= USSize;
X      size_hints.flags &= ~PSize;
X    }
X    if (result & WidthValue && !(rootx = size_hints.width)) rootx = 1;
X    if (result & HeightValue && !(rooty = size_hints.height)) rooty = 1;
X  }
X
X  if (doroot) {
X    nwindows=rootx*rooty;
X    if (!allocate_arrays(nwindows)) {
X      (void)fprintf(stderr,"%s: malloc() failure\n",progname);
X      exit(1);
X    }
X    for (i=0; i<nwindows; i++) {
X      intervals[i] = delayvalue;
X      window[i] = RootWindow(display,screen);
X      visible[i]=1;
X    }
X    nvisible=nwindows;
X    XSelectInput(display,window[0],refresh);
X  }
X  else {
X    Pixmap bitmapicon;
X
X    if (!allocate_arrays((unsigned)(2*nwindows))) {
X      (void)fprintf(stderr,"%s: malloc() failure\n",progname);
X      exit(1);
X    }
X
X    for (i=0; i<nwindows; i++)
X      window[i] = XCreateSimpleWindow(display,RootWindow(display,screen),
X				        size_hints.x,size_hints.y,
X				        size_hints.width,size_hints.height,
X				        bwidth,bdcolor,bgcolor);
X
X    icon_size_hints.max_width=64;
X    icon_size_hints.max_height=64;
X    currsize=0;
X    if (XGetIconSizes(display,RootWindow(display,screen),
X		      &icon_size_list,&numsizes)) {
X      for (i=1; i<numsizes; i++) {	/* Look for largest icon size */
X	if (icon_size_list[i].max_width >= icon_size_list[currsize].max_width &&
X	    icon_size_list[i].max_height >= icon_size_list[currsize].max_height)
X	  currsize=i;
X      }
X      if (icon_size_list[currsize].max_width <= 0 ||
X	  icon_size_list[currsize].max_height <= 0 ) {
X	XFree(icon_size_list);
X        icon_size_list = &icon_size_hints;
X      }
X    }
X    else
X      icon_size_list = &icon_size_hints;
X
X    for (i=0; i<nwindows; i++) {
X      window[i+nwindows] = XCreateSimpleWindow(display,
X					  RootWindow(display,screen), 0,0,
X				          icon_size_list[currsize].max_width,
X				          icon_size_list[currsize].max_height,
X				          2,BlackPixel(display,screen),
X				          WhitePixel(display,screen));
X
X      if (qix) {
X        CX[i+nwindows] = icon_size_list[currsize].max_width;
X        CY[i+nwindows] = icon_size_list[currsize].max_height;
X      }
X      else {
X        CX[i+nwindows] = icon_size_list[currsize].max_width >> 1;
X        CY[i+nwindows] = icon_size_list[currsize].max_height >> 1;
X        M[i+nwindows] = (CX[i+nwindows]>CY[i+nwindows]) ?
X			   CX[i+nwindows] :
X			   CY[i+nwindows];
X        M[i+nwindows] = M[i+nwindows] ? M[i+nwindows] : 1;
X      }
X    }
X
X    if (bstore) {
X      XSetWindowAttributes attributes;
X      attributes.backing_store = WhenMapped;
X      for (i=0; i<2*nwindows; i++) {
X	XChangeWindowAttributes(display,window[i],CWBackingStore,&attributes);
X      }
X    }
X
X    for (i=0; i<nwindows; i++)
X      XSetStandardProperties(display,window[i],"Kaleidoscope",basename,
X			     None,o_argv,o_argc,&size_hints);
X
X    /* Create bitmap icon for wm's that don't support window icons */
X    bitmapicon=XCreateBitmapFromData(display,RootWindow(display,screen),
X				     icon_bits, icon_width, icon_height);
X
X    /* Use window icon for window managers that support one */
X    wm_hints.icon_pixmap = bitmapicon;
X    wm_hints.flags = IconPixmapHint | IconWindowHint;
X
X    if (iconic) {
X      wm_hints.initial_state = IconicState;
X      wm_hints.flags |= StateHint;
X    }
X
X    for (i=0; i<nwindows; i++) {
X      wm_hints.icon_window = window[i+nwindows];
X      XSetWMHints(display,window[i],&wm_hints);
X      XSelectInput(display,window[i],
X	StructureNotifyMask|VisibilityChangeMask|refresh);
X      XSelectInput(display,window[i+nwindows],
X	StructureNotifyMask|VisibilityChangeMask|refresh);
X      XMapWindow(display,window[i]);
X
X      intervals[i] = delayvalue;
X      intervals[i+nwindows] = icondelay;
X
X      if (qix) {
X        CX[i] = size_hints.width;
X        CY[i] = size_hints.height;
X      }
X      else {
X        CX[i] = size_hints.width/2;
X        CY[i] = size_hints.height/2;
X        M[i] = (CX[i]>CY[i]) ? CX[i] : CY[i];
X        M[i] = M[i] ? M[i] : 1;
X      }
X    }
X
X  }
X
X  for (i = 0; i<(doroot ? nwindows : nwindows << 1 ); i++)
X    window_gcs[i] = XCreateGC(display,window[i],0,(XGCValues *)NULL);
X
X  if (doroot) {
X    int dontcare, winno;
X    Window wdontcare;
X    struct sigvec vec;
X    XGetGeometry(display,RootWindow(display,screen),&wdontcare,&dontcare,
X                 &dontcare, &ww, &wh, &dontcare, &dontcare);
X    for (winno=0; winno<nwindows; winno++) {
X      i = winno % rootx;
X      j = winno / rootx;
X      CX[winno] = ww/rootx;
X      CY[winno] = wh/rooty;
X      OX[winno] = i * CX[winno];
X      OY[winno] = j * CY[winno];
X      if (!qix) {
X        CX[winno] >>= 1;
X        CY[winno] >>= 1;
X        M[winno] = (CX[winno]>CY[winno]) ? CX[winno] : CY[winno];
X        M[winno] = M[winno] ? M[winno] : 1;
X      }
X      if (nclips) {
X	int k;
X	double frootx = (double)rootx, frooty = (double)rooty;
X	double fww = (double)ww, fwh = (double)wh;
X	for (k=0; k<nclips; k++) {
X	  cliplist[k].x = (int)(fww * clips[k].x / frootx + .5);
X	  cliplist[k].y = (int)(fwh * clips[k].y / frooty + .5);
X	  cliplist[k].width = (int)(fww * clips[k].width / frootx + .5);
X	  cliplist[k].height = (int)(fwh * clips[k].height / frooty + .5);
X	}
X        XSetClipRectangles(display, window_gcs[winno], OX[winno], OY[winno],
X			   cliplist, nclips, Unsorted);
X      }
X    }
X    for (i=0; i<nwindows; i++) {
X      refreshcount[i]=0;
X      itercount[i]=0;
X      randombase[i][0]=randomseed[i][0];
X      randombase[i][1]=randomseed[i][1];
X      randombase[i][2]=randomseed[i][2];
X      randomize_state_vars(i);
X    }
X    vec.sv_handler = sighandler;
X    vec.sv_mask = 0x0;
X    vec.sv_flags = 0;
X    (void)sigvec(SIGINT, &vec, (struct sigvec *)NULL);
X    (void)sigvec(SIGQUIT, &vec, (struct sigvec *)NULL);
X    (void)sigvec(SIGTERM, &vec, (struct sigvec *)NULL);
X  }
X  else {
X    for (i=0; i<nclips; i++) {
X      cliplist[i].x = (int)((double)size_hints.width * clips[i].x + .5);
X      cliplist[i].y = (int)((double)size_hints.height * clips[i].y + .5);
X      cliplist[i].width = (int)((double)size_hints.width * clips[i].width + .5);
X      cliplist[i].height = (int)((double)size_hints.height * clips[i].height +
X				 .5);
X    }
X    if (nclips) for (i=0; i<nwindows; i++)
X      XSetClipRectangles(display, window_gcs[i], 0, 0,
X			 cliplist, nclips, Unsorted);
X    for (i=0; i<nclips; i++) {
X      cliplist[i].x = (int)((double)icon_size_list[currsize].max_width *
X			    clips[i].x + .5);
X      cliplist[i].y = (int)((double)icon_size_list[currsize].max_height *
X			    clips[i].y + .5);
X      cliplist[i].width = (int)((double)icon_size_list[currsize].max_width *
X			        clips[i].width + .5);
X      cliplist[i].height = (int)((double)icon_size_list[currsize].max_height *
X				 clips[i].height + .5);
X    }
X    if (nclips) for (i=0; i<nwindows; i++)
X      XSetClipRectangles(display, window_gcs[i+nwindows], 0, 0,
X			 cliplist, nclips, Unsorted);
X    nwindows <<= 1;
X    if (icon_size_list != &icon_size_hints) XFree(icon_size_list);
X  }
X
X
X  for (;;) {
X    int winno;
X    for (winno=0; winno<nwindows; winno++) if (visible[winno]) break;
X    while (nvisible) {
X      if (qix) {
X        XDrawLine(display,window[winno], window_gcs[winno],
X                  X1[winno]+OX[winno], Y1[winno]+OY[winno],
X		  X2[winno]+OX[winno], Y2[winno]+OY[winno]);
X        if (!rndm(25L,winno)) {
X	  XGCValues values;
X	  values.foreground = palette[rndm((long)numcolors,winno)];
X	  XChangeGC(display, window_gcs[winno], GCForeground, &values);
X	}
X	if (X1[winno] < 3) XV1[winno] = rndm(6L,winno);
X	if (Y1[winno] > CY[winno]-4) XV1[winno] = rndm(6L,winno)+3;
X	if (X1[winno] > CX[winno]-4) XV1[winno] = rndm(6L,winno)+6;
X	if (Y1[winno] < 3) XV1[winno] = rndm(6L,winno)+9;
X	if (X2[winno] < 3) XV2[winno] = rndm(6L,winno);
X	if (Y2[winno] > CY[winno]-4) XV2[winno] = rndm(6L,winno)+3;
X	if (X2[winno] > CX[winno]-4) XV2[winno] = rndm(6L,winno)+6;
X	if (Y2[winno] < 3) XV2[winno] = rndm(6L,winno)+9;
X	X1[winno] += D[XV1[winno]];
X	Y1[winno] += D[XV1[winno]+3];
X	X2[winno] += D[XV2[winno]];
X	Y2[winno] += D[XV2[winno]+3];
X      }
X      else {
X	XSegment segs[8];
X        if (!rndm(50L,winno)) {
X          X1[winno] = rndm((long)M[winno],winno) + 1;
X          X2[winno] = rndm((long)M[winno],winno) + 1;
X          Y1[winno] = rndm((long)X1[winno],winno);
X          Y2[winno] = rndm((long)X2[winno],winno);
X        }
X        if (!rndm(10L,winno)) {
X	  XGCValues values;
X          XV1[winno] = rndm(7L,winno)-3;
X          XV2[winno] = rndm(7L,winno)-3;
X          YV1[winno] = rndm(7L,winno)-3;
X          YV2[winno] = rndm(7L,winno)-3;
X	  values.foreground = palette[rndm((long)numcolors,winno)];
X	  XChangeGC(display, window_gcs[winno], GCForeground, &values);
X        }
X        if (CX[winno]<CY[winno]) {
X          XA[winno] = (long)X1[winno]*(long)CX[winno]/(long)CY[winno];
X          YA[winno] = (long)Y1[winno]*(long)CX[winno]/(long)CY[winno];
X          XB[winno] = X1[winno];
X          YB[winno] = Y1[winno];
X          XC[winno] = (long)X2[winno]*(long)CX[winno]/(long)CY[winno];
X          YC[winno] = (long)Y2[winno]*(long)CX[winno]/(long)CY[winno];
X          XD[winno] = X2[winno];
X          YD[winno] = Y2[winno];
X        }
X        else {
X          XA[winno] = X1[winno];
X          YA[winno] = Y1[winno];
X          XB[winno] = (long)X1[winno]*(long)CY[winno]/(long)CX[winno];
X          YB[winno] = (long)Y1[winno]*(long)CY[winno]/(long)CX[winno];
X          XC[winno] = X2[winno];
X          YC[winno] = Y2[winno];
X          XD[winno] = (long)X2[winno]*(long)CY[winno]/(long)CX[winno];
X          YD[winno] = (long)Y2[winno]*(long)CY[winno]/(long)CX[winno];
X        }
X        segs[0].x1 = CX[winno]+XA[winno]+OX[winno];
X        segs[0].y1 = CY[winno]-YB[winno]+OY[winno];
X        segs[0].x2 = CX[winno]+XC[winno]+OX[winno];
X        segs[0].y2 = CY[winno]-YD[winno]+OY[winno];
X        segs[1].x1 = CX[winno]-YA[winno]+OX[winno];
X        segs[1].y1 = CY[winno]+XB[winno]+OY[winno];
X        segs[1].x2 = CX[winno]-YC[winno]+OX[winno];
X        segs[1].y2 = CY[winno]+XD[winno]+OY[winno];
X        segs[2].x1 = CX[winno]-XA[winno]+OX[winno];
X        segs[2].y1 = CY[winno]-YB[winno]+OY[winno];
X        segs[2].x2 = CX[winno]-XC[winno]+OX[winno];
X        segs[2].y2 = CY[winno]-YD[winno]+OY[winno];
X        segs[3].x1 = CX[winno]-YA[winno]+OX[winno];
X        segs[3].y1 = CY[winno]-XB[winno]+OY[winno];
X        segs[3].x2 = CX[winno]-YC[winno]+OX[winno];
X        segs[3].y2 = CY[winno]-XD[winno]+OY[winno];
X        segs[4].x1 = CX[winno]-XA[winno]+OX[winno];
X        segs[4].y1 = CY[winno]+YB[winno]+OY[winno];
X        segs[4].x2 = CX[winno]-XC[winno]+OX[winno];
X        segs[4].y2 = CY[winno]+YD[winno]+OY[winno];
X        segs[5].x1 = CX[winno]+YA[winno]+OX[winno];
X        segs[5].y1 = CY[winno]-XB[winno]+OY[winno];
X        segs[5].x2 = CX[winno]+YC[winno]+OX[winno];
X        segs[5].y2 = CY[winno]-XD[winno]+OY[winno];
X        segs[6].x1 = CX[winno]+XA[winno]+OX[winno];
X        segs[6].y1 = CY[winno]+YB[winno]+OY[winno];
X        segs[6].x2 = CX[winno]+XC[winno]+OX[winno];
X        segs[6].y2 = CY[winno]+YD[winno]+OY[winno];
X        segs[7].x1 = CX[winno]+YA[winno]+OX[winno];
X        segs[7].y1 = CY[winno]+XB[winno]+OY[winno];
X        segs[7].x2 = CX[winno]+YC[winno]+OX[winno];
X        segs[7].y2 = CY[winno]+XD[winno]+OY[winno];
X        XDrawSegments(display,window[winno],window_gcs[winno],
X		      segs, 8);
X        X1[winno]= (X1[winno] + XV1[winno]) % M[winno];
X        Y1[winno]= (Y1[winno] + YV1[winno]) % M[winno];
X        X2[winno]= (X2[winno] + XV2[winno]) % M[winno];
X        Y2[winno]= (Y2[winno] + YV2[winno]) % M[winno];
X      }
X      if (!refreshcount[winno] && intervals[winno])
X        XFlush(display);
X      itercount[winno]++;
X      if (!rndm(500L,winno)) {
X	if (doroot) {
X	  int x,y,w,h;
X	  i = winno % rootx;
X	  j = winno / rootx;
X	  w = ww / rootx;
X	  h = wh / rooty;
X	  x = i * w;
X	  y = j * h;
X	  if (i == rootx-1) w=0;
X	  if (j == rooty-1) h=0;
X	  XClearArea(display,window[winno],x,y,w,h,False);
X	}
X	else XClearWindow(display,window[winno]);
X  	refreshcount[winno]=0;
X  	itercount[winno]=0;
X  	randombase[winno][0]=randomseed[winno][0];
X  	randombase[winno][1]=randomseed[winno][1];
X  	randombase[winno][2]=randomseed[winno][2];
X	randomize_state_vars(winno);
X      }
X      winno=scheduler();
X      if (!refreshcount[winno] && dynamic_colors &&
X          !rndm((long)(800/numcolors),-1)) randomize_color();
X      if (XCheckMaskEvent(display,~0L,&event)==True) handle_event(&event);
X    }
X    XNextEvent(display,&event);
X    handle_event(&event);
X  }
X}
X
Xrandomize_color()
X{
X  XColor color;
X  color.pixel = palette[rndm((long)numcolors,-1)];
X  color.red = rndm(65535L,-1);
X  color.green = rndm(65535L,-1);
X  color.blue = rndm(65535L,-1);
X  color.flags = DoRed|DoGreen|DoBlue;
X  XStoreColor(display, DefaultColormap(display,screen), &color);
X}
X
Xrandomize_colors()
X{
X  int i;
X  XColor color[NCOLORS];
X  for (i=0; i<numcolors; i++) {
X    color[i].pixel = palette[i];
X    color[i].red = rndm(65535L,-1);
X    color[i].green = rndm(65535L,-1);
X    color[i].blue = rndm(65535L,-1);
X    color[i].flags = DoRed|DoGreen|DoBlue;
X  }
X  XStoreColors(display, DefaultColormap(display,screen), color, numcolors);
X}
X
Xhandle_event(event)
XXEvent *event;
X{
X  int i;
X  if (event->type==ConfigureNotify) {
X    for (i=0; i<nwindows; i++) {
X      if (event->xconfigure.window==window[i]) {
X	int dorandom=0;
X	if (qix) {
X          if (CX[i] != event->xconfigure.width ||
X              CY[i] != event->xconfigure.height) {
X	    XClearWindow(display,event->xconfigure.window);
X  	    refreshcount[i]=0;
X  	    itercount[i]=0;
X  	    randombase[i][0]=randomseed[i][0];
X  	    randombase[i][1]=randomseed[i][1];
X  	    randombase[i][2]=randomseed[i][2];
X	    dorandom=1;
X	  }
X          CX[i] = event->xconfigure.width;
X          CY[i] = event->xconfigure.height;
X	}
X	else {
X	  int dorandom=0;
X          if (CX[i] != event->xconfigure.width/2 ||
X              CY[i] != event->xconfigure.height/2) {
X	    XClearWindow(display,event->xconfigure.window);
X  	    refreshcount[i]=0;
X  	    itercount[i]=0;
X  	    randombase[i][0]=randomseed[i][0];
X  	    randombase[i][1]=randomseed[i][1];
X  	    randombase[i][2]=randomseed[i][2];
X	    dorandom=1;
X	  }
X          CX[i] = event->xconfigure.width/2;
X          CY[i] = event->xconfigure.height/2;
X          M[i] = (CX[i]>CY[i]) ? CX[i] : CY[i];
X          M[i] = M[i] ? M[i] : 1;
X	}
X	if (dorandom) randomize_state_vars(i);
X	if (nclips) {
X	  int j;
X          for (j=0; j<nclips; j++) {
X            cliplist[j].x = (int)((double)event->xconfigure.width *
X				  clips[j].x + .5);
X            cliplist[j].y = (int)((double)event->xconfigure.height *
X				  clips[j].y + .5);
X            cliplist[j].width = (int)((double)event->xconfigure.width *
X				      clips[j].width + .5);
X            cliplist[j].height = (int)((double)event->xconfigure.height *
X				       clips[j].height + .5);
X          }
X          XSetClipRectangles(display, window_gcs[i], 0, 0,
X			     cliplist, nclips, Unsorted);
X	}
X        break;
X      }
X    }
X  }
X  else if (event->type==MapNotify) {
X    for (i=0; i<nwindows; i++) {
X      if (event->xmap.window==window[i]) {
X        refreshcount[i]=0;
X        itercount[i]=0;
X        randombase[i][0]=randomseed[i][0];
X        randombase[i][1]=randomseed[i][1];
X        randombase[i][2]=randomseed[i][2];
X	randomize_state_vars(i);
X        break;
X      }
X    }
X  }
X  else if (event->type==Expose) {
X    for (i=0; i<nwindows; i++) {
X      if (doroot) {
X	int x,y,w,h,ix,iy;
X	ix = i % rootx;
X	iy = i / rootx;
X	w = ww / rootx;
X	h = wh / rooty;
X	x = ix * w;
X	y = iy * h;
X	if (ix != rootx-1 && event->xexpose.x >= x+w ||
X	    event->xexpose.x + event->xexpose.width < x ||
X	    iy != rooty-1 && event->xexpose.y >= y+h ||
X	    event->xexpose.y + event->xexpose.height < y)
X	      continue;
X      }
X      if (event->xexpose.window==window[i]) {
X	refreshcount[i] += itercount[i];
X	itercount[i] = 0;
X	randomseed[i][0] = randombase[i][0];
X	randomseed[i][1] = randombase[i][1];
X	randomseed[i][2] = randombase[i][2];
X	randomize_state_vars(i);
X        if (!doroot) break;
X      }
X    }
X  }
X  else if (event->type==VisibilityNotify) {
X    for (i=0; i<nwindows; i++) {
X      if (event->xvisibility.window==window[i]) {
X	if (visible[i] &&
X	    event->xvisibility.state == VisibilityFullyObscured) {
X          visible[i]=0;
X          nvisible--;
X	}
X	else if (!visible[i] &&
X		 event->xvisibility.state != VisibilityFullyObscured) {
X          visible[i]=1;
X          nvisible++;
X	}
X        break;
X      }
X    }
X  }
X}
X
Xrandomize_state_vars(i)
Xint i;
X{
X  XGCValues values;
X  if (qix) {
X    X1[i] = (CX[i]>10) ? rndm((long)(CX[i]-10),i)+5 : 5;
X    X2[i] = (CX[i]>10) ? rndm((long)(CX[i]-10),i)+5 : 5;
X    Y1[i] = (CY[i]>10) ? rndm((long)(CY[i]-10),i)+5 : 5;
X    Y2[i] = (CY[i]>10) ? rndm((long)(CY[i]-10),i)+5 : 5;
X    XV1[i] = rndm(12L,i)+1;
X    XV2[i] = rndm(12L,i)+1;
X    values.foreground = palette[rndm((long)numcolors,i)];
X    XChangeGC(display, window_gcs[i], GCForeground, &values);
X  }
X  else {
X    X1[i] = rndm((long)M[i],i) + 1;
X    X2[i] = rndm((long)M[i],i) + 1;
X    Y1[i] = rndm((long)X1[i],i);
X    Y2[i] = rndm((long)X2[i],i);
X    XV1[i] = rndm(7L,i)-3;
X    XV2[i] = rndm(7L,i)-3;
X    YV1[i] = rndm(7L,i)-3;
X    YV2[i] = rndm(7L,i)-3;
X    values.foreground = palette[rndm((long)numcolors,i)];
X    XChangeGC(display, window_gcs[i], GCForeground, &values);
X  }
X}
X
Xusage()
X{
X  int i,j,spaces,xloc;
X  static char *options[] = {
X    "[-bd <border>]",
X    "[-bg <background>]",
X    "[-bstore]",
X    "[-bw <borderwidth>]",
X    "[-clip x,y,w,h[,x,y,w,h[,x,y,w,h]]]",
X    "[-colors <color1>[,<color2>[,...]]]",
X    "[-delay <msec>]",
X    "[-display <displayname>]",
X    "[-geometry <geometry>]",
X    "[-icondelay <msec>]",
X    "[-iconic]",
X    "[-mono]",
X    "[-mult <number>]",
X    "[-qix]",
X    "[-r]",
X    "[-randomcolor]",
X    "[-refresh]"
X  };
X  (void)fprintf(stderr,"Usage: %s", progname);
X  spaces=strlen(progname)+7;
X  xloc=spaces;
X
X  for (j=0; j<(sizeof(options)/sizeof(char *)); j++) {
X    if (xloc+strlen(options[j]) > 78) {
X      putc('\n',stderr);
X      for (i = 0; i<spaces; i++) (void)putc(' ',stderr);
X      xloc=spaces;
X    }
X    xloc += strlen(options[j])+1;
X    fprintf(stderr," %s",options[j]);
X  }
X  putc('\n',stderr);
X
X  exit(1);
X}
X
Xfatalerror(s1,s2)
Xchar *s1,*s2;
X{
X  (void)fprintf(stderr,"%s: ",progname);
X  (void)fprintf(stderr,s1,s2);
X  (void)putc('\n',stderr);
X  exit(1);
X}
X
Xlong rndm(maxval,element)
Xlong maxval;
Xint element;
X{
X  long lrand48();
X  int sr1=15, sr2=16;
X  long mv=maxval;
X  while (mv > 0x8000L) {
X    sr1++;
X    sr2--;
X    mv >>= 1;
X  }
X  if (element == -1) return ((lrand48() >> sr1) * maxval) >> sr2;
X  return ((nrand48(randomseed[element]) >> sr1) * maxval) >> sr2;
X}
X
Xallocate_arrays(nwin)
Xunsigned nwin;
X{
X  int i;
X  if ((window=(Window *)calloc(nwin,sizeof(Window))) == NULL) return 0;
X  if ((window_gcs=(GC *)calloc(nwin,sizeof(GC))) == NULL) return 0;
X  if ((CX=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((CY=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((OX=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((OY=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((visible=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((X1=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((Y1=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((X2=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((Y2=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((XV1=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((XV2=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((schedule=(struct timeval *)calloc(nwin,sizeof(struct timeval))) == NULL)
X    return 0;
X  if ((intervals=(long *)calloc(nwin,sizeof(long))) == NULL) return 0;
X  if ((randomseed=(unsigned short **)calloc(nwin,3*sizeof(short))) == NULL)
X    return 0;
X  if ((randombase=(unsigned short **)calloc(nwin,3*sizeof(short))) == NULL)
X    return 0;
X  for (i=0; i<nwin; i++) {
X    randombase[i][0] = randomseed[i][0] = (unsigned short)rndm(0xffffL,-1);
X    randombase[i][1] = randomseed[i][1] = (unsigned short)rndm(0xffffL,-1);
X    randombase[i][2] = randomseed[i][2] = (unsigned short)rndm(0xffffL,-1);
X  }
X  if ((refreshcount=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((itercount=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if (qix) return 1;
X  if ((M=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((YV1=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((YV2=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((XA=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((YA=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((XB=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((YB=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((XC=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((YC=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((XD=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  if ((YD=(int *)calloc(nwin,sizeof(int))) == NULL) return 0;
X  return 1;
X}
X
Xint scheduler()
X{
X  struct timeval currtime, *nextalarm, *alarmindex;
X  struct timezone tzp;
X  long interval;
X  int i;
X
X  /* Has root-mode operation gotten a die signal? */
X  if (killed) refreshrootquit();
X
X  /* Look for any windows performing refresh... immediate return if found */
X  for (i=0; i<nwindows; i++) if (refreshcount[i] && visible[i]) {
X    refreshcount[i]--;
X    return i;
X  }
X
X  /* Get current time */
X  (void)gettimeofday(&currtime, &tzp);
X
X  /* Find earliest alarm due */
X  alarmindex = nextalarm = schedule;
X  for (i=1; i<nwindows; i++) {
X    if (visible[++alarmindex - schedule] &&
X	( alarmindex->tv_sec < nextalarm->tv_sec ||
X          alarmindex->tv_sec == nextalarm->tv_sec &&
X          alarmindex->tv_usec < nextalarm->tv_usec ))
X      nextalarm = alarmindex;
X  }
X
X  /* If the next alarm is not past due, sleep until it comes due */
X  if (currtime.tv_sec < nextalarm->tv_sec ||
X      currtime.tv_sec == nextalarm->tv_sec &&
X      currtime.tv_usec < nextalarm->tv_usec) {
X    struct timeval timeout;
X    int fd=ConnectionNumber(display), readfds;
X
X    timeout.tv_sec = nextalarm->tv_sec - currtime.tv_sec;
X    timeout.tv_usec = nextalarm->tv_usec - currtime.tv_usec;
X    if (timeout.tv_usec < 0) {
X      timeout.tv_sec -= 1L;
X      timeout.tv_usec += 1000000L;
X    }
X
X    readfds = 1<<fd;
X    if (killed) refreshrootquit();
X    (void)select(fd+1, &readfds, NULL, NULL, &timeout);
X
X    /* Recompute current time */
X    (void)gettimeofday(&currtime, &tzp);
X
X  }
X
X  /* Set next alarm to current time + interval.  If more than one window
X     is visible, introduce a random variance so update is staggered.  */
X  interval = intervals[nextalarm-schedule];
X  if (nvisible > 1) interval += rndm(interval/5L,-1) - interval/10L;
X  nextalarm->tv_sec = currtime.tv_sec + interval/1000;
X  nextalarm->tv_usec = currtime.tv_usec + (interval%1000)*1000;
X  if (nextalarm->tv_usec >= 1000000) {
X    nextalarm->tv_sec += 1;
X    nextalarm->tv_usec -= 1000000;
X  }
X
X  /* Return index of next alarm */
X  return nextalarm-schedule;
X}
END_OF_FILE
if test 32418 -ne `wc -c <'kaleid.c'`; then
    echo shar: \"'kaleid.c'\" unpacked with wrong size!
fi
# end of 'kaleid.c'
fi
if test -f 'kalicon.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'kalicon.h'\"
else
echo shar: Extracting \"'kalicon.h'\" \(3360 characters\)
sed "s/^X//" >'kalicon.h' <<'END_OF_FILE'
X/* Kaleidoscope icon -- for window managers that do not support window
X   icons. */
X
X#define icon_width 64
X#define icon_height 64
Xstatic char icon_bits[] = {
X   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
X   0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff,
X   0xff, 0xf3, 0xff, 0xbb, 0xbb, 0xff, 0x9f, 0xff, 0xff, 0xcf, 0xff, 0x77,
X   0xdd, 0xff, 0xe7, 0xff, 0xff, 0x33, 0xff, 0x6f, 0xed, 0xff, 0x99, 0xff,
X   0xff, 0xcf, 0xfc, 0xeb, 0xae, 0x7f, 0xe6, 0xff, 0xff, 0x3f, 0xf3, 0x57,
X   0xd4, 0x9f, 0xf9, 0xff, 0xff, 0xcf, 0xc8, 0x37, 0xd9, 0x27, 0xe6, 0xff,
X   0xfb, 0x3f, 0x27, 0x2b, 0xa9, 0xc9, 0xf9, 0xbf, 0xd7, 0xff, 0x9c, 0x94,
X   0x52, 0x72, 0xfe, 0xd7, 0xd7, 0xbf, 0x73, 0x90, 0x12, 0x9c, 0xf9, 0xd7,
X   0xaf, 0x7e, 0xce, 0x03, 0x81, 0x67, 0xfe, 0xea, 0xaf, 0xfe, 0x39, 0x07,
X   0x81, 0x99, 0xff, 0xea, 0x5f, 0xf5, 0xe6, 0x00, 0x00, 0xe6, 0x5e, 0xf5,
X   0x5f, 0xed, 0x99, 0x03, 0x80, 0x39, 0x5f, 0xf5, 0xbf, 0xaa, 0x67, 0x06,
X   0x41, 0xce, 0xab, 0xfa, 0xbf, 0x5a, 0x9b, 0x11, 0x88, 0xb3, 0xad, 0xfa,
X   0x7f, 0x56, 0x65, 0x02, 0x81, 0x4c, 0xd5, 0xfc, 0x7f, 0xb5, 0x9a, 0x01,
X   0x00, 0xb3, 0x56, 0xfd, 0xff, 0xac, 0x6a, 0x20, 0x08, 0xac, 0x6a, 0xfe,
X   0xff, 0x6a, 0x95, 0x08, 0x01, 0x52, 0xab, 0xfe, 0xff, 0x59, 0x55, 0x22,
X   0x81, 0x54, 0x35, 0xff, 0xff, 0xd5, 0xaa, 0x28, 0x08, 0xaa, 0x55, 0xff,
X   0xff, 0xb3, 0x0a, 0x98, 0x32, 0xa0, 0x9a, 0xff, 0xff, 0xb3, 0x45, 0x64,
X   0x4c, 0xc4, 0x9a, 0xff, 0xb7, 0x25, 0x01, 0x4a, 0xa4, 0x00, 0x41, 0xdb,
X   0x6f, 0x02, 0x00, 0x05, 0x41, 0x0b, 0x80, 0xec, 0x9f, 0x0d, 0x02, 0x21,
X   0x08, 0x01, 0x60, 0xf3, 0x7f, 0x03, 0x90, 0x12, 0x91, 0x96, 0x80, 0xfd,
X   0xf7, 0x00, 0x00, 0xc6, 0xc7, 0x00, 0x00, 0xde, 0x4f, 0x0c, 0x00, 0xc1,
X   0x07, 0x01, 0x60, 0xe4, 0xbf, 0x33, 0x65, 0xe8, 0x2f, 0x4c, 0x99, 0xf9,
X   0x4f, 0x0c, 0x00, 0xc1, 0x07, 0x01, 0x60, 0xe4, 0xf7, 0x00, 0x00, 0xc6,
X   0xc7, 0x00, 0x00, 0xde, 0x7f, 0x03, 0x90, 0x12, 0x91, 0x96, 0x80, 0xfd,
X   0x9f, 0x0d, 0x02, 0x21, 0x08, 0x01, 0x60, 0xf3, 0x6f, 0x02, 0x00, 0x05,
X   0x41, 0x0b, 0x80, 0xec, 0xb7, 0x25, 0x01, 0x4a, 0xa4, 0x00, 0x41, 0xdb,
X   0xff, 0xb3, 0x45, 0x64, 0x4c, 0xc4, 0x9a, 0xff, 0xff, 0xb3, 0x0a, 0x98,
X   0x32, 0xa0, 0x9a, 0xff, 0xff, 0xd5, 0xaa, 0x28, 0x08, 0xaa, 0x55, 0xff,
X   0xff, 0x59, 0x55, 0x22, 0x81, 0x54, 0x35, 0xff, 0xff, 0x6a, 0x95, 0x08,
X   0x01, 0x52, 0xab, 0xfe, 0xff, 0xac, 0x6a, 0x20, 0x08, 0xac, 0x6a, 0xfe,
X   0x7f, 0xb5, 0x9a, 0x01, 0x00, 0xb3, 0x56, 0xfd, 0x7f, 0x56, 0x65, 0x02,
X   0x81, 0x4c, 0xd5, 0xfc, 0xbf, 0x5a, 0x9b, 0x11, 0x88, 0xb3, 0xad, 0xfa,
X   0xbf, 0xaa, 0x67, 0x06, 0x41, 0xce, 0xab, 0xfa, 0x5f, 0xed, 0x99, 0x03,
X   0x80, 0x39, 0x5f, 0xf5, 0x5f, 0xf5, 0xe6, 0x00, 0x00, 0xe6, 0x5e, 0xf5,
X   0xaf, 0xfe, 0x39, 0x07, 0x81, 0x99, 0xff, 0xea, 0xaf, 0x7e, 0xce, 0x03,
X   0x81, 0x67, 0xfe, 0xea, 0xd7, 0xbf, 0x73, 0x90, 0x12, 0x9c, 0xf9, 0xd7,
X   0xd7, 0xff, 0x9c, 0x94, 0x52, 0x72, 0xfe, 0xd7, 0xfb, 0x3f, 0x27, 0x2b,
X   0xa9, 0xc9, 0xf9, 0xbf, 0xff, 0xcf, 0xc8, 0x37, 0xd9, 0x27, 0xe6, 0xff,
X   0xff, 0x3f, 0xf3, 0x57, 0xd4, 0x9f, 0xf9, 0xff, 0xff, 0xcf, 0xfc, 0xeb,
X   0xae, 0x7f, 0xe6, 0xff, 0xff, 0x33, 0xff, 0x6f, 0xed, 0xff, 0x99, 0xff,
X   0xff, 0xcf, 0xff, 0x77, 0xdd, 0xff, 0xe7, 0xff, 0xff, 0xf3, 0xff, 0xbb,
X   0xbb, 0xff, 0x9f, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff,
X   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
END_OF_FILE
if test 3360 -ne `wc -c <'kalicon.h'`; then
    echo shar: \"'kalicon.h'\" unpacked with wrong size!
fi
# end of 'kalicon.h'
fi
if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'patchlevel.h'\"
else
echo shar: Extracting \"'patchlevel.h'\" \(21 characters\)
sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
X#define PATCHLEVEL 3
END_OF_FILE
if test 21 -ne `wc -c <'patchlevel.h'`; then
    echo shar: \"'patchlevel.h'\" unpacked with wrong size!
fi
# end of 'patchlevel.h'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mike Wexler(wyse!mikew)    Phone: (408)433-1000 x1330
Moderator of comp.sources.x