[comp.sources.x] v03i063: xmandel -- mandelbrot program for color suns, Part01/01

argv@island.uu.net (Dan Heller) (04/01/89)

Submitted-by: Arthur Smith <arthur@helios.tn.cornell.edu>
Posting-number: Volume 3, Issue 63
Archive-name: xmandel/part01

[ This runs on color suns -only-  The makefile is very small and I didn't
  see a need for an Imake file.  It is rather slow and it will almost
  certainly eat up your cpu.  I compiled and ran this on my sun3/60 with 8M.
  I had "to make xmandel68881" because the default wouldn't work for me
  but your milage may vary.  The README says "sit and wait" and it isn't
  kidding.  The mandelbrot image overwrites your background on the root
  window it seems.  I ran it as: "xmandel -display unix:0.1" --argv]

# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by helios!arthur on Sun Mar 26 15:27:09 EST 1989
# Contents:  Makefile README colors.h graphics.c graphics.h wrt.c xmandel.c
 
echo x - Makefile
sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//'
CFLAGS = -O -ffpa
wrt.o: colors.h
xmandel: xmandel.o graphics.o wrt.o
	cc $(CFLAGS) xmandel.o graphics.o wrt.o -o xmandel -lX11 -lm
xmandel6.o: xmandel.c; cc -O -f68881 xmandel.c -c -o xmandel6.o
graphics6.o: graphics.c; cc -O -f68881 graphics.c -c -o graphics6.o
wrt6.o: wrt.c colors.h; cc -O -f68881 wrt.c -c -o wrt6.o
xmandel68881: xmandel6.o graphics6.o wrt6.o
	cc -O -f68881 xmandel6.o graphics6.o wrt6.o -o xmandel -lX11 -lm
@//E*O*F Makefile//
chmod u=rw,g=r,o=r Makefile
 
echo x - README
sed 's/^@//' > "README" <<'@//E*O*F README//'
xmandel - A mandelbrot program for color suns, running under X11.

	This is a crude program which I am submitting simply because
	it actually works (under Release 2 at least). It generates
	the Mandelbrot set at desired coordinates, on the display
	you want, and with the resolution scale you want, and then
	the location and magnification can be interactively
	changed by using the mouse and the "Alternate" key.

	ALT-left button causes the scale to expand by a factor of 5,
	ALT-right button reduces by the same factor,
	ALT-middle causes the screen to shift to be centered on the
		point where the button is pressed.

	If you just let the thing sit and wait, it
	gradually produces a higher resolution picture, eventually
	reaching the maximum resolution possible on the screen.
	There are various defaults set, and maybe some other things
	that people will want to change.

	The graphics stuff is really quite general: for example somebody
	here just changed the function passed to produce Julia sets
	instead of the Mandelbrot set. So I hope other people find this
	useful!

			Arthur Smith
			(arthur@helios.tn.cornell.edu)
@//E*O*F README//
chmod u=rw,g=r,o=r README
 
