[comp.sources.x] v03i032: MacPaint-like graphics, Part02/03

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

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

#! /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 2 (of 3)."
# Contents:  Makefile ReadXBM.c action.c bitedit.c event.c main.c
#   pattern.c save.c
# Wrapped by mikew@wyse on Wed Feb 22 13:37:41 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(6768 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# Makefile generated by imake - do not edit!
X# $XConsortium: imake.c,v 1.37 88/10/08 20:08:30 jim Exp $
X#
X# The cpp used on this machine replaces all newlines and multiple tabs and
X# spaces in a macro expansion with a single space.  Imake tries to compensate
X# for this, but is not always successful.
X#
X
X###########################################################################
X# X Window System Makefile generated from template file Imake.tmpl
X# $XConsortium: Imake.tmpl,v 1.91 88/10/23 22:37:10 jim Exp $
X#
X# Do not change the body of the imake template file.  Server-specific
X# parameters may be set in the appropriate .macros file; site-specific
X# parameters (but shared by all servers) may be set in site.def.  If you
X# make any changes, you'll need to rebuild the makefiles using
X# "make World" (at best) or "make Makefile; make Makefiles" (at least) in
X# the top level directory.
X#
X# If your C preprocessor doesn't define any unique symbols, you'll need
X# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
X# "make Makefile", "make Makefiles", or "make World").
X#
X# If you absolutely can't get imake to work, you'll need to set the
X# variables at the top of each Makefile as well as the dependencies at the
X# bottom (makedepend will do this automatically).
X#
X
X###########################################################################
X# platform-specific configuration parameters - edit Sun.macros to change
X
X# platform:  $XConsortium: Sun.macros,v 1.52 88/10/23 11:00:55 jim Exp $
X# operating system:   SunOS 3.4
X
XBOOTSTRAPCFLAGS =
X             AS = as
X             CC = cc
X            CPP = /lib/cpp
X             LD = ld
X           LINT = lint
X        INSTALL = install
X           TAGS = ctags
X             RM = rm -f
X             MV = mv
X             LN = ln -s
X         RANLIB = ranlib
XRANLIBINSTFLAGS = -t
X             AR = ar clq
X             LS = ls
X       LINTOPTS = -xz
X    LINTLIBFLAG = -C
X           MAKE = make
XSTD_CPP_DEFINES =
X    STD_DEFINES =
X
X###########################################################################
X# site-specific configuration parameters - edit site.def to change
X
X# site:  $XConsortium: site.def,v 1.16 88/10/12 10:30:24 jim Exp $
X
X###########################################################################
X# definitions common to all Makefiles - do not edit
X
X          SHELL =  /bin/sh
X
X        DESTDIR = /global
X      USRLIBDIR = $(DESTDIR)/lib
X         BINDIR = $(DESTDIR)/bin/X11
X         INCDIR = $(DESTDIR)/include
X         ADMDIR = $(DESTDIR)/usr/adm
X         LIBDIR = $(USRLIBDIR)/X11
X     LINTLIBDIR = $(USRLIBDIR)/lint
X        FONTDIR = $(LIBDIR)/fonts
X       XINITDIR = $(LIBDIR)/xinit
X         XDMDIR = $(LIBDIR)/xdm
X         UWMDIR = $(LIBDIR)/uwm
X         AWMDIR = $(LIBDIR)/awm
X         TWMDIR = $(LIBDIR)/twm
X          DTDIR = $(LIBDIR)/dt
X        MANPATH = /usr/man
X  MANSOURCEPATH = $(MANPATH)/man
X         MANDIR = $(MANSOURCEPATH)n
X      LIBMANDIR = $(MANSOURCEPATH)n3
X    XAPPLOADDIR = $(LIBDIR)/app-defaults
X
X   INSTBINFLAGS = -m 0755
X   INSTUIDFLAGS = -m 4755
X   INSTLIBFLAGS = -m 0664
X   INSTINCFLAGS = -m 0444
X   INSTMANFLAGS = -m 0444
X   INSTAPPFLAGS = -m 0444
X  INSTKMEMFLAGS = -m 4755
X        FCFLAGS = -t
X    CDEBUGFLAGS = -O
X
X        PATHSEP = /
X         DEPEND = $(BINDIR)/makedepend
X          IMAKE = $(BINDIR)/imake
X            RGB = $(LIBDIR)/rgb
X             FC = $(BINDIR)/bdftosnf
X      MKFONTDIR = $(BINDIR)/mkfontdir
X      MKDIRHIER = $(BINDIR)/mkdirhier.sh
X
X         CFLAGS = $(CDEBUGFLAGS) $(INCLUDES) $(STD_DEFINES) $(DEFINES)
X      LINTFLAGS = $(LINTOPTS) $(INCLUDES) $(STD_DEFINES) $(DEFINES) -DLINT
X        LDFLAGS = $(CDEBUGFLAGS) -L$(USRLIBDIR) $(SYS_LIBRARIES) $(SYSAUX_LIBRARIES)
X
X       IRULESRC = $(LIBDIR)/imake.includes
X
X   EXTENSIONLIB = $(USRLIBDIR)/libext.a
X           XLIB = $(USRLIBDIR)/libX11.a
X         XMULIB = $(USRLIBDIR)/libXmu.a
X        OLDXLIB = $(USRLIBDIR)/liboldX.a
X       XTOOLLIB = $(USRLIBDIR)/libXt.a
X         XAWLIB = $(USRLIBDIR)/libXaw.a
X       LINTXLIB = $(USRLIBDIR)/lint/llib-lX11.ln
X        LINTXMU = $(USRLIBDIR)/lint/llib-lXmu.ln
X      LINTXTOOL = $(USRLIBDIR)/lint/llib-lXt.ln
X        LINTXAW = $(USRLIBDIR)/lint/llib-lXaw.ln
X       INCLUDES = -I$(INCDIR)
X      MACROFILE = Sun.macros
X   ICONFIGFILES = $(IRULESRC)/Imake.tmpl \
X			$(IRULESRC)/$(MACROFILE) $(IRULESRC)/site.def
X  IMAKE_DEFINES =
X      IMAKE_CMD = $(NEWTOP)$(IMAKE) -TImake.tmpl -I$(NEWTOP)$(IRULESRC) \
X			-s Makefile $(IMAKE_DEFINES)
X         RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a \
X			.emacs_* tags TAGS make.log MakeOut
X
X###########################################################################
X# rules:  $XConsortium: Imake.rules,v 1.71 88/10/23 22:46:34 jim Exp $
X
X###########################################################################
X# start of Imakefile
X
X  SYS_LIBRARIES = -ll -lm $(XMULIB) $(XLIB)
XLOCAL_LIBRARIES =
X           SRCS = ReadXBM.c draw.c menu.c save.c action.c event.c \
X                  pattern.c version.c bitedit.c main.c read.c
X           OBJS = ReadXBM.o draw.o menu.o save.o action.o event.o \
X                  pattern.o version.o bitedit.o main.o read.o
X
X PROGRAM = xpaint
X
Xall:: xpaint
X
Xxpaint: $(OBJS) $(LOCAL_LIBRARIES)
X	$(RM) $@
X	$(CC) -o $@ $(OBJS) $(LOCAL_LIBRARIES) $(LDFLAGS) $(SYSLAST_LIBRARIES)
X
Xrelink::
X	$(RM) $(PROGRAM)
X	$(MAKE) $(MFLAGS) $(PROGRAM)
X
Xinstall:: xpaint
X	$(INSTALL) -c $(INSTALLFLAGS) xpaint $(BINDIR)
X
Xinstall.man:: xpaint.man
X	$(INSTALL) -c $(INSTMANFLAGS) xpaint.man $(MANDIR)/xpaint.n
X
Xdepend:: $(DEPEND)
X
Xdepend::
X	$(DEPEND) -s "# DO NOT DELETE" -- $(CFLAGS) -- $(SRCS)
X
X$(DEPEND):
X	@echo "making $@"; \
X	cd $(DEPENDSRC); $(MAKE)
X
Xclean::
X	$(RM) $(PROGRAM)
X
Xlint:
X	$(LINT) $(LINTFLAGS) $(SRCS) $(LINTLIBS)
Xlint1:
X	$(LINT) $(LINTFLAGS) $(FILE) $(LINTLIBS)
X
X###########################################################################
X# Imake.tmpl common rules for all Makefiles - do not edit
X
Xemptyrule::
X
Xclean::
X	$(RM_CMD) \#*
X
XMakefile:: $(IMAKE)
X
XMakefile:: Imakefile \
X	$(IRULESRC)/Imake.tmpl \
X	$(IRULESRC)/Imake.rules \
X	$(IRULESRC)/site.def \
X	$(IRULESRC)/$(MACROFILE)
X	-@if [ -f Makefile ]; then \
X	echo "$(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \
X	$(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
X	else exit 0; fi
X	$(IMAKE_CMD) -DTOPDIR=$(TOP)
X
X$(IMAKE):
X	@echo "making $@"; \
X	cd $(IMAKESRC); $(MAKE) BOOTSTRAPCFLAGS=$(BOOTSTRAPCFLAGS)
X
Xtags::
X	$(TAGS) -w *.[ch]
X	$(TAGS) -xw *.[ch] > TAGS
X
X###########################################################################
X# empty rules for directories that do not have SUBDIRS - do not edit
X
Xinstall::
X	@echo "install done"
X
Xinstall.man::
X	@echo "install.man done"
X
XMakefiles::
X
X###########################################################################
X# dependencies generated by makedepend
X
END_OF_FILE
if test 6768 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'ReadXBM.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ReadXBM.c'\"
else
echo shar: Extracting \"'ReadXBM.c'\" \(5632 characters\)
sed "s/^X//" >'ReadXBM.c' <<'END_OF_FILE'
X/* Copyright, 1987, Massachusetts Institute of Technology */
X
X#if 0
X#include "copyright.h"
X#endif
X
X/*
X *	Code to read bitmaps from disk files. Interprets 
X *	data from X10 and X11 bitmap files and creates
X *	Pixmap representations of files. Returns Pixmap
X *	ID and specifics about image.
X *
X *	Modified for speedup by Jim Becker, changed image
X *	data parsing logic (removed some fscanf()s). 
X *	Aug 5, 1988
X *
X * Note that this file and ../Xmu/RdBitF.c look very similar....  Keep them
X * that way (but don't use common source code so that people can have one 
X * without the other).
X */
X
X#include <stdio.h>
X#include <ctype.h>
X
Xtypedef int	Bool;
X#define True 1
X#define False 0
Xchar *rindex();
X
X
X#define MAX_SIZE 255
X
X/* shared data for the image read/parse logic */
Xstatic short hexTable[256];		/* conversion value */
Xstatic Bool initialized = False;	/* easier to fill in at run time */
X
X
X/*
X *	Table index for the hex values. Initialized once, first time.
X *	Used for translation value or delimiter significance lookup.
X */
Xstatic void initHexTable()
X{
X    /*
X     * We build the table at run time for several reasons:
X     *
X     *     1.  portable to non-ASCII machines.
X     *     2.  still reentrant since we set the init flag after setting table.
X     *     3.  easier to extend.
X     *     4.  less prone to bugs.
X     */
X    hexTable['0'] = 0;	hexTable['1'] = 1;
X    hexTable['2'] = 2;	hexTable['3'] = 3;
X    hexTable['4'] = 4;	hexTable['5'] = 5;
X    hexTable['6'] = 6;	hexTable['7'] = 7;
X    hexTable['8'] = 8;	hexTable['9'] = 9;
X    hexTable['A'] = 10;	hexTable['B'] = 11;
X    hexTable['C'] = 12;	hexTable['D'] = 13;
X    hexTable['E'] = 14;	hexTable['F'] = 15;
X    hexTable['a'] = 10;	hexTable['b'] = 11;
X    hexTable['c'] = 12;	hexTable['d'] = 13;
X    hexTable['e'] = 14;	hexTable['f'] = 15;
X
X    /* delimiters of significance are flagged w/ negative value */
X    hexTable[' '] = -1;	hexTable[','] = -1;
X    hexTable['}'] = -1;	hexTable['\n'] = -1;
X    hexTable['\t'] = -1;
X	
X    initialized = True;
X}
X
X/*
X *	read next hex value in the input stream, return -1 if EOF
X */
Xstatic NextInt (fstream)
X    FILE *fstream;
X{
X    int	ch;
X    int	value = 0;
X    int gotone = 0;
X    int done = 0;
X    
X    /* loop, accumulate hex value until find delimiter  */
X    /* skip any initial delimiters found in read stream */
X
X    while (!done) {
X	ch = getc(fstream);
X	if (ch == EOF) {
X	    value	= -1;
X	    done++;
X	} else {
X	    /* trim high bits, check type and accumulate */
X	    ch &= 0xff;
X	    if (isascii(ch) && isxdigit(ch)) {
X		value = (value << 4) + hexTable[ch];
X		gotone++;
X	    } else if ((hexTable[ch]) < 0 && gotone)
X	      done++;
X	}
X    }
X    return value;
X}
X
X
Xint ReadXBM (filename, width, height, data)
X    char *filename;
X    unsigned int *width, *height;       /* RETURNED */
X    char   *data[];                     /* RETURNED */
X{
X    FILE *fstream;			/* handle on file  */
X    char line[MAX_SIZE];		/* input line from file */
X    int size;				/* number of bytes of data */
X    char name_and_type[MAX_SIZE];	/* an input line */
X    char *type;				/* for parsing */
X    int value;				/* from an input line */
X    int version10p;			/* boolean, old format */
X    int padding;			/* to handle alignment */
X    int bytes_per_line;			/* per scanline of data */
X    unsigned int ww = 0;		/* width */
X    unsigned int hh = 0;		/* height */
X    int hx = -1;			/* x hotspot */
X    int hy = -1;			/* y hotspot */
X
X    /* first time initialization */
X    if (initialized == False) initHexTable();
X
X    if ((fstream = fopen(filename, "r")) == NULL) {
X	return -1;
X    }
X
X    /* error cleanup and return macro	*/
X#define	RETURN(code) { if (*data) free (*data); fclose (fstream); return code; }
X
X    while (fgets(line, MAX_SIZE, fstream)) {
X	if (strlen(line) == MAX_SIZE-1) {
X	    RETURN (-1);
X	}
X	if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) {
X	    if (!(type = rindex(name_and_type, '_')))
X	      type = name_and_type;
X	    else
X	      type++;
X
X	    if (!strcmp("width", type))
X	      ww = (unsigned int) value;
X	    if (!strcmp("height", type))
X	      hh = (unsigned int) value;
X	    if (!strcmp("hot", type)) {
X		if (type-- == name_and_type || type-- == name_and_type)
X		  continue;
X		if (!strcmp("x_hot", type))
X		  hx = value;
X		if (!strcmp("y_hot", type))
X		  hy = value;
X	    }
X	    continue;
X	}
X    
X	if (sscanf(line, "static short %s = {", name_and_type) == 1)
X	  version10p = 1;
X	else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1)
X	  version10p = 0;
X	else if (sscanf(line, "static char %s = {", name_and_type) == 1)
X	  version10p = 0;
X	else
X	  continue;
X
X	if (!(type = rindex(name_and_type, '_')))
X	  type = name_and_type;
X	else
X	  type++;
X
X	if (strcmp("bits[]", type))
X	  continue;
X    
X	if (!ww || !hh)
X	  RETURN (-1);
X
X	if ((ww % 16) && ((ww % 16) < 9) && version10p)
X	  padding = 1;
X	else
X	  padding = 0;
X
X	bytes_per_line = (ww+7)/8 + padding;
X
X	size = bytes_per_line * hh;
X	*data = (unsigned char *) malloc ((unsigned int) size);
X	if (!*data) 
X	  RETURN (-1);
X
X	if (version10p) {
X	    unsigned char *ptr;
X	    int bytes;
X
X	    for (bytes=0, ptr= *data; bytes<size; (bytes += 2)) {
X		if ((value = NextInt(fstream)) < 0)
X		  RETURN (-1);
X		*(ptr++) = value;
X		if (!padding || ((bytes+2) % bytes_per_line))
X		  *(ptr++) = value >> 8;
X	    }
X	} else {
X	    unsigned char *ptr;
X	    int bytes;
X
X	    for (bytes=0, ptr= *data; bytes<size; bytes++, ptr++) {
X		if ((value = NextInt(fstream)) < 0) 
X		  RETURN (-1);
X		*ptr=value;
X	    }
X	}
X    }					/* end while */
X
X    if (*data == NULL) {
X	RETURN (-1);
X    }
X
X    *width = ww;
X    *height = hh;
X
X    fclose(fstream);
X    return 0;
X}
END_OF_FILE
if test 5632 -ne `wc -c <'ReadXBM.c'`; then
    echo shar: \"'ReadXBM.c'\" unpacked with wrong size!
