[comp.sources.x] v02i076: XReadBitmapFile

mikew@wyse.wyse.com (Mike Wexler) (01/05/89)

Submitted-by: mic@emx.utexas.edu (Mic Kaczmarczik)
Posting-number: Volume 2, Issue 76
Archive-name: newrbf/part01

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 2)."
# Contents:  README Makefile RdBitF.c XRdBitF.c xshow.cursor
# Wrapped by mikew@wyse on Wed Jan  4 11:16:19 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(4009 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XThis directory contains versions of the X 11, Release 3 image file
Xreading routines that can read Suntools icons and single-plane Sun
Xrasterfiles (both unencoded and run-length byte encoded formats), as
Xwell as X 11 bitmap format files.  Also included are programs to
Xdisplay bitmaps in an X window using the routines, and to convert X
Xbitmap format files into Sun rasterfiles.
X
XThis code is likely most useful to Sun users, but it does work on
Xother systems.  I have tested this code on Suns, VAXen (under Ultrix
Xand 4.3 BSD), a Mac II running A/UX, an Encore Multimax, and a Convex,
Xso it seems to be relatively portable.
X
XX 11 clients that link in the routines won't notice any difference
Xbetween files of various formats; they just get a pixmap as the result
Xof the function call, as normal.  The known image formats are tried
Xsequentially until either a pixmap is returned or all the formats have
Xbeen tried.  The order in which formats are tried is:
X	X 11 bitmaps
X	Suntools icons
X	Sun rasterfiles
X
XThe ``native'' and most commonly used format (X 11 bitmaps) comes
Xfirst.  Suntools icons are next because (at least around here) they
Xare used quite frequently as icons and widget pixmap images, whereas
Xrasterfile format images are usually much larger and mainly used as
Xroot window backgrounds.
X
XI have also included xshow, a program that displays bitmap image files
Xon an X 11 display, so you can test the routines. (I used to use
Xxsetroot to look at images before I had this :-).  A last-minute
Xaddition is a slightly cleaned up version of the program I used to
Xconvert the Poskanzer bitmap collection into Sun rasterfile format to
Xsave space.  This program, like the library routines, has the
Xadvantage of working on machines other than Suns.
X
XInstallation
X------------
X
XThe files XRdBitF.c and RdBitF.c are replacements for
X$(TOP)/lib/X/XRdBitF.c and $(TOP)/lib/Xmu/RdBitF.c respectively, where
X$(TOP) represents the top level of your X 11 Release 3 build tree.
XSimply rename the distribution versions to something else (for example
XXRdBitF.c.orig), copy the new files into their respective places,
Xrebuild the X and Xmu libraries, and relink any clients that you want
Xto use the new routines in.
X
XOnce the library is rebuilt, clients such xterm, xsetroot, window
Xmanagers such as twm, and anything using the Release 3 X Toolkit
X(which allows you to define pixmap resources for widgets) are good
Xcandidates for relinking with the updated library.
X
XIf you want (or have) to keep your X 11 library in its original state,
Xyou can compile XRdBitF.c and RdBitF.c by themselves, but you will
Xstill need the private include files used to build the X and Xmu
Xlibraries, found in $(TOP)/lib/X and $(TOP)/lib/Xmu. Once the routines
Xare compiled, simply link them in ahead of the X 11 library on the
X`cc' command line, and they'll be used in preference to the versions
Xin the X library:
X	cc -o myprog myprog.c XRdBitF.o -lX11
X
XAn Imakefile is included.  I've also included a more conventional
XMakefile (Makefile.noimake) that does the same thing; you will likely
Xhave to edit the first few lines to make the program compile at your
Xsite.  Once that's done, type
X	make -f Makefile.noimake
X
Xto compile and link xshow and x11toras.  Sorry, but I don't have a man
Xpage for x11toras.
X
XCredits
X-------
X
XThe library routines are based on the X 11, Release 3 X and Xmu
Xlibrary sources.  The rasterfile uncompression code is from Martin
XBoyer, posted to the Sun-Spots mailing list in summer 1988.  Xshow is
Xbased on Xmac by Patrick Naughton, from the contributed software
Xdirectory on the X 11 Release 2 tape.  Thanks to Patrick and Martin,
Xand to everyone else who has contributed their software to the net --
Xthe wealth of useful programs and good examples has been of great
Xvalue to me over the past few years.
X
XMic Kaczmarczik
XUser Services Unix Support Group
XUT Austin Computation Center
XAustin, Texas
X
XInternet:	mic@emx.utexas.edu
XUUCP:		...!uunet!cs.utexas.edu!ut-emx!mic
XBITNET:		mic@utaivc
XTHENET:		utaivc::mic
END_OF_FILE
if test 4009 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(6845 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 = -axz
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)/llib-lX11.ln
X        LINTXMU = $(USRLIBDIR)/llib-lXmu.ln
X      LINTXTOOL = $(USRLIBDIR)/llib-lXt.ln
X        LINTXAW = $(USRLIBDIR)/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#
X# Imakefile for xshow and x11toras, using enhanced XReadBitmapFile()
X#
X
X          SRCS1 = xshow.c xshow.icon xshow.cursor
X          OBJS1 = xshow.o XRdBitF.o
X          SRCS2 = x11toras.c
X          OBJS2 = x11toras.o
X       PROGRAMS = xshow x11toras
XLOCAL_LIBRARIES = $(XLIB)
X        DEFINES = -I/src/x/x11.3/lib/X
X
X OBJS = $(OBJS1) $(OBJS2) $(OBJS3)
X SRCS = $(SRCS1) $(SRCS2) $(SRCS3)
X
Xall:: $(PROGRAMS)
X
Xxshow: $(OBJS1) $(XLIB)
X	$(RM) $@
X	$(CC) -o $@ $(OBJS1) $(XLIB) $(LDFLAGS)  $(SYSLAST_LIBRARIES)
X
Xinstall:: xshow
X	$(INSTALL) -c $(INSTALLFLAGS) xshow $(BINDIR)
X
Xinstall.man:: xshow.man
X	$(INSTALL) -c $(INSTMANFLAGS) xshow.man $(MANDIR)/xshow.n
X
Xrelink::
X	$(RM) $(PROGRAMS)
X	$(MAKE) $(MFLAGS) $(PROGRAMS)
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) $(PROGRAMS)
X
Xx11toras: $(OBJS2)
X	$(RM) $@
X	$(CC) -o $@ $(OBJS2)  $(LDFLAGS)  $(SYSLAST_LIBRARIES)
X
Xrelink::
X	$(RM) x11toras
X	$(MAKE) $(MFLAGS) x11toras
X
Xclean::
X	$(RM) x11toras
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 6845 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'RdBitF.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'RdBitF.c'\"
else
echo shar: Extracting \"'RdBitF.c'\" \(18757 characters\)
sed "s/^X//" >'RdBitF.c' <<'END_OF_FILE'
X/*
X * $XConsortium: RdBitF.c,v 1.4 88/09/13 12:06:36 jim Exp $
X *
X * Copyright 1988 Massachusetts Institute of Technology
X *
X * This file contains miscellaneous utility routines and is not part of the
X * Xlib standard.
X *
X * Public entry points:
X *
X *     XmuReadBitmapDataFromFile	read X10 or X11 format bitmap files
X *					and return data
X *
X * Note that this file and ../X/XRdBitF.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 "copyright.h"
X
X/*
X * Based on an optimized version provided by Jim Becker, Auguest 5, 1988.
X */
X
X#include <X11/Xos.h>
X#include <X11/Xlib.h>
X#include <X11/Xutil.h>
X#include <stdio.h>
X#include <ctype.h>
X
X
X#define MAX_SIZE 255
X#define	Xmalloc(size)	malloc(size)
X#define	Xfree(ptr)	free(ptr)
Xchar *malloc();
X
X/*
X * The data returned by the following routine is always in left-most byte
X * first and left-most bit first.  If it doesn't return BitmapSuccess then
X * its arguments won't have been touched.  This routine should look as much
X * like the Xlib routine XReadBitmapfile as possible.
X */
Xint XmuReadBitmapDataFromFile (filename, width, height, datap, x_hot, y_hot)
X    char *filename;
X    unsigned int *width, *height;	/* RETURNED */
X    unsigned char **datap;		/* RETURNED */
X    int *x_hot, *y_hot;			/* RETURNED */
X{
X  int		status;
X  FILE		*fstream = NULL, *fopen();
X
X#define RETURN(code) { if (fstream) fclose(fstream); return (code); }
X
X  if ((fstream = fopen(filename, "r")) == NULL)
X	  RETURN (BitmapOpenFailed);
X
X  /* X11/10 bitmaps */
X  status = _ReadBitmapDataFromFile(fstream, width, height, datap, x_hot, y_hot);
X  if (status != BitmapFileInvalid)
X	  RETURN (status);
X
X  /* Suntools icons */
X  fseek(fstream, 0L, 0);
X  status = _ReadIconDataFromFile(fstream, width, height, datap, x_hot, y_hot);
X  if (status != BitmapFileInvalid)
X	  RETURN (status);
X
X  /* Sun rasterfiles */
X  fseek(fstream, 0L, 0);
X  status = _ReadRasterDataFromFile(fstream, width, height, datap, x_hot, y_hot);
X
X  fclose(fstream);
X  return (status);
X}
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
X/*
X * Read X bitmap files (this code, with the exception of replacing the
X * file name argument with a FILE *, is the R3 XmuReadBitmapDataFromFile()).
X */
X
Xstatic int _ReadBitmapDataFromFile (fstream, width, height, datap, x_hot, y_hot)
X    FILE *fstream;
X    unsigned int *width, *height;       /* RETURNED */
X    unsigned char **datap;		/* RETURNED */
X    int *x_hot, *y_hot;                 /* RETURNED */
X{
X    unsigned char *data = NULL;		/* working variable */
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    /* error cleanup and return macro	*/
X#ifdef RETURN
X#undef RETURN
X#endif
X#define	RETURN(code) { if (data) free (data); return code; }
X
X    while (fgets(line, MAX_SIZE, fstream)) {
X	if (strlen(line) == MAX_SIZE-1) {
X	    RETURN (BitmapFileInvalid);
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 (BitmapFileInvalid);
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 *) Xmalloc ((unsigned int) size);
X	if (!data) 
X	  RETURN (BitmapNoMemory);
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 (BitmapFileInvalid);
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 (BitmapFileInvalid);
X		*ptr=value;
X	    }
X	}
X    }					/* end while */
X
X    if (data == NULL) {
X	RETURN (BitmapFileInvalid);
X    }
X
X    *datap = data;
X    data = NULL;
X    *width = ww;
X    *height = hh;
X    if (x_hot) *x_hot = hx;
X    if (y_hot) *y_hot = hy;
X
X    RETURN (BitmapSuccess);
X}
X
X/*
X * ReadRasterDataFromFile -- read Sun rasterfile data into a buffer
X *
X * Calling sequence is the same as XReadBitmapFile().  Run-length
X * decoding routine courtesy of Martin Boyer, posted to the Sun-Spots
X * mailing list May 1988.  This version has been tested on VAXen and
X * Encores as well as Suns.  No chance to test it on a Cray (yet).
X */
X
X#define	RASTERFILE_MAGIC	0x59a66a95
X#define OLD			0
X#define STANDARD		1
X#define	BYTE_ENCODED		2
X
Xstruct rasterfile_header {
X	int	magic;		/* has to be RASTERFILE_MAGIC	*/
X	int	width;
X	int	height;
X	int	depth;
X	int	length;
X	int	type;
X	int	maptype;
X	int	maplength;
X};
X
Xstatic int _ReadRasterDataFromFile(fstream, width, height, datap, x_hot, y_hot)
X     FILE *fstream;
X     unsigned int *width, *height;   /* RETURNED */
X     unsigned char **datap;
X     int *x_hot, *y_hot;    /* RETURNED */
X{
X  int hx = -1;
X  int hy = -1;
X
X  unsigned int decode_image();
X
X  int	imagebytes, databytes, linewidth, nbytes;
X  unsigned char	*image = NULL, *data = NULL;
X  struct rasterfile_header ras;
X
X  GC gc;
X  XImage img;
X  Pixmap pix;
X
X#ifdef	RETURN
X#undef	RETURN
X#endif
X#define RETURN(code) { if (image) Xfree(image); if (data) Xfree(data); \
X			       return (code); }
X
X  /*
X   * read in header and convert MSBFirst integers into local integers
X   */
X  if (fread(&ras, sizeof(ras), 1, fstream) < 1) 
X	  RETURN (BitmapFileInvalid);
X  ras.magic = msb_int((char *)&ras.magic);
X  ras.width = msb_int((char *)&ras.width);
X  ras.height = msb_int((char *)&ras.height);
X  ras.depth = msb_int((char *)&ras.depth);
X  ras.length = msb_int((char *)&ras.length);
X  ras.type = msb_int((char *)&ras.type);
X  ras.maptype = msb_int((char *)&ras.maptype);
X  ras.maplength = msb_int((char *)&ras.maplength);
X
X  /*
X   * Check for unsupported rasterfile formats.   Since we don't handle color
X   * images, ignore color map if provided.
X   */
X
X   if ((ras.magic != RASTERFILE_MAGIC) || (ras.depth != 1))
X	  RETURN (BitmapFileInvalid);
X
X  if ((ras.type != OLD) && (ras.type != STANDARD) && (ras.type != BYTE_ENCODED))
X	  RETURN (BitmapFileInvalid);
X
X  if (ras.maplength &&
X      (0 == fseek(fstream, sizeof(ras) + ras.maplength, 0)))
X	  RETURN (BitmapFileInvalid);
X
X  /*
X   * Determine the size of the image buffer and allocate memory for it.
X   * If we're provided with a length for the image data, use it, else
X   * the data is unencoded and uses the same amount of space as the
X   * image buffer.
X   */
X
X  linewidth = ((ras.width + 15) / 16) * 2;
X  imagebytes = linewidth * ras.height * ras.depth;
X  databytes = ras.length ? ras.length : imagebytes;
X
X  if ((image = (unsigned char *)Xmalloc(imagebytes)) == NULL)
X	  RETURN (BitmapNoMemory);
X
X  /*
X   * Read in the image.  If the format is BYTE_ENCODED, read into
X   * a separate buffer, unpack into the image, then convert to X 11 format.
X   */
X
X  if (ras.type != BYTE_ENCODED) {
X	  if (fread(image, 1, imagebytes, fstream) != imagebytes)
X		  RETURN (BitmapNoMemory);
X  } else {
X	  if ((data = (unsigned char *)Xmalloc(databytes)) == NULL)
X		  RETURN (BitmapNoMemory);
X	  if ((fread(data, 1, databytes, fstream) != databytes) ||
X	      (decode_image(data, image, databytes) != imagebytes))
X		  RETURN (BitmapFileInvalid);
X  }
X  pixtoX11(image, ras.width, ras.height);
X	  
X  *datap = image;
X  image = NULL;
X  *width = ras.width;
X  *height = ras.height;
X
X  if (x_hot)
X    *x_hot = hx;
X  if (y_hot)
X    *y_hot = hy;
X
X  RETURN (BitmapSuccess);
X}
X
X/*
X * ReadIconDataFromFile -- read Suntools icon data into a buffer
X */
X
Xstatic int _ReadIconDataFromFile(fstream, width, height, datap, x_hot, y_hot)
X     FILE *fstream;
X     unsigned int *width, *height;	/* RETURNED */
X     unsigned char **datap;		/* RETURNED */
X     int *x_hot, *y_hot;    		/* RETURNED */
X{
X  int hx = -1;
X  int hy = -1;
X
X  int	iconwidth = 64, iconheight = 64, valid_bits = 16, icondepth = 1;
X  int	iconbytes, linewidth, nbytes, nitems, value, c1, c2;
X  char	buf[BUFSIZ], *malloc();
X  register unsigned char *data = NULL, *cp;
X
X  GC gc;
X  XImage img;
X  Pixmap pix;
X
X#ifdef	RETURN
X#undef	RETURN
X#endif
X#define RETURN(code) { if (data) Xfree(data); return (code); } 
X
X  /*
X   * The string "/* Format_version=1" signifies a Sun icon file. If found,
X   * the rest of the line contains dimensions, etc.
X   */
X  for (;;) {
X	  if (fgets(buf, sizeof(buf), fstream) == NULL)
X		  RETURN (BitmapFileInvalid);
X
X	  if (0 == strncmp("/* Format_version=1",buf,19))
X		  break;
X  }
X
X  nitems = sscanf(buf,
X"/* Format_version=1, Width=%d, Height=%d, Depth = %d, Valid_bits_per_item=%d",
X		  &iconwidth, &iconheight, &icondepth, &valid_bits);
X
X  if (nitems != 4)
X	  RETURN (BitmapFileInvalid);
X
X  if ((icondepth != 1) || (valid_bits != 16))
X	  RETURN (BitmapFileInvalid);
X
X  /*
X   * seek to the end of the header section (end of the C comment)
X   */
X  while ((c1 = getc(fstream)) != EOF)
X	  if ((c1 == '*') && ((c2 = getc(fstream)) == '/'))
X		  break;
X  if ((c1 == EOF) || (c2 == EOF))
X	  RETURN (BitmapFileInvalid);
X
X  /*
X   * Determine the size of the pixrect-format image and allocate memory for it.
X   * A Sun pixrect is composed of raster scan lines, each padded to 16-bit
X   * word boundaries.  Pixels within each scan line are composed of 1, 4, or 8
X   * bits, laid out in big-endian (e.g. most signifigant bit/byte first)
X   * order.  In the case of single-plane images, we can ignore the depth
X   * of the image in calculating the width of each scan line.
X   */
X
X  linewidth = ((iconwidth + 15) / 16) * 2;
X  iconbytes = linewidth * iconheight;
X  if ((data = (unsigned char *)malloc(iconbytes)) == NULL)
X	  RETURN (BitmapNoMemory);
X
X  /*
X   * Read in the pixrect-format image, then convert to X 11 format and
X   * return it to the caller.
X   */
X  nbytes = 0;
X  cp = data; 
X  while (nbytes < iconbytes) {
X	  if (fscanf(fstream," 0x%2x%2x", &c1, &c2) != 2)
X		  RETURN (BitmapFileInvalid);
X	  *(cp++) = c1;
X	  *(cp++) = c2;
X	  if (((nbytes += 2) < iconbytes) && (fscanf(fstream,",") == EOF))
X		  RETURN (BitmapFileInvalid);
X  }
X  pixtoX11(data, iconwidth, iconheight);	/* convert to X 11 format */
X	  
X  *datap = data;
X  data = NULL;
X  *width = iconwidth;
X  *height = iconheight;
X
X  if (x_hot)
X    *x_hot = hx;
X  if (y_hot)
X    *y_hot = hy;
X
X  RETURN (BitmapSuccess);
X}
X
X/*
X * Date:    Mon, 9 May 88 17:17:07 EDT
X * From:    gamin%amadeus.UUCP@larry.mcrcim.mcgill.edu (Martin Boyer)
X * Subject: Re: Format for byte encoded rasterfiles (2)
X *
X * sow@cad.luth.se (Sven-Ove Westberg) and JDEBE@MTUS5.BITNET (John de
X * Beaubien) want to know the format of Suns runlength encoding for
X * rasterfiles.
X *
X * At one point, I wrote a quick filter to decode such files (I didn't want
X * the overhead of the pixrect library).  It took a while to find out (at the
X * time, there was a bug in pr_dump with RT_BYTE_ENCODED) but it paid off,
X * and I got something that is easily twice as fast as
X * /usr/lib/rasfilters/convert.2.
X *
X * The rules are the following:
X *
X * 1.  Encoding is byte per byte (regardless of the depth of the image)
X * 2.  Lengths of less than 3 are not encoded.
X * 3.  Lengths of 3 and more duplicate bytes are encoded as follows:
X *     for n consecutive "YZ" bytes, write out 0x80 (n-1) "YZ"
X *     so:  YZ YZ YZ YZ	=> 0x80 0x03 0xYZ
X *
X *     exception: 0x80 (alone) => 0x80 0x00    (note missing byte)
X * 	and NOT 0x80 0x00 0x80
X *     but 0x80 0x80 => 0x80 0x01 0x80  (follows general rule)
X *
X * Even better, here is a function that does the decoding:
X * (I don't have any for encoding)
X *
X * It worked for at least a year on all sorts of images without a burp.
X * Good luck!
X *
X * Martin Boyer                               amadeus!gamin@mcgill-vision.uucp
X * Institut de recherche d'Hydro-Quebec       sun!sunlegende!amadeus!gamin
X * Varennes, QC, Canada   J0L 2P0             +1 514 652-8136
X */
X
X/*
X * First argument is a pointer to the encoded array of pixels.
X *    Second is a pointer to enough space for the decoded array of pixels,
X *    which will be ras_width (rounded up to a short) * ras_height
X * 	* ras_depth long
X *    Third is length of input (in bytes) (ras_length).
X *
X *    Returns length of decoded output, can be used to verify correct
X *    encoding/decoding.
X */
X
Xunsigned int 
Xdecode_image(inpix, outpix, lin)
X    register unsigned char *inpix, *outpix;
X    register unsigned int    lin;
X{
X    register unsigned char   value;
X    register unsigned int    n;
X    unsigned char  *outpix_0;
X
X    outpix_0 = outpix;
X    while (lin) {
X	if ((value = *inpix++) == 0x80) {
X	    if ((n = *inpix++) == 0) {
X		*outpix++ = 0x80;	/* special: 0x80 0x00 ==> 0x80 */
X		lin -= 2;
X	    } else {
X		for (value = *inpix++, n++; n; n--)
X		    *outpix++ = value;
X		lin -= 3;
X	    }
X	} else {
X	    *outpix++ = value;
X	    lin--;
X	}
X    }
X    return (outpix - outpix_0);
X}
X
X/*
X * Treat cp[0] through cp[3] as a big-endian 32-bit longword and convert
X * it into an integer.
X */
X
Xstatic msb_int(cp)
Xregister unsigned char *cp;
X{
X	return ((cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | cp[3]);
X}
X
X/*
X * 256-byte table for quickly reversing the bits in an unsigned 8-bit char,
X * used to convert between MSBFirst and LSBFirst image formats.
X */
X
Xstatic char revtable[256] = { 
X	    0, -128,   64,  -64,   32,  -96,   96,  -32,
X	   16, -112,   80,  -48,   48,  -80,  112,  -16,
X	    8, -120,   72,  -56,   40,  -88,  104,  -24,
X	   24, -104,   88,  -40,   56,  -72,  120,   -8,
X	    4, -124,   68,  -60,   36,  -92,  100,  -28,
X	   20, -108,   84,  -44,   52,  -76,  116,  -12,
X	   12, -116,   76,  -52,   44,  -84,  108,  -20,
X	   28, -100,   92,  -36,   60,  -68,  124,   -4,
X	    2, -126,   66,  -62,   34,  -94,   98,  -30,
X	   18, -110,   82,  -46,   50,  -78,  114,  -14,
X	   10, -118,   74,  -54,   42,  -86,  106,  -22,
X	   26, -102,   90,  -38,   58,  -70,  122,   -6,
X	    6, -122,   70,  -58,   38,  -90,  102,  -26,
X	   22, -106,   86,  -42,   54,  -74,  118,  -10,
X	   14, -114,   78,  -50,   46,  -82,  110,  -18,
X	   30,  -98,   94,  -34,   62,  -66,  126,   -2,
X	    1, -127,   65,  -63,   33,  -95,   97,  -31,
X	   17, -111,   81,  -47,   49,  -79,  113,  -15,
X	    9, -119,   73,  -55,   41,  -87,  105,  -23,
X	   25, -103,   89,  -39,   57,  -71,  121,   -7,
X	    5, -123,   69,  -59,   37,  -91,  101,  -27,
X	   21, -107,   85,  -43,   53,  -75,  117,  -11,
X	   13, -115,   77,  -51,   45,  -83,  109,  -19,
X	   29,  -99,   93,  -35,   61,  -67,  125,   -3,
X	    3, -125,   67,  -61,   35,  -93,   99,  -29,
X	   19, -109,   83,  -45,   51,  -77,  115,  -13,
X	   11, -117,   75,  -53,   43,  -85,  107,  -21,
X	   27, -101,   91,  -37,   59,  -69,  123,   -5,
X	    7, -121,   71,  -57,   39,  -89,  103,  -25,
X	   23, -105,   87,  -41,   55,  -73,  119,   -9,
X	   15, -113,   79,  -49,   47,  -81,  111,  -17,
X	   31,  -97,   95,  -33,   63,  -65,  127,   -1,
X};
X
X/*
X * Convert pixrect-format data into X 11 format data, which means reversing
X * the bits, and removing the extra byte of padding.  Removing the padding
X * is done by backing up at the end of a pixrect line, if necessary.
X */
X
Xstatic pixtoX11(data, width, height)
Xunsigned char *data;
Xint width, height;
X{
X	register unsigned char tmp, *cp, *end, *datap;
X	int row, linewidth, unpad = False;
X
X	linewidth = ((width + 7) / 8);
X	if (linewidth & 1) {
X		linewidth++;
X		unpad = True;
X	}
X
X	datap = data;
X	for (row = 0 ; row < height ; row++) {
X		cp = data + (row * linewidth);
X		end = cp + linewidth;
X		while (cp < end)
X			*(datap++) = revtable[*(cp++)];
X		if (unpad)
X			datap--;	/* back up to unpad line	*/
X	}
X}
END_OF_FILE
if test 18757 -ne `wc -c <'RdBitF.c'`; then
    echo shar: \"'RdBitF.c'\" unpacked with wrong size!
fi
# end of 'RdBitF.c'
fi
if test -f 'XRdBitF.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'XRdBitF.c'\"
else
echo shar: Extracting \"'XRdBitF.c'\" \(20928 characters\)
sed "s/^X//" >'XRdBitF.c' <<'END_OF_FILE'
X/* Copyright, 1987, Massachusetts Institute of Technology */
X
X#include "X11/copyright.h"
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 *	Sun rasterfile and Suntools icon support by
X *	Mic Kaczmarczik, November 1988. The rasterfile and
X *	icon support can be used on machines other than Suns.
X *	In particular, it works fine on VAXen and Encores.
X *
X *	Uses code to decode run-length encoded Sun rasterfiles
X *	by Martin Boyer.
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 <X11/Xos.h>
X#include "Xlib.h"
X#include "Xutil.h"
X#include "Xlibint.h"
X#include <stdio.h>
X#include <ctype.h>
X
X
X#define MAX_SIZE 255
X
X/*
X * XReadBitmapFile is now a front end for different routines to read
X * in bitmap files.  The order in which formats are tried is somewhat
X * arbitrary, but I figure X bitmaps should come first, then Suntools
X * icons (which will probably be used more often than big rasterfiles),
X * and finally rasterfiles.
X */
X
Xint XReadBitmapFile(display, d, filename, width, height, bitmap, x_hot, y_hot)
X     Display *display;
X     Drawable d;
X     char *filename;
X     unsigned int *width, *height;	/* RETURNED */
X     Pixmap *bitmap;			/* RETURNED */
X     int *x_hot, *y_hot;		/* RETURNED */
X{
X  int		status;
X  FILE		*fstream = NULL, *fopen();
X
X#define RETURN(code) { if (fstream) fclose(fstream); return (code); }
X
X  if ((fstream = fopen(filename, "r")) == NULL)
X	  RETURN (BitmapOpenFailed);
X
X  /* X11/10 bitmaps */
X  status = _ReadBitmapFile(display, d, fstream,
X			   width, height, bitmap, x_hot, y_hot);
X  if (status != BitmapFileInvalid)
X	  RETURN (status);
X
X  /* Suntools icons */
X  fseek(fstream, 0L, 0);
X  status = _ReadIconFile(display, d, fstream, width, height,
X			bitmap, x_hot, y_hot);
X  if (status != BitmapFileInvalid)
X	  RETURN (status);
X
X  /* Sun rasterfiles */
X  fseek(fstream, 0L, 0);
X  status = _ReadRasterFile(display, d, fstream,
X			   width, height, bitmap, x_hot, y_hot);
X
X  fclose(fstream);
X  return (status);
X}
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
X/*
X * Read X bitmap files (this code, with the exception of replacing the
X * file name argument with a FILE *, is the R3 XReadBitmapFile()).
X */
X
X_ReadBitmapFile (display, d, fstream, width, height, pixmap, x_hot, y_hot)
X    Display *display;
X    Drawable d;
X    FILE *fstream;
X    unsigned int *width, *height;       /* RETURNED */
X    Pixmap *pixmap;                     /* RETURNED */
X    int *x_hot, *y_hot;                 /* RETURNED */
X{
X    Pixmap pix;				/* value to return */
X    unsigned char *data = NULL;		/* working variable */
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    /* error cleanup and return macro	*/
X#ifdef RETURN
X#undef RETURN
X#endif
X#define	RETURN(code) { if (data) free (data); return code; }
X
X    while (fgets(line, MAX_SIZE, fstream)) {
X	if (strlen(line) == MAX_SIZE-1) {
X	    RETURN (BitmapFileInvalid);
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 (BitmapFileInvalid);
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 *) Xmalloc ((unsigned int) size);
X	if (!data) 
X	  RETURN (BitmapNoMemory);
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 (BitmapFileInvalid);
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 (BitmapFileInvalid);
X		*ptr=value;
X	    }
X	}
X    }					/* end while */
X
X    if (data == NULL) {
X	RETURN (BitmapFileInvalid);
X    }
X
X    pix = XCreateBitmapFromData (display, d, data, ww, hh);
X    if (pix == None) {
X	RETURN (BitmapNoMemory);
X    }
X    *pixmap = pix;
X    *width = ww;
X    *height = hh;
X    if (x_hot) *x_hot = hx;
X    if (y_hot) *y_hot = hy;
X
X    RETURN (BitmapSuccess);
X}
X
X/*
X * ReadRasterFile -- read a Sun rasterfile into a pixmap
X *
X * Read a Sun rasterfile into a pixmap. Calling sequence is the same as
X * XReadBitmapFile(). Run-length decoding routine courtesy of Martin Boyer,
X * posted to the Sun-Spots mailing list May 1988.  This version has been
X * tested on VAXen and Encores as well as Suns.  No chance to test it
X * on a Cray (yet).
X */
X
X#define	RASTERFILE_MAGIC	0x59a66a95
X#define OLD			0
X#define STANDARD		1
X#define	BYTE_ENCODED		2
X
Xstruct rasterfile_header {
X	int	magic;
X	int	width;
X	int	height;
X	int	depth;
X	int	length;
X	int	type;
X	int	maptype;
X	int	maplength;
X};
X
Xstatic int _ReadRasterFile(display, d, fstream, width, height, bitmap, x_hot, y_hot)
X     Display *display;
X     Drawable d;
X     FILE *fstream;
X     unsigned int *width, *height;   /* RETURNED */
X     Pixmap *bitmap;        /* RETURNED */
X     int *x_hot, *y_hot;    /* RETURNED */
X{
X  int hx = -1;
X  int hy = -1;
X
X  unsigned int decode_image();
X
X  int	imagebytes, databytes, linewidth, nbytes;
X  unsigned char	*image = NULL, *data = NULL;
X  struct rasterfile_header ras;
X
X  GC gc;
X  XImage img;
X  Pixmap pix;
X
X#ifdef	RETURN
X#undef	RETURN
X#endif
X#define RETURN(code) { if (image) Xfree(image); if (data) Xfree(data); \
X			       return (code); }
X
X  /*
X   * read in header and convert MSBFirst 4-byte longwords into integers
X   */
X  if (fread(&ras, sizeof(ras), 1, fstream) < 1) 
X	  RETURN (BitmapFileInvalid);
X
X  ras.magic = msb_int((char *)&ras.magic);
X  ras.width = msb_int((char *)&ras.width);
X  ras.height = msb_int((char *)&ras.height);
X  ras.depth = msb_int((char *)&ras.depth);
X  ras.length = msb_int((char *)&ras.length);
X  ras.type = msb_int((char *)&ras.type);
X  ras.maptype = msb_int((char *)&ras.maptype);
X  ras.maplength = msb_int((char *)&ras.maplength);
X
X  /*
X   * Check for unsupported rasterfile formats.   Since we don't handle color
X   * images, ignore color map if provided.
X   */
X
X   if ((ras.magic != RASTERFILE_MAGIC) || (ras.depth != 1))
X	  RETURN (BitmapFileInvalid);
X
X  if ((ras.type != OLD) && (ras.type != STANDARD) && (ras.type != BYTE_ENCODED))
X	  RETURN (BitmapFileInvalid);
X
X  if (ras.maplength &&
X      (0 == fseek(fstream, sizeof(ras) + ras.maplength, 0)))
X	  RETURN (BitmapFileInvalid);
X
X  /*
X   * Determine the size of the image buffer and allocate memory for it.
X   * If we're provided with a length for the image data, use it, else
X   * the data is unencoded and uses the same amount of space as the
X   * image buffer.
X   */
X
X  linewidth = ((ras.width + 15) / 16) * 2;
X  imagebytes = linewidth * ras.height * ras.depth;
X  databytes = ras.length ? ras.length : imagebytes;
X
X  if ((image = (unsigned char *)Xmalloc(imagebytes)) == NULL)
X	  RETURN (BitmapNoMemory);
X
X  /*
X   * Read in the image.  If the format is BYTE_ENCODED, read into
X   * a separate buffer and unpack into the image.
X   */
X
X  if (ras.type != BYTE_ENCODED) {
X	  if (fread(image, 1, imagebytes, fstream) != imagebytes)
X		  RETURN (BitmapNoMemory);
X  } else {
X	  if ((data = (unsigned char *)Xmalloc(databytes)) == NULL)
X		  RETURN (BitmapNoMemory);
X	  if ((fread(data, 1, databytes, fstream) != databytes) ||
X	      (decode_image(data, image, databytes) != imagebytes))
X		  RETURN (BitmapFileInvalid);
X  }
X	  
X
X  /*
X   * Convert the bitmap data to X 11 format (basically unpad lines with
X   * an odd line width), then create a pixmap from the data.  It might
X   * be more efficient to query the server for the preferred bit order,
X   * but I don't pretend to know the right way to do it.
X   */
X
X  pixtoX11(image, ras.width, ras.height);
X  pix = XCreateBitmapFromData (display, d, image,
X				       ras.width, ras.height);
X  if (pix == None)
X	  RETURN (BitmapNoMemory);
X
X  /*
X   * Return the pixmap and its size, clean up and return.
X   */
X
X  *bitmap = pix;
X  *width = ras.width;
X  *height = ras.height;
X
X  if (x_hot)
X    *x_hot = hx;
X  if (y_hot)
X    *y_hot = hy;
X
X  RETURN (BitmapSuccess);
X}
X
X/*
X * ReadIconFile -- read a Suntools icon into an X11 pixmap
X */
X
Xstatic int _ReadIconFile(display, d, fstream, width, height, bitmap, x_hot, y_hot)
X     Display *display;
X     Drawable d;
X     FILE *fstream;
X     unsigned int *width, *height;   /* RETURNED */
X     Pixmap *bitmap;        /* RETURNED */
X     int *x_hot, *y_hot;    /* RETURNED */
X{
X  int hx = -1;
X  int hy = -1;
X
X  int	iconwidth = 64, iconheight = 64, valid_bits = 16, icondepth = 1;
X  int	iconbytes, linewidth, nbytes, nitems, value, c1, c2;
X  char	buf[BUFSIZ], *malloc();
X  register unsigned char *data = NULL, *cp;
X
X  GC gc;
X  XImage img;
X  Pixmap pix;
X
X#ifdef	RETURN
X#undef	RETURN
X#endif
X#define RETURN(code) { if (data) Xfree(data); return (code); } 
X
X  /*
X   * The string "/* Format_version=1" signifies a Sun icon file. If found,
X   * the rest of the line contains dimensions, etc.
X   */
X  for (;;) {
X	  if (fgets(buf, sizeof(buf), fstream) == NULL)
X		  RETURN (BitmapFileInvalid);
X
X	  if (0 == strncmp("/* Format_version=1",buf,19))
X		  break;
X  }
X
X  nitems = sscanf(buf,
X"/* Format_version=1, Width=%d, Height=%d, Depth = %d, Valid_bits_per_item=%d",
X		  &iconwidth, &iconheight, &icondepth, &valid_bits);
X
X  if (nitems != 4)
X	  RETURN (BitmapFileInvalid);
X
X  if ((icondepth != 1) || (valid_bits != 16))
X	  RETURN (BitmapFileInvalid);
X
X  /*
X   * seek to the end of the header section (end of the C comment)
X   */
X  while ((c1 = getc(fstream)) != EOF)
X	  if ((c1 == '*') && ((c2 = getc(fstream)) == '/'))
X		  break;
X  if ((c1 == EOF) || (c2 == EOF))
X	  RETURN (BitmapFileInvalid);
X
X  /*
X   * Determine the size of the pixrect-format image and allocate memory for it.
X   * A Sun pixrect is composed of raster scan lines, each padded to 16-bit
X   * word boundaries.  Pixels within each scan line are composed of 1, 4, or 8
X   * bits, laid out in big-endian (e.g. most signifigant bit/byte first)
X   * order.  In the case of single-plane images, we can ignore the depth
X   * of the image in calculating the width of each scan line.
X   */
X
X  linewidth = ((iconwidth + 15) / 16) * 2;
X  iconbytes = linewidth * iconheight;
X  if ((data = (unsigned char *)malloc(iconbytes)) == NULL)
X	  RETURN (BitmapNoMemory);
X
X  /*
X   * Read in the image, reading each integer as an MSBFirst 2-byte short
X   * Could of course be done faster.
X   */
X  nbytes = 0;
X  cp = data; 
X  while (nbytes < iconbytes) {
X	  if (fscanf(fstream," 0x%2x%2x", &c1, &c2) != 2)
X		  RETURN (BitmapFileInvalid);
X	  *(cp++) = c1;
X	  *(cp++) = c2;
X	  if (((nbytes += 2) < iconbytes) && (fscanf(fstream,",") == EOF))
X		  RETURN (BitmapFileInvalid);
X  }
X
X	  
X  /*
X   * Convert the data into X 11 format and create a pixmap from it.
X   * It might be more efficient to query the server for the preferred
X   * bitmap bit order.
X   */
X  pixtoX11(data, iconwidth, iconheight);
X  pix = XCreateBitmapFromData (display, d, data,
X				       iconwidth, iconheight);
X  if (pix == None)
X	  RETURN (BitmapNoMemory);
X
X
X  /*
X   * Return the pixmap and its size, clean up and return.
X   */
X
X  *bitmap = pix;
X  *width = iconwidth;
X  *height = iconheight;
X
X  if (x_hot)
X    *x_hot = hx;
X  if (y_hot)
X    *y_hot = hy;
X
X  RETURN (BitmapSuccess);
X}
X
X/*
X * Date:    Mon, 9 May 88 17:17:07 EDT
X * From:    gamin%amadeus.UUCP@larry.mcrcim.mcgill.edu (Martin Boyer)
X * Subject: Re: Format for byte encoded rasterfiles (2)
X *
X * sow@cad.luth.se (Sven-Ove Westberg) and JDEBE@MTUS5.BITNET (John de
X * Beaubien) want to know the format of Suns runlength encoding for
X * rasterfiles.
X *
X * At one point, I wrote a quick filter to decode such files (I didn't want
X * the overhead of the pixrect library).  It took a while to find out (at the
X * time, there was a bug in pr_dump with RT_BYTE_ENCODED) but it paid off,
X * and I got something that is easily twice as fast as
X * /usr/lib/rasfilters/convert.2.
X *
X * The rules are the following:
X *
X * 1.  Encoding is byte per byte (regardless of the depth of the image)
X * 2.  Lengths of less than 3 are not encoded.
X * 3.  Lengths of 3 and more duplicate bytes are encoded as follows:
X *     for n consecutive "YZ" bytes, write out 0x80 (n-1) "YZ"
X *     so:  YZ YZ YZ YZ	=> 0x80 0x03 0xYZ
X *
X *     exception: 0x80 (alone) => 0x80 0x00    (note missing byte)
X * 	and NOT 0x80 0x00 0x80
X *     but 0x80 0x80 => 0x80 0x01 0x80  (follows general rule)
X *
X * Even better, here is a function that does the decoding:
X * (I don't have any for encoding)
X *
X * It worked for at least a year on all sorts of images without a burp.
X * Good luck!
X *
X * Martin Boyer                               amadeus!gamin@mcgill-vision.uucp
X * Institut de recherche d'Hydro-Quebec       sun!sunlegende!amadeus!gamin
X * Varennes, QC, Canada   J0L 2P0             +1 514 652-8136
X */
X
X/*
X * First argument is a pointer to the encoded array of pixels.
X *    Second is a pointer to enough space for the decoded array of pixels,
X *    which will be ras_width (rounded up to a short) * ras_height
X * 	* ras_depth long
X *    Third is length of input (in bytes) (ras_length).
X *
X *    Returns length of decoded output, can be used to verify correct
X *    encoding/decoding.
X */
X
Xunsigned int 
Xdecode_image(inpix, outpix, lin)
X    register unsigned char *inpix, *outpix;
X    register unsigned int    lin;
X{
X    register unsigned char   value;
X    register unsigned int    n;
X    unsigned char  *outpix_0;
X
X    outpix_0 = outpix;
X    while (lin) {
X	if ((value = *inpix++) == 0x80) {
X	    if ((n = *inpix++) == 0) {
X		*outpix++ = 0x80;	/* special: 0x80 0x00 ==> 0x80 */
X		lin -= 2;
X	    } else {
X		for (value = *inpix++, n++; n; n--)
X		    *outpix++ = value;
X		lin -= 3;
X	    }
X	} else {
X	    *outpix++ = value;
X	    lin--;
X	}
X    }
X    return (outpix - outpix_0);
X}
X
X/*
X * Treat cp[0] through cp[3] as a big-endian 32-bit longword and convert
X * it into an integer.
X */
X
Xstatic msb_int(cp)
Xregister unsigned char *cp;
X{
X	return ((cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | cp[3]);
X}
X
X/*
X * 256-byte table for quickly reversing the bits in an unsigned 8-bit char,
X * used to convert between MSBFirst and LSBFirst image formats.
X */
X
Xstatic char revtable[256] = { 
X	    0, -128,   64,  -64,   32,  -96,   96,  -32,
X	   16, -112,   80,  -48,   48,  -80,  112,  -16,
X	    8, -120,   72,  -56,   40,  -88,  104,  -24,
X	   24, -104,   88,  -40,   56,  -72,  120,   -8,
X	    4, -124,   68,  -60,   36,  -92,  100,  -28,
X	   20, -108,   84,  -44,   52,  -76,  116,  -12,
X	   12, -116,   76,  -52,   44,  -84,  108,  -20,
X	   28, -100,   92,  -36,   60,  -68,  124,   -4,
X	    2, -126,   66,  -62,   34,  -94,   98,  -30,
X	   18, -110,   82,  -46,   50,  -78,  114,  -14,
X	   10, -118,   74,  -54,   42,  -86,  106,  -22,
X	   26, -102,   90,  -38,   58,  -70,  122,   -6,
X	    6, -122,   70,  -58,   38,  -90,  102,  -26,
X	   22, -106,   86,  -42,   54,  -74,  118,  -10,
X	   14, -114,   78,  -50,   46,  -82,  110,  -18,
X	   30,  -98,   94,  -34,   62,  -66,  126,   -2,
X	    1, -127,   65,  -63,   33,  -95,   97,  -31,
X	   17, -111,   81,  -47,   49,  -79,  113,  -15,
X	    9, -119,   73,  -55,   41,  -87,  105,  -23,
X	   25, -103,   89,  -39,   57,  -71,  121,   -7,
X	    5, -123,   69,  -59,   37,  -91,  101,  -27,
X	   21, -107,   85,  -43,   53,  -75,  117,  -11,
X	   13, -115,   77,  -51,   45,  -83,  109,  -19,
X	   29,  -99,   93,  -35,   61,  -67,  125,   -3,
X	    3, -125,   67,  -61,   35,  -93,   99,  -29,
X	   19, -109,   83,  -45,   51,  -77,  115,  -13,
X	   11, -117,   75,  -53,   43,  -85,  107,  -21,
X	   27, -101,   91,  -37,   59,  -69,  123,   -5,
X	    7, -121,   71,  -57,   39,  -89,  103,  -25,
X	   23, -105,   87,  -41,   55,  -73,  119,   -9,
X	   15, -113,   79,  -49,   47,  -81,  111,  -17,
X	   31,  -97,   95,  -33,   63,  -65,  127,   -1,
X};
X
X/*
X * Convert pixrect-format data into X 11 format data, which means reversing
X * the bits, and removing the extra byte of padding.  Removing the padding
X * is done by backing up at the end of a pixrect line, if necessary.
X */
X
Xstatic pixtoX11(data, width, height)
Xunsigned char *data;
Xint width, height;
X{
X	register unsigned char tmp, *cp, *end, *datap;
X	int row, linewidth, unpad = False;
X
X	linewidth = ((width + 7) / 8);
X	if (linewidth & 1) {
X		linewidth++;
X		unpad = True;
X	}
X
X	datap = data;
X	for (row = 0 ; row < height ; row++) {
X		cp = data + (row * linewidth);
X		end = cp + linewidth;
X		while (cp < end)
X			*(datap++) = revtable[*(cp++)];
X		if (unpad)
X			datap--;	/* back up to unpad line	*/
X	}
X}
X
X
X/*
X * Emulate CreateBitmapFromData, but using parameters suitable for
X * pixrect-format data.
X */
Xstatic _CreateBitmapFromPixrectData(display, d, data, width, height)
XDisplay *display;
XDrawable d;
Xchar *data;
Xint width, height;
X{
X	GC gc;
X	XImage ximage;
X	Pixmap pix;
X
X	pix = XCreatePixmap(display, d, width, height, 1);
X	if (pix == None)
X		return (pix);
X
X	gc = XCreateGC(display, pix, (unsigned long)0, (XGCValues *)0);
X
X	ximage.width = width;
X	ximage.height = height;
X	ximage.depth = 1;
X	ximage.xoffset = 0;
X	ximage.format = ZPixmap;
X	ximage.data = data;
X	ximage.byte_order = MSBFirst;
X	ximage.bitmap_unit = 8;
X	ximage.bitmap_bit_order = MSBFirst;
X	ximage.bitmap_pad = 16;
X	ximage.bytes_per_line = ((width + 15) / 16) * 2;
X
X	XPutImage(display, pix, gc, &ximage, 0, 0, 0, 0, width, height);
X	XFreeGC(display, gc);
X
X	return (pix);
X}
END_OF_FILE
if test 20928 -ne `wc -c <'XRdBitF.c'`; then
    echo shar: \"'XRdBitF.c'\" unpacked with wrong size!
fi
# end of 'XRdBitF.c'
fi
if test -f 'xshow.cursor' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xshow.cursor'\"
else
echo shar: Extracting \"'xshow.cursor'\" \(564 characters\)
sed "s/^X//" >'xshow.cursor' <<'END_OF_FILE'
X#define bitmap_width 16
X#define bitmap_height 16
X#define bitmap_x_hot 2
X#define bitmap_y_hot 4
Xstatic char bitmap_bits[] = {
X   0x00, 0x00, 0x80, 0x1f, 0x40, 0x08, 0x23, 0x04, 0x57, 0x05, 0x13, 0x04,
X   0xd3, 0x05, 0x1f, 0x3c, 0x1c, 0x7c, 0x10, 0x64, 0x90, 0x74, 0x90, 0x64,
X   0x90, 0x04, 0x88, 0x08, 0x84, 0x10, 0x7c, 0x1f};
Xstatic char bitmap_mask_bits[] = {
X   0x80, 0x3f, 0xc0, 0x3f, 0xe7, 0x1f, 0xff, 0x0f, 0xff, 0x0f, 0xff, 0x0f,
X   0xff, 0x3f, 0xff, 0x7f, 0xff, 0xff, 0xfc, 0xff, 0xf8, 0xff, 0xf8, 0xff,
X   0xf8, 0x6f, 0xfc, 0x1f, 0xfe, 0x3f, 0xfe, 0x3f};
END_OF_FILE
if test 564 -ne `wc -c <'xshow.cursor'`; then
    echo shar: \"'xshow.cursor'\" unpacked with wrong size!
fi
# end of 'xshow.cursor'
fi
echo shar: End of archive 1 \(of 2\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both 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