[comp.sources.x] v09i053: xloadimage, Part06/09

jimf@saber.com (09/28/90)

Submitted-by: saber.com!jimf@saber.com
Posting-number: Volume 9, Issue 53
Archive-name: xloadimage/part06

#! /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 6 (of 9)."
# Contents:  rle.c send.c smooth.c sunraster.c xbitmap.c zio.c
# Wrapped by jimf@armory on Tue Sep 25 19:37:41 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'rle.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'rle.c'\"
else
echo shar: Extracting \"'rle.c'\" \(11071 characters\)
sed "s/^X//" >'rle.c' <<'END_OF_FILE'
X/* 
X * rle - read in a Utah RLE Toolkit type image.
X * 
X * Author:	Graeme Gill
X * Date: 	30/5/90
X * 
X * Bugs - doesn't free up memory used by rle functions.
X *
X */
X
X#undef  DEBUG
X
X#ifdef DEBUG
X# define debug(xx)	fprintf(stderr,xx)
X#else
X# define debug(xx)
X#endif
X
X
X#define MIN(a,b) ( (a)<(b) ? (a) : (b))
X
X#include <math.h>
X#include <stdio.h>
X#include "image.h"
X#include "rle.h"
X
X/* input file stuff */
Xstatic int ptype;				/* picture type : */
X#define BW_NM	0		/* black and white, no map */
X#define BW_M	1		/* black and white, and a map */
X#define SC_M	2		/* single colour channel and colour map */
X#define C_NM	3		/* full colour, no maps */
X#define C_M		4		/* full colour with colour maps */
Xstatic rle_pixel **fmaps;		/* file colour maps from buildmap() */
Xstatic unsigned char **scan;	/* buffer for input data */
Xstatic int x_min;		/* copy of picture x_min */
Xstatic int y_min;		/* copy of picture y_min */
X
X/* option stuff (Not functional) */
Xstatic float disp_gam = 2.0;	/* default display gamma correction factor */
Xstatic int gflag = 0;			/* if user supplies display gamma */
Xstatic int iflag=0;			/* user suplied image gamma */
Xstatic int lflag=0;			/* user supplied levels */
Xstatic float img_gam = 1.0;			/* image gamma */
Xstatic int bwflag = 0;			/* black and white flag */
Xstatic int gammamap[256];
Xstatic int background[3] = {0,0,0};	/* our background colour */
X
X/* stuff for dithering colour pictures */
Xint colmap[216][3];		/* for dither map */
Xint magic[16][16];
Xint modN[256];
Xint divN[256];
X
Xint rleIdent(fullname,name)
Xchar *fullname, *name;
X	{
X	ZFILE *rlefile;
X	int x_len,y_len;
X	int rv;
X
X	debug("rleIdent called\n");
X	rlefile = zopen(fullname);
X	if(!rlefile)
X		{
X		perror("rleIdent: Unable to open file");
X		return(0);
X		}
X	debug("rleIdent: Opened file ok\n");
X	sv_globals.svfb_fd = rlefile;
X	rv = rle_get_setup(&sv_globals);
X	debug("rleIdent: got setup ok\n");
X	zclose(rlefile);
X	debug("rleIdent: closed file ok\n");
X	switch(rv)
X		{
X		case -1:
X			return 0;		/* Not rle format */
X		case 0:
X			/* now figure out the picture type */
X			switch(sv_globals.sv_ncolors)
X				{
X				case 0:
X					perror("rleIdent: no colour channels to display");
X					return(0);
X				case 1:
X					x_len = sv_globals.sv_xmax - sv_globals.sv_xmin + 1;
X					y_len = sv_globals.sv_ymax - sv_globals.sv_ymin + 1;
X					printf("%s is a %dx%d,",name,x_len,y_len);
X					switch(sv_globals.sv_ncmap)
X						{
X						case 0:
X							/* black and white, no map */
X							printf(" 8 bit grey scale image with no map"); 
X							break;
X						case 1:
X							/* black and white with a map */
X							printf(" 8 bit grey scale image with map"); 
X							break;
X						case 3:
X							/* single channel encoded colour with decoding map */
X							printf(" 8 bit colour image with colour map");
X							break;
X						default:
X							perror(" 8 bit image with an illegal colour map");
X							return 0;
X						}
X					break;
X				case 3:
X					switch(sv_globals.sv_ncmap)
X						{
X						case 0:
X							printf(" 24 bit colour image with no map");
X							break;
X						case 3:
X							printf(" 24 bit colour image with colour map");
X							break;
X						default:
X							perror(" 24 bit colour image with an illegal colour map");
X							return 0;
X						}
X					break;
X				default:
X					perror(" image with an illegal number of colour planes");
X					return 0;
X				}
X			return 1;
X		default:			/* Some sort of error */
X/*			perror("rleIdent");*/
X			return 0;
X		}
X	}
X
X
XImage *rleLoad(fullname,name,verbose)
Xchar *fullname,*name;
Xunsigned int verbose;
X	{
X	int x_len, y_len;
X	int i,j;
X	ZFILE *rlefile;
X	int ncol;			/* number of colors */
X	int depth;
X	unsigned char *bufp;
X	char *v;
X	Image *image;
X	unsigned char *buf;
X
X	dith_levels = 256;	/* aim for 128 levels of each colour */
X
X	debug("rleLoad called\n");
X	rlefile = zopen(fullname);
X	if(!rlefile)
X		{
X		perror("rleLoad: Cannot open input file");
X		return(NULL);	
X		}
X	sv_globals.svfb_fd = rlefile;
X	debug("rleLoad: About to call get_setup\n");
X	if(rle_get_setup( &sv_globals )) {
X		zclose(rlefile);
X		return(NULL);	
X	}
X
X	debug("rleLoad: get_setup called ok\n");
X	if(iflag == 1)	/* -i flag */
X		img_gam = 1.0/img_gam;		/* convert to display gamma */
X
X    /* If no image gamma on command line, check comments in file */
X    if (!iflag)
X		{
X		char * v;
X		if ( (v = rle_getcom( "image_gamma", &sv_globals )) != NULL )
X			{	
X			img_gam = atof( v );
X			/* Protect against bogus information */
X			if ( img_gam == 0.0 )
X				img_gam = 1.0;
X			else
X				img_gam = 1.0 / img_gam;	/* convert to display gamma */
X			}
X		else if ( (v = rle_getcom( "display_gamma", &sv_globals )) != NULL )
X			{
X	   		img_gam = atof( v );
X		    /* Protect */
X		    if ( img_gam == 0.0 )
X			img_gam = 1.0;
X			}
X		}
X
X	x_len = sv_globals.sv_xmax - sv_globals.sv_xmin + 1;
X	y_len = sv_globals.sv_ymax - sv_globals.sv_ymin + 1;
X
X	x_min = sv_globals.sv_xmin;
X	y_min = sv_globals.sv_ymin;
X
X	/* fix this so that we don't waste space */
X	sv_globals.sv_xmax -= sv_globals.sv_xmin;
X	sv_globals.sv_xmin = 0;
X
X	/* turn off the alpha channel (don't waste time and space)*/
X	sv_globals.sv_alpha = 0;
X	SV_CLR_BIT(sv_globals,SV_ALPHA);
X
X	/* for now, force background clear */
X	if(sv_globals.sv_background ==1)	/* danger setting */
X		{
X		debug("Forcing clear of background\n");
X		sv_globals.sv_background = 2;
X		if(sv_globals.sv_bg_color==0)	/* if none allocated */
X			sv_globals.sv_bg_color = background;	/* use this one */
X		}
X
X	/* now figure out the picture type */
X	switch(sv_globals.sv_ncolors)
X		{
X		case 0:
X			perror("rleLoad: no colour channels to display");
X			zclose(rlefile);
X			return(NULL);
X		case 1:
X			switch(sv_globals.sv_ncmap)
X				{
X				case 0:
X					ptype = BW_NM;	/* black and white, no map */
X					break;
X				case 1:
X					ptype = BW_M;	/* black and white with a map */
X					break;
X				case 3:
X					ptype = SC_M;	/* single channel encoded colour with decoding map */
X					break;
X				default:
X					zclose(rlefile);
X					perror("rleLoad: Illegal number of maps for one colour channel");
X					return(NULL);
X				}
X			break;
X		case 3:
X			switch(sv_globals.sv_ncmap)
X				{
X				case 0:
X					ptype = C_NM;	/* colour, no map */
X					break;
X				case 3:
X					ptype = C_M;	/* colour with maps */
X					break;
X				default:
X					perror("rleLoad: Illegal number of maps for colour picture");
X					zclose(rlefile);
X					return(NULL);
X				}
X			break;
X		default:
X			perror("rleLoad: Illegal number of colour channels");
X			zclose(rlefile);
X			return(NULL);
X			break;
X		}
X
X	if(verbose)
X		{
X		printf("rleLoad: %s is a %dx%d,",name,x_len,y_len);
X		switch(ptype)
X			{
X			case BW_NM:
X				printf(" 8 bit grey scale image with no map"); 
X				break;
X			case BW_M:
X				printf(" 8 bit grey scale image with map"); 
X				break;
X			case SC_M:
X				printf(" 8 bit colour image with colour map");
X				break;
X			case C_NM:
X				printf(" 24 bit colour image with no map (will dither to 8 bits)");
X				break;
X			case C_M:
X				printf(" 24 bit colour image with colour map (will dither to 8 bits)");
X				break;
X			}
X		printf(", and has an image gama of %4.2f\n",img_gam);
X		}
X
X	if(ptype==SC_M)
X		{	/* don't mess with the image, but change their colour map a bit if needed */
X		disp_gam /= img_gam;	/* amount to change their map */
X		img_gam = 1.0;		/*  not to the image coming in */
X		}
X
X	/* get hold of the colour maps, and set to undo their images gamma */
X	fmaps = buildmap(&sv_globals,sv_globals.sv_ncolors,img_gam);
X
X	/* now we had better sort out the picture data */
X	debug("done colour map\n");
X
X	/* rle stufff */
X	/* Get space for a full colour scan line */
X	scan = (unsigned char **) lmalloc( (sv_globals.sv_ncolors +
X				       sv_globals.sv_alpha) *
X				      sizeof( unsigned char * ) );
X	for ( i = 0; i < sv_globals.sv_ncolors + sv_globals.sv_alpha; i++ )
X	    scan[i] = (unsigned char *)lmalloc(x_len);
X	if ( sv_globals.sv_alpha )
X	    scan++;
X	debug("got space for get_row\n");
X
X	depth = 8;		/* We always supply 8bit images */
X	image = newRGBImage(x_len,y_len,depth);
X	image->title = dupString(name);
X	debug("got image structure\n");
X
X	buf = image->data;
X
X	/* If we are going to dither - then create the dither matrix. */
X	if(!bwflag && ptype!=SC_M && ptype != BW_NM && ptype != BW_M)
X		{
X		dith_np2 = 1;		/* allow non-power of 2 dither map size */
X		dithermap( 6, disp_gam, colmap, divN, modN, magic );
X		}
X
X	debug("About to read image in\n");
X	bufp = buf + (y_len-1) * x_len;
X	for(j=y_len;j>0;j--,bufp -= x_len)
X		{
X		rle_getrow(&sv_globals,scan);
X		switch(ptype)
X			{
X			case SC_M:
X				memcpy(bufp,&scan[0][0],x_len);
X				break;
X			case BW_NM:
X			case BW_M:
X				bw_m_line(bufp,x_len);
X				break;
X			case C_NM:
X			case C_M:
X				c_m_line(bufp,x_len,j);
X				break;
X			}
X		}
X	debug("Image Read in\n");
X
X	/* Deal with colour maps */
X	/* set up our gamma correction */
X	make_gamma(disp_gam,gammamap);	/* we'll need it */
X
X	debug("Creating color map\n");
X	/* now load an appropriate colour map */
X	if(!bwflag && ptype==SC_M)
X		{
X		/* use their maps  & correct their gamma */
X		ncol = 1<<sv_globals.sv_cmaplen;	/* number of entries */
X		for(i=0;i<ncol;i++)
X			{
X			*(image->rgb.red + i) = gammamap[fmaps[0][i]]<<8;
X			*(image->rgb.green + i) = gammamap[fmaps[1][i]]<<8;
X			*(image->rgb.blue + i) = gammamap[fmaps[2][i]]<<8;
X			}
X		}
X	else if(bwflag || ptype == BW_NM || ptype == BW_M)
X		{
X		/* load a black and white map (gamma corrected for this display)*/
X		ncol = 256;			/* don't know whats been used */
X		for(i=0;i<ncol;i++)
X			{
X			*(image->rgb.red + i) = 
X			*(image->rgb.green + i) = 
X			*(image->rgb.blue + i) = gammamap[i]<<8;
X			}
X		}
X	else
X		{
X		/* must be colour, so use dither map (gamma corrected for this display)*/
X		ncol = 6*6*6;
X		/* Dither map has already been created above */
X		for(i = 0; i < ncol; i++)
X			{
X			*(image->rgb.red + i) = colmap[i][0]<<8;
X			*(image->rgb.green + i) = colmap[i][1]<<8;
X			*(image->rgb.blue + i) = colmap[i][2]<<8;
X			}
X		}
X	image->rgb.used = ncol;
X
X	zclose(rlefile);
X	debug("finished\n");
X	return(image);
X	}
X
X#define DMAP(v,x,y)	(modN[v]>magic[x][y] ? divN[v] + 1 : divN[v])
X
X		/* run the black and white through its map */
X		bw_m_line(dp,number)
X		int number;
X		register unsigned char *dp;
X			{
X			register unsigned char *r;
X			register int i;
X
X			for(i=number,r= &scan[0][0];i>0;i--,r++,dp++)
X				{
X				*dp = fmaps[0][*r];
X				}
X			}
X
X		/* convert a colour line with map to 8 bits per pixel */
X		c_m_line(dp,number,line)
X		int number,line;
X		register unsigned char *dp;
X			{
X			register unsigned char *r, *g, *b;
X			register int i, col, row;
X
X			if(!bwflag)
X				{		
X				for ( row = line % dith_size, col = x_min % dith_size, i = number, r = &scan[0][0]
X				,g= &scan[1][0], b= &scan[2][0];
X				i > 0; i--, r++, g++, b++, dp++, col = ((col + 1) % dith_size) )
X					{
X					*dp = DMAP(fmaps[0][*r], col, row) +
X						  DMAP(fmaps[1][*g], col, row) * 6 +
X						  DMAP(fmaps[2][*b], col, row) * 36;
X					}
X				}
X			else
X				{
X				int red,green,blue;
X				for (i = number, r= &scan[0][0], g= &scan[1][0]
X				,b= &scan[2][0]; i>0;i--,r++,g++,b++,dp++)
X					{
X					red = fmaps[0][*r];green=fmaps[1][*g];blue = fmaps[2][*b];
X					*dp = 0.35* red + 0.55* green + 0.1* blue;
X					}
X				}
X			}
X
END_OF_FILE
if test 11071 -ne `wc -c <'rle.c'`; then
    echo shar: \"'rle.c'\" unpacked with wrong size!