echo x - colors.h
sed 's/^@//' > "colors.h" <<'@//E*O*F colors.h//'
unsigned char colors[] = {
	255, 255, 255,
	0, 0, 0,
	216, 216, 191,
	84, 84, 84,
	0, 255, 127,
	255, 0, 255,
	255, 0, 0,
	79, 47, 79,
	35, 142, 35,
	35, 107, 142,
	255, 127, 0,
	79, 47, 47,
	204, 50, 50,
	112, 219, 147,
	192, 32, 0,
	224, 32, 0,
	0, 64, 0,
	32, 64, 0,
	64, 64, 0,
	96, 64, 0,
	128, 64, 0,
	160, 64, 0,
	192, 64, 0,
	224, 64, 0,
	0, 96, 0,
	32, 96, 0,
	64, 96, 0,
	96, 96, 0,
	128, 96, 0,
	160, 96, 0,
	192, 96, 0,
	224, 96, 0,
	0, 128, 0,
	32, 128, 0,
	64, 128, 0,
	96, 128, 0,
	128, 128, 0,
	160, 128, 0,
	192, 128, 0,
	224, 128, 0,
	0, 160, 0,
	32, 160, 0,
	64, 160, 0,
	96, 160, 0,
	128, 160, 0,
	160, 160, 0,
	192, 160, 0,
	224, 160, 0,
	0, 192, 0,
	32, 192, 0,
	64, 192, 0,
	96, 192, 0,
	128, 192, 0,
	160, 192, 0,
	192, 192, 0,
	224, 192, 0,
	0, 224, 0,
	32, 224, 0,
	64, 224, 0,
	96, 224, 0,
	128, 224, 0,
	160, 224, 0,
	192, 224, 0,
	224, 224, 0,
	0, 0, 64,
	32, 0, 64,
	64, 0, 64,
	96, 0, 64,
	128, 0, 64,
	160, 0, 64,
	192, 0, 64,
	224, 0, 64,
	0, 32, 64,
	32, 32, 64,
	64, 32, 64,
	96, 32, 64,
	128, 32, 64,
	160, 32, 64,
	192, 32, 64,
	224, 32, 64,
	0, 64, 64,
	32, 64, 64,
	64, 64, 64,
	96, 64, 64,
	128, 64, 64,
	160, 64, 64,
	192, 64, 64,
	224, 64, 64,
	0, 96, 64,
	32, 96, 64,
	64, 96, 64,
	96, 96, 64,
	128, 96, 64,
	160, 96, 64,
	192, 96, 64,
	224, 96, 64,
	0, 128, 64,
	32, 128, 64,
	64, 128, 64,
	96, 128, 64,
	128, 128, 64,
	160, 128, 64,
	192, 128, 64,
	224, 128, 64,
	0, 160, 64,
	32, 160, 64,
	64, 160, 64,
	96, 160, 64,
	128, 160, 64,
	160, 160, 64,
	192, 160, 64,
	224, 160, 64,
	0, 192, 64,
	32, 192, 64,
	64, 192, 64,
	96, 192, 64,
	128, 192, 64,
	160, 192, 64,
	192, 192, 64,
	224, 192, 64,
	0, 224, 64,
	32, 224, 64,
	64, 224, 64,
	96, 224, 64,
	128, 224, 64,
	160, 224, 64,
	192, 224, 64,
	224, 224, 64,
	0, 0, 128,
	32, 0, 128,
	64, 0, 128,
	96, 0, 128,
	128, 0, 128,
	160, 0, 128,
	192, 0, 128,
	224, 0, 128,
	0, 32, 128,
	32, 32, 128,
	64, 32, 128,
	96, 32, 128,
	128, 32, 128,
	160, 32, 128,
	192, 32, 128,
	224, 32, 128,
	0, 64, 128,
	32, 64, 128,
	64, 64, 128,
	96, 64, 128,
	128, 64, 128,
	160, 64, 128,
	192, 64, 128,
	224, 64, 128,
	0, 96, 128,
	32, 96, 128,
	64, 96, 128,
	96, 96, 128,
	128, 96, 128,
	160, 96, 128,
	192, 96, 128,
	224, 96, 128,
	0, 128, 128,
	32, 128, 128,
	64, 128, 128,
	96, 128, 128,
	128, 128, 128,
	160, 128, 128,
	192, 128, 128,
	224, 128, 128,
	0, 160, 128,
	32, 160, 128,
	64, 160, 128,
	96, 160, 128,
	128, 160, 128,
	160, 160, 128,
	192, 160, 128,
	224, 160, 128,
	0, 192, 128,
	32, 192, 128,
	64, 192, 128,
	96, 192, 128,
	128, 192, 128,
	160, 192, 128,
	192, 192, 128,
	224, 192, 128,
	0, 224, 128,
	32, 224, 128,
	64, 224, 128,
	96, 224, 128,
	128, 224, 128,
	160, 224, 128,
	192, 224, 128,
	224, 224, 128,
	0, 0, 192,
	32, 0, 192,
	64, 0, 192,
	96, 0, 192,
	128, 0, 192,
	160, 0, 192,
	192, 0, 192,
	224, 0, 192,
	0, 32, 192,
	32, 32, 192,
	64, 32, 192,
	96, 32, 192,
	128, 32, 192,
	160, 32, 192,
	192, 32, 192,
	224, 32, 192,
	0, 64, 192,
	32, 64, 192,
	64, 64, 192,
	96, 64, 192,
	128, 64, 192,
	160, 64, 192,
	192, 64, 192,
	224, 64, 192,
	0, 96, 192,
	32, 96, 192,
	64, 96, 192,
	96, 96, 192,
	128, 96, 192,
	160, 96, 192,
	192, 96, 192,
	224, 96, 192,
	0, 128, 192,
	32, 128, 192,
	64, 128, 192,
	96, 128, 192,
	128, 128, 192,
	160, 128, 192,
	192, 128, 192,
	224, 128, 192,
	0, 160, 192,
	32, 160, 192,
	64, 160, 192,
	96, 160, 192,
	128, 160, 192,
	160, 160, 192,
	192, 160, 192,
	224, 160, 192,
	0, 192, 192,
	32, 192, 192,
	64, 192, 192,
	96, 192, 192,
	128, 192, 192,
	160, 192, 192,
	192, 192, 192,
	224, 192, 192,
	0, 224, 192,
	32, 224, 192,
	64, 224, 192,
	96, 224, 192,
	128, 224, 192,
	160, 224, 192,
	192, 224, 192,
	224, 224, 192
};
@//E*O*F colors.h//
chmod u=rw,g=r,o=r colors.h
 
