v03i032: MacPaint-like graphics, Part02/03
Mike Wexler
mikew at wyse.wyse.com
Thu Feb 23 10:00:08 AEST 1989
Submitted-by: koblas at 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 at 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 - at 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
More information about the Comp.sources.x
mailing list