fi
# end of 'rle.c'
fi
if test -f 'send.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'send.c'\"
else
echo shar: Extracting \"'send.c'\" \(6580 characters\)
sed "s/^X//" >'send.c' <<'END_OF_FILE'
X/* send.c:
X *
X * send an Image to an X pixmap
X *
X * jim frost 10.02.89
X *
X * Copyright 1989, 1990 Jim Frost.  See included file "copyright.h" for
X * complete copyright information.
X */
X
X#include "copyright.h"
X#include "xloadimage.h"
X
Xunsigned int sendImageToX(disp, scrn, visual, image, pixmap, cmap, verbose)
X     Display      *disp;
X     int           scrn;
X     Visual       *visual;
X     Image        *image;
X     Pixmap       *pixmap;
X     Colormap     *cmap;
X     unsigned int  verbose;
X{ Pixel        *index;
X  unsigned int  a, b, newmap, x, y, linelen, ddepth, dpixlen;
X  unsigned long plane;
X  byte         *pixptr, *destline, *destptr, *bitplane, destmask;
X  byte	       *modimageptr;
X  XColor        xcolor;
X  XGCValues     gcv;
X  GC            gc;
X  XImage       *ximage;
X
X  goodImage(image, "sendImageToX");
X
X  switch(visual->class) {
X  case PseudoColor:
X  case GrayScale:
X  case StaticColor:
X  case StaticGray:
X    break;
X  default:
X    printf("sendImageToX: unsupported display visual\n");
X    exit(1);
X  }
X
X  index= (Pixel *)lmalloc(sizeof(Pixel) * image->rgb.used);
X  xcolor.flags= DoRed | DoGreen | DoBlue;
X
X  /* get the colormap to use
X   */
X
X  if (visual == DefaultVisual(disp, scrn)) {
X    *cmap= DefaultColormap(disp, scrn);
X    newmap= 0;
X
X    /* allocate colors shareable (if we can)
X     */
X
X    for (a= 0; a < image->rgb.used; a++) {
X      xcolor.red= *(image->rgb.red + a);
X      xcolor.green= *(image->rgb.green + a);
X      xcolor.blue= *(image->rgb.blue + a);
X      if (! XAllocColor(disp, *cmap, &xcolor))
X	if ((visual->class == StaticColor) || (visual->class == StaticGray)) {
X	  printf("sendImageToX: XAllocColor failed on a static visual\n");
X	  return(0);
X	}
X	else {
X
X	  /* we can't allocate the colors shareable so free all the colors
X	   * we had allocated and create a private colormap
X	   */
X
X	  for (b= 0; b < a; b++)
X	    XFreeColors(disp, *cmap, index + b, 1, 0);
X	  *cmap= XCreateColormap(disp, RootWindow(disp, scrn), visual,
X				 AllocNone);
X	  newmap= 1;
X	  break;
X	}
X      *(index + a)= xcolor.pixel;
X    }
X  }
X  else {
X    if ((visual->class == PseudoColor) || (visual->class == GrayScale)) {
X      *cmap= XCreateColormap(disp, RootWindow(disp, scrn), visual, AllocNone);
X    }
X    else
X      *cmap= XCreateColormap(disp, RootWindow(disp, scrn), visual, AllocAll);
X    newmap= 1;
X  }
X
X  if (newmap) {
X    for (a= 0; a < image->rgb.used; a++) /* count entries we got */
X      if (! XAllocColorCells(disp, *cmap, False, NULL, 0, index + a, 1))
X	break;
X
X    if (a < image->rgb.used)     /* can't get enough colors, so reduce */
X      reduce(image, a, verbose); /* the colormap to fit what we have */
X
X    for (b= 0; b < a; b++) {
X      xcolor.pixel= *(index + b);
X      xcolor.red= *(image->rgb.red + b);
X      xcolor.green= *(image->rgb.green + b);
X      xcolor.blue= *(image->rgb.blue + b);
X      XStoreColor(disp, *cmap, &xcolor);
X    }
X  }
X
X  ddepth= DefaultDepth(disp, scrn);
X  *pixmap= XCreatePixmap(disp, RootWindow(disp, scrn), image->width,
X			 image->height, ddepth);
X
X  /* blast the image across
X   */
X
X  switch (image->type) {
X  case IBITMAP:
X    gcv.function= GXcopy;
X    gcv.foreground= *(index + 1);
X    gcv.background= *index;
X    gc= XCreateGC(disp, *pixmap, GCFunction | GCForeground | GCBackground,
X		  &gcv);
X    ximage= XCreateImage(disp, visual, image->depth, XYBitmap, 0, image->data,
X			 image->width, image->height, 8, 0);
X    ximage->bitmap_bit_order= MSBFirst;
X    ximage->byte_order= MSBFirst;
X    XPutImage(disp, *pixmap, gc, ximage, 0, 0, 0, 0,
X	      image->width, image->height);
X    XFreeGC(disp, gc);
X    break;
X
X  case IRGB:
X
X    /* modify image data to match colormap and pack pixels if necessary
X     */
X
X    if (verbose) {
X      printf("  Building XImage...");
X      fflush(stdout);
X    }
X    pixptr= image->data;
X    modimageptr = image->data;
X    dpixlen = ddepth / 8;
X    if(image->pixlen != dpixlen) {  /* Need to convert depth */
X	modimageptr = (byte *)lmalloc(image->height * image->width * dpixlen);
X    }
X    destptr = modimageptr;
X	
X    for (y= 0; y < image->height; y++)
X      for (x= 0; x < image->width; x++) {
X	valToMem(*(index + memToVal(pixptr, image->pixlen)),
X		 destptr, dpixlen);
X	pixptr += image->pixlen;
X        destptr += dpixlen;
X      }
X
X    if (verbose)
X      printf("done\n");
X
X    /* if the destination depth is not a multiple of 8, then we send each
X     * plane as a bitmap because otherwise we would have to pack the pixel
X     * data and the XImage format is pretty vague about how that should
X     * be done.  this is not as fast as it would be if it were packed but
X     * it should be a lot more portable and only slightly slower.
X     */
X
X    if (ddepth % 8) {
X#ifndef SERVER_HAS_BROKEN_PLANEMASK /* see README */
X      gcv.function= GXcopy;
X#else
X      gcv.function= GXor;
X#endif
X      gcv.background= 0;
X      gc= XCreateGC(disp, *pixmap, GCFunction | GCBackground, &gcv);
X      linelen= (image->width / 8) + (image->width % 8 ? 1 : 0);
X      bitplane= lmalloc(image->height * linelen);
X      ximage= XCreateImage(disp, visual, 1, XYBitmap, 0, bitplane,
X			   image->width, image->height, 8, 0);
X      ximage->bitmap_bit_order= MSBFirst;
X      ximage->byte_order= MSBFirst;
X
X      for (plane= 1 << (ddepth - 1); plane; plane >>= 1) {
X	pixptr= image->data;
X	destline= bitplane;
X	for (y= 0; y < image->height; y++) {
X	  destmask= 0x80;
X	  destptr= destline;
X	  for (x= 0; x < image->width; x++) {
X	    if (*pixptr & plane)
X	      *destptr |= destmask;
X	    else
X	      *destptr &= ~destmask;
X	    if (!(destmask >>= 1)) {
X	      destmask= 0x80;
X	      destptr++;
X	    }
X	    pixptr += image->pixlen;
X	  }
X	  destline += linelen;
X	}
X	XSetForeground(disp, gc, plane);
X	XSetPlaneMask(disp, gc, plane);
X	XPutImage(disp, *pixmap, gc, ximage, 0, 0, 0, 0,
X		  image->width, image->height);
X      }
X
X      ximage->data= NULL;
X      XDestroyImage(ximage);
X      lfree(bitplane);
X      break;
X    }
X
X    /* send image across in one whack
X     */
X
X    gcv.function= GXcopy;
X    gc= XCreateGC(disp, *pixmap, GCFunction, &gcv);
X    ximage= XCreateImage(disp, visual, ddepth, ZPixmap, 0, modimageptr,
X			 image->width, image->height, 8, 0);
X    ximage->byte_order= MSBFirst; /* trust me, i know what i'm talking about */
X
X    XPutImage(disp, *pixmap, gc, ximage, 0, 0,
X	      0, 0, image->width, image->height);
X    if(image->data == modimageptr)
X        ximage->data= NULL;
X    XDestroyImage(ximage); /* waste not want not */
X    XFreeGC(disp, gc);
X    break;
X
X  default:
X    printf("sendImageToX: bad image type\n");
X    return(0);
X  }
X  lfree((byte *)index);
X  return(1);
X}
END_OF_FILE
if test 6580 -ne `wc -c <'send.c'`; then
    echo shar: \"'send.c'\" unpacked with wrong size!
