dviselect (Part 4 of 6)

Skip Montanaro montnaro at sprite.crd.ge.com
Tue Nov 14 08:22:58 AEST 1989


#! /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 4 (of 6)."
# Contents:  lib/getopt.c lib/gfclass.c lib/gffont.c lib/gripes.c
#   lib/magfactor.c
# Wrapped by montnaro at sprite on Sat Nov 11 17:13:31 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f lib/getopt.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/getopt.c\"
else
echo shar: Extracting \"lib/getopt.c\" \(1380 characters\)
sed "s/^X//" >lib/getopt.c <<'END_OF_lib/getopt.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X/*
X * getopt - get option letter from argv
X * (From Henry Spencer @ U of Toronto Zoology, slightly edited)
X */
X
X#include <stdio.h>
X
Xchar	*optarg;	/* Global argument pointer. */
Xint	optind;		/* Global argv index. */
X
Xstatic char *scan;	/* Private scan pointer. */
X
Xextern char *index();
X
Xint
Xgetopt(argc, argv, optstring)
X	register int argc;
X	register char **argv;
X	char *optstring;
X{
X	register int c;
X	register char *place;
X
X	optarg = NULL;
X	if (scan == NULL || *scan == 0) {
X		if (optind == 0)
X			optind++;
X		if (optind >= argc || argv[optind][0] != '-' ||
X		    argv[optind][1] == 0)
X			return (EOF);
X		if (strcmp(argv[optind], "--") == 0) {
X			optind++;
X			return (EOF);
X		}
X		scan = argv[optind] + 1;
X		optind++;
X	}
X	c = *scan++;
X	place = index(optstring, c);
X
X	if (place == NULL || c == ':') {
X		fprintf(stderr, "%s: unknown option -%c\n", argv[0], c);
X		return ('?');
X	}
X	place++;
X	if (*place == ':') {
X		if (*scan != '\0') {
X			optarg = scan;
X			scan = NULL;
X		} else {
X			if (optind >= argc) {
X				fprintf(stderr,
X					"%s: missing argument after -%c\n",
X					argv[0], c);
X				return ('?');
X			}
X			optarg = argv[optind];
X			optind++;
X		}
X	}
X	return (c);
X}
END_OF_lib/getopt.c
if test 1380 -ne `wc -c <lib/getopt.c`; then
    echo shar: \"lib/getopt.c\" unpacked with wrong size!
fi
chmod +x lib/getopt.c
# end of overwriting check
fi
if test -f lib/gfclass.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/gfclass.c\"
else
echo shar: Extracting \"lib/gfclass.c\" \(2408 characters\)
sed "s/^X//" >lib/gfclass.c <<'END_OF_lib/gfclass.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/gfclass.c,v 1.3 89/02/13 14:31:07 grunwald Exp Locker: grunwald $";
X#endif
X
X/*
X * gfclass - GF code classification tables.
X */
X
X#include "gfclass.h"
X
X/* shorthand---in lowercase for contrast (read on!) */
X#define	three(x)	x, x, x
X#define	four(x)		x, x, x, x
X#define	five(x)		four(x), x
X#define	six(x)		four(x), x, x
X#define	eight(x)	four(x), four(x)
X#define	sixteen(x)	eight(x), eight(x)
X#define	thirty_two(x)	sixteen(x), sixteen(x)
X#define	sixty_four(x)	thirty_two(x), thirty_two(x)
X#define	one_twenty_eight(x) sixty_four(x), sixty_four(x)
X#define	one_sixty_five(x) one_twenty_eight(x), thirty_two(x), five(x)
X
X/*
X * Length of the single (or first) operand, if any.
X */
Xchar gf_oplen[256] = {
X	sixty_four(GPL_NONE),	/* GF_PAINT_0 through GF_PAINT_63 */
X	GPL_UNS1,		/* GF_PAINT1 */
X	GPL_UNS2,		/* GF_PAINT2 */
X	GPL_UNS3,		/* GF_PAINT3 */
X	GPL_NONE,		/* GF_BOC */
X	GPL_NONE,		/* GF_BOC1 */
X	GPL_NONE,		/* GF_EOC */
X	GPL_NONE,		/* GF_SKIP0 */
X	GPL_UNS1,		/* GF_SKIP1 */
X	GPL_UNS2,		/* GF_SKIP2 */
X	GPL_UNS3,		/* GF_SKIP3 */
X	one_sixty_five(GPL_NONE),/* GF_NEW_ROW_0 through GF_NEW_ROW_164 */
X	GPL_UNS1,		/* GF_XXX1 */
X	GPL_UNS2,		/* GF_XXX2 */
X	GPL_UNS3,		/* GF_XXX3 */
X	GPL_SGN4,		/* GF_XXX4 */
X	GPL_SGN4,		/* GF_YYY */
X	GPL_NONE,		/* GF_NOP */
X	GPL_NONE,		/* GF_CHAR_LOC */
X	GPL_NONE,		/* GF_CHAR_LOC0 */
X	GPL_NONE,		/* GF_PRE */
X	GPL_NONE,		/* GF_POST */
X	GPL_NONE,		/* GF_POSTPOST */
X	six(GPL_NONE)		/* 250 through 255 */
X};
X
X/*
X * Types of the various opcodes.
X */
Xchar gf_gt[256] = {
X	sixty_four(GT_PAINT0),	/* GF_PAINT_0 through GF_PAINT_63 */
X	three(GT_PAINT),	/* GF_PAINT1 through GF_PAINT3 */
X	GT_BOC,			/* GF_BOC */
X	GT_BOC1,		/* GF_BOC1 */
X	GT_EOC,			/* GF_EOC */
X	GT_SKIP0,		/* GF_SKIP0 */
X	three(GT_SKIP),		/* GF_SKIP1 through GF_SKIP3 */
X	one_sixty_five(GT_NEW_ROW),/* GF_NEW_ROW_0 throgh GF_NEW_ROW_164 */
X	four(GT_XXX),		/* GF_XXX1 through GF_XXX4 */
X	GT_YYY,			/* GF_YYY */
X	GT_NOP,			/* GF_NOP */
X	GT_CHAR_LOC,		/* GF_CHAR_LOC */
X	GT_CHAR_LOC0,		/* GF_CHAR_LOC0 */
X	GT_PRE,			/* GF_PRE */
X	GT_POST,		/* GF_POST */
X	GT_POSTPOST,		/* GF_POSTPOST */
X	six(GT_UNDEF)		/* 250 through 255 */
X};
END_OF_lib/gfclass.c
if test 2408 -ne `wc -c <lib/gfclass.c`; then
    echo shar: \"lib/gfclass.c\" unpacked with wrong size!
