[comp.sources.x] v03i031: MacPaint-like graphics, Part01/03

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

Submitted-by: koblas@mips.com (David Koblas)
Posting-number: Volume 3, Issue 31
Archive-name: xpaint/part01

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 3)."
# Contents:  README draw.c menu.c pat_09.xbm
# Wrapped by mikew@wyse on Wed Feb 22 13:37:38 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1752 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X
X				XPAINT
X
X	This intent of this program was a utility to edit images that
XI generated, but very quickly I drifted from my orignal purpose and
Xcreated something that closely resembles MacPaint [probably a trademark 
Xof Apple Computer].  I still intend to add some image enhancements 
Xfacilities (specifically Alpha channel data, and color support).
X
X	Updates, and patches:  Well yes I'm interested in what people
Xdo to this, add, fix.  There are whole regions of this program that
Xare unmaintainable without a real rewrite.  So fairly quickly after this
Xinitial release of XPAINT I will begin to work on version 2.0 which will
Xinclude color support and real image enhancements facilities.  It
Xwill be a 95% rewrite since now I know what the requirements for this
Xtype of program are.  If you didn't know better you might call this
Xan alpha release but since I plan on tossing most of this code
Xin favor of bigger and better things I though I would let the world
Xplay with it until then.
X
X	Also this program is based on the assuption that the client
Xis faster than the server for some things (I use XImages instead of
XPixmaps).  Let me know how this works for you, is this a safe assumtion
X[on a 11/750, on a cray, server on a PMAX, on a sun].  Another question
Xis it a "nice" idea to open up many windows and take advantage of the 
Xserver handling things more me, or should I be reserving this and
Xjust open up 1 or two and wave my hands alot...
X
X	Finally, as I upgrade this program for color I REALLY want
Xpeoples comments and sudgestions on how to make this very useful.
XThis is your chance to see some of your wishes come true, why should
Xall those PC users have all the fun.
X
X
X				David Koblas
X
X    koblas@mips.com				...{ames,decwrl}!mips!koblas
END_OF_FILE
if test 1752 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'draw.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'draw.c'\"
else
echo shar: Extracting \"'draw.c'\" \(36994 characters\)
sed "s/^X//" >'draw.c' <<'END_OF_FILE'
X/* +------------------------------------------------------------------+ */
X/* | Copyright 1989, David Koblas.                                    | */
X/* |   You may copy this file in whole or in part as long as you      | */
X/* |   don't try to make money off it, or pretend that you wrote it.  | */
X/* +------------------------------------------------------------------+ */
X
X#include <stdio.h>
X#include "xpaint.h"
X
X#define Between(min,val,max) (((min)<=(val)) && ((val)<(max)))
X
X#define ABS(x)	(((x)<0) ? 0-(x) : (x))
X#define SIGN(x)	(((x)==0) ? 0 : ((x)<0) ? -1 : 1)
X#define MIN(a,b) ((a)<(b) ? (a) : (b))
X#define MAX(a,b) ((a)>(b) ? (a) : (b))
X#define CTRL(x)	((x)-'A'+1)
X#define DELETE	127
X
X#define PUT_P_PIXEL(x,y)	PATTERN_VAL(x,y)?\
X				PUT_C_PIXEL(CurrentWindow->white,x,y):\
X				PUT_C_PIXEL(CurrentWindow->black,x,y)
X#define PUT_C_PIXEL(c,x,y) XPutPixel(draw.buffer, \
X		CurrentWindow->img_offx+(x),(y),c)
X#define PUT_PIXEL(x,y) PUT_C_PIXEL(CurrentWindow->black,x,y);
X
Xstatic int	buf_flag=FALSE;
Xstatic int	undo_flag=FALSE;
Xstatic int	dot_flag=FALSE;
Xstatic int	dot_inter_id;
Xstatic int	buf_xe,buf_ye,buf_xs,buf_ys;
X
X#ifndef lint
Xstatic char	rcsid[]="$Header: draw.c,v 1.7 89/02/20 19:32:56 koblas Locked $";
X#endif
X
Xstatic	struct {
X	int		width,height;
X	GC		gc;
X	XFontStruct	*font_info;
X	Window		window;
X	XImage		*buffer;
X	int		mapped;
X	int		lastx,lasty;
X} draw;
X
Xstatic struct {
X	int		flag;
X	int		width,height;
X	int		x,y;
X} fatbits;
X
Xstatic struct {
X	XImage	*image;
X	int	xorig,yorig;
X	int	x,y;
X	int	xs;
X	int	width,height;
X} select_buffer;
X
XWindow	CreateDraw()
X{
X	XGCValues		values;
X	XSetWindowAttributes	attr;
X	char			*data;
X
X	draw.width = CurrentWindow->width - (10+32+32+10) - (10+16+10);
X	draw.height= CurrentWindow->height - (10+60+10) - 
X			CurrentWindow->subwind[DRAW_ID].delta_y;
X
X	attr.do_not_propagate_mask = -1;
X	attr.background_pixel = CurrentWindow->white;
X	attr.event_mask = ExposureMask|ButtonPressMask|
X			  KeyPressMask|
X			  ButtonReleaseMask|PointerMotionMask;
X
X	draw.window = XCreateWindow(CurrentWindow->display,
X			   CurrentWindow->window,
X		           DELTA_XPOS(DRAW_ID),DELTA_YPOS(DRAW_ID),
X			   draw.width,draw.height,
X			   1,0,0,0,
X			   CWDontPropagate|CWEventMask|CWBackPixel,&attr);
X	draw.mapped=FALSE;
X	draw.lastx=draw.lasty=0;
X
X	draw.font_info = XLoadQueryFont(CurrentWindow->display,DEF_FONT);
X	if (draw.font_info == NULL) {
X		fprintf(stderr,"Unable to open font %s\n",DEF_FONT);
X		exit(1);
X	}
X	values.foreground = CurrentWindow->black;
X	values.background = CurrentWindow->white;
X	values.font       = draw.font_info -> fid;
X	draw.gc = XCreateGC(CurrentWindow->display,draw.window,
X			    GCFont|GCForeground|GCBackground,&values);
X
X	if ((data=(char *)malloc(CurrentWindow->img_height*draw.height))==NULL){
X		fprintf(stderr,"Malloc for buffer #1 failed\n");
X		exit(1);
X	}
X	draw.buffer = XCreateImage(CurrentWindow->display,CurrentWindow->visual,
X				   CurrentWindow->depth,
X				   ZPixmap,0,data,CurrentWindow->img_width,
X				   draw.height,8,0);
X	if ((data=(char *)malloc(CurrentWindow->img_height*draw.height))==NULL){
X		fprintf(stderr,"Malloc for buffer #1 failed\n");
X		exit(1);
X	}
X	select_buffer.image = XCreateImage(CurrentWindow->display,
X				           CurrentWindow->visual,
X				           CurrentWindow->depth,
X				           ZPixmap,0,data,
X					   CurrentWindow->img_width,
X				           draw.height,8,0);
X
X	return draw.window;
X}
X
Xvoid	OpenDraw()
X{
X	int	x,y;
X	char	*data;
X
X	if (draw.mapped) 
X		return;
X
X	draw.mapped=TRUE;
X	buf_flag=FALSE;
X	undo_flag=FALSE;
X	dot_flag=FALSE;
X	fatbits.flag=FALSE;
X	XMapWindow(CurrentWindow->display,draw.window);
X	draw.lastx=draw.lasty=0;
X
X	CurrentWindow->img_width  = DefaultXsize;
X	CurrentWindow->img_height = DefaultYsize;
X	if ((data=(char *)malloc(DefaultXsize*DefaultYsize))==NULL) {
X		fprintf(stderr,"Malloc for buffer #2 failed\n");
X		exit(1);
X	}
X	CurrentWindow->master = XCreateImage(CurrentWindow->display,
X				     CurrentWindow->visual,
X				     CurrentWindow->depth,
X				     ZPixmap,0,data,DefaultXsize,
X				     DefaultYsize,8,0);
X	for (x=0;x<DefaultXsize;x++) {
X		XPutPixel(CurrentWindow->master,x,0,
X			CurrentWindow->white);
X	}
X	for (y=1;y<DefaultYsize;y++) {
X		bcopy(CurrentWindow->master->data,
X		CurrentWindow->master->data+
X		   (y*CurrentWindow->master->bytes_per_line),
X		CurrentWindow->master->bytes_per_line);
X	}
X
X	XFlush(CurrentWindow->display);
X}
X
Xvoid	CloseDraw()
X{
X	if (draw.mapped) {
X		XUnmapWindow(CurrentWindow->display,draw.window);
X		draw.mapped=FALSE;
X	}
X	XFlush(CurrentWindow->display);
X}
X
Xvoid	ResizeDraw()
X{
X	char	*data;
X
X	draw.width = CurrentWindow->width - (10+32+32+10) - (10+16+10);
X	draw.height= CurrentWindow->height - (10+60+10) - 
X			CurrentWindow->subwind[DRAW_ID].delta_y;
X
X	draw.width  = MIN(draw.width, CurrentWindow->img_width);
X	draw.height = MIN(draw.height, CurrentWindow->img_height);
X
X	XResizeWindow(CurrentWindow->display,draw.window,
X			draw.width,draw.height);
X
X	XDestroyImage(draw.buffer);
X	if ((data=(char *)malloc(CurrentWindow->img_height*draw.height))==NULL){
X		fprintf(stderr,"Malloc for buffer #1 failed\n");
X		exit(1);
X	}
X	draw.buffer = XCreateImage(CurrentWindow->display,CurrentWindow->visual,
X				   CurrentWindow->depth,
X				   ZPixmap,0,data,CurrentWindow->img_width,
X				   draw.height,8,0);
X	XDestroyImage(select_buffer.image);
X	if ((data=(char *)malloc(CurrentWindow->img_height*draw.height))==NULL){
X		fprintf(stderr,"Malloc for buffer #1 failed\n");
X		exit(1);
X	}
X	select_buffer.image = XCreateImage(CurrentWindow->display,
X				           CurrentWindow->visual,
X				           CurrentWindow->depth,
X				           ZPixmap,0,data,
X					   CurrentWindow->img_width,
X				           draw.height,8,0);
X}
X
XShowDraw()
X{
X	ResizeDraw();
X	buf_flag=FALSE;
X	undo_flag=FALSE;
X	dot_flag=FALSE;
X	fatbits.flag=FALSE;
X	XMapWindow(CurrentWindow->display,draw.window);
X	draw.mapped=TRUE;
X	XFlush(CurrentWindow->display);
X}
X
Xvoid	EventDraw(event)
XXEvent	*event;
X{
X	int	x,y;
X	long	pix;
X
X	switch (event->type) {
X	case ButtonPress:
X		OnGraphic(CurrentActionID,event);
X		break;
X	case Expose:
X		if (fatbits.flag) {
X			for (y=0;y<fatbits.height;y++) {
X				for (x=0;x<fatbits.width;x++) {
X					pix = XGetPixel(draw.buffer,
X					    CurrentWindow->img_offx+fatbits.x+x,
X					    fatbits.y+y);
X					if (pix!=CurrentWindow->white)
X					  XFillRectangle(CurrentWindow->display,
X						draw.window,CurrentWindow->igc,
X						x*6,y*6,5,5);
X				}
X			}
X			XPutImage(CurrentWindow->display,draw.window,
X					draw.gc,CurrentWindow->master,
X					CurrentWindow->img_offx+fatbits.x,
X					CurrentWindow->img_offy+fatbits.y,
X					0,0,fatbits.width,fatbits.height);
X		} else {
X			XPutImage(CurrentWindow->display,draw.window,
X				draw.gc,CurrentWindow->master,
X				CurrentWindow->img_offx+event->xexpose.x,
X				CurrentWindow->img_offy+event->xexpose.y,
X				event->xexpose.x,event->xexpose.y,
X				event->xexpose.width,event->xexpose.height);
X			if (buf_flag) {
X				ShowBuffer();
X			}
X			if (dot_flag) {
X				XPutImage(CurrentWindow->display,draw.window,
X					draw.gc,select_buffer.image,
X					select_buffer.xs,
X					0,select_buffer.x,select_buffer.y,
X					select_buffer.width,
X					select_buffer.height);
X			}
X		}
X		break;
X	}
X}
X
XDrawFlipVert()
X{
X	int	x,y,c=select_buffer.width/2;
X	long	pixA,pixB;
X
X	for (y=0;y<select_buffer.height;y++)
X		for (x=0;x<c;x++) {
X			pixA = XGetPixel(select_buffer.image,
X				select_buffer.xs+x,y);
X			pixB = XGetPixel(select_buffer.image,
X				select_buffer.xs+(select_buffer.width-x),y);
X			XPutPixel(select_buffer.image,
X			    select_buffer.xs+x,y,pixB);
X			XPutPixel(select_buffer.image,
X			    select_buffer.xs+(select_buffer.width-x),y,pixA);
X		}
X	XPutImage(CurrentWindow->display,draw.window,
X		draw.gc,select_buffer.image,select_buffer.xs,
X		0,select_buffer.x,select_buffer.y,
X		select_buffer.width,select_buffer.height);
X}
X
XDrawFlipHorz()
X{
X	int	x,y,c=select_buffer.height/2;
X	long	pixA,pixB;
X
X	for (y=0;y<c;y++)
X		for (x=0;x<select_buffer.width;x++) {
X			pixA = XGetPixel(select_buffer.image,
X				select_buffer.xs+x,y);
X			pixB = XGetPixel(select_buffer.image,
X				select_buffer.xs+x,select_buffer.height-y);
X			XPutPixel(select_buffer.image,
X			    select_buffer.xs+x,y,pixB);
X			XPutPixel(select_buffer.image,
X			    select_buffer.xs+x,select_buffer.height-y,pixA);
X		}
X	XPutImage(CurrentWindow->display,draw.window,
X		draw.gc,select_buffer.image,select_buffer.xs,
X		0,select_buffer.x,select_buffer.y,
X		select_buffer.width,select_buffer.height);
X}
X
XDrawBufferInvert()
X{
X	int	x,y;
X	long	pix;
X
X	if (!dot_flag)
X		return;
X
X	for (y=0;y<select_buffer.height;y++)
X		for (x=0;x<select_buffer.width;x++) {
X			pix = XGetPixel(select_buffer.image,
X					x+select_buffer.xs,y);
X			if (pix == CurrentWindow->white)
X				XPutPixel(select_buffer.image,
X				     x+select_buffer.xs,y,CurrentWindow->black);
X			else if (pix == CurrentWindow->black)
X				XPutPixel(select_buffer.image,
X				     x+select_buffer.xs,y,CurrentWindow->white);
X		}
X	XPutImage(CurrentWindow->display,draw.window,
X		draw.gc,select_buffer.image,select_buffer.xs,
X		0,select_buffer.x,select_buffer.y,
X		select_buffer.width,select_buffer.height);
X}
X
Xvoid DrawUndo()
X{
X	if (!undo_flag && !buf_flag)
X		return;
X
X	if (undo_flag) {
X		ShowBuffer();
X		buf_flag = TRUE;
X		undo_flag=FALSE;
X	} else {
X		XPutImage(CurrentWindow->display,draw.window,
X			draw.gc,CurrentWindow->master,
X			CurrentWindow->img_offx+buf_xs,
X			CurrentWindow->img_offy+buf_ys,
X			buf_xs,buf_ys,
X			buf_xe-buf_xs,buf_ye-buf_ys);
X		buf_flag = FALSE;
X		undo_flag=TRUE;
X	}
X	if (dot_flag) {
X		int	t;
X
X		t = select_buffer.x ;
X		select_buffer.x = select_buffer.xorig;
X		select_buffer.xorig = t;
X		t = select_buffer.y ;
X		select_buffer.y = select_buffer.yorig;
X		select_buffer.yorig = t;
X
X		XPutImage(CurrentWindow->display,draw.window,
X			draw.gc,CurrentWindow->master,
X			CurrentWindow->img_offx+select_buffer.xorig,
X			CurrentWindow->img_offy+select_buffer.yorig,
X			select_buffer.xorig,select_buffer.yorig,
X			select_buffer.width,select_buffer.height);
X
X		XPutImage(CurrentWindow->display,draw.window,
X			draw.gc,select_buffer.image,select_buffer.xs,
X			0,select_buffer.x,select_buffer.y,
X			select_buffer.width,select_buffer.height);
X	}
X}
X
XDrawGetRegion(x,y,w,h)
Xint	*x,*y,*w,*h;
X{
X	*x = select_buffer.x;
X	*y = select_buffer.y;
X	*w = select_buffer.width;
X	*h = select_buffer.height;
X}
X
XXeroxMaster()
X{
X	int	len = draw.buffer->height*
X	              CurrentWindow->master->bytes_per_line;
X	char	*start=CurrentWindow->master->data+
X		(CurrentWindow->master->bytes_per_line*CurrentWindow->img_offy);
X
X	bcopy(start,draw.buffer->data,len);
X}
X
XXeroxSubMaster(xs,ys,xe,ye)
Xint	xs,ys,xe,ye;
X{
X	int	len = (ye-ys)*CurrentWindow->master->bytes_per_line;
X	char	*start=CurrentWindow->master->data+
X		(CurrentWindow->master->bytes_per_line*
X		 (CurrentWindow->img_offy+ys));
X	char	*dst=draw.buffer->data+
X		(draw.buffer->bytes_per_line*ys);
X
X	bcopy(start,dst,len);
X}
X
XGetBuffer(xs,ys,xe,ye)
Xint	xs,ys,xe,ye;
X{
X	static int	buf_a_xs,buf_a_xe,buf_a_ys,buf_a_ye;
X
X	if (xe<xs) {
X		int t = xs; xs = xe; xe = t;
X	}
X	if (ye<ys) {
X		int t = ys; ys = ye; ye = t;
X	}
X	xe++;
X	ye++;
X	if (xs<0) xs=0;
X	if (ys<0) ys=0;
X
X	if (!buf_flag) {
X		buf_a_xs = buf_xs = xs;
X		buf_a_ys = buf_ys = ys;
X		buf_a_xe = buf_xe = xe;
X		buf_a_ye = buf_ye = ye;
X		XeroxSubMaster(xs,ys,xe,ye);
X		buf_flag = TRUE;
X	} else {
X		buf_xs = MIN(buf_a_xs,xs);
X		buf_ys = MIN(buf_a_ys,ys);
X		buf_xe = MAX(buf_a_xe,xe);
X		buf_ye = MAX(buf_a_ye,ye);
X		XeroxSubMaster(buf_xs,buf_ys,buf_xe,buf_ye);
X		buf_a_xs = xs;
X		buf_a_ys = ys;
X		buf_a_xe = xe;
X		buf_a_ye = ye;
X	}
X}
X
XShowSubBuffer(xs,ys,xe,ye)
Xint	xs,ys,xe,ye;
X{
X	if (!buf_flag) return;
X
X	if (xe<xs) {
X		int t = xs; xs = xe; xe = t;
X	}
X	if (ye<ys) {
X		int t = ys; ys = ye; ye = t;
X	}
X	xe++;
X	ye++;
X
X	XPutImage(CurrentWindow->display,draw.window,
X		draw.gc,draw.buffer,
X		CurrentWindow->img_offx+buf_xs+xs,ys+buf_ys,
X		buf_xs+xs,buf_ys+ys,xe-xs,ye-ys);
X	XFlush(CurrentWindow->display);
X}
X
XShowBuffer()
X{
X	if (!buf_flag) return;
X
X	XPutImage(CurrentWindow->display,draw.window,
X		draw.gc,draw.buffer,
X		CurrentWindow->img_offx+buf_xs,buf_ys,
X		buf_xs,buf_ys,buf_xe-buf_xs,buf_ye-buf_ys);
X	XFlush(CurrentWindow->display);
X}
X
XFlushBuffer()
X{
X	int	len = (buf_ye-buf_ys)*CurrentWindow->master->bytes_per_line;
X	char	*start=CurrentWindow->master->data+
X		(CurrentWindow->master->bytes_per_line*
X		 (CurrentWindow->img_offy+buf_ys));
X	char	*dst=draw.buffer->data+
X		(draw.buffer->bytes_per_line*buf_ys);
X
X	if (dot_flag) {
X		int	x,y;
X		long	pix;
X
X		DeleteInterrupt(dot_inter_id);
X		dot_flag = FALSE;
X		buf_flag = FALSE;
X		for (y=0;y<select_buffer.height;y++)
X			for (x=0;x<select_buffer.width;x++) {
X				pix = XGetPixel(select_buffer.image,
X						x+select_buffer.xs,y);
X				XPutPixel(CurrentWindow->master,
X				 select_buffer.x+CurrentWindow->img_offx+x,
X				 select_buffer.y+CurrentWindow->img_offy+y,pix);
X			}
X	}
X
X	undo_flag= FALSE;
X
X	if (!buf_flag) return;
X
X	bcopy(dst,start,len);
X	buf_flag=FALSE;
X}
X
XDrawFatbits()
X{
X	int	x,y;
X	int	w=draw.width/6,h=draw.height/6;
X	long	pix;
X
X	if (fatbits.flag)
X		return;
X	FlushBuffer();
X	fatbits.flag=TRUE;
X
X	XClearWindow(CurrentWindow->display,draw.window);
X
X	fatbits.width  = w - 1;
X	fatbits.height = h - 1;
X	fatbits.x = draw.lastx;
X	fatbits.y = draw.lasty;
X
X	for (y=0;y<h;y++) {
X		for (x=0;x<w;x++) {
X			pix = XGetPixel(CurrentWindow->master,
X					CurrentWindow->img_offx+fatbits.x+x,
X					CurrentWindow->img_offy+fatbits.y+y);
X			if (pix!=CurrentWindow->white)
X				XFillRectangle(CurrentWindow->display,
X					draw.window,CurrentWindow->igc,
X					x*6,y*6,5,5);
X		}
X	}
X	XPutImage(CurrentWindow->display,draw.window,
X			draw.gc,CurrentWindow->master,
X			CurrentWindow->img_offx+fatbits.x,
X			CurrentWindow->img_offy+fatbits.y,
X			0,0,fatbits.width,fatbits.height);
X}
X
X/****************************************************************************/
X/****************************************************************************/
X/****************************************************************************/
X/****************************************************************************/
X/****************************************************************************/
X
XTrackLine(flag,x,y)
Xint	flag,x,y;
X{
X	static int 	xstart,ystart;
X	static long	color;
X
X	if (flag) {
X		xstart = x;
X		ystart = y;
X		color = (XGetPixel(draw.buffer,x,y) == CurrentWindow->white) ? 
X			 CurrentWindow->black : CurrentWindow->white;
X		return;
X	}
X
X	GetBuffer(xstart,ystart,x,y);
X	DrawLine(xstart,ystart,x,y,color);
X	ShowBuffer();
X}
X
XTrackArbLine(flag,x,y)
Xint	flag,x,y;
X{
X	static int 	xstart,ystart;
X	static long	color;
X
X	if (flag) {
X		xstart = x;
X		ystart = y;
X		GetBuffer(0,0,draw.width,draw.height);
X		color = (XGetPixel(draw.buffer,CurrentWindow->img_offx+x,y) 
X				== CurrentWindow->white) ? 
X			 CurrentWindow->black : CurrentWindow->white;
X	}
X	DrawLine(xstart,ystart,x,y,color);
X	ShowSubBuffer(xstart,ystart,x,y);
X	xstart=x;
X	ystart=y;
X}
X
XTrackRectangle(flag,x,y)
Xint	flag,x,y;
X{
X	static int 	xstart,ystart;
X	int		xs,ys,w,h;
X
X	if (flag) {
X		xstart = x;
X		ystart = y;
X		return;
X	}
X	if (x<xstart) {
X		xs = x;
X		w  = xstart - x;
X	} else {
X		xs = xstart;
X		w  = x - xstart;
X	}
X	if (y<ystart) {
X		ys = y;
X		h  = ystart - y;
X	} else {
X		ys = ystart;
X		h  = y - ystart;
X	}
X	GetBuffer(xstart,ystart,x,y);
X	DrawRectangle(xs,ys,w,h,FALSE,0);
X	ShowBuffer();
X}
X
XTrackEllipse(flag,x,y)
Xint	flag,x,y;
X{
X	static int 	xstart,ystart;
X	int		xs,ys,w,h;
X
X	if (flag) {
X		xstart = x;
X		ystart = y;
X		return;
X	}
X	if (x<xstart) {
X		xs = x;
X		w  = xstart - x;
X	} else {
X		xs = xstart;
X		w  = x - xstart;
X	}
X	if (y<ystart) {
X		ys = y;
X		h  = ystart - y;
X	} else {
X		ys = ystart;
X		h  = y - ystart;
X	}
X	GetBuffer(xstart,ystart,x,y);
X	DrawEllipse(xs,ys,w,h);
X	ShowBuffer();
X}
X
XTrackEraser(flag,x,y)
Xint	flag,x,y;
X{
X	int	xs=16,ys=10;
X
X	if (flag) {
X		GetBuffer(0,0,draw.width,draw.height);
X	}
X	if (x+xs>draw.width)
X		xs=draw.width-x;
X	if (y+ys>draw.height)
X		ys=draw.height-y;
X	FillRectangle(x,y,xs,ys,CurrentWindow->white);
X	ShowSubBuffer(x,y,x+xs,y+ys);
X}
X
X
XTrackRectfill(flag,x,y)
Xint	flag,x,y;
X{
X	static int 	xstart,ystart;
X	int		xs,ys,w,h;
X
X	if (flag) {
X		xstart = x;
X		ystart = y;
X		return;
X	}
X	if (x<xstart) {
X		xs = x;
X		w  = xstart - x;
X	} else {
X		xs = xstart;
X		w  = x - xstart;
X	}
X	if (y<ystart) {
X		ys = y;
X		h  = ystart - y;
X	} else {
X		ys = ystart;
X		h  = y - ystart;
X	}
X	GetBuffer(xstart,ystart,x,y);
X	DrawRectangle(xs,ys,w,h,TRUE,0);
X	ShowBuffer();
X}
X
XTrackEllipfill(flag,x,y)
Xint	flag,x,y;
X{
X	static int 	xstart,ystart;
X	int		xs,ys,w,h;
X
X	if (flag) {
X		xstart = x;
X		ystart = y;
X		return;
X	}
X	if (x<xstart) {
X		xs = x;
X		w  = xstart - x;
X	} else {
X		xs = xstart;
X		w  = x - xstart;
X	}
X	if (y<ystart) {
X		ys = y;
X		h  = ystart - y;
X	} else {
X		ys = ystart;
X		h  = y - ystart;
X	}
X	GetBuffer(xstart,ystart,x,y);
X	DrawFillEllipse(xs,ys,w,h);
X	ShowBuffer();
X}
X
XTrackBrush(flag,x,y)
Xint	flag,x,y;
X{
X	int	xs=16,ys=10;
X
X	if (flag) {
X		GetBuffer(0,0,draw.width,draw.height);
X	}
X	if (x+xs>draw.width)
X		xs=draw.width-x;
X	if (y+ys>draw.height)
X		ys=draw.height-y;
X	FillRectangle(x,y,xs,ys,CurrentWindow->black);
X	ShowSubBuffer(x,y,x+xs,y+ys);
X}
X
X#include "spraypat.xbm"
Xstatic char	SprayBits[spraypattern_height*spraypattern_width];
Xchar		*SprayBitmap = spraypattern_bits;
Xstatic int	SprayFirst=TRUE;
X
XEditSpray()
X{
X	int	x,y;
X	int	xw=(spraypattern_width+7)/8;
X
X	if (SprayFirst) {
X		for (y=0;y<spraypattern_height;y++) 
X			for (x=0;x<spraypattern_width;x++)
X				if ((spraypattern_bits[(y*xw)+(x/8)]&(1<<(x%8)))!=0){
X					SprayBits[x+y*spraypattern_width]=FALSE;
X				} else {
X					SprayBits[x+y*spraypattern_width]=TRUE;
X				}
X		SprayFirst=FALSE;
X	}
X	Bitedit(spraypattern_width,spraypattern_height,SprayBits);
X}
X
XTrackSpray(flag,xp,yp)
Xint	flag,xp,yp;
X{
X	int		x,y;
X	int		xw = (spraypattern_width+7)/8;
X
X	if (flag) {
X		GetBuffer(0,0,draw.width,draw.height);
X		if (SprayFirst) {
X			for (y=0;y<spraypattern_height;y++) 
X				for (x=0;x<spraypattern_width;x++)
X					if ((spraypattern_bits[(y*xw)+(x/8)]&(1<<(x%8)))!=0){
X						SprayBits[x+y*spraypattern_width] = FALSE;
X					} else {
X						SprayBits[x+y*spraypattern_width] = TRUE;
X					}
X			SprayFirst=FALSE;
X		}
X	}
X	for (y=0;y<spraypattern_height;y++) 
X		for (x=0;x<spraypattern_width;x++)
X			if (!SprayBits[x+y*spraypattern_width])
X				PUT_PIXEL(xp+x,yp+y);
X	ShowSubBuffer(xp,yp,xp+spraypattern_width,yp+spraypattern_height);
X}
X
XTrackDotBox(flag,x,y)
Xint	flag,x,y;
X{
X	static int 	xstart,ystart;
X	int		xs,ys,w,h;
X
X	if (flag) {
X		xstart = x;
X		ystart = y;
X		return;
X	}
X	if (x<xstart) {
X		xs = x;
X		w  = xstart - x;
X	} else {
X		xs = xstart;
X		w  = x - xstart;
X	}
X	if (y<ystart) {
X		ys = y;
X		h  = ystart - y;
X	} else {
X		ys = ystart;
X		h  = y - ystart;
X	}
X	GetBuffer(xstart,ystart,x,y);
X	DrawRectangle(xs,ys,w,h,FALSE,1);
X	ShowBuffer();
X}
X
XTrackArrow(flag,x,y)
Xint	flag,x,y;
X{
X	static int	work_flag;
X	static int	dx,dy;
X	int		xstart,ystart,xend,yend;
X
X	if (flag) {
X		if (Between(select_buffer.x,x,
X			    select_buffer.x+select_buffer.width) &&
X		    Between(select_buffer.y,y,
X			    select_buffer.y+select_buffer.height)) {
X			dx = select_buffer.x - x;
X			dy = select_buffer.y - y;
X			work_flag = TRUE;
X		} else {
X			work_flag = FALSE;
X		}
X		return;
X	}
X	if (!work_flag)
X		return;
X	select_buffer.x = xstart = x + dx;
X	select_buffer.y = ystart = y + dy;
X	xend = xstart + select_buffer.width;
X	yend = ystart + select_buffer.height;
X	GetBuffer(xstart,ystart,xend,yend);
X	ShowBuffer();
X	XPutImage(CurrentWindow->display,draw.window,
X		draw.gc,select_buffer.image,
X		select_buffer.xs,0,select_buffer.x,select_buffer.y,
X		select_buffer.width,select_buffer.height);
X}
X
XTrackFatbits(flag,x,y)
Xint	flag,x,y;
X{
X	static long	color;
X	int		go=TRUE;
X
X	if (Between(0,x,fatbits.width+6-fatbits.width%6) &&
X	    Between(0,y,fatbits.height+6-fatbits.height%6)) 
X		go=FALSE;
X	x = x/6;
X	y = y/6;
X	if (flag) {
X		GetBuffer(fatbits.x,fatbits.y,
X			fatbits.x+fatbits.width,fatbits.y+fatbits.height);
X		color = (XGetPixel(draw.buffer,
X				   CurrentWindow->img_offx+fatbits.x+x,
X				   fatbits.y+y)
X			    == CurrentWindow->white) ? 
X			 CurrentWindow->black : CurrentWindow->white;
X	}
X
X	if (color==CurrentWindow->white) {
X		if (go)
X			XFillRectangle(CurrentWindow->display,draw.window,
X				CurrentWindow->gc,x*6,y*6,5,5);
X		XDrawPoint(CurrentWindow->display,draw.window,
X			CurrentWindow->gc,x,y);
X	} else {
X		if (go)
X			XFillRectangle(CurrentWindow->display,draw.window,
X				CurrentWindow->igc,x*6,y*6,5,5);
X		XDrawPoint(CurrentWindow->display,draw.window,
X			CurrentWindow->igc,x,y);
X	}
X	PUT_C_PIXEL(color,fatbits.x+x,fatbits.y+y);
X}
X
XTrackFatHand(flag,x,y)
Xint	flag,x,y;
X{
X	static int	xstart,ystart;
X	static int	orig_offx,orig_offy;
X	int		dx,dy;
X	int		ddx,ddy;
X	long		pix;
X	int		xp,yp;
X
X	x = x/6;
X	y = y/6;
X	if (flag) {
X		xstart = x;
X		ystart = y;
X		orig_offx = fatbits.x;
X		orig_offy = fatbits.y;
X		return;
X	}
X
X	dx = xstart-x;
X	dy = ystart-y;
X
X        if ((CurrentWindow->img_offx+orig_offx+dx)<0) {
X                dx = -(orig_offx+CurrentWindow->img_offx);
X        }
X        if ((orig_offx+dx+fatbits.width)>CurrentWindow->img_width) {
X                dx=CurrentWindow->img_width-fatbits.width-orig_offx;
X        }
X        if ((CurrentWindow->img_offy+orig_offy+dy)<0) {
X                dy = -(orig_offy+CurrentWindow->img_offy);
X        }
X        if ((orig_offy+dy+fatbits.height)>CurrentWindow->img_height) {
X                dy=CurrentWindow->img_height-fatbits.height-orig_offy;
X        }
X
X        ddx = fatbits.x;
X        ddy = fatbits.y;
X
X        fatbits.x = dx + orig_offx;
X        dx = ddx - fatbits.x ;
X
X	XClearArea(CurrentWindow->display,draw.window,
X		0,0,fatbits.width+6-fatbits.width%6,
X		fatbits.height+6-fatbits.height%6,False);
X	for (yp=0;yp<((fatbits.height+5)/6);yp++) {
X		for (xp=0;xp<((fatbits.width+5)/6);xp++) {
X			pix = XGetPixel(CurrentWindow->master,
X				CurrentWindow->img_offx+fatbits.x+xp,
X				CurrentWindow->img_offy+fatbits.y+yp);
X			if (pix!=CurrentWindow->white)
X				XFillRectangle(CurrentWindow->display,
X					draw.window,CurrentWindow->igc,
X					xp*6,yp*6,5,5);
X		}
X	}
X
X	if (SIGN(dx) == -1) {
X                XCopyArea(CurrentWindow->display,draw.window,
X                          draw.window,draw.gc,
X                          -dx*6,0,
X                          (fatbits.width+dx)*6,
X                          draw.height,
X                          0,0);
X		XClearArea(CurrentWindow->display,draw.window,
X			(fatbits.width+dx-1)*6,0,(-dx+1)*6,draw.height,False);
X		for (yp=0;yp<fatbits.height;yp++) {
X			for (xp=fatbits.width+dx-1;xp<fatbits.width;xp++) {
X				pix = XGetPixel(CurrentWindow->master,
X					CurrentWindow->img_offx+fatbits.x+xp,
X					CurrentWindow->img_offy+fatbits.y+yp);
X				if (pix!=CurrentWindow->white)
X					XFillRectangle(CurrentWindow->display,
X						draw.window,CurrentWindow->igc,
X						xp*6,yp*6,5,5);
X			}
X		}
X	} else if (SIGN(dx) == 1) {
X                XCopyArea(CurrentWindow->display,draw.window,
X                          draw.window,draw.gc,
X                          0,0,
X                          (fatbits.width-dx)*6,
X                          draw.height,
X                          dx*6,0);
X		XClearArea(CurrentWindow->display,draw.window,
X			0,0,dx*6,draw.height,False);
X		for (yp=0;yp<fatbits.height;yp++) {
X			for (xp=0;xp<dx;xp++) {
X				pix = XGetPixel(CurrentWindow->master,
X					CurrentWindow->img_offx+fatbits.x+xp,
X					CurrentWindow->img_offy+fatbits.y+yp);
X				if (pix!=CurrentWindow->white)
X					XFillRectangle(CurrentWindow->display,
X						draw.window,CurrentWindow->igc,
X						xp*6,yp*6,5,5);
X			}
X		}
X	}
X
X	fatbits.y = dy + orig_offy;
X	dy = ddy - fatbits.y;
X	if (SIGN(dy) == -1) {
X                XCopyArea(CurrentWindow->display,draw.window,
X                          draw.window,draw.gc,
X                          0,-dy*6,
X                          draw.width,
X                          (fatbits.height+dy)*6,
X                          0,0);
X		XClearArea(CurrentWindow->display,draw.window,
X			0,(fatbits.height+dy-1)*6,draw.width,(-dy+1)*6,False);
X		for (yp=fatbits.height+dy-1;yp<fatbits.height;yp++) {
X			for (xp=0;xp<fatbits.width;xp++) {
X				pix = XGetPixel(CurrentWindow->master,
X					CurrentWindow->img_offx+fatbits.x+xp,
X					CurrentWindow->img_offy+fatbits.y+yp);
X				if (pix!=CurrentWindow->white)
X					XFillRectangle(CurrentWindow->display,
X						draw.window,CurrentWindow->igc,
X						xp*6,yp*6,5,5);
X			}
X		}
X	} else if (SIGN(dy) == 1) {
X                XCopyArea(CurrentWindow->display,draw.window,
X                          draw.window,draw.gc,
X                          0,0,
X                          draw.width,
X			  (fatbits.height-dy)*6,
X                          0,dy*6);
X		XClearArea(CurrentWindow->display,draw.window,
X			0,0,draw.width,dy*6,False);
X		for (yp=0;yp<dy;yp++) {
X			for (xp=0;xp<fatbits.width;xp++) {
X				pix = XGetPixel(CurrentWindow->master,
X					CurrentWindow->img_offx+fatbits.x+xp,
X					CurrentWindow->img_offy+fatbits.y+yp);
X				if (pix!=CurrentWindow->white)
X					XFillRectangle(CurrentWindow->display,
X						draw.window,CurrentWindow->igc,
X						xp*6,yp*6,5,5);
X			}
X		}
X	}
X
X	XPutImage(CurrentWindow->display,draw.window,
X			draw.gc,CurrentWindow->master,
X			CurrentWindow->img_offx+fatbits.x,
X			CurrentWindow->img_offy+fatbits.y,
X			0,0,fatbits.width,fatbits.height);
X}
X
XTrackHand(flag,x,y)
Xint	flag,x,y;
X{
X	static int	xstart,ystart;
X	static int	orig_offx,orig_offy;
X	int		dx,dy;
X	int		ddx,ddy;
X
X	if (flag) {
X		xstart=x;
X		ystart=y;
X		orig_offx = CurrentWindow->img_offx;
X		orig_offy = CurrentWindow->img_offy;
X		return;
X	}
X	dx = xstart-x;
X	dy = ystart-y;
X	if ((orig_offx+dx)<0) {
X		dx = - orig_offx;
X	}
X	if ((orig_offx+dx+draw.width)>CurrentWindow->img_width) {
X		dx=CurrentWindow->img_width-draw.width-orig_offx;
X	}
X	if ((orig_offy+dy)<0) {
X		dy = - orig_offy;
X	}
X	if ((orig_offy+dy+draw.height)>
X	    CurrentWindow->img_height) {
X		dy=CurrentWindow->img_height-draw.height-orig_offy;
X	}
X
X	ddx = CurrentWindow->img_offx ;
X	ddy = CurrentWindow->img_offy ;
X
X	CurrentWindow->img_offx = dx + orig_offx;
X	dx = ddx - CurrentWindow->img_offx;
X
X	if (SIGN(dx) == -1) {
X		XCopyArea(CurrentWindow->display,draw.window,
X			  draw.window,draw.gc,
X			  -dx,0,
X			  draw.width+dx,
X			  draw.height,
X			  0,0);
X		XPutImage(CurrentWindow->display,draw.window,
X			  draw.gc,CurrentWindow->master,
X			  CurrentWindow->img_offx+draw.width+dx-1,
X			  CurrentWindow->img_offy,
X			  draw.width+dx-1,0,
X			  -dx,draw.height);
X	} else if (SIGN(dx) == 1) {
X		XCopyArea(CurrentWindow->display,draw.window,
X			  draw.window,draw.gc,
X			  0,0,
X			  draw.width-dx,
X			  draw.height,
X			  dx,0);
X		XPutImage(CurrentWindow->display,draw.window,
X			  draw.gc,CurrentWindow->master,
X			  CurrentWindow->img_offx,CurrentWindow->img_offy,
X			  0,0,
X			  dx,draw.height);
X	}
X
X	CurrentWindow->img_offy = dy + orig_offy;
X	dy = ddy - CurrentWindow->img_offy;
X	if (SIGN(dy) == -1) {
X		XCopyArea(CurrentWindow->display,draw.window,
X			  draw.window,draw.gc,
X			  0,-dy,
X			  draw.width,
X			  draw.height+dy,
X			  0,0);
X		XPutImage(CurrentWindow->display,draw.window,
X			  draw.gc,CurrentWindow->master,
X			  CurrentWindow->img_offx,
X			  CurrentWindow->img_offy+draw.height+dy-1,
X			  0,draw.height+dy-1,
X			  draw.width,-dy);
X	} else if (SIGN(dy) == 1) {
X		XCopyArea(CurrentWindow->display,draw.window,
X			  draw.window,draw.gc,
X			  0,0,
X			  draw.width,
X			  draw.height-dy,
X			  0,dy);
X		XPutImage(CurrentWindow->display,draw.window,
X			  draw.gc,CurrentWindow->master,
X			  CurrentWindow->img_offx,CurrentWindow->img_offy,
X			  0,0,
X			  draw.width,dy);
X	}
X}
X
XFlickerDot()
X{
X	static int	val = 1;
X	int		xs=buf_xs;
X	int		ys=buf_ys;
X	int		xe=buf_xe-1;
X	int		ye=buf_ye-1;
X	int		w=xe-xs;
X	int		h=ye-ys;
X
X	if (val==3) 
X		val=0;
X	val++;
X}
X
XDoneDotBox()
X{
X	select_buffer.width  = buf_xe - buf_xs;
X	select_buffer.height = buf_ye - buf_ys;
X	select_buffer.xs = buf_xs+CurrentWindow->img_offx;
X	select_buffer.xorig = select_buffer.x  = buf_xs;
X	select_buffer.yorig = select_buffer.y  = buf_ys;
X
X	bcopy(CurrentWindow->master->data+
X	      ((CurrentWindow->img_offy+buf_ys)*
X	       CurrentWindow->master->bytes_per_line),
X	      select_buffer.image->data,
X	      select_buffer.image->bytes_per_line*select_buffer.height);
X
X	XPutImage(CurrentWindow->display,draw.window,
X		draw.gc,CurrentWindow->master,
X		CurrentWindow->img_offx+buf_xs,
X		CurrentWindow->img_offy+buf_ys,
X		buf_xs,buf_ys,
X		buf_xe-buf_xs,buf_ye-buf_ys);
X	FillRectangle(select_buffer.x,select_buffer.y,
X		select_buffer.width,select_buffer.height,CurrentWindow->white);
X	FlushBuffer();
X
X	dot_flag=TRUE;
X	SetAction(C_ARROW);
X	dot_inter_id = AddInterrupt(FlickerDot);
X}
X
XOnGraphic(act,event)
Xint	act;
XXEvent	*event;
X{
X	XEvent	fake_event;
X
X	if (fatbits.flag) {
X
X		if (Between(0,event->xbutton.x,fatbits.width) &&
X		    Between(0,event->xbutton.y,fatbits.height)) {
X			fatbits.flag = FALSE;
X			fake_event.type   = Expose;
X			fake_event.xexpose.x      = 0;
X			fake_event.xexpose.y      = 0;
X			fake_event.xexpose.width  = draw.width;
X			fake_event.xexpose.height = draw.height;
X			EventDraw(&fake_event);
X			return;
X		}
X	}
X
X	if (fatbits.flag) {
X		switch (act) {
X		case C_HAND:
X			Go(event,TrackFatHand,NULL,TRUE);
X			break;
X		default:
X			Go(event,TrackFatbits,NULL,FALSE);
X			break;
X		}
X	} else {
X		draw.lastx = event->xbutton.x;
X		draw.lasty = event->xbutton.y;
X		switch (act) {
X		case C_ARROW:
X			Go(event,TrackArrow,NULL,TRUE);
X			break;
X		case C_HAND:
X			Go(event,TrackHand,NULL,TRUE);
X			break;
X		case C_DOTBOX:
X			Go(event,TrackDotBox,DoneDotBox,TRUE);
X			break;
X		case C_SCISSORS:
X			break;
X		case C_LINE:
X			Go(event,TrackLine,NULL,TRUE);
X			break;
X		case C_ARBLINE:
X			Go(event,TrackArbLine,NULL,FALSE);
X			break;
X		case C_RECTANGLE:
X			Go(event,TrackRectangle,NULL,TRUE);
X			break;
X		case C_ELIPSE:
X			Go(event,TrackEllipse,NULL,TRUE);
X			break;
X		case C_RECTF:
X			Go(event,TrackRectfill,NULL,TRUE);
X			break;
X		case C_ELIPF:
X			Go(event,TrackEllipfill,NULL,TRUE);
X			break;
X		case C_POLYGON:
X			break;
X		case C_FILL:
X			break;
X		case C_BRUSH:
X			Go(event,TrackBrush,NULL,FALSE);
X			break;
X		case C_ERASER:
X			Go(event,TrackEraser,NULL,FALSE);
X			break;
X		case C_TEXT:
X			GoText(event);
X			break;
X		case C_SPRAY:
X			Go(event,TrackSpray,NULL,FALSE);
X			break;
X		}
X	}
X}
X
XGo(event,track_func,done_func,flag)
XXEvent	*event;
Xint 	(*track_func)();
Xint 	(*done_func)();
Xint	flag;
X{
X	XEvent	new_event,tmp_event;
X	int	called=FALSE;
X
X	if ((CurrentActionID != C_ARROW) || (fatbits.flag))
X		FlushBuffer();
X
X	if (track_func!=NULL)
X		track_func(TRUE,event->xbutton.x,event->xbutton.y);
X
X	do {
X		XWindowEvent(CurrentWindow->display,draw.window,
X			ButtonReleaseMask|PointerMotionMask,&new_event);
X		if (new_event.type == MotionNotify) {
X			if ((flag) && XCheckWindowEvent(CurrentWindow->display,
X					draw.window,
X					PointerMotionMask,&tmp_event)) {
X				XPutBackEvent(CurrentWindow->display,
X					&tmp_event);
X				continue;
X			}
X			if (Between(0,new_event.xbutton.x,
X				    draw.width) &&
X			    Between(0,new_event.xbutton.y,
X				     draw.height) &&
X                            (track_func!=NULL))
X				track_func(FALSE,new_event.xmotion.x,
X				  new_event.xmotion.y);
X			called=TRUE;
X		}
X	} while (!((new_event.type == ButtonRelease) &&
X		  (new_event.xbutton.button == event->xbutton.button)));
X
X	if ((!called) && (track_func!=NULL)) {
X		track_func(FALSE,event->xbutton.x,
X			         event->xbutton.y);
X	}
X
X	if (done_func!=NULL)
X		done_func();
X}
X
XDrawSetFont(id,text)
Xint	id;
Xchar	*text;
X{
X	XFontStruct	*font_info;
X
X	font_info = XLoadQueryFont(CurrentWindow->display,text);
X	if (font_info != NULL) {
X		XUnloadFont(CurrentWindow->display,draw.font_info->fid);
X		draw.font_info = font_info;
X		XSetFont(CurrentWindow->display,draw.gc,font_info->fid);
X	}
X}
X
XGoText(old_event)
XXEvent	*old_event;
X{
X	static char 	str[1024];
X	int		index=0;
X	long		pix;
X	XImage		*img;
X	int		done=FALSE;
X	int		xstart,ystart;
X	int		i,n,height;
X	int		x,y;
X	int		maxx,maxy;
X	XEvent		event;
X	char		buf[80];
X	int		xpos,ypos;
X
X	FlushBuffer();
X	GetBuffer(0,0,draw.width,draw.height);
X	xpos = xstart = old_event->xbutton.x;
X	ypos = (ystart = old_event->xbutton.y)+draw.font_info->ascent;
X	maxx=xstart;
X	maxy=ystart;
X	height = draw.font_info->ascent+draw.font_info->descent;
X
X	do {
X		WindowEvent(draw.window,&event);
X		switch (event.type) {
X		case Expose:
X			EventDraw(&event);
X			break;
X		case MotionNotify:
X			break;
X		case ButtonPress:
X			done=TRUE;
X			break;
X		case KeyPress:
X			n=XLookupString(&event,buf,sizeof(buf),NULL,NULL);
X			for (i=0;i<n;i++) {
X				switch (buf[i]) {
X				case '\r':
X				case '\n':
X					xpos=xstart;
X					ypos+=height;
X					break;
X				case CTRL('U'):
X					break;
X				case DELETE:
X				case CTRL('H'):
X					break;
X				default:
X					if (buf[i]>=' ') {
X						str[index++]=buf[i];
X						XDrawString(
X							CurrentWindow->display,
X							draw.window,draw.gc,
X							xpos,ypos,
X							&buf[i],1);
X						xpos+=XTextWidth(draw.font_info,
X							&buf[i],1);
X					}
X				}
X				if (xpos>maxx) maxx=xpos;
X				if (ypos>maxy) maxy=ypos;
X			}
X			break;
X		}
X	} while (!done);
X
X	img = XGetImage(CurrentWindow->display,draw.window,
X			xstart,ystart,maxx-xstart,maxy-ystart,-1,ZPixmap);
X	for (y=0;y<maxy-ystart;y++)
X		for (x=0;x<maxx-xstart;x++) {
X			pix = XGetPixel(img,x,y);
X			XPutPixel(draw.buffer,
X				xstart+x+CurrentWindow->img_offx,ystart+y,pix);
X		}
X	XDestroyImage(img);
X	OnGraphic(CurrentActionID,&event);
X}
X
X/****************************************************************************/
X/****************************************************************************/
X/****************************************************************************/
X/****************************************************************************/
X/****************************************************************************/
X
XDrawLine(xstart,ystart,xend,yend,color)
Xint	xstart,ystart,xend,yend;
Xlong	color;
X{
X	int	x=xstart,y=ystart;
X	int	dx=ABS(xend-xstart),dy=ABS(yend-ystart);
X	int	sx=SIGN(xend-xstart),sy=SIGN(yend-ystart);
X	int	interchange=0;
X	int	e,i;
X
X	if ((xstart==xend) && (yend==ystart)) {
X		PUT_PIXEL(xstart,ystart);
X		return;
X	}
X
X	if (dy>dx) {
X		int	t=dx;
X		dx = dy;
X		dy = t;
X		interchange = 1;
X	}
X	e=2*dy-dx;
X	for (i=0;i<dx;i++) {
X		PUT_C_PIXEL(color,x,y);
X		while (e>=0) {
X			if (interchange!=0) {
X				x=x+sx;
X			} else {
X				y=y+sy;
X			}
X			e=e-2*dx;
X		}
X		if (interchange!=0) {
X			y=y+sy;
X		} else {
X			x=x+sx;
X		}
X		e=e+2*dy;
X	}
X}
X
X/*
X * Draw an ellipse.
X *
X * The algorithm is from "An Efficient Ellipse-Drawing Algorithm" by
X * Jerry R. Van Aken, IEEE CG&A, September 1984, pp. 24-35,
X * specifically, Figure 10 on page 32.
X */
X
XDrawEllipse(xs,ys,width,height)
Xint	xs,ys,width,height;
X{
X	int	a = width/2, b=height/2;
X	int	cx = xs+a, cy=ys+b;
X	int	d1,d2;
X	int	x,y;
X	int	t1,t2,t3,t4,t5,t6,t7,t8,t9;
X
X	/* intermediate terms to speed up loop */
X	t1 = a * a;	t2 = t1 * 2;	t3 = t2 * 2;
X	t4 = b * b;	t5 = t4 * 2;	t6 = t5 * 2;
X	t7 = a * t5;	t8 = t7 * 2;	t9 = 0;
X
X	d1 = t2-t7+(t4/2);	/* error terms */
X	d2 = (t2/2)-t8+t5;
X
X	x = a;
X	y = 0;
X
X	while (d2 < 0 ) {
X		PUT_PIXEL(cx+x,cy+y);
X		PUT_PIXEL(cx+x,cy-y);
X		PUT_PIXEL(cx-x,cy+y);
X		PUT_PIXEL(cx-x,cy-y);
X		y++;
X		t9 += t3;
X		if (d1<0) {
X			d1 += t9+t2;
X			d2 += t9;
X		} else {
X			x--;
X			t8 -= t6;
X			d1 += t9+t2-t8;
X			d2 += t9+t5-t8;
X		}
X	}
X	do {
X		PUT_PIXEL(cx+x,cy+y);
X		PUT_PIXEL(cx+x,cy-y);
X		PUT_PIXEL(cx-x,cy+y);
X		PUT_PIXEL(cx-x,cy-y);
X		x--;
X		t8-=t6;
X		if (d2<0) {
X			y++;
X			t9 += t3;
X			d2 += t9+t5-t8;
X		} else {
X			d2 += t5-t8;
X		}
X	} while (x>=0);
X}
X
XDrawFillEllipse(xs,ys,width,height)
Xint	xs,ys,width,height;
X{
X	int	a = width/2, b=height/2;
X	int	cx = xs+a, cy=ys+b, yp;
X	int	d1,d2;
X	int	x,y;
X	int	t1,t2,t3,t4,t5,t6,t7,t8,t9;
X
X	/* intermediate terms to speed up loop */
X	t1 = a * a;	t2 = t1 * 2;	t3 = t2 * 2;
X	t4 = b * b;	t5 = t4 * 2;	t6 = t5 * 2;
X	t7 = a * t5;	t8 = t7 * 2;	t9 = 0;
X
X	d1 = t2-t7+(t4/2);	/* error terms */
X	d2 = (t2/2)-t8+t5;
X
X	x = a;
X	y = 0;
X
X	while (d2 < 0 ) {
X		PUT_P_PIXEL(cx+x,cy+y);
X		PUT_P_PIXEL(cx+x,cy-y);
X		PUT_P_PIXEL(cx-x,cy+y);
X		PUT_P_PIXEL(cx-x,cy-y);
X		y++;
X		t9 += t3;
X		if (d1<0) {
X			d1 += t9+t2;
X			d2 += t9;
X		} else {
X			for (yp=cy-y-1;yp<cy+y;yp++) {
X				PUT_P_PIXEL(cx+x,yp);
X				PUT_P_PIXEL(cx-x,yp);
X			}
X			x--;
X			t8 -= t6;
X			d1 += t9+t2-t8;
X			d2 += t9+t5-t8;
X		}
X	}
X	do {
X		for (yp=cy-y;yp<=cy+y;yp++) {
X			PUT_P_PIXEL(cx+x,yp);
X			PUT_P_PIXEL(cx-x,yp);
X		}
X		x--;
X		t8-=t6;
X		if (d2<0) {
X			y++;
X			t9 += t3;
X			d2 += t9+t5-t8;
X		} else {
X			d2 += t5-t8;
X		}
X	} while (x>=0);
X}
X
XDrawRectangle(xs,ys,width,height,flag,dot)
Xint	xs,ys,width,height,flag,dot;
X{
X	int	xp,yp;
X	int	xe=xs+width,ye=ys+height;
X
X	if (!flag) {
X		if (dot == 0) {
X			for (xp=xs;xp<xe;xp++) {
X				PUT_PIXEL(xp,ye);
X				PUT_PIXEL(xp,ys);
X			}
X			for (yp=ys;yp<ye;yp++) {
X				PUT_PIXEL(xs,yp);
X				PUT_PIXEL(xe,yp);
X			}
X			PUT_PIXEL(xe,ye);
X		} else {
X			for (xp=xs+dot;xp<xe;xp+=3) {
X				PUT_PIXEL(xp,ye);
X				PUT_PIXEL(xp,ys);
X			}
X			for (yp=ys+dot;yp<ye;yp+=3) {
X				PUT_PIXEL(xs,yp);
X				PUT_PIXEL(xe,yp);
X			}
X		}
X	} else {
X		for (yp=ys;yp<ye;yp++) {
X			for (xp=xs;xp<xe;xp++) {
X				PUT_P_PIXEL(xp,yp);
X			}
X		}
X	}
X}
X
XFillRectangle(xs,ys,width,height,color)
Xint	xs,ys,width,height;
Xlong	color;
X{
X	int	xp,yp;
X	int	xe=xs+width,ye=ys+height;
X
X	for (xp=xs;xp<xe;xp++)
X		for (yp=ys;yp<ye;yp++) 
X			PUT_C_PIXEL(color,xp,yp);
X}
END_OF_FILE
if test 36994 -ne `wc -c <'draw.c'`; then
    echo shar: \"'draw.c'\" unpacked with wrong size!