fi
# end of 'ReadXBM.c'
fi
if test -f 'action.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'action.c'\"
else
echo shar: Extracting \"'action.c'\" \(9179 characters\)
sed "s/^X//" >'action.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 <X11/cursorfont.h>
X#include "xpaint.h"
X#include <X11/bitmaps/xlogo32>
X
Xstatic char	rcsid[]="$Header: action.c,v 1.3 89/02/20 19:32:55 koblas Locked $";
X
X#define Between(min,val,max) (((min)<=(val)) && ((val)<(max)))
X
X#include "scissor.xbm"
X#include "dotbox.xbm"
X#include "hand.xbm"
X#include "arrow.xbm"
X#include "line.xbm"
X#include "arbline.xbm"
X#include "rectfill.xbm"
X#include "elipfill.xbm"
X#include "rect.xbm"
X#include "elipse.xbm"
X#include "polygon.xbm"
X#include "fill.xbm"
X#include "brush.xbm"
X#include "eraser.xbm"
X#include "text.xbm"
X#include "spray.xbm"
X
Xstatic struct {
X	int	id;
X	int	width,height;
X	char	*bits;
X	int	curid;
X	XImage	*reg_image;
X	XImage	*inv_image;
X} actions[] = {
X	{ C_ARROW,arrow_width,arrow_height,arrow_bits,XC_right_ptr,
X		NULL,NULL},
X	{ C_HAND,hand_width,hand_height,hand_bits,XC_fleur,
X		NULL,NULL},
X	{ C_DOTBOX,dottedbox_width,dottedbox_height,dottedbox_bits,XC_cross,
X		NULL,NULL},
X	{ C_NONE,scissor_width,scissor_height,scissor_bits,XC_X_cursor,
X		NULL,NULL},
X/*
X	{ C_SCISSORS,scissor_width,scissor_height,scissor_bits,XC_X_cursor,
X		NULL,NULL},
X*/
X	{ C_LINE,line_width,line_height,line_bits,XC_crosshair,
X		NULL,NULL},
X	{ C_ARBLINE,arbline_width,arbline_height,arbline_bits,XC_pencil,
X		NULL,NULL},
X	{ C_RECTANGLE,rectangle_width,rectangle_height,rectangle_bits,
X		XC_crosshair,NULL,NULL},
X	{ C_ELIPSE,elipse_width,elipse_height,elipse_bits,XC_crosshair,
X		NULL,NULL},
X	{ C_NONE,polygon_width,polygon_height,polygon_bits,XC_crosshair,
X		NULL,NULL},
X/*
X	{ C_POLYGON,polygon_width,polygon_height,polygon_bits,XC_crosshair,
X		NULL,NULL},
X*/
X	{ C_NONE,xlogo32_width,xlogo32_height,xlogo32_bits,XC_X_cursor,
X		NULL,NULL},
X	{ C_NONE,fill_width,fill_height,fill_bits,XC_crosshair,
X		NULL,NULL},
X/*
X	{ C_FILL,fill_width,fill_height,fill_bits,XC_crosshair,
X		NULL,NULL},
X*/
X	{ C_BRUSH,brush_width,brush_height,brush_bits,XC_X_cursor,
X		NULL,NULL},
X	{ C_ERASER,eraser_width,eraser_height,eraser_bits,XC_X_cursor,
X		NULL,NULL},
X	{ C_TEXT,text_width,text_height,text_bits,XC_xterm,
X		NULL,NULL},
X	{ C_SPRAY,spray_width,spray_height,spray_bits,XC_spraycan,
X		NULL,NULL},
X	{ C_NONE,xlogo32_width,xlogo32_height,xlogo32_bits,XC_X_cursor,
X		NULL,NULL},
X	{ C_RECTF,rectfill_width,rectfill_height,rectfill_bits,XC_crosshair,
X		NULL,NULL},
X	{ C_ELIPF,elipfill_width,elipfill_height,elipfill_bits,XC_crosshair,
X		NULL,NULL},
X	{ C_NONE,xlogo32_width,xlogo32_height,xlogo32_bits,XC_X_cursor,
X		NULL,NULL},
X	{ C_NONE,xlogo32_width,xlogo32_height,xlogo32_bits,XC_X_cursor,
X		NULL,NULL},
X};
X
Xstatic Cursor	cursor_id[30];
X
XWindow	CreateAction()
X{
X	int			i;
X	XSetWindowAttributes	attr;
X	Window			wind;
X
X	for (i=0;i<sizeof(actions)/sizeof(actions[0]);i++) {
X		if (actions[i].id == C_NONE)
X			continue;
X
X		actions[i].reg_image = BitmapToImage(actions[i].width,
X					actions[i].height,actions[i].bits,TRUE);
X		actions[i].inv_image = BitmapToImage(actions[i].width,
X				       actions[i].height,actions[i].bits,FALSE);
X		
X		cursor_id[i] = XCreateFontCursor(CurrentWindow->display,
X						 actions[i].curid);
X	}
X
X	attr.background_pixel = CurrentWindow->black;
X	attr.event_mask = ExposureMask|ButtonPressMask|
X			  ButtonReleaseMask|PointerMotionMask;
X
X	wind = XCreateWindow(CurrentWindow->display,CurrentWindow->window,
X		DELTA_XPOS(ACTION_ID),DELTA_YPOS(ACTION_ID),
X		32*2,32*10,
X		1,0,0,0,CWBackPixel|CWEventMask,&attr);
X	XMapWindow(CurrentWindow->display,wind);
X
X	return wind;
X}
X
XEventAction(event)
XXEvent	*event;
X{
X	static int	last_time = 0;
X	static int	x=0,y=0;
X
X	switch (event->type) {
X	case Expose:
X		redraw(event->xexpose.x,event->xexpose.y,
X		       event->xexpose.width,event->xexpose.height);
X		break;
X	case ButtonPress:
X                if (((event->xbutton.time - last_time) < 500) &&
X                    Between(x-1,event->xbutton.x,x+1) &&
X                    Between(y-1,event->xbutton.y,y+1)) {
X			switch (CurrentActionID) {
X			case C_ARROW:
X				DrawFatbits();
X				break;
X			case C_SPRAY:
X				EditSpray();
X				break;
X			}
X		} else {
X			last_time = event->xbutton.time;
X			x=event->xbutton.x;
X			y=event->xbutton.y;
X			track_mouse(event);
X		}
X		break;
X	}
X}
X
XSetAction(id)
Xint	id;
X{
X	int	new,old;
X	int	i;
X
X	if (id == C_NONE)
X		return;
X
X	for (i=0;i<sizeof(actions)/sizeof(actions[0]);i++) {
X		if (actions[i].id == CurrentActionID)
X			old = i;
X		if (actions[i].id == id)
X			new = i;
X	}
X	if (actions[new].id == id) {
X		XPutImage(CurrentWindow->display,
X			  CurrentWindow->subwind[ACTION_ID].window,
X			  CurrentWindow->gc,
X			  actions[old].inv_image,
X			  0,0,(old%2)*32,(old/2)*32,
X			  actions[old].width,actions[old].height);
X		XPutImage(CurrentWindow->display,
X			  CurrentWindow->subwind[ACTION_ID].window,
X			  CurrentWindow->gc,
X			  actions[new].reg_image,
X			  0,0,(new%2)*32,(new/2)*32,
X			  actions[new].width,actions[new].height);
X		CurrentActionID = new;
X		SetCursor();
X	}
X}
X
Xstatic redraw(x,y,w,h)
Xint	x,y,w,h;
X{
X	int	i;
X	int	c=((((w+31)/32)==2)?1:2),off=(x/32);
X
X	for (i=(y/32)*2+off;i<((y+h+31)/32)*2+off;i+=c) {
X		if (actions[i].id == C_NONE) 
X			continue;
X		XPutImage(CurrentWindow->display,
X			  CurrentWindow->subwind[ACTION_ID].window,
X			  CurrentWindow->gc,
X			  CurrentActionID==actions[i].id?
X			  	actions[i].reg_image:actions[i].inv_image,
X			  0,0,(i%2)*32,(i/2)*32,
X			  actions[i].width,actions[i].height);
X	}
X}
X
Xstatic track_mouse(event)
XXEvent	*event;
X{
X	XEvent		new_event,tmp_event;
X	int		i;
X	int		xpos,ypos;
X	int		new_active,active;
X
X	xpos = event->xbutton.x;
X	ypos = event->xbutton.y;
X
X	for (i=0;;i++) {
X		if (actions[i].id==CurrentActionID) {
X			active=i;
X			break;
X		}
X	}
X
X	do {
X		new_active = ((ypos/32)*2)+(xpos/32);
X		if ((new_active >= sizeof(actions)/sizeof(actions[0])) ||
X		    (actions[new_active].id == C_NONE))
X			new_active = active;
X		if (new_active != active) {
X			XPutImage(CurrentWindow->display,
X				  CurrentWindow->subwind[ACTION_ID].window,
X				  CurrentWindow->gc,
X				  actions[active].inv_image,
X				  0,0,(active%2)*32,(active/2)*32,
X				  actions[active].width,actions[active].height);
X			active = new_active;
X			XPutImage(CurrentWindow->display,
X				  CurrentWindow->subwind[ACTION_ID].window,
X				  CurrentWindow->gc,
X				  actions[active].reg_image,
X				  0,0,(active%2)*32,(active/2)*32,
X				  actions[active].width,actions[active].height);
X		}
X
X		XWindowEvent(CurrentWindow->display,
X			CurrentWindow->subwind[ACTION_ID].window,
X			ButtonReleaseMask|PointerMotionMask,&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	CurrentActionID = actions[active].id;
X
X	SetCursor();
X}
X
XSetCursor()
X{
X	static XColor foreground = { 0,    0,     0,     0  };  /* black */
X	static XColor background = { 0, 65535, 65535, 65535 };  /* white */
X	static int	eraser_made=FALSE,brush_made=FALSE;
X	Pixmap		pix,pixmask;
X	extern char	*SprayBitmap;
X	Cursor		cur;
X	int		pos,i;
X
X	for (i=0;;i++) {
X		if (actions[i].id==CurrentActionID)  {
X			pos=i;
X			break;
X		}
X	}
X
X	switch (CurrentActionID) {
X	case C_SPRAY:
X		pix = XCreatePixmapFromBitmapData(CurrentWindow->display,
X			CurrentWindow->window,
X			SprayBitmap,16,16,CurrentWindow->black,
X			CurrentWindow->white,1);
X		XFreeCursor(CurrentWindow->display,cursor_id[pos]);
X		cursor_id[pos]=XCreatePixmapCursor(CurrentWindow->display,
X					pix,pix,&foreground,&background,0,0);
X		XFreePixmap(CurrentWindow->display,pix);
X		break;
X	case C_BRUSH:
X		if (!brush_made) {
X			brush_made = TRUE;
X			pix = XCreatePixmap(CurrentWindow->display,
X					CurrentWindow->window,18,18,1);
X			pixmask = XCreatePixmap(CurrentWindow->display,
X					CurrentWindow->window,18,18,1);
X			XDrawRectangle(CurrentWindow->display,pix,
X				CurrentWindow->igc,1,1,13,7);
X			XFillRectangle(CurrentWindow->display,pixmask,
X				CurrentWindow->igc,0,0,16,10);
X			cursor_id[pos]=XCreatePixmapCursor(
X				CurrentWindow->display,
X				pix,pixmask,&background,&foreground,0,0);
X			XFreePixmap(CurrentWindow->display,pix);
X			XFreePixmap(CurrentWindow->display,pixmask);
X		}
X		break;
X	case C_ERASER:
X		if (!eraser_made) {
X			eraser_made = TRUE;
X			pix = XCreatePixmap(CurrentWindow->display,
X					CurrentWindow->window,18,18,1);
X			pixmask = XCreatePixmap(CurrentWindow->display,
X					CurrentWindow->window,18,18,1);
X			XDrawRectangle(CurrentWindow->display,pix,
X				CurrentWindow->igc,1,1,13,7);
X			XFillRectangle(CurrentWindow->display,pixmask,
X				CurrentWindow->igc,0,0,16,10);
X			cursor_id[pos]=XCreatePixmapCursor(
X				CurrentWindow->display,
X				pix,pixmask,&foreground,&background,0,0);
X			XFreePixmap(CurrentWindow->display,pix);
X			XFreePixmap(CurrentWindow->display,pixmask);
X		}
X		break;
X	default:
X		break;
X	}
X
X	XDefineCursor(CurrentWindow->display,
X		      CurrentWindow->subwind[DRAW_ID].window,
X		      cursor_id[pos]);
X}
END_OF_FILE
if test 9179 -ne `wc -c <'action.c'`; then
    echo shar: \"'action.c'\" unpacked with wrong size!
fi
# end of 'action.c'
fi
if test -f 'bitedit.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'bitedit.c'\"
else
echo shar: Extracting \"'bitedit.c'\" \(4881 characters\)
sed "s/^X//" >'bitedit.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
Xstatic char		*bit_buffer=NULL;
Xstatic int		bit_width;
Xstatic int		bit_height;
Xstatic Window		bit_window;
Xstatic XFontStruct	*font_info;
Xstatic GC		bit_dot_gc;
X
X#define	SIZE		8
X#define WIDTH		(60+bit_width*(SIZE+1))
X#define HEIGHT		(20+bit_height*(SIZE+1))
X
X#define UPDATE(x,y) XFillRectangle(CurrentWindow->display,bit_window,\
X			   bit_buffer[y*bit_width+x]?\
X				   CurrentWindow->gc:CurrentWindow->igc,\
X			   10+x*(SIZE+1),10+y*(SIZE+1),SIZE,SIZE);\
X			XDrawPoint(CurrentWindow->display,bit_window,\
X			   bit_buffer[y*bit_width+x]?\
X				   CurrentWindow->gc:CurrentWindow->igc,\
X			   WIDTH-40+(x),15+(y));
X			
X
XWindow CreateBitedit()
X{
X	Window			wind;
X	XSetWindowAttributes	attr;
X	XGCValues		values;
X	static char		list[2] = { 1 , 1 };
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(ACTION_ID),DELTA_YPOS(ACTION_ID),
X		           20,20,
X		           1,0,0,0,CWBackPixel|CWEventMask,&attr);
X
X	bit_window = wind;
X
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
X	values.background = CurrentWindow->white;
X	values.foreground = CurrentWindow->black;
X	values.line_style = LineOnOffDash;
X	values.font	  = font_info->fid;
X
X	bit_dot_gc = XCreateGC(CurrentWindow->display,bit_window,
X		GCFont|GCForeground|GCBackground|GCLineStyle,&values);
X	XSetDashes(CurrentWindow->display,bit_dot_gc,0,list,sizeof(list));
X
X	return wind;
X}
X
Xvoid EventBitedit(event)
XXEvent	*event;
X{
X	switch (event->type) {
X	case Expose:
X		break;
X	}
X}
X
XBitedit(width,height,bits)
Xint	width,height;
Xchar	*bits;
X{
X	bit_width = width;
X	bit_height = height;
X
X	bit_buffer = bits;
X
X	XResizeWindow(CurrentWindow->display,bit_window,WIDTH,HEIGHT);
X	XMapWindow(CurrentWindow->display,bit_window);
X	XFlush(CurrentWindow->display);
X
X	MyEventLoop();
X
X	clean_up();
X}
X
Xstatic clean_up()
X{
X	XUnmapWindow(CurrentWindow->display,bit_window);
X	XFlush(CurrentWindow->display);
X}
X
Xstatic redraw()
X{
X	int	x,y;
X
X	for (y=0;y<bit_height;y++)
X		for (x=0;x<bit_width;x++) {
X			UPDATE(x,y);
X		}
X	for (x=0;x<=bit_width;x++)
X		XDrawLine(CurrentWindow->display,bit_window,
X			bit_dot_gc,9+(x*(SIZE+1)),9,
X			9+(x*(SIZE+1)),10+(bit_height*(SIZE+1)));
X	for (y=0;y<=bit_height;y++)
X		XDrawLine(CurrentWindow->display,bit_window,
X			bit_dot_gc,9,9+(y*(SIZE+1)),
X			9+(bit_width*(SIZE+1)),9+(y*(SIZE+1)));
X	
X	XDrawRectangle(CurrentWindow->display,bit_window,
X		       CurrentWindow->igc,0,0,WIDTH-1,HEIGHT-1);
X	XDrawRectangle(CurrentWindow->display,bit_window,
X		       CurrentWindow->igc,1,1,WIDTH-3,HEIGHT-3);
X	XDrawRectangle(CurrentWindow->display,bit_window,
X		       CurrentWindow->igc,WIDTH-41,14,bit_width+1,bit_height+1);
X	
X	XDrawRectangle(CurrentWindow->display,bit_window,
X		CurrentWindow->igc,WIDTH-45,HEIGHT-45,40,
X		font_info->ascent+font_info->descent+6);
X	XDrawImageString(CurrentWindow->display,bit_window,bit_dot_gc,
X		WIDTH-40,(HEIGHT-45)+3+font_info->ascent,"Done",4);
X}
X
Xstatic MyEventLoop()
X{
X	XEvent	event;
X	int	color = FALSE;
X	int	xpos,ypos;
X	int	new_pos,pos;
X	int	done=FALSE,tracking=FALSE;
X
X	while (!done) {
X		XWindowEvent(CurrentWindow->display,bit_window,-1,&event);
X		switch (event.type) {
X		case Expose:
X			redraw();
X			break;
X		case ButtonPress:
X			if (Between(10,event.xbutton.x,WIDTH-50) &&
X			    Between(10,event.xbutton.y,HEIGHT-10)) {
X				tracking = TRUE;
X				xpos = (event.xbutton.x - 10)/(SIZE+1);
X				ypos = (event.xbutton.y - 10)/(SIZE+1);
X				pos = ypos*bit_height+xpos;
X				color = !bit_buffer[pos];
X				bit_buffer[pos] = color;
X				UPDATE(xpos,ypos);
X		    	} else if (Between(HEIGHT-45,event.xbutton.y,
X				    HEIGHT-45+(font_info->ascent+
X					       font_info->descent+6)) &&
X			    Between(WIDTH-45,event.xbutton.x,WIDTH-5)) {
X				done=TRUE;
X		    	}
X			break;
X		case ButtonRelease:
X			if (tracking)
X				tracking=FALSE;
X			break;
X		case MotionNotify:
X			if (tracking) {
X				if (Between(10,event.xmotion.x,WIDTH-50) &&
X				    Between(10,event.xmotion.y,HEIGHT-10)) {
X					xpos = (event.xmotion.x - 10)/(SIZE+1);
X					ypos = (event.xmotion.y - 10)/(SIZE+1);
X					new_pos = ypos*bit_height+xpos;
X					if (new_pos != pos) {
X						pos = new_pos;
X						bit_buffer[pos] = color;
X						UPDATE(xpos,ypos);
X					}
X				}
X			}
X			break;
X		}
X	}
X}
END_OF_FILE
if test 4881 -ne `wc -c <'bitedit.c'`; then
    echo shar: \"'bitedit.c'\" unpacked with wrong size!
