home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mega CD-ROM 1
/
megacd_rom_1.zip
/
megacd_rom_1
/
POSTSCRI
/
DVIPS54.ZIP
/
DVIPS
/
OUTPUT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-11-25
|
15KB
|
609 lines
/*
* These routines do most of the communicating with the printer.
*
* LINELENGTH tells the maximum line length to send out.
*/
#define LINELENGTH (78)
#include "structures.h" /* The copyright notice in that file is included too! */
#include <ctype.h>
/*
* The external routines called here:
*/
extern void error() ;
extern void send_headers() ;
extern FILE *search() ;
extern char *getenv() ;
extern void fonttableout() ;
extern void makepsname() ;
/*
* These are the external variables used by these routines.
*/
extern integer hh, vv ;
extern fontdesctype *curfnt ;
extern FILE *bitfile ;
extern char *oname ;
extern Boolean reverse ;
extern Boolean removecomments ;
extern Boolean sendcontrolD, disablecomments, multiplesects ;
extern Boolean usesPSfonts, headers_off ;
extern Boolean safetyenclose ;
extern int numcopies ;
extern int totalpages ;
extern integer pagenum ;
extern Boolean manualfeed ;
extern int landscape ;
extern int quiet ;
extern int prettycolumn ;
extern int actualdpi ;
extern char *iname ;
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[] ;
/*
* 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(); /* just a forward declaration */
static char strbuffer[LINELENGTH + 20], *strbp = strbuffer ;
static struct {
char *format;
int width, height;
} paper_types[] = {
{ "letter", 612, 792 }, /* 8.5 x 11 */
{ "legal", 612, 1008 }, /* 8.5 x 14 */
{ "ledger", 792, 1224 }, /* 11 x 17 */
{ "a4", 596, 843 }, /* 210mm x 297mm */
{ "a3", 843, 1192 } }; /* 297mm x 420mm */
/*
* This routine copies a file down the pipe. Search path uses the
* header path.
*/
static int infigure ;
void
copyfile(s)
char *s ;
{
FILE *f ;
int c, prevc = '\n' ;
switch (infigure) {
case 1:
f = search(figpath, s, READ) ;
(void)sprintf(errbuf, "Couldn't find figure file %s; continuing", s) ;
break ;
default:
f = search(headerpath, s, READ) ;
(void)sprintf(errbuf, "! Couldn't find header file %s", s) ;
break ;
#ifndef VMS
#ifndef MSDOS
case 2:
f = popen(s, "r") ;
(void)sprintf(errbuf, "Failure to execute %s; continuing", s) ;
break;
#endif
#endif
}
if (f==NULL)
error(errbuf) ;
else {
if (! quiet) {
if (strlen(s) + prettycolumn > 76) {
fprintf(stderr, "\n") ;
prettycolumn = 0 ;
}
(void)fprintf(stderr, "<%s>", s) ;
(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
(void)fprintf(bitfile, "%%%%BeginProcSet: %s\n", s) ;
while ((c=getc(f))!=EOF && c != 4) {
if (! removecomments && c == '%' && prevc == '\n') {/* skip comments */
while ((c=getc(f))!=EOF) {
if (c=='\n')
break ;
}
} else
(void)putc(c, bitfile) ;
prevc = c ;
}
if (prevc != '\n')
(void)putc('\n', bitfile) ;
linepos = 0 ;
#ifndef VMS
#ifndef MSDOS
if (infigure == 2)
(void)pclose(f) ;
else
#endif
#endif
(void)fclose(f) ;
if (!disablecomments)
if (infigure)
(void)fprintf(bitfile, "%%%%EndDocument\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') ;
}
if (c<' ' || c>126 || c=='%') {
*strbp++ = '\\' ;
*strbp++ = '0' + ((c >> 6) & 3) ;
*strbp++ = '0' + ((c >> 3) & 7) ;
*strbp++ = '0' + (c & 7) ;
instring += 4 ;
} else 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 ;
{
char buf[10] ;
(void)sprintf(buf, "%ld", n) ;
cmdout(buf) ;
}
void
mhexout(p, len)
register unsigned char *p ;
register long len ;
{
register char *hexchar = "0123456789ABCDEF" ;
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) {
chrcmd((char)('p' + hh - rhh)) ;
} else if (hh - rhh < d + 5 && rhh - hh < 5 - d) {
chrcmd((char)('g' + hh - rhh - d)) ;
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() ;
}
void
initprinter()
{
void tell_needed_fonts() ;
int i;
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
if ((bitfile=popen(oname+1, "w"))==NULL)
error("! couldn't open output pipe") ;
else
popened = 1 ;
#endif
#endif
} else {
if ((bitfile=fopen(oname,"w"))==NULL)
error("! couldn't open PostScript file") ;
}
} else {
bitfile = stdout ;
}
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 (void)fprintf(bitfile, "%%!PS-Adobe-2.0\n") ;
(void)fprintf(bitfile, "%%%%Creator: %s", banner + 8) ;
if (*iname)
(void)fprintf(bitfile, "%%%%Title: %s\n", iname) ;
(void)fprintf(bitfile, "%%%%Pages: %d %d\n", totalpages, 1 - 2*reverse) ;
for (i=0; i<sizeof(paper_types)/sizeof(paper_types[0]); ++i)
if (strcmp(paperfmt,paper_types[i].format)==0)
(void)fprintf(bitfile, "%%%%BoundingBox: 0 0 %d %d\n",
paper_types[i].width, paper_types[i].height) ;
tell_needed_fonts() ;
(void)fprintf(bitfile, "%%%%EndComments\n") ;
}
if (safetyenclose)
(void)fprintf(bitfile, "/SafetyEnclosure save def\n") ;
if (! headers_off)
send_headers() ;
}
static int endprologsent ;
void setup() {
newline() ;
if (endprologsent == 0 && !disablecomments) {
fonttableout() ;
(void)fprintf(bitfile, "%%%%EndProlog\n") ;
(void)fprintf(bitfile, "%%%%BeginSetup\n") ;
(void)fprintf(bitfile, "%%%%Feature: *Resolution %d\n", DPI) ;
if (manualfeed)
(void)fprintf(bitfile, "%%%%Feature: *ManualFeed True\n") ;
}
cmdout("TeXDict") ;
cmdout("begin") ;
{
char pft[100] ;
strcpy(pft, "@") ;
if (landscape)
strcat(pft, "landscape") ;
else
strcat(pft, paperfmt) ;
strcat(pft, " /") ;
strcat(pft, paperfmt) ;
strcat(pft, " where {pop ") ;
strcat(pft, paperfmt) ;
strcat(pft, "} if") ;
cmdout(pft) ;
}
if (manualfeed) cmdout("@manualfeed") ;
if (numcopies != 1) {
numout((integer)numcopies) ;
cmdout("@copies") ;
}
if (endprologsent == 0 && !disablecomments) {
newline() ;
endprologsent = 1 ;
(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) ;
#ifndef MSDOS
#ifndef VMS
if (popened)
(void)pclose(bitfile) ;
#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() ;
if (!disablecomments && !multiplesects)
(void)fprintf(bitfile, "%%%%Page: %ld %d\n", pagenum, ++thispage) ;
linepos = 0 ;
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 (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") ;
}