[comp.sources.x] v11i012: xswarm version 2.2, Part01/01

butterwo@cs.unc.edu (Jeff Butterworth) (02/01/91)

Submitted-by: butterwo@cs.unc.edu (Jeff Butterworth)
Posting-number: Volume 11, Issue 12
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's, DECStation 3100's,
and DECStation 5000's.

The only thing you will probably have to change in the Makefile is the
location of X include files.

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

#! /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 shell archive."
# Contents:  xswarm.c xswarm.h vroot.h patchlevel.h Makefile Imakefile
#   xswarm.6 README
# Wrapped by butterwo@oscar on Wed Jan 30 07:47:16 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'xswarm.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xswarm.c'\"
else
echo shar: Extracting \"'xswarm.c'\" \(29074 characters\)
sed "s/^X//" >'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
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**		The program meltdown was handy for learning how to take over
X**		the screen.
X**
X**		Any comments, enhances, or fixes are welcome!
X**
X** Created:	by Jeff Butterworth on 7/11/90
X**		butterwo@cs.unc.edu
X**
X** Updated:	by Jeff Butterworth on 1/4/91
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/* This makes it work with virtual root window managers. */
X#include "vroot.h"
X
X/* Standard Includes */
X#include <stdio.h>
X
X/* For those of you who want to know what version you are using. */
X#include "patchlevel.h"
X
X/* Includes for this project. */
X#include "xswarm.h"
X
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X    char	*geometry = NULL;
X
X
X    Initialize();
X
X    Parse_Arguments(argc, argv, &geometry);
X
X    /* The program acts as a screen saver if timeout is non-zero. */
X    if (!timeout)
X    {
X	Create_Window(geometry);
X	Animate();
X    }
X    else
X    {
X	Change_Screen_Saver(False);
X	while(TRUE)
X	{
X	    Wait_For_Idleness();
X	    Create_Big_Window();
X	    Animate();
X	}
X    }
X}
X
X
Xvoid
XQuit(signal, code, scp, address)
Xint			signal, code;
Xstruct sigcontext	*scp;
Xchar			*address;
X{
X    if (timeout)
X    {
X	fprintf(stderr, "Restoring screen saver state.\n");
X	Change_Screen_Saver(True);
X    }
X
X    fprintf(stderr, "Terminating because of signal %d. ", signal);
X    switch (signal)
X    {
X	case SIGHUP:	fprintf(stderr, "(Hangup)\n"); break;
X	case SIGINT:	fprintf(stderr, "(Interrupt)\n"); break;
X	case SIGQUIT:	fprintf(stderr, "(Quit)\n"); break;
X	case SIGILL:	fprintf(stderr, "(Illegal Instruction)\n"); break;
X	case SIGFPE:	fprintf(stderr, "(Floating Point Exception)\n"); break;
X	case SIGKILL:	fprintf(stderr, "(Kill)\n"); break;
X	case SIGBUS:	fprintf(stderr, "(Bus Error)\n"); break;
X	case SIGSEGV:	fprintf(stderr, "(Segmentation Violation)\n"); break;
X	case SIGSYS:	fprintf(stderr, "(Bad Argument to Sys Call)\n"); break;
X	case SIGTERM:	fprintf(stderr, "(Termination from Kill)\n"); break;
X	case SIGSTOP:	fprintf(stderr, "(Stop not from tty)\n"); break;
X	case SIGTSTP:	fprintf(stderr, "(Stop from tty)\n"); break;
X	case SIGXCPU:	fprintf(stderr, "(Exceeded CPU Time Limit)\n"); break;
X	default:	fprintf(stderr, "(Unexpected Signal)\n");
X    }
X
X    exit(-signal);
X}
X
X
Xvoid
XInitialize()
X{
X    signal(SIGHUP, Quit);
X    signal(SIGINT, Quit);
X    signal(SIGQUIT, Quit);
X    signal(SIGILL, Quit);
X    signal(SIGFPE, Quit);
X    signal(SIGKILL, Quit);
X    signal(SIGBUS, Quit);
X    signal(SIGSEGV, Quit);
X    signal(SIGSYS, Quit);
X    signal(SIGTERM, Quit);
X    signal(SIGSTOP, Quit);
X    if (timeout) signal(SIGTSTP, Quit);
X    signal(SIGXCPU, Quit);
X}
X
X
X/* Parse_Arguments()							*/
X/* Analyze command line arguments and set variables accordingly.	*/
X
Xvoid
XParse_Arguments(argc, argv, geometry)
Xint	argc;
Xchar	**argv;
Xchar	**geometry;
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    int			bits;		/* Used to set window geometry. */
X
X
X    /* Check the command line. */
X    while ((option = getopt(argc,argv,"hq?vprVxt:d:g:D:b:a:s:A:S:B:w:c:C:"))
X	    != EOF)
X    {
X        switch (option)
X        {
X            case 'v':
X                verbose = TRUE;
X                break;
X            case 'p':
X                pointer = TRUE;
X                break;
X            case 'V':
X                stay_in_front = TRUE;
X                break;
X	    case 'r':
X		root = TRUE;
X		break;
X	    case 'x':
X		xor = TRUE;
X		break;
X	    case 't':
X		timeout = atoi(optarg);
X		break;
X	    case 'g':
X		*geometry = optarg;
X		break;
X	    case 'd':
X		display.dname = 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	if (stay_in_front)
X	    printf("The bees will try to stay in the clear area of the screen.\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	if (timeout) printf("Screen saved after %d seconds.\n", timeout);
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    /* Open the display. */
X    if (!(display.dpy = XOpenDisplay(display.dname)))
X    {
X	HandleError("Cannot open display.\n");
X	exit(-1);
X    }
X
X    /* Record the screen number and root window. */
X    display.screen = DefaultScreen(display.dpy);
X    display.root = RootWindow(display.dpy, display.screen);
X
X    /* Set the colors. */
X    display.cmap = XDefaultColormap(display.dpy, display.screen);
X    if (!display.cmap) HandleError("There was no default colormap!", FATAL);
X
X    if (wasp_color == NULL)
X	display.wasp =WhitePixel(display.dpy, display.screen);
X    else
X	display.wasp = GetColor(&display, wasp_color, NULL);
X
X    if (bee_color == NULL)
X	display.bee =WhitePixel(display.dpy, display.screen);
X    else
X	display.bee = GetColor(&display, bee_color, NULL);
X
X    if (bg_color == NULL)
X	display.bg = BlackPixel(display.dpy, display.screen);
X    else
X	display.bg = GetColor(&display, bg_color, &(display.bg_xcolor));
X
X    /* Set up window size. */
X    if (!root && !timeout)
X    {
X	winW = WINWIDTH;
X	winH = WINHEIGHT;
X	winX = (DisplayWidth(display.dpy, display.screen)
X		- winW) / 2;
X	winY = (DisplayHeight(display.dpy, display.screen)
X		- winH) / 2;
X	if (*geometry != NULL) 
X	    XParseGeometry(*geometry, &winX, &winY, &winW, &winH);
X    }
X    else
X    {
X	winW = DisplayWidth(display.dpy, display.screen);
X	winH = DisplayHeight(display.dpy, display.screen);
X	winX = 0;
X	winY = 0;
X    }
X
X    /* If screen saving is on, then watch for events everywhere. */
X    /* Traverse the window tree. */
X    if (timeout) Traverse_Tree(display.dpy, display.root);
X}
X
X
X/* Change_Screen_Saver()							*/
X/* Turn the server's screen saver on or off.				*/
X/* This routine should be called with on=False before it is called	*/
X/* with on=True.							*/
X
Xvoid
XChange_Screen_Saver(on)
Xint	on;	/* True or False */
X{
X    static int	timeout, interval, blanking, exposures;
X    static int	set_yet = FALSE;
X
X    if (on)
X    {
X	if (set_yet)
X	{
X	    /* Restore the old settings. */
X	    XSetScreenSaver(display.dpy, timeout, interval, blanking,exposures);
X	    XActivateScreenSaver(display.dpy);
X	    XResetScreenSaver(display.dpy);
X	    XSync(display.dpy, False);
X	}
X    }
X    else
X    {
X	/* Save the old settings and turn off the server's screen saver. */
X	XGetScreenSaver(display.dpy, &timeout, &interval, &blanking,&exposures);
X	XSetScreenSaver(display.dpy, 0, 0, DefaultBlanking, DefaultExposures);
X	XResetScreenSaver(display.dpy);
X	set_yet = TRUE;
X    }
X}
X
X
X/* Traverse_Tree()							*/
X/* Select some events from every single window that is a decendent	*/
X/* of "current".							*/
X
Xvoid
XTraverse_Tree(display, current)
XDisplay	*display;
XWindow	current;
X{
X    Window		my_root, parent, *children;
X    unsigned int	num_children;
X    int		i;
X
X
X    /* Watch for signs of life from the user in this window. */
X    XSelectInput(display, current, ALIVE_MASK);
X
X    /* Who are my kids? */
X    XQueryTree(display, current, &my_root, &parent, &children,
X	&num_children);
X
X    /* Examine all of the children too. */
X    for (i = 0 ; i < num_children ; i++)
X	Traverse_Tree( display, children[i] );
X
X    /* Let's not waste any memory. */
X    XFree( (char *) children);
X}
X
X
X/* Wait_For_Idleness()							*/
X/* Wait for "timeout" seconds of user inactivity.			*/
X
Xvoid
XWait_For_Idleness()
X{
X    int		watching = TRUE;
X    int		found;
X    int		timer = 0;
X    XEvent	event;
X
X    while( watching )
X    {
X	if (timer >= timeout) return;
X
X	sleep(1);
X	timer++;
X
X	found = XCheckIfEvent(display.dpy, &event, Dummy_Predicate, NULL);
X	if (found) timer = 0;
X
X	/* Flush events. */
X	while (found)
X	{
X	    switch (event.type)
X	    {
X		/* Watch for events in new windows too. */
X		case CreateNotify:
X		    {
X			XCreateWindowEvent *ev = (XCreateWindowEvent *) &event;
X
X			XSelectInput(display.dpy, ev->window, ALIVE_MASK);
X			Traverse_Tree(display.dpy, ev->window);
X		    }
X		    break;
X		default:
X		    break;
X	    }
X	    /* Check for the existence of more events. */
X	    found = XCheckIfEvent(display.dpy, &event, Dummy_Predicate, NULL);
X	}
X    }
X}
X
X
XBool
XDummy_Predicate(display, event, arg)
XDisplay	*display;
XXEvent	*event;
Xchar	*arg;
X{
X    return(True);
X}
X
X
Xvoid
XCreate_Big_Window()
X{
X    /* Window Attributes */
X    unsigned long		valuemask;
X    XSetWindowAttributes	xswa;
X
X    XSizeHints		sizehint;
X    XWMHints		wmhints;
X    unsigned char	wname[32];	/* Window Name */
X
X    /* First time. */
X    static int		first = TRUE;
X
X    /* Cursor Stuff */
X    static Cursor	cursor;
X
X
X    /* Turn the cursor the color of the background. (Invisible) */
X    if (first)
X    {
X	/* I don't care which cursor I get. */
X	cursor = XCreateFontCursor(display.dpy, 0);
X
X	XRecolorCursor(display.dpy, cursor, &(display.bg_xcolor),
X			&(display.bg_xcolor));
X	first = FALSE;
X    }
X
X    /* Create a screen sized window. */
X    xswa.cursor = cursor;
X    xswa.background_pixel = display.bg;
X    xswa.override_redirect = True;
X    xswa.do_not_propagate_mask = KeyPressMask | KeyReleaseMask |
X	ButtonPressMask | ButtonReleaseMask;
X    valuemask = CWCursor | CWBackPixel | CWOverrideRedirect | CWDontPropagate;
X    display.win = XCreateWindow(display.dpy, display.root, 
X	0, 0, 
X	winW, winH, 0, 
X	DefaultDepth(display.dpy, display.screen), 
X	InputOutput, DefaultVisual(display.dpy, display.screen),
X	valuemask, &xswa);
X
X    XMapWindow(display.dpy, display.win);
X
X    /* Event Mask */
X    XSelectInput(display.dpy, display.win, KeyPressMask | PointerMotionMask);
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    XFillRectangle(display.dpy, display.win, display.erase_gc,
X	    0,0, winW, winH);
X}
X
X
X
X/* Create_Window()							*/
X/* Create the window, making sure to set it up correctly.		*/
X
Xvoid
XCreate_Window(geometry)
Xchar	*geometry;
X{
X    XSetWindowAttributes xswa;
X    XSizeHints		sizehint;
X    XWMHints		wmhints;
X    unsigned char	wname[256];	/* Window Name */
X
X
X    if (!root)
X    {
X	xswa.event_mask = 0;
X	xswa.background_pixel = display.bg;
X	display.win = XCreateWindow(display.dpy, display.root, 
X	    winX, winY, 
X	    winW, winH, 0, 
X	    DefaultDepth(display.dpy, display.screen), 
X	    InputOutput, DefaultVisual(display.dpy, display.screen),
X	    CWEventMask | CWBackPixel , &xswa);
X
X	sizehint.x = winX;
X	sizehint.y = winY;
X	sizehint.width = winW;
X	sizehint.height = winH;
X	sizehint.min_width = 2*border + 20;
X	sizehint.min_height = 2*border + 20;
X	if (geometry != NULL)
X	    sizehint.flags = USPosition | USSize | PMinSize;
X	else
X	    sizehint.flags = PPosition | PSize | PMinSize;
X	XSetNormalHints(display.dpy, display.win, &sizehint);
X	    
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( (char *) wname, "XSwarm, Version %s, by Jeff Butterworth",
X	    VERSION);
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    {
X	display.win = display.root;
X	xswa.backing_store = Always;
X	XChangeWindowAttributes(display.dpy, display.win,
X	    CWBackingStore, &xswa);
X    }
X
X    /* Event Mask */
X    if (root)
X	XSelectInput(display.dpy, display.win,
X			KeyPressMask | StructureNotifyMask);
X    else
X	XSelectInput(display.dpy, display.win,
X			KeyPressMask | ButtonPressMask | StructureNotifyMask);
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
X
X/* Animate()								*/
X/* Move the swarm around.						*/
X
Xvoid
XAnimate()
X{
X    register int	b;		/* bee index */
X    XSegment		*segs;		/* bee lines */
X    XSegment		*old_segs;	/* old bee lines */
X    int			*x, *y;		/* bee positions x[time][bee#] */
X    int			*xv, *yv;	/* bee velocities xv[bee#] */
X    int			wx[3], wy[3];	/* wasp positions */
X    int			wxv, wyv;	/* wasp velocity */
X    XEvent		xev;
X    int			dx,dy,distance;
X    int			init = TRUE;
X
X    /* These variables are related to bouncing off of other windows. */
X    int			testx, testy;
X    int			BehindWindow;	/* TRUE if wasp is behind a window. */
X    Window		child;
X
X    /* These variables are related to mouse control of the wasp. */
X    int			garbage_int; /* for XQueryPointer */
X    Window		garbage_win; /* ...likewise */
X
X
X
X    /* Get the random number generator ready. */
X    srandom(getpid());
X
X    /* Allocate memory. */
X    segs = (XSegment *) malloc(sizeof(XSegment) * bees);
X    old_segs = (XSegment *) malloc(sizeof(XSegment) * bees);
X    x = (int *) malloc(sizeof(int) * bees * times);
X    y = (int *) malloc(sizeof(int) * bees * times);
X    xv = (int *) malloc(sizeof(int) * bees);
X    yv = (int *) malloc(sizeof(int) * bees);
X
X    /* Initialize point positions, velocities, etc. */
X
X    /* wasp */
X    if (pointer)
X    {
X	XQueryPointer(display.dpy, display.win, &garbage_win,
X			&garbage_win, &garbage_int, &garbage_int,
X			&(wx[0]), &(wy[0]), (unsigned int *) &garbage_int);
X    }
X    else
X    {
X	wx[0] = BORDER + random() % (winW - 2*BORDER);
X	wy[0] = BORDER + random() % (winH - 2*BORDER);
X    }
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    /* This checks to see if we've gone behind a window. */
X    if (stay_in_front)
X    {
X	XTranslateCoordinates(display.dpy, display.win, display.win,
X	    wx[0], wy[0], &testx, &testy, &child);
X	BehindWindow = (child != 0);
X    }
X
X    /* Seemingly endless loop. */
X    while (TRUE)
X    {
X	/* <=- Wasp -=> */
X	/* Age the position arrays. */
X	wx[2] = wx[1];
X	wx[1] = wx[0];
X	wy[2] = wy[1];
X	wy[1] = wy[0];
X
X	if (pointer)
X	{
X	    XQueryPointer(display.dpy, display.win, &garbage_win,
X			    &garbage_win, &garbage_int, &garbage_int,
X			    &wx[0], &wy[0], (unsigned int *) &garbage_int);
X	}
X	else
X	{
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_Against_Windows(wx, wy, &wxv, &wyv, BehindWindow);
X
X	    /* Bounce Checks */
X	    if ((wx[0] < border) || (wx[0] > winW-border-1))
X	    {
X		wxv = -wxv;
X		wx[0] += wxv<<1;
X	    }
X	    if ((wy[0] < border) || (wy[0] > winH-border-1))
X	    {
X		wyv = -wyv;
X		wy[0] += wyv<<1;
X	    }
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	/* Again check to see if the wasp is behind a window. */
X	if (stay_in_front)
X	{
X	    XTranslateCoordinates(display.dpy, display.win, display.win,
X		wx[0], wy[0],
X		&testx, &testy, &child);
X	    BehindWindow = (child != 0);
X	}
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	    /* Make sure the wasp is within the window. */
X	    if (wx[0] < border) wx[0] = border;
X	    if (wx[0] > winW-border-1) wx[0] = winW-border-1;
X	    if (wy[0] < border) wy[0] = border;
X	    if (wy[0] > winH-border-1) wy[0] = winH-border-1;
X	}
X
X	/* Clean up and shut down. */
X	if (stop)
X	{
X	    stop = FALSE; /* reset the "stop" variable */
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
X	    if (!root)
X	    {
X		int		xc, yc;
X		unsigned int	width, height, border_width, depth;
X		Window		root_window;
X
X		/* This is for debugging. */
X		/* I was finding that when using xswarm as a screen	*/
X		/* saver, I would come back after an hour, and it	*/
X		/* would be in a little shriveled window in the		*/
X		/* corner.						*/
X#ifdef DEBUG
X		XGetGeometry(display.dpy, display.win, &root_window,
X		    &xc, &yc, &width, &height, &border_width, &depth);
X		printf("Window info: x,y,width,height,border,depth\n");
X		printf("%d,%d  %d,%d  %d  %d\n",xc,yc,width,height,
X		    border_width,depth);
X		printf("Wasp x,y xv,yv: %d,%d %d,%d\n",wx[0],wy[0],wxv,wyv);
X		printf("Bee 1 x,y xv,yv: %d %d %d %d\n",
X		    X(0,1),Y(0,1),
X		    *(xv+1),yv[1]);
X#endif
X
X		XDestroyWindow(display.dpy, display.win);
X	    }
X
X	    return;
X	}
X
X	/* Delay so we don't use all of the cpu time. */
X#ifdef HP_UX
X	if (delay != 0) usleep(delay);
X#else
X	if (delay != 0) nap(0,delay);
X#endif
X    }
X}
X
X
XBounce_Against_Windows(wx, wy, wxv, wyv, BehindWindow)
Xint	wx[3], wy[3];
Xint	*wxv, *wyv;
Xint	BehindWindow;
X{
X    int		testx, testy;
X    Window	child;
X
X
X    /* This makes the wasp avoid moving behind windows. */
X    if (root && stay_in_front && !BehindWindow)
X    {
X	XTranslateCoordinates(display.dpy, display.win, display.win,
X	    wx[0], wy[0], &testx, &testy, &child);
X	if (child != 0)
X	{
X	    XTranslateCoordinates(display.dpy, display.win, display.win,
X		wx[0] - (*wxv), wy[0], &testx, &testy, &child);
X	    if (child == 0) /* vertical surface */
X	    {
X		wx[0] = wx[1] - (*wxv); /* undo the jump into the window */
X		*wxv = -(*wxv);        /* bounce in x direction */
X	    }
X	    else
X	    {
X		XTranslateCoordinates(display.dpy, display.win,display.win,
X		    wx[0], wy[0] - (*wyv), &testx, &testy, &child);
X		if (child == 0) /* horizontal surface */
X		{
X		    wy[0] = wy[1] - (*wyv); /* undo the jump into the window */
X		    *wyv = - (*wyv);        /* bounce in y direction */
X		}
X		else
X		{ /* concave corner */
X		    wx[0] = wx[1] - (*wxv); /* undo the jump into the corner */
X		    wy[0] = wy[1] - (*wyv);
X		    *wxv = - (*wxv);        /* reverse direction */
X		    *wyv = - (*wyv);
X		}
X	    }
X	}
X    }
X}
X
X
X/*
X** HandleEvent()
X**
X** process X events
X*/
X
XHandleEvent(event)
XXEvent	*event;
X{
X    /* If the screen saver is on, then watch for signs of activity. */
X    if (((event->type == KeyPress) || (event->type == MotionNotify)) &&
X	(timeout)) stop = TRUE;
X
X    switch (event->type)
X    {
X	case ClientMessage: /* sent by f.delete from twm */
X	    {
X		XClientMessageEvent	*ev = (XClientMessageEvent *) event;
X
X		printf("Client message received.\n");
X		if (ev->message_type == display.protocol_atom &&
X		    ev->data.l[0] == display.kill_atom)
X		    stop = TRUE;
X	    }
X	    break;
X        case ConfigureNotify:
X	    {
X		XConfigureEvent *ev = (XConfigureEvent *) event;
X		winW = ev->width;
X		winH = ev->height;
X		winX = ev->x;
X		winY = ev->y;
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	case ButtonPress:
X	    pointer = !pointer;
X	    break;
X	default:
X	    break;
X    }
X}
X
X
X#ifndef HP_UX
X
X/*  Put the process to sleep for a while.  */
Xvoid nap(sec,usec)
Xlong sec, usec;
X{
X    static struct timeval tv;
X
X    tv.tv_sec = sec;
X    tv.tv_usec = usec;
X    select(0, 0, 0, 0, &tv);
X}
X
X#else
X
Xstatic void alarmhandler() 
X{
X}
X
Xsleepms(msec)
Xint msec;
X{
X    struct itimerval value,ovalue;
X    struct sigvec vec;
X    long savemask, sigblock(), sigpause();
X
X    vec.sv_handler = alarmhandler;
X    vec.sv_mask = 0x0;
X    vec.sv_flags = 0;
X    sigvector(SIGALRM, &vec, &vec); /* Set up alarmhandler for SIGALRM */
X    savemask = sigblock((long)(1L << (SIGALRM - 1)));
X
X    value.it_interval.tv_sec = 0;
X    value.it_interval.tv_usec = 0;
X    value.it_value.tv_sec = msec/1000;
X    value.it_value.tv_usec = (msec%1000)*1000;
X    setitimer(ITIMER_REAL,&value,&ovalue);
X
X    (void)sigpause(0L);
X    (void)sigsetmask(savemask);
X
X    sigvector(SIGALRM, &vec, NULL); /* Restore previous signal handler */
X}
X
Xusleep(us)
Xlong us;
X{
X    sleepms(us / 1000);
X}
X
X#endif
X
X
Xvoid
XUsage(program)
Xchar *program;
X{
X    printf("%s [options]  where options are listed below\n", program);
X    printf("-h|q|?		display this message\n");
X    printf("-v		give verbose list of current settings\n");
X    printf("-p		use mouse (pointer) button to control wasp\n");
X    printf("-r		use root window\n");
X    printf("-V		stay in clear area of the screen (only with -r)\n");
X    printf("-x		use the logical xor raster operation (saves the root bitmap)\n");
X    printf("-g geometry		window geometry\n");
X    printf("-d host:display	X server to connect to\n");
X    printf("-t timeout	screen saved after 'timeout' seconds\n");
X    printf("-D delay	non-blocking delay between updates (milliseconds)\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("\nPress any mouse button in the window to grab/release the wasp.\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, final_color)
Xdisp		*display;
Xchar		*color;
XXColor		*final_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    {
X	sprintf(error_str, "Color \"%s\" wasn't found.", color);
X	HandleError(error_str, FATAL);
X    }
X
X    /* Copy the final color. */
X    if (final_color != NULL) *final_color = cdef;
X
X    return(cdef.pixel);
X}
END_OF_FILE
if test 29074 -ne `wc -c <'xswarm.c'`; then
    echo shar: \"'xswarm.c'\" unpacked with wrong size!
fi
# end of 'xswarm.c'
fi
if test -f 'xswarm.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xswarm.h'\"
else
echo shar: Extracting \"'xswarm.h'\" \(2970 characters\)
sed "s/^X//" >'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#define ALIVE_MASK	(SubstructureNotifyMask | KeyPressMask | PointerMotionMask)
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	int	screen;
X	Window	root;
X	char	*dname;
X	long	wasp, bee, bg; /* colors */
X	XColor	bg_xcolor;
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
X/*--------------------------- Function Prototypes ---------------------------*/
Xvoid    nap();
Xvoid	Usage();
Xvoid	HandleError();
X
Xvoid	Initialize();
X
Xvoid
XQuit(
X#ifdef USE_PROTOTYPES
Xint,
Xint,
Xstruct sigcontext *,
Xchar *
X#endif
X);
X
Xvoid
XChange_Screen_Saver(
X#ifdef USE_PROTOTYPES
Xint
X#endif
X);
X
Xlong
XGetColor(
X#ifdef USE_PROTOTYPES
Xdisp	*,
Xchar	*,
XXColor	*
X#endif
X);
X
Xvoid
XParse_Arguments(
X#ifdef USE_PROTOTYPES
Xint,
Xchar **,
Xchar *
X#endif
X);
X
Xvoid
XCreate_Window(
X#ifdef USE_PROTOTYPES
Xchar *
X#endif
X);
X
Xvoid Animate();
X
Xvoid
XTraverse_Tree(
X#ifdef USE_PROTOTYPES
XDisplay *,
XWindow
X#endif
X);
X
Xvoid Wait_For_Idleness();
X
XBool
XDummy_Predicate(
X#ifdef USE_PROTOTYPES
XDisplay *,
XXEvent *,
Xchar *
X#endif
X);
X
Xvoid Create_Big_Window();
X
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	timeout = 0;		/* time in seconds before screen saving */
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 */
Xint	stay_in_front = FALSE;	/* Try to stay in clear area of the screen. */
Xint	root = FALSE;		/* display in root window */
Xint	pointer = FALSE;	/* control wasp with mouse */
X
X
END_OF_FILE
if test 2970 -ne `wc -c <'xswarm.h'`; then
    echo shar: \"'xswarm.h'\" unpacked with wrong size!
fi
# end of 'xswarm.h'
fi
if test -f 'vroot.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'vroot.h'\"
else
echo shar: Extracting \"'vroot.h'\" \(2198 characters\)
sed "s/^X//" >'vroot.h' <<'END_OF_FILE'
X/*
X * vroot.h -- Virtual Root Window handling header file
X *
X * This header file redefines the X11 macros RootWindow and DefaultRootWindow,
X * making them look for a virtual root window as provided by certain `virtual'
X * window managers like swm and tvtwm. If none is found, the ordinary root
X * window is returned, thus retaining backward compatibility with standard
X * window managers.
X * The function implementing the virtual root lookup remembers the result of
X * its last invocation to avoid overhead in the case of repeated calls
X * on the same display and screen arguments. 
X * The lookup code itself is taken from Tom LaStrange's ssetroot program.
X *
X * Most simple root window changing X programs can be converted to using
X * virtual roots by just including
X *
X * #include "vroot.h"
X *
X * after all the X11 header files.  It has been tested on such popular
X * X clients as xphoon, xfroot, xloadimage, and xaqua.
X *
X * Andreas Stolcke (stolcke@ICSI.Berkeley.EDU), 9/7/90
X */
X
X#include <X11/X.h>
X#include <X11/Xatom.h>
X
Xstatic Window
XVirtualRootWindow(dpy, screen)
XDisplay *dpy;
X{
X	static Display *save_dpy = (Display *)0;
X	static int save_screen = -1;
X	static Window root = (Window)0;
X
X	Atom __SWM_VROOT = None;
X	int i;
X	Window rootReturn, parentReturn, *children;
X	unsigned int numChildren;
X
X	if ( dpy != save_dpy || screen != save_screen ) {
X		root = RootWindow(dpy, screen);
X
X		/* go look for a virtual root */
X		__SWM_VROOT = XInternAtom(dpy, "__SWM_VROOT", False);
X		XQueryTree(dpy, root, &rootReturn, &parentReturn,
X				 &children, &numChildren);
X		for (i = 0; i < numChildren; i++) {
X			Atom actual_type;
X			int actual_format;
X			long nitems, bytesafter;
X			Window *newRoot = (Window)0;
X
X			if (XGetWindowProperty(dpy, children[i], __SWM_VROOT,
X				0, 1, False, XA_WINDOW,
X				&actual_type, &actual_format,
X				&nitems, &bytesafter,
X				(unsigned char **) &newRoot) == Success
X			    && newRoot) {
X			    root = *newRoot;
X			    break;
X			}
X		}
X
X		save_dpy = dpy;
X		save_screen = screen;
X	}
X
X	return root;
X}
X
X#undef DefaultRootWindow
X#define DefaultRootWindow(dpy) RootWindow(dpy, DefaultScreen(dpy))
X
X#undef RootWindow
X#define RootWindow(dpy,screen) VirtualRootWindow(dpy,screen)
X
END_OF_FILE
if test 2198 -ne `wc -c <'vroot.h'`; then
    echo shar: \"'vroot.h'\" unpacked with wrong size!
fi
# end of 'vroot.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'\" \(387 characters\)
sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
X/* Version 1.0 was cute, but it hadn't quite a few little bugs.		*/
X/* For a list of nifty features in the current version, see the		*/
X/* manual page.								*/
X
X/* For version 2.* patches have not been released, because the changes	*/
X/* were often fairly significant.  After I've sent out a patch, I'll	*/
X/* increment PATCHLEVEL.						*/
X
X#define VERSION		"2.1"
X#define PATCHLEVEL	0
END_OF_FILE
if test 387 -ne `wc -c <'patchlevel.h'`; then
    echo shar: \"'patchlevel.h'\" unpacked with wrong size!
fi
# end of 'patchlevel.h'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(717 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# Gcc usually works better if you have it.
XCC	= gcc
X#CC	= cc
X
X# If the path to Xlib.h needs to be set explicitly...
X#XINC	= -I/usr1/butterwo/X11R4/include
X
X# If you are on a Stardent Titan, then this will help it find random().
X#BSD	= -43
X
X# If you are using a compiler that supports prototypes then uncomment this.
X# (Only little girlie men don't use prototypes. :-) )
X#PROTO	= -DUSE_PROTOTYPES
X
XSRCS	= xswarm.c
XOBJS	= xswarm.o
XHEADERS	= xswarm.h vroot.h patchlevel.h
XPROGRAM	= xswarm
X
XCFLAGS	= $(BSD) $(PROTO) $(XINC)
X
XLIBS	= -lX11 -lm
X
X$(PROGRAM): $(SRCS) $(HEADERS) Makefile
X	$(CC) $(CFLAGS) -o $(PROGRAM) $(SRCS) $(LIBS)
X
Xdistribution:
X	shar -o xswarm.shar $(SRCS) $(HEADERS) Makefile Imakefile xswarm.6 README
X
END_OF_FILE
if test 717 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'Imakefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Imakefile'\"
else
echo shar: Extracting \"'Imakefile'\" \(124 characters\)
sed "s/^X//" >'Imakefile' <<'END_OF_FILE'
XIMAKE_DEFINES= -DManSuffix=6
X
XDEFINES = -DX11R4
XDEPLIBS = $(DEPXLIB)
XLOCAL_LIBRARIES = $(XLIB)
X
XSimpleProgramTarget(xswarm)
END_OF_FILE
if test 124 -ne `wc -c <'Imakefile'`; then
    echo shar: \"'Imakefile'\" unpacked with wrong size!
fi
# end of 'Imakefile'
fi
if test -f 'xswarm.6' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xswarm.6'\"
else
echo shar: Extracting \"'xswarm.6'\" \(6831 characters\)
sed "s/^X//" >'xswarm.6' <<'END_OF_FILE'
X.TH XSWARM 6 "January 30, 1991"
X.UC 4
X.SH NAME
XXswarm Version 2.2 \- X11 animated toy
X.SH SYNOPSIS
X.B xswarm
X.B \[\-hq?vprVx\]
X.B \[\-t
X.I timeout\]
X.B \[\-D
X.I delay\]
X.B \[\-g
X.I geometry\]
X.B \[\-d
X.I host:display\]
X.B \[\-b
X.I bees\]
X.B \[\-a
X.I bee-acceleration\]
X.B \[\-s
X.I bee-velocity\]
X.B \[\-A
X.I wasp-acceleration\]
X.B \[\-S
X.I wasp-velocity\]
X.B \[\-B
X.I border-width\]
X.B \[\-w
X.I wasp-color\]
X.B \[\-c
X.I bee-color\]
X.B \[\-C
X.I background-color\]
X.SH DESCRIPTION
X.I Xswarm
Xis an X11 client that animates a group of line segments.  One line is
Xcalled the wasp and the others are the bees.  The bees constantly accelerate 
Xtoward the wasp, forming a cute pattern that continually changes.  Because
X.I Xswarm
Xis commonly left running in the root window, it was made possible to control
Xhow much cpu time it uses with the -d option.
X.LP
XIf a mouse button is pressed while the pointer is in the xswarm window,
Xthe wasp becomes controlled by the mouse.  Control is released when the
Xmouse button is pressed again.  To kill
X.I Xswarm
X, press q in it's window.
X.LP
XThe parameters that affect behavior of the swarm are controllable by the user
Xthrough command line parameters.  Some of the niftier features are controlling
Xthe wasp with the mouse, putting it in the root window, using it as a screen
Xsaver, and making the swarm fly "above" a background bitmap.
X.LP
XAfter playing with
X.I Xswarm
Xinteractively, one of it's common uses is in the root
Xwindow where it helps break the monotony of X.  When putting it there, don't
Xforget to play with the -V and -x options!
X.LP
XOne of the recently added capabilities of
X.I Xswarm
Xis screen saving.  If a non-zero timeout is given with the -t option, the
Xscreen will be cleared after the given amount of idle time and the swarm will
Xanimate until a key is pressed or the mouse is moved.  As far as I know,
Xthis is the first example of an
X.I X
Xscreen saver other than the one built into the server.  By screen saver, I
Xmean a program that does not require a signal from the user to take over the
Xscreen.
X.PP
X.SH OPTIONS
X.I Xswarm
Xhas the following options:
X.TP
X.B "\-h, \-q, \-?"
XDisplay usage message and exit.
X.TP
X.B "-v"
XDisplay verbose information about the current settings.
X.TP
X.B "-p"
XUse the mouse (pointer) button to control the wasp.  This can be turned on
Xand off at any time by pressing a button in the window.
X.TP
X.B "-r"
XUse root window.
X.TP
X.B "-V"
XStay in the clear area of the root window.  (Only useful with -r.)
X.TP
X.B "-x"
XUse xor raster operation so that the bees don't destroy the root bitmap.
X(Only useful with -r.)
X.TP
X.BI \-t " timeout"
XThis is the number of seconds of idle time to wait before clearing the
Xscreen.  The idle swarm disappears when a key is pressed or the mouse is
Xmoved.
X.TP
X.BI \-D " delay"
XThis is the non-blocking delay between frames. (in milliseconds)
X.TP
X.BI \-g " geometry"
Xlike -g 500x450+100+200
X.TP
X.BI \-d " host:display"
Xlike -d spacsun:0.0 or -d unix:0.0
X.TP
X.BI \-b " bees"
XThis is the number of bees that will be flying around.
X.TP
X.BI \-a " bee-acceleration"
XThis is measured in pixels per frame per frame. (try 2-10)
X.TP
X.BI \-s " bee-velocity"
XThis is measured in pixels per frame. (try 5-20)
X.TP
X.BI \-A " wasp-acceleration"
XThis is measured in pixels per frame per frame. (try 2-10)
X.TP
X.BI \-S " wasp-velocity"
XThis is measured in pixels per frame. (try 5-20)
X.TP
X.BI \-w " wasp-color"
XOne of the colors in .../lib/X11/rgb.txt or a color of the form #rrggbb in
Xhexadecimal.  For instance, #ef9595 is sort of a flesh tone.  r stands for red,
Xg stands for green, and b stands for blue.
X.TP
X.BI \-c " bee-color"
X.TP
X.BI \-C " background-color"
XIf you are using -x, then you may have to twiddle with this color in order
Xto get the bees to show up.  (-x works well with black and white)
X.SH EXAMPLES
XFor a swarm that doesn't stick so tightly to the wasp, try a larger
Xspeed limit for the bees, like this...
X.LP
Xxswarm -s 16
X.LP
XFor a wasp that gets away more often, give the wasp a higher speed limit
Xand better acceleration, like this...
X.LP
Xxswarm -A 7 -S 20
X.LP
XTo put the swarm in you background without harming your root bitmap,
Xdo this...
X.LP
Xxswarm -r -x -V
X.LP
XYou may need to fiddle with -w, -c, and -C to make the swarm visible...
X.LP
Xxswarm -r -x -V -w red -c blue -C green
X.LP
XTo speed up the swarm, decrease the delay between frames...
X.LP
Xxswarm -D 10  (Try taking control with the mouse button.)
X.LP
XTo use xswarm as a screen saver, put a line like this in your X startup
Xscript...
X.LP
Xxswarm -t 300 -w red -c blue
X.LP
X.SH BUGS
XI still haven't gotten backing store to work perfectly in the root window
Xwith the xor raster operation.  Occasionally, the swarm leaves a semi-permanent
Xmark on the root window.  If anyone is interested in fixing up any part of
Xxswarm, then please feel free, but I would like a copy of the changes.
X.LP
XPlease let me know if you have any problems with the screen saver
Xfeature.  It seems to work just fine on the Sun-4's that I use, but it
Xoccasionally flakes out on the DecStation 3100's.
X.SH MISCELLANEOUS RAMBLINGS
XImplementing the screen saver feature took alot of thinking.  I would be
X.I VERY
Xinterested in hearing of any other schemes for detecting user inactivity.
XThe way I did it seems a little messy to me, but here it is.  Initially,
XI traverse the entire window hierarchy.  As I get to each window, I do an
XXSelectInput() on it.  Then when I want to watch for user activity, I
Xincrement a timer and check for events.  If there are any events, then I
Xzero the timer.  If the timer exceeds whatever the timeout is, then I toss
Xup the screen saver window.  Does anyone have better ideas on how to watch
Xfor user activity in ALL windows other than the way I described?
X.LP
XI admit that I've gotten many ideas from public domain software, but I've
Xtried to give credit to the original authors at least in the documentation.
XIf you use any part of xswarm or the swarm animation algorithm, then please
Xinclude my name in your man page/documentation somewhere.
X.SH AUTHOR
XXswarm's author is Jeff Butterworth (butterwo@cs.unc.edu).
X.LP
XLooking at the source code to
X.I psychoII
Xhelped me learn how to open a window.
XTaking over the screen was surprisingly simple once I looked at the source
Xcode for
X.I meltdown
Xwritten by Dave Lemke (lemke@ncd.com).
XThe following people have helped immensely with bug fixes and suggestions:
X.TP
X.nf
X\ \ 
XDavid Elliott: tips for SYSV nap() and the sizehints structure
XKarl Fox: improved the backing store problem
XArne Helme: fixed "nap" function for HP machines
XCasey Leedom: supplied a simple imakefile and man page
XRob Nelson: added correct resizing
XAndreas ?Stolcke?: fixed -g option, added virtual root
XBill Trost: explained the race condition in nap(), added mouse control
XJon Webb: bouncing against windows while in the root window
X.fi
END_OF_FILE
if test 6831 -ne `wc -c <'xswarm.6'`; then
    echo shar: \"'xswarm.6'\" unpacked with wrong size!
fi
# end of 'xswarm.6'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(927 characters\)
sed "s/^X//" >'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's, DECStation 3100's,
Xand DECStation 5000's.
X
XThe only thing you will probably have to change in the Makefile is the
Xlocation of X include files.
X
XTry xswarm -h for help.  Fiddle with the parameters.  You can get really
Xdifferent effects!
X
X
XJeff Butterworth
X
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
X
END_OF_FILE
if test 927 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
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.