fi
# end of 'send.c'
fi
if test -f 'smooth.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'smooth.c'\"
else
echo shar: Extracting \"'smooth.c'\" \(6012 characters\)
sed "s/^X//" >'smooth.c' <<'END_OF_FILE'
X/* smooth.c:
X *
X * this performs a smoothing convolution using a 3x3 area.
X *
X * jim frost 09.20.90
X *
X * Copyright 1989 Jim Frost.  See included file "copyright.h" for complete
X * copyright information.
X */
X
X#include "copyright.h"
X#include "image.h"
X
X/* this stuff is all used to pick the best possible color out of the
X * image's colormap.  it creates a table sorted by the sum of the rgb
X * values.  we then do a binary search to find the colors which are
X * closest to our sum.  we then search those colors to find the best
X * possible color.  this will have a complexity between log n base 2 and
X * n depending on the distribution of colormap sums.  usually it's pretty
X * good.
X */
X
Xextern unsigned int squareInit;
Xextern unsigned long squareTable[];
X
Xstruct colorarray {
X  Pixel         pixel; /* pixel value */
X  unsigned long sum;   /* sum of rgb values */
X};
X
Xstatic int colorPredicate(c1, c2)
X     struct colorarray *c1, *c2;
X{
X  return(c1->sum < c2->sum ? -1 : 1);
X}
X
Xstatic struct colorarray *createColorArray(rgb)
X     RGBMap *rgb;
X{ struct colorarray *carray;
X  Pixel a;
X
X  carray= (struct colorarray *)lmalloc(rgb->used * sizeof(struct colorarray));
X  for (a= 0; a < rgb->used; a++) {
X    carray[a].pixel= a;
X    carray[a].sum= rgb->red[a] + rgb->green[a] + rgb->blue[a];
X  }
X  qsort(carray, rgb->used, sizeof(struct colorarray), colorPredicate);
X  return(carray);
X}
X
X#define DIST(A, B) ((A) < (B) ? (B) - (A) : (A) - (B))
X
Xstatic Pixel bestColorByRGB(rgb, carray, red, green, blue)
X     RGBMap *rgb;
X     struct colorarray *carray;
X     unsigned long red, green, blue;
X{ unsigned long bdist, qdist, sum, sum2;
X  Pixel pick, bpick, qpick;
X  unsigned int areasize;
X
X  sum= red + green + blue;
X
X  /* binary search to find colors which are close to us
X   */
X
X  pick= areasize= rgb->used / 2;
X  while ((pick > 0) && (pick < rgb->used - 1)) {
X    areasize= (areasize + 1) >> 1;
X    pick += (carray[pick].sum > sum ? -areasize : areasize);
X    if ((carray[pick].sum <= sum) && (sum < carray[pick + 1].sum))
X      break;
X  }
X
X  /* look at colors that are a little darker than we are
X   */
X
X  bdist= 
X    squareTable[DIST(rgb->red[carray[pick].pixel], red) >> 1] +
X    squareTable[DIST(rgb->green[carray[pick].pixel], green) >> 1] +
X    squareTable[DIST(rgb->blue[carray[pick].pixel], blue) >> 1];
X  bpick= pick;
X
X  if (pick > 0) {
X    qpick= pick - 1;
X    sum2= carray[qpick].sum;
X    while (carray[qpick].sum == sum2) {
X      qdist= 
X        squareTable[DIST(rgb->red[carray[qpick].pixel], red) >> 1] +
X        squareTable[DIST(rgb->green[carray[qpick].pixel], green) >> 1] +
X        squareTable[DIST(rgb->blue[carray[qpick].pixel], blue) >> 1];
X      if (qdist < bdist) {
X	bpick= qpick;
X	bdist= qdist;
X	if (!bdist)
X	  return(carray[bpick].pixel);
X      }
X      if (qpick == 0)
X	break;
X      qpick--;
X    }
X  }
X
X  if (pick == rgb->used - 1) /* nothing following */
X    return(carray[bpick].pixel);
X
X  /* look at colors which are a little lighter than we are
X   */
X
X  qpick= pick + 1;
X  sum2= carray[qpick].sum;
X  do {
X    qdist= 
X      squareTable[DIST(rgb->red[carray[qpick].pixel], red) >> 1] +
X      squareTable[DIST(rgb->green[carray[qpick].pixel], green) >> 1] +
X      squareTable[DIST(rgb->blue[carray[qpick].pixel], blue) >> 1];
X    if (qdist < bdist) {
X      bpick= qpick;
X      bdist= qdist;
X      if (!bdist)
X	return(carray[bpick].pixel);
X    }
X    qpick++;
X  } while ((qpick < rgb->used) && (carray[qpick].sum == sum2));
X
X  return(carray[bpick].pixel);
X}
X
Xstatic Image *doSmooth(image)
X     Image *image;
X{ Image *new;
X  int    x, y, x1, y1, linelen, reductions;
X  int    xindex[3];
X  byte  *yindex[3];
X  byte  *srcptr, *destptr;
X  Pixel  pixval;
X  unsigned long avgred, avggreen, avgblue;
X  struct colorarray *carray;
X
X  /* create new image and copy colormap
X   */
X
X  new= newRGBImage(image->width, image->height, image->depth);
X  new->title= (char *)lmalloc(strlen(image->title) + 12);
X  sprintf(new->title, "%s (smoothed)", image->title);
X  bcopy(image->rgb.red, new->rgb.red, image->rgb.used * sizeof(Intensity));
X  bcopy(image->rgb.green, new->rgb.green, image->rgb.used * sizeof(Intensity));
X  bcopy(image->rgb.blue, new->rgb.blue, image->rgb.used * sizeof(Intensity));
X  new->rgb.used= image->rgb.used;
X
X  carray= createColorArray(&(new->rgb));
X
X  /* run through image and take a guess as to what the color should
X   * actually be.
X   */
X
X  for (y= 0; y < image->height; y++) {
X    linelen= image->pixlen * image->width;
X    destptr= new->data + (y * linelen);
X    yindex[1]= image->data + (y * linelen);
X    yindex[0]= yindex[1] - (y > 0 ? linelen : 0);
X    yindex[2]= yindex[1] + (y < image->height - 1 ? linelen : 0);
X    for (x= 0; x < image->width; x++) {
X      avgred= avggreen= avgblue= 0;
X      xindex[1]= x * image->pixlen;
X      xindex[0]= xindex[1] - (x > 0 ? image->pixlen : 0);
X      xindex[2]= xindex[1] + (x < image->width - 1 ? image->pixlen : 0);
X      for (y1= 0; y1 < 3; y1++) {
X	for (x1= 0; x1 < 3; x1++) {
X	  pixval= memToVal(yindex[y1] + xindex[x1], image->pixlen);
X	  avgred += *(image->rgb.red + pixval);
X	  avggreen += *(image->rgb.green + pixval);
X	  avgblue += *(image->rgb.blue + pixval);
X	}
X      }
X
X      /* pick the pixel that's closest to this average and put in image
X       */
X
X      avgred= ((avgred + 8) / 9);
X      avggreen= ((avggreen + 8) / 9);
X      avgblue= ((avgblue + 8) / 9);
X      pixval= bestColorByRGB(&(new->rgb), carray, avgred, avggreen, avgblue);
X      valToMem(pixval, destptr, new->pixlen);
X      destptr += new->pixlen;
X    }
X  }
X
X  lfree(carray);
X  return(new);
X}
X
XImage *smooth(image, iterations, verbose)
X     Image *image;
X     int    verbose;
X{ int a;
X  Image *new;
X
X  if (!squareInit)
X    initSquareTable();
X
X  if (!RGBP(image)) /* no effect unless color image (yet) */
X    return(image);
X
X  if (verbose) {
X    printf("  Smoothing...");
X    fflush(stdout);
X  }
X
X  for (a= 0; a < iterations; a++) {
X    new= doSmooth(image);
X    freeImage(image);
X    image= new;
X  }
X
X  if (verbose)
X    printf("done\n");
X
X  return(image);
X}
END_OF_FILE
if test 6012 -ne `wc -c <'smooth.c'`; then
    echo shar: \"'smooth.c'\" unpacked with wrong size!