fi
chmod +x lib/gfclass.c
# end of overwriting check
fi
if test -f lib/gffont.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/gffont.c\"
else
echo shar: Extracting \"lib/gffont.c\" \(22029 characters\)
sed "s/^X//" >lib/gffont.c <<'END_OF_lib/gffont.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/gffont.c,v 1.4 89/02/13 14:31:08 grunwald Exp Locker: grunwald $";
X#endif
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include "types.h"
X#include "font.h"
X#include "gfcodes.h"
X#include "gfclass.h"
X#include "num.h"
X
X/*
X * GF font operations.
X *
X * GF files may be compact, but this code surely is not!
X *
X * TODO:
X *	think about fonts with characters outside [0..255]
X *	find some way to free gf body when done
X */
X
Xstatic gf_read();
Xstatic gf_getgly();
Xstatic gf_rasterise();
Xstatic gf_freefont();
X
Xstruct	fontops gfops =
X	{ "gf", 1.0, gf_read, gf_getgly, gf_rasterise, gf_freefont };
X
X/*
X * Local info.
X */
X
X/*
X * A bounding box.  The names follow those in the GF documentation.
X */
Xstruct bounds {
X	i32	min_m, max_m;	/* min and max `m' (colunm) values */
X	i32	min_n, max_n;	/* min and max `n' (row) values */
X};
X
X/*
X * char_loc is one `character locator' from a GF file, save for the
X * `character residue', which we need not.
X */
Xstruct char_loc {
X	i32	cl_dx;		/* x escapement (scaled pixels) */
X	i32	cl_dy;		/* y escapement (scaled pixels) */
X	i32	cl_w;		/* TFM width */
X	i32	cl_p;		/* pointer to BOC (or specials) */
X};
X
X/*
X * GF details include:
X *  ->	the main body of the GF file (all bytes save pre- and post-amble);
X *  ->	global box boundaries;
X * and	character locators, addressed by `character residue'.  Empty
X *	slots are indicated by a -1 `pointer'.
X */
Xstruct gf_details {
X	char	*gd_body;		/* GF body */
X	char	*gd_base;		/* == gd_body - preamble_size */
X	struct	bounds gd_gb;		/* global boundaries */
X	struct	char_loc gd_cl[256];	/* character locators */
X};
X
X/*
X * Get the gf_details from font f.
X */
X#define	ftogd(f) ((struct gf_details *) (f)->f_details)
X
Xextern	int errno;
Xchar	*malloc(), *copyit();
X
Xstatic int gf_read();
Xstatic int gf_read();
Xstatic int gf_rasterise();
Xstatic int gf_freefont();
X
X/*
X * I am making the assumption that 530 bytes will always be enough
X * to find the end of the GF file.  12 should suffice, as there
X * should be at most seven GF_FILLER bytes, preceded by the GF ID,
X * preceded by the four byte postamble pointer; but at least one
X * VMS TeX pads pads DVI files to a full `sector', so I am assuming
X * it may do the same to GF files.
X */
X#ifdef vms
X#define	POSTSIZE	530	/* make only VMS pay for its ways; */
X#else
X#define	POSTSIZE	16	/* others get to use something reasonable */
X#endif
X
X/*
X * Find the GF postamble.  Store the offsets of the POST and POSTPOST
X * opcodes through postp and postpostp.
X */
Xstatic
XfindGFpostamble(fd, postp, postpostp)
X	int fd;
X	long *postp, *postpostp;
X{
X	register long offset;
X	register char *p;
X	register int i;
X	register i32 n;
X	char postbuf[POSTSIZE];
X
X	/*
X	 * Avoid lseek()ing beyond beginning of file; it may give odd
X	 * results.  Read the last POSTSIZE bytes (or however many we
X	 * can get).
X	 */
X	offset = lseek(fd, 0L, 2) - (long) POSTSIZE;
X	if (offset < 0L)
X		offset = 0L;
X	(void) lseek(fd, offset, 0);
X	i = read(fd, postbuf, POSTSIZE);
X	if (i <= 0)
X		return (-1);
X	p = &postbuf[i];
X	i -= 4;			/* account for the pointer in advance */
X
X	/*
X	 * Now search backwards for the GF_ID byte.  The postamble
X	 * pointer will be four bytes behind that.
X	 */
X	while (--i >= 0) {
X		if (UnSign8(*--p) == GF_ID)
X			goto foundit;
X		if (UnSign8(*p) != GF_FILLER)
X			break;
X	}
X	return (-1);		/* cannot find postamble ptr */
X
Xfoundit:
X	/*
X	 * Store the (presumed) position of the POSTPOST byte, which
X	 * is i-1 bytes beyond `offset'.
X	 */
X	*postpostp = offset + i - 1;
X
X	/*
X	 * Read out the postamble pointer and seek to the postamble,
X	 * also saving the offset.
X	 */
X	p -= 4;
X	pGetLong(p, n);
X	*postp = offset = n;
X	(void) lseek(fd, offset, 0);
X	return (0);		/* made it */
X}
X
X/*
X * Read a GF file.
X */
Xstatic int
Xgf_read(f)
X	register struct font *f;
X{
X	register struct gf_details *gd;
X	register char *p;
X	register struct char_loc *cl;
X	register int i;
X	int fd, presize, postsize, bodysize, firstc, lastc;
X	char *postamble;
X	long postaddr, postpostaddr;
X	i32 lasteoc;
X	char *problem = NULL;
X	struct stat st;
X	char b[4];
X	int saverr;
X
X	if ((fd = open(f->f_path, 0)) < 0)
X		return (-1);
X	gd = NULL;		/* prepare for failure */
X	postamble = NULL;
X
X	/*
X	 * The file had best be at least 50 bytes long.  A
X	 * `completely empty' GF file might consist of a PRE, a GF_ID,
X	 * no comment (one zero byte), then: POST, pointer to last
X	 * EOC, design size, checksum, hppp, vppp, min_m, max_m,
X	 * min_n, max_n, POSTPOST, pointer to POST, GF_ID, and four
X	 * FILLERs.
X	 */
X	(void) fstat(fd, &st);
X	if (st.st_size < 50) {	/* too small to be a GF file */
X		problem = "file is too short";
X		goto fail;
X	}
X
X	/*
X	 * Read the very beginning and pick up the preamble size.
X	 */
X	if (read(fd, b, 4) != 4)
X		goto fail;
X	if (UnSign8(b[0]) != GF_PRE) {
X		problem = "file does not begin with PRE";
X		goto fail;
X	}
X	i = UnSign8(b[1]);
X	if (i != GF_ID)
X		error(0, 0, "Warning: strange GF id (%d) in \"%s\"", i,
X			f->f_path);
X	presize = 3 + UnSign8(b[2]);
X
X	/*
X	 * Find the postamble, allocate space, and read it in.
X	 */
X	if (findGFpostamble(fd, &postaddr, &postpostaddr)) {
X		problem = "cannot find postamble";
X		goto fail;
X	}
X	postsize = postpostaddr - postaddr + 1;
X	if ((p = malloc(postsize)) == NULL)
X		goto fail;
X	if (read(fd, p, postsize) != postsize)
X		goto fail;
X	postamble = p;
X	
X	/*
X	 * Make sure we found it.
X	 */
X	if (pgetbyte(p) != GF_POST) {
X		problem = "no GF_POST at postamble";
X		goto fail;
X	}
X
X	/*
X	 * Looks okay.  Allocate detail space and poke through the postamble.
X	 */
X	if ((gd = (struct gf_details *) malloc(sizeof (*gd))) == NULL)
X		goto fail;
X	gd->gd_body = NULL;
X
X	pGetLong(p, lasteoc);	/* actually one past last EOC */
X	pGetLong(p, f -> f_design_size );
X	pGetLong(p, f->f_checksum);
X	pGetLong(p, f -> f_hppp);
X	pGetLong(p, f -> f_vppp);
X
X	pGetLong(p, gd->gd_gb.min_m);
X	pGetLong(p, gd->gd_gb.max_m);
X	pGetLong(p, gd->gd_gb.min_n);
X	pGetLong(p, gd->gd_gb.max_n);
X
X	/*
X	 * Zap all the character locators, then read those that are
X	 * defined in the postamble.  Remember the first and last
X	 * characters so that we know which glyphs are defined.  Lastc
X	 * is actually the last-plus-one'th character.
X	 */
X	for (cl = gd->gd_cl, i = 256; --i >= 0; cl++)
X		cl->cl_p = -1;
X	firstc = 256;
X	lastc = 0;
X	for (;;) {
X		i32 dx, dy;
X
X		switch (pgetbyte(p)) {
X
X		case GF_CHAR_LOC:
X			i = pgetbyte(p);
X			pGetLong(p, dx);
X			pGetLong(p, dy);
X			goto merge;
X
X		case GF_CHAR_LOC0:
X			i = pgetbyte(p);
X			dx = ((i32) pgetbyte(p)) << 16;
X			dy = 0;
Xmerge:
X			if (i < firstc)
X				firstc = i;
X			if (i >= lastc)
X				lastc = i + 1;
X			cl = &gd->gd_cl[i];
X			cl->cl_dx = dx;
X			cl->cl_dy = dy;
X			pGetLong(p, cl->cl_w);
X			pGetLong(p, cl->cl_p);
X			break;
X
X		case GF_POSTPOST:
X			goto done;
X
X		default:
X			error(0, 0, "I do not understand %d here",
X				UnSign8(p[-1]));
X			problem = "unexpected opcode in postamble";
X			goto fail;
X		}
X	}
Xdone:
X	free(postamble);
X	postamble = NULL;	/* all done with it */
X
X	/*
X	 * Alas, we need the instructions whether or not we need
X	 * the rasters, since the raster bounding box information
X	 * can only be properly determined by converting the rasters.
X	 * Compute the size of the main body of the GF file, then
X	 * read it in.
X	 */
X	bodysize = lasteoc - presize;
X	if ((gd->gd_body = malloc(bodysize + 1)) == NULL)
X		goto fail;
X	(void) lseek(fd, (long) presize, 0);
X	if (read(fd, gd->gd_body, bodysize) != bodysize)
X		goto fail;
X	/*
X	 * The next byte might be a special, so we just
X	 * arbitrarily stuff in a POST.
X	 */
X	gd->gd_body[bodysize] = GF_POST;
X	gd->gd_base = gd->gd_body - presize;
X
X	f->f_details = (char *) gd;
X	if (FontHasGlyphs(f, firstc, lastc))
X		goto fail2;
X	(void) close(fd);
X	return (0);
X
Xfail:
X	if (problem == NULL)
X		error(0, errno, "trouble reading \"%s\"", f->f_path);
X	else
X		error(0, 0, "%s\n\t(are you sure \"%s\" is a GF file?)",
X			problem, f->f_path);
X	errno = 0;
Xfail2:
X	saverr = errno;
X	if (postamble != NULL) {
X		free(postamble); postamble = 0;
X	      }
X	if (gd != NULL) {
X		if (gd->gd_body != NULL) {
X			free(gd->gd_body); gd -> gd_body = 0;
X		      }
X		free((char *) gd); gd = 0;
X	}
X	(void) close(fd);
X	errno = saverr;
X	return (-1);
X}
X
X/*
X * Some global variables, used while building rasters.  (These are
X * referenced also in copyit(), so must be global.  Fortunately, no
X * one yet requires the font routines to be re-entrant.)
X */
Xstatic char *buildraster;	/* raster being built */
Xstatic int buildsize;		/* size of buildraster (bytes) */
X
Xstatic struct bounds tempb;	/* bounds used during buildraster */
Xstatic struct bounds ob;	/* observed bounds */
X
X/*
X * Bit tables: `left' and `right' bits.  lbits[b] has all the bits
X * that are to the left of bit b set; rbits[b] has all the bits
X * that are to the right of bit b set, as well as bit b itself.
X */
Xstatic char lbits[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
Xstatic char rbits[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
X
X/*
X * The magic address `nullraster' is known in getgly() as a valid
X * but empty raster, and changed there to NULL.  A NULL return from
X * drawchar indicates failure; we need something to distinguish the
X * empty raster.
X */
Xstatic char nullraster[1];
X
X/*
X * `Inline functions':
X *  ->	convert a bit number to a byte number (round down);
X *  ->	convert a number of bits to a number of bytes (round up);
X * and	convert a bit to a bit index.
X */
X#define btoby(b) ((b) >> 3)
X#define	btonb(b) (((b) + 7) >> 3)
X#define	btobi(b) ((b) & 7)
X
X/*
X * Helper function for getgly: build the raster, and compute its
X * minimal bounding box.  Called with `p' pointing past the backpointer
X * field of the BOC command (i.e., at min_m or del_m).  `abbrev' is true
X * iff this was a BOC1.  `globalb' are the global bounds from the GF file,
X * whose name is pointed to by gfname.
X */
Xstatic char *
Xdrawchar(p, abbrev, globalb, gfname)
X	register char *p;
X	int abbrev;
X	struct bounds globalb;
X	char *gfname;
X{
X	register i32 m;		/* m register (column) */
X	register char *colp;	/* pointer to byte corresponding to m */
X	register int c;		/* temporary */
X	register i32 i;		/* temporary */
X	register int black;	/* true when paint_switch==black */
X	register i32 n;		/* n register (row) */
X	int stride;		/* multiplier to convert linear to 2d array */
X	int wrotethisrow;	/* true iff we wrote in the current row */
X	char *virtrast;		/* virtual origin version of buildraster */
X	int mustcopy;		/* true if we must copy the built raster */
X	struct bounds gb;	/* bounds from the GF file */
X
X	/* get the bounds */
X	if (abbrev) {
X		c = pgetbyte(p);/* del_m */
X		gb.min_m = (gb.max_m = pgetbyte(p)) - c;
X		c = pgetbyte(p);/* del_n */
X		gb.min_n = (gb.max_n = pgetbyte(p)) - c;
X	} else {
X		pGetLong(p, gb.min_m);
X		pGetLong(p, gb.max_m);
X		pGetLong(p, gb.min_n);
X		pGetLong(p, gb.max_n);
X	}
X
X	/*
X	 * Trim the GF bounds according to the global bounds.  We
X	 * use the trimmed values to allocate the build space.
X	 */
X	tempb = gb;
X#define	GB_ADJ(field, cmp) \
X	if (tempb.field cmp globalb.field) \
X		tempb.field = globalb.field
X	GB_ADJ(min_m, <);
X	GB_ADJ(max_m, >);
X	GB_ADJ(min_n, <);
X	GB_ADJ(max_n, >);
X#undef GB_ADJ
X
X	/*
X	 * Compute the distance between rows (the number of bytes per
X	 * column), then make sure there is room in the build space
X	 * for [min_n..max_n] of these, possibly by allocating a new raster.
X	 */
X	stride = btonb(tempb.max_m - tempb.min_m + 1);
X	c = stride * (tempb.max_n - tempb.min_n + 1);
X	if (c <= 0)		/* completely empty character */
X		return (nullraster);
X	if (c > buildsize) {
X		if (buildraster != NULL) {
X			free(buildraster); buildraster = 0;
X		      }
X		if ((buildraster = malloc(c)) == NULL) {
X			buildsize = 0;
X			return (NULL);
X		}
X		buildsize = c;
X	}
X
X	/*
X	 * If we are using an old raster that is too big, remember to
X	 * scrunch it down later.
X	 */
X	mustcopy = buildsize > c;
X
X	/* clear the raster to white */
X	bzero(buildraster, c);
X
X	/*
X	 * Make a virtual origin raster pointer.  The virtual origin is
X	 * where raster[0][0] is, whether or not there is a raster[0][0].
X	 * Normally, this would be
X	 *	&buildraster[-gb.min_n * stride - btoby(gb.min_m)],
X	 * but it is complicated by two things.  Firstly, we would like
X	 * n==max_n to be the bottommost point in the raster (low
X	 * addresses), and n==min_n to be the topmost (high addresses).
X	 * In other words, we need to reflect the n (Y) values about
X	 * the X axis: negate them.  Secondly, the raster we create
X	 * must be `flush left'.  That is, somewhere along its rows,
X	 * bit 0x80 must be set at the left edge of one of its columns.
X	 * We need to subtract away the minimum bit index before
X	 * calculating bit values.  This cannot really be done in
X	 * advance, since we cannot address bits directly.
X	 */
X	virtrast = &buildraster[gb.max_n * stride];
X
X	/*
X	 * Set up the bounds-trimming variables.  The observed m bounds
X	 * are kept offset by gb.min_m until we finish drawing the
X	 * character.
X	 */
X	ob.min_m = tempb.max_m - gb.min_m + 1;
X	ob.max_m = tempb.min_m - gb.min_m - 1;
X	ob.min_n = tempb.max_n + 1;
X	ob.max_n = tempb.min_n - 1;
X	wrotethisrow = 0;
X
X#define FIX_N_BOUNDS() { \
X	if (wrotethisrow) { \
X		c = -n; /* recall that n is reflected about X axis */ \
X		if (c < ob.min_n) \
X			ob.min_n = c; \
X		if (c > ob.max_n) \
X			ob.max_n = c; \
X		wrotethisrow = 0; \
X	} \
X}
X
X	/*
X	 * Initialise state variables: m = min_m, n = max_n,
X	 * paint_switch = white.
X	 */
X	m = 0;			/* gb.min_m - gb.min_m */
X	n = -gb.max_n;		/* reflected */
X	colp = &virtrast[n * stride];
Xif (colp != buildraster)
Xpanic("gffont drawchar colp != buildraster");
X	black = 0;
X
X	/*
X	 * Now interpret the character.
X	 * `for (;;)' pushes everything off the right edge, alas.
X	 */
Xmore:
X	c = pgetbyte(p);
X	if (GF_IsPaint(c))	/* faster? */
X		goto paint;
X	switch (GF_OpLen(c)) {
X
X	case GPL_NONE:
X		break;
X
X	case GPL_UNS1:
X		i = pgetbyte(p);
X		break;
X
X	case GPL_UNS2:
X		pGetWord(p, i);
X		break;
X
X	case GPL_UNS3:
X		pGet3Byte(p, i);
X		break;
X
X	case GPL_SGN4:
X		pGetLong(p, i);
X		break;
X
X	default:
X		panic("gffont drawchar GF_OpLen(%d) = %d", c, GF_OpLen(c));
X		/* NOTREACHED */
X	}
X
X	switch (GF_TYPE(c)) {
X
X	case GT_PAINT0:
Xpaint:
X		i = c - GF_PAINT_0;
X		/* FALLTHROUGH */
X
X	case GT_PAINT:
X		/*
X		 * Paint `i' bits in the current row at columns [m..m+i).
X		 */
X		if (i && black) {
X			/* remember to adjust n bounds later */
X			wrotethisrow = 1;
X			/* adjust minimum m bound */
X			if (m < ob.min_m)
X				ob.min_m = m;
X
X			/*
X			 * Finish the partial byte at colp.  There are 8-k
X			 * bits to set to finish it, where k is the bit
X			 * index value from m.  If we need to set fewer
X			 * than 8-k bits, set them now and skip the rest
X			 * of this.
X			 */
X			c = 8 - btobi(m);
X			if (i < c) {	/* cannot finish it off */
X				*colp |= UnSign8(lbits[i]) >> btobi(m);
X				m += i;
X			} else {	/* finish it off */
X				*colp++ |= rbits[btobi(m)];
X				i -= c;
X				m += c;
X
X				/*
X				 * Update m to reflect having written the
X				 * remaining i bits, then write them.
X				 * First write all the full bytes, then
X				 * start a partial byte with whatever
X				 * is left over, if anything.
X				 */
X				m += i;
X				i >>= 3;
X				while (--i >= 0)
X					*colp++ = 0xff;
X				*colp |= lbits[btobi(m)];
X			}
X
X			/* adjust maximum m bound */
X			if (m > ob.max_m)
X				ob.max_m = m;
X		} else {
X			/*
X			 * Add the bit index so that we round up whenever
X			 * this fills the partial byte at colp.
X			 */
X			colp += (i + btobi(m)) >> 3;
X			m += i;
X		}
X		black = !black;
X		break;
X
X	case GT_EOC:		/* all done */
X		FIX_N_BOUNDS();
X		goto done;
X
X	case GT_SKIP0:		/* skip no rows */
X		i = 0;
X		/* FALLTHROUGH */
X
X	case GT_SKIP:		/* skip some rows, draw white */
X		m = 0;
X		black = 0;
X		goto skip_or_new_row;
X
X	case GT_NEW_ROW:	/* next row near left col, draw black */
X		m = c - GF_NEW_ROW_0;
X		black = 1;
X		i = 0;			/* n offset is 1: skip no rows */
Xskip_or_new_row:
X		FIX_N_BOUNDS();
X		n += i + 1;		/* += because reflected */
X		colp = &virtrast[n * stride + btoby(m)];
X		break;
X
X	case GT_XXX:		/* special */
X		p += i;
X		break;
X
X	case GT_YYY:		/* numspecial */
X		break;
X
X	case GT_NOP:		/* dull */
X		break;
X
X	case GT_BOC:		/* should not appear */
X	case GT_BOC1:
X	case GT_CHAR_LOC:
X	case GT_CHAR_LOC0:
X	case GT_PRE:
X	case GT_POST:
X	case GT_POSTPOST:
X	case GT_UNDEF:
X		error(0, 0, "unexpected GF opcode %d", c);
X		error(1, 0, "bad GF file \"%s\"", gfname);
X		/* NOTREACHED */
X
X	default:
X		panic("gffont drawchar GF_TYPE(%d) = %d", c, GF_TYPE(c));
X		/* NOTREACHED */
X	}
X	goto more;
X
Xdone:
X	/*
X	 * The observed bounds `m' values are both off by gb.min_m, so
X	 * fix them now.  CONSIDER ADJUSTING n HERE TOO
X	 */
X	ob.min_m += gb.min_m;
X	ob.max_m += gb.min_m;
X
X	/*
X	 * If we used too much memory for the raster, copy it now.
X	 */
X	if (mustcopy || tempb.min_n != ob.min_n || tempb.max_n != ob.max_n ||
X	    btonb(ob.max_m - ob.min_m + 1) != stride)
X		return (copyit());
X
X	/*
X	 * If the left column bounds match, just move the raster in place.
X	 */
X	if (tempb.min_m == ob.min_m) {
X		p = buildraster;
X		buildraster = NULL;
X		buildsize = 0;
X		return (p);
X	}
X
X	/*
X	 * The raster must be copied, but only because it is not
X	 * `left justified'.
X	 *
X	 * CONSIDER DEFERRING THIS PHASE UNTIL THE RASTER IS USED
X	 */
X	return (copyit());
X}
X
X/*
X * Copy the built raster to newly allocated space.
X * We may need to shift all the bits left as well.
X */
Xchar *
Xcopyit()
X{
X	register char *o, *p;
X	register int i, oldoff, newoff;
X	char *n;
X
X	/*
X	 * Compute the observed minimum stride.  If it is zero or negative,
X	 * there is no raster at all, else allocate just enough space
X	 * to hold the new raster.
X	 */
X	newoff = btonb(ob.max_m - ob.min_m + 1);
X	if (newoff <= 0)
X		return (nullraster);
Xif (ob.max_n < ob.min_n)
Xpanic("gffont copyit max_n < min_n");
X	n = malloc((unsigned) (newoff * (ob.max_n - ob.min_n + 1)));
X	if ((p = n) == NULL)
X		return (NULL);
X
X	/*
X	 * Compute the old stride.
X	 */
X	oldoff = btonb(tempb.max_m - tempb.min_m + 1);
Xif (oldoff < newoff)
Xpanic("gffont copyit oldoff < newoff");
X
X	/*
X	 * Point at the old raster, then add the offset to the first
X	 * written row, and then the offset to the first written column.
X	 */
X	o = buildraster;
X	o += (ob.max_n - tempb.max_n) * oldoff;
X	i = ob.min_m - tempb.min_m;
X	o += btoby(i);
X
X	/*
X	 * Now copy each row, doing shifting if required.
X	 */
X	if ((i = btobi(i)) != 0) {	/* must shift, alas */
X		register int r = 8 - i, j, k;
X
X		oldoff -= newoff;
X		for (k = ob.max_n; k >= ob.min_n; k--) {
X			for (j = newoff; --j >= 0;) {
X				*p++ = *o++ << i;
X				p[-1] |= UnSign8(*o) >> r;
X			}
X			o += oldoff;
X		}
X	} else if (oldoff > newoff) {	/* compressing columns */
X		for (i = ob.max_n; i >= ob.min_n; i--) {
X			bcopy(o, p, newoff);
X			o += oldoff;
X			p += newoff;
X		}
X	} else				/* just squeezing out extra rows */
X		bcopy(o, p, newoff * (ob.max_n - ob.min_n + 1));
X
X	/* finally, return the copy */
X	return (n);
X}
X
X/*
X * Obtain the specified range of glyphs.
X */
Xstatic int
Xgf_getgly(f, l, h)
X	register struct font *f;
X	int l, h;
X{
X	register struct glyph *g;
X	register struct char_loc *cl;
X	register char *p;
X	register i32 c;
X	register int i;
X	register i32 thisboc;
X	int abbrev;
X	struct gf_details *gd = ftogd(f);
X
X	/*
X	 * For each glyph, make sure there exists an instance of that
X	 * character residue.  Go find the actual glyph (which may be
X	 * arbitrarily far down a chain of pointers) and get its info.
X	 */
X	for (cl = &gd->gd_cl[i = l]; i < h; i++, cl++) {
X		g = f->f_gly[i];
X		thisboc = cl->cl_p;
X
X		/*
X		 * Screw around locating the character for real.
X		 */
X		while (thisboc != -1) {
X			p = gd->gd_base + thisboc;
Xskip:
X			c = pgetbyte(p);
X			switch (GF_TYPE(c)) {
X
X			case GT_XXX:
X				switch (GF_OpLen(c)) {
X
X				case GPL_UNS1:
X					c = pgetbyte(p);
X					break;
X
X				case GPL_UNS2:
X					pGetWord(p, c);
X					break;
X
X				case GPL_UNS3:
X					pGet3Byte(p, c);
X					break;
X
X				case GPL_SGN4:
X					pGetLong(p, c);
X					break;
X
X				default:
X					panic("gf_getgly GF_OpLen(%d) = %d",
X						c, GF_OpLen(c));
X					/* NOTREACHED */
X				}
X				p += c;
X				goto skip;
X
X			case GT_YYY:
X				p += 4;
X				goto skip;
X
X			case GT_BOC:
X				abbrev = 0;
X				pGetLong(p, c);
X				break;
X
X			case GT_BOC1:
X				abbrev = 1;
X				c = pgetbyte(p);
X				break;
X
X			default:
X				error(0, 0, "GF code %d; I expected BOC", c);
X				error(1, 0, "bad GF file \"%s\"", f->f_path);
X				/* NOTREACHED */
X			}
X			/*
X			 * Found a BOC.  If it is the right character,
X			 * go handle it.
X			 */
X			if (c == i)
X				goto handleit;
X			if ((c & 255) != i) {
X				error(0, 0, "%d != %d mod 256", c, i);
X				error(1, 0, "Bad GF file \"%s\"", f->f_path);
X			}
X			/*
X			 * Follow the backpointer.
X			 */
X			if (abbrev)
X				thisboc = -1;
X			else
X				pGetLong(p, thisboc);
X		}
X
X		/*
X		 * If we get here, the glyph is not valid after all.
X		 */
X		continue;
X	
X		/*
X		 * The glyph is okay.  Set it up.
X		 */
Xhandleit:
X		g->g_flags = GF_VALID;
X		g->g_xescapement = cl->cl_dx;
X		g->g_yescapement = cl->cl_dy;
X		g->g_tfmwidth = cl->cl_w;
X		g -> g_rawtfmwidth = g -> g_tfmwidth;
X		if (!abbrev)
X			p += 4;		/* skip backpointer */
X		if ((p = drawchar(p, abbrev, gd->gd_gb, f->f_path)) == NULL)
X			return (-1);	/* ??? */
X		if (p == nullraster)
X			p = NULL;
X		/* set height &c based on observed bounds */
X		g->g_height = ob.max_n - ob.min_n + 1;
X		g->g_width = ob.max_m - ob.min_m + 1;
X		g->g_yorigin = ob.max_n;
X		g->g_xorigin = -ob.min_m;
X		g->g_raster = p;
X		g->g_rotation = ROT_NORM;
X	}
X	return (0);
X}
X
X/*
X * Obtain rasters for the specified glyphs.  We did this above, while
X * adjusting the bounding boxes, so this routine should never get called.
X */
Xstatic int
Xgf_rasterise(f, l, h)
X	struct font *f;
X	int l, h;
X{
X
X	panic("gf_rasterise(%s, %d, %d)", f->f_path, l, h);
X}
X
X/*
X * Discard the font details.
X */
Xstatic
Xgf_freefont(f)
X	struct font *f;
X{
X	struct gf_details *gd;
X
X	if ((gd = ftogd(f)) != NULL) {
X		free(gd->gd_body); gd -> gd_body = 0;
X		free((char *) gd); gd = 0;
X	}
X}
END_OF_lib/gffont.c
if test 22029 -ne `wc -c <lib/gffont.c`; then
    echo shar: \"lib/gffont.c\" unpacked with wrong size!
fi
chmod +x lib/gffont.c
# end of overwriting check
fi
if test -f lib/gripes.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/gripes.c\"
else
echo shar: Extracting \"lib/gripes.c\" \(3046 characters\)
sed "s/^X//" >lib/gripes.c <<'END_OF_lib/gripes.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /home/reed/grunwald/Projects/Iptex/lib/RCS/gripes.c,v 1.3 89/02/13 14:31:11 grunwald Exp Locker: grunwald $";
X#endif
X
X/*
X * Common errors (`gripes').
X */
X
X#include <stdio.h>
X#include "types.h"
X
Xstatic char areyousure[] = "Are you sure this is a DVI file?";
X
Xextern	errno;
X
X/*
X * DVI file requests a font it never defined.
X */
XGripeNoSuchFont(n)
X	i32 n;
X{
X
X	error(0, 0, "DVI file wants font %ld, which it never defined", n);
X	error(1, 0, areyousure);
X	/* NOTREACHED */
X}
X
X/*
X * DVI file redefines a font.
X */
XGripeFontAlreadyDefined(n)
X	i32 n;
X{
X
X	error(0, 0, "DVI file redefines font %ld", n);
X	error(1, 0, areyousure);
X	/* NOTREACHED */
X}
X
X/*
X * Unexpected DVI opcode.
X */
XGripeUnexpectedOp(s)
X	char *s;
X{
X
X	error(0, 0, "unexpected %s", s);
X	error(1, 0, areyousure);
X	/* NOTREACHED */
X}
X
X/*
X * Missing DVI opcode.
X */
XGripeMissingOp(s)
X	char *s;
X{
X
X	error(0, 0, "missing %s", s);
X	error(1, 0, areyousure);
X	/* NOTREACHED */
X}
X
X/*
X * Cannot find DVI postamble.
X */
XGripeCannotFindPostamble()
X{
X
X	error(0, 0, "cannot find postamble");
X	error(1, 0, areyousure);
X	/* NOTREACHED */
X}
X
X/*
X * Inconsistent DVI value.
X */
XGripeMismatchedValue(s)
X	char *s;
X{
X
X	error(0, 0, "mismatched %s", s);
X	error(1, 0, areyousure);
X	/* NOTREACHED */
X}
X
X/*
X * Undefined DVI opcode.
X */
XGripeUndefinedOp(n)
X	int n;
X{
X
X	error(0, 0, "undefined DVI opcode %d");
X	error(1, 0, areyousure);
X	/* NOTREACHED */
X}
X
X/*
X * Cannot allocate memory.
X */
XGripeOutOfMemory(n, why)
X	int n;
X	char *why;
X{
X
X	error(1, errno, "ran out of memory allocating %d bytes for %s",
X		n, why);
X	/* NOTREACHED */
X}
X
X/*
X * Cannot get a font.
X * RETURNS TO CALLER
X */
XGripeCannotGetFont(name, mag, dsz, dev, fullname)
X	char *name;
X	i32 mag, dsz;
X	char *dev, *fullname;
X{
X	int e = errno;
X	char scale[40];
X
X	if (mag == dsz)		/* no scaling */
X		scale[0] = 0;
X	else
X		(void) sprintf(scale, " scaled %d",
X			(int) ((double) mag / (double) dsz * 1000.0 + .5));
X
X	error(0, e, "cannot get font %s%s", name, scale);
X	if (fullname)
X		error(0, 0, "(wanted, e.g., \"%s\")", fullname);
X	else {
X		if (dev)
X			error(1, 0, "(there are no fonts for the %s engine!)",
X				dev);
X		else
X			error(1, 0, "(I cannot find any fonts!)");
X		/* NOTREACHED */
X	}
X}
X
X/*
X * Font checksums do not match.
X * RETURNS TO CALLER
X */
XGripeDifferentChecksums(font, tfmsum, fontsum)
X	char *font;
X	i32 tfmsum, fontsum;
X{
X
X	error(0, 0, "\
XWARNING: TeX and I have different checksums for font\n\
X\t\"%s\"\n\
X\tPlease notify your TeX maintainer\n\
X\t(TFM checksum = 0%o, my checksum = 0%o)",
X		font, tfmsum, fontsum);
X}
X
X/*
X * A font, or several fonts, are missing, so no output.
X */
XGripeMissingFontsPreventOutput(n)
X	int n;
X{
X	static char s[2] = {'s', 0};
X
X	error(1, 0, "%d missing font%s prevent%s output (sorry)", n,
X		n > 1 ? s : &s[1], n == 1 ? s : &s[1]);
X	/* NOTREACHED */
X}
END_OF_lib/gripes.c
if test 3046 -ne `wc -c <lib/gripes.c`; then
    echo shar: \"lib/gripes.c\" unpacked with wrong size!
fi
chmod +x lib/gripes.c
# end of overwriting check
fi
if test -f lib/magfactor.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/magfactor.c\"
else
echo shar: Extracting \"lib/magfactor.c\" \(869 characters\)
sed "s/^X//" >lib/magfactor.c <<'END_OF_lib/magfactor.c'
X/*
X * Copyright (c) 1987 University of Maryland Department of Computer Science.
X * All rights reserved.  Permission to copy for any purpose is hereby granted
X * so long as this copyright notice remains intact.
X */
X
X/*
X * Convert a magnification factor to floating point.  This is used in
X * conjunction with the FONT_SLOP stuff to try to get the file names
X * right, and may also be used by DVI reading programs to get slightly
X * more accurate values for (mag/1000.0).
X */
Xdouble
XDMagFactor(mag)
X	int mag;
X{
X
X	switch (mag) {
X
X	case 1095:		/* stephalf */
X		return (1.095445);
X
X	case 1315:		/* stepihalf */
X		return (1.314534);
X
X	case 2074:		/* stepiv */
X		return (2.0736);
X
X	case 2488:		/* stepv */
X		return (2.48832);
X
X	case 2986:		/* stepiv */
X		return (2.985984);
X
X	default:		/* remaining mags have been ok */
X		return ((double) mag / 1000.);
X	}
X	/* NOTREACHED */
X}
END_OF_lib/magfactor.c
if test 869 -ne `wc -c <lib/magfactor.c`; then
    echo shar: \"lib/magfactor.c\" unpacked with wrong size!
fi
chmod +x lib/magfactor.c
# end of overwriting check
fi
echo shar: End of archive 4 \(of 6\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    echo "Now do 'make dviselect'"
    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
--
Skip Montanaro (montanaro at crdgw1.ge.com)



More information about the Alt.sources mailing list