fi
# end of 'bitedit.c'
fi
if test -f 'event.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'event.c'\"
else
echo shar: Extracting \"'event.c'\" \(3617 characters\)
sed "s/^X//" >'event.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	<sys/types.h>
X#include	<X11/Xos.h>
X#include	"xpaint.h"
X
X#ifndef FD_SET
X#define	FD_SET(n, s)	(((s)->fds_bits[0]) |= (1 << n))
X#define	FD_ZERO(s)	bzero((char *)(s), sizeof (*(s)))
X#endif
X#define AllEventMask	(-1)
X
X#define Between(min,val,max) (((min)<=(val)) && ((val)<(max)))
X
X#define MAXINTR 20
X
Xstruct s_intr {
X	int	used;
X	void	(*func)();
X} interrupt_list[MAXINTR];
X
Xstatic int	ActiveItem = C_ARROW;
Xstatic Cursor 	CurrentCursor = 0;
X#ifndef lint
Xstatic char rcsid[]="$Header: event.c,v 1.9 89/02/22 12:31:14 koblas Locked $";
X#endif
X
Xstatic int	Done=FALSE;
X
XEventLoop()
X{
X	XEvent			event;
X	int			i,n;
X	static struct timeval	tv = { 0,500000 };
X	fd_set			read_fd;
X	int			nfd = getdtablesize();
X
X	for (i=0;i<MAXINTR;i++) {
X		interrupt_list[i].used=FALSE;
X	}
X
X	goto start;
X
X	while (!Done) {
X
X		FD_ZERO(&read_fd);
X		FD_SET(ConnectionNumber(CurrentWindow->display),&read_fd);
X		if ((n=select(nfd,&read_fd,NULL,NULL,&tv))<0) {
X			perror("select");
X			Done=TRUE;
X			continue;
X		}
X		if (n==0) {
X			tv.tv_sec = 0;
X			tv.tv_usec = 500000;
X			Interrupt();
X			continue;
X		}
Xstart:
X		while (XCheckMaskEvent(CurrentWindow->display,
X				       AllEventMask,&event) && !Done) {
X			HandleEvent(&event);
X		}
X	}
X}
X
XHandleEvent(event)
XXEvent	*event;
X{
X	int	i,n;
X	char	buf[80];
X
X	if (event->xany.window != CurrentWindow->window) {
X		for (i=0;i<CurrentWindow->numsub;i++) {
X			if (CurrentWindow->subwind[i].window==
X				event->xany.window)
X				break;
X		}
X		if ((i<CurrentWindow->numsub) &&
X		    (CurrentWindow->subwind[i].event_handler!=NULL))
X			CurrentWindow->subwind[i].
X				event_handler(event);
X	}
X
X	switch(event->type) {
X	case NoExpose: /* probably want to do something about this one..*/
X	case MapNotify:
X	case ReparentNotify:
X		break;
X	case ButtonPress:
X		break;
X	case ButtonRelease:
X		break;
X	case KeyPress   :
X	case KeyRelease :
X		break;
X	case LeaveNotify:
X		break;
X	case EnterNotify:
X		break;
X	case FocusOut   :
X		break;
X	case FocusIn    :
X		break;
X	case MotionNotify:
X		break;
X	case ConfigureNotify:
X		if (event->xconfigure.window != CurrentWindow->window)
X			break;
X		CurrentWindow->width  = event->xconfigure.width;
X		CurrentWindow->height = event->xconfigure.height;
X		for (i=0;i<CurrentWindow->numsub;i++) {
X			if (CurrentWindow->subwind[i].resize_handler
X				!=NULL)
X			     CurrentWindow->subwind[i].resize_handler();
X			else {
X				XMoveWindow(CurrentWindow->display,
X				   CurrentWindow->subwind[i].window,
X				   DELTA_XPOS(i),DELTA_YPOS(i));
X			}
X		}
X		break;
X	case Expose:
X		break;
X	default:
X		fprintf(stderr,"Unknown event recieved == %d\n",event->type);
X		break;
X	}
X}
X
XWindowEvent(wind,event)
XWindow	wind;
XXEvent	*event;
X{
X	int	flag=FALSE;
X	do {
X		if (flag)
X			HandleEvent(event);
X		XNextEvent(CurrentWindow->display,event);
X		flag=TRUE;
X	} while (event->xany.window != wind);
X}
X
Xvoid Quit()
X{
X	Done=TRUE;
X}
X
XDeleteInterrupt(id)
Xint	id;
X{
X	interrupt_list[id].used = FALSE;
X}
X
XAddInterrupt(func)
Xvoid	(*func)();	
X{
X	int	i;
X
X	for (i=0;i<MAXINTR;i++)
X		if (!interrupt_list[i].used)
X			break;
X	if (i==MAXINTR)
X		return -1;
X	interrupt_list[i].used = TRUE;
X	interrupt_list[i].func = func;
X
X	return i;
X}
X
XInterrupt()
X{
X	int	i;
X
X	for (i=0;i<MAXINTR;i++)
X		if (interrupt_list[i].used) 
X			interrupt_list[i].func();
X}
END_OF_FILE
if test 3617 -ne `wc -c <'event.c'`; then
    echo shar: \"'event.c'\" unpacked with wrong size!