fi
# end of 'smooth.c'
fi
if test -f 'sunraster.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sunraster.c'\"
else
echo shar: Extracting \"'sunraster.c'\" \(5487 characters\)
sed "s/^X//" >'sunraster.c' <<'END_OF_FILE'
X/* sunraster.c:
X *
X * sun rasterfile image type
X *
X * jim frost 09.27.89
X *
X * Copyright 1989 Jim Frost.  See included file "copyright.h" for complete
X * copyright information.
X */
X
X#include "copyright.h"
X#include "image.h"
X#include "sunraster.h"
X
Xstatic void babble(name, header)
X     char           *name;
X     struct rheader *header;
X{
X  printf("%s is a", name);
X  switch (memToVal(header->type, 4)) {
X  case ROLD:
X    printf("n old-style");
X    break;
X  case RSTANDARD:
X    printf(" standard");
X    break;
X  case RRLENCODED:
X    printf(" run-length encoded");
X    break;
X  default:
X    printf(" unknown-type");
X  }
X  printf(" %dx%d ", memToVal(header->width, 4), memToVal(header->height, 4));
X  if (memToVal(header->depth, 4) > 1)
X    printf("%d plane %s",
X	       memToVal(header->depth, 4),
X	       (memToVal(header->maplen, 4) > 0 ? "color" : "greyscale")
X	       );
X  else
X    printf("monochrome");
X  printf(" Sun rasterfile\n");
X}
X
Xint sunRasterIdent(fullname, name)
X     char *fullname, *name;
X{ ZFILE          *zf;
X  struct rheader  header;
X  int             r;
X
X  if (! (zf= zopen(fullname))) {
X    perror("sunRasterIdent");
X    return(0);
X  }
X  switch (zread(zf, &header, sizeof(struct rheader))) {
X  case -1:
X    perror("sunRasterIdent");
X    r= 0;
X    break;
X
X  case sizeof(struct rheader):
X    if (memToVal(header.magic, 4) != RMAGICNUMBER) {
X      r= 0;
X      break;
X    }
X    babble(name, &header);
X    r= 1;
X    break;
X
X  default:
X    r= 0;
X    break;
X  }
X  zclose(zf);
X  return(r);
X}
X
X/* read either rl-encoded or normal image data
X */
X
Xstatic void sunread(zf, buf, len, enc)
X     ZFILE        *zf;
X     byte         *buf;
X     unsigned int  len;
X     unsigned int  enc;  /* true if encoded file */
X{ static byte repchar, remaining= 0;
X
X  /* rl-encoded read
X   */
X
X  if (enc) {
X    while (len--)
X      if (remaining) {
X	remaining--;
X	*(buf++)= repchar;
X      }
X      else {
X	if (zread(zf, &repchar, 1) != 1) {
X	  printf("sunRasterLoad: Bad read on image data\n");
X	  exit(1);
X	}
X	if (repchar == RESC) {
X	  if (zread(zf, &remaining, 1) != 1) {
X	    printf("sunRasterLoad: Bad read on image data\n");
X	    exit(1);
X	  }
X	  if (remaining == 0)
X	    *(buf++)= RESC;
X	  else {
X	    if (zread(zf, &repchar, 1) != 1) {
X	      printf("sunRasterLoad: Bad read on image data\n");
X	      exit(1);
X	    }
X	    *(buf++)= repchar;
X	  }
X	}
X	else
X	  *(buf++)= repchar;
X      }
X  }
X
X  /* normal read
X   */
X
X  else {
X    if (zread(zf, buf, len) < len) {
X      printf("sunRasterLoad: Bad read on image data\n");
X      exit(1);
X    }
X  }
X}
X
XImage *sunRasterLoad(fullname, name, verbose)
X     char         *fullname, *name;
X     unsigned int  verbose;
X{ ZFILE          *zf;
X  struct rheader  header;
X  unsigned int    mapsize;
X  byte           *map;
X  byte           *mapred, *mapgreen, *mapblue;
X  unsigned int    depth;
X  unsigned int    linelen;   /* length of raster line in bytes */
X  unsigned int    fill;      /* # of fill bytes per raster line */
X  unsigned int    enc;
X  byte            fillchar;
X  Image          *image;
X  byte           *lineptr;
X  unsigned int    y;
X
X  if (! (zf= zopen(fullname))) {
X    perror("sunRasterLoad");
X    return(NULL);
X  }
X  switch (zread(zf, &header, sizeof(struct rheader))) {
X  case -1:
X    perror("sunRasterLoad");
X    zclose(zf);
X    exit(1);
X
X  case sizeof(struct rheader):
X    if (memToVal(header.magic, 4) != RMAGICNUMBER) {
X      zclose(zf);
X      return(NULL);
X    }
X    if (verbose)
X      babble(name, &header);
X    break;
X
X  default:
X    zclose(zf);
X    return(NULL);
X  }
X
X  /* get an image to put the data in
X   */
X
X  depth= memToVal(header.depth, 4);
X  if (depth == 1)
X    image= newBitImage(memToVal(header.width, 4),
X		       memToVal(header.height, 4));
X  else
X    image= newRGBImage(memToVal(header.width, 4),
X		       memToVal(header.height, 4),
X		       memToVal(header.depth, 4));
X
X  /* set up the colormap
X   */
X
X  if (depth == 1)
X    linelen= (image->width / 8) + (image->width % 8 ? 1 : 0);
X  else
X    linelen= image->width * image->pixlen;
X  fill= (linelen % 2 ? 1 : 0);
X  /*
X   *  Handle color...
X   */
X  if (mapsize= memToVal(header.maplen, 4)) {
X    map= lmalloc(mapsize);
X    if (zread(zf, map, mapsize) < mapsize) {
X      printf("sunRasterLoad: Bad read on colormap\n");
X      exit(1);
X    }
X    mapsize /= 3;
X    mapred= map;
X    mapgreen= mapred + mapsize;
X    mapblue= mapgreen + mapsize;
X    for (y= 0; y < mapsize; y++) {
X      *(image->rgb.red + y)= (*(mapred++) << 8);
X      *(image->rgb.green + y)= (*(mapgreen++) << 8);
X      *(image->rgb.blue + y)= (*(mapblue++) << 8);
X    }
X    lfree(map);
X    image->rgb.used= mapsize;
X  }
X
X  /*
X   *  Handle 8-bit greyscale via a simple ramp function...
X   */
X  else if (depth > 1) {
X    mapsize = 256*3;
X    map= lmalloc(mapsize);
X    for (y = 0; y < 256; y += 1) {
X      map[y] = map[256+y] = map[2*256+y] = y;
X    }
X    mapsize /= 3;
X    mapred= map;
X    mapgreen= mapred + mapsize;
X    mapblue= mapgreen + mapsize;
X    for (y= 0; y < mapsize; y++) {
X      *(image->rgb.red + y)= (*(mapred++) << 8);
X      *(image->rgb.green + y)= (*(mapgreen++) << 8);
X      *(image->rgb.blue + y)= (*(mapblue++) << 8);
X    }
X    lfree(map);
X    image->rgb.used= mapsize;
X  }
X    
X
X  enc= (memToVal(header.type, 4) == RRLENCODED);
X  lineptr= image->data;
X  for (y= 0; y < image->height; y++) {
X    sunread(zf, lineptr, linelen, enc);
X    lineptr += linelen;
X    if (fill)
X      sunread(zf, &fillchar, fill, enc);
X  }
X  zclose(zf);
X  image->title= dupString(name);
X  return(image);
X}
END_OF_FILE
if test 5487 -ne `wc -c <'sunraster.c'`; then
    echo shar: \"'sunraster.c'\" unpacked with wrong size!