echo x - graphics.c
sed 's/^@//' > "graphics.c" <<'@//E*O*F graphics.c//'
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include <math.h>
#include <signal.h>
#include "graphics.h"

#define NMAX 256
#define SCFAC 5
#define FLOOR2(x) ((x)/2)
#define CEIL2(x)  ((x) - (x)/2)

unsigned long pixellist[NMAX];

char *malloc();

int ntx,nrx,nty,nry;
int nmaxt,nmint,numpix;
int nomin = 1;
int nomax = NMAX-1;
char *display = NULL;
double xin = 0;
double yin = 0;
double scale = 1;
int rsiz = 12;
double dx,dy;
double pscale;
int restartflag;
int (*func)();
char *name = "XGraphics";

Rectangle root;

int rscreen;
Display *dpy;
Colormap cid;
Window rwindow,nwindow;
Pixmap pixmap;
Pixmap npixmap;
GC gc;
XGCValues gcv;

graphics(display0,xin0,yin0,scale0,res,f)
char *display0;
double xin0,yin0,scale0;
int res,(*f)();
{
	display = display0;
	xin = xin0;
	yin = yin0;
	scale = scale0;
	func = f;
	rsiz = res;

	root.x = root.y = 0;
	root.w = root.h = rsiz;
	rectinit(&root);
	init();
	doplot();

	finish();
}

init()
{
	int sigfin();
	int i,width,height;
	XWindowAttributes war;
	XSetWindowAttributes setwa;
	XColor sdr;

	signal(SIGINT, sigfin);
	signal(SIGQUIT, sigfin);
	signal(SIGTERM, sigfin);

        if ((dpy = XOpenDisplay(display)) == 0) {
                fprintf(stderr, "Graphics: Can't open display \"%s\"\n",
                    XDisplayName(display));
                exit(1);
        }

	rwindow = XDefaultRootWindow(dpy);
	pointerinit();

	rscreen = XDefaultScreen(dpy);

	XGetWindowAttributes(dpy,rwindow,&war);
	width = war.width;
	height = war.height;
	nrx = ceil(((double) width)/rsiz);
	ntx = nrx*rsiz;
	nry = ceil(((double) height)/rsiz);
	nty = nry*rsiz;

	nwindow = XCreateWindow(dpy, rwindow, 0, 0,
		(unsigned int) nrx, (unsigned int) nry, 0, 0,
		CopyFromParent, CopyFromParent, 0L, &setwa);
	 /* Give the window a name */
	XChangeProperty(dpy, nwindow, XA_WM_NAME, XA_STRING, 8,
		PropModeReplace, name, strlen(name));
	XMapWindow(dpy,nwindow);
	XMoveWindow(dpy,nwindow,0,0);

	cid = XDefaultColormap(dpy,rscreen);

	numpix = 1<<war.depth;
	pixellist[0] = 1;
	for (i=1;i<NMAX;i++){
		pixellist[i] = (i + 1) % numpix;
	}

	pixmap = XCreatePixmap(dpy,rwindow,ntx,nty,war.depth);
	if (pixmap==0){
		fprintf(stderr, "Graphics: Unable to create Pixmap");
		exit(1);
	}
	npixmap = XCreatePixmap(dpy,nwindow,nrx,nry,war.depth);
	if (npixmap==0){
		fprintf(stderr, "Graphics: Unable to create Pixmap");
		exit(1);
	}
	gc = XCreateGC(dpy,pixmap,0L,&gcv);
}

