[comp.text.desktop] TeX PK to HP SFP format font conversion

clewis@ecicrl.UUCP (Chris Lewis) (09/17/90)

Since this keeps coming up, and psroff hasn't apparently made it to
comp.sources.unix, here's the utility to convert PK fonts to HP
SFP's that Liam mentions:

Shell archive - cut here -
#!/bin/sh
sed -e 's/^X//' > README <<\!BLOTTO
XThis distribution is that of pk2sfp, which is a subset of
Xthe full psroff 2.0 distribution.  Psroff is a complete package
Xto allow you to use CAT (aka "old") troff with HP Laserjet
Xcompatible printers, Postscript and ditroff output drivers.
XPsroff has a complete set of utilities for handling PK and SFP
Xformat fonts.  Pk2sfp converts PK and SFP fonts into SFP format,
Xwhich can be useful outside of psroff.  Psroff 2.0 is currently
Xsitting in the queue for comp.sources.unix, but since people keep
Xasking for pk2sfp, I've decided to release this subset separately.
XIt also includes pktype, a program for printing the characteristics
Xof PK and SFP fonts.  This distribution corresponds to Proff 2.0,
Xpatchlevel 3, though, patches 1 thru 2 did not touch any of this code,
Xand patch 3 was exclusively to make standalone pk2sfp possible.
XPatch 3 to psroff has not been distributed yet.
X
XTo build: modify defs.h as appropriate and type "make".
X
XThe man page for pk2sfp is uneditted from the psroff distribution
Xand refers to some things that aren't in this release:
X
X    1) pk2ditwid		(creates ditroff-like width tables)
X    2) pk2ps			(converts SFP's and PK's to Postscript fonts)
X    3) "partial" pk2sfp downloading stuff (-p).
X
XIn the interests of saving space, they have been omitted.  If
Xyou need them, pick up the full Psroff release (they need tables
Xbuilt by other major parts of psroff).  Further, you'll see some
Xstrange things that look like ``%%LJF%%''.  If you had the full
Xpsroff release, they'd expand into configuration dependent directory
Xnames, but they're not builtin to any of *this* code.
X
XIf you intend to do any substantial work with PK and SFP fonts,
XI suggest that you get the whole psroff package.
X
XThis distribution is unsupported.  However, psroff 2.0 *is*, and patches
Xto psroff may be applicable to this distribution.
X
XPsroff availability (while it's languishing in comp.sources.unix's queue):
X
X	- gatekeeper.dec.com (16.1.0.2) as anonymous,
X	  file /pub/misc/psroff-2.0.tar.Z,
X	  courtesy Paul Vixie (vixie@wrl.dec.com)
X	- cs.toronto.edu as anonymous,
X	  file pub/psroff.tar.Z,
X	  pub/psroff.patch[1-2].Z,
X	  courtesy Mark Moraes (moraes@cs.toronto.edu)
X
XHave fun!
X
XChris Lewis,
X
Xpsroff-request@eci386 or ...!uunet!utai!lsuc!eci386!psroff-request
!BLOTTO
sed -e 's/^X//' > Makefile <<\!BLOTTO
XCFLAGS = -DALONE
X
Xall:	pk2sfp pktype
X
Xpk2sfp:	pk.o pk2sfp.o debug.o
X	$(CC) -o pk2sfp debug.o pk.o pk2sfp.o
X
Xpktype: pk.o pktype.o debug.o
X	$(CC) -o pktype debug.o pk.o pktype.o
X
Xpk.o pk2sfp.o debug.o:	pk.h defs.h
X
Xclean:
X	rm -f *.o pktype pk2sfp
!BLOTTO
sed -e 's/^X//' > defs.h <<\!BLOTTO
X/*	Copyright 1988, 1989 11:12:33 Chris Lewis
X		All Rights Reserved
X
X    Permission to copy and further distribute is freely given provided
X    this copyright notice remains intact and that this software is not
X    sold for profit.
X
X	Project:	Generic Troff drivers
X	Module:		defs.h 2.5 90/09/17 11:12:33
X	Author: 	Chris Lewis
X	Specs:		Main header file - contains some customization
X */
X
X/*	Official Release and Patch level:	*/
X#define	T2VERSION	"@(#)PSROFF Copyright 90/09/17 Chris Lewis - R2 P3"
X
X#ifndef	LIBDIR
X/*	Don't touch this */
X#define	LIBDIR	"/usr/lib/troff2"
X#endif
X
X/*	Configuration parameters:
X */
X
X#undef	BSD		/* Define if you are a V7 or BSD machine */
X			/* strchr vs. index etc.... */
X
X#define	ATT		/* Define if you are some sort of SIII or SV system */
X
X#undef	BCOPY		/* Define if you don't have memcpy and friends - eg:
X			   oldish BSD systems */
X
X#undef	UNSIGNEDCHAR	/* Define if chars are unsigned on your machine */
X
X/*	The name of a routine that can be called thusly:
X	VFPRINTF(stream, format, ap)
X	FILE *stream;
X	char *format;
X	va_list ap;
X    (eg: you have varargs.h and you have a routine functionally compatible
X    with System V vfprintf.  I think BSD has one too)
X
X    undef if you don't got, and maybe my fakeout will work.
X */
X
X#define VFPRINTF	vfprintf
X
X/* If you have the stand-alone pk2sfp distribution, do not touch
X   anything from here on */
X
X/*	Font width file configuration:
X
X	- If HEADERSIZE defined, use that many bytes as a prefix to the
X	  compiled font width table.  HEADERSIZE 0 is the correct definition
X	  for Xenix and most System V Troffs.  HEADERSIZE=32 works for Ultrix.
X	  HEADERSIZE=0 works properly for Suns (I think).
X	- If COFF is defined instead, use a COFF header on the beginning of
X	  the file.  I personally know of no machine that supports these.
X	- If neither are defined, use a BSD/V7 style a.out.h header, this
X	  is appropriate for V7 and BSD troffs
X
X    The headers I write out do not have anything in them, so some
X    troff's may blow.  Please let me know if they work for you...
X    If you do need the headers, and these doesn't work for you, enable
X    the COMPILE option in gfnttab.  I know of no troff that *needs*
X    COMPILE on.
X
X */
X
X#define	HEADERSIZE 0	/* size of header in bytes */
X#undef	COFF		/* systems using COFF headers */
X
X/* What do your CAT codes look like?
X
X   If BSDHACK defined, the code to magnify the next lead by 64 replaces the
X   codes to set the tilt (tilt used only on 8-font CATs, which most CAT troff
X   programs don't support).
X
X   Both FONT8 and BSDHACK code are *untested*.  FONT8 probably does *not*
X   work.
X */
X
X#undef	BSDHACK		/* Has magnify lead opcode - untested */
X#undef	FONT8		/* 8 Font device - untested */
X#define FONT4		/* Normal 4 font device */
X
X			/* define a command for decompressing an argument
X			   file to stdout - allows you to compress SFP's.
X			   undef if you don't got.  The -d option may be
X			   undocumented, but means decompress.  "-dc"
X			   is equivalent to zcat.  -dc appears to be
X			   in most versions of compress (eg: v3 & v4) */
X#define	COMPRESS	"/usr/lbin/compress -dc"
X
X/*	Some postscript printers don't accept control-D as job termination
X	(DEC scriptwriters for instance).  In that case, define this
X	macro.  Alternately, if you have a proper printer manager that
X	does this sort of stuff, define it too.
X */
X#undef	NOCONTROLD
X
X/*	define if you don't want your Postscript printer talking to you */
X#undef	NOCHATTER
X
X/*	The only advantage to commenting-out one of these is to make the
X	binary executable of troff2?? smaller.
X */
X
X/*	Basic drivers: */
X#define	PS	/* Postscript */
X#define	LJ	/* Laserjet - psroff will not build with this undef'd */
X#define	DT	/* ditroff */
X
X/*	Laserjet driver config: */
X#define	PK	/* enable PK font downloading (needs LJ) */
X
X#define	SFP	/* enable SFP incremental font downloading (needs PK).
X		   You can still use SFP's without this turned on, but
X		   you won't get incremental downloading */
X
X#define	PARTIAL	/* partial (not incremental) font downloading */
X
X#define	INCR	/* enable incremental font downloading (needs PARTIAL) */
X
X#define	MDLF	16	/* Max # downloaded fonts permitted by your laserjet
X			   per *page*.  16 is correct for HPLJ+ and most II's.
X			   IIP's are 32 I think.  Some newer ones have higher
X			   restrictions (don't put this too high even if
X			   your printer supports it, you may run out of
X			   memory) */
X
X#define	PRELOAD	0	/* set to number of LJ fonts permanently
X			   downloaded to printer.  The backend will
X			   make sure that you don't go over the number
X			   of fonts permitted by the printer */
X
X#define	DEBUG		/* Do you want the debugger in?  If you encounter
X			   problems and you want help from me, you'll have
X			   to have this turned on */
X
X#define	OPT		/* Experimental code */
X
X#define	DEFPL  11	/* Default page length (11 inches).
X			   DO NOT change unless you absolutely HAVE to.
X			   You should only need to change this if you
X			   desire your printer to use something different
X			   as default.  If so, you'll HAVE to change
X			   your macro package to agree on the default - RT
X			   owners take note! (the man macros are wrong) */
X
X#define	DEFOFF 0.5	/* Default page offset.  DO NOT change unless you
X			   absolutely HAVE to.  You should only need this
X			   if: your vendor has buggered your macros to
X			   have a different default .po offset (Xenix),
X			   and you aren't using the macro adapter
X			   libraries that come with psroff (eg: you're
X			   using troff2ps directly).  See README/TROUBLE/
X			   psroff(1) (-O vs. -rO options) */
X
X#define	DEFYOFF   0	/* Default page vertical offset.  See README/TROUBLE/
X			   psroff(1) -Y options too */
X
X/*	Edit no more .... */
X
X#define	MAXDLFONTS (MDLF - PRELOAD)	/* # fonts troff2ps can download */
X
X/*	configuration verification */
X
X#if	defined(BSDHACK) && defined(FONT8)
X#include	"BSDHACK and FONT8 cannot be defined at the same time"
X#endif
X#if	defined(FONT4) && defined(FONT8)
X#include	"FONT4 and FONT8 cannot be defined at the same time"
X#endif
X
X#if	!defined(LJ) && defined(PK)
X#include	"Pointless to define PK without LJ"
X#endif
X
X#if	!defined(PK) && (defined(INCR) || defined(PARTIAL))
X#include	"Pointless to define INCR or PARTIAL without PK"
X#endif
X
X#if	defined(INCR) && !defined(PARTIAL)
X#include	"Don't support INCR without PARTIAL"
X#endif
X
X#if	defined(SFP) && !defined(PK)
X#include	"Can't define SFP without PK"
X#endif
X
X#include <stdio.h>
X#include <ctype.h>
X
X#ifdef BSD
X#include <strings.h>
X#define	strchr	index
X#define	strrchr	rindex
X#else
X#include <string.h>
X#endif
X
X#ifdef	BCOPY
X#define	memcpy(to, from, len)	bcopy(from, to, len)
X#define	clrarray(array, len)	bzero(array, len)
X#else
X#define	clrarray(array, len)	memset(array, '\0', len)
X#endif
X
X#ifdef	UNSIGNEDCHAR
X/* Ah heck, and this is probably not ANSI C either... */
X#define	SIGNED(x) (((x)&0x80) ? ((x) - 256) : (x))
X#endif
X
X#define	ESC	0x80
X#define	FLASH	0x00
X#define	CONTROL	0x40
X#define	LEAD	0x60
X#define	SIZE	0x50
X
X#define	DOWN	0
X#define	UP	1
X#define	LOWER	2
X#define	UPPER	3
X#define	FORWARD	4
X#define	BACKWARD 5
X
X#define	TROFFRESOLUTION	432
X
X#define	SPECIAL		/* define if you want to supports special directives */
X#define	FORM		/* define if you want the forms facility */
X
XFILE	*diagFile;
X
X#ifdef DEBUG
X#define	DBP(x)	if (diagFile) dprintf x
Xextern dprintf();
X#else
X#define	DBP(x)
X#endif
X
Xtypedef int(*FUNC)();
X
X#define	FNULL	(FUNC) NULL
X
Xstruct	troff2befont {
X	short	t2b_font;	/* font (troff nomenclature) S=don't change */
X	short	t2b_xc;		/* X-shift */
X	short	t2b_yc;		/* Y-shift */
X	short	t2b_scale;	/* point size scale adjust */
X	char 	*t2b_charseq;	/* character sequence - may include PS */
X};
X
Xstruct cattab {
X    char *ch_name;
X    char ch_set;
X    unsigned char ch_catidx;
X    unsigned char ch_wididx;
X    unsigned char ch_info;	/* used by some auxiliary programs */
X    char *ch_desc;
X};
X
Xstruct backend {
X    char	*bename;
X    FUNC	beprolog,
X		beepilog,
X		beputchar,
X		bepage,
X		befontsel,	/* special function F */
X		beoverlay,	/* special function O */
X		bepassthru,	/* special function P */
X		bexlat,		/* Xlate function */
X		bedraw;		/* Ditroff draw emulation routine */
X    struct troff2befont
X		*bestdfont,	/* standard font translate table */
X		*besymfont;	/* symbol font translate table */
X};
X
X#define	MAXFONTS	50
X
Xstruct fonttable {
X    char *tab[4];
X    long flags;
X#ifdef	INCR
X    struct downmaps *map;
X#endif
X#ifdef	OPT
X    char *widthtable;
X#endif
X};
X
X/*	Symbolic names for tab entries in fonttable	*/
X#define	troffName	tab[0]	/* troff name */
X#define	fontName	tab[1]	/* back-end name (if used) */
X#define	fontSeq		tab[2]	/* sequence to emit to shift to it
X				   lj builtin's mostly */
X
X/*	fontFlags is 16 characters that reflect the state of the font
X	at a particular pointsize - mainly for lj */
X
X/*	Use of flags:
X	s:	unloaded SFP
X	S:	loaded SFP
X	p:	unloaded PK
X	P:	loaded PK
X	n:	non-existant
X	b:	builtin.
X */
X#define	fontFlags	tab[3]
X
X
X
Xextern struct fonttable fonttable[MAXFONTS+1];
Xextern struct fonttable *xlatetable[8];
X
Xstruct backend *be;
X#define	BNULL	(struct backend *) NULL
X
Xextern char *skipblanks();
X
X/*	Common Back-end definitions */
X
X#define	N	(unsigned char) (0xff)	/* Use standard font */
X#define	S	(unsigned char) (0xfe)	/* Use symbol font */
X#define	D	(unsigned char) (0xfd)	/* Draw macro exists - use string directly */
X#define	NTC	(unsigned char) (0xfc)	/* No font/Special flag */
X
X#define	NOC	NULL
X
Xextern int currentPage;
Xextern int pageoffset;
Xextern int pageyoffset;
Xextern int pagelength;
Xextern int pagePending;
X
X#ifdef	OPT
Xextern char *widthtables;
Xextern char *widthptr;
Xextern int optimize;
X#endif
X
Xextern int lastFont, lastPoints;
Xextern int lastYPos, lastXPos, specXPos, specYPos;
Xextern char *progname, *printer, *device;
Xextern char **prologs;
X
Xint metrics;
X
XFILE *libopen();
X
X/*	Encoding format for generating width tables from font files */
X/*	Used by pk2ditwid and friends */
Xstruct enctab {
X    char *e_name;
X    char *e_seq;
X    char e_wid;
X};
X
X/*	Points in an inch */
X#define	POINT	72.27
X
X#define	min(a,b)	((a) < (b) ? (a) : (b))
X#define	max(a,b)	((a) > (b) ? (a) : (b))
X
X/* debug flags */
X#define	D_CAT	1
X#define	D_SPEC	2
X#define	D_CHAR	4
X#define	D_FONT	8
X#define	D_BEND	0x10
X#define	D_PK	0x20
X#define	D_VERB	0x40
X
Xextern int debug;
X
Xextern char username[];
X
Xextern char *mustmalloc();
X
Xextern char *version, *shortversion;
X
X#ifdef	ALONE
X#undef	PARTIAL
X#undef	INCR
X#endif
!BLOTTO
sed -e 's/^X//' > pk.h <<\!BLOTTO
X/*	Copyright 1985, 1986, 1987, 1988 16:47:03 Chris Lewis
X		All Rights Reserved
X
X    Permission to copy and further distribute is freely given provided
X    this copyright notice remains intact and that this software is not
X    sold for profit.
X
X	Project:	Generic Troff drivers
X	Module:		pk.h
X	Author: 	Chris Lewis
X	Specs:		PK format font file description
X */
X
X#ifdef	PK
X
X#define	int8	unsigned char
X#define	PK_ID	89
X#define	PK_xxx1	240
X#define	PK_xxx2	241
X#define	PK_xxx3	242
X#define	PK_xxx4	243
X#define	PK_yyy	244
X#define	PK_post	245
X#define	PK_no_op	246
X#define	PK_pre	247
X
X/*	PK header data */
Xstruct pkp {
X#define	PK_PK	01
X#define	PK_SFP	02
X    long pkp_ds;	/* design size */
X    long pkp_npts;	/* pointsize normalized to 300 dpi */
X    long pkp_res;	/* resolution of this font */
X    long pkp_cs;	/* checksum */
X    long pkp_hppp;	/* Horizontal pixel ratio */
X    long pkp_vppp;	/* Vertical pixel ratio */
X    long pkp_bmax;	/* baseline max */
X    long pkp_dmax;	/* descender max */
X    long pkp_wmax;	/* width max */
X    long pkp_xomax;	/* left offset max */
X    long pkp_kh;	/* kern high */
X    long pkp_kl;	/* kern low */
X    struct pkc *pkp_chars;	/* pointer to character descriptors */
X    struct pkc *pkp_last;	/* pointer to last character descriptor */
X    struct pkc **pkp_list;	/* pointer to sorted list of descriptors */
X    long pkp_num;	/* number of characters */
X    int pkp_symset;	/* symbol set */
X    char pkp_flags;	/* font format */
X    char pkp_style;	/* style */
X    char pkp_sw;	/* stroke weight */
X    char pkp_typeface;	/* typeface */
X};
X
Xstruct pkp *pk_read();
X
Xstruct pkc {
X    long pkc_flag;	/* flag byte */
X    long pkc_dyn_f;	/* dynamic packing byte */
X    long pkc_pl;	/* packet length */
X    long pkc_char;	/* character code */
X    long pkc_tfm;	/* TeX font metrics */
X    long pkc_dx;	/* Horizontal escapement */
X    long pkc_dy;	/* Vertical escapement */
X    long pkc_width;	/* character width of BB */
X    long pkc_height;	/* character height of BB */
X    long pkc_x_off;	/* horizontal offset from upper left pixel to ref. */
X    long pkc_y_off;	/* vertical offset from upper left pixel to ref. */
X    long turnon;	/* used for unravelling bits */
X    long pkc_rlen;	/* actual raster length */
X    int8 *pkc_pkr;	/* actual PK raster */
X    struct ras *pkc_sfpr;	/* SFP raster */
X    struct pkc *pkc_next;	/* next character */
X};
X
Xstruct ras {
X    long ras_width;
X    long ras_height;
X    long ras_bline;
X    long ras_bytes;
X    long ras_xcur;
X    long ras_ycur;
X    int8 *ras_raster;
X};
X
X#define	pow2(x)	(1L << (x))
X
X#define	OUTRES	300
X#endif
!BLOTTO
sed -e 's/^X//' > pk.c <<\!BLOTTO
X/*	Copyright 1990 Chris Lewis
X */
X
X
X#include "defs.h"
X
X#ifdef	PK
X
X#ifndef lint
Xstatic char SCCSid[] = "@(#)pk.c 2.1 Copyright 90/07/18 16:51:38 Chris Lewis";
X#endif
X
X#define	DRAW
X#define	OUTRES	300
X
X#include "pk.h"
X
X#if	defined(PARTIAL)
X#include "pkc.h"
Xstruct needmaps *needmaps = (struct needmaps *) NULL;
X#endif
X
Xextern char *progname;
X
Xstatic FILE *fin;
Xstatic char *filename;	/* name of *current* font being read */
Xextern char *malloc();
X
Xstatic long flag_byte;
Xstatic repeatcount;
Xstatic dyn_f;
X
Xstatic readraster();
X
Xstatic long
Xget1int() { return(getc(fin)); }
X
Xstatic long
Xget2int() {
X    register long c;
X    c = get1int();
X    c = (c<<8) | (0xff & get1int());
X    return(c);
X}
X
Xstatic long
Xget4int() {
X    register long c;
X    c = get2int();
X    c = (c << 16) | (0xffff & get2int());
X    return(c);
X}
X
Xstatic long
Xget3int() {
X    register long c;
X    c = get2int();
X    c = (c << 8) | (0xff & get1int());
X    return(c);
X}
X
X#ifdef VFPRINTF
X#include <varargs.h>
X/* VARARGS */
Xpkmsg(va_alist)
Xva_dcl
X{
X	va_list args;
X	char *fmt;
X
X	va_start(args);
X	fmt = (char *) va_arg(args, char *);
X	VFPRINTF(stderr, fmt, args);
X	va_end(args);
X}
X#else
X/* VARARGS1 ARGSUSED */
Xpkmsg(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
Xchar	*fmt;
Xint	a1, a2, a3, a4, a5, a6, a7, a8, a9, a10; {
X	char buf[BUFSIZ];
X	sprintf(buf, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
X	fprintf(stderr, buf);
X}
X#endif
X
Xstatic
Xskipspecials() {
X    register int i,c;
X    do {
X	flag_byte = getc(fin);
X	if (flag_byte >= 240) {
X	    i = 0;
X	    switch(flag_byte) {
X		case PK_xxx4:
X		    i = (i << 8) + getc(fin);
X		case PK_xxx3:
X		    i = (i << 8) + getc(fin);
X		case PK_xxx2:
X		    i = (i << 8) + getc(fin);
X		case PK_xxx1:
X		    i = (i << 8) + getc(fin);
X		    DBP((D_PK, "PK_xxx%d: ", flag_byte - PK_xxx1 + 1));
X		    while(i--) {
X			c = getc(fin);
X			DBP((D_PK, "%c", c));
X		    }
X		    DBP((D_PK, "\n"));
X		    break;
X		case PK_yyy:
X		    i = get4int();
X		    DBP((D_PK, "Num special: %d\n", i));
X		    break;
X		case PK_post:
X		    DBP((D_PK, "Postamble\n"));
X		    break;
X		case PK_no_op:
X		    DBP((D_PK, "No-op\n"));
X		    break;
X		default:
X		    pkmsg("PK file %s: Unexpected %ld\n", filename,
X			flag_byte);
X		    exit(1);
X	    }
X	}
X    } while (flag_byte >= 240 && flag_byte != PK_post);
X}
X
Xstatic
Xreadschar(p)
Xstruct pkc *p; {
X    p->pkc_pl = get1int() + ((p->pkc_flag&0x3) << 8);
X    p->pkc_char = get1int();
X    p->pkc_tfm = get3int();
X    p->pkc_dx = get1int() * pow2(16);
X    p->pkc_dy = 0;
X    p->pkc_width = get1int();
X    p->pkc_height = get1int();
X    p->pkc_x_off = get1int();
X    p->pkc_y_off = get1int();
X    if (p->pkc_x_off > 127)
X	p->pkc_x_off -= 256;
X    if (p->pkc_y_off > 127)
X	p->pkc_y_off -= 256;
X    p->pkc_rlen = p->pkc_pl - 8;
X    readraster(p);
X}
X
Xstatic
Xreadeschar(p)
Xstruct pkc *p; {
X    p->pkc_pl = get2int() + ((p->pkc_flag&0x3) << 16);
X    p->pkc_char = get1int();
X    p->pkc_tfm = get3int();
X    p->pkc_dx = get2int() * pow2(16);
X    p->pkc_dy = 0;
X    p->pkc_width = get2int();
X    p->pkc_height = get2int();
X    p->pkc_x_off = get2int();
X    p->pkc_y_off = get2int();
X    if (p->pkc_x_off > 32767)
X	p->pkc_x_off -= 65536;
X    if (p->pkc_y_off > 32767)
X	p->pkc_y_off -= 65536;
X    p->pkc_rlen = p->pkc_pl - 13;
X    readraster(p);
X}
X
Xstatic
Xreadlchar(p)
Xstruct pkc *p; {
X    p->pkc_pl = get4int();
X    p->pkc_char = get4int();
X    p->pkc_tfm = get4int();
X    p->pkc_dx = get4int();
X    p->pkc_dy = get4int();
X    p->pkc_width = get4int();
X    p->pkc_height = get4int();
X    p->pkc_x_off = get4int();
X    p->pkc_y_off = get4int();
X    p->pkc_rlen = p->pkc_pl - 28;
X    readraster(p);
X}
X
Xstatic
Xreadraster(p)
Xstruct pkc *p; {
X    p->pkc_pkr = (int8 *) mustmalloc((int) p->pkc_rlen, filename);
X    fread((char *) p->pkc_pkr, 1, (int) p->pkc_rlen, fin);
X}
X
X/*	Read a character sequence from a PK file */
Xstatic struct pkc *
Xrpkc() {
X    register struct pkc *p = (struct pkc *) mustmalloc(sizeof(struct pkc),
X	filename);
X
X    p->pkc_pkr = NULL;
X    p->pkc_sfpr = NULL;
X    p->pkc_flag = flag_byte;
X    p->pkc_dyn_f = p->pkc_flag >> 4;
X    flag_byte &= 0x7;
X
X    if (flag_byte == 7)
X	readlchar(p);
X    else if (flag_byte > 3)
X	readeschar(p);
X    else
X	readschar(p);
X    return(p);
X}
X
X#ifdef	SFP
X/*	Read a character sequence from an SFP */
Xstatic struct pkc *
Xrsfpc() {
X    register struct pkc *p;
X    int len;
X
X    if ((len = getc(fin)) == EOF || len != '\033') {
X	/* HP fonts when loaded often have trailing nulls due to DOS
X	   file padding.  Screech on non-null */
X	if (len && len != EOF)
X	    fprintf(stderr,
X	    "%s: WARNING: trailing garbage in %s, offset %ld, char 0x%02x\n",
X		progname, filename, ftell(fin), len);
X	flag_byte = PK_post;
X	return((struct pkc *) NULL);
X    }
X
X    p = (struct pkc *) mustmalloc(sizeof(struct pkc), filename);
X    p->pkc_pkr = NULL;
X    p->pkc_sfpr = NULL;
X    p->pkc_flag = 0;
X    p->pkc_dyn_f = 0;
X
X    if (fscanf(fin, "*c%ldE", &(p->pkc_char)) != 1) {
X	pkmsg("SFP file: %s, bad/missing SET CHAR CODE, offset: %ld\n",
X	    filename, ftell(fin));
X	exit(1);
X    }
X
X    if (fscanf(fin, "\033(s%dW", &len) != 1 || len < 16) {
X	pkmsg("SFP file: %s, bad/missing/tooshort CHAR DOWNLOAD sequence\n",
X	    filename);
X	exit(1);
X    }
X
X    get4int();	/* skip some garbage */
X    get2int();	/* skip more garbage (actually, orientation & dummy */
X
X    p->pkc_x_off = get2int();
X    if (p->pkc_x_off > 32767)
X	p->pkc_x_off -= 65536;
X    p->pkc_x_off = -p->pkc_x_off;
X    p->pkc_y_off = get2int();
X    if (p->pkc_y_off > 32767)
X	p->pkc_y_off -= 65536;
X    p->pkc_width = get2int();
X    p->pkc_height = get2int();
X    p->pkc_dx = get2int() * pow2(16) / 4;
X
X    p->pkc_sfpr = (struct ras *) mustmalloc(sizeof(struct ras), filename);
X
X    p->pkc_sfpr->ras_height = p->pkc_height;
X    p->pkc_sfpr->ras_width = p->pkc_width;
X    p->pkc_sfpr->ras_bline = (p->pkc_width + 7) / 8;
X    p->pkc_sfpr->ras_bytes = p->pkc_sfpr->ras_height * p->pkc_sfpr->ras_bline;
X    if (p->pkc_sfpr->ras_bytes) {
X	p->pkc_sfpr->ras_raster = (int8 *) mustmalloc((int)
X	    p->pkc_sfpr->ras_bytes, filename);
X
X	fread((char *) p->pkc_sfpr->ras_raster, (int) p->pkc_sfpr->ras_bytes,
X	    1, fin);
X    } else {
X	free((char *) p->pkc_sfpr);
X	p->pkc_sfpr = NULL;
X    }
X
X    return(p);
X}
X#endif
X
Xstatic struct pkc *
Xreadchar(p)
Xstruct pkp *p; {
X    if (p->pkp_flags&PK_PK)
X	return(rpkc());
X#ifdef	SFP
X    else if (p->pkp_flags&PK_SFP)
X	return(rsfpc());
X#endif
X    else
X	return((struct pkc *) NULL);
X}
X
Xstatic int
Xpkccomp(a, b)
Xstruct pkc **a, **b; {
X    if ((*a)->pkc_char < (*b)->pkc_char)
X	return(-1);
X    else
X	return(1);
X    /* can't be equal! */
X}
X
Xstatic
Xrastbit(x,y,r)
Xregister int x, y;
Xregister struct ras *r; {
X    register int bi = y * r->ras_bline + (x >> 3);
X
X    /* You don't really want to uncomment this.... ;-) */
X    /*	printf("x,y,bi: %d,%d,%d\n", x, y, bi);*/
X    return(r->ras_raster[bi] & (0x80 >> (x&7)));
X}
X
Xstatic int8 *rptr;
Xstatic long bitweight;
X
Xgetnyb() {
X    register int8 b;
X    if (!bitweight) {
X	bitweight = 8;
X	rptr++;
X    }
X    b = *rptr;
X    bitweight -= 4;
X#ifdef	VDEBUG
X    DBP((D_PK, "getnyb byte: %x\n", b));
X    DBP((D_PK, "getnyb: %x\n", (b >> bitweight) & 0xf));
X#endif
X    return((b >> bitweight)&0xf);
X}
X
X#ifdef	NEVER
Xgetbit() {
X    register int8 b;
X    if (!bitweight) {
X	bitweight = 8;
X	rptr++;
X    }
X    b = *rptr;
X    bitweight--;
X    return((b>>bitweight)&1);
X}
X#endif
X
X/*	Dumps an ASCII version of the SFP raster r, to line n.
X	Normally only for debugging, but is also used from pktype
X */
X
Xdumpr(r, n)
Xstruct ras *r;
Xint n; {
X    int x, y;
X    if (!diagFile)
X	return;
X    fprintf(diagFile, "\n");
X    for (y = 0; y < n; y++) {
X	fprintf(diagFile, "%3d  ", y);
X	for (x = 0; x < r->ras_width; x++) {
X	    if (rastbit(x, y, r))
X		putc('*', diagFile);
X	    else
X		putc(' ', diagFile);
X	}
X	putc('\n', diagFile);
X    }
X}
X
Xstatic long
Xpkpack(pc,r)
Xregister struct pkc *pc;
Xregister struct ras *r; {
X    long i, j;
X    long pkpackret;
X    i = getnyb();
X    if (i == 0) {
X	do {
X	    j = getnyb();
X	    i++;
X	} while(!j);
X	while(i--)
X	    j = (j << 4) + getnyb();
X	pkpackret = (j - 15 + (13 - dyn_f) * 16 + dyn_f);
X    } else if (i <= dyn_f)
X	pkpackret = (i);
X    else if (i < 14)
X	pkpackret = ((i - dyn_f - 1)*16 + getnyb() + dyn_f + 1);
X    else {
X	if (repeatcount) {
X	    pkmsg("Second repeat count for this row!\n");
X	    exit(1);
X	}
X	if (i == 14)
X	    repeatcount = pkpack(pc,r);
X	else
X	    repeatcount = 1;
X	/*sendout(1, repeatcount, pc, r);*/
X	pkpackret = (pkpack(pc,r));
X    }
X    if (pkpackret < 1) {
X	pkmsg("pkpack returned < 1! (%s)", filename);
X	exit(1);
X    }
X    return(pkpackret);
X}
X
Xstatic
Xgetpbits(pc, r)
Xregister struct pkc *pc;
Xregister struct ras *r; {
X    register int h_bit		= pc->pkc_width,
X		 count,
X		 turnon;
X    turnon = pc->pkc_flag&0x8;
X    dyn_f = pc->pkc_dyn_f;
X    repeatcount = 0;
X    r->ras_xcur = r->ras_ycur = 0;
X    while(r->ras_ycur < pc->pkc_height) {
X	count = pkpack(pc,r);
X	while(count > 0) {
X	    if (count >= h_bit) {
X		count -= h_bit;
X		while(h_bit--) {
X		    if (turnon)
X			r->ras_raster[r->ras_ycur*r->ras_bline + (r->ras_xcur>>3)]
X			    |= (0x80 >> (r->ras_xcur&7));
X		    r->ras_xcur++;
X		}
X		r->ras_ycur++;
X		r->ras_xcur = 0;
X		while(repeatcount --) {
X#ifdef	VDEBUG
X		    DBP((D_PK, "Copy line %d to %d\n", r->ras_ycur,
X			r->ras_ycur-1));
X#endif
X		    memcpy((char*)&(r->ras_raster[r->ras_ycur * r->ras_bline]),
X			   (char*)&(r->ras_raster[(r->ras_ycur - 1) *
X			       r->ras_bline]),
X			   (int) r->ras_bline);
X		    r->ras_ycur++;
X		}
X		repeatcount = 0;
X		h_bit = pc->pkc_width;
X	    } else {
X		h_bit -= count;
X		while(count--) {
X		    if (turnon)
X			r->ras_raster[r->ras_ycur*r->ras_bline +
X			    (r->ras_xcur>>3)] |= (0x80 >> (r->ras_xcur&7));
X		    r->ras_xcur++;
X		}
X		count = 0;
X	    }
X	}
X	turnon = !turnon;
X    }
X    if (r->ras_ycur != pc->pkc_height ||
X	h_bit != pc->pkc_width)
X	pkmsg("Bad bit somehow (%s)\n", filename);
X}
X
Xstatic
Xgetrbits(pc, r)
Xregister struct pkc *pc;
Xregister struct ras *r; {
X    register int x, y;
X    register int bit = 0;
X    for (y = 0; y < pc->pkc_height; y++) {
X	for (x = 0; x < pc->pkc_width; x++) {
X	    if (pc->pkc_pkr[bit >> 3] & (0x80 >> (bit&7)))
X		r->ras_raster[y*r->ras_bline + (x>>3)] |= (0x80 >> (x&7));
X	    bit++;
X	}
X    }
X}
X
X/*	Convert a PK raster to an unpacked SFP version.
X	(If there's already an SFP version, it's returned instead)
X */
Xstruct ras *
Xpkrast(pc)
Xstruct pkc *pc; {
X    register struct ras *r;
X    if (pc->pkc_sfpr)
X	return(pc->pkc_sfpr);
X    if (!pc->pkc_rlen)
X	return(NULL);
X
X    pc->pkc_sfpr = r = (struct ras *) mustmalloc(sizeof(struct ras),
X	filename);
X
X    r->ras_height = pc->pkc_height;
X    r->ras_width = pc->pkc_width;
X    r->ras_bline = (pc->pkc_width + 7) / 8;
X    r->ras_bytes = r->ras_height * r->ras_bline;
X    r->ras_raster = (int8 *) mustmalloc((int) r->ras_bytes, filename);
X
X    /* initialize bit unpackers */
X    rptr = pc->pkc_pkr;
X    bitweight = 8;
X
X    /* calculate bits here...*/
X    if (pc->pkc_dyn_f == 14)
X	getrbits(pc, r);
X    else
X	getpbits(pc, r);
X    return(r);
X}
X
X/*	Read a PK font file header */
Xstatic struct pkp *
Xpk_rpk(p)
Xregister struct pkp *p; {
X    register int i,c;
X
X    if (getc(fin) != 89) {
X	pkmsg("PK file %s: Wrong version of packed file!\n", filename);
X	exit(1);
X    }
X    i = getc(fin);
X    if (i > 0) {
X	DBP((D_PK, "PKVersion: "));
X	while (i--) {
X	    c = getc(fin);
X	    DBP((D_PK, "%c", c));
X	}
X	DBP((D_PK, "\n"));
X    }
X    p->pkp_bmax = 0;
X    p->pkp_dmax = 0;
X    p->pkp_wmax = 0;
X    p->pkp_xomax = 0;
X    p->pkp_ds = get4int();
X    p->pkp_cs = get4int();
X    p->pkp_hppp = get4int();
X    p->pkp_vppp = get4int();
X
X    if (p->pkp_hppp != p->pkp_vppp)
X	pkmsg("PK file %s: Warning aspect ratio not 1:1\n", filename);
X    p->pkp_res = (double) p->pkp_hppp * POINT / pow2(16) + .5;
X    p->pkp_npts = ((double) p->pkp_ds / pow2(20)) *
X	((double) p->pkp_res / OUTRES) + .5;
X    p->pkp_chars = (struct pkc *) NULL;
X    p->pkp_last = (struct pkc *) NULL;
X    p->pkp_num = 0;
X    p->pkp_list = (struct pkc **) NULL;
X
X    /*	Try to guess symset, style, stroke weight and typeface
X	These aren't particularly important, but it assists the LJ
X	if it's trying to select one of these via characteristic.
X	This will only work if the file name reflects the Troff name,
X	according to the following conventions:
X
X	filename: {<path>/}troffname.pointsize.[pk|sfp]
X
X	All ROMAN8 encodings unless MATH8.
X	All 0 strokeweight, unless Bold.
X	All upright, unless Italic
X	All Roman typeface, unless otherwise specified
X
X		R	: Normal Roman
X		I	: Italic
X		B	: Bold
X		S	: MATH8 Symbol
X		X	: Bold italic
X		.X	: <typeface> Bold italic
X		.I	: <typeface> Italic
X		.B	: <typeface> Bold
X		.R	: <typeface> Normal
X		H or H.	: Helvetica typeface
X		C or C.	: Courier typeface
X			  typefaces should be extended.
X     */
X
X    {
X	register char *fp;
X	register int char1, char2, italic, bold, bolditalic, onechar;
X
X	fp = strrchr(filename, '/');
X	if (!fp)
X	    fp = filename;
X	else
X	    fp++;
X
X	/* Default settings */
X	p->pkp_symset = (8 << 5) - 64 + 'U';	/* ROMAN 8 */
X	p->pkp_style = 0;	/* upright */
X	p->pkp_sw = 0;		/* stroke 0 */
X	p->pkp_typeface = 5;	/* typeface Roman */
X
X	char1 = *fp++;
X	onechar = (*fp == '.');
X
X	if (char1 == 'S' && onechar)
X	    p->pkp_symset = (8 << 5) - 64 + 'M';	/* MATH 8 */
X	else {
X
X	    char2 = *fp;
X
X	    italic = ((onechar && char1 == 'I') || char2 == 'I');
X	    bold = ((onechar && char1 == 'B') || char2 == 'B');
X	    bolditalic = ((onechar && char1 == 'X') || char2 == 'X');
X
X	    if (bold || bolditalic)
X		p->pkp_sw = 3;
X
X	    if (italic || bolditalic)
X		p->pkp_style = 1;
X
X	    /* This should be extended, but I don't have a good feeling
X	       for troff typeface -> HPLJ nomenclature */
X	    switch(char1) {
X		case 'H':
X		    p->pkp_typeface = 4;	/* Helvetica */
X		    break;
X		case 'C':
X		    p->pkp_typeface = 3;	/* Courier */
X		    break;
X		/* more? */
X	    }
X	}
X    }
X
X    return(p);
X}
X
X#ifdef	SFP
X
X/*	Read an SFP header and convert it into the PK internal structure.
X */
Xstatic struct pkp *
Xpk_rsfp(p)
Xregister struct pkp *p; {
X    register int c;
X    int len;
X
X    if (fscanf(fin, ")s%dW", &len) != 1) {
X	pkmsg("SFP file %s: Bad CREATE FONT sequence\n", filename);
X	exit(1);
X    }
X
X    if (len < 26) {
X	pkmsg("SFP file %s: CREATE FONT sequence too short (%d)\n",
X	    filename, len);
X	exit(1);
X    }
X
X    get2int();	/* 26 */
X    get1int();	/* 0 */
X    get1int();	/* 0 or 1 - forced 1 anyways */
X    get2int();	/* dummy */
X
X    p->pkp_bmax = get2int();	/* baseline */
X    p->pkp_wmax = get2int();	/* cell width */
X    p->pkp_dmax = get2int() - p->pkp_bmax;	/* cell height */
X
X    get1int();	/* 0 port, 1 land - forced 0 */
X    get1int();	/* fixed/proportional - forced proportional */
X
X    p->pkp_symset = get2int();
X
X    get2int();		/* pitch - we calculate this from height */
X    c = get2int();	/* retrieved *height* */
X    p->pkp_npts = c * POINT / (OUTRES*4) + .5;
X
X    get2int();	/* dummy */
X    get1int();	/* dummy */
X
X    p->pkp_style = get1int();
X    p->pkp_sw = get1int();
X    p->pkp_typeface = get1int();
X
X    p->pkp_xomax = 0;
X
X    /* These are simulated so that the PK handlers can figure the font out */
X    p->pkp_ds = p->pkp_npts * pow2(20);
X    p->pkp_cs = 0;
X    p->pkp_hppp = OUTRES * pow2(16) / POINT;
X    p->pkp_vppp = OUTRES * pow2(16) / POINT;
X    p->pkp_res = (double) p->pkp_hppp * POINT / pow2(16) + .5;
X
X    p->pkp_chars = (struct pkc *) NULL;
X    p->pkp_last = (struct pkc *) NULL;
X    p->pkp_num = 0;
X    p->pkp_list = (struct pkc **) NULL;
X
X
X    len -= 26;
X    while(len--)
X	getc(fin);
X    return(p);
X}
X#endif
X
Xstatic struct pkp *
Xreadhead() {
X    register struct pkp *p = (struct pkp *) mustmalloc(sizeof(struct pkp),
X	filename);
X    switch(getc(fin)) {
X	case PK_pre:
X	    p->pkp_flags |= PK_PK;
X	    return(pk_rpk(p));
X#ifdef	SFP
X	case 0x1b:
X	    p->pkp_flags |= PK_SFP;
X	    flag_byte = 0;
X	    return(pk_rsfp(p));
X#endif
X	default:
X	    fprintf(stderr, "PK file: %s don't know what it is!\n",
X		filename);
X	    exit(1);
X    }
X    /*NOTREACHED*/
X}
X
Xpk_destroy(p)
Xregister struct pkp *p; {
X    register struct pkc *pc, *opc;
X    for (pc = p->pkp_chars; pc;) {
X	if (pc->pkc_pkr)
X	    free((char *) pc->pkc_pkr);
X
X	if (pc->pkc_sfpr) {
X	    free((char *) pc->pkc_sfpr->ras_raster);
X	    free((char *) pc->pkc_sfpr);
X	}
X
X	opc = pc;
X	pc = opc->pkc_next;
X	free((char *) opc);
X    }
X    if (p->pkp_list)
X	free((char *) p->pkp_list);
X    free((char *) p);
X}
X
Xstruct pkp *
Xpk_read(file, fontcode)
Xchar *file; int fontcode; {
X    register struct pkp *p;
X    register struct pkc *pc, **pcp;
X#ifdef	COMPRESS
X    int compressed = 0;
X#endif
X    fin = (FILE *) NULL;
X    if (access(filename = file, 4) == 0)
X	fin = fopen(filename, "r");
X#ifdef	COMPRESS
X    else {
X	char buf[1024];
X	strcpy(buf, file);
X	strcat(buf, ".Z");
X	if (access(buf, 4) == 0) {
X	    sprintf(buf, "%s %s.Z", COMPRESS, file);
X	    fin = popen(buf, "r");
X	    compressed = 1;
X	}
X    }
X#endif
X    if (!fin) {
X	pkmsg("Cannot open PK/SFP file %s\n", file);
X	exit(1);
X    }
X    p = readhead();
X    if (p->pkp_flags&PK_PK)
X	skipspecials();
X
X    while ((flag_byte != PK_post) && (pc = readchar(p))) {
X	DBP((D_VERB, "type: %s: %d\n", p->pkp_flags&PK_PK? "PK": "SFP",
X	    pc->pkc_char));
X#ifdef	PARTIAL
X	if (!needchar(fontcode, pc->pkc_char)) {
X	    DBP((D_FONT|D_PK, "Dropping char %02x from load\n", pc->pkc_char));
X
X	    if (pc->pkc_pkr) {
X		free((char *) pc->pkc_pkr);
X		pc->pkc_pkr = (int8 *) NULL;
X	    }
X
X	    if (pc->pkc_sfpr) {
X		free((char *) pc->pkc_sfpr->ras_raster);
X		free((char *) pc->pkc_sfpr);
X		pc->pkc_sfpr = (struct ras *) NULL;
X	    }
X
X	    free((char *) pc);
X	    if (p->pkp_flags&PK_PK)
X		skipspecials();
X	    continue;
X	}
X#endif
X	DBP((D_FONT|D_PK, "Loading char %02x\n", pc->pkc_char));
X	p->pkp_num++;
X	pc->pkc_next = (struct pkc *) NULL;
X	if (!p->pkp_chars)
X	    p->pkp_chars = pc;
X	if (p->pkp_last)
X	    p->pkp_last->pkc_next = pc;
X	p->pkp_last = pc;
X	if (p->pkp_flags&PK_PK) {
X	    p->pkp_bmax = max(p->pkp_bmax, pc->pkc_y_off);
X	    p->pkp_dmax = max(p->pkp_dmax, pc->pkc_height - pc->pkc_y_off);
X	    p->pkp_wmax = max(p->pkp_wmax, pc->pkc_width - pc->pkc_x_off);
X	}
X	p->pkp_xomax = min(p->pkp_xomax, pc->pkc_x_off);
X	if (pc->pkc_char == 'a') {
X	    p->pkp_kh = pc->pkc_y_off;
X	    p->pkp_kl = pc->pkc_y_off - pc->pkc_height;
X	}
X	if (p->pkp_flags&PK_PK)
X	    skipspecials();
X    }
X    DBP((D_FONT|D_PK, "End of font\n"));
X#ifdef	COMPRESS
X    if (compressed) {
X	if (pclose(fin)) {
X	    pkmsg("Decompression of %s failed\n", file);
X	    exit(1);
X	}
X    } else
X#endif
X	fclose(fin);
X    pcp = p->pkp_list = (struct pkc **)
X	mustmalloc((int) (p->pkp_num * sizeof(struct pkc *)), filename);
X    for (pc = p->pkp_chars; pc; pc = pc->pkc_next)
X	*pcp++ = pc;
X    qsort(p->pkp_list, (unsigned) p->pkp_num, sizeof(struct pkc *), pkccomp);
X    return(p);
X}
X
X/*	Emit routines */
X
X/*	Emit a font descriptor in SFP format */
Xepk_desc(p, sfp)
Xregister struct pkp *p;
XFILE *sfp; {
X
X    fprintf(sfp, "\033)s26W");
X    fputshort(26, sfp);
X    fputc(0, sfp);
X    fputc(1, sfp);	/* font type 1 (33-127 && 160-255 printable) */
X    fputshort(0, sfp);
X    fputshort(p->pkp_bmax, sfp);	/* baseline position */
X    fputshort(p->pkp_wmax, sfp);	/* cell width */
X    fputshort(p->pkp_bmax + p->pkp_dmax, sfp);	/* cell height */
X    fputc(0, sfp);	/* portrait */
X    fputc(1, sfp);	/* proportional */
X
X    fputshort((long) p->pkp_symset, sfp);
X
X    fputshort((long) (OUTRES * p->pkp_npts * 4) / 120, sfp);
X    fputshort((long) (p->pkp_npts * (OUTRES / POINT) * 4), sfp);
X    fputshort(0, sfp);
X    fputc(0, sfp);
X    fputc(p->pkp_style, sfp);
X    fputc(p->pkp_sw, sfp);
X    fputc(p->pkp_typeface, sfp);
X
X}
X
Xfputshort(val, f)
XFILE *f;
Xlong val; {
X    fputc(((int) val >> 8) & 0xff, f);
X    fputc((int) val & 0xff, f);
X}
X
X
X/*	Emit a character descriptor in SFP format.
X	Notes: if this is a PK font, the PK raster is converted
X	to SFP format and dumpped.  If the font was originally
X	SFP format, it's dumpped directly.  In either event, epkc_desc
X	deletes the SFP raster *and* the PK raster (if the character
X	has one), meaning that once this routine has emitted a character,
X	you can't emit it again!  Which is why pkc's pkflush completely
X	destroys the font.  Why?  Well, SFP's can get rather large, and
X	it seems reasonable to get rid of them as quickly as possible.
X
X	Returns number of bytes emitted.
X */
Xepkc_desc(pc, sfp)
Xregister struct pkc *pc;
Xregister FILE *sfp; {
X    register struct ras *r;
X
X    if (!pc->pkc_pkr && !pc->pkc_sfpr) {
X	fprintf(stderr, "%s: already downloaded %02x\n", pc->pkc_char);
X	return(0);
X    }
X
X    /* Emit SET CHARACTER sequence */
X    fprintf(sfp, "\033*c%dE", pc->pkc_char);
X
X    /* Emit DOWNLOAD CHARACTER sequence */
X    fprintf(sfp, "\033(s%dW", 16 + ((pc->pkc_width + 7) / 8) *
X    pc->pkc_height);
X    fputc(4, sfp);
X    fputc(0, sfp);
X    fputc(14, sfp);
X    fputc(1, sfp);
X    fputc(0, sfp);		/* portrait */
X    fputc(0, sfp);
X    fputshort(-pc->pkc_x_off, sfp);
X    fputshort(pc->pkc_y_off, sfp);
X    fputshort(pc->pkc_width, sfp);
X    fputshort(pc->pkc_height, sfp);
X    fputshort(pc->pkc_dx * 4 / pow2(16), sfp);
X    r = pkrast(pc);
X
X    if (pc->pkc_pkr)
X	free((char *) pc->pkc_pkr);
X    pc->pkc_pkr = (int8 *) NULL;
X
X    if (r) {
X#ifdef	VDEBUG
X	dumpr(r, r->ras_ycur);
X#endif
X	fwrite((char *) r->ras_raster, 1, (int) ((pc->pkc_width + 7) / 8) *
X	    (int) pc->pkc_height, sfp);
X	free((char *) r->ras_raster);
X	free((char *) r);
X    }
X    pc->pkc_sfpr = (struct ras *) NULL;
X    return(((pc->pkc_width + 7) / 8) * pc->pkc_height);
X}
X#endif
!BLOTTO
sed -e 's/^X//' > debug.c <<\!BLOTTO
X#include "defs.h"
X
X#ifndef	lint
Xstatic char SCCSid[] =
X    "@(#)debug.c: 2.2 Copyright 90/08/08 13:14:09 Chris Lewis";
X#endif
X
X#ifdef	DEBUG
X
Xint debug = 0;
X
X#define	D_CAT	1
X#define	D_SPEC	2
X#define	D_CHAR	4
X#define	D_FONT	8
X#define	D_BEND	0x10
X#define	D_PK	0x20
X#define	D_VERB	0x40
X#define	D_FLSH	0x80
X
Xstruct dbm {
X    char req;
X    int bit;
X} dbm[] = {
X    {'c', D_CAT},
X    {'s', D_SPEC},
X    {'C', D_CHAR},
X    {'f', D_FONT},
X    {'F', D_FLSH},
X    {'b', D_BEND},
X    {'p', D_PK},
X    {'v', D_VERB},
X    {'A', ~0},
X    {0, 0}
X};
X
Xsetdebug(str, df)
Xchar *str, *df; {
X    register struct dbm *d;
X    for(;*str; str++) {
X	for(d = dbm; d->req; d++)
X	    if (d->req == *str) {
X		debug |= d->bit;
X		break;
X	    }
X	if (!d->req) {
X	    fprintf(stderr, "%s: don't understand %c debug flag\n",
X		progname, *str);
X	    exit(1);
X	}
X    }
X
X    if (debug) {
X	if (!(diagFile = fopen(df, "w"))) {
X	    fprintf(stderr, "%s: Cannot open diagnostics file (%s)\n",
X		progname, df);
X	    exit(1);
X	}
X	fprintf(diagFile, "Debug flags: %x\n", debug);
X    }
X}
X
X#ifdef VFPRINTF
X#include <varargs.h>
X/* VARARGS */
Xdprintf(level, va_alist)
Xint level;
Xva_dcl
X{
X	va_list args;
X	char *fmt;
X
X	if (!(debug&level))
X	    return;
X
X	va_start(args);
X	fmt = va_arg(args, char *);
X	VFPRINTF(diagFile, fmt, args);
X	va_end(args);
X	if (debug&D_FLSH)
X	    fflush(diagFile);
X}
X#else
X/* VARARGS1 ARGSUSED */
Xdprintf(level, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
Xint level;
Xchar	*fmt;
Xint	a1, a2, a3, a4, a5, a6, a7, a8, a9, a10; {
X	char buf[BUFSIZ];
X
X	if (!(debug&level))
X	    return;
X
X	sprintf(buf, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
X	fprintf(diagFile, buf);
X	if (debug&D_FLSH)
X	    fflush(diagFile);
X}
X#endif
X#endif
X
Xchar *
Xmustmalloc(n, msg)
Xint n;
Xchar *msg; {
X    extern char *malloc();
X    register char *p = malloc((unsigned) n);
X    if (!p) {
X	fprintf(stderr, "%s: Out of space! (requesting %d bytes, key: %s)\n",
X	    progname, n, msg);
X	exit(1);
X    }
X    clrarray(p, n);
X    return(p);
X}
X
X#ifdef	BCOPY
X/*	"slowish" routines when you don't have memcpy and friends
X */
Xbcopy(from, to, len)
Xregister char *from, *to;
Xregister int n; {
X    while(n--)
X	*to++ = *from++;
X}
Xbzero(array, len)
Xregister char *array;
Xregister int len; {
X    while(n--)
X	*array++ = '\0';
X}
X#endif
!BLOTTO
-- 
Chris Lewis, Phone: (416)-294-9253
UUCP: uunet!utai!lsuc!ecicrl!clewis
Moderator of the Ferret Mailing List (ferret-request@eci386)
Psroff mailing list (psroff-request@eci386)