fi
# end of 'draw.c'
fi
if test -f 'menu.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'menu.c'\"
else
echo shar: Extracting \"'menu.c'\" \(11231 characters\)
sed "s/^X//" >'menu.c' <<'END_OF_FILE'
X/* +------------------------------------------------------------------+ */
X/* | Copyright 1989, David Koblas.                                    | */
X/* |   You may copy this file in whole or in part as long as you      | */
X/* |   don't try to make money off it, or pretend that you wrote it.  | */
X/* +------------------------------------------------------------------+ */
X
X#include <stdio.h>
X#include "xpaint.h"
X
X#define MAX(a,b)		(((a)<(b))?(b):(a))
X
Xstatic GC		menu_gc,menu_igc;
Xstatic XFontStruct	*font_info;
Xstatic Window		item_window;
Xstatic Pixmap		buf_pixmap;
Xstatic int		buf_xs,buf_ys;
X
Xstatic void	bogus_func() { ; }
X
Xvoid	DrawUndo();
Xvoid	Quit();
Xvoid	DrawSetFont();
Xvoid	DrawBufferInvert(),DrawFlipHorz(),DrawFlipVert();
Xvoid	SaveMenu(),SaveMenuAs();
Xvoid	SaveRegion(),CloseDraw(),OpenFile(),OpenDraw();
X
X#ifndef lint
Xstatic char rcsid[]="$Header: menu.c,v 1.2 89/02/20 19:32:59 koblas Locked $";
X#endif
X
Xstruct s_menu_items {
X	int	id;
X	char	*text;
X	int	state;
X	void	(*func)();
X};
X
Xstruct s_menu_items	file_items[] = {
X		{0, "Open", TRUE, OpenDraw},
X		{0, "Close", TRUE, CloseDraw},
X		{0, "Read", TRUE, OpenFile},
X		{0, "Save", TRUE, SaveMenu},
X		{0, "Save As", TRUE, SaveMenuAs},
X		{0, "Save Region", TRUE, SaveRegion},
X		{0, "Quit", TRUE , Quit},
X};
X
Xstruct s_menu_items	buffer_items[] = {
X		{0, "Undo", TRUE, DrawUndo},
X		{0, "-", TRUE, NULL},
X		{0, "Cut", TRUE, bogus_func},
X		{0, "Copy", TRUE, bogus_func},
X		{0, "Clear", TRUE, bogus_func},
X		{0, "Invert", TRUE, DrawBufferInvert},
X		{0, "Flip Horz.", TRUE, DrawFlipHorz},
X		{0, "Flip Vert.", TRUE, DrawFlipVert},
X};
X
Xstruct s_menu_items	font_items[] = {
X		{0, "6x10",		TRUE, DrawSetFont},
X		{1, "6x12",		TRUE, DrawSetFont},
X		{2, "8x13",		TRUE, DrawSetFont},
X		{3, "8x13bold",		TRUE, DrawSetFont},
X		{4, "9x15",		TRUE, DrawSetFont},
X		{5, "cursor",		TRUE, DrawSetFont},
X		{6, "gallant.r.10",	TRUE, DrawSetFont},
X		{7, "gallant.r.19",	TRUE, DrawSetFont},
X		{8, "cmr.b.14",		TRUE, DrawSetFont},
X		{9, "cmr.b.8",		TRUE, DrawSetFont},
X		{10, "cmr.r.14",	TRUE, DrawSetFont},
X		{11, "cmr.r.8",		TRUE, DrawSetFont},
X		{12, "apl.r.10",	TRUE, DrawSetFont},
X		{13, "variable",	TRUE, DrawSetFont},
X};
X
Xstruct {
X	char			*title;
X	int			xstart,xend,width;
X	int			item_width;
X	int			item_height;
X	int			n_items;
X	struct s_menu_items	*items;
X} menu[] = {
X	{ "File", 0, 0, 0, 0, 0,
X		sizeof(file_items)/sizeof(file_items[0]), file_items },
X	{ "Buffer", 0, 0, 0, 0, 0,
X		sizeof(buffer_items)/sizeof(buffer_items[0]), buffer_items },
X	{ "Font", 0, 0, 0, 0, 0,
X		sizeof(font_items)/sizeof(font_items[0]), font_items },
X};
X
X#define PAD		15
X#define HEIGHT		15
X
XWindow CreateMenu()
X{
X	int			i,w,x,j;
X	int			max_w=0,max_h=0;
X	XSetWindowAttributes	attr;
X	Window			wind;
X	XGCValues		values;
X
X	attr.background_pixel = CurrentWindow->white;
X	attr.event_mask = ExposureMask|ButtonPressMask|
X			  ButtonReleaseMask|PointerMotionMask;
X	
X	wind = XCreateWindow(CurrentWindow->display,CurrentWindow->window,
X			    DELTA_XPOS(MENU_ID),DELTA_YPOS(MENU_ID),
X			    CurrentWindow->width,HEIGHT,
X			    0,0,0,0,CWBackPixel|CWEventMask,&attr);
X
X	item_window = XCreateWindow(CurrentWindow->display,
X			    CurrentWindow->window,
X			    DELTA_XPOS(MENU_ID),DELTA_YPOS(MENU_ID),
X			    1,1,0,0,0,0,CWBackPixel|CWEventMask,&attr);
X
X	values.foreground = CurrentWindow->white;
X	values.background = CurrentWindow->black;
X	font_info = XLoadQueryFont(CurrentWindow->display,DEF_FONT);
X	if (font_info == NULL) {
X		fprintf(stderr,"Unable to open font %s\n",DEF_FONT);
X		exit(1);
X	}
X	values.font	  = font_info->fid;
X
X	menu_igc = XCreateGC(CurrentWindow->display,wind,
X			GCForeground|GCBackground|GCFont,&values);
X
X	values.foreground = CurrentWindow->black;
X	values.background = CurrentWindow->white;
X	menu_gc = XCreateGC(CurrentWindow->display,wind,
X			GCForeground|GCBackground|GCFont,&values);
X
X	XMapWindow(CurrentWindow->display,wind);
X
X	x=PAD;
X	for (i=0;i<sizeof(menu)/sizeof(menu[0]);i++) {
X		menu[i].xstart = x;
X		menu[i].width = XTextWidth(font_info,menu[i].title,
X						strlen(menu[i].title));
X		menu[i].xend = x+menu[i].width;
X		x += menu[i].width+PAD;
X
X		for (j=0;j<menu[i].n_items;j++) {
X			w=XTextWidth(font_info,menu[i].items[j].text,
X				strlen(menu[i].items[j].text));
X			menu[i].item_width=MAX(w+10,menu[i].item_width);
X		}
X		menu[i].item_height = (font_info->max_bounds.ascent+
X				       font_info->max_bounds.descent)*
X				      menu[i].n_items;
X		max_w=MAX(menu[i].item_width,max_w);
X		max_h=MAX(menu[i].item_height,max_h);
X	}
X
X	buf_pixmap = XCreatePixmap(CurrentWindow->display,
X				   CurrentWindow->window,max_w,max_h,
X				   CurrentWindow->depth);
X
X	return wind;
X}
X
Xvoid ResizeMenu()
X{
X	XResizeWindow(CurrentWindow->display,
X		      CurrentWindow->subwind[MENU_ID].window,
X		      CurrentWindow->width,HEIGHT);
X}
X
Xvoid EventMenu(event)
XXEvent	*event;
X{
X	switch (event->type) {
X	case Expose:
X		redraw();
X		break;
X	case ButtonPress:
X		track_mouse(event);
X		break;
X	}
X}
X
Xstatic redraw()
X{
X	int	i;
X
X	for (i=0;i<sizeof(menu)/sizeof(menu[0]);i++) {
X		XDrawImageString(CurrentWindow->display,
X			CurrentWindow->subwind[MENU_ID].window,
X			menu_gc,menu[i].xstart,font_info->ascent,
X			menu[i].title,strlen(menu[i].title));
X	}
X}
X
Xstatic track_mouse(event)
XXEvent	*event;
X{
X	XEvent	new_event;
X	int	i;
X	int	xpos,ypos;
X	int	active_menu= -1,new_active_menu= -1;
X	int	active_item= -1,new_active_item= -1;
X
X	xpos = event->xbutton.x;
X	ypos = event->xbutton.y;
X
X
X	do {
X		if (ypos<HEIGHT) {
X			new_active_menu = -1;
X			for (i=0;i<sizeof(menu)/sizeof(menu[0]);i++) {
X				if (Between(menu[i].xstart-5,
X					    xpos,menu[i].xend+5)) {
X					new_active_menu = i;
X				}
X			}
X			new_active_item = -1;
X		} else if (active_menu != -1) {
X			if ((ypos-HEIGHT)<menu[active_menu].item_height) {
X				new_active_item = (ypos-HEIGHT)/
X					(font_info->max_bounds.ascent+
X					 font_info->max_bounds.descent);
X			} else {
X				new_active_item = -1;
X			}
X			if ((menu[active_menu].items[new_active_item].func  == NULL) ||
X			    (menu[active_menu].items[new_active_item].state == FALSE))
X				new_active_item = -1;
X		}
X
X		if (new_active_menu != active_menu) {
X			if (active_menu != -1) {
X				XUnmapWindow(CurrentWindow->display,item_window);
X				XFillRectangle(CurrentWindow->display,
X					CurrentWindow->subwind[MENU_ID].window,
X					menu_igc,menu[active_menu].xstart-5,
X					0,menu[active_menu].width+10,HEIGHT);
X				XDrawImageString(CurrentWindow->display,
X					CurrentWindow->subwind[MENU_ID].window,
X					menu_gc,menu[active_menu].xstart,
X					font_info->ascent,
X					menu[active_menu].title,
X					strlen(menu[active_menu].title));
X				XFlush(CurrentWindow->display);
X			}
X			active_menu = new_active_menu;
X			if (active_menu != -1) {
X				buf_xs = menu[active_menu].xstart-5;
X				buf_ys = HEIGHT;
X				XMoveResizeWindow(CurrentWindow->display,
X					item_window,menu[active_menu].xstart-5,
X					HEIGHT,menu[active_menu].item_width,
X					menu[active_menu].item_height);
X				XMapWindow(CurrentWindow->display,item_window);
X				XFillRectangle(CurrentWindow->display,
X					CurrentWindow->subwind[MENU_ID].window,
X					menu_gc,menu[active_menu].xstart-5,
X					0,menu[active_menu].width+10,HEIGHT);
X				XDrawImageString(CurrentWindow->display,
X					CurrentWindow->subwind[MENU_ID].window,
X					menu_igc,menu[active_menu].xstart,
X					font_info->ascent,
X					menu[active_menu].title,
X					strlen(menu[active_menu].title));
X				XFlush(CurrentWindow->display);
X				WindowEvent(item_window,&new_event);
X				for (i=0;i<menu[active_menu].n_items;i++) {
X					PutMenuItem(FALSE,active_menu,i);
X				}
X			}
X		}
X
X		if ((active_menu != -1) && (new_active_item != active_item)) {
X			if (active_item != -1) {
X				PutMenuItem(FALSE,active_menu,active_item);
X#if 0
X				XFillRectangle(CurrentWindow->display,
X					item_window,menu_igc,0,active_item*
X						(font_info->max_bounds.ascent+
X						 font_info->max_bounds.descent),
X					menu[active_menu].item_width+10,
X					(font_info->max_bounds.ascent+
X					 font_info->max_bounds.descent));
X				XDrawImageString(CurrentWindow->display,
X					item_window,
X					menu_gc,5,
X					font_info->ascent+active_item*
X						(font_info->max_bounds.ascent+
X						 font_info->max_bounds.descent),
X					menu[active_menu].
X						items[active_item].text,
X					strlen(menu[active_menu].
X						items[active_item].text));
X#endif
X			}
X			active_item = new_active_item;
X			if (active_item != -1) {
X				PutMenuItem(TRUE,active_menu,active_item);
X#if 0
X				XFillRectangle(CurrentWindow->display,
X					item_window,menu_gc,0,active_item*
X						(font_info->max_bounds.ascent+
X						 font_info->max_bounds.descent),
X					menu[active_menu].item_width+10,
X					(font_info->max_bounds.ascent+
X					 font_info->max_bounds.descent));
X				XDrawImageString(CurrentWindow->display,
X					item_window,
X					menu_igc,5,
X					font_info->ascent+active_item*
X						(font_info->max_bounds.ascent+
X						 font_info->max_bounds.descent),
X					menu[active_menu].
X						items[active_item].text,
X					strlen(menu[active_menu].
X						items[active_item].text));
X				XFlush(CurrentWindow->display);
X#endif
X			}
X		}
X
X		WindowEvent(CurrentWindow->subwind[MENU_ID].window,&new_event);
X		if (new_event.type == MotionNotify) {
X			xpos = new_event.xmotion.x;
X			ypos = new_event.xmotion.y;
X		}
X	} while (!((new_event.type == ButtonRelease) && 
X		   (new_event.xbutton.button == event->xbutton.button)));
X
X	if (active_menu != -1) {
X		XUnmapWindow(CurrentWindow->display,item_window);
X		XFillRectangle(CurrentWindow->display,
X			CurrentWindow->subwind[MENU_ID].window,
X			menu_igc,menu[active_menu].xstart-5,
X			0,menu[active_menu].width+10,HEIGHT);
X		XDrawImageString(CurrentWindow->display,
X			CurrentWindow->subwind[MENU_ID].window,
X			menu_gc,menu[active_menu].xstart,
X			font_info->ascent,
X			menu[active_menu].title,
X			strlen(menu[active_menu].title));
X		if (active_item != -1) {
X			menu[active_menu].items[active_item].func(
X			     menu[active_menu].items[active_item].id,
X			     menu[active_menu].items[active_item].text);
X		}
X	}
X}
X
Xstatic PutMenuItem(flag,menu_num,item)
Xint	flag,menu_num,item;
X{
X	GC	gc,igc;
X
X	if (flag) {
X		gc=menu_igc;
X		igc=menu_gc;
X	} else {
X		igc=menu_igc;
X		gc=menu_gc;
X	}
X
X
X	XFillRectangle(CurrentWindow->display,item_window,igc,0,
X		       item*(font_info->max_bounds.ascent+
X                                    font_info->max_bounds.descent),
X                       menu[menu_num].item_width+10,
X                       (font_info->max_bounds.ascent+
X			font_info->max_bounds.descent));
X
X	if ((menu[menu_num].items[item].text[0]=='-') &&
X	    (menu[menu_num].items[item].text[1]=='\0')) {
X		XDrawLine(CurrentWindow->display,item_window,gc,
X			0,((font_info->max_bounds.ascent+
X			    font_info->max_bounds.descent)/2)+
X			  (item*(font_info->max_bounds.ascent+
X			         font_info->max_bounds.descent)),
X			menu[menu_num].item_width,
X			((font_info->max_bounds.ascent+
X			  font_info->max_bounds.descent)/2)+
X			(item*(font_info->max_bounds.ascent+
X		               font_info->max_bounds.descent)));
X		return;
X	}
X	XDrawString(CurrentWindow->display,item_window,gc,5,
X                         font_info->max_bounds.ascent+
X			 item*(font_info->max_bounds.ascent+
X			       font_info->max_bounds.descent),
X		         menu[menu_num].items[item].text,
X                         strlen(menu[menu_num].items[item].text));
X}
END_OF_FILE
if test 11231 -ne `wc -c <'menu.c'`; then
    echo shar: \"'menu.c'\" unpacked with wrong size!
fi
# end of 'menu.c'
fi
if test -f 'pat_09.xbm' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'pat_09.xbm'\"
else
echo shar: Extracting \"'pat_09.xbm'\" \(949 characters\)
sed "s/^X//" >'pat_09.xbm' <<'END_OF_FILE'
X#define pattern_09_width 32
X#define pattern_09_height 32
X#define pattern_09_x_hot -1
X#define pattern_09_y_hot -1
Xstatic char pattern_09_bits[] = {
X   0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
X   0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
X   0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff,
X   0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
X   0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
X   0x00, 0x01, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x01, 0x00,
X   0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
X   0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00,
X   0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
X   0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
X   0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01};
END_OF_FILE
if test 949 -ne `wc -c <'pat_09.xbm'`; then
    echo shar: \"'pat_09.xbm'\" unpacked with wrong size!
fi
# end of 'pat_09.xbm'
fi
echo shar: End of archive 1 \(of 3\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mike Wexler(wyse!mikew)    Phone: (408)433-1000 x1330
Moderator of comp.sources.x