initpix()
{
	int i;

	pixellist[0] = 1;
	nomax = nmaxt;
	nomin = nmint;
	for (i=1;i<NMAX;i++){
		pixellist[i] = (2 + ((i - nomin)*(numpix-2)) /
					(nomax-nomin)) % numpix;
	}
}

pointerinit()
{
	long event_mask;
	int mkpm;
	XModifierKeymap *modmap;
	KeyCode *mkdptr;

	modmap = XGetModifierMapping(dpy);
	mkpm = modmap->max_keypermod;
	mkdptr = modmap->modifiermap;
	mkdptr[4*mkpm] = (char) 26; /* This is the keycode for the Alt key,
					and Mod2 has position 4 */
	XSetModifierMapping(dpy,modmap);

	event_mask = ButtonPressMask;
	XGrabButton(dpy,AnyButton,Mod2Mask,rwindow,True,event_mask,
		GrabModeAsync,GrabModeAsync,None,0);
}

int rescale(n)
int n;
{
	int i;

	i = abs(n)%NMAX;
	if (i>nmaxt) nmaxt = i;
	if ((i>0)&&(i<nmint)) nmint = i;
	return i;
}

plotpt(i,j,w,h,n)
int i,j,w,h,n;
{
	XSetForeground(dpy,gc,pixellist[n]);
	XFillRectangle(dpy,pixmap,gc,i,j,w,h);
	if ((i%rsiz==0)&&(j%rsiz==0))
			XDrawPoint(dpy,npixmap,gc,i/rsiz,j/rsiz);
}

plotall()
{
	XSetWindowBackgroundPixmap(dpy,rwindow,pixmap);
	XSetWindowBackgroundPixmap(dpy,nwindow,npixmap);
	XClearWindow(dpy,rwindow);
	XClearWindow(dpy,nwindow);
	XFlush(dpy);
	checkevent();
}

checkevent()
{
	long event_mask;
	XEvent evr;
	XButtonEvent xbevr;
	char *args = NULL;
	Bool checkb2();

	event_mask = ButtonPressMask;
	if (XCheckIfEvent(dpy,&evr,checkb2,args)== True){
		restartflag = 1;
		xbevr = evr.xbutton;
		xin += (-(nrx+1)*rsiz + 2*xbevr.x)/(pscale*rsiz);
		yin += (-(nry+1)*rsiz + 2*xbevr.y)/(pscale*rsiz);
	}
	while(XCheckMaskEvent(dpy,event_mask,&evr)==True){
		restartflag = 1;
		xbevr = evr.xbutton;
		if (xbevr.button == Button1) scale /= SCFAC;
		if (xbevr.button == Button3) scale *= SCFAC;
	}
	printf("xin,yin: %g, %g, scale: %g\n",xin,yin,scale);
}

Bool checkb2(display,event,args)
Display *display;
XEvent *event;
char *args;
{
	XButtonEvent xbevr;
	xbevr = event->xbutton;
	if ((xbevr.button == Button2)&&
		(event->type==ButtonPress)) return True;
	else return False;
}

Rectangle *newrect()
{
	Rectangle *t;

	t = (Rectangle *) malloc(sizeof(Rectangle));
	return t;
}

