[comp.sources.x] v08i069: xswarm, Part01/01

butterwo@kimchee.ncsc.org (08/11/90)

Submitted-by: butterwo@kimchee.ncsc.org
Posting-number: Volume 8, Issue 69
Archive-name: xswarm/part01

This program animates a bunch of little line segments chasing a randomly
accelerating line segment.  The concept is simple, but the effect is pretty
cute.  By default, it comes up in a window, but it can be put in the root
window too.  In order to make it usable as a screen background, you can
alter the delay between updates, making it use very little cpu time.  One of
the reasons why it doesn't use much cpu time is that it only uses integer
arithmetic.

This program has been tested successfully on a Sun4, a DECStation 3100, and
a Stardent Titan.  The 3100 and the Titan were running X11R3 and the Sun4
was running X11R4.

The only thing you will probably have to change in the Makefile is the
location of X include files.  Sorry for the lack of an Imakefile, but imake
on all of the systems I have access to is installed improperly.

Try xswarm -h for help.  Fiddle with the parameters.  You can get really
different effects!

Jeff

-------------------------------------------------------------------------------
"Between two evils, I always choose the one I haven't tried." -Mae West

Jeff Butterworth
Home:   100-G Misty Woods Cir., Chapel Hill, NC 27514  (919) 967-7359
School: 235 Sitterson, UNC-Chapel Hill, NC 27599  (919) 962-1719
	butterwo@cs.unc.edu
Work:	North Carolina Supercomputing Center, RTP, NC 27709  (919) 248-1147
	butterwo@ncsc.org

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# If this archive is complete, you will see the following message at the end:
#		"End of shell archive."
# Contents:  xswarm xswarm/Imakefile xswarm/Makefile xswarm/README
#   xswarm/TODO xswarm/patchlevel.h xswarm/xswarm.c xswarm/xswarm.h
# Wrapped by argv@turnpike on Fri Aug 10 11:31:55 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test ! -d 'xswarm' ; then
    echo shar: Creating directory \"'xswarm'\"
    mkdir 'xswarm'
fi
if test -f 'xswarm/Imakefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xswarm/Imakefile'\"
else
echo shar: Extracting \"'xswarm/Imakefile'\" \(225 characters\)
sed "s/^X//" >'xswarm/Imakefile' <<'END_OF_FILE'
X#ifdef BandAidCompiler
X#include BandAidCompiler
X#endif
X
XDEFINES =
XINCLUDES = -I$(TOP) -I$(TOP)/X11
XDEPLIBS = $(DEPXLIB)
XLOCAL_LIBRARIES = $(XLIB)
XSYS_LIBRARIES =
X
XSRCS = xswarm.c
XOBJS = xswarm.o
X
XComplexProgramTarget(xswarm)
END_OF_FILE
if test 225 -ne `wc -c <'xswarm/Imakefile'`; then
    echo shar: \"'xswarm/Imakefile'\" unpacked with wrong size!
fi
# end of 'xswarm/Imakefile'
fi
if test -f 'xswarm/Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xswarm/Makefile'\"
else
echo shar: Extracting \"'xswarm/Makefile'\" \(406 characters\)
sed "s/^X//" >'xswarm/Makefile' <<'END_OF_FILE'
X# Gcc usually works better if you have it.
X#CC	= gcc
XCC	= cc
X
X# Uncomment this if you use X11 Release 3 instead of Release 4.
X#XVERSION = -DX11R3
X
X# If the path to Xlib.h needs to be set explicitly...
X#XINC	=
X
X# If you are on a Stardent Titan, then this will help it find random().
X#BSD	= -43
X
XCFLAGS	= -O ${BSD} -I. ${XVERSION}
X
XLIBS	= -lX11
X
Xxswarm: xswarm.c
X	$(CC) $(CFLAGS) -o xswarm xswarm.c $(LIBS)
X
END_OF_FILE
if test 406 -ne `wc -c <'xswarm/Makefile'`; then
    echo shar: \"'xswarm/Makefile'\" unpacked with wrong size!