fi
# end of 'event.c'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.c'\"
else
echo shar: Extracting \"'main.c'\" \(6721 characters\)
sed "s/^X//" >'main.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 <X11/cursorfont.h>
X#include "xpaint.h"
X#include <X11/bitmaps/xlogo32>
X
X#ifndef lint
Xstatic char	rcsid[]="$Header: main.c,v 1.7 89/02/20 19:32:58 koblas Locked $";
X#endif
Xstatic char	*Default_font="serif.r.14";
X
Xt_window	*CurrentWindow;
Xint		CurrentActionID = C_ARROW;
Xint		CurrentPatternID = 0;
Xchar		*FileName=NULL;
Xint		FileType=FT_NONE;
Xint		DefaultXsize=1024;
Xint		DefaultYsize=1024;
X
X#define EVENT_MASK	(ExposureMask|KeyPressMask|FocusChangeMask|\
X			 StructureNotifyMask|PointerMotionMask|\
X			 ButtonPressMask|ButtonReleaseMask|\
X			 EnterWindowMask|LeaveWindowMask)
X
XWindow	CreateDraw(),CreateAction(),CreatePattern(),CreateMenu(),
X	CreateBitedit(),CreateSave();
Xvoid	EventDraw(),EventAction(),EventPattern(),EventMenu(),EventBitedit();
Xvoid	ResizeDraw(),ResizeMenu();
X
Xt_sub_window	newwind[] = {
X	{CreateDraw,EventDraw,ResizeDraw,0,
X		10+32+32+10,20,DELTA_TOP|DELTA_LEFT},
X	{CreateAction,EventAction,NULL,0,
X		10,20,DELTA_TOP|DELTA_LEFT},
X	{CreatePattern,EventPattern,NULL,0,
X		10+32+32+10,10+32,DELTA_LEFT|DELTA_BOTTOM},
X	{CreateMenu,EventMenu,ResizeMenu,0,
X		0,0,DELTA_LEFT|DELTA_TOP},
X	{CreateBitedit,EventBitedit,NULL,0,
X		64,64,DELTA_LEFT|DELTA_TOP},
X	{CreateSave,NULL,NULL,0,
X		64,64,DELTA_LEFT|DELTA_TOP},
X};
X
X#define Between(min,val,max) (((min)<=(val)) && ((val)<(max)))
X
Xmain(argc,argv)
Xint	argc;
Xchar	**argv;
X{
X	extern char	*optarg;
X	extern int	optind;
X	int		c;
X	char		filename[80];
X	char		display_name[80];
X
X	filename[0]='\0';
X	display_name[0]='\0';
X
X	while ((c=getopt(argc,argv,"d:v"))!=EOF) {
X		switch (c) {
X		case 'x':
X			DefaultXsize = atoi(optarg);
X			if (DefaultXsize==0)
X				DefaultXsize=1024;
X			break;
X		case 'y':
X			DefaultYsize = atoi(optarg);
X			if (DefaultYsize==0)
X				DefaultYsize=1024;
X			break;
X		case 'd':
X			strcpy(display_name,optarg);
X			break;
X		case 'v':
X			Version();
X			exit(0);
X		}
X	}
X
X	OpenAndInit((display_name[0]=='\0')?NULL:display_name,
X		    (filename[0]=='\0')?TRUE:FALSE);
X
X	if (filename[0]!='\0') {
X		ReadFile(filename,FT_XBM); 
X		FileName = filename;
X		FileType = FT_XBM;
X	}
X
X	EventLoop();
X}
X
XOpenAndInit(distxt,flag)
Xchar	*distxt;
Xint	flag;
X{
X	int		i;
X	char		*data;
X
X	if ((CurrentWindow=(t_window *)malloc(sizeof(t_window)))==NULL) {
X		fprintf(stderr,"Unable to malloc space for window info\n");
X		exit(1);
X	}
X	if ((CurrentWindow->display = XOpenDisplay(distxt))==NULL) {
X		fprintf(stderr,"Unable to open display (%s)\n",
X			(distxt==NULL)?"$DISPLAY":distxt);
X		exit(1);
X	}
X	CurrentWindow->screen = DefaultScreen(CurrentWindow->display);
X	CurrentWindow->rootwindow = DefaultRootWindow(CurrentWindow->display);
X	CurrentWindow->visual = DefaultVisual(CurrentWindow->display,
X					      CurrentWindow->screen);
X	CurrentWindow->depth = DefaultDepth(CurrentWindow->display,
X					      CurrentWindow->screen);
X	CurrentWindow->numsub = sizeof(newwind)/sizeof(newwind[0]);
X	CurrentWindow->subwind = newwind;
X
X	OpenXWindow(640,480);
X
X	for (i=0;i<CurrentWindow->numsub;i++) {
X		if (CurrentWindow->subwind[i].create_handler!=NULL)
X			CurrentWindow->subwind[i].window = 
X				CurrentWindow->subwind[i].create_handler();
X	}
X
X	OpenDraw();
X	XFlush(CurrentWindow->display);
X}
X
XOpenXWindow(xsize,ysize)
Xint	xsize,ysize;
X{
X	XSetWindowAttributes	attr;
X	Window			wind;
X	XSizeHints		hints;
X	Pixmap			source,mask;
X	XColor			foreground_color,background_color;
X	XGCValues		values;
X	int			i;
X	XEvent			event;
X
X	XParseColor(CurrentWindow->display,
X		DefaultColormap(CurrentWindow->display,CurrentWindow->screen),
X		"Black",&background_color);
X	XParseColor(CurrentWindow->display,
X		DefaultColormap(CurrentWindow->display,CurrentWindow->screen),
X		"White",&foreground_color);
X	XAllocColor(CurrentWindow->display,
X		DefaultColormap(CurrentWindow->display,CurrentWindow->screen),
X		&background_color);
X	XAllocColor(CurrentWindow->display,
X		DefaultColormap(CurrentWindow->display,CurrentWindow->screen),
X		&foreground_color);
X
X	CurrentWindow->white = foreground_color.pixel;
X	CurrentWindow->black = background_color.pixel;
X	attr.background_pixel = background_color.pixel;
X	attr.event_mask       = EVENT_MASK;
X	CurrentWindow->default_cursor = attr.cursor= 
X			XCreateFontCursor(CurrentWindow->display,XC_arrow);
X	XRecolorCursor(CurrentWindow->display,CurrentWindow->default_cursor,
X		       &foreground_color,&background_color);
X
X	CurrentWindow->width  = xsize;
X	CurrentWindow->height = ysize;
X	CurrentWindow->img_offx = 0;
X	CurrentWindow->img_offy = 0;
X	CurrentWindow->window = XCreateWindow(CurrentWindow->display,
X					      CurrentWindow->rootwindow,
X					      0,0,xsize,ysize,2,0,0,0,
X					      CWCursor|CWEventMask|CWBackPixel,
X					      &attr);
X
X	hints.flags      = PMinSize|PResizeInc|PSize;
X	hints.width      = xsize;
X	hints.height     = ysize;
X	hints.min_width  = 640;
X	hints.min_height = 480;
X	hints.width_inc  = 1;
X	hints.height_inc = 1;
X	XSetNormalHints(CurrentWindow->display,CurrentWindow->window,&hints);
X	XStoreName(CurrentWindow->display,CurrentWindow->window,"xpaint");
X	XSetIconName(CurrentWindow->display,CurrentWindow->window,"xpaintIcon");
X
X	XMapWindow(CurrentWindow->display,CurrentWindow->window);
X	XFlush(CurrentWindow->display);
X	XWindowEvent(CurrentWindow->display,CurrentWindow->window,
X			ExposureMask,&event);
X
X	values.foreground = foreground_color.pixel;
X	values.background = background_color.pixel;
X	CurrentWindow->gc = XCreateGC(CurrentWindow->display,
X				      CurrentWindow->window,
X				      GCBackground|GCForeground,
X				      &values);
X	values.foreground = background_color.pixel;
X	values.background = foreground_color.pixel;
X	CurrentWindow->igc= XCreateGC(CurrentWindow->display,
X				      CurrentWindow->window,
X				      GCBackground|GCForeground,
X				      &values);
X}
X
XXImage *BitmapToImage(xsize,ysize,data,flag)
Xint	xsize,ysize;
Xchar	*data;
Xint	flag;
X{
X	XImage		*image;
X	char		*pixels=(char *)malloc(xsize*ysize);
X	int		x,y;
X	unsigned int	v;
X	int		xw = (xsize+7)/8;
X
X	if (pixels==NULL)
X		return NULL;
X	image = XCreateImage(CurrentWindow->display,CurrentWindow->visual,
X		     CurrentWindow->depth,XYPixmap,0,pixels,xsize,ysize,8,0);
X	if (image==NULL)
X		return NULL;
X
X	for (y=0;y<ysize;y++) {
X		for (x=0;x<xsize;x++) {
X			v = data[(y*xw)+(x/8)]&(1<<(x%8));
X			if ((flag && (v!=0)) || (!flag && (v==0))) {
X				XPutPixel(image,x,y,CurrentWindow->black);
X			} else {
X				XPutPixel(image,x,y,CurrentWindow->white);
X			}
X		}
X	}
X	return image;
X}
END_OF_FILE
if test 6721 -ne `wc -c <'main.c'`; then
    echo shar: \"'main.c'\" unpacked with wrong size!