rectinit(rptr)
Rectangle *rptr;
{
	Rectangle *nptr;
	int w,h;

	w  = rptr->w;
	h = rptr->h;

	if ((h==1)&&(w==1)) rptr->ul = NULL;
	else {
		nptr = rptr->ul = newrect();
		nptr->x = rptr->x;
		nptr->y = rptr->y;
		nptr->w = CEIL2(w);
		nptr->h = CEIL2(h);
		rectinit(nptr);
	}
	if (w==1) rptr->ur = NULL;
	else {

		nptr = rptr->ur = newrect();
		nptr->x = rptr->x + CEIL2(w);
		nptr->y = rptr->y;
		nptr->w = FLOOR2(w);
		nptr->h = CEIL2(h);
		rectinit(nptr);
	}
	if (h == 1) rptr->ll = NULL;
	else {
		nptr = rptr->ll = newrect();
		nptr->x = rptr->x;
		nptr->y = rptr->y + CEIL2(h);
		nptr->w = CEIL2(w);
		nptr->h = FLOOR2(h);
		rectinit(nptr);
	}
	if ((h == 1)||(w == 1)) rptr->lr = NULL;
	else {
		nptr = rptr->lr = newrect();
		nptr->x = rptr->x + CEIL2(w);
		nptr->y = rptr->y + CEIL2(h);
		nptr->w = FLOOR2(w);
		nptr->h = FLOOR2(h);
		rectinit(nptr);
	}
}

doplot()
{
	int dographics();
	int l,maxl;

	maxl = 0;
	l = 1;
	while (l<rsiz){
		l *=2;
		maxl++;
	}
restart:
	
	restartflag = 0;
	pscale = nrx*scale;
	dx = 2/(pscale);
	dy = 2/(pscale);
	nmaxt = 0;
	nmint = NMAX;
	if (dographics(&root,0)==0) goto restart;
	initpix();
	for (l=0;l<=maxl;l++){
		if (dographics(&root,l)==0) goto restart;
	}
}

int dographics(rptr,level)
Rectangle *rptr;
int level;
{
	int i,j,ii,jj,n;
	double xstart,ystart,x,y;

	if (rptr==NULL) return 1;
	if (level==0){
	    ii = rptr->x;
	    jj = rptr->y;
	    xstart = xin - nrx/pscale + (-rsiz+2*ii)/(pscale*rsiz);
	    ystart = yin - nry/pscale + (-rsiz + 2*jj)/(pscale*rsiz);
	    for (x = xstart,i=0;i<nrx;i++,x += dx)
	 	for (y = ystart, j=0;j<nry;j++,y += dy){
			n = rescale((*func)(x,y));
			plotpt(rsiz*i+ii,rsiz*j+jj,rptr->w,rptr->h,n);
		}
	    plotall();
	    if (restartflag==1) return(0);
	    return(1);
	}
	if (dographics2(rptr,level)==0) return 0;
	return 1;
}

int dographics2(rptr,level)
Rectangle *rptr;
int level;
{
	if (rptr==NULL) return 1;
	if (dographics2(rptr->ul,level-1)==0) return 0;
	if (dographics(rptr->ur,level-1)==0) return 0;
	if (dographics(rptr->ll,level-1)==0) return 0;
	if (dographics(rptr->lr,level-1)==0) return 0;
	return 1;
}

finish()
{
	XFreeGC(dpy,gc);
	XFreePixmap(dpy,pixmap);
	XFreePixmap(dpy,npixmap);
	XDestroyWindow(dpy,nwindow);
}

sigfin(sig,code,scp)
int sig,code;
struct sigcontext *scp;
{
	finish();
	exit(sig);
}
@//E*O*F graphics.c//
chmod u=rw,g=r,o=r graphics.c
 
echo x - graphics.h
sed 's/^@//' > "graphics.h" <<'@//E*O*F graphics.h//'
typedef struct rectangle{
	int x,y,w,h;
	struct rectangle *ul,*ur,*ll,*lr;
} Rectangle;
@//E*O*F graphics.h//
chmod u=rw,g=r,o=r graphics.h
 
echo x - wrt.c
sed 's/^@//' > "wrt.c" <<'@//E*O*F wrt.c//'
#include <stdio.h>
#include <sys/file.h>
#include <math.h>
#include <rasterfile.h>

