summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipsk/output.c
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
committerKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
commit487ca4806cc046076293cf6cc5fbba0db282bac7 (patch)
tree847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/dvipsk/output.c
parenta3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff)
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvipsk/output.c')
-rw-r--r--Build/source/texk/dvipsk/output.c1580
1 files changed, 1580 insertions, 0 deletions
diff --git a/Build/source/texk/dvipsk/output.c b/Build/source/texk/dvipsk/output.c
new file mode 100644
index 00000000000..aae043849bd
--- /dev/null
+++ b/Build/source/texk/dvipsk/output.c
@@ -0,0 +1,1580 @@
+/*
+ * These routines do most of the communicating with the printer.
+ *
+ * LINELENGTH tells the maximum line length to send out. It's been
+ * reduced to 72 because sometimes PostScript files are included in
+ * mail messages and many mailers mutilate longer lines.
+ */
+#define LINELENGTH (72)
+#include "dvips.h" /* The copyright notice in that file is included too! */
+#include <ctype.h>
+#include <stdlib.h>
+
+#ifdef OS2
+#ifdef _MSC_VER
+#define popen(pcmd, pmode) _popen(pcmd, pmode)
+#define pclose(pstream) _pclose(pstream)
+#endif
+#endif
+
+#ifdef __DJGPP__
+#include <unistd.h> /* for `isatty' */
+#endif
+
+/*
+ * The external routines called here:
+ */
+#include "protos.h"
+
+/*
+ * These are the external variables used by these routines.
+ */
+extern integer hh, vv ;
+extern fontdesctype *curfnt ;
+extern FILE *bitfile ;
+extern char *oname ;
+extern Boolean secure ;
+extern Boolean reverse ;
+extern Boolean removecomments ;
+extern Boolean sendcontrolD, disablecomments, multiplesects ;
+extern Boolean shiftlowchars ;
+extern Boolean usesPSfonts, headers_off ;
+extern Boolean safetyenclose ;
+extern Boolean cropmarks ;
+extern Boolean tryepsf ;
+extern Boolean compressed ;
+extern Boolean sepfiles ;
+extern int numcopies ;
+extern int collatedcopies ;
+extern integer pagecopies ;
+extern int totalpages ;
+extern integer pagenum ;
+extern Boolean manualfeed ;
+extern int landscape ;
+extern int quiet ;
+extern int prettycolumn ;
+extern int actualdpi, vactualdpi ;
+extern char *iname, *nextstring ;
+extern char *paperfmt ;
+#ifndef KPATHSEA
+extern char *headerpath ;
+extern char *figpath ;
+#endif
+extern char errbuf[] ;
+extern shalfword linepos ;
+extern struct header_list *ps_fonts_used ;
+extern char banner[], banner2[] ;
+extern int gargc ;
+extern char **gargv ;
+extern struct papsiz *papsizes ;
+extern integer hpapersize, vpapersize ;
+char preamblecomment[256] ; /* usually "TeX output ..." */
+#ifdef HPS
+extern Boolean noprocset, HPS_FLAG ;
+#endif
+/*
+ * We need a few statics to take care of things.
+ */
+static integer rhh, rvv ;
+static int instring ;
+static Boolean lastspecial = 1 ;
+static shalfword d ;
+static Boolean popened = 0 ;
+int lastfont ; /* exported to dospecial to fix rotate.tex problem */
+static void chrcmd P1H(char c); /* just a forward declaration */
+static char strbuffer[LINELENGTH + 20], *strbp = strbuffer ;
+static struct papsiz *finpapsiz ;
+static struct papsiz defpapsiz = {
+ 0, 40258437L, 52099154L, "letter", ""
+} ;
+#ifdef CREATIONDATE
+#if (!defined(VMS) && !defined(MSDOS) && !(defined(OS2) && defined(_MSC_VER)) && !defined(ATARIST))
+ /* VAXC/MSDOS don't like/need this !! */
+#include <sys/types.h>
+#include <sys/time.h> /* time(), at least on BSD Unix */
+#endif
+#include <time.h> /* asctime() and localtime(), at least on BSD Unix */
+static time_t jobtime;
+#endif
+/*
+ * This routine copies a file down the pipe. Search path uses the
+ * header path.
+ *
+ * We add code to handle the case of MS-DOS font files.
+ *
+ * Format: 80 {01,02} four byte length in littleendian order data
+ * repeated possibly multiple times.
+ */
+static char *hxdata = "0123456789ABCDEF" ;
+static int infigure ;
+extern char *infont ;
+static char possibleDSCLine[81],
+ *dscLinePointer = possibleDSCLine, *dscLineEnd = possibleDSCLine + 80 ;
+void
+copyfile_general P2C(char *, s, struct header_list *, cur_header)
+{
+ FILE *f = NULL ;
+ int c, prevc = '\n' ;
+ long len ;
+ /* begin DOS EPS code */
+ int doseps = 0;
+ unsigned long dosepsbegin, dosepsend = 0;
+ int removingBytes = 0 ;
+ char *scanForEnd = 0 ;
+ /* end DOS EPS code */
+#ifdef VMCMS
+ register char *lastdirsep ;
+ register char *trunc_s ;
+ trunc_s = s ;
+#endif
+#ifdef MVSXA
+ register char *lastdirsep ;
+ register char *trunc_s ;
+ trunc_s = s ;
+#endif
+ dscLinePointer = possibleDSCLine ;
+
+ switch (infigure) {
+ case 1:
+/*
+ * Look in headerpath too, just in case. This allows common header
+ * or figure files to be installed in the .../ps directory.
+ */
+ f = search(figpath, s, READBIN) ;
+ if (f == 0)
+ f = search(headerpath, s, READBIN) ;
+#ifdef VMCMS
+ lastdirsep = strrchr(s, '/') ;
+ if ( NULL != lastdirsep ) trunc_s = lastdirsep + 1 ;
+ (void)sprintf(errbuf,
+ "Couldn't find figure file %s with CMS name %s; continuing", s, trunc_s) ;
+#else
+#ifdef MVSXA
+ lastdirsep = strrchr(s, '/') ;
+ if ( NULL != lastdirsep ) trunc_s = lastdirsep + 1 ;
+ (void)sprintf(errbuf,
+ "Couldn't find figure file %s with MVS name %s; continuing", s, trunc_s) ;
+#else
+ (void)sprintf(errbuf, "Could not find figure file %s; continuing", s) ;
+#endif
+#endif
+ break ;
+#ifndef VMCMS
+#ifndef MVSXA
+#ifndef VMS
+#if !defined(MSDOS) || defined(__DJGPP__)
+#ifndef ATARIST
+#ifndef __THINK__
+ case 2:
+#ifdef SECURE
+ (void)sprintf(errbuf, "<%s>: Tick filename execution disabled", s) ;
+#else
+#ifdef OS2
+ if (_osmode == OS2_MODE) {
+#endif
+ if (secure == 0) {
+ (void)sprintf(errbuf, "Execution of <%s> failed ", s) ;
+ f = popen(s, "r") ;
+ if (f != 0)
+ SET_BINARY(fileno(f)) ;
+ }
+ else {
+ (void)sprintf(errbuf,"Secure mode is %d so execute <%s> will not run", secure,s) ;
+ }
+#ifdef OS2
+ }
+#endif
+#endif
+ break;
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+ default:
+ f = search(headerpath, s, READBIN) ;
+ if(cur_header && (cur_header->precode || cur_header->postcode)) {
+ if(f==NULL)
+ f = search(figpath, s, READBIN) ;
+ }
+ (void)sprintf(errbuf, "! Could not find header file %s", s) ;
+ break ;
+ }
+ if (f==NULL)
+ error(errbuf) ;
+ else {
+ if (! quiet) {
+ if (strlen(s) + prettycolumn > STDOUTSIZE) {
+ fprintf(stderr, "\n") ;
+ prettycolumn = 0 ;
+ }
+#ifdef VMCMS
+ (void)fprintf(stderr, "<%s>", trunc_s) ;
+#else
+#ifdef MVSXA
+ (void)fprintf(stderr, "<%s>", trunc_s) ;
+#else
+ (void)fprintf(stderr, "<%s>", s) ;
+#endif
+#endif
+ (void)fflush(stderr) ;
+ prettycolumn += 2 + strlen(s) ;
+ }
+ if (linepos != 0)
+ (void)putc('\n', bitfile) ;
+/*
+ * Suggested by Andrew Trevorrow; don't ever BeginFont a file ending in .enc
+ */
+ if (infont && strstr(s,".enc"))
+ infont = 0 ;
+ if (! disablecomments) {
+ if (infigure)
+ (void)fprintf(bitfile, "%%%%BeginDocument: %s\n", s) ;
+ else if (infont)
+ (void)fprintf(bitfile, "%%%%BeginFont: %s\n", infont) ;
+#ifdef HPS
+ else if (noprocset) {}
+#endif
+ else
+ (void)fprintf(bitfile, "%%%%BeginProcSet: %s 0 0\n", s) ;
+ }
+ if (cur_header && cur_header->precode) {
+ (void)fprintf(bitfile, "%s\n", cur_header->precode) ;
+ free(cur_header->precode) ;
+ }
+ c = getc(f) ;
+ if (c == 0x80) {
+ while (1) {
+ c = getc(f) ;
+ switch(c) {
+case 1:
+case 2:
+ len = getc(f) ;
+ len += getc(f) * 256L ;
+ len += getc(f) * 65536L ;
+ len += getc(f) * 256L * 65536 ;
+ if (c == 1) {
+ while (len > 0) {
+ c = getc(f) ;
+ if (c == EOF) {
+ error("premature EOF in MS-DOS font file") ;
+ len = 0 ;
+ } else {
+ if (c == '\r') { /* Mac- or DOS-style text file */
+ (void)putc('\n', bitfile) ;
+ if ((c = getc(f)) == '\n') /* DOS-style text */
+ len--; /* consume, but don't generate NL */
+ else
+ ungetc(c, f);
+ }
+ else
+ (void)putc(c, bitfile) ;
+ len-- ;
+ }
+ }
+ } else {
+ putc('\n', bitfile) ;
+ prevc = 0 ;
+ while (len > 0) {
+ c = getc(f) ;
+ if (c == EOF) {
+ error("premature EOF in MS-DOS font file") ;
+ len = 0 ;
+ } else {
+ (void)putc(hxdata[c >> 4], bitfile) ;
+ (void)putc(hxdata[c & 15], bitfile) ;
+ len-- ;
+ prevc += 2 ;
+ if (prevc >= 76) {
+ putc('\n', bitfile) ;
+ prevc = 0 ;
+ }
+ }
+ }
+ }
+ break ;
+case 3:
+ goto msdosdone ;
+default:
+ error("saw type other than 1, 2, or 3 in MS-DOS font file") ;
+ break ;
+ }
+ c = getc(f) ;
+ if (c == EOF)
+ break ;
+ if (c != 0x80) {
+ error("saw non-MSDOS header in MSDOS font file") ;
+ break ;
+ }
+ }
+msdosdone:
+ prevc = 0 ;
+ } else {
+/* begin DOS EPS code */
+ if (c == 'E'+0x80) {
+ if ((getc(f)=='P'+0x80) && (getc(f)=='S'+0x80)
+ && (getc(f)=='F'+0x80)) {
+ doseps = 1;
+ dosepsbegin = getc(f) ;
+ dosepsbegin += getc(f) * 256L ;
+ dosepsbegin += getc(f) * 65536L ;
+ dosepsbegin += getc(f) * 256L * 65536 ;
+ dosepsend = getc(f) ;
+ dosepsend += getc(f) * 256L ;
+ dosepsend += getc(f) * 65536L ;
+ dosepsend += getc(f) * 256L * 65536 ;
+ fseek(f, dosepsbegin, 0);
+ c = getc(f);
+ dosepsend-- ;
+ }
+ else {
+ rewind(f);
+ c = getc(f);
+ }
+ }
+/* end DOS EPS code */
+ if (c != EOF) {
+ while (1) {
+ if (c == '\n') { /* end or beginning of line; check DSC */
+ *dscLinePointer = 0 ; /* make sure we terminate!
+ * might be a new empty line! */
+ if (strncmp(possibleDSCLine, "%%BeginBinary:", 14) == 0 ||
+ strncmp(possibleDSCLine, "%%BeginData:", 12) == 0) {
+ integer size = 0 ;
+ char *p = possibleDSCLine ;
+ *dscLinePointer = 0 ;
+ *dscLineEnd = 0 ;
+ if (scanForEnd == 0 && removecomments)
+ (void)fputs(possibleDSCLine, bitfile) ;
+ scanForEnd = 0 ;
+ while (*p != ':')
+ p++ ;
+ p++ ;
+ while (*p && *p <= ' ')
+ p++ ;
+ if ('0' > *p || *p > '9') {
+ /*
+ * No byte count! We need to scan for end binary
+ * or end data, and hope we get it right. Really
+ * the file is malformed.
+ */
+ scanForEnd = "Yes" ;
+ }
+ while ('0' <= *p && *p <= '9') {
+ size = size * 10 + *p - '0' ;
+ p++ ;
+ }
+ while (*p && *p <= ' ')
+ p++ ;
+ if (*p == 'h' || *p == 'H')
+ /*
+ * Illustrator 8 and 9 have bogus byte counts
+ * for hex data. But if it is hex, we assume
+ * that it is safe to use ASCII scanning, so
+ * we do so.
+ */
+ scanForEnd = "Yes" ;
+ while (*p > ' ') /* ignore Hex/Binary/ASCII */
+ p++ ;
+ while (*p && *p <= ' ')
+ p++ ;
+ (void)putc(c, bitfile) ;
+ if (c == '\r') { /* maybe we have a DOS-style text file */
+ c = getc(f);
+ if (c == '\n') {
+ (void)putc(c, bitfile);
+ dosepsend-- ;
+ } else
+ ungetc(c, f);
+ }
+ if (scanForEnd != 0) {
+ if (strncmp(possibleDSCLine, "%%BeginBinary", 13) == 0)
+ scanForEnd = "%%EndBinary" ;
+ else
+ scanForEnd = "%%EndData" ;
+ }
+ if (scanForEnd == 0) {
+ if (strncmp(p, "lines", 5) != 0 &&
+ strncmp(p, "Lines", 5) != 0) {
+ for (; size>0; size--) {
+ c = getc(f) ;
+ dosepsend-- ;
+ if (c == EOF)
+ error(
+ "! premature end of file in binary section") ;
+ (void)putc(c, bitfile) ;
+ }
+ } else {
+ /*
+ * Count both newlines and returns, and when either
+ * goes over the count, we are done.
+ */
+ int newlines=0, returns=0 ;
+ while (newlines < size && returns < size) {
+ c = getc(f) ;
+ dosepsend-- ;
+ if (c == EOF)
+ error(
+ "! premature end of file in binary section") ;
+ (void)putc(c, bitfile) ;
+ if (c == '\n')
+ newlines++ ;
+ else if (c == '\r')
+ returns++ ;
+ }
+ /*
+ * If we've seen precisely one too few newlines,
+ * and the next char is a newline, include it too.
+ */
+ if (returns == newlines + 1) {
+ if ((c = getc(f)) == '\n') {
+ putc(c, bitfile) ;
+ dosepsend-- ;
+ } else {
+ ungetc(c, f);
+ }
+ }
+ }
+ c = getc(f) ;
+ dosepsend-- ;
+ if (c == '\n' || c == '\r') {
+ (void)putc(c, bitfile) ;
+ if (c == '\r') { /* DOS-style text file? */
+ c = getc(f);
+ dosepsend-- ;
+ if (c == '\n') {
+ putc(c, bitfile);
+ c = getc(f);
+ dosepsend-- ;
+ }
+ } else {
+ c = getc(f) ;
+ dosepsend-- ;
+ }
+ }
+ if (c != '%') {
+ /* try to find %%EndBinary or %%EndData anywhere
+ in the rest of the file, and pretend it
+ worked; this works around various Illustrator
+ bugs. -tgr, 14 June 2003 */
+ char *m1 = "%%EndData" ;
+ char *m2 = "%%EndBinary" ;
+ char *p1 = m1 ;
+ char *p2 = m2 ;
+ error(
+ " expected to see %%EndBinary at end of data; struggling on") ;
+ while (1) {
+ (void)putc(c, bitfile) ;
+ if (c == '\r' || c == '\n') {
+ if (c == '\r') { /* DOS-style text file? */
+ c = getc(f);
+ if (c != '\n')
+ ungetc(c, f);
+ else
+ dosepsend-- ;
+ }
+ break ;
+ }
+ c = getc(f) ;
+ dosepsend-- ;
+ if (c == EOF)
+ error(
+ "! premature end of file in binary section") ;
+ /*
+ * By the way, this code can be fooled by things like %%%EndBinary
+ * or even %%EndBi%%EndBinary, but this isn't valid DSC anyway.
+ * This comment is mainly here to prevent anyone else from emulating
+ * this code when doing stream-based substring matching.
+ */
+ if (c == *p1) {
+ p1++ ;
+ if (*p1 == 0)
+ break ;
+ } else {
+ p1 = m1 ;
+ }
+ if (c == *p2) {
+ p2++ ;
+ if (*p2 == 0)
+ break ;
+ } else {
+ p2 = m2 ;
+ }
+ }
+ }
+ while (1) {
+ (void)putc(c, bitfile) ;
+ if (c == '\r' || c == '\n') {
+ if (c == '\r') { /* DOS-style text file? */
+ c = getc(f);
+ if (c != '\n')
+ ungetc(c, f);
+ else
+ dosepsend-- ;
+ }
+ break ;
+ }
+ c = getc(f) ;
+ dosepsend-- ;
+ if (c == EOF)
+ error(
+ "! premature end of file in binary section") ;
+ }
+ c = getc(f) ;
+ dosepsend-- ;
+ }
+ } else if (scanForEnd && strncmp(possibleDSCLine, scanForEnd,
+ strlen(scanForEnd))==0) {
+ scanForEnd = 0 ;
+ }
+ dscLinePointer = possibleDSCLine ;
+ } else if (dscLinePointer < dscLineEnd) {
+ *dscLinePointer++ = c ;
+ if (removecomments && scanForEnd == 0 &&
+ c == '%' && dscLinePointer == possibleDSCLine + 1) {
+ /* % is first char */
+ c = getc(f) ;
+ if (c == '%' || c == '!')
+ removingBytes = 1 ;
+ if (c != EOF)
+ ungetc(c, f) ;
+ c = '%' ;
+ }
+ }
+#ifdef VMCMS
+ if (c != 0x37 ) {
+#else
+#ifdef MVSXA
+ if (c != 0x37 ) {
+#else
+ if (c != 4) {
+#endif
+#endif
+ if (!removingBytes)
+ (void)putc(c, bitfile) ;
+ }
+ prevc = c ;
+/* begin DOS EPS code */
+ if (doseps && (dosepsend <= 0))
+ break; /* stop at end of DOS EPS PostScript section */
+/* end DOS EPS code */
+ c = getc(f) ;
+ dosepsend-- ;
+ if (c == EOF)
+ break ;
+ else if (c == '\r') {
+ c = getc(f);
+ if (c == '\n') { /* DOS-style text file? */
+ if (!removingBytes) (void)putc('\r', bitfile);
+ dosepsend-- ;
+ } else
+ ungetc(c, f);
+ c = '\n' ;
+ }
+ if (prevc == '\n')
+ removingBytes = 0 ;
+ }
+ }
+ }
+ if (prevc != '\n')
+ (void)putc('\n', bitfile) ;
+ linepos = 0 ;
+#ifndef VMCMS
+#ifndef MVSXA
+#ifndef VMS
+#if !defined(MSDOS) || defined(__DJGPP__)
+#ifndef ATARIST
+#ifndef __THINK__
+ if (infigure == 2)
+#ifdef OS2
+ {
+ if (_osmode == OS2_MODE)
+ (void)pclose(f) ;
+ }
+#else
+ (void)pclose(f) ;
+#endif
+ else
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+ (void)fclose(f) ;
+ if (cur_header && cur_header->postcode) {
+ (void)fprintf(bitfile, "\n%s", cur_header->postcode) ;
+ free(cur_header->postcode) ;
+ }
+ if (!disablecomments) {
+ if (infigure)
+ (void)fprintf(bitfile, "\n%%%%EndDocument\n") ;
+ else if (infont)
+ (void)fprintf(bitfile, "\n%%%%EndFont\n") ;
+#ifdef HPS
+ else if (noprocset) {}
+#endif
+ else
+ (void)fprintf(bitfile, "\n%%%%EndProcSet\n") ;
+ }
+ }
+}
+
+void
+copyfile P1C(char *, s)
+{
+ copyfile_general(s, NULL) ;
+}
+
+/*
+ * For included PostScript graphics, we use the above routine, but
+ * with no fatal error message.
+ */
+void figcopyfile P2C(char *, s, int, systemtype)
+{
+ infigure = systemtype ? 2 : 1 ;
+ copyfile(s) ;
+ infigure = 0 ;
+}
+/*
+ * This next routine writes out a `special' character. In this case,
+ * we simply put it out, since any special character terminates the
+ * preceding token.
+ */
+void
+specialout P1C(char, c)
+{
+ if (linepos >= LINELENGTH) {
+ (void)putc('\n', bitfile) ;
+ linepos = 0 ;
+ }
+ (void)putc(c, bitfile) ;
+ linepos++ ;
+ lastspecial = 1 ;
+}
+
+void
+stringend P1H(void)
+{
+ if (linepos + instring >= LINELENGTH - 2) {
+ (void)putc('\n', bitfile) ;
+ linepos = 0 ;
+ }
+ (void)putc('(', bitfile) ;
+ *strbp = 0 ;
+ (void)fputs(strbuffer, bitfile) ;
+ (void)putc(')', bitfile) ;
+ linepos += instring + 2 ;
+ lastspecial = 1 ;
+ instring = 0 ;
+ strbp = strbuffer ;
+}
+
+#ifdef SHIFTLOWCHARS
+/*
+ * moving chars 0-32 and 127 to higher positions
+ * is desirable when using some fonts
+ */
+int T1Char P1C(int, c)
+{
+ int tmpchr = c;
+ if (shiftlowchars && curfnt->resfont) {
+ if ((tmpchr <= 0x20)&&(tmpchr>=0)) {
+ if (tmpchr < 0x0A) {
+ tmpchr += 0xA1;
+ }
+ else {
+ tmpchr += 0xA3;
+ }
+ }
+ else if (tmpchr == 0x7F) {
+ tmpchr = 0xC4;
+ }
+ }
+ if (curfnt->chardesc[tmpchr].flags2 & EXISTS)
+ tmpchr = c ;
+ return tmpchr;
+}
+#endif
+
+void
+scout P1C(unsigned char, c) /* string character out */
+{
+/*
+ * Is there room in the buffer? LINELENGTH-6 is used because we
+ * need room for (, ), and a possible four-byte string \000, for
+ * instance. If it is too long, we send out the string.
+ */
+ if (instring > LINELENGTH-6) {
+ stringend() ;
+ chrcmd('p') ;
+ }
+#ifdef SHIFTLOWCHARS
+ c=T1Char(c);
+#endif
+/* changed next line to hex representation for VMCMS port
+ if (c<' ' || c > 126 || c=='%' ) {
+*/
+ if ( c<0x20 || c>= 0x7F || c==0x25 ) {
+ *strbp++ = '\\' ;
+ *strbp++ = '0' + ((c >> 6) & 3) ;
+ *strbp++ = '0' + ((c >> 3) & 7) ;
+ *strbp++ = '0' + (c & 7) ;
+ instring += 4 ;
+ } else {
+#ifdef VMCMS
+ c = ascii2ebcdic[c];
+#else
+#ifdef MVSXA
+ c = ascii2ebcdic[c];
+#endif
+#endif
+ if (c == '(' || c == ')' || c == '\\') {
+ *strbp++ = '\\' ;
+ *strbp++ = c ;
+ instring += 2 ;
+ } else {
+ *strbp++ = c ;
+ instring++ ;
+ }
+ }
+}
+
+void
+scout2 P1C(int, c)
+{
+ char s[64] ;
+
+ sprintf(s, "<%04x>p", c) ;
+ cmdout(s) ;
+}
+
+void
+cmdout P1C(char *, s)
+{
+ int l ;
+
+ /* hack added by dorab */
+ if (instring) {
+ stringend();
+ chrcmd('p');
+ }
+ l = strlen(s) ;
+ if ((! lastspecial && linepos >= LINELENGTH - 20) ||
+ linepos + l >= LINELENGTH) {
+ (void)putc('\n', bitfile) ;
+ linepos = 0 ;
+ lastspecial = 1 ;
+ } else if (! lastspecial) {
+ (void)putc(' ', bitfile) ;
+ linepos++ ;
+ }
+ (void)fputs(s, bitfile) ;
+ linepos += l ;
+ lastspecial = 0 ;
+}
+
+
+static void
+chrcmd P1C(char, c)
+{
+ if ((! lastspecial && linepos >= LINELENGTH - 20) ||
+ linepos + 2 > LINELENGTH) {
+ (void)putc('\n', bitfile) ;
+ linepos = 0 ;
+ lastspecial = 1 ;
+ } else if (! lastspecial) {
+ (void)putc(' ', bitfile) ;
+ linepos++ ;
+ }
+ (void)putc(c, bitfile) ;
+ linepos++ ;
+ lastspecial = 0 ;
+}
+
+void
+floatout P1C(float, n)
+{
+ char buf[20] ;
+
+ (void)sprintf(buf, "%.2f", n) ;
+ cmdout(buf) ;
+}
+
+void doubleout P1C(double, n)
+{
+ char buf[40] ;
+
+ (void)sprintf(buf, "%g", n) ;
+ cmdout(buf) ;
+}
+
+void
+numout P1C(integer, n)
+{
+ char buf[10] ;
+
+#ifdef SHORTINT
+ (void)sprintf(buf, "%ld", n) ;
+#else
+ (void)sprintf(buf, "%d", n) ;
+#endif
+ cmdout(buf) ;
+}
+
+void
+mhexout P2C(register unsigned char *, p,
+ register long, len)
+{
+ register char *hexchar = hxdata ;
+ register int n, k ;
+
+ while (len > 0) {
+ if (linepos > LINELENGTH - 2) {
+ (void)putc('\n', bitfile) ;
+ linepos = 0 ;
+ }
+ k = (LINELENGTH - linepos) >> 1 ;
+ if (k > len)
+ k = len ;
+ len -= k ;
+ linepos += (k << 1) ;
+ while (k--) {
+ n = *p++ ;
+ (void)putc(hexchar[n >> 4], bitfile) ;
+ (void)putc(hexchar[n & 15], bitfile) ;
+ }
+ }
+}
+
+void
+fontout P1C(int, n)
+{
+ char buf[6] ;
+
+ if (instring) {
+ stringend() ;
+ chrcmd('p') ;
+ }
+ makepsname(buf, n) ;
+ cmdout(buf) ;
+}
+
+void
+hvpos P1H(void)
+{
+ if (rvv != vv) {
+ if (instring) {
+ stringend() ;
+ numout(hh) ;
+ numout(vv) ;
+ chrcmd('y') ;
+ } else if (rhh != hh) {
+ numout(hh) ;
+ numout(vv) ;
+ chrcmd('a') ;
+ } else { /* hard to get this case, but it's there when you need it! */
+ numout(vv - rvv) ;
+ chrcmd('x') ;
+ }
+ rvv = vv ;
+ } else if (rhh != hh) {
+ if (instring) {
+ stringend() ;
+ if (hh - rhh < 5 && rhh - hh < 5) {
+#ifdef VMCMS /* should replace 'p' in non-VMCMS line as well */
+ chrcmd(ascii2ebcdic[(char)(112 + hh - rhh)]) ;
+#else
+#ifdef MVSXA /* should replace 'p' in non-MVSXA line as well */
+ chrcmd(ascii2ebcdic[(char)(112 + hh - rhh)]) ;
+#else
+ chrcmd((char)('p' + hh - rhh)) ;
+#endif
+#endif
+ } else if (hh - rhh < d + 5 && rhh - hh < 5 - d) {
+#ifdef VMCMS /* should replace 'g' in non-VMCMS line as well */
+ chrcmd(ascii2ebcdic[(char)(103 + hh - rhh - d)]) ;
+#else
+#ifdef MVSXA /* should replace 'g' in non-MVSXA line as well */
+ chrcmd(ascii2ebcdic[(char)(103 + hh - rhh - d)]) ;
+#else
+ chrcmd((char)('g' + hh - rhh - d)) ;
+#endif
+#endif
+ d = hh - rhh ;
+ } else {
+ numout(hh - rhh) ;
+ chrcmd('b') ;
+ d = hh - rhh ;
+ }
+ } else {
+ numout(hh - rhh) ;
+ chrcmd('w') ;
+ }
+ }
+ rhh = hh ;
+}
+
+/*
+ * initprinter opens the bitfile and writes the initialization sequence
+ * to it.
+ */
+void newline P1H(void)
+{
+ if (linepos != 0) {
+ (void)fprintf(bitfile, "\n") ;
+ linepos = 0 ;
+ }
+ lastspecial = 1 ;
+}
+
+void
+nlcmdout P1C(char *, s)
+{
+ newline() ;
+ cmdout(s) ;
+ newline() ;
+}
+/*
+ * Is the dimension close enough for a match? We use a quarter inch
+ * as a match; this is 65536*72.27/4 or 1,184,072 scaled points.
+ */
+static int indelta P1C(integer, i)
+{
+ if (i < 0)
+ i = -i ;
+ return (i <= 1184072) ;
+}
+/*
+ * A case-irrelevant string compare.
+ */
+int mlower P1C(int, c)
+{
+ if ('A' <= c && c <= 'Z')
+ return c - 'A' + 'a' ;
+ else
+ return c ;
+}
+int ncstrcmp P2C(char *, a, char *, b)
+{
+ while (*a && (*a == *b ||
+ mlower(*a) == mlower(*b)))
+ a++, b++ ;
+ if (*a == 0 && *b == 0)
+ return 0 ;
+ else
+ return 1 ;
+}
+/*
+ * Find the paper size.
+ */
+void findpapersize P1H(void) {
+ if (finpapsiz == 0) {
+ struct papsiz *ps ;
+
+ if (tryepsf && !landscape) {
+ finpapsiz = &defpapsiz ;
+ hpapersize = defpapsiz.xsize ;
+ vpapersize = defpapsiz.ysize ;
+ return ;
+ }
+ if (cropmarks) {
+/*
+ * If user wanted crop marks, we increase the size of the page by
+ * a half inch all around.
+ */
+ if (hpapersize == 0 || vpapersize == 0) {
+ error(
+ "warning: -k crop marks wanted, but no paper size specified; using default") ;
+ if (landscape) {
+ hpapersize = defpapsiz.ysize ;
+ vpapersize = defpapsiz.xsize ;
+ } else {
+ hpapersize = defpapsiz.xsize ;
+ vpapersize = defpapsiz.ysize ;
+ }
+ }
+ hpapersize += 2368143L ;
+ vpapersize += 2368143L ;
+ add_header(CROPHEADER) ;
+ }
+ if (paperfmt && *paperfmt) {
+ for (ps = papsizes; ps; ps = ps->next)
+ if (ncstrcmp(paperfmt, ps->name)==0)
+ finpapsiz = ps ;
+ if (finpapsiz == 0)
+ error("no match for papersize") ;
+ }
+ if (finpapsiz == 0 && hpapersize > 0 && vpapersize > 0) {
+ for (ps=papsizes; ps; ps = ps->next) {
+ if (indelta(ps->xsize-hpapersize) &&
+ indelta(ps->ysize-vpapersize)) {
+ landscape = 0 ;
+ break ;
+ }
+ }
+ if (ps == 0) {
+ for (ps=papsizes; ps; ps = ps->next) {
+ if (indelta(ps->ysize-hpapersize) &&
+ indelta(ps->xsize-vpapersize)) {
+ landscape = 1 ;
+ break ;
+ }
+ }
+ if (ps == 0) {
+ for (ps=papsizes; ps; ps = ps->next) {
+ if (ps->ysize == 0 && ps->xsize == 0)
+ break ;
+ }
+ if (ps == 0) {
+ landscape = (hpapersize > vpapersize) ;
+ error(
+ "no match for special paper size found; using default") ;
+ }
+ }
+ }
+ finpapsiz = ps ;
+ }
+ if (finpapsiz == 0) {
+ if (papsizes)
+ finpapsiz = papsizes ;
+ else
+ finpapsiz = &defpapsiz ;
+/*
+ * But change xsize/ysize to match so bounding box works.
+ */
+ if (hpapersize && vpapersize) {
+ if (landscape) {
+ finpapsiz->ysize = hpapersize ;
+ finpapsiz->xsize = vpapersize ;
+ } else {
+ finpapsiz->xsize = hpapersize ;
+ finpapsiz->ysize = vpapersize ;
+ }
+ }
+ }
+/*
+ * Here, there was no papersize special. We set the paper size from
+ * the selected paper format. If the selected paper format has no
+ * sizes, we use the defaults.
+ */
+ if (hpapersize == 0 || vpapersize == 0) {
+ if (finpapsiz->xsize == 0 || finpapsiz->ysize == 0) {
+ finpapsiz->xsize = defpapsiz.xsize ;
+ finpapsiz->ysize = defpapsiz.ysize ;
+ }
+ if (landscape) {
+ vpapersize = finpapsiz->xsize ;
+ hpapersize = finpapsiz->ysize ;
+ } else {
+ hpapersize = finpapsiz->xsize ;
+ vpapersize = finpapsiz->ysize ;
+ }
+/*
+ * Here, there was a papersize special, but the selected paper
+ * format has 0 0 for sizes. We set the sizes here so that the
+ * bounding box works.
+ */
+ } else if (finpapsiz->xsize == 0 || finpapsiz->ysize == 0) {
+ finpapsiz->xsize = hpapersize ;
+ finpapsiz->ysize = vpapersize ;
+/*
+ * Here, the user specified a size with -t, and there was a
+ * papersize special, and its sizes were greater than zero.
+ * We make sure the sizes are okay. Note that the user must have
+ * specified landscape if this is desired.
+ */
+ } else if (paperfmt && *paperfmt) {
+ if (landscape) {
+ if (!indelta(vpapersize - finpapsiz->xsize) ||
+ !indelta(hpapersize - finpapsiz->ysize)) {
+ if (vpapersize > finpapsiz->xsize ||
+ hpapersize > finpapsiz->ysize)
+ error("warning: -t selected paper may be too small") ;
+ else
+ error("note: -t selected paper may be too large") ;
+ }
+ } else {
+ if (!indelta(hpapersize - finpapsiz->xsize) ||
+ !indelta(vpapersize - finpapsiz->ysize)) {
+ if (hpapersize > finpapsiz->xsize ||
+ vpapersize > finpapsiz->ysize)
+ error("warning: -t selected paper may be too small") ;
+ else
+ error("note: -t selected paper may be too large") ;
+ }
+ }
+ }
+ }
+}
+/*
+ * Convert scaled points to PostScript points. This is the same
+ * as return (i * 72 / (65536 * 72.27)), which is the same as
+ * dividing by 65781.76, but we want to round up.
+ */
+static int topoints P1C(integer, i)
+{
+ i += 65780L ;
+ return (i / 6578176L)*100 + (i % 6578176) * 100 / 6578176 ;
+}
+/*
+ * Send out the special paper stuff. If `hed' is non-zero, only
+ * send out lines starting with `!' else send all other lines out.
+ */
+void paperspec P2C(char *, s, int, hed)
+{
+ int sendit ;
+
+ while (*s) {
+ s++ ;
+ if (*s == '\0')
+ return ;
+ if (*s == '!') {
+ s++ ;
+ while (*s == ' ') s++ ;
+ sendit = hed ;
+ } else
+ sendit = ! hed ;
+ if (sendit) {
+ while (*s && *s != '\n')
+ (void)putc(*s++, bitfile) ;
+ putc('\n', bitfile) ;
+ } else {
+ while (*s && *s != '\n')
+ s++ ;
+ }
+ }
+}
+char *epsftest P1C(integer, bop)
+{
+ if (tryepsf && paperfmt == 0 && *iname) {
+ findbb(bop+44) ;
+ return nextstring ;
+ }
+ return 0 ;
+}
+static char *isepsf = 0 ;
+static int endprologsent ;
+void open_output P1H(void) {
+ FILE * pf = NULL;
+ if (*oname != 0) {
+/*
+ * We check to see if the first character is a exclamation
+ * point, and popen if so.
+ */
+ if (*oname == '!' || *oname == '|') {
+#if defined (MSDOS) && !defined (__DJGPP__)
+ error("! can't open output pipe") ;
+#else
+#ifdef VMS
+ error("! can't open output pipe") ;
+#else
+#ifdef VMCMS
+ error("! can't open output pipe") ;
+#else
+#ifdef MVSXA
+ error("! can't open output pipe") ;
+#else
+#ifdef __THINK__
+ error("! can't open output pipe") ;
+#else
+#ifdef ATARIST
+ error("! can't open output pipe") ;
+#else
+#ifdef OS2
+ if (_osmode != OS2_MODE) {
+ error("! can't open output pipe") ;
+ } else {
+#endif
+#ifdef __DJGPP__
+ /* Feature: if they pipe to "lpr" and there's no executable by
+ that name anywhere in sight, write to local printer instead.
+
+ We do this up front, before even trying to popen, because on
+ MS-DOS popen always succeeds for writing (it only opens a
+ temporary file), and by the time we get to actually run the
+ (possibly nonexistent) program in pclose, it's too late to
+ fall back.
+
+ We don't use kpathsea functions here because they don't
+ know about DOS-specific executable extensions, while we
+ want to be able to find "lpr.exe", "lpr.com", "lpr.bat" etc. */
+ extern char *__dosexec_find_on_path(const char *,
+ char **, char *) ;
+ extern char **environ ;
+ char *p = oname + 1 ;
+ char found[FILENAME_MAX] ;
+
+ while (ISSPACE(*p))
+ p++ ;
+ if (strncmp(p, "lpr", 3) == 0 && (ISSPACE(p[3]) || p[3] == '\0')
+ && !__dosexec_find_on_path(oname+1, (char **)0, found)
+ && !__dosexec_find_on_path(oname+1, environ, found))
+ pf = fopen("PRN", "w") ;
+#endif
+ if (pf == NULL && (pf = popen(oname+1, "w")) != NULL)
+ popened = 1;
+ if (pf == NULL)
+ error("! couldn't open output pipe") ;
+ bitfile = pf;
+#ifdef OS2
+ }
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+ } else {
+ if ((bitfile=fopen(oname,"w"))==NULL)
+ error("! couldn't open PostScript file") ;
+ }
+ } else {
+ bitfile = stdout ;
+ }
+
+ /* Even PostScript output may include binary characters, so switch
+ bitfile to binary mode. */
+ if (O_BINARY && !isatty(fileno(bitfile)))
+ SET_BINARY(fileno(bitfile)) ;
+}
+void
+initprinter P1C(sectiontype *, sect)
+{
+ void tell_needed_fonts() ;
+ int n = sect->numpages * pagecopies * collatedcopies ;
+#ifdef HPS
+ if (!HPS_FLAG)
+#endif
+ open_output() ;
+
+ findpapersize() ;
+ if (disablecomments) {
+ (void)fprintf(bitfile,
+ "%%!PS (but not EPSF; comments have been disabled)\n") ;
+ (void)fprintf(stderr, "Warning: no %%%%Page comments generated.\n") ;
+ } else {
+ if (multiplesects) {
+ (void)fprintf(bitfile,
+ "%%!PS (but not EPSF because of memory limits)\n") ;
+ (void)fprintf(stderr, "Warning: no %%%%Page comments generated.\n") ;
+ } else {
+ isepsf = epsftest(sect->bos) ;
+ if (isepsf)
+ (void)fprintf(bitfile, "%%!PS-Adobe-2.0 EPSF-2.0\n") ;
+ else
+ (void)fprintf(bitfile, "%%!PS-Adobe-2.0\n") ;
+ }
+ if (tryepsf && isepsf == 0)
+ error("We tried, but couldn't make it EPSF.") ;
+ (void)fprintf(bitfile, "%%%%Creator: %s\n", banner + 8) ;
+ if (*iname)
+ (void)fprintf(bitfile, "%%%%Title: %s\n", iname) ;
+#ifdef CREATIONDATE
+ jobtime=time(0);
+ (void)fprintf(bitfile, "%%%%CreationDate: %s",
+ asctime(localtime(&jobtime))) ;
+#endif
+ if (! isepsf) {
+/*
+ * Normally, we wouldn't want to add that second field
+ * indicating that the page order is reversed, as per page
+ * 644 of the Red book. But we have to, for many existing
+ * spoolers.
+ */
+ (void)fprintf(bitfile, "%%%%Pages: %d%s\n", (sepfiles ? n : totalpages),
+ (reverse?" -1":"")) ;
+ (void)fprintf(bitfile, "%%%%PageOrder: %sscend\n", reverse?"De":"A");
+ }
+ if (landscape) {
+ fprintf(bitfile, "%%%%Orientation: Landscape\n") ;
+ fprintf(bitfile, "%%%%BoundingBox: 0 0 %d %d\n",
+ topoints(finpapsiz->xsize), topoints(finpapsiz->ysize)) ;
+ } else if (isepsf)
+ fprintf(bitfile, "%%%%BoundingBox: %s\n", isepsf) ;
+ else
+ fprintf(bitfile, "%%%%BoundingBox: 0 0 %d %d\n",
+ topoints(finpapsiz->xsize), topoints(finpapsiz->ysize)) ;
+ tell_needed_fonts() ;
+ paperspec(finpapsiz->specdat, 1) ;
+ (void)fprintf(bitfile, "%%%%EndComments\n") ;
+ }
+ {
+ int i, len ;
+ char *p ;
+
+/*
+ * Here, too, we have to be careful not to exceed the line length
+ * limitation, if possible.
+ */
+ (void)fprintf(bitfile, "%%DVIPSWebPage: %s\n", banner2) ;
+ (void)fprintf(bitfile, "%%DVIPSCommandLine:") ;
+ len = 18 ;
+ for (i=0; i<gargc; i++) {
+ p = gargv[i] ;
+ while (*p > ' ')
+ p++ ;
+ if (*p)
+ len += 2 ;
+ len += strlen(gargv[i]) + 1 ;
+ if (len > LINELENGTH) {
+ (void)fprintf(bitfile, "\n%%+") ;
+ len = strlen(gargv[i]) + 3 ;
+ if (*p)
+ len += 2 ;
+ }
+ (void)fprintf(bitfile, (*p ? " \"%s\"" : " %s"), gargv[i]) ;
+ }
+ (void)fprintf(bitfile, "\n%%DVIPSParameters: dpi=%d", actualdpi) ;
+ if (actualdpi != vactualdpi)
+ (void)fprintf(bitfile, "x%d", vactualdpi) ;
+ if (compressed)
+ (void)fprintf(bitfile, ", compressed") ;
+ if (removecomments)
+ (void)fprintf(bitfile, ", comments removed") ;
+ (void)fputc('\n', bitfile) ;
+ }
+#ifdef VMCMS /* convert preamblecomment to ebcdic so we can read it */
+ {
+ int i ;
+ for ( i=0 ; preamblecomment[i] ; i++ )
+ preamblecomment[i] = ascii2ebcdic[preamblecomment[i]] ;
+ }
+#else
+#ifdef MVSXA /* IBM: MVS/XA */
+ {
+ int i ;
+ for ( i=0 ; preamblecomment[i] ; i++ )
+ preamblecomment[i] = ascii2ebcdic[preamblecomment[i]] ;
+ }
+#endif /* VMCMS */
+#endif
+ (void)fprintf(bitfile, "%%DVIPSSource: %s\n", preamblecomment) ;
+ linepos = 0 ;
+ endprologsent = 0 ;
+ if (safetyenclose)
+ (void)fprintf(bitfile, "/SafetyEnclosure save def\n") ;
+ if (! headers_off)
+ send_headers() ;
+}
+void setup P1H(void) {
+ newline() ;
+ if (endprologsent == 0 && !disablecomments) {
+ (void)fprintf(bitfile, "%%%%EndProlog\n") ;
+ (void)fprintf(bitfile, "%%%%BeginSetup\n") ;
+ if (vactualdpi == actualdpi)
+ (void)fprintf(bitfile, "%%%%Feature: *Resolution %ddpi\n",
+ actualdpi) ;
+ else
+ (void)fprintf(bitfile, "%%%%Feature: *Resolution %dx%ddpi\n",
+ actualdpi, vactualdpi) ;
+ if (multiplesects && *(finpapsiz->specdat)) {
+ (void)fprintf(bitfile, "TeXDict begin\n") ;
+ paperspec(finpapsiz->specdat, 0) ;
+ (void)fprintf(bitfile, "end\n") ;
+ }
+ if (manualfeed)
+ (void)fprintf(bitfile, "%%%%Feature: *ManualFeed True\n") ;
+#ifdef HPS
+ if (!HPS_FLAG)
+#endif
+ if (multiplesects)
+ (void)fprintf(bitfile, "%%%%EndSetup\n") ;
+ }
+ if (multiplesects && ! disablecomments)
+ (void)fprintf(bitfile, "%%DVIPSBeginSection\n") ;
+ cmdout("TeXDict") ;
+ cmdout("begin") ;
+ if (endprologsent || disablecomments || multiplesects == 0) {
+ (void)fprintf(bitfile, "\n") ;
+ paperspec(finpapsiz->specdat, 0) ;
+ }
+ if (manualfeed) cmdout("@manualfeed") ;
+ if (landscape) cmdout("@landscape") ;
+ if (numcopies != 1) {
+ numout((integer)numcopies) ;
+ cmdout("@copies") ;
+ }
+ cmdout("end") ;
+ if (endprologsent == 0 && !disablecomments) {
+ newline() ;
+ endprologsent = 1 ;
+#ifdef HPS
+ if (!HPS_FLAG)
+#endif
+ if (! multiplesects)
+ (void)fprintf(bitfile, "%%%%EndSetup\n") ;
+ }
+#ifdef HPS
+ if (HPS_FLAG) {
+ fclose(bitfile) ;
+ set_bitfile("body.tmp",0) ;
+ }
+#endif
+}
+/*
+ * cleanprinter is the antithesis of the above routine.
+ */
+void
+cleanprinter P1H(void)
+{
+ (void)fprintf(bitfile, "\n") ;
+ (void)fprintf(bitfile, "userdict /end-hook known{end-hook}if\n") ;
+ if (safetyenclose)
+ (void)fprintf(bitfile, "SafetyEnclosure restore\n") ;
+ if (!disablecomments)
+ (void)fprintf(bitfile, "%%%%EOF\n") ;
+ if (sendcontrolD)
+ (void)putc(4, bitfile) ;
+ if (ferror(bitfile))
+ error("Problems with file writing; probably disk full.") ;
+#if !defined(MSDOS) || defined(__DJGPP__)
+#ifndef VMS
+#ifndef MVSXA
+#ifndef VMCMS
+#ifndef __THINK__
+#ifndef ATARIST
+#ifdef OS2
+ if (_osmode == OS2_MODE)
+#endif
+ if (popened)
+ (void)pclose(bitfile) ;
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+ if (popened == 0)
+ (void)fclose(bitfile) ;
+ bitfile = NULL ;
+}
+
+/* this tells dvips that it has no clue where it is. */
+static int thispage = 0 ;
+static integer rulex, ruley ;
+void psflush P1H(void) {
+ rulex = ruley = rhh = rvv = -314159265 ;
+ lastfont = -1 ;
+}
+/*
+ * pageinit initializes the output variables.
+ */
+void
+pageinit P1H(void)
+{
+ psflush() ;
+ newline() ;
+ thispage++ ;
+ if (!disablecomments)
+ if (multiplesects)
+#ifdef SHORTINT
+ (void)fprintf(bitfile, "%%DVIPSSectionPage: %ld\n", pagenum) ;
+ else if (! isepsf)
+ (void)fprintf(bitfile, "%%%%Page: %ld %d\n", pagenum, thispage) ;
+#else
+ (void)fprintf(bitfile, "%%DVIPSSectionPage: %d\n", pagenum) ;
+ else if (! isepsf)
+ (void)fprintf(bitfile, "%%%%Page: %d %d\n", pagenum, thispage) ;
+#endif
+ linepos = 0 ;
+ cmdout("TeXDict") ;
+ cmdout("begin") ;
+#ifdef HPS
+ if (HPS_FLAG) {
+ cmdout("HPSdict") ;
+ cmdout("begin") ;
+ }
+#endif
+ if (landscape) cmdout("@landscape") ;
+ numout((integer)pagenum) ;
+ numout((integer)thispage-1) ;
+ cmdout("bop") ;
+ d = 0 ;
+}
+
+
+
+/*
+ * This routine ends a page.
+ */
+void
+pageend P1H(void)
+{
+ if (instring) {
+ stringend() ;
+ chrcmd('p') ;
+ }
+ cmdout("eop") ;
+ cmdout("end") ;
+#ifdef HPS
+ if (HPS_FLAG)
+ cmdout("end") ;
+#endif
+}
+
+/*
+ * drawrule draws a rule at the specified position.
+ * It does nothing to save/restore the current position,
+ * or even draw the current string. (Rules are normally
+ * set below the baseline anyway, so this saves us on
+ * output size almost always.)
+ */
+void
+drawrule P2C(integer, rw, integer, rh)
+{
+ numout((integer)hh) ;
+ numout((integer)vv) ;
+ if (rw == rulex && rh == ruley)
+ chrcmd('V') ;
+ else {
+ numout((integer)rw) ;
+ numout((integer)rh) ;
+ chrcmd('v') ;
+ rulex = rw ;
+ ruley = rh ;
+ }
+}
+
+/*
+ * drawchar draws a character at the specified position.
+ */
+void
+drawchar P2C(chardesctype *, c, int, cc)
+{
+ hvpos() ;
+ if (lastfont != curfnt->psname) {
+ fontout((int)curfnt->psname) ;
+ lastfont = curfnt->psname ;
+ }
+ if (curfnt->codewidth==1) scout((unsigned char)cc) ;
+ else scout2(cc) ;
+ rhh = hh + c->pixelwidth ; /* rvv = rv */
+}
+/*
+ * This routine sends out the document fonts comment.
+ */
+void tell_needed_fonts P1H(void) {
+ struct header_list *hl = ps_fonts_used ;
+ char *q ;
+ int roomleft = -1 ;
+
+ if (hl == 0)
+ return ;
+ while (0 != (q=get_name(&hl))) {
+ if ((int)strlen(q) >= roomleft) {
+ if (roomleft != -1) {
+ fprintf(bitfile, "\n%%%%+") ;
+ roomleft = LINELENGTH - 3 ;
+ } else {
+ fprintf(bitfile, "%%%%DocumentFonts:") ;
+ roomleft = LINELENGTH - 16 ;
+ }
+ }
+ fprintf(bitfile, " %s", q) ;
+ roomleft -= strlen(q) + 1 ;
+ }
+ fprintf(bitfile, "\n") ;
+}