fi
# end of 'main.c'
fi
if test -f 'pattern.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'pattern.c'\"
else
echo shar: Extracting \"'pattern.c'\" \(6543 characters\)
sed "s/^X//" >'pattern.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#ifndef lint
Xstatic char rcsid[]=
X  "$Header: pattern.c,v 1.3 89/02/20 19:33:00 koblas Locked $";
X#endif
X
X#define Between(min,val,max) (((min)<=(val)) && ((val)<(max)))
X
X#include "pat_01.xbm"
X#include "pat_02.xbm"
X#include "pat_03.xbm"
X#include "pat_04.xbm"
X#include "pat_05.xbm"
X#include "pat_06.xbm"
X#include "pat_07.xbm"
X#include "pat_08.xbm"
X#include "pat_09.xbm"
X#include "pat_10.xbm"
X#include "pat_11.xbm"
X#include "pat_12.xbm"
X#include "pat_13.xbm"
X#include "pat_14.xbm"
X#include "pat_15.xbm"
X#include "pat_16.xbm"
X
X
Xstatic struct { 
X	int	width,height;
X	char	*bits;
X	XImage	*reg_image;
X	XImage	*inv_image;
X} pattern[] = {
X	{ pattern_01_width, pattern_01_height, pattern_01_bits, NULL, NULL},
X	{ pattern_02_width, pattern_02_height, pattern_02_bits, NULL, NULL},
X	{ pattern_03_width, pattern_03_height, pattern_03_bits, NULL, NULL},
X	{ pattern_04_width, pattern_04_height, pattern_04_bits, NULL, NULL},
X	{ pattern_05_width, pattern_05_height, pattern_05_bits, NULL, NULL},
X	{ pattern_06_width, pattern_06_height, pattern_06_bits, NULL, NULL},
X	{ pattern_07_width, pattern_07_height, pattern_07_bits, NULL, NULL},
X	{ pattern_08_width, pattern_08_height, pattern_08_bits, NULL, NULL},
X	{ pattern_09_width, pattern_09_height, pattern_09_bits, NULL, NULL},
X	{ pattern_10_width, pattern_10_height, pattern_10_bits, NULL, NULL},
X	{ pattern_11_width, pattern_11_height, pattern_11_bits, NULL, NULL},
X	{ pattern_12_width, pattern_12_height, pattern_12_bits, NULL, NULL},
X	{ pattern_13_width, pattern_13_height, pattern_13_bits, NULL, NULL},
X	{ pattern_14_width, pattern_14_height, pattern_14_bits, NULL, NULL},
X	{ pattern_15_width, pattern_15_height, pattern_15_bits, NULL, NULL},
X	{ pattern_16_width, pattern_16_height, pattern_16_bits, NULL, NULL}
X};
X
Xchar PatternBits[32*32];
X
XWindow CreatePattern()
X{
X	int			i;
X	XSetWindowAttributes	attr;
X	Window			wind;
X
X	for (i=0;i<sizeof(pattern)/sizeof(pattern[0]);i++) {
X		pattern[i].reg_image = BitmapToImage(pattern[i].width,
X				          pattern[i].height,
X					  pattern[i].bits,TRUE);
X		pattern[i].inv_image = BitmapToImage(pattern[i].width,
X				          pattern[i].height,
X					  pattern[i].bits,FALSE);
X	}
X
X	attr.background_pixel = CurrentWindow->black;
X        attr.event_mask = ExposureMask|ButtonPressMask|
X			  ButtonReleaseMask|PointerMotionMask;
X	
X	wind = XCreateWindow(CurrentWindow->display,CurrentWindow->window,
X		DELTA_XPOS(PATTERN_ID),DELTA_YPOS(PATTERN_ID),
X		32*16,32,1,0,0,0,CWBackPixel|CWEventMask,&attr);
X	XMapWindow(CurrentWindow->display,wind);
X
X	CurrentPatternID=0;
X	set_patternbits();
X
X	return wind;
X}
X
Xvoid EventPattern(event)
XXEvent	*event;
X{
X	static int	last_time = 0;
X	static int	x=0,y=0;
X	static char	bits[sizeof(PatternBits)];
X
X	switch (event->type) {
X	case Expose:
X		redraw();
X		break;
X	case ButtonPress:
X		if (((event->xbutton.time - last_time) < 500) &&
X		    Between(x-1,event->xbutton.x,x+1) &&
X		    Between(y-1,event->xbutton.y,y+1)) {
X			bcopy(PatternBits,bits,sizeof(PatternBits));
X			Bitedit(32,32,bits);
X			set_pattern(bits);
X		} else {
X			last_time = event->xbutton.time;
X			x = event->xbutton.x;
X			y = event->xbutton.y;
X			track_mouse(event);
X		}
X		break;
X	}
X}
X
Xstatic redraw()
X{
X	int	i;
X
X	for (i=0;i<sizeof(pattern)/sizeof(pattern[0]);i++) {
X		XPutImage(CurrentWindow->display,
X			  CurrentWindow->subwind[PATTERN_ID].window,
X			  CurrentWindow->gc,
X			  (i==CurrentPatternID)?
X			  	pattern[i].reg_image:pattern[i].inv_image,
X			  0,0,32*i,0,pattern[i].width,pattern[i].height);
X	}
X	XFlush(CurrentWindow->display);
X}
X
Xstatic track_mouse(event)
XXEvent	*event;
X{
X	XEvent		new_event,tmp_event;
X	int		i;
X	int		xpos,ypos;
X	int		new_active,active=CurrentPatternID;
X
X	xpos = event->xbutton.x;
X	ypos = event->xbutton.y;
X
X	do {
X		new_active = (xpos/32);
X		if (new_active >= 16)
X			new_active = 15;
X		if (new_active != active) {
X			XPutImage(CurrentWindow->display,
X				  CurrentWindow->subwind[PATTERN_ID].window,
X				  CurrentWindow->gc,
X				  pattern[active].inv_image,
X				  0,0,active*32,0,
X				  pattern[active].width,pattern[active].height);
X			active = new_active;
X			XPutImage(CurrentWindow->display,
X				  CurrentWindow->subwind[PATTERN_ID].window,
X				  CurrentWindow->gc,
X				  pattern[active].reg_image,
X				  0,0,active*32,0,
X				  pattern[active].width,pattern[active].height);
X		}
X
X		XWindowEvent(CurrentWindow->display,
X			CurrentWindow->subwind[PATTERN_ID].window,
X			ButtonReleaseMask|PointerMotionMask,&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	CurrentPatternID = active;
X	set_patternbits();
X}
X
Xstatic set_pattern(bits)
Xchar	*bits;
X{
X	int	x,y,pos;
X	int	xw = (pattern[CurrentPatternID].width+7)/8;
X
X	for (y=0;y<pattern[CurrentPatternID].height;y++)
X		for (x=0;x<xw;x++)
X			pattern[CurrentPatternID].bits[x+y*xw]=0;
X
X	for (pos=0;pos<pattern[CurrentPatternID].width*
X		       pattern[CurrentPatternID].height;pos++) {
X		x = pos%pattern[CurrentPatternID].width;
X		y = pos/pattern[CurrentPatternID].height;
X		if (!bits[pos]) {
X			pattern[CurrentPatternID].bits[(y*xw)+(x/8)]|=1<<(x%8);
X		}
X	}
X
X	XDestroyImage(pattern[CurrentPatternID].reg_image);
X	XDestroyImage(pattern[CurrentPatternID].inv_image);
X
X	pattern[CurrentPatternID].reg_image = BitmapToImage(
X				  pattern[CurrentPatternID].width,
X				  pattern[CurrentPatternID].height,
X				  pattern[CurrentPatternID].bits,TRUE);
X	pattern[CurrentPatternID].inv_image = BitmapToImage(
X				  pattern[CurrentPatternID].width,
X				  pattern[CurrentPatternID].height,
X				  pattern[CurrentPatternID].bits,FALSE);
X	bcopy(bits,PatternBits,pattern[CurrentPatternID].width*
X		       	       pattern[CurrentPatternID].height);
X	redraw();
X}
X
Xstatic set_patternbits()
X{
X	int	xsize = pattern[CurrentPatternID].width;
X	int	ysize = pattern[CurrentPatternID].height;
X	int	xw = (xsize+7)/8;
X	int	x,y;
X
X	for (y=0;y<ysize;y++) {
X		for (x=0;x<xsize;x++) {
X			if ((pattern[CurrentPatternID].bits
X						[(y*xw)+(x/8)]&(1<<(x%8)))==0)
X				PatternBits[(y*32)+x]=TRUE;
X			else
X				PatternBits[(y*32)+x]=FALSE;
X		}
X	}
X}
END_OF_FILE
if test 6543 -ne `wc -c <'pattern.c'`; then
    echo shar: \"'pattern.c'\" unpacked with wrong size!
fi
# end of 'pattern.c'
fi
if test -f 'save.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'save.c'\"
else
echo shar: Extracting \"'save.c'\" \(6741 characters\)
sed "s/^X//" >'save.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
Xchar	*rindex();
X
X#ifndef lint
Xstatic char rcsid[]="$Header: save.c,v 1.2 89/02/20 19:33:01 koblas Locked $";
X#endif
X
X#define MIN(a,b)	((a)<(b) ? (a) : (b))
X#define CTRL(x)		((x)-'A'+1)
X#define DELETE		127
X
Xstatic Window		save_window;
Xstatic XFontStruct	*font_info;
Xstatic GC		save_gc;
Xstatic int		xstart,ystart;
Xstatic int		width,height;
X#define XSIZE		300
X#define YSIZE		100
X
XWindow	CreateSave()
X{
X	XSetWindowAttributes		attr;
X	Window				wind;
X	XGCValues			values;
X
X	attr.background_pixel = CurrentWindow->white;
X	attr.event_mask =  ExposureMask|ButtonPressMask|KeyPressMask;
X
X	save_window=XCreateWindow(CurrentWindow->display,CurrentWindow->window,
X			 	DELTA_XPOS(SAVE_ID),DELTA_YPOS(SAVE_ID),
X				XSIZE,YSIZE,
X				0,0,0,0,CWBackPixel|CWEventMask,&attr);
X	
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
X	values.background = CurrentWindow->white;
X	values.foreground = CurrentWindow->black;
X	values.font       = font_info->fid;
X
X	save_gc = XCreateGC(CurrentWindow->display,save_window,
X			GCFont|GCForeground|GCBackground,&values);
X
X	return save_window;
X}
X
XSaveRegion()
X{
X	static char	str[1024];
X
X	DrawGetRegion(&xstart,&ystart,&width,&height);
X
X	if (GetString(str))
X		SaveFile(str,FT_XBM);
X}
X
XSaveMenuAs()
X{
X	static char	str[1024];
X
X	xstart = ystart = 0;
X	width = CurrentWindow->img_width;
X	height = CurrentWindow->img_height;
X
X	if (GetString(str))
X		SaveFile(str,FT_XBM);
X}
X
XGetString(str)
Xchar	*str;
X{
X	XEvent		event;
X	int		done=FALSE;
X	static char	buf[80];
X	int		i,n;
X	int		cancel=FALSE;
X	int		index=0;
X	int		c_width  = font_info->max_bounds.width;
X	int		c_height = font_info->max_bounds.ascent+
X				   font_info->max_bounds.descent;
X
X	XMapWindow(CurrentWindow->display,save_window);
X	XFlush(CurrentWindow->display);
X
X	while (!done) {
X		XWindowEvent(CurrentWindow->display,save_window,-1,&event);
X		switch (event.type) {
X		case Expose:
X			XDrawRectangle(CurrentWindow->display,save_window,
X				CurrentWindow->igc,1,1,XSIZE-3,YSIZE-3);
X			XDrawRectangle(CurrentWindow->display,save_window,
X				CurrentWindow->igc,0,0,XSIZE-1,YSIZE-1);
X			XDrawRectangle(CurrentWindow->display,save_window,
X				CurrentWindow->igc,10,10,XSIZE-20,
X					c_height+6);
X			XDrawRectangle(CurrentWindow->display,save_window,
X				CurrentWindow->igc,10,40,
X				c_width*8,c_height+6);
X			XDrawRectangle(CurrentWindow->display,save_window,
X				CurrentWindow->igc,10,65,
X				c_width*8,c_height+6);
X			XDrawImageString(CurrentWindow->display,
X				save_window,save_gc,
X				10+c_width,40+3+font_info->ascent,
X				"Cancel",6);
X			XDrawImageString(CurrentWindow->display,
X				save_window,save_gc,
X				10+c_width*3,65+3+font_info->ascent,
X				"OK",2);
X			XDrawImageString(CurrentWindow->display,
X				save_window,save_gc,
X				10+c_width,10+3+font_info->ascent,
X				str,index);
X			break;
X		case ButtonPress:
X			if (Between(10,event.xbutton.x,10+c_width*8) &&
X			    Between(40,event.xbutton.y,40+6+c_height)) {
X				XFillRectangle(CurrentWindow->display,
X					save_window,
X					CurrentWindow->igc,10,40,
X					c_width*8,c_height+6);
X				done=TRUE;
X				cancel=TRUE;
X			}
X			if (Between(10,event.xbutton.x,10+c_width*8) &&
X			    Between(65,event.xbutton.y,65+6+c_height)) {
X				done=TRUE;
X			}
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					if (index!=0)
X						done=TRUE;
X					break;
X				case CTRL('U'):
X					break;
X				case CTRL('H'):
X				case DELETE:
X					if (index>0)
X						index--;
X					break;
X				default:
X					if (buf[i]>=' ')
X						str[index++]=buf[i];
X				}
X			}
X			if (n!=0) {
X				XClearArea(CurrentWindow->display,
X					save_window,11,11,XSIZE-22,c_height+4,
X					FALSE);
X				XDrawImageString(CurrentWindow->display,
X					save_window,save_gc,
X					10+c_width,10+3+font_info->ascent,
X					str,MIN(index,(XSIZE-22)/c_width));
X			}
X			break;
X		}
X	}
X
X	if (!cancel) {
X		XFillRectangle(CurrentWindow->display,
X			save_window,
X			CurrentWindow->igc,10,65,
X			c_width*8,c_height+6);
X		XDrawString(CurrentWindow->display,
X			save_window,CurrentWindow->gc,
X			10+c_width*3,65+3+font_info->ascent,
X			"OK",2);
X		XFlush(CurrentWindow->display);
X	}
X	XUnmapWindow(CurrentWindow->display,save_window);
X
X	if ((index==0) || (cancel))
X		return FALSE;
X	str[index]='\0';
X	return TRUE;
X}
X
XSaveMenu()
X{
X	static char str[1024];
X
X	xstart = ystart = 0;
X	width = CurrentWindow->img_width;
X	height = CurrentWindow->img_height;
X
X	if ((FileName==NULL) || (FileType==FT_NONE)) {
X		if (GetString(str)) 
X			SaveFile(str,FT_XBM);
X	} else
X		SaveFile(FileName,FileType);
X}
X
XSaveFile(filename,type)
Xchar	*filename;
Xint	type;
X{
X	int	ret_code = -1;
X
X	FlushBuffer();
X
X	switch (type) {
X	case FT_XBM:
X		ret_code = save_xbm(filename);
X		break;
X	case FT_UTAH:
X		fprintf(stderr,"file type not supported (UTAH RLE)\n");
X		break;
X	case FT_GIF:
X		fprintf(stderr,"file type not supported (GIF)\n");
X		break;
X	case FT_TIFF:
X		fprintf(stderr,"file type not supported (TIFF)\n");
X		break;
X	case FT_PIC:
X		fprintf(stderr,"file type not supported (PIC)\n");
X		break;
X	}
X
X	return ret_code;
X}
X
Xstatic save_xbm(filename)
Xchar	*filename;
X{
X	char		*data;
X	int		x,y;
X	int		bitpos=0;
X	int		byte;
X	int		col = 0;
X	FILE		*fd;
X	long		pix;
X	static char	hexdigits[]={'0','1','2','3','4','5','6','7','8',
X			     '9','a','b','c','d','e','f'};
X
X	if ((fd=fopen(filename,"w"))==NULL) {
X		fprintf(stderr,"Unable to open %s for writing\n",filename);
X		return;
X	}
X
X	fprintf(fd,"#define unknown_width %d\n#define unknown_height %d\n",
X		width,height);
X	fputs("static char unknown_bits[] = {\n",fd);
X
X	for (y=0;y<height;y++) {
X		for (x=0;x<width;x++) {
X			pix=XGetPixel(CurrentWindow->master,x+xstart,y+ystart);
X			bitpos = x&7;
X			byte |= ((pix==CurrentWindow->black)?1:0)<<bitpos;
X			if (bitpos==7) {
X				putc('0',fd);
X				putc('x',fd);
X				putc(hexdigits[(byte>>4)&0xf],fd);
X				putc(hexdigits[(byte   )&0xf],fd);
X				putc(',',fd);
X				col++;
X				if (col==15) {
X					putc('\n',fd);
X					col=0;
X				}
X				byte=0;
X			}
X		}
X		if (bitpos!=7) {
X			putc('0',fd);
X			putc('x',fd);
X			putc(hexdigits[(byte>>4)&0xf],fd);
X			putc(hexdigits[(byte   )&0xf],fd);
X			putc(',',fd);
X			col++;
X			if (col==15) {
X				putc('\n',fd);
X				col=0;
X			}
X			byte=0;
X		}
X	}
X
X	fputs("};\n",fd);
X
X	fclose(fd);
X}
END_OF_FILE
if test 6741 -ne `wc -c <'save.c'`; then
    echo shar: \"'save.c'\" unpacked with wrong size!
fi
# end of 'save.c'
fi
echo shar: End of archive 2 \(of 3\).
cp /dev/null ark2isdone
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