fi
# end of 'sunraster.c'
fi
if test -f 'xbitmap.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xbitmap.c'\"
else
echo shar: Extracting \"'xbitmap.c'\" \(5417 characters\)
sed "s/^X//" >'xbitmap.c' <<'END_OF_FILE'
X/* xbitmap.c:
X *
X * at one time this was XRdBitF.c.  it bears very little resemblence to it
X * now.  that was ugly code.  this is cleaner, faster, and more reliable
X * in most cases.
X *
X * jim frost 10.06.89
X *
X * Copyright, 1987, Massachusetts Institute of Technology
X *
X * Copyright 1989 Jim Frost.  See included file "copyright.h" for complete
X * copyright information.
X */
X
X#include "mit.cpyrght"
X#include "copyright.h"
X#include "image.h"
X#include <ctype.h>
X
X#ifdef SYSV
X#include <string.h>
X#define rindex strrchr
X#else
Xchar *rindex();
X#endif
X
X#define MAX_SIZE 255
X
Xstatic short        HexTable[256];  /* conversion value */
Xstatic unsigned int Initialized= 0; /* easier to fill in at run time */
X
X#define b0000 0 /* things make more sense if you see them by bit */
X#define b0001 1
X#define b0010 2
X#define b0011 3
X#define b0100 4
X#define b0101 5
X#define b0110 6
X#define b0111 7
X#define b1000 8
X#define b1001 9
X#define b1010 10
X#define b1011 11
X#define b1100 12
X#define b1101 13
X#define b1110 14
X#define b1111 15
X
X#define HEXSTART -1
X#define HEXDELIM -2
X#define HEXBAD   -3
X
X/* build a hex digit value table with the bits inverted
X */
X
Xstatic void initHexTable()
X{ int a;
X
X  for (a= 0; a < 256; a++)
X    HexTable[a]= HEXBAD;
X
X  HexTable['0']= b0000;
X  HexTable['1']= b1000;
X  HexTable['2']= b0100;
X  HexTable['3']= b1100;
X  HexTable['4']= b0010;
X  HexTable['5']= b1010;
X  HexTable['6']= b0110;
X  HexTable['7']= b1110;
X  HexTable['8']= b0001;
X  HexTable['9']= b1001;
X  HexTable['A']= b0101; HexTable['a']= HexTable['A'];
X  HexTable['B']= b1101; HexTable['b']= HexTable['B'];
X  HexTable['C']= b0011; HexTable['c']= HexTable['C'];
X  HexTable['D']= b1011; HexTable['d']= HexTable['D'];
X  HexTable['E']= b0111; HexTable['e']= HexTable['E'];
X  HexTable['F']= b1111; HexTable['f']= HexTable['F'];
X  HexTable['x']= HEXSTART;
X  HexTable['\r']= HEXDELIM;
X  HexTable['\n']= HEXDELIM;
X  HexTable['\t']= HEXDELIM;
X  HexTable[' ']= HEXDELIM;
X  HexTable[',']= HEXDELIM;
X  HexTable['}']= HEXDELIM;
X
X  Initialized = 1;
X}
X
X/* read a hex value and return its value
X */
X
Xstatic int nextInt(zf)
X     ZFILE *zf;
X{ int c;
X  int value= 0;
X  int shift= 0;
X    
X  for (;;) {
X    c= zgetc(zf);
X    if (c == EOF)
X      return(-1);
X    else {
X      c= HexTable[c & 0xff];
X      switch(c) {
X      case HEXSTART:
X	shift= 0; /* reset shift counter */
X	break;
X      case HEXDELIM:
X	if (shift)
X	  return(value);
X	break;
X      case HEXBAD:
X	return(-1);
X      default:
X	value += (c << shift);
X	shift += 4;
X      }
X    }
X  }
X}
X
Xstatic void badFile(name)
X     char *name;
X{
X  printf("%s: bad X bitmap file\n", name);
X  exit(1);
X}
X
XImage *xbitmapLoad(fullname, name, verbose)
X     char         *fullname, *name;
X     unsigned int  verbose;
X{ ZFILE        *zf;
X  Image        *image;
X  char          line[MAX_SIZE];
X  char          name_and_type[MAX_SIZE];
X  char         *type;
X  int           value;
X  int           v10p;
X  unsigned int  linelen, dlinelen;
X  unsigned int  x, y;
X  unsigned int  w = 0, h = 0;
X  byte         *dataptr;
X
X  if (!Initialized)
X    initHexTable();
X
X  if (! (zf= zopen(fullname)))
X    return(NULL);
X
X  /* get width/height values */
X
X  while (zgets(line, MAX_SIZE, zf)) {
X    if (strlen(line) == MAX_SIZE-1) {
X      zclose(zf);
X      return(NULL);
X    }
X
X    /* width/height/hot_x/hot_y scanning
X     */
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	w= (unsigned int)value;
X      if (!strcmp("height", type))
X	h= (unsigned int)value;
X    }
X
X    /* if start of data, determine if it's X10 or X11 data and break
X     */
X
X    if (sscanf(line, "static short %s = {", name_and_type) == 1) {
X      v10p = 1;
X      break;
X    }
X    if ((sscanf(line,"static unsigned char %s = {", name_and_type) == 1) ||
X	(sscanf(line, "static char %s = {", name_and_type) == 1)) {
X      v10p = 0;
X      break;
X    }
X  }
X
X  if (!w || !h) {
X    zclose(zf);
X    return(NULL);
X  }
X  image= newBitImage(w, h);
X
X  /* get title of bitmap if any
X   */
X
X  if ((type = rindex(name_and_type, '_')) && !strcmp("bits[]", type + 1)) {
X    *type= '\0';
X    image->title= dupString(name_and_type);
X  }
X    
X  /* read bitmap data
X   */
X
X  linelen= (w / 8) + (w % 8 ? 1 : 0); /* internal line length */
X  if (v10p) {
X    dlinelen= (w / 8) + (w % 16 ? 2 : 0);
X    dataptr= image->data;
X    for (y= 0; y < h; y++) {
X      for (x= 0; x < dlinelen; x++) {
X	if ((value= nextInt(zf)) < 0) {
X	  freeImage(image);
X	  zclose(zf);
X	  return(NULL);
X	}
X	*(dataptr++)= value >> 8;
X	if (++x < linelen)
X	  *(dataptr++)= value & 0xff;
X      }
X    }
X  }
X  else {
X    dataptr= image->data;
X    for (y= 0; y < h; y++)
X      for (x= 0; x < linelen; x++) {
X	if ((value= nextInt(zf)) < 0)
X	  badFile(name);
X	*(dataptr++)= value;
X      }
X  }
X
X  if (verbose) {
X    printf("%s is a %dx%d X", name, image->width, image->height);
X    if (v10p)
X      printf("10");
X    else
X      printf("11");
X    if (image->title)
X      printf(" bitmap file titled '%s'", image->title);
X    printf("\n");
X  }
X  zclose(zf);
X  return(image);
X}
X
X/* this is the easiest way to do this.  it's not likely we'll have mondo
X * x bitmaps anyway given their size
X */
X
Xint xbitmapIdent(fullname, name)
X     char         *fullname, *name;
X{ Image *image;
X
X  if (image= xbitmapLoad(fullname, name, (unsigned int)1)) {
X    freeImage(image);
X    return(1);
X  }
X  return(0);
X}
END_OF_FILE
if test 5417 -ne `wc -c <'xbitmap.c'`; then
    echo shar: \"'xbitmap.c'\" unpacked with wrong size!
