-
-/*
-
- * Original Author Unknow.
-
- * 8/10/88 - Ported from X10 to X11R3 by:
-
- Jonathan Greenblatt (jonnyg@rover.umd.edu)
-
- * Cleaned up by Dave Lemke (lemke@sun.com)
-
- * Ported to monocrome by Jonathan Greenblatt (jonnyg@rover.umd.edu)
-
- * 05/02/1996 Added TrueColor support by TJ Phan (phan@aur.alcatel.com)
-
- TODO:
-
- Parameter parsing needs to be redone.
-
- * Throughout 1991 improved for animation and color and multiple
- fish types. Broke monocrome in the process.
- Eric Bina (ebina@ncsa.uiuc.edu)
-
- * 1992 added extra color remapping control options, as well as ways
- to let the fish swim on the root window, or an image of the users
- choice. Eric Bina (ebina@ncsa.uiuc.edu)
-
-*/
-
-#include <sys/types.h>
-#ifndef hpux
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#ifdef sgi
-#define _BSD_SIGNALS
-#endif
-#include <signal.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <Imlib2.h>
-
-#include "vroot.h"
-#include "xfishy.h"
-#include "bubbles.h"
-#include "medcut.h"
-
-/* constants are based on rand(3C) returning an integer between 0 and 32767 */
-
-#if defined(ultrix) || defined(sun) || defined(linux)
-#define RAND_I_1_16 134217728
-#define RAND_F_1_8 268435455.875
-#define RAND_I_1_4 536870911
-#define RAND_I_1_2 1073741823
-#define RAND_I_3_4 1610612735
-#define RAND_F_MAX 2147483647.0
-#elif defined(__FreeBSD__) || defined(__OpenBSD__)
-#define RAND_I_1_16 (RAND_MAX>>4)
-#define RAND_F_1_8 ((float)(RAND_MAX>>3))
-#define RAND_I_1_4 (RAND_MAX>>2)
-#define RAND_I_1_2 (RAND_MAX>>1)
-#define RAND_I_3_4 ((RAND_MAX>>2)*3)
-#define RAND_F_MAX ((float)RAND_MAX)
-#else
-#define RAND_I_1_16 2048
-#define RAND_F_1_8 4096.0
-#define RAND_I_1_4 8096
-#define RAND_I_1_2 16384
-#define RAND_I_3_4 24575
-#define RAND_F_MAX 32767.0
-#endif
-
-
-extern unsigned char *ReadBitmap();
-
-
-/* externals for pixmap and bimaps from xfishy.h */
-
-
-/* typedefs for bubble and fish structures, also caddr_t (not used in X.h) */
-typedef struct {
- int x, y, s, erased, i;
-} bubble;
-typedef struct {
- int x, y, d, frame, type, i;
-} fish;
-typedef unsigned char *caddrt;
-
-
-/* bubble increment and yes check tables */
-int binc[] = { 0, 64, 56, 48, 40, 32, 24, 16, 8 };
-char *yess[] = { "yes", "Yes", "YES", "on", "On", "ON" };
-
-
-char *pname, /* program name from argv[0] */
- sname[64], /* host:display specification */
- cname[64]; /* colorname specification */
-char picname[256]; /* name of the background picture file */
-int *Allocated; /* mark the used colors */
-int AllocCnt; /* count number of colors used */
-int mlimit = 0; /* num colors to median cut to. 0 = no limit */
-int climit = 0; /* limit on color use. 0 = no limit */
-int DoubleBuf = 0; /* Should we use double buffering */
-int Overlap = 0; /* Should fish swim over each other */
-int DoClipping = 0; /* Should clip masks be used. */
-int blimit = 32, /* bubble limit */
- flimit = 10, /* fish limit */
- pmode = 1, /* pop mode, (1 for lower, 0 for raise) */
- width, /* width of initial window in pixels */
- height, /* height of initial window in pixels */
- screen, /* Default screen of this display */
- Init_B, *cmap; /* Initialize bubbles with random y value */
-int Pwidth; /* width of background picture */
-int Pheight; /* height of background picture */
-int Pcnt; /* number of colors in background picture */
-unsigned char *Pdata; /* data from background picture */
-double rate = 0.2, /* update interval in seconds */
- smooth = 0.2; /* smoothness increment multiplier */
-bubble *binfo; /* bubble info structures, allocated
- * dynamically */
-fish *finfo; /* fish info structures, allocated dynamically */
-Display *Dpy;
-Window root_window;
-XImage *xfishA[NUM_FISH][3]; /* fish pixmaps (1 is left-fish, 2 is
- * right-fish) */
-XImage *xfishB[NUM_FISH][3]; /* fish pixmaps (1 is left-fish, 2 is
- * right-fish) */
-Pixmap pfishA[NUM_FISH][3];
-Pixmap pfishB[NUM_FISH][3];
-
-Pixmap mfishA[NUM_FISH][3]; /* masking pixmaps for fish to use as */
-Pixmap mfishB[NUM_FISH][3]; /* clipmasks */
-
-Pixmap PicMap; /* pixmap for background picture */
-
-Pixmap PixBuf; /* Pixmap buffer for double buffering */
-Pixmap ClipBuf; /* Clipmask buffer for double buffering */
-
-Pixmap xbubbles[9]; /* bubbles bitmaps (1 to 8, by size in pixels) */
-Window wid; /* aqaurium window */
-unsigned long white, black, bcolor;
-Colormap colormap;
-GC c0gc, cpgc; /* GCs to operateon the Clipmask buffer */
-GC pgc;
-GC gc, bgc;
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-Output desired error message and exit.
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-void
-msgdie(message)
-char *message;
-{
- fprintf(stderr, "%s: %s\n", pname, message);
- exit(1);
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-Set up program defaults, get X defaults, parse command line using getopts.
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-void
-parse(argc, argv)
-int argc;
-char **argv;
-{
- int c;
- const char *display = getenv("DISPLAY");
- extern int optind;
- extern char *optarg;
- extern double atof();
-
- pname = argv[0];
- if (display != NULL)
- strncpy(sname, display, sizeof(sname) - 1);
- strcpy(cname, "MediumAquamarine");
-
- while ((c = getopt(argc, argv, "dDob:C:c:p:m:f:i:r:s")) != EOF) {
- switch (c) {
- case 'd':
- DoClipping = 1;
- break;
- case 'D':
- DoubleBuf = 1;
- break;
- case 'o':
- Overlap = 1;
- break;
- case 'b':
- blimit = atoi(optarg);
- break;
- case 'C':
- climit = atoi(optarg);
- break;
- case 'm':
- mlimit = atoi(optarg);
- break;
- case 'c':
- strncpy(cname, optarg, sizeof(cname) - 1);
- break;
- case 'p':
- strncpy(picname, optarg, sizeof(picname) - 1);
- break;
- case 'f':
- flimit = atoi(optarg);
- break;
- case 'i':
- smooth = atof(optarg);
- break;
- case 'r':
- rate = atof(optarg);
- break;
- case 's':
- pmode = 0;
- break;
- case '?':
- fprintf(stderr, "usage: %s\n", pname);
- fprintf(stderr, "\t\t[-c color] background color\n");
- fprintf(stderr, "\t\t[-b limit] number of bubbles (default 32)\n");
- fprintf(stderr, "\t\t[-f limit] number of fish (default 10)\n");
- fprintf(stderr, "\t\t[-i mult] move interval (default 0.2)\n");
- fprintf(stderr, "\t\t[-r rate] move frequency (default 0.2)\n");
- fprintf(stderr, "\t\t[-m num] median cut to this many colors\n");
- fprintf(stderr, "\t\t[-C num] use only this many color cells\n");
- fprintf(stderr, "\t\t[-d] clip fish, swim on root window\n");
- fprintf(stderr, "\t\t[-p file] fish swim on picture in file\n");
- fprintf(stderr, "\t\t[host:display]\n");
- exit(1);
- }
- }
-
- if (optind < argc) {
- char *display;
-
- strncpy(sname, argv[optind], sizeof(sname) - 1);
- display = (char *) malloc(strlen(sname) + 9);
- snprintf(display, sizeof(display) - 1, "DISPLAY=%s", sname);
- putenv(display);
- }
-}
-
-
-void
-erasefish(f, x, y, d)
-fish *f;
-int x, y, d;
-{
- /*
- * for something as small as a bubble, it was never worth the
- * effort of using clipmasks to only turn of the bubble itself, so
- * we just clear the whole rectangle.
- */
- XClearArea(Dpy, wid, x, y, rwidth[f->type], rheight[f->type], False);
-#if 0
- XGCValues gcv;
-
- if (f->frame) {
- gcv.foreground = cmap[0];
- gcv.fill_style = FillTiled;
- gcv.fill_style = FillSolid;
- gcv.tile = pfishB[f->type][d];
- gcv.ts_x_origin = f->x;
- gcv.ts_y_origin = f->y;
- gcv.clip_mask = mfishB[f->type][d];
- gcv.clip_x_origin = x;
- gcv.clip_y_origin = y;
- XChangeGC(Dpy, gc, GCForeground | GCClipMask |
- GCTile | GCTileStipXOrigin | GCTileStipYOrigin |
- GCFillStyle | GCClipXOrigin | GCClipYOrigin, &gcv);
- XCopyPlane(Dpy, mfishB[f->type][d], wid, gc, 0, 0,
- rwidth[f->type], rheight[f->type], x, y, (unsigned long) 1);
- } else {
- gcv.foreground = cmap[0];
- gcv.fill_style = FillTiled;
- gcv.fill_style = FillSolid;
- gcv.tile = pfishA[f->type][d];
- gcv.ts_x_origin = f->x;
- gcv.ts_y_origin = f->y;
- gcv.clip_mask = mfishA[f->type][d];
- gcv.clip_x_origin = x;
- gcv.clip_y_origin = y;
- XChangeGC(Dpy, gc, GCForeground | GCClipMask |
- GCTile | GCTileStipXOrigin | GCTileStipYOrigin |
- GCFillStyle | GCClipXOrigin | GCClipYOrigin, &gcv);
- XCopyPlane(Dpy, mfishA[f->type][d], wid, gc, 0, 0,
- rwidth[f->type], rheight[f->type], x, y, (unsigned long) 1);
- }
-#endif
-}
-
-
-/*
- * Just places a fish. Normally this is all you need for animation, since
- * placeing the fish places an entire rectangle which erases most of the old
- * fish (the rest being cleaned up by the function that called putfish.
- * If DoClipping is set, this function is only called when placing a new
- * fish, otherwise newfish is called.
- */
-void
-putfish(f)
-fish *f;
-{
- XGCValues gcv;
-
- if (f->frame) {
- /*
- * If we have a pixmap of the fish use it, otherwise use
- * the XImage of the fish. In reality we will never use
- * the XImage since X dies if the pixmap create failed
- */
- if (pfishA[f->type][f->d]) {
- /*
- * Clipping overrides background picture because
- * the clipping prevents the drawing of any background
- * anyway.
- * DoClipping says just print a fish leaving the
- * background unchanged.
- * If there is a background picture, we use a buffer
- * to prevent flashing, we combine the background
- * picture and the fish, and then copy the
- * whole rectangle in.
- * Default is just copy in fish in with a background
- * color.
- */
- if (DoClipping) {
- gcv.clip_mask = mfishA[f->type][f->d];
- gcv.clip_x_origin = f->x;
- gcv.clip_y_origin = f->y;
- XChangeGC(Dpy, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
- XCopyArea(Dpy, pfishA[f->type][f->d], wid, gc,
- 0, 0, rwidth[f->type], rheight[f->type], f->x, f->y);
- } else if (picname[0] != '\0') {
- gcv.fill_style = FillTiled;
- gcv.tile = PicMap;
- gcv.ts_x_origin = -(f->x);
- gcv.ts_y_origin = -(f->y);
- gcv.clip_mask = None;
- XChangeGC(Dpy, pgc, (GCFillStyle |
- GCTile | GCTileStipXOrigin |
- GCTileStipYOrigin | GCClipMask), &gcv);
- XFillRectangle(Dpy, PixBuf, pgc, 0, 0, rwidth[f->type], rheight[f->type]);
-
- gcv.clip_mask = mfishA[f->type][f->d];
- gcv.clip_x_origin = 0;
- gcv.clip_y_origin = 0;
- XChangeGC(Dpy, pgc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
- XCopyArea(Dpy, pfishA[f->type][f->d], PixBuf, pgc,
- 0, 0, rwidth[f->type], rheight[f->type], 0, 0);
-
- XCopyArea(Dpy, PixBuf, wid, gc,
- 0, 0, rwidth[f->type], rheight[f->type], f->x, f->y);
- } else {
- XCopyArea(Dpy, pfishA[f->type][f->d], wid, gc,
- 0, 0, rwidth[f->type], rheight[f->type], f->x, f->y);
- }
- } else {
- XPutImage(Dpy, wid, gc, xfishA[f->type][f->d], 0, 0,
- f->x, f->y, rwidth[f->type], rheight[f->type]);
- }
- f->frame = 0;
- } else {
- /*
- * same as the above, only for the second frame of animation
- */
- if (pfishB[f->type][f->d]) {
- if (DoClipping) {
- gcv.clip_mask = mfishB[f->type][f->d];
- gcv.clip_x_origin = f->x;
- gcv.clip_y_origin = f->y;
- XChangeGC(Dpy, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
- XCopyArea(Dpy, pfishB[f->type][f->d], wid, gc,
- 0, 0, rwidth[f->type], rheight[f->type], f->x, f->y);
- } else if (picname[0] != '\0') {
- gcv.fill_style = FillTiled;
- gcv.tile = PicMap;
- gcv.ts_x_origin = -(f->x);
- gcv.ts_y_origin = -(f->y);
- gcv.clip_mask = None;
- XChangeGC(Dpy, pgc, (GCFillStyle |
- GCTile | GCTileStipXOrigin |
- GCTileStipYOrigin | GCClipMask), &gcv);
- XFillRectangle(Dpy, PixBuf, pgc, 0, 0, rwidth[f->type], rheight[f->type]);
-
- gcv.clip_mask = mfishB[f->type][f->d];
- gcv.clip_x_origin = 0;
- gcv.clip_y_origin = 0;
- XChangeGC(Dpy, pgc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
- XCopyArea(Dpy, pfishB[f->type][f->d], PixBuf, pgc,
- 0, 0, rwidth[f->type], rheight[f->type], 0, 0);
-
- XCopyArea(Dpy, PixBuf, wid, gc,
- 0, 0, rwidth[f->type], rheight[f->type], f->x, f->y);
- } else {
- XCopyArea(Dpy, pfishB[f->type][f->d], wid, gc,
- 0, 0, rwidth[f->type], rheight[f->type], f->x, f->y);
- }
- } else {
- XPutImage(Dpy, wid, gc, xfishB[f->type][f->d], 0, 0,
- f->x, f->y, rwidth[f->type], rheight[f->type]);
- }
- f->frame = 1;
- }
-}
-
-
-/*
- * This function can only be called if DoClipping is True. It is used to
- * move a clipmasked fish. First the area under the fish is cleared,
- * and then the new fish is masked in.
- * The parameters x, y, amd d are from the old fish that is being
- * erased before the new fish is drawn.
- */
-void
-movefish(f, x, y, d)
-fish *f;
-int x, y, d;
-{
- XGCValues gcv;
- int bx, by, bw, bh;
-
- /*
- * If we are going to double buffer, we need to find the bounding
- * rectangle of the overlap of the bounding rectangles of the old
- * and the new fish.
- */
- if (DoubleBuf) {
- if (x < f->x) {
- bx = x;
- bw = f->x - x + rwidth[f->type];
- } else {
- bx = f->x;
- bw = x - f->x + rwidth[f->type];
- }
- if (y < f->y) {
- by = y;
- bh = f->y - y + rheight[f->type];
- } else {
- by = f->y;
- bh = y - f->y + rheight[f->type];
- }
- }
-
- if (f->frame) {
- /*
- * If there is a pixmap use it.
- * This branchis always taken since right now, if the pixmap
- * allocation failed, the program dies.
- */
- if (pfishA[f->type][f->d]) {
- /*
- * A pointless if, you now only come here if
- * DoClipping is set, I've just been too lazy to
- * clean up my code.
- */
- if (DoClipping) {
- /*
- * Set up the masked gc for when we eventually
- * draw the fish. Origin is different for
- * whether we are drawing into the buffer
- * or into the window
- */
- gcv.clip_mask = mfishA[f->type][f->d];
- if (DoubleBuf) {
- gcv.clip_x_origin = f->x - bx;
- gcv.clip_y_origin = f->y - by;
- } else {
- gcv.clip_x_origin = f->x;
- gcv.clip_y_origin = f->y;
- }
- XChangeGC(Dpy, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
-
- /*
- * If we have a background picture we want to
- * clear to that background, otherwise we just
- * do an XCleararea, and let the root restore
- * the background.
- */
- if (picname[0] != '\0') {
- gcv.fill_style = FillTiled;
- gcv.tile = PicMap;
- gcv.clip_mask = mfishB[f->type][d];
- if (DoubleBuf) {
- gcv.ts_x_origin = 0 - bx;
- gcv.ts_y_origin = 0 - by;
- gcv.clip_x_origin = x - bx;
- gcv.clip_y_origin = y - by;
- } else {
- gcv.ts_x_origin = 0;
- gcv.ts_y_origin = 0;
- gcv.clip_x_origin = x;
- gcv.clip_y_origin = y;
- }
- XChangeGC(Dpy, pgc, (GCFillStyle |
- GCTile | GCTileStipXOrigin |
- GCTileStipYOrigin | GCClipMask |
- GCClipXOrigin | GCClipYOrigin), &gcv);
-
- /*
- * if bouble buffering we clear the buffer
- * to the backgound picture, and then
- * shape the clip buffer to the shape of
- * the fish being erased.
- */
- if (DoubleBuf) {
- XFillRectangle(Dpy, PixBuf, pgc,
- x - bx, y - by, rwidth[f->type], rheight[f->type]);
- XFillRectangle(Dpy, ClipBuf, c0gc, 0, 0, 500, 500);
- XCopyArea(Dpy, mfishB[f->type][d],
- ClipBuf, cpgc, 0, 0,
- rwidth[f->type], rheight[f->type], x - bx, y - by);
- } else {
- XFillRectangle(Dpy, wid, pgc, x, y, rwidth[f->type], rheight[f->type]);
- }
- } else {
- XClearArea(Dpy, wid, x, y, rwidth[f->type], rheight[f->type], 0);
- }
- }
- /*
- * Now we just copy in the new fish with a clipmasked gc.
- * But if we doublebuffered, we copy the new fish into
- * the buffer, combine the new fishes clipmask in, and
- * then mask the whole lot from the buffer to the window.
- */
- if (DoubleBuf) {
- XCopyArea(Dpy, pfishA[f->type][f->d], PixBuf, gc, 0, 0,
- rwidth[f->type], rheight[f->type], f->x - bx, f->y - by);
- XCopyArea(Dpy, mfishA[f->type][f->d], ClipBuf, cpgc,
- 0, 0, rwidth[f->type], rheight[f->type], f->x - bx, f->y - by);
- gcv.clip_mask = ClipBuf;
- gcv.clip_x_origin = bx;
- gcv.clip_y_origin = by;
- XChangeGC(Dpy, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
- XCopyArea(Dpy, PixBuf, wid, gc, 0, 0, bw, bh, bx, by);
- } else {
- XCopyArea(Dpy, pfishA[f->type][f->d], wid, gc, 0, 0,
- rwidth[f->type], rheight[f->type], f->x, f->y);
- }
- } else {
- if (DoClipping) {
- if (picname[0] != '\0') {
- gcv.fill_style = FillTiled;
- gcv.tile = PicMap;
- gcv.ts_x_origin = 0;
- gcv.ts_y_origin = 0;
- gcv.clip_mask = mfishB[f->type][d];
- gcv.clip_x_origin = x;
- gcv.clip_y_origin = y;
- XChangeGC(Dpy, pgc, (GCFillStyle |
- GCTile | GCTileStipXOrigin |
- GCTileStipYOrigin | GCClipMask |
- GCClipXOrigin | GCClipYOrigin), &gcv);
- XFillRectangle(Dpy, wid, pgc, x, y, rwidth[f->type], rheight[f->type]);
- } else {
- XClearArea(Dpy, wid, x, y, rwidth[f->type], rheight[f->type], 0);
- }
- }
- XPutImage(Dpy, wid, gc, xfishA[f->type][f->d], 0, 0,
- f->x, f->y, rwidth[f->type], rheight[f->type]);
- }
- f->frame = 0;
- } else {
- /*
- * Same as above, only for the second frame of animation.
- */
- if (pfishB[f->type][f->d]) {
- if (DoClipping) {
- gcv.clip_mask = mfishB[f->type][f->d];
- if (DoubleBuf) {
- gcv.clip_x_origin = f->x - bx;
- gcv.clip_y_origin = f->y - by;
- } else {
- gcv.clip_x_origin = f->x;
- gcv.clip_y_origin = f->y;
- }
- XChangeGC(Dpy, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
- if (picname[0] != '\0') {
- gcv.fill_style = FillTiled;
- gcv.tile = PicMap;
- gcv.clip_mask = mfishA[f->type][d];
- if (DoubleBuf) {
- gcv.ts_x_origin = 0 - bx;
- gcv.ts_y_origin = 0 - by;
- gcv.clip_x_origin = x - bx;
- gcv.clip_y_origin = y - by;
- } else {
- gcv.ts_x_origin = 0;
- gcv.ts_y_origin = 0;
- gcv.clip_x_origin = x;
- gcv.clip_y_origin = y;
- }
- XChangeGC(Dpy, pgc, (GCFillStyle |
- GCTile | GCTileStipXOrigin |
- GCTileStipYOrigin | GCClipMask |
- GCClipXOrigin | GCClipYOrigin), &gcv);
- if (DoubleBuf) {
- XFillRectangle(Dpy, PixBuf, pgc,
- x - bx, y - by, rwidth[f->type], rheight[f->type]);
- XFillRectangle(Dpy, ClipBuf, c0gc, 0, 0, 500, 500);
- XCopyArea(Dpy, mfishA[f->type][d],
- ClipBuf, cpgc, 0, 0,
- rwidth[f->type], rheight[f->type], x - bx, y - by);
- } else {
- XFillRectangle(Dpy, wid, pgc, x, y, rwidth[f->type], rheight[f->type]);
- }
- } else {
- XClearArea(Dpy, wid, x, y, rwidth[f->type], rheight[f->type], 0);
- }
- }
- if (DoubleBuf) {
- XCopyArea(Dpy, pfishB[f->type][f->d], PixBuf, gc, 0, 0,
- rwidth[f->type], rheight[f->type], f->x - bx, f->y - by);
- XCopyArea(Dpy, mfishB[f->type][f->d], ClipBuf, cpgc,
- 0, 0, rwidth[f->type], rheight[f->type], f->x - bx, f->y - by);
- gcv.clip_mask = ClipBuf;
- gcv.clip_x_origin = bx;
- gcv.clip_y_origin = by;
- XChangeGC(Dpy, gc, GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
- XCopyArea(Dpy, PixBuf, wid, gc, 0, 0, bw, bh, bx, by);
- } else {
- XCopyArea(Dpy, pfishB[f->type][f->d], wid, gc, 0, 0,
- rwidth[f->type], rheight[f->type], f->x, f->y);
- }
- } else {
- if (DoClipping) {
- if (picname[0] != '\0') {
- gcv.fill_style = FillTiled;
- gcv.tile = PicMap;
- gcv.ts_x_origin = 0;
- gcv.ts_y_origin = 0;
- gcv.clip_mask = mfishA[f->type][d];
- gcv.clip_x_origin = x;
- gcv.clip_y_origin = y;
- XChangeGC(Dpy, pgc, (GCFillStyle |
- GCTile | GCTileStipXOrigin |
- GCTileStipYOrigin | GCClipMask |
- GCClipXOrigin | GCClipYOrigin), &gcv);
- XFillRectangle(Dpy, wid, pgc, x, y, rwidth[f->type], rheight[f->type]);
- } else {
- XClearArea(Dpy, wid, x, y, rwidth[f->type], rheight[f->type], 0);
- }
- }
- XPutImage(Dpy, wid, gc, xfishB[f->type][f->d], 0, 0,
- f->x, f->y, rwidth[f->type], rheight[f->type]);
- }
- f->frame = 1;
- }
-}
-
-
-void
-erasebubble(b, s)
-bubble *b;
-int s;
-{
- XClearArea(Dpy, wid, b->x, b->y, s, s, 0);
-}
-
-
-void
-putbubble(b, s, c)
-bubble *b;
-int s;
-unsigned long c;
-{
- XGCValues gcv;
-
- gcv.foreground = c;
- gcv.clip_mask = xbubbles[s];
- gcv.clip_x_origin = b->x;
- gcv.clip_y_origin = b->y;
- XChangeGC(Dpy, bgc, GCForeground | GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcv);
- XFillRectangle(Dpy, wid, bgc, b->x, b->y, s, s);
-}
-
-
-/*
- * Find the closest color by allocating it, or picking an already allocated
- * color
- */
-Visual(*visual_info) = NULL;
-int r_mask, g_mask, b_mask;
-int r_shift = 0, g_shift = 0, b_shift = 0;
-int r_bits = 0, g_bits = 0, b_bits = 0;
-void
-FindColor(Dpy, colormap, colr)
-Display *Dpy;
-Colormap colormap;
-XColor *colr;
-{
- int i, match;
- double rd, gd, bd, dist, mindist;
- int cindx;
- XColor def_colrs[256];
- int NumCells;
-
- if (visual_info == NULL && DefaultDepth(Dpy, DefaultScreen(Dpy)) > 8) {
- visual_info = DefaultVisual(Dpy, DefaultScreen(Dpy));
- r_mask = visual_info->red_mask;
- while (!(r_mask & 1)) {
- r_mask >>= 1;
- r_shift++;
- }
- while (r_mask & 1) {
- r_mask >>= 1;
- r_bits++;
- }
-
- g_mask = visual_info->green_mask;
- while (!(g_mask & 1)) {
- g_mask >>= 1;
- g_shift++;
- }
- while (g_mask & 1) {
- g_mask >>= 1;
- g_bits++;
- }
-
- b_mask = visual_info->blue_mask;
- while (!(b_mask & 1)) {
- b_mask >>= 1;
- b_shift++;
- }
- while (b_mask & 1) {
- b_mask >>= 1;
- b_bits++;
- }
- }
-
- if (DefaultDepth(Dpy, DefaultScreen(Dpy)) > 8) {
- colr->red >>= 16 - r_bits;
- colr->green >>= 16 - g_bits;
- colr->blue >>= 16 - b_bits;
-
- colr->pixel = ((colr->red << r_shift) & visual_info->red_mask) |
- ((colr->green << g_shift) & visual_info->green_mask) |
- ((colr->blue << b_shift) & visual_info->blue_mask);
- return;
- }
-
- if (AllocCnt < climit) {
- match = XAllocColor(Dpy, colormap, colr);
- } else {
- match = 0;
- }
- if (match == 0) {
- NumCells = DisplayCells(Dpy, DefaultScreen(Dpy));
- for (i = 0; i < NumCells; i++) {
- def_colrs[i].pixel = i;
- }
- XQueryColors(Dpy, colormap, def_colrs, NumCells);
- mindist = 65536.0 * 65536.0;
- cindx = colr->pixel;
- for (i = 0; i < NumCells; i++) {
- rd = (def_colrs[i].red - colr->red) / 256.0;
- gd = (def_colrs[i].green - colr->green) / 256.0;
- bd = (def_colrs[i].blue - colr->blue) / 256.0;
- dist = (rd * rd * rd * rd) + (gd * gd * gd * gd) + (bd * bd * bd * bd);
- if (dist < mindist) {
- mindist = dist;
- cindx = def_colrs[i].pixel;
- }
- }
- colr->pixel = cindx;
- colr->red = def_colrs[cindx].red;
- colr->green = def_colrs[cindx].green;
- colr->blue = def_colrs[cindx].blue;
- } else {
- if (Allocated[colr->pixel] == 0) {
- Allocated[colr->pixel] = 1;
- AllocCnt++;
- }
- }
-}
-
-
-int
-ColorUsage(data, width, height, colrs)
-unsigned char *data;
-int width, height;
-struct colr_data *colrs;
-{
- int mapping[256];
- int i, size;
- int cnt, indx;
- unsigned char *ptr;
- struct colr_data newcol[256];
-
- for (i = 0; i < 256; i++) {
- mapping[i] = -1;
- }
-
- size = width * height;
- cnt = 0;
- ptr = data;
- for (i = 0; i < size; i++) {
- indx = (int) *ptr;
- if (mapping[indx] == -1) {
- mapping[indx] = cnt;
- newcol[cnt].red = colrs[indx].red;
- newcol[cnt].green = colrs[indx].green;
- newcol[cnt].blue = colrs[indx].blue;
- cnt++;
- }
- ptr++;
- }
-
- ptr = data;
- for (i = 0; i < size; i++) {
- indx = (int) *ptr;
- *ptr = (unsigned char) mapping[indx];
- ptr++;
- }
-
- for (i = 0; i < cnt; i++) {
- colrs[i].red = newcol[i].red;
- colrs[i].green = newcol[i].green;
- colrs[i].blue = newcol[i].blue;
- }
- for (i = cnt; i < 256; i++) {
- colrs[i].red = 0;
- colrs[i].green = 0;
- colrs[i].blue = 0;
- }
-
- return (cnt);
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-Initialize colormap for background color and required fish colors.
-The fish colors are coded in xfishy.h as a trio of tables.
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-void
-init_colormap()
-{
- int i, j, cnt;
- int NumCells;
- XColor hdef, edef;
- struct colr_data *cdp;
- struct colr_data colrs[256];
-
- colormap = XDefaultColormap(Dpy, screen);
-
- NumCells = DisplayCells(Dpy, DefaultScreen(Dpy));
- Allocated = (int *) malloc(NumCells * sizeof(int));
- for (i = 0; i < NumCells; i++) {
- Allocated[i] = 0;
- }
- AllocCnt = 0;
- if ((climit <= 0) || (climit > NumCells)) {
- climit = NumCells;
- }
-
- Pcnt = 0;
- if (picname[0] != '\0') {
- Imlib_Image image = imlib_load_image(picname);
- if (image == NULL) {
- fprintf(stderr, "Cannot load image %s\n", picname);
- picname[0] = 0;
- } else {
- imlib_context_set_image(image);
- imlib_context_set_display(Dpy);
- imlib_context_set_visual(DefaultVisual(Dpy, screen));
- Pwidth = imlib_image_get_width();
- Pheight = imlib_image_get_height();
- DATA32 *image_data = imlib_image_get_data_for_reading_only();
- Pdata = malloc(4 * Pwidth * Pheight);
- for (i = 0; i < Pwidth * Pheight; i++) {
- Pdata[4 * i] = image_data[i] & 0xFF;
- Pdata[4 * i + 1] = image_data[i] & 0xFF00;
- Pdata[4 * i + 2] = image_data[i] & 0xFF0000;
- Pdata[4 * i + 3] = image_data[i] & 0xFF000000;
- }
- Pcnt = ColorUsage(Pdata, Pwidth, Pheight, colrs);
- }
- }
-
- cnt = 0;
- cnt += Pcnt;
- for (i = 0; i < NUM_FISH; i++) {
- cnt += rcolors[i];
- }
- cmap = (int *) malloc((cnt + 1) * sizeof(int));
-
- XLookupColor(Dpy, colormap, cname, &hdef, &edef);
- hdef.flags = DoRed | DoGreen | DoBlue;
- FindColor(Dpy, colormap, &hdef);
- cmap[0] = hdef.pixel;
-
- if (mlimit > 0) {
- MedianInit();
- }
-
- if (mlimit > 0) {
- if (picname[0] != '\0') {
- MedianCount(Pdata, Pwidth, Pheight, colrs);
- }
- for (j = 0; j < NUM_FISH; j++) {
- int *rp, *gp, *bp;
-
- cdp = (struct colr_data *) malloc(rcolors[j] * sizeof(struct colr_data));
- rp = rreds[j];
- gp = rgreens[j];
- bp = rblues[j];
- for (i = 0; i < rcolors[j]; i++) {
- cdp[i].red = *rp++;
- cdp[i].green = *gp++;
- cdp[i].blue = *bp++;
- }
- MedianCount((unsigned char *) xfishRasterA[j],
- (int) rwidth[j], (int) rheight[j], cdp);
- free((char *) cdp);
- }
- MedianSplit(mlimit);
- }
-
- cnt = 1;
- if (picname[0] != '\0') {
- for (i = 0; i < Pcnt; i++) {
- int rv, gv, bv;
-
- rv = colrs[i].red;
- gv = colrs[i].green;
- bv = colrs[i].blue;
-
- if (mlimit > 0) {
- ConvertColor(&rv, &gv, &bv);
- }
-
- hdef.red = rv;
- hdef.green = gv;
- hdef.blue = bv;
- hdef.flags = DoRed | DoGreen | DoBlue;
- FindColor(Dpy, colormap, &hdef);
- cmap[cnt] = hdef.pixel;
- cnt++;
- }
- }
- for (j = 0; j < NUM_FISH; j++) {
- int *rp, *gp, *bp;
-
- rp = rreds[j];
- gp = rgreens[j];
- bp = rblues[j];
- for (i = 0; i < rcolors[j]; i++) {
- int rv, gv, bv;
-
- rv = *rp++;
- gv = *gp++;
- bv = *bp++;
-
- if (mlimit > 0) {
- ConvertColor(&rv, &gv, &bv);
- }
-
- hdef.red = rv;
- hdef.green = gv;
- hdef.blue = bv;
- hdef.flags = DoRed | DoGreen | DoBlue;
- FindColor(Dpy, colormap, &hdef);
- cmap[cnt] = hdef.pixel;
- if (i == rback[j]) {
- cmap[cnt] = cmap[0];
- }
- cnt++;
- }
- }
-
- bcolor = white;
-}
-
-
-/*
- * Make am image of appropriate depth for display from image data.
- */
-XImage *
-MakeImage(data, width, height)
-unsigned char *data;
-int width, height;
-{
- int linepad, shiftnum;
- int shiftstart, shiftstop, shiftinc;
- int bytesperline;
- int depth, temp;
- int w, h;
- XImage *newimage;
- unsigned char *bit_data, *bitp, *datap;
-
- depth = DefaultDepth(Dpy, DefaultScreen(Dpy));
- if ((depth != 1) && (depth != 2) && (depth != 4) && (depth != 8)) {
- fprintf(stderr, "Don't know how to format image for display of depth %d\n", depth);
- exit(1);
- }
-
- if (BitmapBitOrder(Dpy) == LSBFirst) {
- shiftstart = 0;
- shiftstop = 8;
- shiftinc = depth;
- } else {
- shiftstart = 8 - depth;
- shiftstop = -depth;
- shiftinc = -depth;
- }
- linepad = 8 - (width % 8);
- bit_data = (unsigned char *) malloc(((width + linepad) * height) + 1);
- bitp = bit_data;
- datap = data;
- *bitp = 0;
- shiftnum = shiftstart;
- for (h = 0; h < height; h++) {
- for (w = 0; w < width; w++) {
- temp = *datap++ << shiftnum;
- *bitp = *bitp | temp;
- shiftnum = shiftnum + shiftinc;
- if (shiftnum == shiftstop) {
- shiftnum = shiftstart;
- bitp++;
- *bitp = 0;
- }
- }
- for (w = 0; w < linepad; w++) {
- shiftnum = shiftnum + shiftinc;
- if (shiftnum == shiftstop) {
- shiftnum = shiftstart;
- bitp++;
- *bitp = 0;
- }
- }
- }
-
- bytesperline = (width * depth / 8 + linepad);
- newimage = XCreateImage(Dpy, DefaultVisual(Dpy, screen), depth,
- ZPixmap, 0, (char *) bit_data,
- (width + linepad), height, 8, bytesperline);
-
- return (newimage);
-}
-
-
-
-static unsigned char bits[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-Calibrate the pixmaps and bimaps. The right-fish data is coded in xfishy.h,
-this is transformed to create the left-fish. The eight bubbles are coded
-in bubbles.h as a two dimensional array.
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-void
-init_pixmap()
-{
- register caddrt p, q, x1A, x1B, x2A, x2B;
- unsigned char *data;
- register int i, j, k;
- int cnt, wcnt;
-
- cnt = 1;
- cnt += Pcnt;
- for (k = 0; k < NUM_FISH; k++) {
-
- /*
- * The clipmasks must be created before we remap colors.
- * otherwise an opaque color might get remapped to a
- * transparent color.
- */
- if ((DoClipping) || (picname[0] != '\0')) {
- data = (unsigned char *) malloc((rwidth[k] + 7) / 8 * rheight[k]);
-
- p = (caddrt) xfishRasterA[k];
- q = data;
- wcnt = 0;
- for (i = 0; i < ((rwidth[k] + 7) / 8 * rheight[k]); i++) {
- unsigned char bt = 0x00;
- for (j = 0; j < 8; j++) {
- if (*p != rback[k]) {
- bt = bt | bits[j];
- }
- wcnt++;
- p++;
- if (wcnt == rwidth[k]) {
- wcnt = 0;
- break;
- }
- }
- *q++ = bt;
- }
- mfishA[k][2] = XCreateBitmapFromData(Dpy, wid,
- (char *) data, rwidth[k], rheight[k]);
-
- p = (caddrt) xfishRasterA[k];
- p = p + rwidth[k] - 1;
- q = data;
- wcnt = 0;
- for (i = 0; i < ((rwidth[k] + 7) / 8 * rheight[k]); i++) {
- unsigned char bt = 0x00;
- for (j = 0; j < 8; j++) {
- if (*p != rback[k]) {
- bt = bt | bits[j];
- }
- wcnt++;
- p--;
- if (wcnt == rwidth[k]) {
- wcnt = 0;
- p = p + (2 * rwidth[k]);
- break;
- }
- }
- *q++ = bt;
- }
- mfishA[k][1] = XCreateBitmapFromData(Dpy, wid,
- (char *) data, rwidth[k], rheight[k]);
-
- p = (caddrt) xfishRasterB[k];
- q = data;
- wcnt = 0;
- for (i = 0; i < ((rwidth[k] + 7) / 8 * rheight[k]); i++) {
- unsigned char bt = 0x00;
- for (j = 0; j < 8; j++) {
- if (*p != rback[k]) {
- bt = bt | bits[j];
- }
- wcnt++;
- p++;
- if (wcnt == rwidth[k]) {
- wcnt = 0;
- break;
- }
- }
- *q++ = bt;
- }
- mfishB[k][2] = XCreateBitmapFromData(Dpy, wid,
- (char *) data, rwidth[k], rheight[k]);
-
- p = (caddrt) xfishRasterB[k];
- p = p + rwidth[k] - 1;
- q = data;
- wcnt = 0;
- for (i = 0; i < ((rwidth[k] + 7) / 8 * rheight[k]); i++) {
- unsigned char bt = 0x00;
- for (j = 0; j < 8; j++) {
- if (*p != rback[k]) {
- bt = bt | bits[j];
- }
- wcnt++;
- p--;
- if (wcnt == rwidth[k]) {
- wcnt = 0;
- p = p + (2 * rwidth[k]);
- break;
- }
- }
- *q++ = bt;
- }
- mfishB[k][1] = XCreateBitmapFromData(Dpy, wid,
- (char *) data, rwidth[k], rheight[k]);
-
- free((char *) data);
- }
-
- if (DisplayPlanes(Dpy, screen) < 8) {
-
- j = rwidth[k] * rheight[k];
- x1A = (caddrt) malloc(rwidth[k] * rheight[k]);
- p = (caddrt) xfishRasterA[k];
-
-
- q = x1A;
- for (i = 0; i < j; i++) {
- *q = cmap[cnt + (int) (*p)];
- p++;
- q++;
- }
-
- x1B = (caddrt) malloc(rwidth[k] * rheight[k]);
- p = (caddrt) xfishRasterB[k];
- q = x1B;
- for (i = 0; i < j; i++) {
- *q = cmap[cnt + (int) (*p)];
- p++;
- q++;
- }
-
- x2A = (caddrt) malloc(rwidth[k] * rheight[k]);
- for (i = 0; i < rheight[k]; i++) {
- p = x1A + i * rwidth[k];
- q = x2A + (i + 1) * rwidth[k] - 1;
- for (j = 0; j < rwidth[k]; j++) {
- *q-- = *p++;
- }
- }
-
- x2B = (caddrt) malloc(rwidth[k] * rheight[k]);
- for (i = 0; i < rheight[k]; i++) {
- p = x1B + i * rwidth[k];
- q = x2B + (i + 1) * rwidth[k] - 1;
- for (j = 0; j < rwidth[k]; j++) {
- *q-- = *p++;
- }
- }
-
- xfishA[k][2] = MakeImage(x1A, rwidth[k], rheight[k]);
- xfishA[k][1] = MakeImage(x2A, rwidth[k], rheight[k]);
- xfishB[k][2] = MakeImage(x1B, rwidth[k], rheight[k]);
- xfishB[k][1] = MakeImage(x2B, rwidth[k], rheight[k]);
-
- free((char *) x1A);
- free((char *) x2A);
- free((char *) x1B);
- free((char *) x2B);
- } else {
- i = DisplayPlanes(Dpy, screen);
-
- xfishA[k][2] =
- XGetImage(Dpy, root_window, 0, 0, rwidth[k], rheight[k], 0, ZPixmap);
-
- p = (caddrt) xfishRasterA[k];
-
- for (j = 0; j < rheight[k]; j++) {
- for (i = 0; i < rwidth[k]; i++) {
- XPutPixel(xfishA[k][2], i, j, cmap[cnt + (int) (*p)]);
- p++;
- }
- }
-
- xfishB[k][2] =
- XGetImage(Dpy, root_window, 0, 0, rwidth[k], rheight[k], 0, ZPixmap);
-
- p = (caddrt) xfishRasterB[k];
-
- for (j = 0; j < rheight[k]; j++) {
- for (i = 0; i < rwidth[k]; i++) {
- XPutPixel(xfishB[k][2], i, j, cmap[cnt + (int) (*p)]);
- p++;
- }
- }
-
- xfishA[k][1] =
- XGetImage(Dpy, root_window, 0, 0, rwidth[k], rheight[k], 0, ZPixmap);
-
- for (j = 0; j < rheight[k]; j++) {
- for (i = 0; i < rwidth[k]; i++) {
- XPutPixel(xfishA[k][1], i, j,
- XGetPixel(xfishA[k][2], rwidth[k] - i - 1, j));
- }
- }
-
- xfishB[k][1] =
- XGetImage(Dpy, root_window, 0, 0, rwidth[k], rheight[k], 0, ZPixmap);
-
- for (j = 0; j < rheight[k]; j++) {
- for (i = 0; i < rwidth[k]; i++) {
- XPutPixel(xfishB[k][1], i, j,
- XGetPixel(xfishB[k][2], rwidth[k] - i - 1, j));
- }
- }
-
- }
-
-
- i = DisplayPlanes(Dpy, screen);
-
- pfishA[k][1] = XCreatePixmap(Dpy, wid, rwidth[k], rheight[k], i);
- pfishA[k][2] = XCreatePixmap(Dpy, wid, rwidth[k], rheight[k], i);
- pfishB[k][1] = XCreatePixmap(Dpy, wid, rwidth[k], rheight[k], i);
- pfishB[k][2] = XCreatePixmap(Dpy, wid, rwidth[k], rheight[k], i);
-
- if (pfishA[k][1]) {
- XPutImage(Dpy, pfishA[k][1], gc, xfishA[k][1], 0, 0, 0, 0, rwidth[k], rheight[k]);
- }
- if (pfishA[k][2]) {
- XPutImage(Dpy, pfishA[k][2], gc, xfishA[k][2], 0, 0, 0, 0, rwidth[k], rheight[k]);
- }
- if (pfishB[k][1]) {
- XPutImage(Dpy, pfishB[k][1], gc, xfishB[k][1], 0, 0, 0, 0, rwidth[k], rheight[k]);
- }
- if (pfishB[k][2]) {
- XPutImage(Dpy, pfishB[k][2], gc, xfishB[k][2], 0, 0, 0, 0, rwidth[k], rheight[k]);
- }
-
- cnt += rcolors[k];
- }
-
- for (i = 1; i <= 8; i++) {
- xbubbles[i] = XCreateBitmapFromData(Dpy, wid, (char *) xbBits[i], i, i);
- }
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-Toggle secure mode on receipt of signal
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-#ifdef sgi
-int
-#else
-void
-#endif
-toggle_secure()
-{
- pmode = !pmode;
- if (pmode)
- XLowerWindow(Dpy, wid);
- else
- XRaiseWindow(Dpy, wid);
- XFlush(Dpy);
-#ifdef sgi
- return (1);
-#endif
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-Initialize signal so that SIGUSR1 causes secure mode to toggle.
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-void
-init_signals()
-{
-#if defined(linux)
- signal(SIGUSR1, toggle_secure);
-#elif defined(MOTOROLA) || defined(SCO)
- sigset(SIGUSR1, toggle_secure);
-#else
- struct sigvec vec;
-
- vec.sv_handler = toggle_secure;
- vec.sv_mask = 0;
- vec.sv_onstack = 0;
-
-#ifndef hpux
- sigvec(SIGUSR1, &vec, &vec);
-#else
- sigvector(SIGUSR1, &vec, &vec);
-#endif
-#endif
-}
-
-
-void
-set_window_type_desktop(Display *dpy, Window wid)
-{
- Atom _NET_WM_WINDOW_TYPE, _NET_WM_WINDOW_TYPE_DESKTOP;
-
- _NET_WM_WINDOW_TYPE = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
- _NET_WM_WINDOW_TYPE_DESKTOP = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", False);
-
- XChangeProperty(dpy, wid, _NET_WM_WINDOW_TYPE, XA_ATOM, 32,
- PropModeReplace, (unsigned char *) &_NET_WM_WINDOW_TYPE_DESKTOP, 1);
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-Variety of initialization calls, including getting the window up and running.
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-void
-initialize()
-{
- XWindowAttributes winfo;
- XSetWindowAttributes attr;
- XGCValues vals;
- XSizeHints xsh;
- int i;
- char *p;
-
- root_window = VirtualRootWindowOfScreen(DefaultScreenOfDisplay(Dpy));
-
- XGetWindowAttributes(Dpy, root_window, &winfo);
- width = winfo.width;
- height = winfo.height;
-
- if ((p = XGetDefault(Dpy, pname, "BubbleLimit")) != NULL)
- blimit = atoi(p);
- if ((p = XGetDefault(Dpy, pname, "ColorLimit")) != NULL)
- climit = atoi(p);
- if ((p = XGetDefault(Dpy, pname, "MedianCutLimit")) != NULL)
- mlimit = atoi(p);
- if ((p = XGetDefault(Dpy, pname, "DoClipping")) != NULL)
- DoClipping = atoi(p);
- if ((p = XGetDefault(Dpy, pname, "DoubleBuffer")) != NULL)
- DoubleBuf = atoi(p);
- if ((p = XGetDefault(Dpy, pname, "Overlap")) != NULL)
- Overlap = atoi(p);
- if ((p = XGetDefault(Dpy, pname, "Color")) != NULL)
- strcpy(cname, p);
- if ((p = XGetDefault(Dpy, pname, "Picture")) != NULL)
- strcpy(picname, p);
- if ((p = XGetDefault(Dpy, pname, "FishLimit")) != NULL)
- flimit = atoi(p);
- if ((p = XGetDefault(Dpy, pname, "IncMult")) != NULL)
- smooth = atof(p);
- if ((p = XGetDefault(Dpy, pname, "Rate")) != NULL)
- rate = atof(p);
- if ((p = XGetDefault(Dpy, pname, "Secure")) != NULL)
- for (i = 0; i < 6; i++)
- if (strcmp(p, yess[i]) == 0)
- pmode = 0;
-
- /*
- * DoubleBuf is only useful if we are doing clipping on our
- * own background picture, otherwise turn it off.
- */
- if ((DoubleBuf) && ((!DoClipping) || (picname[0] == '\0'))) {
- DoubleBuf = 0;
- }
-
- init_colormap();
-
- if (picname[0] != '\0') {
- imlib_context_set_colormap(colormap);
- PicMap = XCreatePixmap(Dpy, root_window, Pwidth, Pheight, DisplayPlanes(Dpy, screen));
- imlib_context_set_drawable(PicMap);
- imlib_render_image_on_drawable(0, 0);
-
- }
-
- if ((DoubleBuf) || (picname[0] != '\0')) {
- i = DisplayPlanes(Dpy, screen);
- PixBuf = XCreatePixmap(Dpy, root_window, 500, 500, i);
- ClipBuf = XCreatePixmap(Dpy, root_window, 500, 500, 1);
- c0gc = XCreateGC(Dpy, ClipBuf, 0, NULL);
- XSetForeground(Dpy, c0gc, (unsigned long) 0);
- XSetFunction(Dpy, c0gc, GXcopy);
- cpgc = XCreateGC(Dpy, ClipBuf, 0, NULL);
- XSetFunction(Dpy, cpgc, GXor);
- }
-
- attr.override_redirect = True;
- attr.background_pixel = cmap[0];
-
- if (!DoClipping || picname[0] != '\0') {
- wid = XCreateWindow(Dpy, root_window,
- 1, 1, width - 2, height - 2, 0,
- CopyFromParent, CopyFromParent, CopyFromParent,
- CWBackPixel | CWOverrideRedirect, &attr);
-
- if (!wid)
- msgdie("XCreateWindow failed");
- set_window_type_desktop(Dpy, wid);
- } else {
- wid = root_window;
- XClearArea(Dpy, wid, 0, 0, 0, 0, False);
- }
-
- vals.foreground = vals.background = cmap[0];
- vals.graphics_exposures = False;
- gc = XCreateGC(Dpy, wid, GCForeground | GCBackground | GCGraphicsExposures, &vals);
- pgc = XCreateGC(Dpy, wid, GCForeground | GCBackground | GCGraphicsExposures, &vals);
- bgc = XCreateGC(Dpy, wid, GCForeground | GCBackground | GCGraphicsExposures, &vals);
-
- for (i = 0; i < NUM_FISH; i++) {
- pfishA[i][0] = 0;
- pfishA[i][1] = 0;
- pfishA[i][2] = 0;
- pfishB[i][0] = 0;
- pfishB[i][1] = 0;
- pfishB[i][2] = 0;
-
- mfishA[i][0] = 0;
- mfishA[i][1] = 0;
- mfishA[i][2] = 0;
- mfishB[i][0] = 0;
- mfishB[i][1] = 0;
- mfishB[i][2] = 0;
- }
-
- init_pixmap();
- init_signals();
-
- if (!DoClipping || picname[0] != '\0') {
- XStoreName(Dpy, wid, pname);
-
- xsh.flags = USSize | USPosition | PPosition | PSize;
- xsh.x = xsh.y = 0;
- xsh.width = width;
- xsh.height = height;
- XSetNormalHints(Dpy, wid, &xsh);
-
- if (picname[0] != '\0') {
- XSetWindowBackgroundPixmap(Dpy, wid, PicMap);
- }
-
- XMapWindow(Dpy, wid);
- }
-
- binfo = (bubble *) malloc(blimit * sizeof(bubble));
- finfo = (fish *) malloc(flimit * sizeof(fish));
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-Create a new bubble. Placement along the x axis is random, as is the size of
-the bubble. Increment value is determined by speed.
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-void
-new_bubble(b0)
-bubble *b0;
-{
- register int s;
- register bubble *b = b0;
-
- b->x = width * (rand() / RAND_F_MAX);
- if (Init_B)
- b->y = (height / 16) * (rand() / RAND_I_1_16 + 1) - 1;
- else
- b->y = height - 1;
- b->s = s = 1.0 + rand() / RAND_F_1_8;
- if ((b->i = smooth * height / (float) binc[s]) == 0)
- b->i = 1;
- b->erased = 0;
- putbubble(b, s, bcolor);
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-Erase old bubbles, move and draw new bubbles. Random left-right factor
-can move bubble one size-unit in either direction.
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-void
-step_bubbles()
-{
- register int i, j, s;
- register bubble *b;
-
- for (i = 0; i < blimit; i++) {
- b = &binfo[i];
- s = b->s;
- /* clear */
- if ((b->y > 0) && (b->erased == 0)) {
- if ((DoClipping) || (picname[0] != '\0')) {
- erasebubble(b, s);
- } else {
- putbubble(b, s, cmap[0]);
- }
- }
- if ((b->y -= b->i) > 0) {
- j = rand();
- if (j < RAND_I_1_4) {
- b->x -= s;
- } else if (j > RAND_I_3_4) {
- b->x += s;
- }
- putbubble(b, s, bcolor);
- } else {
- if (rand() < RAND_I_1_4) {
- new_bubble(b);
- }
- }
- b->erased = 0;
- }
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-Fish over bubble collision detection. The specified fish is checked against
-all bubbles for overlap. This way we don't try and erase bubbles that are
-already gone.
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-void
-collide_bubbles(f0, ofx, ofy)
-fish *f0;
-int ofx, ofy;
-{
- int i, delta;
- register fish *f = f0;
- register bubble *b;
-
- for (i = 0; i < blimit; i++) {
- b = &binfo[i];
- delta = b->x - ofx;
- if ((delta >= 0) && (delta <= (rwidth[f->type] - b->s))) {
- delta = b->y - ofy;
- if ((delta >= 0) && (delta <= (rheight[f->type] - b->s))) {
- b->erased = 1;
- continue;
- }
- }
- delta = b->x - f->x;
- if ((delta >= 0) && (delta <= (rwidth[f->type] - b->s))) {
- delta = b->y - f->y;
- if ((delta >= 0) && (delta <= (rheight[f->type] - b->s))) {
- b->erased = 1;
- continue;
- }
- }
- }
-}
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-Fish collision detection. The specified fish is checked against all other
-fish for overlap. The xt parameter specifies a x axis multiplier for overlap.
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-int
-collide_fish(f0, xt)
-fish *f0;
-int xt;
-{
- int i, j;
- register fish *f = f0;
-
- if (Overlap) {
- return (0);
- }
-
- for (i = 0; i < flimit; i++) {
- if (&finfo[i] != f) {
- j = finfo[i].y - f->y;
- if ((j > -rheight[finfo[i].type]) && (j < rheight[f->type])) {
- j = finfo[i].x - f->x;
- if ((j > -xt * rwidth[finfo[i].type]) && (j < xt * rwidth[f->type])) {
- return (1);
- }
- }
- }
- }
- return (0);
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-Create a new fish. Placement along the y axis is random, as is the side
->from which the fish appears. Direction is determined from side. Increment
-is also random.
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-void
-new_fish(f0)
-fish *f0;
-{
- int i, collide;
- fish *f = f0;
-
- f->type = rand() % NUM_FISH;
- for (i = 0, collide = 1; (i < 16) && (collide); i++) {
- f->y = (height - rheight[f->type]) * (rand() / RAND_F_MAX);
- if ((f->i = smooth * width / (8.0 * (1.0 + rand() / RAND_F_1_8))) == 0) {
- f->i = 1;
- }
- if (rand() < RAND_I_1_2) {
- f->d = 1;
- f->x = width;
- } else {
- f->d = 2;
- f->x = -rwidth[f->type];
- }
- collide = collide_fish(f, 2);
- }
-
- if (!collide) {
- putfish(f);
- } else {
- f->d = 0;
- }
-
- f->frame = 0;
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-Move all the fish. Clearing old fish is accomplished by masking only the
-exposed areas of the old fish. Random up-down factor can move fish 1/4 a
-fish height in either direction, if no collisions are caused.
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-void
-move_fish()
-{
- register int i, j, x, y, ofx, ofy, ofd, done;
- register fish *f;
-
- for (i = 0; i < flimit; i++) {
- f = &finfo[i];
- if (f->d) {
- ofx = f->x;
- ofy = f->y;
- ofd = f->d;
-
- if (f->d == 1) {
- done = ((f->x -= f->i) < -rwidth[f->type]);
- x = f->x + rwidth[f->type];
- } else if (f->d == 2) {
- done = ((f->x += f->i) > width);
- x = f->x - f->i;
- }
-
- if (!collide_fish(f, 1)) {
- if (!done) {
- j = rand();
- if (j < RAND_I_1_4) {
- y = f->i / 4;
- } else if (j > RAND_I_3_4) {
- y = f->i / -4;
- } else {
- y = 0;
- }
-
- if (y) {
- f->y += y;
- if (collide_fish(f, 1)) {
- f->y -= y;
- y = 0;
- } else {
- if (y > 0) {
- j = f->y - y;
- } else {
- j = f->y + rheight[f->type];
- y *= -1;
- }
- }
- }
- if (DoClipping) {
- movefish(f, ofx, ofy, ofd);
- } else {
- putfish(f);
- XClearArea(Dpy, wid, x, ofy, f->i, rheight[f->type], 0);
- if (y) {
- XClearArea(Dpy, wid, ofx, j, rwidth[f->type], y, 0);
- }
- }
-
- } else {
- XClearArea(Dpy, wid, x, f->y, f->i, rheight[f->type], 0);
- new_fish(f);
- }
- } else {
- if ((f->d = 3 - f->d) == 1) {
- f->x = f->x - 2 * f->i;
- x = f->x + rwidth[f->type];
- } else {
- f->x = f->x + 2 * f->i;
- x = f->x - f->i;
- }
- if (DoClipping) {
- movefish(f, ofx, ofy, ofd);
- } else {
- putfish(f);
- XClearArea(Dpy, wid, x, f->y, f->i, rheight[f->type], 0);
- }
- }
- if ((!DoClipping) || (picname[0] == '\0')) {
- collide_bubbles(f, ofx, ofy);
- }
- } else {
- new_fish(f);
- }
- }
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-Higher-resolution sleep
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-void
-high_res_sleep(seconds)
-double seconds;
-{
- struct timeval timeout;
-
- timeout.tv_sec = seconds;
- timeout.tv_usec = (seconds - timeout.tv_sec) * 1000000.0;
- select(0, NULL, NULL, NULL, &timeout);
-}
-
-
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-int
-main(argc, argv)
-int argc;
-char **argv;
-{
- int i;
- XEvent ev;
-
- parse(argc, argv);
- if ((Dpy = XOpenDisplay(sname)) == 0)
- msgdie("XOpenDisplay failed");
- screen = DefaultScreen(Dpy);
-
- white = WhitePixel(Dpy, screen);
- black = BlackPixel(Dpy, screen);
- initialize();
-
- srand((unsigned) getpid());
-
- Init_B = 1;
- for (i = 0; i < blimit; i++)
- new_bubble(&binfo[i]);
- for (i = 0; i < flimit; i++) {
- finfo[i].x = 0;
- finfo[i].y = 0;
- finfo[i].type = 0;
- }
- for (i = 0; i < flimit; i++)
- new_fish(&finfo[i]);
- if (pmode)
- XLowerWindow(Dpy, wid);
- else
- XRaiseWindow(Dpy, wid);
- XFlush(Dpy);
-
- Init_B = 0;
-
- for (;;) {
- if (XPending(Dpy))
- XNextEvent(Dpy, &ev);
-
- high_res_sleep(rate);
-
- move_fish();
-
- step_bubbles();
-
- if (pmode)
- XLowerWindow(Dpy, wid);
- else
- XRaiseWindow(Dpy, wid);
- }
-
- return 0;
-}