home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Meeting Pearls 3
/
Meeting_Pearls_III.iso
/
Pearls
/
texmf
/
source
/
dvips
/
output.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-27
|
36KB
|
1,336 lines
/*
* 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>
#ifdef OS2
#include <stdlib.h>
#ifdef _MSC_VER
#define popen(pcmd, pmode) _popen(pcmd, pmode)
#define pclose(pstream) _pclose(pstream)
#endif
#endif
/*
* The external routines called here:
*/
#ifdef AMIGA
#include <stdlib.h>
#include "output_protos.h"
#include "dvips_protos.h"
#include "header_protos.h"
#include "search_protos.h"
#include "finclude_protos.h"
#include "download_protos.h"
#include "papersiz_protos.h"
#include "bbox_protos.h"
#include "pipe.h"
static void chrcmd(char);
static int indelta(integer);
static int topoints(integer);
#else
extern void error() ;
extern void send_headers() ;
extern int add_header() ;
extern FILE *search() ;
extern char *getenv() ;
extern void makepsname() ;
extern void handlepapersize() ;
extern void findbb() ;
#endif
/*
* 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 usesPSfonts, headers_off ;
extern Boolean safetyenclose ;
extern Boolean cropmarks ;
extern Boolean tryepsf ;
extern Boolean compressed ;
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 ;
extern char *headerpath ;
extern char errbuf[] ;
extern shalfword linepos ;
extern char *figpath ;
extern struct header_list *ps_fonts_used ;
extern char banner[] ;
extern int gargc ;
extern char **gargv ;
extern struct papsiz *papsizes ;
extern integer hpapersize, vpapersize ;
char preamblecomment[256] ; /* usually "TeX output ..." */
/*
* 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 */
#ifndef AMIGA
static void chrcmd(); /* just a forward declaration */
#endif
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) && !defined(AMIGA)
/* VAXC/MSDOS/AMIGA 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 *begbinary = "\n%%BeginBinary:" ;
void
copyfile(s)
char *s ;
{
FILE *f = NULL ;
int c, prevc = '\n' ;
long len ;
char *bbmatch = begbinary ;
/* begin DOS EPS code */
int doseps = 0;
unsigned long dosepsbegin, dosepsend = 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
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, READ) ;
if (f == 0)
f = search(headerpath, s, READ) ;
#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, "Couldn't find figure file %s; continuing", s) ;
#endif
#endif
break ;
default:
f = search(headerpath, s, READ) ;
(void)sprintf(errbuf, "! Couldn't find header file %s", s) ;
break ;
#ifndef VMCMS
#ifndef MVSXA
#ifndef VMS
#ifndef MSDOS
#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)
f = popen(s, "r") ;
#ifdef OS2
}
#endif
(void)sprintf(errbuf, "Failure to execute %s; continuing", s) ;
#endif
break;
#endif
#endif
#endif
#endif
#endif
#endif
}
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) ;
if (! disablecomments)
if (infigure)
(void)fprintf(bitfile, "%%%%BeginDocument: %s\n", s) ;
else if (infont)
(void)fprintf(bitfile, "%%%%BeginFont: %s\n", infont) ;
else
(void)fprintf(bitfile, "%%%%BeginProcSet: %s\n", s) ;
c = getc(f) ;
if (c == 0x80) {
#if defined MSDOS || defined OS2 || defined(ATARIST)
(void)fclose(f) ; /* close MSDOS font file */
f = search(headerpath, s, READBIN) ; /* reopen in BINARY mode */
(void)sprintf(errbuf, "! Couldn't find header file %s", s) ;
if (f==NULL)
error(errbuf) ;
c = getc(f);
#endif
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 == 13)
(void)putc('\n', bitfile) ;
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)) {
#if defined MSDOS || defined OS2
(void)fclose(f) ; /* close DOS EPS file */
f = search(headerpath, s, READBIN) ;
/* reopen in BINARY mode */
(void)sprintf(errbuf, "! Couldn't find header file %s", s) ;
if (f==NULL)
error(errbuf) ;
fseek(f, 4L, 0);
#endif
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 ;
dosepsend += dosepsbegin;
#if defined MSDOS || defined OS2
(void)fclose(f) ; /* close DOS EPS file */
f = search(headerpath, s, READ) ; /* reopen in TEXT mode */
(void)sprintf(errbuf, "! Couldn't find header file %s", s) ;
if (f==NULL)
error(errbuf) ;
#endif
fseek(f, dosepsbegin, 0);
c = getc(f);
}
else {
rewind(f);
c = getc(f);
}
}
/* end DOS EPS code */
if (c != EOF) {
while (1) {
if (c == *bbmatch) {
bbmatch++ ;
if (*bbmatch == '\0') {
integer size = 0 ;
if (removecomments)
(void)fputs(begbinary, bitfile) ;
(void)putc(c, bitfile) ;
while (1) {
c = getc(f) ;
if (c == ' ')
(void)putc(c, bitfile) ;
else
break ;
}
while ('0' <= c && c <= '9') {
size = size * 10 + c - '0' ;
(void)putc(c, bitfile) ;
c = getc(f) ;
}
while (c != '\r' && c != '\n') {
if (c == EOF)
error("! bad BeginBinary line in epsf") ;
(void)putc(c, bitfile) ;
c = getc(f) ;
}
(void)putc(c, bitfile) ;
for (; size>0; size--) {
c = getc(f) ;
if (c == EOF)
error("! premature end of file in binary section") ;
(void)putc(c, bitfile) ;
}
c = getc(f) ;
if (c == '\n' || c == '\r') {
(void)putc(c, bitfile) ;
c = getc(f) ;
}
if (c != '%')
error("! expected to see %%EndBinary at end of data") ;
while (1) {
(void)putc(c, bitfile) ;
if (c == '\r' || c == '\n')
break ;
c = getc(f) ;
if (c == EOF)
error("! premature end of file in binary section") ;
}
c = getc(f) ;
}
} else
bbmatch = begbinary ;
if (removecomments && c == '%' && prevc == '\n') {
/* skip comments */
/* revised: only skip %% and %! comments */
c = getc(f) ;
if (c == '%' || c == '!') {
while ((c=getc(f))!=EOF) {
if (c == '\n' || c == '\r') {
c = '\n' ;
break ;
}
}
} else {
(void)putc('%', bitfile) ;
if (c != EOF)
(void)putc(c, bitfile) ;
}
#ifdef VMCMS
} else if (c != 0x37 ) {
#else
#ifdef MVSXA
} else if (c != 0x37 ) {
#else
} else if (c != 4) {
#endif
#endif
(void)putc(c, bitfile) ;
}
prevc = c ;
/* begin DOS EPS code */
if (doseps && (ftell(f)>=dosepsend))
break; /* stop at end of DOS EPS PostScript section */
/* end DOS EPS code */
c = getc(f) ;
if (c == EOF)
break ;
else if (c == '\r')
c = '\n' ;
}
}
}
if (prevc != '\n')
(void)putc('\n', bitfile) ;
linepos = 0 ;
#ifndef VMCMS
#ifndef MVSXA
#ifndef VMS
#ifndef MSDOS
#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 (!disablecomments)
if (infigure)
(void)fprintf(bitfile, "%%%%EndDocument\n") ;
else if (infont)
(void)fprintf(bitfile, "%%%%EndFont\n") ;
else
(void)fprintf(bitfile, "%%%%EndProcSet\n") ;
}
}
/*
* For included PostScript graphics, we use the above routine, but
* with no fatal error message.
*/
void figcopyfile(s, systemtype)
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(c)
char c ;
{
if (linepos >= LINELENGTH) {
(void)putc('\n', bitfile) ;
linepos = 0 ;
}
(void)putc(c, bitfile) ;
linepos++ ;
lastspecial = 1 ;
}
void
stringend()
{
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 ;
}
void
scout(c) /* string character out */
char c ;
{
/*
* 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') ;
}
/* 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
cmdout(s)
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(c)
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(n)
float n ;
{
char buf[20] ;
(void)sprintf(buf, "%.2f", n) ;
cmdout(buf) ;
}
void
numout(n)
integer n ;
{
#ifdef AMIGA
char buf[12] ;
#else
char buf[10] ;
#endif
#ifdef SHORTINT
(void)sprintf(buf, "%ld", n) ;
#else
(void)sprintf(buf, "%d", n) ;
#endif
cmdout(buf) ;
}
void
mhexout(p, len)
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(n)
int n ;
{
char buf[6] ;
if (instring) {
stringend() ;
chrcmd('p') ;
}
makepsname(buf, n) ;
cmdout(buf) ;
}
void
hvpos()
{
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()
{
if (linepos != 0) {
(void)fprintf(bitfile, "\n") ;
linepos = 0 ;
}
lastspecial = 1 ;
}
void
nlcmdout(s)
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(i)
integer i ;
{
if (i < 0)
i = -i ;
return (i <= 1184072) ;
}
/*
* A case-irrelevant string compare.
*/
int mlower(c)
int c ;
{
if ('A' <= c && c <= 'Z')
return c - 'A' + 'a' ;
else
return c ;
}
int ncstrcmp(a, b)
char *a, *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() {
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(i)
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(s, hed)
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')
#if defined(AMIGA) && defined(__SASC)
(void)fputc(*s++, bitfile) ; /* default putc is a macro on SAS/C */
#else
(void)putc(*s++, bitfile) ;
#endif
putc('\n', bitfile) ;
} else {
while (*s && *s != '\n')
s++ ;
}
}
}
char *epsftest() {
if (tryepsf && totalpages == 1 && paperfmt == 0 && *iname) {
findbb() ;
return nextstring ;
}
return 0 ;
}
static char *isepsf = 0 ;
static int endprologsent ;
void
initprinter(n)
int n ; /* number of pages if greater than 0 */
{
void tell_needed_fonts() ;
n *= pagecopies * collatedcopies ;
if (*oname != 0) {
/*
* We check to see if the first character is a exclamation
* point, and popen if so.
*/
if (*oname == '!' || *oname == '|') {
#ifdef MSDOS
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
if (secure || (bitfile=popen(oname+1, "w"))==NULL)
error("! couldn't open output pipe") ;
else
popened = 1 ;
#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 ;
}
findpapersize() ;
if (disablecomments)
(void)fprintf(bitfile,
"%%!PS (but not EPSF; comments have been disabled)\n") ;
else {
if (multiplesects)
(void)fprintf(bitfile,
"%%!PS (but not EPSF because of memory limits)\n") ;
else {
isepsf = epsftest() ;
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", 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", (n ? 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, "%%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() {
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") ;
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") ;
}
if (endprologsent == 0 && !disablecomments) {
newline() ;
endprologsent = 1 ;
if (! multiplesects)
(void)fprintf(bitfile, "%%%%EndSetup\n") ;
}
}
/*
* cleanprinter is the antithesis of the above routine.
*/
void
cleanprinter()
{
(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.") ;
#ifndef MSDOS
#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() {
rulex = ruley = rhh = rvv = -314159265 ;
lastfont = -1 ;
}
/*
* pageinit initializes the output variables.
*/
void
pageinit()
{
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 ;
numout((integer)pagenum) ;
numout((integer)thispage-1) ;
cmdout("bop") ;
d = 0 ;
}
/*
* This routine ends a page.
*/
void
pageend()
{
if (instring) {
stringend() ;
chrcmd('p') ;
}
cmdout("eop") ;
}
/*
* 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(rw, rh)
integer rw, 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(c, cc)
chardesctype *c ;
int cc ;
{
hvpos() ;
if (lastfont != curfnt->psname) {
fontout((int)curfnt->psname) ;
lastfont = curfnt->psname ;
}
scout(cc) ;
rhh = hh + c->pixelwidth ; /* rvv = rv */
}
/*
* This routine sends out the document fonts comment.
*/
void tell_needed_fonts() {
struct header_list *hl = ps_fonts_used ;
char *q ;
int roomleft = -1 ;
extern char *get_name() ;
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") ;
}