/* @(#)io.c 1.8 89/12/11 * * File handling routines used by the popi program. * * Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs. * This version is based on the code in his Prentice Hall book, * "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7, * which is copyright (c) 1988 by Bell Telephone Laboratories, Inc. * * Permission is given to distribute these extensions, as long as these * introductory messages are not removed, and no monies are exchanged. * * No responsibility is taken for any errors or inaccuracies inherent * either to the comments or the code of this program, but if reported * (see README file) then an attempt will be made to fix them. */ #include #include #include #include "popi.h" #if unix || AMIGA #define RMODE "r" #define WMODE "w" #else /* ! (unix || AMIGA) */ #define RMODE "rb" #define WMODE "wb" #endif /* unix || AMIGA */ int nsrc = 2; static int IsPopen = 0; pixel_t ** ImgAlloc() { int y; pixel_t **p; noerr = 1; if ((p = (pixel_t **) LINT_CAST(Emalloc((unsigned)Xsize * sizeof(pixel_t *)))) == 0) return (pixel_t **) 0; for (y = 0; y < Ysize; ++y) p[y] = (pixel_t *) Emalloc((unsigned)Xsize * sizeof (pixel_t)); if (noerr == 0) { /* Run out of memory; free what we have allocated */ for (y = 0; y < Ysize; ++y) { if (p[y]) free((char *) p[y]); } return (pixel_t **) 0; } return p; } void ImgFree(img) struct SRC *img; { int y; pixel_t **p; free(img->str); img->str = (char *) 0; p = img->pix; for (y = 0; y < Ysize; ++y) free((char *) (*p++)); free((char *) img->pix); img->pix = (pixel_t **) 0; } void Efclose(stream) FILE *stream; { #if unix if (IsPopen) PCLOSE(stream); else #endif /* unix */ FCLOSE(stream); } FILE * EfopenR(filename) char *filename; { FILE *istr; #if unix FILE *popen(); #endif /* unix */ DEBUG((Debug, "EfopenR(%s)\n", filename)); IsPopen = 0; if ((istr = fopen(filename, RMODE)) != NULL) return istr; #if unix if (errno == ENOENT) { char buf[512]; /* first see if the compressed file exists and is readable */ SPRINTF(buf, "%s.Z", filename); if ((istr = fopen(buf, "r")) != NULL) { /* OK - it's there */ FCLOSE(istr); SPRINTF(buf, "zcat %s", filename); DEBUG((Debug, "popen(%s)\n", buf)); if ((istr = popen(buf, "r")) != NULL) { IsPopen = 1; return istr; } } } #endif /* unix */ SPRINTF(ErrBuf, "Can't read file '%s'", filename); error(ERR_SYS); return NULL; } FILE * EfopenW(filename) char *filename; { FILE *ostr; FILE *popen(); DEBUG((Debug, "EfopenW(%s)\n", filename)); IsPopen = 0; #if unix if (*filename == '|') { ++filename; if ((ostr = popen(filename, "w")) == NULL) { SPRINTF(ErrBuf, "Can't run command '%s'", filename); error(ERR_SYS); } return ostr; } #endif /* unix */ if ((ostr = fopen(filename, WMODE)) == NULL) { SPRINTF(ErrBuf, "Can't write file '%s'", filename); error(ERR_SYS); } return ostr; } void getpix(filename, imgname) char *filename; /* file name */ char *imgname; /* image name */ { FILE *fd; int y, c; struct SRC *img = (struct SRC *) 0; /* work buffer */ char *p, *rem; if ((fd = EfopenR(filename)) == NULL) return; if (imgname == 0 || *imgname == '\0') { imgname = filename; /* * Use the basename of the filename for the image name. * If this results in a non-valid image name, they'll * just have to use the $n equivalent. It's not our * business to go transforming names. */ /* find last '/' in string */ for (p = rem = imgname; *p; ++p) if (*p == '/' && p[1] != '\0') rem = p + 1; imgname = rem; } /* See if the named image already exists */ for (c = 0; c < nsrc; c++) if (src[c].str && strcmp(src[c].str, imgname) == 0) { img = &src[c]; break; } if (img == (struct SRC *) 0) { /* Allocate a new image */ img = &src[nsrc++]; if ( (img->pix = ImgAlloc()) == 0 || (img->str = (char *) Emalloc((unsigned int) (strlen(imgname)+1))) == 0 ) return; STRCPY(img->str, imgname); } /* Read in the image */ for (y = 0; y < Ysize; y++) { long total = 0; int count; if ((count = fread((char *) img->pix[y], 1, Xsize, fd)) <= 0) { if (ferror(fd)) { SPRINTF(ErrBuf, "File '%s' read error (read %ld of %ld bytes)", filename, total, (long)Xsize * Ysize); error(ERR_SYS); FCLOSE(fd); return; } SPRINTF(ErrBuf, "File '%s' insufficient data (read %ld of %ld bytes)", filename, total, Xsize * Ysize); error(0); return; } total += count; } Efclose(fd); } void putpix(into, str) struct SRC *into ; /* work buffer */ char *str ; /* file name */ { FILE *fd; int i; if ((fd = EfopenW(str)) == NULL) return; for (i = 0; i < Ysize; i++) FWRITE((char *) into->pix[i], 1, Xsize, fd); Efclose(fd); } void showfiles() { int n; for (n = 2; n < nsrc; n++) if(src[n].str) { PRINTF("$%d = %s\n", n - 1, src[n].str); if (LogStr) FPRINTF(LogStr, "$%d = %s\n", n - 1, src[n].str); } }