#define XSIZ 1152
#define YSIZ 900
#define TOTSIZ 1036800
#define LINE 80
#define MAXCHAR 256

extern double xin,yin,scale;
extern int nomin,nomax;
int head[] = {
	RAS_MAGIC,
	XSIZ, 	/* Width */
	YSIZ,	/* height */
	8,	/* depth */
	TOTSIZ,	/* length - set later */
	RT_STANDARD,	/* type 1 rasterfile */
	RMT_EQUAL_RGB,		/* RGB vectors */
	768		/* Size of colormap = 3*256 */
};

writeman(func)
int (*func)();
{
	char filename[LINE];
	char instr[LINE];
	unsigned char *buffer;
	unsigned char colormap[768];
	int rsiz,fd;
	int nrx,nry;
	int i,j;
	unsigned char n;
	double x,xstart,y,ystart;
	double pscale,dx,dy;

	fprintf(stderr,"Name of file: ");
	fflush(stderr);
	fgets(instr, LINE, stdin);
	sscanf(instr,"%s",filename);
	rsiz = igetd("resolution scale", 1);
	if ((fd = open(filename,O_CREAT|O_WRONLY,0644))==-1){
		fprintf(stderr,"Sorry, can't open file\n");
		exit(-1);
	}
	if (fork()) exit(0);

	write(fd, head, sizeof(head));
	putcolor(colormap);
	write(fd, colormap, 768);

	buffer = (unsigned char *) malloc(TOTSIZ*sizeof(char));

	nrx = (int) ceil(((double) XSIZ)/rsiz);
	nry = (int) ceil(((double) YSIZ)/rsiz);

/*	write(fd, &nrx, sizeof(int));
	write(fd, &nry, sizeof(int));*/

	pscale = nrx*scale;
	dy = dx = 2/pscale;
	xstart = xin - nrx/pscale;
	ystart = yin - nry/pscale;
	for (y=ystart, j=0;j<nry;j++,y += dy)
	    for (x = xstart,i=0;i<nrx;i++,x += dx){
			n = abs((*func)(x,y))%MAXCHAR;
			if (n==0) n=1;
			else n = (2 + ((n - nomin)*(MAXCHAR-2)) /
					(nomax-nomin)) % MAXCHAR;
			writebuf(buffer, n, i, j, rsiz);
	    }
	close(fd);
}

writebuf(buf, c, x, y, rsiz)
unsigned char *buf, c;
int x, y, rsiz;
{
	int index,i,j,ind;

	index = x*rsiz + y*rsiz*XSIZ;
	for (i=0;i<rsiz;i++){
		ind = index + i*XSIZ;
		for(j = 0;j<rsiz;j++){
			if (ind >= TOTSIZ) break;
			buf[ind++] = c;
		}
	}
}

igetd(mesg,deflt)
char *mesg;
int deflt;
{
    int i;
    char s[LINE];
    fprintf(stderr,"*Enter %s [%d]: ",mesg,deflt);
    fflush(stderr);
    if (!fgets(s,LINE,stdin)) exit(-1);
    if(sscanf(s,"%d%>",&i)==EOF)
        return(deflt);
    else
        return(i);
}

#include "colors.h"

putcolor(cm)
unsigned char *cm;
{
	int i, j;

	for (i=0;i<3;i++)
		for (j=0;j<256;j++)
			*cm++ = colors[3*j + i];
}
@//E*O*F wrt.c//
chmod u=rw,g=r,o=r wrt.c
 
echo x - xmandel.c
sed 's/^@//' > "xmandel.c" <<'@//E*O*F xmandel.c//'
#include <stdio.h>
#include <signal.h>
#include <math.h>
#include <string.h>
#include <ctype.h>

#define NMAX 200
#define LINE 80
#define SCFAC 5

typedef struct complx{
	double re;
	double im;
} Cmplx;

char *argv0;
int rsiz0 = 12;
double xin0 = 0;
double yin0 = 0;
double scale0 = 1;
char *display0 = NULL;
char *malloc();
double xo,yo;
FILE *fp = stderr;
FILE *fpin = stdin;