fi
# end of 'xswarm/Makefile'
fi
if test -f 'xswarm/README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xswarm/README'\"
else
echo shar: Extracting \"'xswarm/README'\" \(1360 characters\)
sed "s/^X//" >'xswarm/README' <<'END_OF_FILE'
XThis program animates a bunch of little line segments chasing a randomly
Xaccelerating line segment.  The concept is simple, but the effect is pretty
Xcute.  By default, it comes up in a window, but it can be put in the root
Xwindow too.  In order to make it usable as a screen background, you can
Xalter the delay between updates, making it use very little cpu time.  One of
Xthe reasons why it doesn't use much cpu time is that it only uses integer
Xarithmetic.
X
XThis program has been tested successfully on a Sun4, a DECStation 3100, and
Xa Stardent Titan.  The 3100 and the Titan were running X11R3 and the Sun4
Xwas running X11R4.
X
XThe only thing you will probably have to change in the Makefile is the
Xlocation of X include files.  Sorry for the lack of an Imakefile, but imake
Xon all of the systems I have access to is installed improperly.
X
XTry xswarm -h for help.  Fiddle with the parameters.  You can get really
Xdifferent effects!
X
XJeff
X
X-------------------------------------------------------------------------------
X"Between two evils, I always choose the one I haven't tried." -Mae West
X
XJeff Butterworth
XHome:   100-G Misty Woods Cir., Chapel Hill, NC 27514  (919) 967-7359
XSchool: 235 Sitterson, UNC-Chapel Hill, NC 27599  (919) 962-1719
X	butterwo@cs.unc.edu
XWork:	North Carolina Supercomputing Center, RTP, NC 27709  (919) 248-1147
X	butterwo@ncsc.org
X
END_OF_FILE
if test 1360 -ne `wc -c <'xswarm/README'`; then
    echo shar: \"'xswarm/README'\" unpacked with wrong size!
fi
# end of 'xswarm/README'
fi
if test -f 'xswarm/TODO' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xswarm/TODO'\"
else
echo shar: Extracting \"'xswarm/TODO'\" \(1288 characters\)
sed "s/^X//" >'xswarm/TODO' <<'END_OF_FILE'
XThese features and bug fixes are in no particular order.  I'll get to them
Xas soon as I can, but other people are more than welcome to give these things
Xa try.
X
XIf you do improve Xswarm, then please send me your new version so that I can
Xincorporate the changes into the next release.  Please don't distribute
Xaltered versions of this program!  I'll post it to the net with all new
Xchanges.
X
X					Jeff Butterworth
X					butterwo@cs.unc.edu
X
XBugs
X----
X- The xor feature has problems.  In the root window any movement of windows
X  over the swarm will cause it to leave an ugly trail.
X- The program doesn't receive the f.delete event from twm when it is in the
X  root window.
X- A very short delay between updates (like 5 milliseconds) can cause xswarm
X  to hang.  Someone mentioned to me that this may be a race condition.
X  What the heck is a race condition?  If anyone wants to look at the
X  non-blocking delay subroutine Nap(), then please feel free.
X
XNew Features
X------------
X- Allow the user to control the wasp with the cursor.  I did this in the gl
X  implementation on the SGI Iris.  It's pretty fun.
X- Colorize the bees base on speed or proximity to the wasp.  Again, I did this
X  on an Iris and it made the whole thing more attractive.
X- Use shapes other than simple line segments.
END_OF_FILE
if test 1288 -ne `wc -c <'xswarm/TODO'`; then
    echo shar: \"'xswarm/TODO'\" unpacked with wrong size!
fi
# end of 'xswarm/TODO'
fi
if test -f 'xswarm/patchlevel.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xswarm/patchlevel.h'\"
else
echo shar: Extracting \"'xswarm/patchlevel.h'\" \(21 characters\)
sed "s/^X//" >'xswarm/patchlevel.h' <<'END_OF_FILE'
X#define PATCHLEVEL 0
END_OF_FILE
if test 21 -ne `wc -c <'xswarm/patchlevel.h'`; then
    echo shar: \"'xswarm/patchlevel.h'\" unpacked with wrong size!