fi
# end of 'xbitmap.c'
fi
if test -f 'zio.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'zio.c'\"
else
echo shar: Extracting \"'zio.c'\" \(4983 characters\)
sed "s/^X//" >'zio.c' <<'END_OF_FILE'
X/* zio.c:
X *
X * this properly opens and reads from an image file, compressed or otherwise.
X *
X * jim frost 10.03.89
X *
X * this was hacked on 09.12.90 to cache reads and to use stdin.
X *
X * Copyright 1989 Jim Frost.  See included file "copyright.h" for complete
X * copyright information.
X */
X
X#include "copyright.h"
X#include "image.h"
X
X#define MAX_ZFILES 32
X
Xstatic ZFILE ZFileTable[MAX_ZFILES];
X
X/* read some info through the read cache
X */
X
Xstatic int doRead(zf, buf, len)
X     ZFILE *zf;
X     byte *buf;
X     int len;
X{ int bread, readlen;
X
X  /* loop through the read
X   */
X
X  for (bread= 0; bread < len; bread += readlen, zf->bufptr += readlen) {
X
X    /* read new or move to next data block if necessary
X     */
X
X    if (!zf->dataptr || (zf->bufptr == zf->dataptr->len)) {
X      if (zf->dataptr && zf->dataptr->next)
X	zf->dataptr= zf->dataptr->next;
X      else {
X	if (!zf->dataptr)
X	  zf->data= zf->dataptr= (struct cache *)lmalloc(sizeof(struct cache));
X	else {
X	  zf->dataptr->next= (struct cache *)lmalloc(sizeof(struct cache));
X	  zf->dataptr= zf->dataptr->next;
X	}
X	zf->dataptr->next= NULL;
X	zf->dataptr->len= fread(zf->dataptr->buf, 1, BUFSIZ, zf->stream);
X	if (zf->dataptr->len < 0) {
X	  perror("fread");
X	  exit(1);
X	}
X      }
X      zf->bufptr= 0;
X    }
X
X    /* calculate length we can get out of read buffer
X     */
X
X    readlen= (len - bread > zf->dataptr->len - zf->bufptr ?
X	      zf->dataptr->len - zf->bufptr : len - bread);
X    if (!readlen) /* we're at EOF */
X      return(bread);
X    bcopy(zf->dataptr->buf + zf->bufptr, buf + bread, readlen);
X  }
X  return(bread);
X}
X
X/* reset a read cache
X */
X
Xvoid zreset(filename)
X     char *filename;
X{ int a;
X  struct cache *old;
X
X  /* if NULL filename, reset the entire table
X   */
X
X  if (!filename) {
X    for (a= 0; a < MAX_ZFILES; a++)
X      if (ZFileTable[a].filename)
X	zreset(ZFileTable[a].filename);
X    return;
X  }
X
X  for (a= 0; a < MAX_ZFILES; a++)
X    if (ZFileTable[a].filename && !strcmp(filename, ZFileTable[a].filename))
X      break;
X
X  if (a == MAX_ZFILES) /* no go joe */
X    return;
X
X  if (ZFileTable[a].dataptr != ZFileTable[a].data)
X    printf("zreset: warning: ZFILE for %s was not closed properly\n",
X	   ZFileTable[a].filename);
X  while (ZFileTable[a].data) {
X    old= ZFileTable[a].data;
X    ZFileTable[a].data= ZFileTable[a].data->next;
X    free(old);
X  }
X  lfree(ZFileTable[a].filename);
X  ZFileTable[a].filename= NULL;
X  ZFileTable[a].dataptr= NULL;
X  ZFileTable[a].bufptr= 0;
X
X  switch(ZFileTable[a].type) {
X  case ZSTANDARD:
X    fclose(ZFileTable[a].stream);
X    break;
X  case ZPIPE:
X    pclose(ZFileTable[a].stream);
X    break;
X  case ZSTDIN:
X    break;
X  default:
X    printf("zreset: bad ZFILE structure\n");
X    exit(1);
X  }
X}
X
XZFILE *zopen(name)
X     char *name;
X{ int    a;
X  ZFILE *zf;
X  char   buf[BUFSIZ];
X
X  /* look for filename in open file table
X   */
X
X  for (a= 0; a < MAX_ZFILES; a++)
X    if (ZFileTable[a].filename && !strcmp(name, ZFileTable[a].filename)) {
X      if (ZFileTable[a].dataptr != ZFileTable[a].data)
X	printf("zopen: warning: file doubly opened\n");
X      ZFileTable[a].dataptr= ZFileTable[a].data;
X      ZFileTable[a].bufptr= 0;
X      return(ZFileTable + a);
X    }
X
X  /* find open ZFileTable entry
X   */
X
X  for (a= 0; (a < MAX_ZFILES) && ZFileTable[a].filename; a++)
X    /* EMPTY */
X    ;
X
X  if (a == MAX_ZFILES) {
X    printf("zopen: no more files available\n");
X    exit(1);
X  }
X  zf= ZFileTable + a;
X
X  zf->filename= dupString(name);
X  zf->dataptr= NULL;
X  zf->bufptr= 0;
X
X  /* file filename is `stdin' then use stdin
X   */
X
X  if (!strcmp(name, "stdin")) {
X    zf->type= ZSTDIN;
X    zf->stream= stdin;
X    return(zf);
X  }
X
X  /* if filename ends in `.Z' then open pipe to uncompress.  if your
X   * system doesn't have uncompress you can define NO_UNCOMPRESS and
X   * it just won't check for this.
X   */
X
X#ifndef NO_UNCOMPRESS
X  if ((strlen(name) > 2) && !strcmp(".Z", name + (strlen(name) - 2))) {
X    zf->type= ZPIPE;
X    sprintf(buf, "uncompress -c %s", name);
X    if (! (zf->stream= popen(buf, "r"))) {
X      return(NULL);
X    }
X    return(zf);
X  }
X#endif
X
X  /* default to normal stream
X   */
X
X  zf->type= ZSTANDARD;
X  if (! (zf->stream= fopen(name, "r"))) {
X    return(NULL);
X  }
X  return(zf);
X}
X
Xint zread(zf, buf, len)
X     ZFILE        *zf;
X     byte         *buf;
X     unsigned int  len;
X{
X  return(doRead(zf, buf, len));
X}
X
Xint zgetc(zf)
X     ZFILE *zf;
X{ unsigned char c;
X
X  if (doRead(zf, &c, 1) > 0)
X    return(c);
X  else
X    return(EOF);
X}
X
Xchar *zgets(buf, size, zf)
X     byte         *buf;
X     unsigned int  size;
X     ZFILE        *zf;
X{ int p= 0;
X
X  while (doRead(zf, buf + p, 1) > 0) {
X    if (p == size)
X      return((char *)buf);
X    if (*(buf + p) == '\n') {
X      *(buf + p + 1)= '\0';
X      return((char *)buf);
X    }
X    p++;
X  }
X  return(NULL);
X}
X
X/* reset cache pointers in a ZFILE.  nothing is actually reset until a
X * zreset() is called with the filename.
X */
X
Xvoid zclose(zf)
X     ZFILE *zf;
X{
X  zf->dataptr= zf->data;
X  zf->bufptr= 0;
X}
END_OF_FILE
if test 4983 -ne `wc -c <'zio.c'`; then
    echo shar: \"'zio.c'\" unpacked with wrong size!
fi
# end of 'zio.c'
fi
echo shar: End of archive 6 \(of 9\).
cp /dev/null ark6isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 9 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

dan
----------------------------------------------------
O'Reilly && Associates   argv@sun.com / argv@ora.com
Opinions expressed reflect those of the author only.