main(argc,argv)
int argc;
char **argv;
{
	int nmand(), length;
	void exithandler();

	argv0 = argv[0];
again:
	if (argc > 2 && strcmp(argv[1], "-display") == 0) {
		argv++;
		argc--;
		length = strlen(argv[1]);
		display0 = malloc(length + 5);
		strcpy(display0,argv[1]);
		if ((length < 4) || (argv[1][length - 4] != ':'))
			strcat(display0,":0.0");
		argv++;
		argc--;
		goto again;
	}
	if (argc > 2 && strcmp(argv[1], "-x") == 0) {
		argv++;
		argc--;
		if (sscanf(argv[1], "%F", &xin0) !=1)
			usage();
		argv++;
		argc--;
		goto again;
	}
	if (argc > 2 && strcmp(argv[1], "-y") == 0) {
		argv++;
		argc--;
		if (sscanf(argv[1], "%F", &yin0) !=1)
			usage();
		argv++;
		argc--;
		goto again;
	}
	if (argc > 2 && strcmp(argv[1], "-s") == 0) {
		argv++;
		argc--;
		if (sscanf(argv[1], "%F", &scale0) !=1)
			usage();
		argv++;
		argc--;
		goto again;
	}
	if (argc > 2 && strcmp(argv[1], "-r") == 0) {
		argv++;
		argc--;
		if (sscanf(argv[1], "%d", &rsiz0) !=1)
			usage();
		argv++;
		argc--;
		goto again;
	}

	if (argc > 1) usage();

	on_exit(exithandler);
	graphics(display0,xin0,yin0,scale0,rsiz0,nmand,NMAX);
}

int nmand(x,y)
double x,y;
{
	Cmplx map(),z;
	int n;

	n = 1;
	xo = z.re = x;
	yo = z.im = y;
	for(;z.re*z.re+z.im*z.im < 4;z = map(z))
		if (++n>=NMAX) break;
	return NMAX - n;
}

Cmplx map(z)
Cmplx z;
{
	Cmplx t;

	t.re = z.re*z.re - z.im*z.im + xo;
	t.im = 2*z.re*z.im + yo;
	return t;
}

usage()
{
	fprintf(stderr,
	    "usage: %s [-display host] [-x x0] [-y y0] [-s scale]\n",argv0);
	fprintf(stderr,"       [-r resolution]\n");
	exit(1);
}

void exithandler(status)
int status;
{
	int wtf,nmand();

	if (status != SIGINT) exit(0);
	wtf = lgetd("Write to file",0);
	if (wtf == 0) exit(0);
	writeman(nmand);
}

lgetd(mesg,deflt)
char *mesg;
int deflt;
{
    char s[LINE], *sptr;
    for(;;) {
        fprintf(fp,"*%s [%c]: ",mesg,(deflt ? 'y' : 'n'));
        fflush(fp);
        sptr = fgets(s,LINE,fpin);
        if (!sptr) exit(-1);
        while(isspace(*sptr)) sptr++;
        if(*sptr=='\0') return(deflt);
        if(isupper(*sptr)) *sptr = tolower(*sptr);
          if(*sptr == 'y')
                return(1);
          else if(*sptr == 'n')
                return(0);
          else
                fprintf(fp,"   Say what? Enter y or n.\n");
    }
}
@//E*O*F xmandel.c//
chmod u=rw,g=r,o=r xmandel.c
 
echo Inspecting for damage in transit...
temp=/tmp/shar$$; dtemp=/tmp/.shar$$
trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
cat > $temp <<\!!!
       9      61     431 Makefile
      27     181    1131 README
     258     774    3643 colors.h
     359     802    6833 graphics.c
       4      10      88 graphics.h
     118     297    2300 wrt.c
     154     365    2666 xmandel.c
     929    2490   17092 total
!!!
wc  Makefile README colors.h graphics.c graphics.h wrt.c xmandel.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
if [ -s $dtemp ]
then echo "Ouch [diff of wc output]:" ; cat $dtemp
else echo "No problems found."
fi
exit 0