fi
# end of 'xswarm/patchlevel.h'
fi
if test -f 'xswarm/xswarm.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xswarm/xswarm.c'\"
else
echo shar: Extracting \"'xswarm/xswarm.c'\" \(15525 characters\)
sed "s/^X//" >'xswarm/xswarm.c' <<'END_OF_FILE'
X/*
X** XSwarm
X** ======
X**
X** Purpose:	Display a swarm of bees chasing a wasp.
X**
X** Features:	uses only integer math
X**		can be put in the root window
X**		uses non-blocking delays to decrease cpu usage and control speed
X**		has no redeeming social value
X**
X** Comments:	I used psychoII (I assume it's a derivative of ico.) as an
X**		an example of how to open up a window and draw some lines.
X**		Most of this program is now totally rewritten by me, but the
X**		initial window manager hints stuff is left over from the older
X**		program.
X**
X**		Any comments, enhances, or fixes are welcome!
X**
X** Created:	by Jeff Butterworth on 7/11/90
X**		butterwo@cs.unc.edu or butterwo@ncsc.org
X**
X** Updated:	by Jeff Butterworth on 8/1/90
X**
X*/
X
X/* These are needed for the nap function. */
X#include <sys/time.h>
X#include <signal.h>
X
X/* X Includes */
X#include <X11/Xlib.h>
X#include <X11/Xatom.h>
X#include <X11/Xutil.h>
X
X/* Standard Includes */
X#include <stdio.h>
X
X/* Includes for this project. */
X#include <xswarm.h>
X
X
X/* Main()
X** process command line parameters, setup X stuff
X*/
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X    /* These variables are used to analyze the command line parameters. */
X    int         option;
X    extern int  optind;
X    extern char *optarg;
X
X    char		*geom = NULL;
X    int			root = FALSE;
X    XSetWindowAttributes xswa;
X    XWMHints		wmhints;
X    unsigned char	wname[32];
X    XSizeHints		sizehint;
X
X
X    /* Check the command line. */
X    while ((option = getopt(argc,argv,"hq?vrxg:b:a:s:A:S:d:B:w:c:C:")) != EOF)
X    {
X        switch (option)
X        {
X            case 'v':
X                verbose = TRUE;
X                break;
X	    case 'r':
X		root = TRUE;
X		break;
X	    case 'x':
X		xor = TRUE;
X		break;
X	    case 'g':
X		geom = optarg;
X		break;
X	    case 'b':
X		bees = atoi(optarg);
X		break;
X	    case 'a':
X		bee_acc = atoi(optarg);
X		break;
X	    case 's':
X		bee_vel = atoi(optarg);
X		break;
X	    case 'A':
X		wasp_acc = atoi(optarg);
X		break;
X	    case 'S':
X		wasp_vel = atoi(optarg);
X		break;
X	    case 'd':
X		delay = atoi(optarg) * 1000; /* convert to microseconds */
X		break;
X	    case 'B':
X		border = atoi(optarg);
X		break;
X	    case 'w':
X		wasp_color = optarg;
X		break;
X	    case 'c':
X		bee_color = optarg;
X		break;
X	    case 'C':
X		bg_color = optarg;
X		break;
X            case 'h':
X            case 'q':
X            case '?':
X                Usage(*argv);
X                HandleError("The command line parameters were incorrect.",
X                    FATAL);
X		break;
X        }
X    }
X
X    /* Display the arguments. */
X    if (verbose)
X    {
X	printf("Here are the current settings...\n");
X	if (xor)
X	    printf("The logical raster operation GXxor is being used.\n");
X	else
X	    printf("The logical raster operation GXcopy is being used.\n");
X	printf("There are %d bees.\n", bees);
X	printf("Bee acceleration is %d pixels per frame per frame.\n",bee_acc);
X	printf("Bee speed limit is %d pixels per frame.\n", bee_vel);
X	printf("Wasp acceleration is %d pixels per frame per frame.\n",
X	    wasp_acc);
X	printf("Wasp speed limit is %d pixels per frame.\n", wasp_vel);
X	printf("The non-blocking delay is %d milliseconds per frame.\n",
X	    delay / 1000);
X	printf("The wasp can't go within %d pixels of the window edge.\n",
X	    border);
X	printf("The wasp color is \"%s\"\n", wasp_color);
X	printf("The bee color is \"%s\"\n", bee_color);
X	printf("The background color is \"%s\"\n", bg_color);
X    }
X
X    /* This is a remnant of an earlier program.  I don't remember if it is
X       necessary. */
X    display.dname = NULL;
X
X    winW = winH = winX = winY = 0;
X
X    /* Open the display. */
X    if (!(display.dpy = XOpenDisplay(display.dname)))
X    {
X	HandleError("Cannot open display.\n");
X	exit(-1);
X    }
X
X    /* Set the colors. */
X    display.cmap = XDefaultColormap(display.dpy, DefaultScreen(display.dpy));
X    if (!display.cmap) HandleError("There was no default colormap!", FATAL);
X
X    if (wasp_color == NULL)
X	display.wasp =WhitePixel(display.dpy, DefaultScreen(display.dpy));
X    else
X	display.wasp = GetColor(&display, wasp_color);
X
X    if (bee_color == NULL)
X	display.bee =WhitePixel(display.dpy, DefaultScreen(display.dpy));
X    else
X	display.bee = GetColor(&display, bee_color);
X
X    if (bg_color == NULL)
X	display.bg =BlackPixel(display.dpy, DefaultScreen(display.dpy));
X    else
X	display.bg = GetColor(&display, bg_color);
X
X    /* Set up window parameters, create and map window if necessary */
X    if (!root)
X    {
X	winW = WINWIDTH;
X	winH = WINHEIGHT;
X	winX = (DisplayWidth(display.dpy,
X	    DefaultScreen(display.dpy)) - winW) >> 1;
X	winY = (DisplayHeight(display.dpy, 
X	    DefaultScreen(display.dpy)) - winH) >> 1;
X	if (geom) 
X	    XParseGeometry(geom, &winX, &winY, &winW, &winH);
X    }
X    else
X    {
X	winW = DisplayWidth(display.dpy, DefaultScreen(display.dpy));
X	winH = DisplayHeight(display.dpy, DefaultScreen(display.dpy));
X	winX = 0;
X	winY = 0;
X    }
X
X    if (!root)
X    {
X	xswa.event_mask = 0;
X	xswa.background_pixel = display.bg;
X	xswa.border_pixel = display.wasp;
X	display.win = XCreateWindow(display.dpy, 
X	    DefaultRootWindow(display.dpy), 
X	    winX + winW + 50, winY, 
X	    winW, winH, 0, 
X	    DefaultDepth(display.dpy, DefaultScreen(display.dpy)), 
X	    InputOutput, DefaultVisual(display.dpy, 
X	    DefaultScreen(display.dpy)),
X	    CWEventMask | CWBackPixel | CWBorderPixel, &xswa);
X
X	sizehint.flags = PPosition | PSize;
X	    
X	XSetNormalHints(display.dpy, display.win, &sizehint);
X	display.protocol_atom = XInternAtom(display.dpy, "WM_PROTOCOLS", False);
X	display.kill_atom = XInternAtom(display.dpy, "WM_DELETE_WINDOW", False);
X#ifdef X11R4
X	XSetWMProtocols(display.dpy, display.win, &display.kill_atom, 1);
X#endif
X
X	/* Title */
X	sprintf(wname, "XSwarm, Version 1.1, by Jeff Butterworth");
X	XChangeProperty(display.dpy, display.win,
X	    XA_WM_NAME, XA_STRING, 8, PropModeReplace, wname, 
X	    strlen(wname));
X
X	/* Window Manager Hints (This is supposed to make input work.) */
X	wmhints.flags = InputHint;
X	wmhints.input = True;
X	XSetWMHints(display.dpy, display.win, &wmhints);
X
X	XMapWindow(display.dpy, display.win);
X    }
X    else
X	display.win = display.dpy->screens[display.dpy->default_screen].root;
X
X    /* Event Mask */
X    XSelectInput(display.dpy, display.win, KeyPressMask | CWEventMask);
X
X    /* Set up the bees' graphics context. */ 
X    display.bee_gc = XCreateGC(display.dpy, display.win, 0, NULL); 
X    XSetForeground(display.dpy, display.bee_gc, display.bee); 
X    XSetBackground(display.dpy, display.bee_gc, display.bg);
X
X    /* Set up the wasp's graphics context. */ 
X    display.wasp_gc = XCreateGC(display.dpy, display.win, 0, NULL); 
X    XSetForeground(display.dpy, display.wasp_gc, display.wasp); 
X    XSetBackground(display.dpy, display.wasp_gc, display.bg);
X
X    /* Set up an erasing graphics context. */
X    display.erase_gc = XCreateGC(display.dpy, display.win, 0, NULL); 
X    XCopyGC(display.dpy, display.bee_gc, 0xffffffff, display.erase_gc); 
X    XSetForeground(display.dpy, display.erase_gc, display.bg);
X
X    /* Set up an xor wasp graphics context. */
X    display.wasp_xor_gc = XCreateGC(display.dpy, display.win, 0, NULL); 
X    XCopyGC(display.dpy, display.wasp_gc, 0xffffffff, display.wasp_xor_gc); 
X    XSetFunction(display.dpy, display.wasp_xor_gc, GXxor);
X    XSetForeground(display.dpy, display.wasp_xor_gc, display.bg); 
X
X    /* Set up an xor bee graphics context. */
X    display.bee_xor_gc = XCreateGC(display.dpy, display.win, 0, NULL); 
X    XCopyGC(display.dpy, display.bee_gc, 0xffffffff, display.bee_xor_gc); 
X    XSetFunction(display.dpy, display.bee_xor_gc, GXxor);
X    XSetForeground(display.dpy, display.bee_xor_gc, display.bg); 
X
X    /* Clear the background. */
X    if (!xor)
X    {
X	XSetWindowBackground(display.dpy, display.win, display.bg);
X	XFillRectangle(display.dpy, display.win, display.erase_gc,
X	    0,0, winW, winH);
X    }
X
X    /* Animate the swarm. */
X    Animate();
X}
X
X
X
XAnimate()
X{
X    register int	b;		/* bee index */
X    XSegment		*segs;		/* bee lines */
X    XSegment		*old_segs;	/* old bee lines */
X    short		*x, *y;		/* bee positions x[time][bee#] */
X    short		*xv, *yv;	/* bee velocities xv[bee#] */
X    short		wx[3], wy[3];
X    short		wxv, wyv;
X    XEvent		xev;
X    short		dx,dy,distance;
X    int			init = TRUE;
X
X
X    /* Get the random number generator ready. */
X    srandom((int) time(0) % 231);
X
X    /* Allocate memory. */
X    segs = (XSegment *) malloc(sizeof(XSegment) * bees);
X    old_segs = (XSegment *) malloc(sizeof(XSegment) * bees);
X    x = (short *) malloc(sizeof(short) * bees * times);
X    y = (short *) malloc(sizeof(short) * bees * times);
X    xv = (short *) malloc(sizeof(short) * bees);
X    yv = (short *) malloc(sizeof(short) * bees);
X
X    /* Initialize point positions, velocities, etc. */
X
X    /* wasp */
X    wx[0] = BORDER + random() % (winW - 2*BORDER);
X    wy[0] = BORDER + random() % (winH - 2*BORDER);
X    wx[1] = wx[0];
X    wy[1] = wy[0];
X    wxv = 0;
X    wyv = 0;
X
X    /* bees */
X    for (b = 0 ; b < bees ; b++)
X    {
X	X(0,b) = random() % winW;
X	X(1,b) = X(0,b);
X	Y(0,b) = random() % winH;
X	Y(1,b) = Y(0,b);
X	xv[b] = RAND(7);
X	yv[b] = RAND(7);
X    }
X
X    /* Seemingly endless loop. */
X    for (;;)
X    {
X	/* <=- Wasp -=> */
X	/* Age the arrays. */
X	wx[2] = wx[1];
X	wx[1] = wx[0];
X	wy[2] = wy[1];
X	wy[1] = wy[0];
X	/* Accelerate */
X	wxv += RAND(wasp_acc);
X	wyv += RAND(wasp_acc);
X
X	/* Speed Limit Checks */
X	if (wxv > wasp_vel) wxv = wasp_vel;
X	if (wxv < -wasp_vel) wxv = -wasp_vel;
X	if (wyv > wasp_vel) wyv = wasp_vel;
X	if (wyv < -wasp_vel) wyv = -wasp_vel;
X
X	/* Move */
X	wx[0] = wx[1] + wxv;
X	wy[0] = wy[1] + wyv;
X
X	/* Bounce Checks */
X	if ((wx[0] < border) || (wx[0] > winW-border-1))
X	{
X	    wxv = -wxv;
X	    wx[0] += wxv;
X	}
X	if ((wy[0] < border) || (wy[0] > winH-border-1))
X	{
X	    wyv = -wyv;
X	    wy[0] += wyv;
X	}
X
X	/* Don't let things settle down. */
X	xv[random() % bees] += RAND(3);
X	yv[random() % bees] += RAND(3);
X
X	/* <=- Bees -=> */
X	for (b = 0 ; b < bees ; b++)
X	{
X	    /* Age the arrays. */
X	    X(2,b) = X(1,b);
X	    X(1,b) = X(0,b);
X	    Y(2,b) = Y(1,b);
X	    Y(1,b) = Y(0,b);
X
X	    /* Accelerate */
X	    dx = wx[1] - X(1,b);
X	    dy = wy[1] - Y(1,b);
X	    distance = abs(dx)+abs(dy); /* approximation */
X	    if (distance == 0) distance = 1;
X	    xv[b] += (dx*bee_acc)/distance;
X	    yv[b] += (dy*bee_acc)/distance;
X
X	    /* Speed Limit Checks */
X	    if (xv[b] > bee_vel) xv[b] = bee_vel;
X	    if (xv[b] < -bee_vel) xv[b] = -bee_vel;
X	    if (yv[b] > bee_vel) yv[b] = bee_vel;
X	    if (yv[b] < -bee_vel) yv[b] = -bee_vel;
X
X	    /* Move */
X	    X(0,b) = X(1,b) + xv[b];
X	    Y(0,b) = Y(1,b) + yv[b];
X
X	    /* Fill the segment lists. */
X	    segs[b].x1 = X(0,b);
X	    segs[b].y1 = Y(0,b);
X	    segs[b].x2 = X(1,b);
X	    segs[b].y2 = Y(1,b);
X	    old_segs[b].x1 = X(1,b);
X	    old_segs[b].y1 = Y(1,b);
X	    old_segs[b].x2 = X(2,b);
X	    old_segs[b].y2 = Y(2,b);
X	}
X
X	/* Erase previous, draw current, sync for smoothness. */
X
X	/* Wasp */
X	if (xor)
X	{
X	    if (init == FALSE)
X		XDrawLine(display.dpy, display.win, display.wasp_xor_gc,
X		    wx[1], wy[1], wx[2], wy[2]);
X	    XDrawLine(display.dpy, display.win, display.wasp_xor_gc,
X		wx[0], wy[0], wx[1], wy[1]);
X	}
X	else
X	{
X	    if (init == FALSE)
X		XDrawLine(display.dpy, display.win, display.erase_gc,
X		    wx[1], wy[1], wx[2], wy[2]);
X	    XDrawLine(display.dpy, display.win, display.wasp_gc,
X		wx[0], wy[0], wx[1], wy[1]);
X	}
X
X	/* Bees */
X	if (xor)
X	{
X	    if (init == FALSE)
X		XDrawSegments(display.dpy, display.win, display.bee_xor_gc,
X		    old_segs, bees);
X	    else
X		init = FALSE;
X	    XDrawSegments(display.dpy, display.win, display.bee_xor_gc,
X		segs, bees);
X	}
X	else
X	{
X	    if (init == FALSE)
X		XDrawSegments(display.dpy, display.win, display.erase_gc,
X		    old_segs, bees);
X	    else
X		init = FALSE;
X	    XDrawSegments(display.dpy, display.win, display.bee_gc, segs, bees);
X	}
X
X	XSync(display.dpy, False);
X
X	/* Check for events. */
X	if (XPending(display.dpy))
X	{
X	    XNextEvent(display.dpy, &xev);
X	    HandleEvent(&xev);
X	}
X
X	/* Clean up and shut down. */
X	if (stop)
X	{
X	    if (xor)
X	    {
X		XDrawSegments(display.dpy, display.win, display.bee_xor_gc,
X		    segs, bees);
X		XDrawLine(display.dpy, display.win, display.wasp_xor_gc,
X		    wx[0], wy[0], wx[1], wy[1]);
X	    }
X	    else
X		XFillRectangle(display.dpy, display.win, display.erase_gc,
X		    0,0, winW, winH);
X	    XSync(display.dpy, 0);
X	    exit(0);
X	}
X
X	/* Delay so we don't use all of the cpu time. */
X	if (delay != 0) nap(0,delay);
X    }
X}
X
X
X/*
X** HandleEvent()
X**
X** process X events
X*/
X
XHandleEvent(event)
XXEvent	*event;
X{
X    switch (event->type)
X    {
X	case ClientMessage: /* sent by f.delete from twm */
X	{
X	    XClientMessageEvent	*ev = (XClientMessageEvent *) event;
X	    if (ev->message_type == display.protocol_atom && ev->data.l[0] == display.kill_atom)
X		stop = TRUE;
X	}
X	break;
X	case KeyPress:
X	{
X	    XKeyEvent *key_event = (XKeyEvent *) event;
X            char buf[128];
X            KeySym ks;
X            XComposeStatus status;
X
X            XLookupString(key_event,buf,128,&ks,&status);
X            if (buf[0]=='q' || buf[0]=='Q')
X		stop = TRUE;
X	}
X	break;
X	default:
X	break;
X    }
X}
X
X
X/* nap
X**
X** put the process to sleep for a while
X*/
X
Xint catchalarm() { }	/* SIGALRM (null) signal handler */
X
Xvoid nap(sec,usec)
Xlong sec, usec;
X{
X    extern int setitimer();
X    extern void sigpause();
X    struct itimerval wait;
X    static int sigset = FALSE;
X
X    /* If usec is larger than 1 second: */
X    while(usec >= 1e6) { sec++;  usec -= 1e6; }
X
X    if(!sigset) {
X	signal(SIGALRM,catchalarm);
X	sigset = TRUE;
X    }
X
X    wait.it_value.tv_sec = sec;
X    wait.it_value.tv_usec = usec;
X    wait.it_interval.tv_sec = 0;
X    wait.it_interval.tv_usec = 0;
X
X    if((setitimer(ITIMER_REAL,&wait,NULL)) == -1) {
X	HandleError("bad setitimer()", FATAL);
X    }
X
X    sigpause(0);
X}
X
X
Xvoid
XUsage(program)
Xchar *program;
X{
X    printf("%s [options]  where options are listed below\n", program);
X    printf("-r		use root window\n");
X    printf("-d delay	non-blocking delay between screen updates in milliseconds\n");
X    printf("		(Less than 10 is dangerous!)\n");
X    printf("-x		use the logical xor raster operation\n");
X    printf("		(This is buggy, but it leaves your root bitmap alone!)\n");
X    printf("-g geom		window geometry\n");
X    printf("-b bees		number of bees\n");
X    printf("-a bee_acc	bee acceleration in pixels per frame per frame\n");
X    printf("-s bee_vel	bee speed limit in pixels per frame\n");
X    printf("-A wasp_acc	wasp max acceleration in pixels per frame per frame\n");
X    printf("-S wasp_vel	wasp speed limit in pixels per frame\n");
X    printf("-B width	border width that wasp can't cross\n");
X    printf("-w wasp_clr	wasp color\n");
X    printf("-c bee_clr	bee color\n");
X    printf("-C bg_color	background color\n");
X    printf("-h|q|?		display this message\n");
X    printf("\nPress q in the window to stop the insanity.\n\n");
X}
X
X
Xvoid
XHandleError(description, degree)
Xchar    *description;
Xint     degree;
X{
X    fprintf(stderr, "An error has occurred.  The description is below...\n");
X    fprintf(stderr, "%s\n", description);
X
X    if (degree == FATAL)
X    {
X        fprintf(stderr, "Program aborting...\n");
X        exit(-1);
X    }
X}
X
Xlong
XGetColor(display, color)
Xdisp		*display;
Xchar		*color;
X{
X    XColor	cdef;
X    char	error_str[STD_STR];
X
X    if (XParseColor(display->dpy, display->cmap, color, &cdef) &&
X	XAllocColor(display->dpy, display->cmap, &cdef))
X	return(cdef.pixel);
X    else
X    {
X	sprintf(error_str, "Color \"%s\" wasn't found.", color);
X	HandleError(error_str, FATAL);
X    }
X}
END_OF_FILE
if test 15525 -ne `wc -c <'xswarm/xswarm.c'`; then
    echo shar: \"'xswarm/xswarm.c'\" unpacked with wrong size!
