summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipsk/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipsk/output.c')
-rw-r--r--Build/source/texk/dvipsk/output.c1897
1 files changed, 1897 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..da3b6098262
--- /dev/null
+++ b/Build/source/texk/dvipsk/output.c
@@ -0,0 +1,1897 @@
+/*
+ * 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
+#if defined(WIN32) && defined(KPATHSEA)
+#undef fopen
+#undef popen
+#undef pclose
+extern FILE *generic_fsyscp_fopen(const char *name, const char *mode);
+#define fopen(file, fmode) generic_fsyscp_fopen(file, fmode)
+#define popen(pcmd, pmode) fsyscp_popen(pcmd, pmode)
+#define pclose(pstream) _pclose(pstream)
+#endif
+
+#ifdef __DJGPP__
+#include <unistd.h> /* for `isatty' */
+#endif
+
+/* UCS -> UTF-8 */
+#define UCStoUTF8B1(x) (0xc0 + (((x) >> 6) & 0x1f))
+#define UCStoUTF8B2(x) (0x80 + (((x) ) & 0x3f))
+
+#define UCStoUTF8C1(x) (0xe0 + (((x) >> 12) & 0x0f))
+#define UCStoUTF8C2(x) (0x80 + (((x) >> 6) & 0x3f))
+#define UCStoUTF8C3(x) (0x80 + (((x) ) & 0x3f))
+
+#define UCStoUTF8D1(x) (0xf0 + (((x) >> 18) & 0x07))
+#define UCStoUTF8D2(x) (0x80 + (((x) >> 12) & 0x3f))
+#define UCStoUTF8D3(x) (0x80 + (((x) >> 6) & 0x3f))
+#define UCStoUTF8D4(x) (0x80 + (((x) ) & 0x3f))
+
+/* UTF-32 over U+FFFF -> UTF-16 surrogate pair */
+#define UTF32toUTF16HS(x) (0xd800 + (((x-0x10000) >> 10) & 0x3ff))
+#define UTF32toUTF16LS(x) (0xdc00 + ( x & 0x3ff))
+
+/*
+ * The external declarations:
+ */
+#include "protos.h"
+
+char preamblecomment[256]; /* usually "TeX output ..." */
+integer rdir = 0, fdir = 0;
+/*
+ * We need a few statics to take care of things.
+ */
+static void chrcmd(char c);
+static void tell_needed_fonts(void);
+static void print_composefont(void);
+static void setdir(int d);
+static int JIStoSJIS(int c);
+
+static Boolean any_dir = 0; /* did we output any direction commands? */
+static Boolean jflag = 0;
+static integer rhh, rvv;
+static int instring;
+static Boolean lastspecial = 1;
+static shalfword d;
+static Boolean popened = 0;
+static int lastfont;
+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>
+#ifndef WIN32
+#include <sys/time.h> /* time(), at least on BSD Unix */
+#endif
+#endif
+#include <time.h> /* asctime() and localtime(), at least on BSD Unix */
+static time_t jobtime;
+
+#if defined(_MSC_VER)
+#define strtoll _strtoi64
+#endif
+
+#define INVALID_EPOCH_VALUE ((time_t) -1)
+
+static time_t
+get_unique_time_if_given(void)
+{
+ const char *source_date_epoch;
+ int64_t epoch;
+ char *endptr;
+ time_t ret = INVALID_EPOCH_VALUE;
+
+ source_date_epoch = getenv("SOURCE_DATE_EPOCH");
+ if (source_date_epoch) {
+ errno = 0;
+ epoch = strtoll(source_date_epoch, &endptr, 10);
+ if (!(epoch < 0 || *endptr != '\0' || errno != 0)) {
+ ret = (time_t) epoch;
+#if defined(_MSC_VER)
+ if (ret > 32535291599ULL)
+ ret = 32535291599ULL;
+#endif
+ }
+ }
+ return ret;
+}
+#endif /* CREATIONDATE */
+
+/*
+ * 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 const char *hxdata = "0123456789ABCDEF";
+static int infigure;
+static char possibleDSCLine[81],
+ *dscLinePointer = possibleDSCLine, *dscLineEnd = possibleDSCLine + 80;
+void
+copyfile_general(const 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;
+ const char *scanForEnd = 0;
+ int scanningFont = 0;
+
+ /* end DOS EPS code */
+#if defined(VMCMS) || defined (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 defined(WIN32)
+ if (f == 0 && file_system_codepage != win32_codepage) {
+ int tmpcp = file_system_codepage;
+ file_system_codepage = win32_codepage;
+ f = search(figpath, s, READBIN);
+ file_system_codepage = tmpcp;
+ }
+#endif
+ if (f == 0)
+ f = search(headerpath, s, READBIN);
+#if defined(VMCMS) || defined (MVSXA)
+ lastdirsep = strrchr(s, '/');
+ if ( NULL != lastdirsep ) trunc_s = lastdirsep + 1;
+#ifdef VMCMS
+ sprintf(errbuf,
+ "Couldn't find figure file %s with CMS name %s; continuing.", s, trunc_s);
+ if (secure == 2) {
+ strcat(errbuf, "\nNote that an absolute path or a relative path with .. are denied in -R2 mode.");
+ }
+#else /* ! VMCMS */
+ sprintf(errbuf,
+ "Couldn't find figure file %s with MVS name %s; continuing.", s, trunc_s);
+ if (secure == 2) {
+ strcat(errbuf, "\nNote that an absolute path or a relative path with .. are denied in -R2 mode.");
+ }
+#endif /* ! VMCMS */
+#else /* ! (VMCMS || MVSXA) */
+ sprintf(errbuf, "Could not find figure file %.500s; continuing.", s);
+ if (secure == 2) {
+ strcat(errbuf, "\nNote that an absolute path or a relative path with .. are denied in -R2 mode.");
+ }
+#endif /* !(VMCMS || MVSXA) */
+ break;
+#ifndef VMCMS
+#ifndef MVSXA
+#ifndef VMS
+#if !defined(MSDOS) || defined(__DJGPP__)
+#ifndef ATARIST
+#ifndef __THINK__
+ case 2:
+#ifdef SECURE
+ sprintf(errbuf, "<%.500s>: Tick filename execution disabled", s);
+#else
+#ifdef OS2
+ if (_osmode == OS2_MODE) {
+#endif
+ if (secure == 0) {
+ sprintf(errbuf, "Execution of <%.500s> failed ", s);
+ f = popen(s, "r");
+ if (f != 0)
+ SET_BINARY(fileno(f));
+ }
+ else {
+ sprintf(errbuf,"Secure mode is %d so execute <%.500s> 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);
+ }
+ sprintf(errbuf, "! Could not find header file %.500s.", s);
+ if (secure == 2) {
+ strcat(errbuf, "\nNote that an absolute path or a relative path with .. are denied in -R2 mode.");
+ }
+ break;
+ }
+ if (f==NULL) {
+ found_problems = 1; /* continue, but eventually exit unsuccessfully */
+ error(errbuf);
+ } else {
+ if (! quiet) {
+#if defined(VMCMS) || defined (MVSXA)
+ if (strlen(s) + prettycolumn > STDOUTSIZE) {
+#else
+ if (strlen(realnameoffile) + prettycolumn > STDOUTSIZE) {
+#endif
+ fprintf(stderr, "\n");
+ prettycolumn = 0;
+ }
+#if defined(VMCMS) || defined (MVSXA)
+ fprintf(stderr, "<%s>", trunc_s);
+#else
+ fprintf_str(stderr, "<%s>", realnameoffile);
+#endif
+ fflush(stderr);
+#if defined(VMCMS) || defined (MVSXA)
+ prettycolumn += 2 + strlen(s);
+#else
+ prettycolumn += 2 + strlen(realnameoffile);
+#endif
+ }
+ if (linepos != 0)
+ 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)
+ fprintf(bitfile, "%%%%BeginDocument: %s\n", s);
+ else if (infont)
+ fprintf(bitfile, "%%%%BeginFont: %s\n", infont);
+#ifdef HPS
+ else if (noprocset) {}
+#endif
+ else
+ fprintf(bitfile, "%%%%BeginProcSet: %s 0 0\n", s);
+ }
+ if (cur_header && cur_header->precode) {
+ 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 */
+ putc('\n', bitfile);
+ if ((c = getc(f)) == '\n') /* DOS-style text */
+ len--; /* consume, but don't generate NL */
+ else
+ ungetc(c, f);
+ }
+ else
+ 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 {
+ putc(hxdata[c >> 4], bitfile);
+ 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 ||
+ strncmp(possibleDSCLine, "%%BeginFont:", 12) == 0) {
+ integer size = 0;
+ char *p = possibleDSCLine;
+ *dscLinePointer = 0;
+ *dscLineEnd = 0;
+ if (scanForEnd == 0 && removecomments) {
+ fputs(possibleDSCLine, bitfile);
+ putc('\n', bitfile);
+ }
+
+ if (strncmp(possibleDSCLine, "%%BeginFont:", 12) == 0) {
+
+ /* Theoretically, we could wait until we see
+ the "currentfile eexec" and possibly even
+ check that the following data really looks
+ like binary before we begin verbatim
+ copying, but that would complicate the code
+ beyond our present needs. If we were going
+ to do that much work, this entire chunk of
+ code should probably be
+ rewritten. [dmj@ams.org, 2007/08/20] */
+
+ scanForEnd = "%%EndFont";
+ scanningFont = 1;
+ } else {
+ scanningFont = 0;
+
+ 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++;
+ putc(c, bitfile);
+ if (c == '\r') { /* maybe we have a DOS-style text file */
+ c = getc(f);
+ if (c == '\n') {
+ 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");
+ 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");
+ 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') {
+ 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 */
+ const char *m1 = "%%EndData";
+ const char *m2 = "%%EndBinary";
+ const char *p1 = m1;
+ const char *p2 = m2;
+ error(
+ " expected to see %%EndBinary at end of data; struggling on");
+ while (1) {
+ 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) {
+ 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 {
+ putc(c, bitfile);
+ dosepsend--;
+ }
+ }
+ break;
+ }
+ c = getc(f);
+ removingBytes = 0;
+ 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;
+ scanningFont = 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 = '%';
+ }
+ }
+#if defined(VMCMS) || defined (MVSXA)
+ if (c != 0x37 || scanningFont) {
+#else
+ if (c != 4 || scanningFont) {
+#endif
+ if (!removingBytes)
+ 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' && ! scanningFont) {
+ c = getc(f);
+ if (c == '\n') { /* DOS-style text file? */
+ if (!removingBytes) putc('\r', bitfile);
+ dosepsend--;
+ } else
+ ungetc(c, f);
+ c = '\n';
+ }
+ if (prevc == '\n')
+ removingBytes = 0;
+ }
+ }
+ }
+ if (prevc != '\n')
+ 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)
+ pclose(f);
+ }
+#else
+ pclose(f);
+#endif
+ else
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+ fclose(f);
+ if (cur_header && cur_header->postcode) {
+ fprintf(bitfile, "\n%s", cur_header->postcode);
+ free(cur_header->postcode);
+ }
+ if (!disablecomments) {
+ if (infigure)
+ fprintf(bitfile, "\n%%%%EndDocument\n");
+ else if (infont)
+ fprintf(bitfile, "\n%%%%EndFont\n");
+#ifdef HPS
+ else if (noprocset) {}
+#endif
+ else
+ fprintf(bitfile, "\n%%%%EndProcSet\n");
+ }
+ }
+}
+
+void
+copyfile(const char *s)
+{
+ copyfile_general(s, NULL);
+}
+
+/*
+ * For included PostScript graphics, we use the above routine, but
+ * with no fatal error message.
+ */
+void
+figcopyfile(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(char c)
+{
+ if (linepos >= LINELENGTH) {
+ putc('\n', bitfile);
+ linepos = 0;
+ }
+ putc(c, bitfile);
+ linepos++;
+ lastspecial = 1;
+}
+
+void
+stringend(void)
+{
+ if (linepos + instring >= LINELENGTH - 2) {
+ putc('\n', bitfile);
+ linepos = 0;
+ }
+ putc('(', bitfile);
+ *strbp = 0;
+ fputs(strbuffer, bitfile);
+ 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(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(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.
+ */
+ jflag = 0;
+ 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 {
+#if defined(VMCMS) || defined (MVSXA)
+ c = ascii2ebcdic[c];
+#endif
+ if (c == '(' || c == ')' || c == '\\') {
+ *strbp++ = '\\';
+ *strbp++ = c;
+ instring += 2;
+ } else {
+ *strbp++ = c;
+ instring++;
+ }
+ }
+}
+
+static void
+scout2(int c)
+{
+ char s[64];
+
+ sprintf(s, "<%04x>p", c);
+ cmdout(s);
+}
+
+static void
+jscout(int c, char *fs) /* string character out */
+{
+ char s[64];
+
+ if (!dir) {
+ numout(hh);
+ numout(vv);
+ } else {
+ numout(vv);
+ numout(-hh);
+ }
+ if (strstr(fs,"-UTF32-")!=NULL) {
+ snprintf(s, sizeof(s), "a<%08x>p", c);
+ } else if (strstr(fs,"-UTF8-")!=NULL) {
+ if (c<0x80) {
+ snprintf(s, sizeof(s), "a<%02x>p", c);
+ } else if (c<0x800) {
+ snprintf(s, sizeof(s), "a<%02x%02x>p", UCStoUTF8B1(c), UCStoUTF8B2(c));
+ } else if (c<0x10000) {
+ snprintf(s, sizeof(s), "a<%02x%02x%02x>p", UCStoUTF8C1(c),
+ UCStoUTF8C2(c), UCStoUTF8C3(c));
+ } else if (c<0x110000) {
+ snprintf(s, sizeof(s), "a<%02x%02x%02x%02x>p", UCStoUTF8D1(c),
+ UCStoUTF8D2(c), UCStoUTF8D3(c), UCStoUTF8D4(c));
+ } else {
+ error("warning: Illegal code value.");
+ }
+ } else if (c>0xffff && strstr(fs,"-UTF16-")!=NULL) {
+ snprintf(s, sizeof(s), "a<%04x%04x>p",
+ UTF32toUTF16HS(c), UTF32toUTF16LS(c));
+ } else {
+ if ((strstr(fs,"-RKSJ-")!=NULL)) c = JIStoSJIS(c);
+ snprintf(s, sizeof(s), "a<%04x>p", c);
+ }
+ cmdout(s);
+ instring = 0;
+ jflag = 1;
+ strbuffer[0] = '\0';
+}
+
+void
+cmdout(const char *s)
+{
+ int l;
+
+ /* hack added by dorab */
+ if (instring && !jflag) {
+ stringend();
+ chrcmd('p');
+ }
+ l = strlen(s);
+ if ((! lastspecial && linepos >= LINELENGTH - 20) ||
+ linepos + l >= LINELENGTH) {
+ putc('\n', bitfile);
+ linepos = 0;
+ } else if (! lastspecial) {
+ putc(' ', bitfile);
+ linepos++;
+ }
+ fputs(s, bitfile);
+ linepos += l;
+ lastspecial = 0;
+}
+
+void psnameout(const char *s) {
+ // we lead with a special, so we don't need the space.
+ lastspecial = 1 ;
+ cmdout(s) ;
+}
+
+void pslineout(const char *s) {
+ fputs(s, bitfile) ;
+ fprintf(bitfile, "\n");
+ linepos = 0;
+}
+
+static void
+chrcmd(char c)
+{
+ if ((! lastspecial && linepos >= LINELENGTH - 20) ||
+ linepos + 2 > LINELENGTH) {
+ putc('\n', bitfile);
+ linepos = 0;
+ } else if (! lastspecial) {
+ putc(' ', bitfile);
+ linepos++;
+ }
+ putc(c, bitfile);
+ linepos++;
+ lastspecial = 0;
+}
+
+void
+floatout(float n)
+{
+ char buf[50];
+
+ snprintf(buf, sizeof(buf), "%.2f", n);
+ cmdout(buf);
+}
+
+void
+doubleout(double n)
+{
+ char buf[50];
+
+ snprintf(buf, sizeof(buf), "%g", n);
+ cmdout(buf);
+}
+
+void
+numout(integer n)
+{
+ char buf[50];
+
+#ifdef SHORTINT
+ snprintf(buf, sizeof(buf), "%ld", n);
+#else
+ snprintf(buf, sizeof(buf), "%d", n);
+#endif
+ cmdout(buf);
+}
+
+void
+mhexout(register unsigned char *p,
+ register long len)
+{
+ register const char *hexchar = hxdata;
+ register int n, k;
+
+ while (len > 0) {
+ if (linepos > LINELENGTH - 2) {
+ putc('\n', bitfile);
+ linepos = 0;
+ }
+ k = (LINELENGTH - linepos) >> 1;
+ if (k > len)
+ k = len;
+ len -= k;
+ linepos += (k << 1);
+ while (k--) {
+ n = *p++;
+ putc(hexchar[n >> 4], bitfile);
+ putc(hexchar[n & 15], bitfile);
+ }
+ }
+}
+
+static void
+fontout(halfword n)
+{
+ char buf[6];
+
+ if (instring && !jflag) {
+ stringend();
+ chrcmd('p');
+ }
+ makepsname(buf, n);
+ cmdout(buf);
+
+ lastfont = curfnt->psname;
+}
+
+void
+hvpos(void)
+{
+ if (!dir) {
+ if (rvv != vv || jflag) {
+ if (instring) {
+ stringend();
+ numout(hh);
+ numout(vv);
+ chrcmd('y');
+ } else if (rhh != hh || jflag) {
+ 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 || jflag) {
+ if (instring) {
+ stringend();
+ if (hh - rhh < 5 && rhh - hh < 5) {
+#if defined(VMCMS) || defined (MVSXA) /* should replace 'p' in non-VMCMS, non-MVSXA line as well */
+ chrcmd(ascii2ebcdic[(char)(112 + hh - rhh)]);
+#else
+ chrcmd((char)('p' + hh - rhh));
+#endif
+ } else if (hh - rhh < d + 5 && rhh - hh < 5 - d) {
+#if defined(VMCMS) || defined (MVSXA) /* should replace 'g' in non-VMCMS, non-MVSXA line as well */
+ chrcmd(ascii2ebcdic[(char)(103 + hh - rhh - d)]);
+#else
+ chrcmd((char)('g' + hh - rhh - d));
+#endif
+ d = hh - rhh;
+ } else {
+ numout(hh - rhh);
+ chrcmd('b');
+ d = hh - rhh;
+ }
+ } else {
+ numout(hh - rhh);
+ chrcmd('w');
+ }
+ }
+ rhh = hh;
+ } else {
+ if (rhh != hh || jflag) {
+ if (instring) {
+ stringend();
+ numout(vv);
+ numout(-hh);
+ chrcmd('y');
+ } else if (rvv != vv || jflag) {
+ numout(vv);
+ numout(-hh);
+ chrcmd('a');
+ } else { /* hard to get this case, but it's there when you need it! */
+ numout(rhh - hh);
+ chrcmd('x');
+ }
+ rhh = hh;
+ } else if (rvv != vv || jflag) {
+ if (instring) {
+ stringend();
+ if (vv - rvv < 5 && rvv - vv < 5) {
+#if defined(VMCMS) || defined (MVSXA) /* should replace 'p' in non-VMCMS, non-MVSXA line as well */
+ chrcmd(ascii2ebcdic[(char)(112 + vv - rvv)]);
+#else
+ chrcmd((char)('p' + vv - rvv));
+#endif
+ } else if (vv - rvv < d + 5 && rvv - vv < 5 - d) {
+#if defined(VMCMS) || defined (MVSXA) /* should replace 'g' in non-VMCMS, non-MVSXA line as well */
+ chrcmd(ascii2ebcdic[(char)(103 + vv - rvv - d)]);
+#else
+ chrcmd((char)('g' + vv - rvv - d));
+#endif
+ d = vv - rvv;
+ } else {
+ numout(vv - rvv);
+ chrcmd('b');
+ d = vv - rvv;
+ }
+ } else {
+ numout(vv - rvv);
+ chrcmd('w');
+ }
+ }
+ rvv = vv;
+ }
+}
+
+/*
+ * initprinter opens the bitfile and writes the initialization sequence
+ * to it.
+ */
+void
+newline(void)
+{
+ if (linepos != 0) {
+ fprintf(bitfile, "\n");
+ linepos = 0;
+ }
+ lastspecial = 1;
+}
+
+void
+nlcmdout(const char *s)
+{
+ newline();
+ cmdout(s);
+ newline();
+}
+/*
+ * Is the dimension close enough for a match? We use 5bp
+ * as a match; this is 65536*72.27*5/72 or 328909 scaled points.
+ */
+static int
+indelta(integer i)
+{
+ if (i < 0)
+ i = -i;
+ return (i <= 328909);
+}
+/*
+ * A case-irrelevant string compare.
+ */
+static int
+mlower(int c)
+{
+ if ('A' <= c && c <= 'Z')
+ return c - 'A' + 'a';
+ else
+ return c;
+}
+static int
+ncstrcmp(const char *a, const 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.
+ */
+static void
+findpapersize(void) {
+ if (finpapsiz == 0) {
+ struct papsiz *ps;
+ struct papsiz *fps = 0;
+ int ih, iv, it;
+ int mindiff = 0x7fffffff;
+
+ 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) {
+ ih = ps->xsize-hpapersize;
+ iv = ps->ysize-vpapersize;
+ if (ih < 0) ih = -ih;
+ if (iv < 0) iv = -iv;
+ it = ih;
+ if (it < iv) it = iv;
+ if (it < mindiff) {
+ mindiff = it;
+ fps = ps;
+ }
+ }
+ if (indelta(mindiff))
+ landscape = 0;
+ else
+ fps = 0;
+ mindiff = 0x7fffffff;
+ if (fps == 0) {
+ for (ps=papsizes; ps; ps = ps->next) {
+ iv = ps->ysize-hpapersize;
+ ih = ps->xsize-vpapersize;
+ if (ih < 0) ih = -ih;
+ if (iv < 0) iv = -iv;
+ it = ih;
+ if (it < iv) it = iv;
+ if (it < mindiff) {
+ mindiff = it;
+ fps = ps;
+ }
+ }
+ if (indelta(mindiff))
+ landscape = 1;
+ else
+ fps = 0;
+ if (fps == 0) {
+ for (ps=papsizes; ps; ps = ps->next) {
+ if (ps->ysize == 0 && ps->xsize == 0) {
+ fps = ps;
+ break;
+ }
+ }
+ if (fps == 0) {
+ landscape = (hpapersize > vpapersize);
+ error(
+ "no match for special paper size found; using default");
+ }
+ }
+ }
+ finpapsiz = fps;
+ }
+ 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(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.
+ */
+static void
+paperspec(const 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')
+ putc(*s++, bitfile);
+ putc('\n', bitfile);
+ } else {
+ while (*s && *s != '\n')
+ s++;
+ }
+ }
+}
+static char *
+epsftest(integer bop)
+{
+ if (tryepsf && paperfmt == 0 && *iname) {
+ findbb(bop+44);
+ return nextstring;
+ }
+ return 0;
+}
+static char *isepsf = 0;
+static int endprologsent;
+void
+open_output(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__) || defined(VMS) || defined(VMCMS) || defined(MVSXA) || defined(__THINK__) || defined(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;
+ SET_BINARY(fileno(pf));
+ }
+ if (pf == NULL)
+ error("! couldn't open output pipe");
+ bitfile = pf;
+#ifdef OS2
+ }
+#endif
+#endif /* MSDOS && !__DJGPP__ || VMS || ... */
+ } else {
+ if ((bitfile=fopen(oname,"w"))==NULL)
+ error("! couldn't open PostScript file");
+ SET_BINARY(fileno(bitfile));
+ }
+ } 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(sectiontype *sect)
+{
+ int n = sect->numpages * pagecopies * collatedcopies;
+#ifdef HPS
+ if (!HPS_FLAG)
+#endif
+ open_output();
+
+ findpapersize();
+ if (disablecomments) {
+ fprintf(bitfile,
+ "%%!PS (but not EPSF; comments have been disabled)\n");
+ fprintf(stderr, "Warning: no %%%%Page comments generated.\n");
+ } else {
+ if (multiplesects) {
+ fprintf(bitfile,
+ "%%!PS (but not EPSF because of memory limits)\n");
+ fprintf(stderr, "Warning: no %%%%Page comments generated.\n");
+ } else {
+ isepsf = epsftest(sect->bos);
+ if (isepsf)
+ fprintf(bitfile, "%%!PS-Adobe-2.0 EPSF-2.0\n");
+ else
+ fprintf(bitfile, "%%!PS-Adobe-2.0\n");
+ }
+ if (tryepsf && isepsf == 0)
+ error("We tried, but couldn't make it EPSF.");
+ fprintf(bitfile, "%%%%Creator: %s\n", banner + 8);
+ if (*titlename)
+ fprintf(bitfile, "%%%%Title: %s\n", titlename);
+ else if (*iname)
+ fprintf(bitfile, "%%%%Title: %s\n", xbasename(iname));
+#ifdef CREATIONDATE
+ jobtime = get_unique_time_if_given();
+ if (jobtime == INVALID_EPOCH_VALUE) {
+ jobtime = time(0);
+ }
+ fprintf(bitfile, "%%%%CreationDate: %s", asctime(gmtime(&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.
+ */
+ fprintf(bitfile, "%%%%Pages: %d%s\n", (sepfiles ? n : totalpages),
+ (reverse?" -1":""));
+ 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);
+ fprintf(bitfile, "%%%%EndComments\n");
+/*
+ * If we encode Type 3 fonts with an encoding vector, this can cause
+ * Distiller's autoorientation to get confused. We remedy this by
+ * emitting underdocumented ViewingOrientation comments right after
+ * EndComments. Known defect: if a user "flips" the landscape to be
+ * 180 degrees using one of the \special{} commands available, the
+ * document will be rendered in the viewer upside down. (But only
+ * with bitmap font encoding enabled and bitmapped fonts actually used.)
+ * --tgr, 29 February 2020.
+ */
+ if (encodetype3 && bitmapfontseen) {
+ fprintf(bitfile, "%%%%BeginDefaults\n") ;
+ if (landscape) {
+ fprintf(bitfile, "%%%%ViewingOrientation: 0 -1 1 0\n") ;
+ } else {
+ fprintf(bitfile, "%%%%ViewingOrientation: 1 0 0 1\n") ;
+ }
+ fprintf(bitfile, "%%%%EndDefaults\n") ;
+ }
+ }
+ {
+ int i, len;
+ char *p;
+
+/*
+ * Here, too, we have to be careful not to exceed the line length
+ * limitation, if possible.
+ */
+ fprintf(bitfile, "%%DVIPSWebPage: %s\n", banner2);
+ 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) {
+ fprintf(bitfile, "\n%%+");
+ len = strlen(gargv[i]) + 3;
+ if (*p)
+ len += 2;
+ }
+ fprintf(bitfile, (*p ? " \"%s\"" : " %s"), gargv[i]);
+ }
+ fprintf(bitfile, "\n%%DVIPSParameters: dpi=%d", actualdpi);
+ if (actualdpi != vactualdpi)
+ fprintf(bitfile, "x%d", vactualdpi);
+ if (compressed)
+ fprintf(bitfile, ", compressed");
+ if (removecomments)
+ fprintf(bitfile, ", comments removed");
+ fputc('\n', bitfile);
+ }
+#if defined(VMCMS) || defined (MVSXA) /* convert preamblecomment to ebcdic so we can read it */
+ {
+ int i;
+ for ( i=0; preamblecomment[i]; i++ )
+ preamblecomment[i] = ascii2ebcdic[preamblecomment[i]];
+ }
+#endif
+ fprintf(bitfile, "%%DVIPSSource: %s\n", preamblecomment);
+ linepos = 0;
+ endprologsent = 0;
+ if (safetyenclose)
+ fprintf(bitfile, "/SafetyEnclosure save def\n");
+ print_composefont();
+ if (! headers_off)
+ send_headers();
+}
+void
+setup(void) {
+ newline();
+ if (endprologsent == 0 && !disablecomments) {
+ fprintf(bitfile, "%%%%EndProlog\n");
+ fprintf(bitfile, "%%%%BeginSetup\n");
+ if (vactualdpi == actualdpi)
+ fprintf(bitfile, "%%%%Feature: *Resolution %ddpi\n",
+ actualdpi);
+ else
+ fprintf(bitfile, "%%%%Feature: *Resolution %dx%ddpi\n",
+ actualdpi, vactualdpi);
+ if (multiplesects && *(finpapsiz->specdat)) {
+ fprintf(bitfile, "TeXDict begin\n");
+ paperspec(finpapsiz->specdat, 0);
+ fprintf(bitfile, "end\n");
+ }
+ if (manualfeed)
+ fprintf(bitfile, "%%%%Feature: *ManualFeed True\n");
+#ifdef HPS
+ if (!HPS_FLAG)
+#endif
+ if (multiplesects)
+ fprintf(bitfile, "%%%%EndSetup\n");
+ }
+ if (multiplesects && ! disablecomments)
+ fprintf(bitfile, "%%DVIPSBeginSection\n");
+ cmdout("TeXDict");
+ cmdout("begin");
+ if (endprologsent || disablecomments || multiplesects == 0) {
+ 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)
+ 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(void)
+{
+ fprintf(bitfile, "\n");
+ fprintf(bitfile, "userdict /end-hook known{end-hook}if\n");
+ if (safetyenclose)
+ fprintf(bitfile, "SafetyEnclosure restore\n");
+ if (!disablecomments)
+ fprintf(bitfile, "%%%%EOF\n");
+ if (sendcontrolD)
+ 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)
+ pclose(bitfile);
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+ if (popened == 0)
+ 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(void) {
+ rulex = ruley = rhh = rvv = -314159265;
+ lastfont = -1;
+}
+/*
+ * pageinit initializes the output variables.
+ */
+void
+pageinit(void)
+{
+ psflush();
+ newline();
+ thispage++;
+ if (!disablecomments) {
+ if (multiplesects)
+#ifdef SHORTINT
+ fprintf(bitfile, "%%DVIPSSectionPage: %ld\n", pagenum);
+ else if (! isepsf)
+ fprintf(bitfile, "%%%%Page: %ld %d\n", pagenum, thispage);
+#else
+ fprintf(bitfile, "%%DVIPSSectionPage: %d\n", pagenum);
+ else if (! isepsf)
+ 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(void)
+{
+ if (instring) {
+ stringend();
+ chrcmd('p');
+ }
+ if (dir)
+ cmdout("-90 rotate");
+ if (any_dir)
+ cmdout("dyy");
+ 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(integer rw, integer rh)
+{
+ if (!dir) {
+ numout((integer)hh);
+ numout((integer)vv);
+ } else {
+ numout((integer)vv);
+ numout((integer)-hh);
+ }
+ 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(chardesctype *c, int cc)
+{
+ if (rdir != dir || fdir != curfnt->dir) {
+ if (curfnt->dir == 9)
+ setdir(dir+2);
+ else
+ setdir(dir);
+ rdir = dir;
+ fdir = curfnt->dir;
+ }
+
+ if (curfnt->iswide == 0 && curfnt->codewidth == 2) {
+ Boolean savejflag = jflag;
+ jflag = 1;
+ hvpos();
+ jflag = savejflag;
+ if (lastfont != curfnt->psname)
+ fontout(curfnt->psname);
+ scout2(cc);
+ }
+ else if (curfnt->iswide) {
+ if (lastfont != curfnt->psname)
+ fontout(curfnt->psname);
+ jscout(cc, curfnt->resfont->PSname);
+ }
+ else {
+ if (jflag) {
+ if (!dir){
+ numout(hh);
+ numout(vv);
+ }
+ else {
+ numout(vv);
+ numout(-hh);
+ }
+ chrcmd('a');
+ rhh = hh;
+ rvv = vv;
+ }
+ else hvpos();
+ if (lastfont != curfnt->psname)
+ fontout(curfnt->psname);
+ scout((unsigned char)cc);
+ }
+ if (!dir)
+ rhh = hh + c->pixelwidth; /* rvv = rv */
+ else
+ rvv = vv + c->pixelwidth; /* rhh = rh */
+}
+/*
+ * This routine sends out the document fonts comment.
+ */
+static void
+tell_needed_fonts(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");
+}
+
+static void print_composefont(void)
+{
+ struct header_list *hl = ps_fonts_used;
+ int len;
+ char *q, *p;
+
+ if (hl == 0)
+ return;
+ while (0 != (q=get_name(&hl))) {
+ len = strlen(q);
+ if(len > 11 && (!strncmp(q+len-10, "Identity-H", 10) ||
+ !strncmp(q+len-10, "Identity-V", 10))) {
+ fprintf(bitfile, "%%%%BeginFont: %s\n", q);
+ fprintf(bitfile, "/%s ", q);
+ fprintf(bitfile, "/%s ", q+len-10);
+ fprintf(bitfile, "[/");
+ for(p=q; p <= q+len-12; p++)
+ fprintf(bitfile, "%c", *p);
+ fprintf(bitfile, "] composefont pop\n");
+ fprintf(bitfile, "%%%%EndFont\n");
+ }
+ }
+}
+
+static void setdir(int d)
+{
+ if (instring) {
+ stringend();
+ chrcmd('p');
+ }
+ switch(d) {
+ case 1 :
+ cmdout("dyt");
+ break;
+ case 2 :
+ cmdout("dty");
+ break;
+ case 3 :
+ cmdout("dtt");
+ break;
+ default :
+ cmdout("dyy");
+ break;
+ }
+ linepos += 4;
+ any_dir = 1;
+}
+
+void cmddir(void)
+{
+ if (dir != rdir) {
+ if (dir)
+ cmdout("90 rotate");
+ else
+ cmdout("-90 rotate");
+ rdir = dir;
+ }
+}
+
+static int JIStoSJIS(int c)
+{
+ int high, low;
+ int nh,nl;
+
+ high = (c>>8) & 0xff;
+ low = c & 0xff;
+ nh = ((high-0x21)>>1) + 0x81;
+ if (nh>0x9f)
+ nh += 0x40;
+ if (high & 1) {
+ nl = low + 0x1f;
+ if (low>0x5f)
+ nl++;
+ }
+ else
+ nl = low + 0x7e;
+ if (((nh >= 0x81 && nh <= 0x9f) || (nh >= 0xe0 && nh <= 0xfc)) &&
+ (nl >= 0x40 && nl <= 0xfc && nl != 0x7f))
+ return((nh<<8) | nl);
+ else
+ return(0x813f);
+}