fi
# end of 'xswarm/xswarm.c'
fi
if test -f 'xswarm/xswarm.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xswarm/xswarm.h'\"
else
echo shar: Extracting \"'xswarm/xswarm.h'\" \(1914 characters\)
sed "s/^X//" >'xswarm/xswarm.h' <<'END_OF_FILE'
X/* Constants */
X#define TRUE 1
X#define FALSE 0
X#define STD_STR	100
X#define BEES	20	/* number of bees */
X#define TIMES	3	/* number of time positions recorded */
X#define BEEACC	3	/* acceleration of bees */
X#define WASPACC 5	/* maximum acceleration of wasp */
X#define BEEVEL	11	/* maximum bee velocity */
X#define WASPVEL 12	/* maximum wasp velocity */
X#define DELAY	40000	/* microsecond delay between updates */
X#define WINWIDTH 512	/* default window width */
X#define WINHEIGHT 512	/* default window height */
X#define BORDER	50	/* wasp won't go closer than this to the edges */
X
X/* Error Codes */
X#define FATAL	-1
X#define WARNING	-2
X
X/* Macros */
X#define X(t,b)	(x[t*bees + b])		/* addressing into dynamic array */
X#define Y(t,b)	(y[t*bees + b])		/* addressing into dynamic array */
X#define RAND(v)	((random() % v) - (v/2)) /* random number around 0 */
X
X/* Type Definitions */
Xtypedef struct _disp
X{
X	Window	win;
X	Display	*dpy;
X	char	*dname;
X	long	wasp, bee, bg; /* colors */
X	GC	wasp_gc;
X	GC	bee_gc;
X	GC	erase_gc;
X	GC	wasp_xor_gc;
X	GC	bee_xor_gc;
X	Atom	kill_atom, protocol_atom;
X	Colormap cmap;
X} disp;
X
X/* Function Prototypes */
Xvoid    nap();
Xvoid	Usage();
Xvoid	HandleError();
Xlong	GetColor();
X
X/* Global Variables */
X
X/* X related */
Xint		winX, winY;
Xunsigned int	winW, winH;
Xdisp		display;
X
X/* animation related */
Xint	times = TIMES;		/* number of time steps recorded  */
Xint	bees = BEES;		/* number of bees */
Xint	wasp_vel = WASPVEL;	/* maximum wasp speed */
Xint	bee_vel = BEEVEL;	/* maximum bee speed */
Xint	wasp_acc = WASPACC;	/* maximum wasp acceleration */
Xint	bee_acc = BEEACC;	/* bee acceleration */
Xint	delay = DELAY;		/* delay between updates, in microseconds */
Xint	border = BORDER;	/* border limiting wasp travel */
Xchar	*wasp_color = NULL;
Xchar	*bee_color = NULL;
Xchar	*bg_color = NULL;
Xchar	stop = FALSE;
Xint	xor = FALSE;		/* use GXxor if TRUE */
Xint	verbose = FALSE;	/* display settings if TRUE */
END_OF_FILE
if test 1914 -ne `wc -c <'xswarm/xswarm.h'`; then
    echo shar: \"'xswarm/xswarm.h'\" unpacked with wrong size!
fi
# end of 'xswarm/xswarm.h'
fi
echo shar: End of shell archive.
exit 0
dan
----------------------------------------------------
O'Reilly && Associates   argv@sun.com / argv@ora.com
Opinions expressed reflect those of the author only.