From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- dviware/psprint/unix/00readme.txt | 125 +++ dviware/psprint/unix/bad.ps | 19 + dviware/psprint/unix/box.ps | 12 + dviware/psprint/unix/build | 9 + dviware/psprint/unix/ctrld | 1 + dviware/psprint/unix/dvireader.h | 143 ++++ dviware/psprint/unix/dvireader.p | 1495 ++++++++++++++++++++++++++++++++++ dviware/psprint/unix/files.h | 17 + dviware/psprint/unix/fontlist.ps | 97 +++ dviware/psprint/unix/fontreader.h | 9 + dviware/psprint/unix/fontreader.p | 926 +++++++++++++++++++++ dviware/psprint/unix/fontsample.tex | 241 ++++++ dviware/psprint/unix/globals.h | 14 + dviware/psprint/unix/greybox.ps | 31 + dviware/psprint/unix/info.ps | 107 +++ dviware/psprint/unix/lino_fonts.ps | 68 ++ dviware/psprint/unix/lino_header.ps | 273 +++++++ dviware/psprint/unix/lino_pages.ps | 16 + dviware/psprint/unix/lino_trailer.ps | 1 + dviware/psprint/unix/lw_fonts.ps | 43 + dviware/psprint/unix/lw_header.ps | 136 ++++ dviware/psprint/unix/lw_trailer.ps | 1 + dviware/psprint/unix/nasty.tex | 349 ++++++++ dviware/psprint/unix/options.h | 44 + dviware/psprint/unix/options.p | 469 +++++++++++ dviware/psprint/unix/piechart.ps | 68 ++ dviware/psprint/unix/ps.ps | 20 + dviware/psprint/unix/ps40_fonts.ps | 39 + dviware/psprint/unix/ps40_header.ps | 67 ++ dviware/psprint/unix/psdvi.p | 859 +++++++++++++++++++ dviware/psprint/unix/psfonts.tex | 69 ++ dviware/psprint/unix/psprint | 403 +++++++++ dviware/psprint/unix/psprint.man | 358 ++++++++ dviware/psprint/unix/pstext.tex | 73 ++ dviware/psprint/unix/pswriter.h | 58 ++ dviware/psprint/unix/pswriter.p | 340 ++++++++ dviware/psprint/unix/random.ps | 39 + dviware/psprint/unix/setmargins.ps | 7 + dviware/psprint/unix/test.tex | 13 + dviware/psprint/unix/tex.ps | 236 ++++++ dviware/psprint/unix/text.ps | 83 ++ dviware/psprint/unix/two.ps | 119 +++ dviware/psprint/unix/userguide.tex | 563 +++++++++++++ dviware/psprint/unix/wide.ps | 117 +++ 44 files changed, 8177 insertions(+) create mode 100644 dviware/psprint/unix/00readme.txt create mode 100644 dviware/psprint/unix/bad.ps create mode 100644 dviware/psprint/unix/box.ps create mode 100644 dviware/psprint/unix/build create mode 100644 dviware/psprint/unix/ctrld create mode 100644 dviware/psprint/unix/dvireader.h create mode 100644 dviware/psprint/unix/dvireader.p create mode 100644 dviware/psprint/unix/files.h create mode 100644 dviware/psprint/unix/fontlist.ps create mode 100644 dviware/psprint/unix/fontreader.h create mode 100644 dviware/psprint/unix/fontreader.p create mode 100644 dviware/psprint/unix/fontsample.tex create mode 100644 dviware/psprint/unix/globals.h create mode 100644 dviware/psprint/unix/greybox.ps create mode 100644 dviware/psprint/unix/info.ps create mode 100644 dviware/psprint/unix/lino_fonts.ps create mode 100644 dviware/psprint/unix/lino_header.ps create mode 100644 dviware/psprint/unix/lino_pages.ps create mode 100644 dviware/psprint/unix/lino_trailer.ps create mode 100644 dviware/psprint/unix/lw_fonts.ps create mode 100644 dviware/psprint/unix/lw_header.ps create mode 100644 dviware/psprint/unix/lw_trailer.ps create mode 100644 dviware/psprint/unix/nasty.tex create mode 100644 dviware/psprint/unix/options.h create mode 100644 dviware/psprint/unix/options.p create mode 100644 dviware/psprint/unix/piechart.ps create mode 100644 dviware/psprint/unix/ps.ps create mode 100644 dviware/psprint/unix/ps40_fonts.ps create mode 100644 dviware/psprint/unix/ps40_header.ps create mode 100644 dviware/psprint/unix/psdvi.p create mode 100644 dviware/psprint/unix/psfonts.tex create mode 100644 dviware/psprint/unix/psprint create mode 100644 dviware/psprint/unix/psprint.man create mode 100644 dviware/psprint/unix/pstext.tex create mode 100644 dviware/psprint/unix/pswriter.h create mode 100644 dviware/psprint/unix/pswriter.p create mode 100644 dviware/psprint/unix/random.ps create mode 100644 dviware/psprint/unix/setmargins.ps create mode 100644 dviware/psprint/unix/test.tex create mode 100644 dviware/psprint/unix/tex.ps create mode 100644 dviware/psprint/unix/text.ps create mode 100644 dviware/psprint/unix/two.ps create mode 100644 dviware/psprint/unix/userguide.tex create mode 100644 dviware/psprint/unix/wide.ps (limited to 'dviware/psprint/unix') diff --git a/dviware/psprint/unix/00readme.txt b/dviware/psprint/unix/00readme.txt new file mode 100644 index 0000000000..f94dcb9723 --- /dev/null +++ b/dviware/psprint/unix/00readme.txt @@ -0,0 +1,125 @@ +PSPRINT 3.0 for UNIX, October 1989 +================================== +Andrew Trevorrow + +PSPRINT is a public-domain PostScript driver that can print a DVI file, +raw PostScript program, or text file on a variety of PostScript printers. +Currently supported printers are the Apple LaserWriter, DEC's PrintServer 40 +and the Linotronic 300. + +This version of PSPRINT was developed on a Pyramid running OS/x. +It should be reasonably easy to port the program to any other UNIX system +with a Pascal compiler. + +Installation +------------ + +1. Use Build to create the psdvi program. + You may need to change the Pascal source files to suit your compiler. +2. Make sure all the files in this directory are world readable or executable. +3. Copy psprint into something like /usr/bin, edit it and make any changes to + suit your site (see in particular the values flagged by SYSDEP). + +The important files in this directory +------------------------------------- + +Executable files: +psprint script that users run +psdvi program run by psprint to turn DVI file into PostScript +Build compiles and links psdvi + +Documentation and help files: +userguide.tex LaTeX source for the PSPRINT User Guide +piechart.ps used in userguide.tex to produce Figure 1 +greybox.ps used in userguide.tex to produce Figure 2 +random.ps used in userguide.tex to produce Figure 3 +psfonts.tex illustrates use of PostScript fonts in a TeX document +pstext.tex used in psfonts.tex; defines \PStext and \CMtext +psprint.man source file for on-line help + +Pascal source files: +psdvi.p the main module for psdvi +globals.h global data and routines +files.h random file i/o routines +options.h/p command line interface routines +dvireader.h/p DVI file access routines +fontreader.h/p PK and TFM file access routines +pswriter.h/p PostScript generating routines + +Test files: +nasty.tex TeX source for nasty.dvi, a torture test for psdvi +bad.ps used by nasty.tex; contains deliberate PostScript error +box.ps used by nasty.tex; draws a box +empty.ps used by nasty.tex; empty file +test.tex TeX source for test.dvi; tests origin position + +These files are used by psprint: +ps.ps prologue for a PostScript job +tex.ps prologue for a DVI job +text.ps prologue for a text job +two.ps prologue for a two-page-per-sheet text job +wide.ps prologue for a two-wide-page-per-sheet text job +ctrld contains ^D (sent at end of each lw/lino job) +lw_header.ps defines @bannerpage and error handler +lw_trailer.ps calls @bannerpage +lw_fonts.ps converts TFM names to LaserWriter font names +lino_header.ps defines @bannerpage, @footerpage, error handler, etc. +lino_trailer.ps calls @footerpage +lino_fonts.ps converts TFM names to Linotronic font names +ps40_header.ps defines error handler +ps40_fonts.ps converts TFM names to PrintServer font names + +Other useful files: +fontsample.tex TeX source for producing font samples +fontlist.ps prints a list of the available fonts in your printer +info.ps to discover various printer details +lino_pages.ps tests various page setups available in Linotronic +setmargins.ps permanently adjusts margin settings in LaserWriter + +Revision history +---------------- + +Version 1.0 was released in January 1988 and was based on an Apollo DOMAIN +Pascal version (which in turn was based on a VAX/VMS Modula-2 version). + +Version 3.0 was released in October 1988 and corresponds to +VAX/VMS version 3.0 of PSPRINT. Here are the changes to version 1.0: + +Changes to psprint: + - Many new options have been added: + -device lw/lino/ps40 specifies the type of PostScript printer + -two will print a text file with two 60-line by 80-col "pages" per A4 sheet + -wide will print a text file with two 60-line by 132-col "pages" per A4 sheet + -o file saves the PostScript code in given file rather than printing it + -q queue overrides the default queue + -n string includes given string on the flag page + -i integer allows you to print every ith page in the current page range + -conserve/-noconserve control the conservation of VM + -reverse/-noreverse control the order in which pages are printed + -flag/-noflag control whether or not a flag page is produced + -manual instructs a LaserWriter to wait for paper to be fed manually + -cutmarks/-nocutmarks control whether or not cut marks appear on Lino output + -size a3l/a4p/a4l/a5p/a5l/b5p/b5l specifies which Lino page setup to use + -lowres switches Linotronic DVI output to "low" resolution (635dpi) + -ho dimension shifts DVI output horizontally by given amount + -vo dimension shifts DVI output vertically by given amount + - A single .tmp file is now created and queued for printing + (or renamed if "-o file" is used). + - A PSPRINT User Guide has been written. + +Changes to psdvi: + - The version number is now displayed if -s is used. + - psdvi can now handle PostScript fonts. + The -P (psprefix) option defines the unique font name prefix used to + recognize a PostScript font and the -T (tfmdir) option defines the + location of the TFM files for these fonts. + - The -ho and -vo options allow horizontal and vertical margin shifting. + - The -f (fontdir) option value must end with '/' (as must -t) and is now + automatically prepended to the -d (dummyfont) option value. + - The limitation requiring a fixed-length fontsize substring in PK file names + has been removed. + - The search for the end of a DVI file now allows for trailing NUL-bytes + (after the terminating 223-bytes) to cope with DVI files that have been + transferred to and from a VMS machine. + - The copying of header and special files in PSWriter has been speeded up. + - The generation of bitmap hex data in FontReader has been speeded up. diff --git a/dviware/psprint/unix/bad.ps b/dviware/psprint/unix/bad.ps new file mode 100644 index 0000000000..e419ef5eb6 --- /dev/null +++ b/dviware/psprint/unix/bad.ps @@ -0,0 +1,19 @@ +% this file contains deliberate PS error(s) to test error handling + +/Courier findfont 20 scalefont setfont +72 72 moveto +(hello) show + +% put a few objects on stack before error + +999999 +mark +/abc +(abc) +[ 0.99 (ABC) /xyz ] +{ 1 } +true + +xxx % undefined + +showpage diff --git a/dviware/psprint/unix/box.ps b/dviware/psprint/unix/box.ps new file mode 100644 index 0000000000..b9dfb348ae --- /dev/null +++ b/dviware/psprint/unix/box.ps @@ -0,0 +1,12 @@ +72 72 scale % units are now inches instead of big points + +newpath + 0 0 moveto % bottom left corner at origin + 0 1 rlineto + 1 0 rlineto + 0 -1 rlineto + closepath + .1 setlinewidth +stroke + +showpage % redefined to do nothing if this file included in TeX \special diff --git a/dviware/psprint/unix/build b/dviware/psprint/unix/build new file mode 100644 index 0000000000..a25ff3e61c --- /dev/null +++ b/dviware/psprint/unix/build @@ -0,0 +1,9 @@ +# Compile (with optimization) and link PSDVI. +# +echo options.p ; pascal -OPG -f -c options.p +echo dvireader.p ; pascal -OPG -f -c dvireader.p +echo fontreader.p ; pascal -OPG -f -c fontreader.p +echo pswriter.p ; pascal -OPG -f -c pswriter.p +echo psdvi.p ; pascal -OPG -f -c psdvi.p +echo linking psdvi... +pascal *.o -o psdvi diff --git a/dviware/psprint/unix/ctrld b/dviware/psprint/unix/ctrld new file mode 100644 index 0000000000..ce9a8a9d59 --- /dev/null +++ b/dviware/psprint/unix/ctrld @@ -0,0 +1 @@ + diff --git a/dviware/psprint/unix/dvireader.h b/dviware/psprint/unix/dvireader.h new file mode 100644 index 0000000000..0a0db2c07a --- /dev/null +++ b/dviware/psprint/unix/dvireader.h @@ -0,0 +1,143 @@ +(* DVIReader *) + +CONST + ruletablesize = 300; (* maximum number of rules in a ruletable *) + ruletablesizem = ruletablesize - 1; + chartablesize = 3000; (* maximum number of chars in a chartable *) + chartablesizem = chartablesize - 1; + maxfontspec = maxstring; (* max length of a font file specification *) + maxspeciallen = maxstring; (* max length of \special string *) + maxTeXchar = 255; (* ignore character codes > 255 *) + +TYPE + (* Information about the rules and characters appearing on a page is stored + in dynamic one-way lists to avoid imposing any limit on their numbers. + To reduce pointer overheads, the nodes in these lists contain large + tables (the values of ruletablesize and chartablesize have been chosen + so that the vast majority of DVI pages will only require one-node lists). + When interpreting a DVI page, DVIReader adds a new rule or character node + to the TAIL of the relevant list so that when the main program + accesses such lists (starting at the head), rules and characters will be + processed in somewhat the same sequence as seen in the DVI file; i.e., + top-to-bottom and left-to-right across the page. + Since a character list is part of the information stored for a font, + the precise sequence in which DVI characters are seen is not remembered. + Font information is also linked together in a one-way list, but the + ordering is more or less random (see, however, the SortFonts routine). + *) + ruleinfoptr = ^ruleinfo; + ruleinfo = (* a node in a list of ruletables *) + RECORD + rulecount : INTEGER; (* number of rules in ruletable *) + ruletable : ARRAY [0..ruletablesizem] OF + RECORD + hp, vp : INTEGER; (* pixel coords of rule's ref point *) + wd, ht : INTEGER; (* dimensions of rule in pixels *) + END; + nextrule : ruleinfoptr; (* next node in rule list *) + END; + + charinfoptr = ^charinfo; + charinfo = (* a node in list of chartables *) + RECORD + charcount : INTEGER; (* number of chars in chartable *) + chartable : ARRAY [0..chartablesizem] OF + RECORD + hp, vp : INTEGER; (* pixel coords of char's ref point *) + code : 0..maxTeXchar; (* char's code and pixeltable index *) + END; + nextchar : charinfoptr; (* next node in char list *) + END; + + (* DVIReader uses wd, ht, xo and yo to calculate minhp, minvp, maxhp and + maxvp. dwidth and pwidth are used to advance horizontally. + The mapadr and loaded fields are not used by DVIReader; they are used + by FontReader and the main program to load character bitmaps. + *) + pixeltableptr = ^pixeltable; + pixeltable = ARRAY [0..maxTeXchar] OF + RECORD + wd, ht : INTEGER; (* glyph width and height in pixels; they + define the size of the smallest box + containing all the black pixels *) + xo, yo : INTEGER; (* x and y offsets from top left corner + of glyph to character's reference point *) + dwidth : INTEGER; (* advance width in DVI units computed from + fix width stored in font file *) + pwidth : INTEGER; (* advance width in pixels computed from + fix width stored in font file *) + mapadr : INTEGER; (* byte offset of bitmap info in font file *) + loaded : BOOLEAN; (* has bitmap been downloaded? *) + END; + + fontinfoptr = ^fontinfo; + fontinfo = (* a node in list of fonts *) + RECORD + psfont : BOOLEAN; (* is this a PostScript font? *) + fontused : BOOLEAN; (* is font used on current page? *) + fontnum : INTEGER; (* DVI font number: -2^31 .. 2^30 - 1 *) + scaledsize : INTEGER; (* scaled font size in DVI units *) + designsize : INTEGER; (* design size in DVI units *) + fontarea : string; (* explicit font directory *) + fontarealen : INTEGER; (* length of fontarea *) + fontname : string; (* font name; e.g., "cmr10" *) + fontnamelen : INTEGER; (* length of font name *) + fontspec : string; (* complete font file pathname *) + fontspeclen : INTEGER; (* length of fontspec *) + fontexists : BOOLEAN; (* can fontspec be opened? *) + fontid : string; (* unique font identifier *) + totalchars : INTEGER; (* number of chars from font on page *) + charlist : charinfoptr; (* head of char information list *) + chartail : charinfoptr; (* tail of char information list *) + pixelptr : pixeltableptr; (* allocated once: 1st time font used *) + nextfont : fontinfoptr; (* next node in font list *) + END; + + (* For the parameter in MoveToTeXPage: *) + TeXcounters = ARRAY [0..9] OF INTEGER; + TeXpageinfo = + RECORD + value : TeXcounters; (* \count0..\count9 values *) + present : ARRAY [0..9] OF BOOLEAN; (* is counter relevant? *) + lastvalue : 0..9; (* last relevant counter *) + END; + + (* DVIReader also builds a list of \special info: *) + specialinfoptr = ^specialinfo; + specialinfo = RECORD + special : string; + hp, vp : INTEGER; + nextspecial : specialinfoptr; + END; + + +VAR + (* Most of these should be treated as read-only parameters: *) + DVImag : INTEGER; (* magnification stored in DVI file *) + totalpages : INTEGER; (* number of pages in DVI file *) + totalfonts : INTEGER; (* number of fonts in DVI file *) + currDVIpage : INTEGER; (* updated by MoveTo... calls *) + currTeXpage : TeXcounters; (* ditto *) + speciallist : specialinfoptr; (* head of \special information list *) + totalrules : INTEGER; (* number of rules on current page *) + rulelist : ruleinfoptr; (* head of rule information list *) + ruletail : ruleinfoptr; (* tail of rule information list *) + fontlist : fontinfoptr; (* head of font information list *) + currfont : fontinfoptr; (* InterpretPage's current font info *) + pageempty : BOOLEAN; (* is page empty of rules and chars? *) + minhp : INTEGER; (* minimum horizontal pixel coordinate *) + minvp : INTEGER; (* minimum vertical pixel coordinate *) + maxhp : INTEGER; (* maximum horizontal pixel coordinate *) + maxvp : INTEGER; (* maximum vertical pixel coordinate *) + +PROCEDURE InitDVIReader; EXTERNAL; +PROCEDURE OpenDVIFile (name : string); EXTERNAL; +PROCEDURE SetConversionFactor (resolution, magnification : INTEGER); EXTERNAL; +FUNCTION PixelRound (DVIunits : INTEGER) : INTEGER; EXTERNAL; +PROCEDURE MoveToDVIPage (n : INTEGER); EXTERNAL; +PROCEDURE MoveToNextPage (ascending : BOOLEAN); EXTERNAL; +FUNCTION MoveToTeXPage (VAR newTeXpage : TeXpageinfo) : BOOLEAN; EXTERNAL; +FUNCTION CurrMatchesNew (VAR newTeXpage : TeXpageinfo) : BOOLEAN; EXTERNAL; +PROCEDURE InterpretPage; EXTERNAL; +PROCEDURE SortFonts (VAR unusedlist : fontinfoptr); EXTERNAL; +PROCEDURE CloseDVIFile; EXTERNAL; diff --git a/dviware/psprint/unix/dvireader.p b/dviware/psprint/unix/dvireader.p new file mode 100644 index 0000000000..152a8d6844 --- /dev/null +++ b/dviware/psprint/unix/dvireader.p @@ -0,0 +1,1495 @@ +(* Routines and data structures for use in a TeX82 DVI translator. + Much of the code in DVIReader is based on DVITYPE 2.7 by Donald Knuth. + DVITYPE is a program for verifying a DVI file and also serves as a model + for other DVI-reading programs. See the TeXWARE manual by Knuth for a + complete description of DVITYPE and the format of DVI files. + For efficiency reasons we assume the given DVI file is formatted correctly; + it is the job of DVITYPE to diagnose bad DVI files. +*) + +#include 'globals.h'; +#include 'files.h'; +#include 'dvireader.h'; +#include 'fontreader.h'; +#include 'fontreader.h'; (* only PixelTableRoutine *) +#include 'options.h'; (* hoffset and voffset *) + +(******************************************************************************* + DECLARATIONS FOR ACCESSING BYTES IN A DVI FILE + + A DVI file is a stream of 8-bit bytes. Once opened, we can access any byte + by setting DVIoffset to the required position and then calling GetDVIByte. +*) + +VAR + DVIfile : integer; (* DVI file descriptor *) + DVIoffset : INTEGER; (* current byte offset in DVIfile *) + currDVIbuff : INTEGER; (* starting byte offset in buffer *) + DVIbuff : buffer; (* input buffer *) + postpostid : INTEGER; (* offset of postpost's id byte *) + +(******************************************************************************* + DECLARATIONS FOR GETTING TO A DVI PAGE + + The user can select a particular page by specifying a DVI page + number (from 1 to totalpages), or a TeX page number (based on the + values of \count0,\count1,...,\count9), or simply requesting the next page + in the DVI file (which depends on whether we are ascending or not). + We will often need to follow the DVI backpointers to locate the bop byte + of a selected page. +*) + +VAR + curreop, (* position of eop byte of current page *) + currbop, (* position of bop byte of current page *) + lastbop : INTEGER; (* position of last bop byte *) + prevbop : INTEGER; (* position of bop byte of previous page; + note that prevbop of first page = -1 *) + +(******************************************************************************* + DECLARATIONS FOR INTERPRETING A DVI PAGE + + The commands between the bop and eop bytes for a particular page need to be + translated (based on the method used by DVITYPE) before we can determine the + the position and shape of all rules on that page, as well as the position + of all characters and which fonts they belong to. +*) + +CONST + (* Use symbolic names for the opcodes of DVI commands: *) + setchar0 = 0; (* setchar1..setchar127 = 1..127 *) + set1 = 128; (* set2,set3,set4 = 129,130,131 *) + setrule = 132; + put1 = 133; (* put2,put3,put4 = 134,135,136 *) + putrule = 137; + nop = 138; + bop = 139; + eop = 140; + push = 141; + pop = 142; + right1 = 143; w0 = 147; x0 = 152; down1 = 157; y0 = 161; z0 = 166; + right2 = 144; w1 = 148; x1 = 153; down2 = 158; y1 = 162; z1 = 167; + right3 = 145; w2 = 149; x2 = 154; down3 = 159; y2 = 163; z2 = 168; + right4 = 146; w3 = 150; x3 = 155; down4 = 160; y3 = 164; z3 = 169; + w4 = 151; x4 = 156; y4 = 165; z4 = 170; + fntnum0 = 171; (* fntnum1..fntnum63 = 172..234 *) + fnt1 = 235; (* fnt2,fnt3,fnt4 = 236,237,238 *) + xxx1 = 239; (* xxx2,xxx3,xxx4 = 240,241,242 *) + fntdef1 = 243; (* fntdef2,fntdef3,fntdef4 = 244,245,246 *) + pre = 247; + post = 248; + postpost = 249; + (* undefined commands = 250..255 *) + + maxstacksize = 100; (* maximum stack size for state values *) + maxstacksizem = maxstacksize - 1; + maxdrift = 2; (* prevent hh & vv from drifting too far *) + maxint = 2147483647; (* 2^31 - 1 *) + +VAR + DVIcommand : 0..255; (* holds next DVI command *) + maxstack, (* max pushes over pops in DVI file *) + num, (* DVI numerator *) + den : INTEGER; (* DVI denominator *) + conv : REAL; (* converts DVI units to pixels *) + h, v, (* current pos on page in DVI units *) + w, x, (* horizontal increments in DVI units *) + y, z, (* vertical increments in DVI units *) + hh, vv : INTEGER; (* h and v in pixels (approx) *) + hhh, vvv : INTEGER; (* h and v rounded to nearest pixel *) + hstack, vstack, (* push down stacks for state values *) + wstack, xstack, + ystack, zstack, + hhstack, vvstack : ARRAY [0..maxstacksizem] OF INTEGER; + stackpos : 0..maxstacksize; (* stacks empty when stackpos = 0, + i.e., top of stacks = stackpos - 1 *) + fontspace : INTEGER; (* used in DoRight and DoDown *) + thisrule : ruleinfoptr; (* temporary pointer to node in rulelist *) + thischar : charinfoptr; (* temporary pointer to node in charlist *) + thisspecial : specialinfoptr; (* temporary ptr to node in speciallist *) + + +(******************************************************************************) + +(* Here are the functions used to get byte/s from DVIfile. + They are essentially the same as those used in DVITYPE. +*) + +FUNCTION GetDVIByte : INTEGER; + +(* Returns the value (unsigned) of the byte at DVIoffset and + advances DVIoffset for the next GetDVIByte. + Buffering is used to reduce the number of IOS calls. +*) + +VAR buffstart, result : INTEGER; + +BEGIN +buffstart := (DVIoffset DIV bufflen) * bufflen; (* 0, bufflen, 2*bufflen... *) +IF buffstart <> currDVIbuff THEN BEGIN + currDVIbuff := buffstart; + result := lseek(DVIfile, buffstart, 0); + { DEBUG + IF result <> buffstart THEN BEGIN + writeln('Lseek failed in GetDVIByte!'); exit(1); + END; + GUBED } + result := read(DVIfile, DVIbuff, bufflen); + { DEBUG + IF result = -1 THEN BEGIN + writeln('Read failed in GetDVIByte!'); exit(1); + END; + GUBED } +END; +GetDVIByte := ORD(DVIbuff[DVIoffset - buffstart]); +DVIoffset := DVIoffset + 1; +END; (* GetDVIByte *) + +(******************************************************************************) + +FUNCTION SignedDVIByte : INTEGER; (* the next byte, signed *) + +VAR b : INTEGER; + +BEGIN +b := GetDVIByte; +IF b < 128 THEN + SignedDVIByte := b +ELSE + SignedDVIByte := b - 256; +END; (* SignedDVIByte *) + +(******************************************************************************) + +FUNCTION GetTwoDVIBytes : INTEGER; (* the next 2 bytes, unsigned *) + +VAR a, b : INTEGER; + +BEGIN +a := GetDVIByte; +b := GetDVIByte; +GetTwoDVIBytes := a * 256 + b; +END; (* GetTwoDVIBytes *) + +(******************************************************************************) + +FUNCTION SignedDVIPair : INTEGER; (* the next 2 bytes, signed *) + +VAR a, b : INTEGER; + +BEGIN +a := GetDVIByte; +b := GetDVIByte; +IF a < 128 THEN + SignedDVIPair := a * 256 + b +ELSE + SignedDVIPair := (a - 256) * 256 + b; +END; (* SignedDVIPair *) + +(******************************************************************************) + +FUNCTION GetThreeDVIBytes : INTEGER; (* the next 3 bytes, unsigned *) + +VAR a, b, c : INTEGER; + +BEGIN +a := GetDVIByte; +b := GetDVIByte; +c := GetDVIByte; +GetThreeDVIBytes := (a * 256 + b) * 256 + c; +END; (* GetThreeDVIBytes *) + +(******************************************************************************) + +FUNCTION SignedDVITrio : INTEGER; (* the next 3 bytes, signed *) + +VAR a, b, c : INTEGER; + +BEGIN +a := GetDVIByte; +b := GetDVIByte; +c := GetDVIByte; +IF a < 128 THEN + SignedDVITrio := (a * 256 + b) * 256 + c +ELSE + SignedDVITrio := ((a - 256) * 256 + b) * 256 + c; +END; (* SignedDVITrio *) + +(******************************************************************************) + +FUNCTION SignedDVIQuad : INTEGER; (* the next 4 bytes, signed *) + +TYPE int_or_bytes = RECORD + CASE b : BOOLEAN OF + TRUE : (int : INTEGER); + FALSE : (byt : PACKED ARRAY [0..3] OF CHAR); + END; + +VAR w : int_or_bytes; + +BEGIN +WITH w DO BEGIN + w.byt[0] := CHR(GetDVIByte); + w.byt[1] := CHR(GetDVIByte); + w.byt[2] := CHR(GetDVIByte); + w.byt[3] := CHR(GetDVIByte); +END; +SignedDVIQuad := w.int; +(* Pyramid Pascal returns incorrect answer if a >= 128!!! +IF a < 128 THEN + SignedDVIQuad := ((a * 256 + b) * 256 + c) * 256 + d +ELSE + SignedDVIQuad := (((a - 256) * 256 + b) * 256 + c) * 256 + d; +*) +END; (* SignedDVIQuad *) + +(******************************************************************************) + +PROCEDURE ProcessPostamble; + +(* Having successfully opened the DVI file, we find the postamble + and initialize these global variables: + lastbop, num, den, DVImag, maxstack, totalpages. + The font definitions are read by ProcessFontDefs. +*) + +VAR postamblepos, postamble, pagehtplusdp, pagewidth : INTEGER; + +BEGIN +DVIoffset := postpostid - 4; +postamblepos := SignedDVIQuad; (* get post_post's postamble ptr *) +DVIoffset := postamblepos; +postamble := GetDVIByte; +lastbop := SignedDVIQuad; +num := SignedDVIQuad; +den := SignedDVIQuad; +DVImag := SignedDVIQuad; +pagehtplusdp := SignedDVIQuad; +pagewidth := SignedDVIQuad; +maxstack := SignedDVIPair; +totalpages := SignedDVIPair; +IF maxstack > maxstacksize THEN BEGIN + writeln; writeln('Stack capacity exceeded!'); exit(1); + (* now we don't need to test for stack overflow in DoPush *) +END; +{ DEBUG + writeln('postamble opcode = ', postamble:1); + writeln('postion of last bop = ', lastbop:1); + writeln('num = ', num:1); + writeln('den = ', den:1); + writeln('DVI mag = ', DVImag:1); + writeln('ht+dp of tallest page = ', pagehtplusdp:1); + writeln('width of widest page = ', pagewidth:1); + writeln('max stack depth = ', maxstack:1); + writeln('total # of pages = ', totalpages:1); +GUBED } +END; (* ProcessPostamble *) + +(******************************************************************************) + +PROCEDURE ProcessFontDefs; + +(* Read the fntdef commands in the postamble (fntdef commands in the DVI + pages will be skipped) and store the information in the font list. + (Note that complete fontspecs are NOT built here because DVIReader does not + want to know about the format or naming conventions of font files.) + Since ProcessPostamble ended by reading the totalpages parameter, the + next GetDVIByte should return nop or first fntdef. +*) + +VAR f, c, s, d, a, l : INTEGER; (* hold fntdef parameters *) + i : INTEGER; ch : CHAR; (* for getting farea and fname *) + farea, fname : string; (* a and l bytes long respectively *) + +BEGIN +totalfonts := 0; (* number of nodes in font list *) +fontlist := NIL; +REPEAT + DVIcommand := GetDVIByte; + IF (DVIcommand >= fntdef1) AND (DVIcommand <= fntdef1+3) THEN BEGIN + CASE DVIcommand - fntdef1 OF + 0 : f := GetDVIByte; + 1 : f := GetTwoDVIBytes; + 2 : f := GetThreeDVIBytes; + 3 : f := SignedDVIQuad + END; + c := SignedDVIQuad; (* checksum; ignore it *) + s := SignedDVIQuad; (* scaled size *) + d := SignedDVIQuad; (* design size *) + a := GetDVIByte; (* length of font area *) + l := GetDVIByte; (* length of font name *) + farea := ''; (* initialize with blanks *) + FOR i := 0 TO a-1 DO BEGIN (* read and store font area *) + ch := CHR(GetDVIByte); + IF i < maxfontspec THEN farea[i] := ch; + END; + fname := ''; + FOR i := 0 TO l-1 DO BEGIN (* read and store font name *) + ch := CHR(GetDVIByte); + IF i < maxfontspec THEN fname[i] := ch; + END; + NEW(currfont); + WITH currfont^ DO BEGIN + fontused := FALSE; + fontnum := f; + scaledsize := s; + designsize := d; + fontarea := farea; fontarealen := a; + fontname := fname; fontnamelen := l; + fontspec := ''; + fontspeclen := 0; (* fontspec is built in FontReader *) + fontexists := FALSE; (* becomes TRUE if fontspec can be opened *) + totalchars := 0; + charlist := NIL; (* first node allocated in DoFont *) + chartail := NIL; (* nodes are added to tail of char list *) + pixelptr := NIL; (* allocated once per font; see DoFont *) + nextfont := fontlist; + END; + fontlist := currfont; (* add new font to head of list *) + totalfonts := totalfonts + 1; + END + ELSE IF DVIcommand = nop THEN + (* nop commands can occur between DVI commands *) + ELSE IF DVIcommand = postpost THEN + (* we have reached end of postamble *) + ELSE BEGIN + writeln; writeln('Unexpected DVI command in postamble = ', DVIcommand:1); + exit(1); + END; +UNTIL DVIcommand = postpost; +END; (* ProcessFontDefs *) + +(******************************************************************************) + +PROCEDURE OpenDVIFile (name : string); + +(* If the given file can be opened and is a valid TeX82 DVI file then + the following global variables are initialized: + + DVImag := magnification value stored in DVI file (TeX's \mag) + totalpages := total number of pages in DVI file + currDVIpage := 0 (and remains so until a page is selected) + currTeXpage := ten 0s (ditto) + totalfonts := total number of fonts in DVI file (= nodes in font list) + fontlist^. (nodes are added to head of list) + fontused := FALSE + fontnum := internal DVI font number + scaledsize := scaled size of font (in DVI units) + designsize := design size of font (in DVI units) + fontarea := a string of min(fontarealen,maxfontspec) characters + fontname := a string of min(fontnamelen,maxfontspec) characters + fontspec := a null string (fontspeclen := 0) + fontexists := FALSE + totalchars := 0 + charlist := NIL + chartail := NIL + pixelptr := NIL + nextfont := next node in font list (if not NIL) +*) + +LABEL 666, 777, 888; + +VAR length, i : integer; + +BEGIN +currDVIbuff := -1; (* impossible value for first GetDVIByte *) +length := 0; +WHILE length < maxstring DO BEGIN + IF name[length] = ' ' THEN goto 888; + length := length + 1; +END; +888: +IF length < maxstring THEN name[length] := CHR(0); (* terminate with NULL *) +DVIfile := open(name, O_RDONLY, 0); +IF length < maxstring THEN name[length] := ' '; (* restore space *) +IF DVIfile >= 0 THEN BEGIN + (* get offset of last DVI byte *) + DVIoffset := lseek(DVIfile, 0, 2); + IF DVIoffset = -1 THEN BEGIN + writeln('Failed to find end of file!'); exit(1); + END; + IF DVIoffset = 0 THEN BEGIN + writeln('File is empty!'); exit(1); + END; + { DEBUG + writeln('total bytes = ', DVIoffset:1); + GUBED } + DVIoffset := DVIoffset - 1; + WHILE TRUE DO BEGIN (* skip any NULs *) + IF GetDVIByte <> 0 THEN goto 777; + IF DVIoffset = 1 THEN goto 777; (* start of file! *) + DVIoffset := DVIoffset - 2; (* GetDVIByte increments *) + END; + 777: + DVIoffset := DVIoffset - 1; + WHILE TRUE DO BEGIN (* skip 223s *) + IF GetDVIByte <> 223 THEN goto 666; + IF DVIoffset = 1 THEN goto 666; (* start of file! *) + DVIoffset := DVIoffset - 2; (* GetDVIByte increments *) + END; + 666: + DVIoffset := DVIoffset - 1; + postpostid := DVIoffset; (* remember offset of id byte *) + IF GetDVIByte <> 2 THEN BEGIN + writeln(name:length,' is not a valid DVI file!'); exit(1); + END + ELSE BEGIN + ProcessPostamble; (* get DVImag, totalpages, etc *) + ProcessFontDefs; (* build and initialize font list *) + currDVIpage := 0; (* we haven't processed a page yet *) + FOR i := 0 TO 9 DO currTeXpage[i] := 0; + END; +END +ELSE BEGIN + writeln('Couldn''t open file: ', name:length); exit(1); +END; +END; (* OpenDVIFile *) + +(******************************************************************************) + +PROCEDURE SkipFntdef (which : INTEGER); + +(* Read past a fntdef command without interpreting it. *) + +VAR dummy, a, l, i : INTEGER; + +BEGIN +CASE which OF (* which = DVIcommand - fntdef1 *) + 0 : dummy := GetDVIByte; + 1 : dummy := GetTwoDVIBytes; + 2 : dummy := GetThreeDVIBytes; + 3 : dummy := SignedDVIQuad +END; +dummy := SignedDVIQuad; +dummy := SignedDVIQuad; +dummy := SignedDVIQuad; +a := GetDVIByte; (* length of directory *) +l := GetDVIByte; (* length of font name *) +FOR i := 1 TO l+a DO + dummy := GetDVIByte; +END; (* SkipFntdef *) + +(******************************************************************************) + +PROCEDURE ReadFirstBop; + +(* Read first bop by skipping past preamble; update currbop and currDVIpage. *) + +VAR k, i, dummy : INTEGER; + +BEGIN +DVIoffset := 14; (* position of preamble's k parameter *) +k := GetDVIByte; (* length of x parameter *) +FOR i := 1 TO k DO + dummy := GetDVIByte; (* skip preamble comment *) +REPEAT (* skip any nops and fntdefs *) + DVIcommand := GetDVIByte; + IF (DVIcommand = nop) OR (DVIcommand = bop) THEN + (* do nothing *) + ELSE IF (DVIcommand >= fntdef1) AND (DVIcommand <= fntdef1+3) THEN + SkipFntdef(DVIcommand - fntdef1) + ELSE BEGIN + writeln; + writeln('Unexpected DVI command before first bop = ', DVIcommand:1); + exit(1); + END; +UNTIL DVIcommand = bop; +currbop := DVIoffset - 1; (* position in DVI file of first bop *) +currDVIpage := 1; +END; (* ReadFirstBop *) + +(******************************************************************************) + +PROCEDURE ReadNextBop; + +(* We are currently positioned after an eop byte which we know is not the + last. This routine positions us after the next bop byte and updates + currbop and currDVIpage. +*) + +BEGIN +REPEAT (* skip any nops and fntdefs *) + DVIcommand := GetDVIByte; + IF (DVIcommand = nop) OR (DVIcommand = bop) THEN + (* do nothing *) + ELSE IF (DVIcommand >= fntdef1) AND (DVIcommand <= fntdef1+3) THEN + SkipFntdef(DVIcommand - fntdef1) + ELSE BEGIN + writeln; + writeln('Unexpected DVI command between eop and bop = ', DVIcommand:1); + exit(1); + END; +UNTIL DVIcommand = bop; +currbop := DVIoffset - 1; (* position in DVI file of this bop *) +currDVIpage := currDVIpage + 1; +END; (* ReadNextBop *) + +(******************************************************************************) + +PROCEDURE ReadBopParameters; + +(* We should now be positioned after the bop of desired page, so read + the 10 TeX counters and update currTeXpage and prevbop. + At the end of this routine we will be at the byte after currbop's parameters + and ready to InterpretPage. +*) + +VAR i : INTEGER; + +BEGIN +FOR i := 0 TO 9 DO + currTeXpage[i] := SignedDVIQuad; +prevbop := SignedDVIQuad; (* position of previous bop in DVI file *) +END; (* ReadBopParameters *) + +(******************************************************************************) + +PROCEDURE MoveToNextPage (ascending : BOOLEAN); + +(* MoveToNextPage will select the next page, depending on the current page + and the specified direction. If the value of currDVIpage is 0 (set in + OpenDVIFile), then MoveToNextPage will select the first page if ascending is + TRUE and the last page if ascending is FALSE. If currDVIpage is > 0 then + MoveToNextPage will select currDVIpage+1 if ascending (unless currDVIpage = + totalpages, in which case it does nothing), or currDVIpage-1 if descending + (unless currDVIpage = 0). + + Before calling InterpretPage, PSDVI must position DVIReader to the + desired page by calling one of the MoveTo... routines. + The global variables updated if a page is located by any MoveTo... call are: + currDVIpage := the current DVI page (1..totalpages) + currTeXpage := the ten TeX counter values stored with this page + Note that currDVIpage is initially 0 until one of these routines succeeds. +*) + +LABEL 999; + +BEGIN +IF (currDVIpage = 1) AND (NOT ascending) THEN + goto 999 +ELSE IF (currDVIpage = totalpages) AND ascending THEN + goto 999 +ELSE IF currDVIpage = 0 THEN + (* we haven't processed a page yet *) + IF ascending THEN (* get first page *) + ReadFirstBop + ELSE BEGIN (* get last page *) + currbop := lastbop; + DVIoffset := currbop + 1; + currDVIpage := totalpages; + END +ELSE + IF ascending THEN + (* currently positioned after eop of currDVIpage, so get next bop *) + ReadNextBop + ELSE BEGIN + (* move to bop pointed to by currbop's backpointer *) + currbop := prevbop; + DVIoffset := currbop + 1; (* move to byte after previous bop *) + currDVIpage := currDVIpage - 1; + END; +ReadBopParameters; (* update currTeXpage and prevbop *) +999: +END; (* MoveToNextPage *) + +(******************************************************************************) + +PROCEDURE MoveToDVIPage (n : INTEGER); + +(* Move to nth DVI page; n should be in 1..totalpages. *) + +LABEL 888, 999; + +BEGIN +IF (n < 1) OR (n > totalpages) THEN (* do nothing *) + goto 999 +ELSE IF n = 1 THEN + (* Note that this test must come before next test so that we avoid any + problems when currDVIpage initially = 0. *) + ReadFirstBop +(* We have removed the ELSIF code because it assumes InterpretPage is called + after every MoveTo... routine (which PSDVI does NOT call when locating the + first and final pages of a given subrange). +ELSE IF n = currDVIpage + 1 THEN + ReadNextBop +*) +ELSE BEGIN + IF n < currDVIpage THEN BEGIN + currbop := prevbop; (* start searching backwards from previous page *) + currDVIpage := currDVIpage - 1; + END + ELSE IF n > currDVIpage THEN BEGIN + currbop := lastbop; (* start searching backwards from last page *) + currDVIpage := totalpages; + END; + (* if n = currDVIpage we'll just move back to currbop *) + (* n is now <= currDVIpage so search by following backpointers *) + WHILE TRUE DO + IF n = currDVIpage THEN BEGIN + DVIoffset := currbop + 1; (* move to byte after currbop *) + goto 888; + END + ELSE BEGIN + DVIoffset := currbop + 41; (* move to location of backpointer *) + currbop := SignedDVIQuad; (* get location of previous page *) + currDVIpage := currDVIpage - 1; + END; + 888: +END; +ReadBopParameters; (* update currTeXpage and prevbop *) +999: +END; (* MoveToDVIPage *) + +(******************************************************************************) + +FUNCTION CurrMatchesNew (VAR newTeXpage : TeXpageinfo) : BOOLEAN; + +(* Return TRUE iff currTeXpage matches newTeXpage. *) + +VAR i : 0..9; + +BEGIN +CurrMatchesNew := TRUE; +WITH newTeXpage DO + FOR i := 0 TO lastvalue DO + IF present[i] THEN + IF value[i] <> currTeXpage[i] THEN + CurrMatchesNew := FALSE; +END; (* CurrMatchesNew *) + +(******************************************************************************) + +FUNCTION MoveToTeXPage (VAR newTeXpage : TeXpageinfo) : BOOLEAN; + +(* MoveToTeXPage will search for the lowest DVI page matching the given TeX page + specification. (TeX stores the values of \count0,\count1,...,\count9 with + every DVI page. Plain TeX uses \count0 to control page numbering.) + newTeXpage is a VAR parameter only for efficiency; it won't be changed. + The value array stores the requested counter values, the present array + indicates which counters are relevant and lastvalue indicates + the position (0..9) of the last relevant counter. + + PSDVI converts a more friendly representation + of a TeX page request into the TeXpageinfo format. For example, + [2..5] would be converted to: and [] would be converted to: + value = [2,?,5,?,?,?,?,?,?,?] value = [?,?,?,?,?,?,?,?,?,?] + present = [T,F,T,?,?,?,?,?,?,?] present = [F,?,?,?,?,?,?,?,?,?] + lastvalue = 2 lastvalue = 0 + MoveToTeXPage returns TRUE iff the requested TeX page is located. +*) + +LABEL 999; + +VAR savecurrbop, savecurrDVIpage : INTEGER; + nextbop : INTEGER; + i : INTEGER; + atleastone : BOOLEAN; + +BEGIN +(* save away current page and DVI position *) +savecurrDVIpage := currDVIpage; +IF currDVIpage <> 0 THEN (* only if we've processed a page *) + savecurrbop := currbop; + (* note that curreop is saved in last InterpretPage *) +(* search backwards through all DVI pages for lowest matching page *) +atleastone := FALSE; +nextbop := lastbop; +FOR i := totalpages DOWNTO 1 DO BEGIN + DVIoffset := nextbop + 1; + ReadBopParameters; (* update currTeXpage and prevbop *) + IF CurrMatchesNew(newTeXpage) THEN BEGIN + currbop := nextbop; + currDVIpage := i; + atleastone := TRUE; + END; + nextbop := prevbop; +END; +IF NOT atleastone THEN BEGIN (* no match, so restore currDVIpage *) + currDVIpage := savecurrDVIpage; + IF currDVIpage <> 0 THEN BEGIN (* restore page and positioning info *) + currbop := savecurrbop; + DVIoffset := currbop + 1; + ReadBopParameters; (* restore currTeXpage and prevbop *) + DVIoffset := curreop + 1; + (* we should now be after the eop byte of the original page *) + END; + MoveToTeXPage := FALSE; + goto 999; +END +ELSE (* we found lowest matching page *) + DVIoffset := currbop + 1; +ReadBopParameters; (* update currTeXpage and prevbop *) +MoveToTeXPage := TRUE; +999: +END; (* MoveToTeXPage *) + +(******************************************************************************) + +PROCEDURE SetConversionFactor (resolution, magnification : INTEGER); + +(* This routine must be called before the first InterpretPage call. + DVIReader needs to know the resolution and magnification values + before it attempts to convert DVI units into pixel values. +*) + +BEGIN +conv := num/254000.0 * resolution/den * magnification/1000.0; +END; (* SetConversionFactor *) + +(******************************************************************************) + +PROCEDURE InitStateValues; + +(* Initialize state values and stack. *) + +BEGIN +hh := hoffset; (* 0 if no horizontal shift specified *) +vv := voffset; (* 0 if no vertical shift specified *) +IF hoffset >= 0 THEN + h := TRUNC(hoffset / conv + 0.5) +ELSE + h := - TRUNC(ABS(hoffset) / conv + 0.5); +IF voffset >= 0 THEN + v := TRUNC(voffset / conv + 0.5) +ELSE + v := - TRUNC(ABS(voffset) / conv + 0.5); +w := 0; x := 0; +y := 0; z := 0; +stackpos := 0; +fontspace := 0; (* for DoRight and DoDown before a DoFont call *) +END; (* InitStateValues *) + +(******************************************************************************) + +PROCEDURE InitPage; + +(* Initialize page so that there are no fonts, chars, rules, specials. *) + +BEGIN +(* page edges will change if there is at least one char or rule on page *) +minhp := maxint; +minvp := maxint; +maxhp := -maxint; +maxvp := -maxint; +currfont := fontlist; +WHILE currfont <> NIL DO + WITH currfont^ DO BEGIN + IF fontused THEN BEGIN (* only reset those fonts used in last page *) + fontused := FALSE; + totalchars := 0; + (* deallocate char list completely; DoFont will allocate first node *) + WHILE charlist <> NIL DO BEGIN + thischar := charlist; + charlist := thischar^.nextchar; + DISPOSE(thischar); + END; + chartail := NIL; + (* pixel table remains allocated *) + END; + currfont := nextfont; + END; +currfont := NIL; (* current font is undefined at start of page *) +totalrules := 0; +(* deallocate rule information except for one node (for DoSet/PutRule) *) +WHILE rulelist <> ruletail DO BEGIN + thisrule := rulelist; + rulelist := thisrule^.nextrule; + DISPOSE(thisrule); +END; +rulelist^.rulecount := 0; (* no rules in this node *) +rulelist^.nextrule := NIL; +(* deallocate \special information *) +WHILE speciallist <> NIL DO BEGIN + thisspecial := speciallist; + speciallist := speciallist^.nextspecial; + DISPOSE(thisspecial); +END; +END; (* InitPage *) + +(******************************************************************************) + +FUNCTION PixelRound (DVIunits : INTEGER) : INTEGER; + +(* Return the nearest number of pixels in the given DVI dimension. *) + +BEGIN +IF DVIunits > 0 THEN + PixelRound := TRUNC(conv * DVIunits + 0.5) +ELSE + PixelRound := - TRUNC(conv * ABS(DVIunits) + 0.5); +END; (* PixelRound *) + +(******************************************************************************) + +PROCEDURE DoSetChar (ch : INTEGER); + +(* Add char info to current chartable, update our horizontal + position on the page and check the page edges. +*) + +LABEL 999; + +BEGIN +WITH currfont^ DO BEGIN + IF ch > maxTeXchar THEN BEGIN + writeln('Unknown character from ', fontspec:fontspeclen); + goto 999; (* ignore ch *) + END; + WITH chartail^ DO + IF charcount = chartablesize THEN BEGIN + (* allocate a new chartable *) + NEW(nextchar); (* add new node to end of char list *) + nextchar^.charcount := 0; (* reset charcount *) + nextchar^.nextchar := NIL; + chartail := nextchar; + END; + WITH chartail^ DO BEGIN (* may be new chartable *) + WITH chartable[charcount] DO BEGIN + hp := hh; + vp := vv; + code := ch; + END; + WITH pixelptr^[ch] DO BEGIN + (* do page edges increase? *) + IF vv - yo < minvp THEN minvp := vv - yo; + IF hh - xo < minhp THEN minhp := hh - xo; + IF vv + (ht - yo - 1) > maxvp THEN maxvp := vv + (ht - yo - 1); + IF hh + (wd - xo - 1) > maxhp THEN maxhp := hh + (wd - xo - 1); + (* add pixel width calculated in PixelTableRoutine *) + hh := hh + pwidth; + (* use hhh and maxdrift to prevent hh drifting too far from h *) + hhh := PixelRound(h + dwidth); + IF ABS(hhh - hh) > maxdrift THEN + IF hhh > hh THEN + hh := hhh - maxdrift + ELSE + hh := hhh + maxdrift; + (* add DVI width calculated in PixelTableRoutine *) + h := h + dwidth; + END; + totalchars := totalchars + 1; + charcount := charcount + 1; + END; +END; +999: +END; (* DoSetChar *) + +(******************************************************************************) + +PROCEDURE DoPutChar (ch : INTEGER); + +(* Exactly the same as DoSetChar, but we DON'T update the horizontal + position on the page. (We still have to check page edges.) +*) + +LABEL 999; + +BEGIN +WITH currfont^ DO BEGIN + IF ch > maxTeXchar THEN BEGIN + writeln('Unknown character from ', fontspec:fontspeclen); + goto 999; (* ignore ch *) + END; + WITH chartail^ DO + IF charcount = chartablesize THEN BEGIN + (* allocate a new chartable *) + NEW(nextchar); (* add new node to end of char list *) + nextchar^.charcount := 0; (* reset charcount *) + nextchar^.nextchar := NIL; + chartail := nextchar; + END; + WITH chartail^ DO BEGIN (* may be new chartable *) + WITH chartable[charcount] DO BEGIN + hp := hh; + vp := vv; + code := ch; + END; + WITH pixelptr^[ch] DO BEGIN + (* do page edges increase? *) + IF vv - yo < minvp THEN minvp := vv - yo; + IF hh - xo < minhp THEN minhp := hh - xo; + IF vv + (ht - yo - 1) > maxvp THEN maxvp := vv + (ht - yo - 1); + IF hh + (wd - xo - 1) > maxhp THEN maxhp := hh + (wd - xo - 1); + END; + totalchars := totalchars + 1; + charcount := charcount + 1; + END; +END; +999: +END; (* DoPutChar *) + +(******************************************************************************) + +PROCEDURE DoPush; + +(* Push state values onto stack. + No need to test for stack overflow since we compare maxstack and + maxstacksize in ProcessPostamble. +*) + +BEGIN +hstack[stackpos] := h; vstack[stackpos] := v; +wstack[stackpos] := w; xstack[stackpos] := x; +ystack[stackpos] := y; zstack[stackpos] := z; +hhstack[stackpos] := hh; vvstack[stackpos] := vv; +stackpos := stackpos + 1; +END; (* DoPush *) + +(******************************************************************************) + +PROCEDURE DoPop; + +(* Pop state values from top of stack. *) + +BEGIN +{ DEBUG + IF stackpos = 0 THEN BEGIN + writeln; writeln('Stack empty!'); exit(1); + END; +GUBED } +stackpos := stackpos - 1; +h := hstack[stackpos]; v := vstack[stackpos]; +w := wstack[stackpos]; x := xstack[stackpos]; +y := ystack[stackpos]; z := zstack[stackpos]; +hh := hhstack[stackpos]; vv := vvstack[stackpos]; +END; (* DoPop *) + +(******************************************************************************) + +PROCEDURE DoRight (amount : INTEGER); + +(* Move the reference point horizontally by given amount (usually +ve). + When the amount is small, like a kern, hh changes + by rounding the amount; but when the amount is large, hh changes by rounding + the true position h so that accumulated rounding errors disappear. +*) + +BEGIN +IF (amount < fontspace) AND (amount > -4 * fontspace) THEN BEGIN + hh := hh + PixelRound(amount); + (* use hhh and maxdrift to prevent hh drifting too far from h *) + hhh := PixelRound(h + amount); + IF ABS(hhh - hh) > maxdrift THEN + IF hhh > hh THEN + hh := hhh - maxdrift + ELSE + hh := hhh + maxdrift; +END +ELSE + hh := PixelRound(h + amount); +h := h + amount; +END; (* DoRight *) + +(******************************************************************************) + +PROCEDURE DoDown (amount : INTEGER); + +(* Move the reference point vertically by given amount (usually +ve). + Rounding is done similarly to DoRight but with the threshold between + small and large amounts increased by a factor of 5. +*) + +BEGIN +IF ABS(amount) < 5 * fontspace THEN BEGIN + vv := vv + PixelRound(amount); + (* use vvv and maxdrift to prevent vv drifting too far from v *) + vvv := PixelRound(v + amount); + IF ABS(vvv - vv) > maxdrift THEN + IF vvv > vv THEN + vv := vvv - maxdrift + ELSE + vv := vvv + maxdrift; +END +ELSE + vv := PixelRound(v + amount); +v := v + amount; +END; (* DoDown *) + +(******************************************************************************) + +FUNCTION RulePixels (DVIunits : INTEGER) : INTEGER; + +(* Return the number of pixels in the given height or width of a rule + using the method recommended in DVITYPE. +*) + +VAR n : INTEGER; + +BEGIN +n := TRUNC(conv * DVIunits); +IF n < conv * DVIunits THEN RulePixels := n + 1 ELSE RulePixels := n; +END; (* RulePixels *) + +(******************************************************************************) + +PROCEDURE DoSetRule (height, width : INTEGER); + +(* Add rule information to current ruletable, update page edges, h and hh + (but only if width and height are > 0). +*) + +BEGIN +IF (height > 0) AND (width > 0) THEN BEGIN + WITH ruletail^ DO + IF rulecount = ruletablesize THEN BEGIN + (* allocate a new ruletable *) + NEW(nextrule); (* add new node to end of rule list *) + nextrule^.rulecount := 0; (* reset rulecount *) + nextrule^.nextrule := NIL; + ruletail := nextrule; + END; + WITH ruletail^ DO BEGIN (* may be new ruletable *) + WITH ruletable[rulecount] DO BEGIN + hp := hh; + vp := vv; + wd := RulePixels(width); + ht := RulePixels(height); + (* do page edges increase? *) + IF vv - (ht - 1) < minvp THEN minvp := vv - (ht - 1); + IF hh + (wd - 1) > maxhp THEN maxhp := hh + (wd - 1); + (* ref pt of rule is bottom left black pixel *) + IF vv > maxvp THEN maxvp := vv; + IF hh < minhp THEN minhp := hh; + hh := hh + wd; + (* use hhh and maxdrift to prevent hh drifting too far from h *) + hhh := PixelRound(h + width); + IF ABS(hhh - hh) > maxdrift THEN + IF hhh > hh THEN + hh := hhh - maxdrift + ELSE + hh := hhh + maxdrift; + h := h + width; + END; + totalrules := totalrules + 1; + rulecount := rulecount + 1; + END; +END; +END; (* DoSetRule *) + +(******************************************************************************) + +PROCEDURE DoPutRule (height, width : INTEGER); + +(* Exactly the same as DoSetRule, but we DON'T update the horizontal + position on the page. (We still have to check page edges.) +*) + +BEGIN +IF (height > 0) AND (width > 0) THEN BEGIN + WITH ruletail^ DO + IF rulecount = ruletablesize THEN BEGIN + (* allocate a new ruletable *) + NEW(nextrule); (* add new node to end of rule list *) + nextrule^.rulecount := 0; (* reset rulecount *) + nextrule^.nextrule := NIL; + ruletail := nextrule; + END; + WITH ruletail^ DO BEGIN (* may be new ruletable *) + WITH ruletable[rulecount] DO BEGIN + hp := hh; + vp := vv; + wd := RulePixels(width); + ht := RulePixels(height); + (* do page edges increase? *) + IF vv - (ht - 1) < minvp THEN minvp := vv - (ht - 1); + IF hh + (wd - 1) > maxhp THEN maxhp := hh + (wd - 1); + (* ref pt of rule is bottom left black pixel *) + IF vv > maxvp THEN maxvp := vv; + IF hh < minhp THEN minhp := hh; + END; + totalrules := totalrules + 1; + rulecount := rulecount + 1; + END; +END; +END; (* DoPutRule *) + +(******************************************************************************) + +PROCEDURE DoFont (externf : INTEGER); + +(* Search font list for externf, setting currfont and fontspace. + If this is the first time we've seen this font (on current page) then + we need to allocate the first chartable. + If this is the first time we've seen this font used at all then we + allocate a pixeltable and call routine to fill it in. +*) + +LABEL 888; + +BEGIN +currfont := fontlist; +WHILE currfont <> NIL DO + IF currfont^.fontnum <> externf THEN + currfont := currfont^.nextfont + ELSE + goto 888; +888: +{ DEBUG + IF currfont = NIL THEN BEGIN + writeln; writeln('Failed to find font #', externf:1); exit(1); + END; +GUBED } +WITH currfont^ DO BEGIN + IF fontused THEN + (* do nothing since we've already used this font on this page *) + ELSE BEGIN + fontused := TRUE; + NEW(charlist); (* allocate first chartable *) + WITH charlist^ DO BEGIN + charcount := 0; (* for DoSet/PutChar *) + nextchar := NIL; (* this node is also last *) + END; + chartail := charlist; + IF pixelptr = NIL THEN BEGIN (* first time we've seen this font *) + NEW(pixelptr); + PixelTableRoutine; + END; + END; + fontspace := scaledsize DIV 6; + (* See DVITYPE; a 3-unit thin space. + Note that a thin space is 1/6 of a quad, where a quad is + 1 em in the current font and usually equals the design size. + *) +END; +END; (* DoFont *) + +(******************************************************************************) + +PROCEDURE DoSpecial (hpos, vpos, totalbytes : INTEGER); (* in *) + +(* DVIReader has seen a \special command while interpreting the current page. + It will pass the current page position and number of bytes in the command. + We save the info away in speciallist for later use by the main program. +*) + +VAR i, flush : INTEGER; temp : specialinfoptr; + +BEGIN +NEW(temp); +WITH temp^ DO BEGIN + special := ''; (* SYSDEP: fill with spaces *) + FOR i := 0 TO totalbytes-1 DO + IF i < maxspeciallen THEN special[i] := CHR(GetDVIByte); + (* we must read all the \special bytes *) + IF totalbytes > maxspeciallen THEN BEGIN + warncount := warncount + 1; + writeln; + writeln('\special command truncated:'); + writeln(special:maxspeciallen); + FOR i := 1 TO totalbytes - maxspeciallen DO flush := GetDVIByte; + END; + hp := hpos; + vp := vpos; + nextspecial := speciallist; +END; +speciallist := temp; (* add new info to head of list *) +END; (* DoSpecial *) + +(******************************************************************************) + +PROCEDURE InterpretPage; + +(* When this routine is called we are positioned after the bytes of a bop + command (i.e., at currbop + 45). At the end of this routine we will be + positioned after the eop byte for the current page. In between we carry + out the important task of translating the DVI description of this page + and filling in the following global data structures: + + totalrules := number of rules on page + rulelist^. (nodes are added to tail of rule list) + rulecount := number of rules in this ruletable + ruletable[0..rulecount-1]. + hp, vp := reference point of a rule + wd, ht := pixel dimensions of a rule (both > 0) + nextrule := next node in rule list (if not NIL) + ruletail := pointer to last node in rule list + + speciallist^. (nodes are added to head of this list) + hp, vp := reference point on page + special := \special bytes + nextspecial := next node in list (if not NIL) + + fontlist^. + (the following fontinfo is relevant only if fontused is TRUE) + totalchars := number of chars on page from this font + charlist^. (nodes are added to tail of char list) + charcount := number of chars in this chartable + chartable[0..charcount-1]. + hp, vp := reference point of a character + code := TeX character code (and index into pixel table) + nextchar := next node in char list (if not NIL) + chartail := pointer to last node in char list + pixelptr^[0..maxTeXchar]. + (filled in by FontReader's PixelTableRoutine) + wd, ht := glyph width and height in pixels + xo, yo := offsets from the character's reference point + dwidth := advance width in DVI units + pwidth := advance width in pixels + mapadr := offset in fontspec of the glyph's bitmap info + bitmap := NIL + nextfont := next node in font list (if not NIL) + + pageempty := TRUE iff the page has no rules and no characters + minhp, minvp, maxhp, maxvp + := the edges of the page (undefined if pageempty is TRUE) + They define the smallest rectangle containing all black + pixels on the page;(minhp,minvp) is the top left corner. + + Reference points for rules and characters are stored as a pair of + horizontal and vertical pixel coordinates. The point (0,0) is assumed + to be the pixel 1 inch in from the top and left edges of an imaginary sheet + of paper. Horizontal coordinates increase to the right and vertical + coordinates increase down the paper. + The number of pixels per inch is defined by the resolution parameter + given to SetConversionFactor. +*) + +VAR param, ht, wd : INTEGER; + +BEGIN +InitStateValues; +InitPage; +REPEAT + DVIcommand := GetDVIByte; + (* For efficiency reasons the most frequent commands should be tested 1st. + The following order is the result of frequency testing on typical + DVI files. Note that the most frequent commands in the DVI file + generated by TeX 1.3 for the Dec. 1983 LaTeX manual were: + z4) AND (DVIcommand < fnt1) (* fntnum0..fntnum63 *) + THEN DoFont(DVIcommand - fntnum0) + + (* catch all the remaining movement commands *) + ELSE IF (DVIcommand > pop) AND (DVIcommand < fntnum0) THEN BEGIN + IF DVIcommand = right2 THEN DoRight(SignedDVIPair) + ELSE IF DVIcommand = right4 THEN DoRight(SignedDVIQuad) + ELSE IF DVIcommand = x2 THEN BEGIN x := SignedDVIPair; DoRight(x) END + ELSE IF DVIcommand = x3 THEN BEGIN x := SignedDVITrio; DoRight(x) END + ELSE IF DVIcommand = down3 THEN DoDown(SignedDVITrio) + ELSE IF DVIcommand = down4 THEN DoDown(SignedDVIQuad) + ELSE IF DVIcommand = w2 THEN BEGIN w := SignedDVIPair; DoRight(w) END + ELSE IF DVIcommand = z0 THEN DoDown(z) + ELSE IF DVIcommand = y3 THEN BEGIN y := SignedDVITrio; DoDown(y) END + ELSE IF DVIcommand = z3 THEN BEGIN z := SignedDVITrio; DoDown(z) END + ELSE IF DVIcommand = down2 THEN DoDown(SignedDVIPair) + (* the next DVI commands are used very rarely (by TeX 1.3 at least) *) + ELSE IF DVIcommand = w1 THEN BEGIN w := SignedDVIByte; DoRight(w) END + ELSE IF DVIcommand = w4 THEN BEGIN w := SignedDVIQuad; DoRight(w) END + ELSE IF DVIcommand = x1 THEN BEGIN x := SignedDVIByte; DoRight(x) END + ELSE IF DVIcommand = x4 THEN BEGIN x := SignedDVIQuad; DoRight(x) END + ELSE IF DVIcommand = y1 THEN BEGIN y := SignedDVIByte; DoDown(y) END + ELSE IF DVIcommand = y2 THEN BEGIN y := SignedDVIPair; DoDown(y) END + ELSE IF DVIcommand = y4 THEN BEGIN y := SignedDVIQuad; DoDown(y) END + ELSE IF DVIcommand = z1 THEN BEGIN z := SignedDVIByte; DoDown(z) END + ELSE IF DVIcommand = z2 THEN BEGIN z := SignedDVIPair; DoDown(z) END + ELSE IF DVIcommand = z4 THEN BEGIN z := SignedDVIQuad; DoDown(z) END + ELSE IF DVIcommand = right1 THEN DoRight(SignedDVIByte) + ELSE IF DVIcommand = down1 THEN DoDown(SignedDVIByte) + ELSE BEGIN + writeln; writeln('Bug in InterpretPage!'); exit(1); + END; + END + ELSE IF DVIcommand = setrule THEN BEGIN + ht := SignedDVIQuad; wd := SignedDVIQuad; DoSetRule(ht,wd); + END + ELSE IF DVIcommand = putrule THEN BEGIN + ht := SignedDVIQuad; wd := SignedDVIQuad; DoPutRule(ht,wd); + END + ELSE IF (DVIcommand >= put1) AND (DVIcommand <= put1+3) THEN + CASE DVIcommand - put1 OF + 0 : DoPutChar(GetDVIByte); + 1 : DoPutChar(GetTwoDVIBytes); + 2 : DoPutChar(GetThreeDVIBytes); + 3 : DoPutChar(SignedDVIQuad) + END + + ELSE IF (DVIcommand >= set1) AND (DVIcommand <= set1+3) THEN + CASE DVIcommand - set1 OF + 0 : DoSetChar(GetDVIByte); + 1 : DoSetChar(GetTwoDVIBytes); + 2 : DoSetChar(GetThreeDVIBytes); + 3 : DoSetChar(SignedDVIQuad) + END + + ELSE IF (DVIcommand >= fnt1) AND (DVIcommand <= fnt1+3) THEN + CASE DVIcommand - fnt1 OF + 0 : DoFont(GetDVIByte); + 1 : DoFont(GetTwoDVIBytes); + 2 : DoFont(GetThreeDVIBytes); + 3 : DoFont(SignedDVIQuad) + END + + ELSE IF (DVIcommand >= xxx1) AND (DVIcommand <= xxx1+3) THEN BEGIN + CASE DVIcommand - xxx1 OF + 0 : param := GetDVIByte; + 1 : param := GetTwoDVIBytes; + 2 : param := GetThreeDVIBytes; + 3 : param := SignedDVIQuad + END; + (* pass current pixel position and number of bytes *) + DoSpecial(hh, vv, param); + END + + (* skip fntdef command since we've got this info from postamble *) + ELSE IF (DVIcommand >= fntdef1) AND (DVIcommand <= fntdef1+3) + THEN SkipFntdef(DVIcommand - fntdef1) + + ELSE IF DVIcommand = nop THEN (* do nothing *) + ELSE IF DVIcommand = eop THEN (* do nothing *) + ELSE BEGIN + writeln; + writeln('Unexpected DVI command while interpreting page = ', DVIcommand:1); + exit(1); + END; +UNTIL DVIcommand = eop; +(* save position of eop byte for use in MoveToTeXPage *) +curreop := DVIoffset - 1; +IF stackpos <> 0 THEN BEGIN + writeln; writeln('Stack not empty at eop!'); exit(1); +END; +pageempty := (minhp = maxint) AND (minvp = maxint) AND + (maxhp = -maxint) AND (maxvp = -maxint); (* InitPage values *) +END; (* InterpretPage *) + +(******************************************************************************) + +PROCEDURE SortFonts (VAR unusedlist : fontinfoptr); (* out *) + +(* Sort fontlist in order of ascending totalchars. + Fonts with least characters can then be accessed first. + Since the number of fonts used on a typical page is quite small, a simple + sorting algorithm should be good enough. Note that unused fonts are moved + to the end of the list and unusedlist points to the first such node. + PSDVI need only process fonts up to (but excluding) unusedlist + and does not have to worry about checking the fontused flag. + If unusedlist is NIL then either 1) all fonts are used on the current page + or 2) fontlist is also NIL (totalfonts = 0). +*) + +VAR newfontlist, prevfont, largest, prevlargest : fontinfoptr; + mostchars : INTEGER; + +BEGIN +newfontlist := NIL; +(* go thru fontlist once and move all unused fonts to head of newfontlist *) +prevfont := NIL; +currfont := fontlist; +WHILE currfont <> NIL DO + WITH currfont^ DO + IF fontused THEN BEGIN + prevfont := currfont; (* remember previous node *) + currfont := nextfont; + END + ELSE + (* move node from fontlist to head of newfontlist + and don't change prevfont + *) + IF prevfont = NIL THEN BEGIN + fontlist := nextfont; (* remove first node in fontlist *) + nextfont := newfontlist; + newfontlist := currfont; + currfont := fontlist; + END + ELSE BEGIN + prevfont^.nextfont := nextfont; + nextfont := newfontlist; + newfontlist := currfont; + currfont := prevfont^.nextfont; + END; +(* unusedlist will be last unused font moved to newfontlist. It will be NIL + if either fontlist is NIL or all fonts are used. +*) +unusedlist := newfontlist; +(* Now go thru fontlist repeatedly moving node with max totalchars to + head of newfontlist until fontlist is exhausted. +*) +WHILE fontlist <> NIL DO BEGIN + prevfont := NIL; + currfont := fontlist; + prevlargest := NIL; + largest := fontlist; + mostchars := 0; + WHILE currfont <> NIL DO (* search for largest totalchars *) + WITH currfont^ DO BEGIN + IF totalchars > mostchars THEN BEGIN + prevlargest := prevfont; + largest := currfont; + mostchars := totalchars; + END; + prevfont := currfont; + currfont := nextfont; + END; + (* move largest node from fontlist to head of newfontlist *) + WITH largest^ DO BEGIN + IF prevlargest = NIL THEN + fontlist := nextfont (* remove first node in fontlist *) + ELSE + prevlargest^.nextfont := nextfont; + nextfont := newfontlist; + newfontlist := largest; + END; +END; +fontlist := newfontlist; (* used fonts now sorted and unused fonts at end *) +END; (* SortFonts *) + +(******************************************************************************) + +PROCEDURE CloseDVIFile; + +(* Close the currently open DVI file and deallocate dynamic data structures. *) + +VAR result : integer; + +BEGIN +result := close(DVIfile); +WHILE fontlist <> NIL DO BEGIN + currfont := fontlist; + WITH currfont^ DO BEGIN + WHILE charlist <> NIL DO BEGIN + thischar := charlist; + charlist := thischar^.nextchar; + DISPOSE(thischar); (* deallocate char list *) + END; + IF pixelptr <> NIL THEN + DISPOSE(pixelptr); (* deallocate pixel table *) + fontlist := nextfont; + END; + DISPOSE(currfont); (* deallocate font information *) +END; +(* Deallocate rule information except for one node + (in case PSDVI ever opens another DVI file). +*) +WHILE rulelist <> ruletail DO BEGIN + thisrule := rulelist; + rulelist := thisrule^.nextrule; + DISPOSE(thisrule); +END; +WHILE speciallist <> NIL DO BEGIN + thisspecial := speciallist; + speciallist := speciallist^.nextspecial; + DISPOSE(thisspecial); +END; +END; (* CloseDVIFile *) + +(******************************************************************************) + +PROCEDURE InitDVIReader; + +BEGIN +totalrules := 0; +NEW(rulelist); (* for first InitPage *) +ruletail := rulelist; (* ditto *) +speciallist := NIL; (* ditto *) +fontlist := NIL; (* safer for CloseDVIFile *) +END; (* InitDVIReader *) diff --git a/dviware/psprint/unix/files.h b/dviware/psprint/unix/files.h new file mode 100644 index 0000000000..98a09bd8c9 --- /dev/null +++ b/dviware/psprint/unix/files.h @@ -0,0 +1,17 @@ +(* Random file access; used in DVIReader and FontReader *) + +CONST + bufflen = 1024; (* size of buffer for holding DVI/PK bytes *) + bufflenm = bufflen - 1; + + O_RDONLY = 0; (* SYSDEP: read-only flag for open; + value came from /usr/include/sys/fcntl.h + *) + +TYPE + buffer = ARRAY [0..bufflenm] OF CHAR; + +FUNCTION open (VAR path : string; flags, mode : integer) : integer; EXTERNAL; +FUNCTION lseek (f, offset, whence : integer) : integer; EXTERNAL; +FUNCTION read (f : integer; VAR b : buffer; n : integer) : integer; EXTERNAL; +FUNCTION close (f : integer) : integer; EXTERNAL; diff --git a/dviware/psprint/unix/fontlist.ps b/dviware/psprint/unix/fontlist.ps new file mode 100644 index 0000000000..4bcd9d57b1 --- /dev/null +++ b/dviware/psprint/unix/fontlist.ps @@ -0,0 +1,97 @@ +% Produces an alphabetical list of fonts available in printer. + +/MaxNrOfFonts 50 def % Maximum numbers of fonts... +/Xpos 136 def +/Ypos 690 def +/num 0 def % local counter +/incr { + /num num 1 add def +} def + +/s40 { 40 string } def % Proper length of the fontname + +/showline { % Show and newlines + show + newline +} def + +/newline { % Spacing between lines + /Ypos Ypos 12 sub def + Xpos Ypos moveto +} def + +/CountFonts { % Count the fonts and put the names into array + FontDirectory + { + pop + s40 + cvs + incr + } + forall + /FontArray num array def + FontArray astore + pop +} def + +/ListFonts { % Sort the fonts and show them on paper + Bubbelsort + FontArray + { + showline + } + forall +} def + +/Bubbelsort { % Here is the sorting routine + 1 1 num 1 sub + { + /localcount exch def + num 1 sub -1 localcount + { + /innercount exch def + /firststring FontArray innercount 1 sub get def + /secondstring FontArray innercount get def + firststring secondstring gt + { + FontArray innercount 1 sub secondstring put + FontArray innercount firststring put + } if + } for + } for +} def + +/prettyline +{ /YPOSition exch def + newpath + Xpos Ypos YPOSition add moveto + Xpos 100 add Ypos YPOSition add lineto + stroke +} def + +/Times-Roman findfont 12 scalefont setfont +14 prettyline + +Xpos Ypos 18 add moveto +CountFonts +(Number of fonts: ) show +num s40 cvs show + +30 prettyline +Xpos Ypos moveto +ListFonts +newline + +/Times-Bold findfont 12 scalefont setfont +(Total memory: ) show +vmstatus s40 cvs show newline +(Memory used: ) show +s40 cvs show newline +pop +(Free memory: ) show +vmstatus exch sub s40 cvs show newline newline +pop +/Times-Roman findfont 12 scalefont setfont +(From ulfis@nada.kth.se, 88-10-05) show + +showpage diff --git a/dviware/psprint/unix/fontreader.h b/dviware/psprint/unix/fontreader.h new file mode 100644 index 0000000000..f120304167 --- /dev/null +++ b/dviware/psprint/unix/fontreader.h @@ -0,0 +1,9 @@ +(* FontReader *) + +PROCEDURE InitFontReader; EXTERNAL; +PROCEDURE PixelTableRoutine; EXTERNAL; +PROCEDURE LoadBitmap (fontptr : fontinfoptr; code : INTEGER); EXTERNAL; +PROCEDURE BuildFontSpec (fontptr : fontinfoptr; + VAR firstn, lastn : INTEGER); EXTERNAL; +FUNCTION OpenFontFile (VAR name : string) : BOOLEAN; EXTERNAL; +PROCEDURE CloseFontFile; EXTERNAL; diff --git a/dviware/psprint/unix/fontreader.p b/dviware/psprint/unix/fontreader.p new file mode 100644 index 0000000000..c52c214a1e --- /dev/null +++ b/dviware/psprint/unix/fontreader.p @@ -0,0 +1,926 @@ +(* FontReader implements the routines for reading character metric and + bitmap information from PK files, or from TFM files for PostScript fonts. +*) + +#include 'globals.h'; +#include 'files.h'; +#include 'options.h'; +#include 'dvireader.h'; +#include 'fontreader.h'; +#include 'pswriter.h'; (* for PSfile and NewBitmapFont *) + +TYPE + BITSET = SET OF 0..31; + + (* SYSDEP: The following variant record is needed because + Pyramid Pascal does not provide type coercion. + Note that we couldn't overlay INTEGER and BITSET because + of the crazy storage scheme used to represent a set of 0..31 + where the bit order within a word is 7..0 15..8 23..16 31..24! + *) + + bytes_or_bits = RECORD + CASE b : BOOLEAN OF + TRUE : (ch : PACKED ARRAY [0..3] OF CHAR); + FALSE : (bits : BITSET); + END; + +VAR + PTfile : integer; (* PK/TFM file descriptor *) + PToffset : INTEGER; (* current byte offset in PTfile *) + currPTbuff : INTEGER; (* starting byte offset in buffer *) + PTbuffer : buffer; (* input buffer *) + psprefixlen, (* length of psprefix string *) + fontdirlen : INTEGER; (* length of fontdir string *) + hexdigs : ARRAY [0..15] OF CHAR; (* 0..9ABCDEF for LoadBitmap *) + gpower : ARRAY [0..32] OF BITSET; (* 0,1,11,111,1111,... *) + turnon : BOOLEAN; (* is current run black? *) + dynf, (* dynamic packing variable *) + repeatcount, (* times to repeat the next row *) + bitweight : INTEGER; (* for bits or nybbles from inputbyte *) + inputbyte : bytes_or_bits; (* the current input byte *) + lf, lh, bc, ec, nw, nh : INTEGER; (* TFM file data *) + TFMinfo : ARRAY [0..255] OF + RECORD + wdindex, htindex, dpindex : INTEGER; + END; + charmetrics : ARRAY [0..255] OF + RECORD + width, height, depth : ARRAY [0..3] OF INTEGER; + END; + +(******************************************************************************) + +PROCEDURE BuildTFMSpec (fontptr : fontinfoptr); + +(* Build a complete TFM file specification in fontptr^.fontspec. + This will only be done once per font; fontspeclen will no longer be 0. + fontptr^.fontexists becomes TRUE if the file can be opened. +*) + +LABEL 999; + +VAR f, result, i, nxt : INTEGER; + +BEGIN +WITH fontptr^ DO BEGIN + i := 0; + IF fontarealen > 0 THEN BEGIN + nxt := fontarealen; + REPEAT + fontspec[i] := fontarea[i]; (* start fontspec with fontarea *) + i := i + 1; + UNTIL (i = nxt) OR (i > maxfontspec); + END + ELSE BEGIN + nxt := Len(tfmdir); (* assume > 0 *) + REPEAT + fontspec[i] := tfmdir[i]; (* start fontspec with tfmdir *) + i := i + 1; + UNTIL (i = nxt) OR (i > maxfontspec); + END; + IF nxt >= maxfontspec THEN BEGIN + fontspeclen := maxfontspec; + goto 999; (* fontspec truncated *) + END; + (* nxt is current length of fontspec; append fontname.tfm *) + i := 0; + WHILE (i < fontnamelen) AND (nxt < maxfontspec) DO BEGIN + fontspec[nxt] := fontname[i]; (* append fontname *) + i := i + 1; + nxt := nxt + 1; + END; + IF nxt + 4 <= maxfontspec THEN BEGIN (* append .tfm *) + fontspec[nxt] := '.'; nxt := nxt + 1; + fontspec[nxt] := 't'; nxt := nxt + 1; + fontspec[nxt] := 'f'; nxt := nxt + 1; + fontspec[nxt] := 'm'; nxt := nxt + 1; + END + ELSE BEGIN + fontspeclen := maxfontspec; + goto 999; (* fontspec truncated *) + END; + fontspeclen := nxt; + IF fontspeclen < maxstring THEN fontspec[fontspeclen] := CHR(0); + f := open(fontspec,O_RDONLY,0); (* try to open file *) + IF fontspeclen < maxstring THEN fontspec[fontspeclen] := ' '; + IF f >= 0 THEN BEGIN + result := close(f); + fontexists := TRUE; (* fontspec exists *) + END; +END; +999: +END; (* BuildTFMSpec *) + +(******************************************************************************) + +FUNCTION CompleteFontSpec (fontptr : fontinfoptr; + nxt : INTEGER; + fontsizelen : INTEGER; + VAR firstn : INTEGER) : BOOLEAN; + +(* Return TRUE if we can append "fontname.n...npk" to fontspec. + Such a scheme is used in the latest TeX distributions. +*) + +LABEL 999; + +VAR i : INTEGER; + +BEGIN +WITH fontptr^ DO BEGIN + i := 0; + WHILE (i < fontnamelen) AND (nxt < maxfontspec) DO BEGIN + fontspec[nxt] := fontname[i]; (* append fontname *) + i := i + 1; + nxt := nxt + 1; + END; + firstn := nxt + 1; (* position of 1st n *) + IF nxt + fontsizelen + 2 < maxfontspec THEN BEGIN + fontspec[nxt] := '.'; + nxt := nxt + fontsizelen + 1; (* skip n...n *) + fontspec[nxt] := 'p'; (* append pk *) + nxt := nxt + 1; + fontspec[nxt] := 'k'; + nxt := nxt + 1; + END + ELSE BEGIN + fontspeclen := maxfontspec; + CompleteFontSpec := FALSE; + goto 999; (* fontspec truncated *) + END; + fontspeclen := nxt; + IF nxt < maxfontspec THEN fontspec[nxt] := ' '; (* terminate string *) + CompleteFontSpec := TRUE; +END; +999: +END; (* CompleteFontSpec *) + +(******************************************************************************) + +PROCEDURE BuildFontSpec (fontptr : fontinfoptr; VAR firstn, lastn : INTEGER); + +(* Build a complete file specification in fontptr^.fontspec. + This will only be done once per font; fontspeclen will no longer be 0. + fontptr^.fontexists becomes TRUE if the file can be opened. +*) + +LABEL 888, 999; + +VAR f, result, i, j, nxt, fontsize, tempsize, tempsizelen : INTEGER; + +BEGIN +WITH fontptr^ DO BEGIN + (* first check for a PostScript font; following code will set psfont to TRUE + if psprefixlen = 0 --- ALL fonts will be considered PostScript fonts + *) + psfont := TRUE; + i := 0; + WHILE TRUE DO BEGIN + IF i = psprefixlen THEN goto 888; + IF Cap(fontname[i]) <> Cap(psprefix[i]) THEN BEGIN + psfont := FALSE; + goto 888; + END; + i := i + 1; + END; + 888: + IF psfont THEN BEGIN + BuildTFMSpec(fontptr); (* build TFM file spec *) + goto 999; + END; + i := 0; + nxt := fontdirlen; + REPEAT + fontspec[i] := fontdir[i]; (* start fontspec with fontdir *) + i := i + 1; + UNTIL (i = nxt) OR (i > maxfontspec); + IF nxt >= maxfontspec THEN BEGIN + fontspeclen := maxfontspec; + goto 999; (* fontspec truncated *) + END; + fontsize := TRUNC( mag * (scaledsize / designsize) + * (resolution / 1000.0) + 0.5 ); + IF fontsize = 0 THEN + fontsize := fontsize + 1; (* allow for subtracting 1 *) + tempsize := fontsize; + i := 1; + WHILE TRUE DO BEGIN + (* Complete rest of fontspec starting at nxt + and return the position of first digit for fontsize. + We have to try fontsize +/- 1 before giving up because + rounding problems can occur in the above fontsize calculation. + *) + j := tempsize; + tempsizelen := 0; + WHILE j > 0 DO BEGIN + tempsizelen := tempsizelen + 1; + j := j DIV 10; + END; + IF NOT CompleteFontSpec(fontptr, nxt, tempsizelen, firstn) THEN + goto 999; (* fontspec truncated *) + lastn := firstn + tempsizelen - 1; + (* put tempsize into fontspec[firstn..lastn] *) + FOR j := lastn DOWNTO firstn DO BEGIN + fontspec[j] := CHR(ORD('0') + (tempsize MOD 10)); + tempsize := tempsize DIV 10; + END; + IF i > 3 THEN (* original fontsize has been restored *) + goto 999; (* could not open fontspec *) + IF fontspeclen < maxstring THEN fontspec[fontspeclen] := CHR(0); + f := open(fontspec,O_RDONLY,0); (* try to open file *) + IF fontspeclen < maxstring THEN fontspec[fontspeclen] := ' '; + IF f >= 0 THEN BEGIN + result := close(f); + fontexists := TRUE; (* fontspec exists *) + goto 999; + END + ELSE IF i = 1 THEN + tempsize := fontsize - 1 (* try fontsize-1 *) + ELSE IF i = 2 THEN + tempsize := fontsize + 1 (* try fontsize+1 *) + ELSE + tempsize := fontsize; (* restore original fontsize *) + i := i + 1; + END; +END; +999: +END; (* BuildFontSpec *) + +(******************************************************************************) + +FUNCTION OpenFontFile (VAR name : string) : BOOLEAN; + +(* Return TRUE if given file can be opened. + Only one font file will be open at any given time. +*) + +LABEL 888; + +VAR length : integer; + +BEGIN +currPTbuff := -1; (* impossible value for first GetPTByte *) +length := 0; +WHILE length < maxstring DO BEGIN + IF name[length] = ' ' THEN goto 888; + length := length + 1; +END; +888: +IF length < maxstring THEN name[length] := CHR(0); (* terminate with NULL *) +PTfile := open(name, O_RDONLY, 0); +IF length < maxstring THEN name[length] := ' '; (* restore space *) +OpenFontFile := PTfile >= 0; +END; (* OpenFontFile *) + +(******************************************************************************) + +PROCEDURE CloseFontFile; + +(* Close the currently open font file. *) + +VAR result : integer; + +BEGIN +result := close(PTfile); +END; (* CloseFontFile *) + +(******************************************************************************) + +FUNCTION GetPTByte : INTEGER; + +(* Returns the value (unsigned) of the byte at PToffset and + advances PToffset for the next GetPTByte. +*) + +VAR buffstart, result : INTEGER; + +BEGIN +buffstart := (PToffset DIV bufflen) * bufflen; (* 0, bufflen, 2*bufflen... *) +IF buffstart <> currPTbuff THEN BEGIN + currPTbuff := buffstart; + result := lseek(PTfile, buffstart, 0); + { DEBUG + IF result <> buffstart THEN BEGIN + writeln('Lseek failed in GetPTByte!'); exit(1); + END; + GUBED } + result := read(PTfile, PTbuffer, bufflen); + { DEBUG + IF result = -1 THEN BEGIN + writeln('Read failed in GetPTByte!'); exit(1); + END; + GUBED } +END; +GetPTByte := ORD(PTbuffer[PToffset - buffstart]); +PToffset := PToffset + 1; +END; (* GetPTByte *) + +(******************************************************************************) + +FUNCTION SignedPTByte : INTEGER; (* the next byte, signed *) + +VAR b : INTEGER; + +BEGIN +b := GetPTByte; +IF b < 128 THEN + SignedPTByte := b +ELSE + SignedPTByte := b - 256; +END; (* SignedPTByte *) + +(******************************************************************************) + +FUNCTION GetTwoPTBytes : INTEGER; (* the next 2 bytes, unsigned *) + +VAR a, b : INTEGER; + +BEGIN +a := GetPTByte; +b := GetPTByte; +GetTwoPTBytes := a * 256 + b; +END; (* GetTwoPTBytes *) + +(******************************************************************************) + +FUNCTION SignedPTPair : INTEGER; (* the next 2 bytes, signed *) + +VAR a, b : INTEGER; + +BEGIN +a := GetPTByte; +b := GetPTByte; +IF a < 128 THEN + SignedPTPair := a * 256 + b +ELSE + SignedPTPair := (a - 256) * 256 + b; +END; (* SignedPTPair *) + +(******************************************************************************) + +FUNCTION GetThreePTBytes : INTEGER; (* the next 3 bytes, unsigned *) + +VAR a, b, c : INTEGER; + +BEGIN +a := GetPTByte; +b := GetPTByte; +c := GetPTByte; +GetThreePTBytes := (a * 256 + b) * 256 + c; +END; (* GetThreePTBytes *) + +(******************************************************************************) + +FUNCTION SignedPTQuad : INTEGER; (* the next 4 bytes, signed *) + + +TYPE int_or_bytes = RECORD + CASE b : BOOLEAN OF + TRUE : (int : INTEGER); + FALSE : (byt : PACKED ARRAY [0..3] OF CHAR); + END; + +VAR w : int_or_bytes; + +BEGIN +WITH w DO BEGIN + w.byt[0] := CHR(GetPTByte); + w.byt[1] := CHR(GetPTByte); + w.byt[2] := CHR(GetPTByte); + w.byt[3] := CHR(GetPTByte); +END; +SignedPTQuad := w.int; +END; (* SignedPTQuad *) + +(******************************************************************************) + +FUNCTION GetNyb : INTEGER; + +(* Return next nybble in PK file. *) + +BEGIN +IF bitweight = 0 THEN BEGIN + (* SYSDEP: Pyramid Pascal stores bits 7..0 in the LEFT + byte of a 4-byte BITSET word. *) + inputbyte.ch[0] := CHR(GetPTByte); + bitweight := 16; (* for next call of GetNyb *) + GetNyb := ORD(inputbyte.ch[0]) DIV 16; (* high nybble *) +END +ELSE BEGIN + bitweight := 0; (* for next call of GetNyb *) + GetNyb := ORD(inputbyte.ch[0]) MOD 16; (* low nybble *) +END; +END; (* GetNyb *) + +(******************************************************************************) + +FUNCTION PackedNum : INTEGER; + +(* Return next run count using algorithm given in section 23 of PKtype. + A possible side-effect is to set the global repeatcount value used + to duplicate the current row. +*) + +VAR i, j : INTEGER; + +BEGIN +i := GetNyb; +IF i = 0 THEN BEGIN + REPEAT j := GetNyb; i := i + 1 UNTIL j <> 0; + WHILE i > 0 DO BEGIN j := j * 16 + GetNyb; i := i - 1 END; + PackedNum := j - 15 + (13 - dynf) * 16 + dynf; +END +ELSE IF i <= dynf THEN + PackedNum := i +ELSE IF i < 14 THEN + PackedNum := (i - dynf - 1) * 16 + GetNyb + dynf + 1 +ELSE BEGIN + IF i = 14 THEN + repeatcount := PackedNum (* recursive *) + ELSE + repeatcount := 1; (* nybble = 15 *) + PackedNum := PackedNum; (* recursive *) +END; +END; (* PackedNum *) + +(******************************************************************************) + +PROCEDURE LoadBitmap (fontptr : fontinfoptr; code : INTEGER); + +(* Output PostScript character definition using bitmap info at mapadr + in currently open PK file. +*) + +CONST maxhexline = 72; (* keep even and < 80 *) + +VAR + hexline : PACKED ARRAY [1..maxhexline] OF CHAR; + hexcount, (* current hexline length *) + i, j, flagbyte, bitpos, bytesperrow, + rowsleft, hbit, count, rp : INTEGER; + byte : bytes_or_bits; (* we'll only consider bits 0..7 *) + row : ARRAY [0..400] OF CHAR; (* maximum glyph width = 3200 bits *) + +BEGIN +WITH fontptr^.pixelptr^[code] DO BEGIN +bytesperrow := (wd + 7) DIV 8; (* bytes in one row *) +PToffset := mapadr; (* mapadr = flagbyte offset in PK file *) +flagbyte := GetPTByte; (* assume < 240 *) +dynf := flagbyte DIV 16; +turnon := (flagbyte MOD 16) >= 8; (* is 1st pixel black? *) +flagbyte := flagbyte MOD 8; (* value of bottom 3 bits *) +IF flagbyte < 4 THEN (* skip short char preamble *) + PToffset := PToffset + 10 +ELSE IF flagbyte < 7 THEN (* skip extended short char preamble *) + PToffset := PToffset + 16 +ELSE (* skip long char preamble *) + PToffset := PToffset + 36; +hexline[1] := '['; (* start of hex string *) +hexline[2] := '<'; +hexcount := 2; (* chars in current hexline *) +bitweight := 0; (* to get 1st inputbyte *) +IF dynf = 14 THEN BEGIN + (* raster info is a string of bits in the next (wd * ht + 7) DIV 8 bytes *) + FOR i := 1 TO ht DO BEGIN + byte.bits := []; (* set all bits to 0 *) + bitpos := 7; (* leftmost bit *) + FOR j := 1 TO wd DO BEGIN + IF bitweight = 0 THEN BEGIN + inputbyte.ch[0] := CHR(GetPTByte); + bitweight := 8; + END; + bitweight := bitweight - 1; (* 7..0 *) + IF bitweight IN inputbyte.bits THEN + byte.bits := byte.bits + [bitpos]; (* include bitpos *) + IF bitpos > 0 THEN + bitpos := bitpos - 1 (* next bit *) + ELSE BEGIN + (* SYSDEP: Pyramid Pascal stores bits 7..0 in the LEFT + byte of a 4-byte BITSET word. *) + hexcount := hexcount + 1; + hexline[hexcount] := hexdigs[ ORD(byte.ch[0]) DIV 16 ]; + hexcount := hexcount + 1; + hexline[hexcount] := hexdigs[ ORD(byte.ch[0]) MOD 16 ]; + IF hexcount = maxhexline THEN BEGIN + writeln(PSfile,hexline:hexcount); + hexcount := 0; + END; + byte.bits := []; + bitpos := 7; + END; + END; + IF bitpos < 7 THEN BEGIN + hexcount := hexcount + 1; + hexline[hexcount] := hexdigs[ ORD(byte.ch[0]) DIV 16 ]; + hexcount := hexcount + 1; + hexline[hexcount] := hexdigs[ ORD(byte.ch[0]) MOD 16 ]; + IF hexcount = maxhexline THEN BEGIN + writeln(PSfile,hexline:hexcount); + hexcount := 0; + END; + END; + END +END +ELSE BEGIN + (* raster info is encoded as run and repeat counts *) + rowsleft := ht; + hbit := wd; + repeatcount := 0; + rp := 1; + bitpos := 8; + byte.bits := []; + WHILE rowsleft > 0 DO BEGIN + count := PackedNum; + WHILE count > 0 DO BEGIN + IF (count < bitpos) AND (count < hbit) THEN BEGIN + IF turnon THEN + byte.bits := byte.bits + gpower[bitpos] + - gpower[bitpos - count]; + hbit := hbit - count; + bitpos := bitpos - count; + count := 0; + END + ELSE IF (count >= hbit) AND (hbit <= bitpos) THEN BEGIN + IF turnon THEN + byte.bits := byte.bits + gpower[bitpos] + - gpower[bitpos - hbit]; + (* SYSDEP: Pyramid Pascal stores bits 7..0 in the LEFT + byte of a 4-byte BITSET word. *) + row[rp] := byte.ch[0]; + (* end of current row, so send it repeatcount+1 times *) + FOR i := 0 TO repeatcount DO + FOR j := 1 TO bytesperrow DO BEGIN + hexcount := hexcount + 1; + hexline[hexcount] := hexdigs[ ORD(row[j]) DIV 16 ]; + hexcount := hexcount + 1; + hexline[hexcount] := hexdigs[ ORD(row[j]) MOD 16 ]; + IF hexcount = maxhexline THEN BEGIN + writeln(PSfile,hexline:hexcount); + hexcount := 0; + END; + END; + rowsleft := rowsleft - (repeatcount + 1); + repeatcount := 0; + rp := 1; + byte.bits := []; + bitpos := 8; + count := count - hbit; + hbit := wd; + END + ELSE BEGIN + IF turnon THEN byte.bits := byte.bits + gpower[bitpos]; + row[rp] := byte.ch[0]; + rp := rp + 1; + byte.bits := []; + count := count - bitpos; + hbit := hbit - bitpos; + bitpos := 8; + END; + END; + turnon := NOT turnon; + END; +END; +IF hexcount > 0 THEN write(PSfile,hexline:hexcount); +writeln(PSfile, '>'); +writeln(PSfile, bytesperrow * 8:1, ' ', ht:1, ' ', xo:1, ' ', yo:1, ' ', + pwidth:1, '] ', code:1, ' dc'); +END; (* WITH *) +END; (* LoadBitmap *) + +(******************************************************************************) + +FUNCTION FixToDVI (b0, b1, b2, b3 : INTEGER) : INTEGER; + +(* Convert the given fix width (made up of 4 bytes) into DVI units + using the method recommended in DVITYPE. +*) + +VAR alpha, beta, temp, s : INTEGER; + +BEGIN +WITH currfont^ DO BEGIN + s := scaledsize; + alpha := 16 * s; + beta := 16; + WHILE s >= 8#40000000 DO BEGIN (* 2^23 *) + s := s DIV 2; + beta := beta DIV 2; + END; + temp := (((((b3 * s) DIV 8#400) + (b2 * s)) DIV 8#400) + (b1 * s)) DIV beta; + IF b0 > 0 THEN + IF b0 = 255 THEN + FixToDVI := temp - alpha + ELSE BEGIN + writeln; writeln('Bad TFM width! 1st byte = ', b0:1); exit(1); + END + ELSE + FixToDVI := temp; +END; +END; (* FixToDVI *) + +(******************************************************************************) + +PROCEDURE PKFillPixelTable; + +(* Fill the pixeltable for currfont^ using the font directory info + in the currently open PK file. +*) + +LABEL 888; + +CONST + pkid = 89; + pkpost = 245; + pknoop = 246; + pkpre = 247; + +VAR + i, j, flagbyte, flagpos, + chcode, (* assumed to be <= 255 *) + packetlen, endofpacket, + b0, b1, b2, b3 : INTEGER; (* 4 bytes in TFM width *) + +BEGIN +WITH currfont^ DO BEGIN + PToffset := 0; (* move to first byte *) + IF GetPTByte <> pkpre THEN BEGIN + writeln; writeln('Bad pre command in ', fontspec:fontspeclen); exit(1); + END; + IF GetPTByte <> pkid THEN BEGIN + writeln; writeln('Bad id byte in ', fontspec:fontspeclen); exit(1); + END; + j := GetPTByte; (* length of comment *) + PToffset := PToffset + j + 16; (* skip rest of preamble *) + FOR i := 0 TO maxTeXchar DO + WITH pixelptr^[i] DO BEGIN + mapadr := 0; (* all chars absent initially *) + loaded := FALSE; (* bitmap not yet downloaded *) + END; + WHILE TRUE DO BEGIN + flagpos := PToffset; (* remember position of flagbyte *) + flagbyte := GetPTByte; + IF flagbyte < 240 THEN BEGIN (* read character definition *) + flagbyte := flagbyte MOD 8; (* value of bottom 3 bits *) + IF flagbyte < 4 THEN BEGIN (* short char preamble *) + packetlen := flagbyte * 256 + GetPTByte; + chcode := GetPTByte; + endofpacket := packetlen + PToffset; + WITH pixelptr^[chcode] DO BEGIN + b1 := GetPTByte; + b2 := GetPTByte; + b3 := GetPTByte; + dwidth := FixToDVI(0,b1,b2,b3); (* b0 = 0 *) + pwidth := GetPTByte; + wd := GetPTByte; + ht := GetPTByte; + xo := SignedPTByte; + yo := SignedPTByte; + END; + END + ELSE IF flagbyte < 7 THEN BEGIN (* extended short char preamble *) + packetlen := (flagbyte - 4) * 65536 + GetTwoPTBytes; + chcode := GetPTByte; + endofpacket := packetlen + PToffset; + WITH pixelptr^[chcode] DO BEGIN + b1 := GetPTByte; + b2 := GetPTByte; + b3 := GetPTByte; + dwidth := FixToDVI(0,b1,b2,b3); (* b0 = 0 *) + pwidth := GetTwoPTBytes; + wd := GetTwoPTBytes; + ht := GetTwoPTBytes; + xo := SignedPTPair; + yo := SignedPTPair; + END; + END + ELSE BEGIN (* long char preamble *) + packetlen := SignedPTQuad; + chcode := SignedPTQuad; + endofpacket := packetlen + PToffset; + WITH pixelptr^[chcode] DO BEGIN + b0 := GetPTByte; + b1 := GetPTByte; + b2 := GetPTByte; + b3 := GetPTByte; + dwidth := FixToDVI(b0,b1,b2,b3); + pwidth := SignedPTQuad DIV 65536; (* dx in pixels *) + PToffset := PToffset + 4; (* skip dy *) + wd := SignedPTQuad; + ht := SignedPTQuad; + xo := SignedPTQuad; + yo := SignedPTQuad; + END; + END; + WITH pixelptr^[chcode] DO + IF (wd = 0) OR (ht = 0) THEN + mapadr := 0 (* no bitmap *) + ELSE + mapadr := flagpos; (* position of flagbyte *) + PToffset := endofpacket; (* skip raster info *) + END + ELSE + CASE flagbyte OF + 240, 241, 242, 243 : + BEGIN + i := 0; + FOR j := 240 TO flagbyte DO i := 256 * i + GetPTByte; + PToffset := PToffset + i; (* skip special parameter *) + END; + 244 : PToffset := PToffset + 4; (* skip numspecial param *) + pknoop : ; (* do nothing *) + pkpost : goto 888; (* no more char defs *) + OTHERWISE + writeln; writeln('Bad flag byte in ', fontspec:fontspeclen); + exit(1); + END; + END; (* of LOOP; flagbyte = pkpost *) + 888: +END; +END; (* PKFillPixelTable *) + +(******************************************************************************) + +PROCEDURE ReadTFMIntegers; + +(* Read the first 6 16-bit integers in the TFM file. See TFtoPL section 8. *) + +BEGIN +PToffset := 0; (* start reading at 1st byte in TFM file *) +lf := GetTwoPTBytes; +lh := GetTwoPTBytes; +bc := GetTwoPTBytes; +ec := GetTwoPTBytes; +nw := GetTwoPTBytes; +nh := GetTwoPTBytes; +END; (* ReadTFMIntegers *) + +(******************************************************************************) + +PROCEDURE ReadTFMCharInfo; + +(* Read the TFMinfo array. See TFtoPL section 11. *) + +VAR c, i : INTEGER; + +BEGIN +PToffset := 24 + (lh * 4); (* offset of TFMinfo array *) +FOR c := bc TO ec DO + WITH TFMinfo[c] DO BEGIN + wdindex := GetPTByte * 4; (* offset from start of width array *) + i := GetPTByte; (* 2nd byte contains htindex and dpindex *) + htindex := (i DIV 16) * 4; (* offset from start of height array *) + dpindex := (i MOD 16) * 4; (* offset from start of depth array *) + PToffset := PToffset + 2; (* skip itindex and remainder bytes *) + END; +END; (* ReadTFMCharInfo *) + +(******************************************************************************) + +PROCEDURE ReadTFMCharMetrics; + +(* Read the charmetrics array using the indices in TFMinfo. *) + +VAR wdbase, htbase, dpbase, b, c : INTEGER; + +BEGIN +wdbase := 24 + lh * 4 + (ec - bc + 1) * 4; (* offset of width array *) +htbase := wdbase + nw * 4; (* offset of height array *) +dpbase := htbase + nh * 4; (* offset of depth array *) +FOR c := bc TO ec DO + WITH TFMinfo[c] DO + WITH charmetrics[c] DO BEGIN + PToffset := wdbase + wdindex; + FOR b := 0 TO 3 DO width[b] := GetPTByte; + PToffset := htbase + htindex; + FOR b := 0 TO 3 DO height[b] := GetPTByte; + PToffset := dpbase + dpindex; + FOR b := 0 TO 3 DO depth[b] := GetPTByte; + END; +END; (* ReadTFMCharMetrics *) + +(******************************************************************************) + +PROCEDURE TFMFillPixelTable; + +(* Fill the pixeltable for currfont^ (a PostScript font) + using information in the currently open TFM file. +*) + +VAR c, dheight, pheight, ddepth, pdepth : INTEGER; + +BEGIN +ReadTFMIntegers; (* read lf..nh *) +ReadTFMCharInfo; (* fill TFMinfo array *) +ReadTFMCharMetrics; (* fill charmetrics array *) +WITH currfont^ DO BEGIN + FOR c := 0 TO bc - 1 DO + pixelptr^[c].mapadr := 0; (* chars < bc don't exist *) + FOR c := ec + 1 TO 255 DO + pixelptr^[c].mapadr := 0; (* chars > ec don't exist *) + FOR c := bc TO ec DO + WITH pixelptr^[c] DO + WITH charmetrics[c] DO BEGIN + dwidth := FixToDVI(width[0],width[1],width[2],width[3]); + dheight := FixToDVI(height[0],height[1],height[2],height[3]); + ddepth := FixToDVI(depth[0],depth[1],depth[2],depth[3]); + (* convert DVI units to pixels *) + pwidth := PixelRound(dwidth); + pheight := PixelRound(dheight); + pdepth := PixelRound(ddepth); + (* Since we don't have access to bitmap info for a PostScript font + we will have to use the TFM width/height/depth info to + approximate wd, ht, xo, yo. + *) + wd := pwidth; + wd := wd - (wd DIV 8); (* better approximation *) + ht := pheight + pdepth; + xo := 0; + yo := pheight - 1; + IF (wd = 0) OR (ht = 0) THEN + mapadr := 0 (* char all-white or not in font *) + ELSE + mapadr := 1; (* anything but 0 *) + loaded := FALSE; (* no bitmap available *) + END; +END; +END; (* TFMFillPixelTable *) + +(******************************************************************************) + +PROCEDURE PixelTableRoutine; + +(* DVIReader has just allocated a new pixeltable for currfont^ and + calls this routine from InterpretPage only ONCE per font + (the first time the font is used). + We get the pixeltable information from the font file given by fontspec. + We also set fontid to a unique identifier of the form "fontname.fontsize". + If fontspec does not exist then dummyfont is used and fontid is undefined. + We don't output any PostScript for non-existent fonts. +*) + +VAR i, fontsizelen, firstn, lastn : INTEGER; + +BEGIN +(* Initialize currfont^.fontspec and return start and end of fontsize + (unless psfont flag is set to TRUE). + currfont^.fontexists may also become TRUE. +*) +BuildFontSpec(currfont,firstn,lastn); +WITH currfont^ DO BEGIN + IF OpenFontFile(fontspec) THEN BEGIN + (* only need fontid for a bitmapped font *) + IF NOT psfont THEN BEGIN + fontid := fontname; + fontsizelen := lastn - firstn + 1; + IF fontnamelen + fontsizelen < maxfontspec THEN BEGIN + (* append ".fontsize" to fontid *) + fontid[fontnamelen] := '.'; + FOR i := 1 TO fontsizelen DO + fontid[fontnamelen + i] := fontspec[firstn + i - 1]; + END + ELSE BEGIN + (* in the unlikely event that there is no room to append ".fontsize" + we simply leave fontid = fontname and hope it's unique *) + writeln; + writeln('Warning! fontname too long: ', fontname:fontnamelen); + END; + IF NOT conserveVM THEN NewBitmapFont(fontid); + END; + END + ELSE IF OpenFontFile(dummyfont) THEN BEGIN + (* fontid is left undefined; it will not be used *) + warncount := warncount + 1; + writeln; + writeln('Couldn''t open font file: ', fontspec:fontspeclen); + (* use dummy font info instead *) + END + ELSE BEGIN + writeln; + writeln('Couldn''t open dummy font: ', dummyfont:Len(dummyfont)); + exit(1); + END; + IF psfont AND fontexists THEN + TFMFillPixelTable + ELSE + PKFillPixelTable; + CloseFontFile; +END; +END; (* PixelTableRoutine *) + +(******************************************************************************) + +PROCEDURE InitFontReader; + +(* This routine initializes some global variables. *) + +VAR i : INTEGER; + +BEGIN +hexdigs := '0123456789ABCDEF'; (* for LoadBitmap *) +gpower[0] := []; +FOR i := 1 TO 8 DO + gpower[i] := gpower[i-1] + [i-1]; (* for LoadBitmap *) +psprefixlen := Len(psprefix); +fontdirlen := Len(fontdir); +END; (* InitFontReader *) diff --git a/dviware/psprint/unix/fontsample.tex b/dviware/psprint/unix/fontsample.tex new file mode 100644 index 0000000000..f531af4cf3 --- /dev/null +++ b/dviware/psprint/unix/fontsample.tex @@ -0,0 +1,241 @@ +% This file produces font samples. +% See the end for how to select fonts for evaluation. + +\nopagenumbers +\parindent=0pt +\hsize=6.3in +\vsize=9.7in + +\def\init{\font\testfont=\fontname + \leftline{\tt\fontname} + \bigskip\bigskip + \testfont} + +\newcount\m \newcount\n \newcount\p \newdimen\dim +\def\oct#1{\hbox{\rm\'{}\kern-.2em\it#1\/\kern.05em}} % octal constant +\def\hex#1{\hbox{\rm\H{}\tt#1}} % hexadecimal constant +\def\setdigs#1"#2{\gdef\h{#2}% \h=hex prefix; \0\1=corresponding octal + \m=\n \divide\m by 64 \xdef\0{\the\m}% + \multiply\m by-64 \advance\m by\n \divide\m by 8 \xdef\1{\the\m}} +\def\testrow{\setbox0=\hbox{\penalty 1\def\\{\char"\h}% + \\0\\1\\2\\3\\4\\5\\6\\7\\8\\9\\A\\B\\C\\D\\E\\F% + \global\p=\lastpenalty}} % \p=1 if none of the characters exist +\def\oddline{\cr + \noalign{\nointerlineskip} + \multispan{19}\hrulefill& + \setbox0=\hbox{\lower 2.3pt\hbox{\hex{\h x}}}\smash{\box0}\cr + \noalign{\nointerlineskip}} +\newif\ifskipping + +\def\halfevenline{\loop\skippingfalse + \ifnum\n<128 \m=\n \divide\m 16 \chardef\next=\m + \expandafter\setdigs\meaning\next \testrow + \ifnum\p=1 + \skippingfalse % if \skippingtrue then empty rows are removed + \fi\fi + \ifskipping \global\advance\n 16 \repeat + \ifnum\n=128 \let\next=\endchart\else\let\next=\halfmorechart\fi + \next} +\def\halfmorechart{\cr\noalign{\hrule\penalty5000} + \chartline \oddline \m=\1 \advance\m 1 \xdef\1{\the\m} + \chartline \halfevenline} + +\def\evenline{\loop\skippingfalse + \ifnum\n<256 \m=\n \divide\m 16 \chardef\next=\m + \expandafter\setdigs\meaning\next \testrow + \ifnum\p=1 + \skippingfalse % if \skippingtrue then empty rows are removed + \fi\fi + \ifskipping \global\advance\n 16 \repeat + \ifnum\n=256 \let\next=\endchart\else\let\next=\morechart\fi + \next} + +\def\morechart{\cr\noalign{\hrule\penalty5000} + \chartline \oddline \m=\1 \advance\m 1 \xdef\1{\the\m} + \chartline \evenline} +\def\chartline{&\oct{\0\1x}&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&\:&&} +\def\chartstrut{\lower4.5pt\vbox to14pt{}} + +\def\halftable{$$\global\n=0 + \halign to\hsize\bgroup + \chartstrut##\tabskip0pt plus10pt& + &\hfil##\hfil&\vrule##\cr + \lower6.5pt\null + &&&\oct0&&\oct1&&\oct2&&\oct3&&\oct4&&\oct5&&\oct6&&\oct7&\halfevenline} + +\def\table{$$\global\n=0 + \halign to\hsize\bgroup + \chartstrut##\tabskip0pt plus10pt& + &\hfil##\hfil&\vrule##\cr + \lower6.5pt\null + &&&\oct0&&\oct1&&\oct2&&\oct3&&\oct4&&\oct5&&\oct6&&\oct7&\evenline} + +\def\endchart{\cr\noalign{\hrule} + \raise11.5pt\null&&&\hex 8&&\hex 9&&\hex A&&\hex B& + &\hex C&&\hex D&&\hex E&&\hex F&\cr\egroup$$\par\vfil\eject} + +\def\:{\setbox0=\hbox{\char\n}% + \ifdim\ht0>7.5pt\reposition + \else\ifdim\dp0>2.5pt\reposition\fi\fi + \box0\global\advance\n 1 } +\def\reposition{\setbox0=\vbox{\kern2pt\box0}\dim=\dp0 + \advance\dim 2pt \dp0=\dim} +\def\centerlargechars{ + \def\reposition{\setbox0=\hbox{$\vcenter{\kern2pt\box0\kern2pt}$}}} + +\def\text#1{{\baselineskip=#1\rightskip=0pt plus5em +Our task is to create a paragraph illustrating what a typical piece of text +looks like in a particular \TeX\ font. It should be stressed that not all +\TeX\ fonts can be used for typesetting text. We need to show most of the +characters in this font---for instance, something like ``the quick brown fox +jumps over a lazy dog'' would use all the lower-case letters. +How about ``THE QUICK BROWN FOX JUMPS OVER 9876543210 LAZY DOGS'' to make +sure we show all the upper-case letters and digits? Such a paragraph would +hardly be typical! Then there's ligatures (try and fit in words like fluffy, +waffle, firefly, difficult) and examples of kerning (boxer, AWAY, vowel). +But how do we put all this stuff into a paragraph that makes sense!?\par +}\bigskip\bigskip} + + +% Computer Modern fonts currently have 128 characters, so we use \halftable. +% Parameter to \text is the \baselineskip and should be 2pt more than font size. +% It is not possible to produce a DVI file with all the fonts listed below +% because TeX has a limitation of about 100 fonts. + +\def\fontname{circle10} \init\halftable % no \text +\def\fontname{circlew10} \init\halftable % no \text +\def\fontname{cmb10} \init\text{12pt}\halftable +\def\fontname{cmbsy10} \init\halftable % no \text +\def\fontname{cmbx10} \init\text{12pt}\halftable +\def\fontname{cmbx12} \init\text{14pt}\halftable +\def\fontname{cmbx5} \init\text{7pt}\halftable +\def\fontname{cmbx6} \init\text{8pt}\halftable +\def\fontname{cmbx7} \init\text{9pt}\halftable +\def\fontname{cmbx8} \init\text{10pt}\halftable +\def\fontname{cmbx9} \init\text{11pt}\halftable +\def\fontname{cmbxsl10} \init\text{12pt}\halftable +\def\fontname{cmbxti10} \init\text{12pt}\halftable +\def\fontname{cmcsc10} \init\text{12pt}\halftable +\def\fontname{cmdunh10} \init\text{12pt}\halftable +\def\fontname{cmex10} \init\halftable % no \text +\def\fontname{cmff10} \init\text{12pt}\halftable +\def\fontname{cmfi10} \init\text{12pt}\halftable +\def\fontname{cmfib8} \init\text{10pt}\halftable +%% TOO BIG!!! \def\fontname{cminch} \init\halftable % no \text +%\def\fontname{cmitt10} \init\text{12pt}\halftable +%\def\fontname{cmmi10} \init\halftable % no \text +%\def\fontname{cmmi12} \init\halftable % no \text +%\def\fontname{cmmi5} \init\halftable % no \text +%\def\fontname{cmmi6} \init\halftable % no \text +%\def\fontname{cmmi7} \init\halftable % no \text +%\def\fontname{cmmi8} \init\halftable % no \text +%\def\fontname{cmmi9} \init\halftable % no \text +%\def\fontname{cmmib10} \init\halftable % no \text +%\def\fontname{cmr10} \init\text{12pt}\halftable +%\def\fontname{cmr12} \init\text{14pt}\halftable +%\def\fontname{cmr17} \init\text{19pt}\halftable +%\def\fontname{cmr5} \init\text{7pt}\halftable +%\def\fontname{cmr6} \init\text{8pt}\halftable +%\def\fontname{cmr7} \init\text{9pt}\halftable +%\def\fontname{cmr8} \init\text{10pt}\halftable +%\def\fontname{cmr9} \init\text{11pt}\halftable +%\def\fontname{cmsl10} \init\text{12pt}\halftable +%\def\fontname{cmsl12} \init\text{14pt}\halftable +%\def\fontname{cmsl8} \init\text{10pt}\halftable +%\def\fontname{cmsl9} \init\text{11pt}\halftable +%\def\fontname{cmsltt10} \init\text{12pt}\halftable +%\def\fontname{cmss10} \init\text{12pt}\halftable +%\def\fontname{cmss12} \init\text{14pt}\halftable +%\def\fontname{cmss17} \init\text{19pt}\halftable +%\def\fontname{cmss8} \init\text{10pt}\halftable +%\def\fontname{cmss9} \init\text{11pt}\halftable +%\def\fontname{cmssbx10} \init\text{12pt}\halftable +%\def\fontname{cmssdc10} \init\text{12pt}\halftable +%\def\fontname{cmssi10} \init\text{12pt}\halftable +%\def\fontname{cmssi12} \init\text{14pt}\halftable +%\def\fontname{cmssi17} \init\text{19pt}\halftable +%\def\fontname{cmssi8} \init\text{10pt}\halftable +%\def\fontname{cmssi9} \init\text{11pt}\halftable +%\def\fontname{cmssq8} \init\text{10pt}\halftable +%\def\fontname{cmssqi8} \init\text{10pt}\halftable +%\def\fontname{cmsy10} \init\halftable % no \text +%\def\fontname{cmsy5} \init\halftable % no \text +%\def\fontname{cmsy6} \init\halftable % no \text +%\def\fontname{cmsy7} \init\halftable % no \text +%\def\fontname{cmsy8} \init\halftable % no \text +%\def\fontname{cmsy9} \init\halftable % no \text +%\def\fontname{cmtcsc10} \init\text{12pt}\halftable +%\def\fontname{cmtex10} \init\text{12pt}\halftable +%\def\fontname{cmtex8} \init\text{10pt}\halftable +%\def\fontname{cmtex9} \init\text{11pt}\halftable +%\def\fontname{cmti10} \init\text{12pt}\halftable +%\def\fontname{cmti12} \init\text{14pt}\halftable +%\def\fontname{cmti7} \init\text{9pt}\halftable +%\def\fontname{cmti8} \init\text{10pt}\halftable +%\def\fontname{cmti9} \init\text{11pt}\halftable +%\def\fontname{cmtt10} \init\text{12pt}\halftable +%\def\fontname{cmtt12} \init\text{14pt}\halftable +%\def\fontname{cmtt8} \init\text{10pt}\halftable +%\def\fontname{cmtt9} \init\text{11pt}\halftable +%\def\fontname{cmu10} \init\text{12pt}\halftable +%\def\fontname{cmvtt10} \init\text{12pt}\halftable +%\def\fontname{crest} \init\halftable % no \text +%\def\fontname{lasy10} \init\halftable % no \text +%\def\fontname{lasy5} \init\halftable % no \text +%\def\fontname{lasy6} \init\halftable % no \text +%\def\fontname{lasy7} \init\halftable % no \text +%\def\fontname{lasy8} \init\halftable % no \text +%\def\fontname{lasy9} \init\halftable % no \text +%\def\fontname{lasyb10} \init\halftable % no \text +%\def\fontname{line10} \init\halftable % no \text +%\def\fontname{linew10} \init\halftable % no \text +%\def\fontname{logo10} \init\halftable % no \text +%\def\fontname{logo8} \init\halftable % no \text +%\def\fontname{logo9} \init\halftable % no \text +%\def\fontname{logobf10} \init\halftable % no \text +%\def\fontname{logosl10} \init\halftable % no \text + +% PostScript fonts can have up to 256 characters. +% These fonts are resident in all PostScript printers: + +%\def\fontname{ps-times-r at 10pt} \init\text{12pt}\table +%\def\fontname{ps-times-b at 10pt} \init\text{12pt}\table +%\def\fontname{ps-times-bi at 10pt} \init\text{12pt}\table +%\def\fontname{ps-times-i at 10pt} \init\text{12pt}\table +%\def\fontname{ps-times-s at 10pt} \init\text{12pt}\table +%\def\fontname{ps-courier at 10pt} \init\text{12pt}\table +%\def\fontname{ps-courier-b at 10pt} \init\text{12pt}\table +%\def\fontname{ps-courier-bo at 10pt} \init\text{12pt}\table +%\def\fontname{ps-courier-o at 10pt} \init\text{12pt}\table +%\def\fontname{ps-helv at 10pt} \init\text{12pt}\table +%\def\fontname{ps-helv-b at 10pt} \init\text{12pt}\table +%\def\fontname{ps-helv-bo at 10pt} \init\text{12pt}\table +%\def\fontname{ps-helv-o at 10pt} \init\text{12pt}\table +%\def\fontname{ps-symbol at 10pt} \init\table % no \text + +% These fonts are in LaserWriter Plus and later models: + +%\def\fontname{ps-avantg-b at 10pt} \init\text{12pt}\table +%\def\fontname{ps-avantg-bo at 10pt} \init\text{12pt}\table +%\def\fontname{ps-avantg-d at 10pt} \init\text{12pt}\table +%\def\fontname{ps-avantg-do at 10pt} \init\text{12pt}\table +%\def\fontname{ps-bookman-d at 10pt} \init\text{12pt}\table +%\def\fontname{ps-bookman-di at 10pt} \init\text{12pt}\table +%\def\fontname{ps-bookman-l at 10pt} \init\text{12pt}\table +%\def\fontname{ps-bookman-li at 10pt} \init\text{12pt}\table +%\def\fontname{ps-helv-n at 10pt} \init\text{12pt}\table +%\def\fontname{ps-helv-nb at 10pt} \init\text{12pt}\table +%\def\fontname{ps-helv-nbo at 10pt} \init\text{12pt}\table +%\def\fontname{ps-helv-no at 10pt} \init\text{12pt}\table +%\def\fontname{ps-ncs-b at 10pt} \init\text{12pt}\table +%\def\fontname{ps-ncs-bo at 10pt} \init\text{12pt}\table +%\def\fontname{ps-ncs-i at 10pt} \init\text{12pt}\table +%\def\fontname{ps-ncs-r at 10pt} \init\text{12pt}\table +%\def\fontname{ps-pal-b at 10pt} \init\text{12pt}\table +%\def\fontname{ps-pal-bi at 10pt} \init\text{12pt}\table +%\def\fontname{ps-pal-i at 10pt} \init\text{12pt}\table +%\def\fontname{ps-pal-r at 10pt} \init\text{12pt}\table +%\def\fontname{ps-zapfch-mi at 10pt} \init\text{12pt}\table +%\def\fontname{ps-zapfdb at 10pt} \init\table % no \text + +\end diff --git a/dviware/psprint/unix/globals.h b/dviware/psprint/unix/globals.h new file mode 100644 index 0000000000..b2e49f4b7c --- /dev/null +++ b/dviware/psprint/unix/globals.h @@ -0,0 +1,14 @@ +(* Global data and routines *) + +CONST + maxstring = 80; + maxstringm = maxstring - 1; + +TYPE + string = ARRAY [0..maxstringm] OF CHAR; + +VAR + warncount : INTEGER; (* used to determine exit status *) + +PROCEDURE exit (status : integer); EXTERNAL; +(* SYSDEP: 0 = success, 1 = error, 2 = warning *) diff --git a/dviware/psprint/unix/greybox.ps b/dviware/psprint/unix/greybox.ps new file mode 100644 index 0000000000..220564810a --- /dev/null +++ b/dviware/psprint/unix/greybox.ps @@ -0,0 +1,31 @@ +% This file is inserted into the PSPRINT User Guide using \special. +% It draws a shaded rectangle. + +72 72 scale % units are now inches instead of big points + +% uncomment the next line if you want to "psprint greybox.ps" +% 2 2 translate + +newpath % prepare to draw a rectangle + -.25 0.1 moveto % top left corner is a little left and above origin + 0 -.7 rlineto % down .7 + 4.5 0 rlineto % right 4.5 + 0 .7 rlineto % up .7 +closepath % complete rectangle +gsave % save current path + +0.9 setgray % light grey + +statusdict /product known +{ statusdict /product get + 0 11 getinterval + (LaserWriter) eq + {.99 setgray} if % if LaserWriter use very light shading (0=black, 1=white) +} if + +fill % paint interior of rectangle +grestore % restore current path +.01 setlinewidth % thickness of borders +stroke % paint borders + +showpage diff --git a/dviware/psprint/unix/info.ps b/dviware/psprint/unix/info.ps new file mode 100644 index 0000000000..c1fbaf1f98 --- /dev/null +++ b/dviware/psprint/unix/info.ps @@ -0,0 +1,107 @@ +% Print page showing various status values. + +/oldusertime usertime def + +initgraphics +newpath clippath stroke % show maximum image area + +72 0 translate % move origin to the right +/vpos 720 def % initial vertical pos +0 vpos moveto % start near top left corner + +/newline +{ /vpos vpos 12 sub def % decrease vertical pos + 0 vpos moveto % move to start of new line +} def + +/Courier findfont 10 scalefont setfont + +statusdict begin + margins % int int (top and left margins) + 9 sccbatch % baud options (for 9-pin serial channel) + 25 sccbatch % baud options (for 25-pin serial channel) + revision % int + product dup % string + (Linotype) eq + { userdiskpercent % percent + diskstatus % free total + resolution % int + true % we are running on a Linotronic + } + { false % we are running on some other device + } ifelse +end + +% true or false currently on top of stack + +{ (RESOLUTION = ) show ( ) cvs show newline + (DISK STATUS = ) show ( ) cvs show + ( ) show ( ) cvs show newline + (USER DISK % = ) show ( ) cvs show newline +} if + +(PRODUCT = ) show show newline +(REVISION = ) show ( ) cvs show newline +(VERSION = ) show version show newline + +newline +(CHANNEL 25 = ) show ( ) cvs show +( ) show ( ) cvs show newline +(CHANNEL 9 = ) show ( ) cvs show +( ) show ( ) cvs show newline + +newline +(LEFT MARGIN = ) show ( ) cvs show newline +(TOP MARGIN = ) show ( ) cvs show newline + +version cvr 25.0 gt % PS version >= 25.0 ? +{ + newline + currentpacking % bool + (CURRENT PACKING = ) show + ( ) cvs show newline + + newline + currentcacheparams % mark lower upper + (CURRENT CACHE PARAMS) show newline + counttomark + { ( ) cvs show newline } + repeat + pop % remove mark +} if + +newline +(DEFAULTMATRIX = ) show +matrix defaultmatrix % [ ? ? ? ? ? ? ] +dup 0 get ( ) cvs show ( ) show +dup 1 get ( ) cvs show ( ) show +dup 2 get ( ) cvs show ( ) show +dup 3 get ( ) cvs show ( ) show +dup 4 get ( ) cvs show ( ) show +dup 5 get ( ) cvs show ( ) show +newline +pop + +newline +(CACHE STATUS) show newline +cachestatus % bsize bmax msize mmax csize cmax blimit +(blimit = ) show ( ) cvs show newline +(cmax = ) show ( ) cvs show newline +(csize = ) show ( ) cvs show newline +(mmax = ) show ( ) cvs show newline +(msize = ) show ( ) cvs show newline +(bmax = ) show ( ) cvs show newline +(bsize = ) show ( ) cvs show newline + +newline +(VM STATUS) show newline +vmstatus % savelevel vmused vmmax +(vm max = ) show ( ) cvs show newline +(vm used = ) show ( ) cvs show newline +(save level = ) show ( ) cvs show newline + +newline +(JOB TIME (secs) = ) show +usertime oldusertime sub 1000 div ( ) cvs show newline + +showpage diff --git a/dviware/psprint/unix/lino_fonts.ps b/dviware/psprint/unix/lino_fonts.ps new file mode 100644 index 0000000000..e0c18a2fcc --- /dev/null +++ b/dviware/psprint/unix/lino_fonts.ps @@ -0,0 +1,68 @@ +% This file converts TFM font names into the actual Linotronic font names: + + % These fonts are resident in all PostScript printers: +/ps-courier-b /Courier-Bold def +/ps-courier-bo /Courier-BoldOblique def +/ps-courier-o /Courier-Oblique def +/ps-courier /Courier def +/ps-helv-b /Helvetica-Bold def +/ps-helv-bo /Helvetica-BoldOblique def +/ps-helv-o /Helvetica-Oblique def +/ps-helv /Helvetica def +/ps-symbol /Symbol def +/ps-times-b /Times-Bold def +/ps-times-bi /Times-BoldItalic def +/ps-times-i /Times-Italic def +/ps-times-r /Times-Roman def + + % This font will be constructed from Times-Roman: +/ps-times-s /Times-Slanted def + + % These fonts MIGHT be available in Linotronic: +/ps-avantg-b /AvantGarde-Book def +/ps-avantg-bo /AvantGarde-BookOblique def +/ps-avantg-d /AvantGarde-Demi def +/ps-avantg-do /AvantGarde-DemiOblique def +/ps-bookman-d /Bookman-Demi def +/ps-bookman-di /Bookman-DemiItalic def +/ps-bookman-l /Bookman-Light def +/ps-bookman-li /Bookman-LightItalic def +/ps-helv-n /Helvetica-Narrow def +/ps-helv-nb /Helvetica-Narrow-Bold def +/ps-helv-nbo /Helvetica-Narrow-BoldOblique def +/ps-helv-no /Helvetica-Narrow-Oblique def +/ps-ncs-b /NewCenturySchlbk-Bold def +/ps-ncs-bo /NewCenturySchlbk-BoldItalic def +/ps-ncs-i /NewCenturySchlbk-Italic def +/ps-ncs-r /NewCenturySchlbk-Roman def +/ps-pal-b /Palatino-Bold def +/ps-pal-bi /Palatino-BoldItalic def +/ps-pal-i /Palatino-Italic def +/ps-pal-r /Palatino-Roman def +/ps-zapfch-mi /ZapfChancery-MediumItalic def +/ps-zapfdb /ZapfDingbats def + + % These fonts don't have TFM files for them as yet: +% /??? /Garamond-Bold def +% /??? /Garamond-BoldItalic def +% /??? /Garamond-Light def +% /??? /Garamond-LightItalic def +% /??? /Goudy-Bold def +% /??? /Goudy-BoldItalic def +% /??? /Goudy-Italic def +% /??? /Goudy def +% /??? /Helvetica-Light def +% /??? /Helvetica-LightOblique def +% /??? /NewBaskerville-Bold def +% /??? /NewBaskerville-BoldItalic def +% /??? /NewBaskerville-Italic def +% /??? /NewBaskerville-Roman def +% /??? /Optima-Bold def +% /??? /Optima-BoldOblique def +% /??? /Optima-Oblique def +% /??? /Optima def +% /??? /Sonata def +% /??? /Souvenir-Demi def +% /??? /Souvenir-DemiItalic def +% /??? /Souvenir-Light def +% /??? /Souvenir-LightItalic def diff --git a/dviware/psprint/unix/lino_header.ps b/dviware/psprint/unix/lino_header.ps new file mode 100644 index 0000000000..44aaeef320 --- /dev/null +++ b/dviware/psprint/unix/lino_header.ps @@ -0,0 +1,273 @@ +% This file is sent at the start of each Linotronic job. +% It defines @bannerpage, @footerpage and a PostScript error handler. +% It also defines page sizes and orientations, margin, and cutmark procedure. + +statusdict begin /waittimeout 300 def end % wait 5 minutes + +/@bannerpage % called below +{ initgraphics + statusdict begin + 842 72 0 1 setpageparams % width height margin orientation + end + 25 0 translate % move origin to the right + /vpos 55 def % initial vertical pos + 0 vpos moveto % start near top left corner + /newline + { /vpos vpos 15 sub def % decrease vertical pos by 15pt + 0 vpos moveto % move to start of new line + } def + /newline2 + { /vpos vpos 10 sub def % decrease vertical pos by 10pt + 0 vpos moveto % move to start of new line + } def + /Courier findfont % Courier typewriter font + 9 scalefont setfont % at 9pt + (****************************************************************************\ +**********************************************************) show newline2 + /Courier findfont % Courier typewriter font + 15 scalefont setfont % at 15pt + @USER show newline % user name and file spec + /Courier findfont % Courier typewriter font + 9 scalefont setfont % at 9pt + @DATE show newline2 + @NOTE show newline2 + (----------------------------------------------------------------------------\ +----------------------------------------------------------) show + /#copies 1 def % print only 1 copy of banner page + systemdict /showpage get exec +} def + +/@footerpage % called at end of job or after error +{ initgraphics + statusdict begin + 842 72 0 1 setpageparams % width height margin orientation + end + 25 0 translate % move origin to the right + /vpos 55 def % initial vertical pos + 0 vpos moveto % start near top left corner + /newline + { /vpos vpos 15 sub def % decrease vertical pos by 15pt + 0 vpos moveto % move to start of new line + } def + /newline2 + { /vpos vpos 10 sub def % decrease vertical pos by 10pt + 0 vpos moveto % move to start of new line + } def + /Courier findfont % Courier typewriter font + 9 scalefont setfont % at 9pt + (----------------------------------------------------------------------------\ +----------------------------------------------------------) show newline2 + /Courier findfont % Courier typewriter font + 15 scalefont setfont % at 15pt + @USER show newline % user name and file spec + /Courier findfont % Courier typewriter font + 9 scalefont setfont % at 9pt + @DATE show newline2 + (PAGE COUNT: ) show + statusdict begin + pagecount % current pagecount + end + @oldpagecount % pagecount saved in banner.ps + sub ( ) cvs + show newline2 % show pages printed + (****************************************************************************\ +**********************************************************) show + /#copies 1 def % print only 1 copy of footer page + systemdict /showpage get exec +} def + +% Redefine the error handler in errordict to show a suitable error message. + +/@errpage 64 dict def +@errpage begin +/prnt +{ dup type/stringtype ne{=string cvs}if dup length 6 mul/tx exch def/ty 10 def + currentpoint/toy exch def/tox exch def 1 setgray newpath + tox toy 2 sub moveto 0 ty rlineto tx 0 rlineto 0 ty neg rlineto + closepath fill tox toy moveto 0 setgray show +} bind def +/nl {currentpoint exch pop lmargin exch moveto 0 -11 rmoveto} def +/== {/cp 0 def typeprint nl} def +/typeprint +{ dup type dup currentdict exch known + {exec}{unknowntype}ifelse +} readonly def +/lmargin 72 def +/rmargin 72 def +/tprint +{ dup length cp add rmargin gt{nl/cp 0 def}if + dup length cp add/cp exch def prnt +} readonly def +/cvsprint {=string cvs tprint( )tprint} readonly def +/unknowntype {exch pop cvlit(??)tprint cvsprint} readonly def +/integertype {cvsprint} readonly def +/realtype {cvsprint} readonly def +/booleantype {cvsprint} readonly def +/operatortype {(//)tprint cvsprint} readonly def +/marktype {pop(-mark- )tprint} readonly def +/dicttype {pop(-dictionary- )tprint} readonly def +/nulltype {pop(-null- )tprint} readonly def +/filetype {pop(-filestream- )tprint} readonly def +/savetype {pop(-savelevel- )tprint} readonly def +/fonttype {pop(-fontid- )tprint} readonly def +/nametype {dup xcheck not{(/)tprint}if cvsprint} readonly def +/stringtype +{ dup rcheck{(\()tprint tprint(\))tprint}{pop(-string- )tprint}ifelse +} readonly def +/arraytype +{ dup rcheck{dup xcheck + {({)tprint{typeprint}forall(})tprint} + {([)tprint{typeprint}forall(])tprint}ifelse}{pop(-array- )tprint}ifelse +} readonly def +/packedarraytype +{ dup rcheck{dup xcheck + {({)tprint{typeprint}forall(})tprint} + {([)tprint{typeprint}forall(])tprint}ifelse}{pop(-packedarray- )tprint}ifelse +} readonly def +/courier /Courier findfont 10 scalefont def +/@oldhandleerror errordict /handleerror get def % save current error handler +end +% of @errpage + +errordict /handleerror % redefine error handler +{ systemdict begin $error begin @errpage begin + newerror + { /newerror false store + vmstatus pop pop 0 ne { grestoreall } if + initgraphics + newpath clippath pathbbox % push LLx LLy URx URy + lmargin exch 360 sub moveto % subtract 5" from URy + pop pop pop % remove URx LLy LLx + courier setfont + (POSTSCRIPT ERROR: ) prnt errorname prnt nl + (OFFENDING COMMAND: ) prnt /command load prnt nl + $error /ostack known + { (OPERAND STACK:) prnt nl + $error /ostack get aload length {==} repeat + } if + /#copies 1 store % print only one error page + systemdict /showpage get exec + userdict begin @footerpage end % then print footer page + /newerror true store + /@oldhandleerror load end end end exec } + { end end end } + ifelse +} dup 0 systemdict put dup 4 @errpage put bind readonly put + +@bannerpage % print the banner page + +/@oldpagecount % used in @footerpage + statusdict begin pagecount end +def + +% margin is offset (in pts) from paper edge. +% psprint must make sure that one of the following page setups is called. +% The built-in page setups are available in version 42.5 but not 38.0. + +/A3Lsetup +{ /margin 0 def % margin + width must be <= 842 = 11.7in + statusdict begin + margin setpagemargin + end + a3 % built-in procedure in userdict +} def + +/A4Psetup +{ /margin 0 def % margin + width must be <= 842 = 11.7in + statusdict begin + margin setpagemargin + end + A4 % built-in procedure in userdict +} def + +/A4Lsetup +{ /margin 25 def + statusdict begin + margin setpagemargin + end + a4 % built-in procedure in userdict +} def + +/A5Psetup +{ /margin 25 def + statusdict begin + margin setpagemargin + end + A5 % built-in procedure in userdict +} def + +/A5Lsetup +{ /margin 25 def + statusdict begin + margin setpagemargin + end + a5 % built-in procedure in userdict +} def + +/B5Psetup +{ /margin 25 def + statusdict begin + margin setpagemargin + end + B5 % built-in procedure in userdict +} def + +/B5Lsetup +{ /margin 25 def + statusdict begin + margin setpagemargin + end + b5 % built-in procedure in userdict +} def + +/cornercuts +{ % draw short lines at corners of page image area + initgraphics + newpath clippath pathbbox % push LLx LLy URx URy + /URy exch def + /URx exch def + % don't use LLx LLy because they don't allow for margin setting + pop pop + newpath % remove clipping path + % line length = 10pt + URx URy moveto -10 0 rlineto + URx URy moveto 0 -10 rlineto + 0 0 moveto 10 0 rlineto + 0 0 moveto 0 10 rlineto + 0 URy moveto 10 0 rlineto + 0 URy moveto 0 -10 rlineto + URx 0 moveto -10 0 rlineto + URx 0 moveto 0 10 rlineto + 0.2 setlinewidth + stroke +} def + +% psprint will override this default if user asks for -nocut: + +/@cutmarks { cornercuts } def + +% Redefine userdict showpage to first call @cutmarks, then showpage +% from systemdict, then a thin blank page to separate job pages: + +/showpage +{ @cutmarks % draw any cut marks + systemdict /showpage get exec % show current page + statusdict begin pageparams end % get width height margin orientation + /oldorientation exch def + /oldmargin exch def + /oldheight exch def + /oldwidth exch def % save current page setups + /old#copies #copies def % save current #copies + /#copies 1 def % only print 1 gap page + statusdict begin + 842 18 0 1 setpageparams % 18pt = .25" gap + end + systemdict /showpage get exec % show gap page + /@oldpagecount @oldpagecount 1 add def % increment @oldpagecount + oldwidth + oldheight + oldmargin + oldorientation + statusdict begin setpageparams end % restore saved page setup + /#copies old#copies def % restore saved #copies +} def diff --git a/dviware/psprint/unix/lino_pages.ps b/dviware/psprint/unix/lino_pages.ps new file mode 100644 index 0000000000..3813b51408 --- /dev/null +++ b/dviware/psprint/unix/lino_pages.ps @@ -0,0 +1,16 @@ +% Tests Lino page setups defined in lino_header.ps. + +/Helvetica findfont 30 scalefont setfont + +/borders +{ % draw border lines around page image area + newpath clippath 0.1 setlinewidth stroke +} def + +A3Lsetup borders 216 216 moveto (A3L) show showpage +A4Psetup borders 216 216 moveto (A4P) show showpage +A4Lsetup borders 216 216 moveto (A4L) show showpage +A5Psetup borders 216 216 moveto (A5P) show showpage +A5Lsetup borders 216 216 moveto (A5L) show showpage +B5Psetup borders 216 216 moveto (B5P) show showpage +B5Lsetup borders 216 216 moveto (B5L) show showpage diff --git a/dviware/psprint/unix/lino_trailer.ps b/dviware/psprint/unix/lino_trailer.ps new file mode 100644 index 0000000000..26534f7984 --- /dev/null +++ b/dviware/psprint/unix/lino_trailer.ps @@ -0,0 +1 @@ +@footerpage % print footer page at end of Linotronic job diff --git a/dviware/psprint/unix/lw_fonts.ps b/dviware/psprint/unix/lw_fonts.ps new file mode 100644 index 0000000000..56589c8cd0 --- /dev/null +++ b/dviware/psprint/unix/lw_fonts.ps @@ -0,0 +1,43 @@ +% This file converts TFM font names into the actual LaserWriter font names: + + % These fonts are resident in all PostScript printers: +/ps-courier-b /Courier-Bold def +/ps-courier-bo /Courier-BoldOblique def +/ps-courier-o /Courier-Oblique def +/ps-courier /Courier def +/ps-helv-b /Helvetica-Bold def +/ps-helv-bo /Helvetica-BoldOblique def +/ps-helv-o /Helvetica-Oblique def +/ps-helv /Helvetica def +/ps-symbol /Symbol def +/ps-times-b /Times-Bold def +/ps-times-bi /Times-BoldItalic def +/ps-times-i /Times-Italic def +/ps-times-r /Times-Roman def + + % This font will be constructed from Times-Roman: +/ps-times-s /Times-Slanted def + + % These fonts are resident in a LaserWriter Plus: +/ps-avantg-b /AvantGarde-Book def +/ps-avantg-bo /AvantGarde-BookOblique def +/ps-avantg-d /AvantGarde-Demi def +/ps-avantg-do /AvantGarde-DemiOblique def +/ps-bookman-d /Bookman-Demi def +/ps-bookman-di /Bookman-DemiItalic def +/ps-bookman-l /Bookman-Light def +/ps-bookman-li /Bookman-LightItalic def +/ps-helv-n /Helvetica-Narrow def +/ps-helv-nb /Helvetica-Narrow-Bold def +/ps-helv-nbo /Helvetica-Narrow-BoldOblique def +/ps-helv-no /Helvetica-Narrow-Oblique def +/ps-ncs-b /NewCenturySchlbk-Bold def +/ps-ncs-bo /NewCenturySchlbk-BoldItalic def +/ps-ncs-i /NewCenturySchlbk-Italic def +/ps-ncs-r /NewCenturySchlbk-Roman def +/ps-pal-b /Palatino-Bold def +/ps-pal-bi /Palatino-BoldItalic def +/ps-pal-i /Palatino-Italic def +/ps-pal-r /Palatino-Roman def +/ps-zapfch-mi /ZapfChancery-MediumItalic def +/ps-zapfdb /ZapfDingbats def diff --git a/dviware/psprint/unix/lw_header.ps b/dviware/psprint/unix/lw_header.ps new file mode 100644 index 0000000000..bd6bbac0d1 --- /dev/null +++ b/dviware/psprint/unix/lw_header.ps @@ -0,0 +1,136 @@ +% psprint uses this file to build an appropriate header file for each job. +% It defines @bannerpage and redefines the PostScript error handler. + +statusdict begin /waittimeout 300 def end % wait 5 minutes + +/@oldpagecount statusdict begin pagecount end def + +/@bannerpage % called at end of job or upon error +{ initgraphics + 36 0 translate % move origin to the right + /vpos 800 def % initial vertical pos + 0 vpos moveto % start near top left corner + /newline + { /vpos vpos 20 sub def % decrease vertical pos by 20pt + 0 vpos moveto % move to start of new line + } def + /Courier findfont % Courier typewriter font + 12 scalefont setfont % at 12pt + (*********************** psprint 3.0 **********************) show newline + @USER show newline + @NODE show newline + @FILE show newline + @FORMAT show newline + @QUEUED show newline + (PAGES : ) show + statusdict begin + pagecount % current pagecount + end + @oldpagecount % pagecount saved at start of job + sub ( ) cvs + show newline % show pages printed + @NOTE show newline +% @status % uncomment to get status info + /#copies 1 def % only 1 copy of banner page + systemdict /showpage get exec +} def + +% Uncomment the following (and above call) to get status info on banner page: +% +% /@oldusertime usertime def % save current usertime +% /@status % show cache and VM status values +% { newline +% (CACHE STATUS) show newline +% cachestatus % bsize bmax msize mmax csize cmax blimit +% (blimit = ) show ( ) cvs show newline +% (cmax = ) show ( ) cvs show newline +% (csize = ) show ( ) cvs show newline +% (mmax = ) show ( ) cvs show newline +% (msize = ) show ( ) cvs show newline +% (bmax = ) show ( ) cvs show newline +% (bsize = ) show ( ) cvs show newline +% newline +% (VM STATUS) show newline +% vmstatus % savelevel vmused vmmax +% (vm max = ) show ( ) cvs show newline +% (vm used = ) show ( ) cvs show newline +% (save level = ) show ( ) cvs show newline +% newline +% (JOB TIME (secs) = ) show usertime @oldusertime sub 1000 div +% ( ) cvs show +% } def + +% Redefine the error handler in errordict to show a suitable error message. + +/@errpage 64 dict def +@errpage begin +/prnt +{ dup type/stringtype ne{=string cvs}if dup length 6 mul/tx exch def/ty 10 def + currentpoint/toy exch def/tox exch def 1 setgray newpath + tox toy 2 sub moveto 0 ty rlineto tx 0 rlineto 0 ty neg rlineto + closepath fill tox toy moveto 0 setgray show +} bind def +/nl {currentpoint exch pop lmargin exch moveto 0 -11 rmoveto} def +/== {/cp 0 def typeprint nl} def +/typeprint +{ dup type dup currentdict exch known + {exec}{unknowntype}ifelse +} readonly def +/lmargin 72 def +/rmargin 72 def +/tprint +{ dup length cp add rmargin gt{nl/cp 0 def}if + dup length cp add/cp exch def prnt +} readonly def +/cvsprint {=string cvs tprint( )tprint} readonly def +/unknowntype {exch pop cvlit(??)tprint cvsprint} readonly def +/integertype {cvsprint} readonly def +/realtype {cvsprint} readonly def +/booleantype {cvsprint} readonly def +/operatortype {(//)tprint cvsprint} readonly def +/marktype {pop(-mark- )tprint} readonly def +/dicttype {pop(-dictionary- )tprint} readonly def +/nulltype {pop(-null- )tprint} readonly def +/filetype {pop(-filestream- )tprint} readonly def +/savetype {pop(-savelevel- )tprint} readonly def +/fonttype {pop(-fontid- )tprint} readonly def +/nametype {dup xcheck not{(/)tprint}if cvsprint} readonly def +/stringtype +{ dup rcheck{(\()tprint tprint(\))tprint}{pop(-string- )tprint}ifelse +} readonly def +/arraytype +{ dup rcheck{dup xcheck + {({)tprint{typeprint}forall(})tprint} + {([)tprint{typeprint}forall(])tprint}ifelse}{pop(-array- )tprint}ifelse +} readonly def +/packedarraytype +{ dup rcheck{dup xcheck + {({)tprint{typeprint}forall(})tprint} + {([)tprint{typeprint}forall(])tprint}ifelse}{pop(-packedarray- )tprint}ifelse +} readonly def +/courier /Courier findfont 10 scalefont def +/@oldhandleerror errordict /handleerror get def % save current error handler +end +% of @errpage + +errordict /handleerror % redefine error handler +{ systemdict begin $error begin @errpage begin + newerror + { /newerror false store + vmstatus pop pop 0 ne { grestoreall } if + initgraphics courier setfont + lmargin 792 moveto + (POSTSCRIPT ERROR: ) prnt errorname prnt nl + (OFFENDING COMMAND: ) prnt /command load prnt nl + $error /ostack known + { (OPERAND STACK:) prnt nl + $error /ostack get aload length {==} repeat + } if + /#copies 1 store % print only one error page + systemdict /showpage get exec + userdict begin @bannerpage end % print banner page + /newerror true store + /@oldhandleerror load end end end exec } + { end end end } + ifelse +} dup 0 systemdict put dup 4 @errpage put bind readonly put diff --git a/dviware/psprint/unix/lw_trailer.ps b/dviware/psprint/unix/lw_trailer.ps new file mode 100644 index 0000000000..6ab5dcd5e2 --- /dev/null +++ b/dviware/psprint/unix/lw_trailer.ps @@ -0,0 +1 @@ +@bannerpage diff --git a/dviware/psprint/unix/nasty.tex b/dviware/psprint/unix/nasty.tex new file mode 100644 index 0000000000..784e60f4aa --- /dev/null +++ b/dviware/psprint/unix/nasty.tex @@ -0,0 +1,349 @@ +% TeX source file for testing PSDVI and PSPRINT with a very nasty DVI file +% (using the same philosophy as Donald Knuth's torture test for TeX). +% First 11 pages are nasty but should all be printable. +% Remaining pages contain one or more deliberate errors!!! + +\nopagenumbers +\topskip 0pt +\parindent 0pt +\parskip 0pt + +% DVI page 1 +\message{Empty page.} +\null +\vfil\eject + +% DVI page 2 +\message{Page with special file empty.ps.} +\null +\special{empty.ps} +\vfil\eject + +% DVI page 3 +\message{Page with special file box.ps.} +\null +\vskip 2in +\special{box.ps} +\vskip 2in +\special{box.ps 1.5 .5 scale} % test optional PostScript text +\vskip 2in +\special{box.ps } % should just add blank line +\vfil\eject + +% DVI page 4 +\message{Page with special file box.ps in horizontal mode.} +\null +\vskip 1in +\line{a\hfil \special{box.ps} \hfil b} +\vfil\eject + +% DVI page 5 +\message{Page with 1 black pixel at (0,0).} +\hrule height 1sp width 1sp depth 0sp +\vfil\eject + +% DVI page 6 +\message{A4 paper filled with 1mm grid.} +{% change page size and location temporarily +\hoffset=-1in +\voffset=-1in +\hsize=209.9mm +\vsize=296.9mm +\newcount\temp +\hbox to \hsize +{\temp=209 +\loop\ifnum\temp>0 + \vrule height \vsize width 1sp + \hfil + \advance\temp by -1 +\repeat +\vrule height \vsize width 1sp +} +\vskip -\vsize +\temp=296 +\loop\ifnum\temp>0 + \hrule height 1sp width \hsize + \vfil + \advance\temp by -1 +\repeat +\hrule height 1sp width \hsize +\eject +}% reset page size and location + +% DVI page 7 +\message{Multiple TeX page counters.} +\footline={\hss\tenrm\folio\hss} % turn on page numbers +\pageno=0 +\count1=1 \count2=2 \count3=3 \count4=4 \count9=9 +\noindent +This is \TeX\ page [0.1.2.3.4.....9]. +\vfil\eject +\count1=0 \count2=0 \count3=0 \count4=0 \count9=0 % reset TeX counters + +% DVI page 8 +\message{Negative TeX page.} +\pageno=-99 +This is \TeX\ page [-99]. +\vfil\eject +\pageno=0 % restart TeX page numbers +\nopagenumbers % turn off page numbers again + +% DVI page 9 +\message{Standard paragraphs in Computer Modern and PostScript fonts.} + +\font\sf=cmss10 +\font\timesr=ps-times-r at 10pt +\font\helv=ps-helv at 10pt + +\rm +Our task is to create a paragraph illustrating what a typical piece of text +looks like in a particular \TeX\ font. It should be stressed that not all +\TeX\ fonts can be used for typesetting text. We need to show most of the +characters in this font---for instance, something like ``the quick brown fox +jumps over a lazy dog'' would use all the lower-case letters. Hmmm \dots\ +how about ``THE QUICK BROWN FOX JUMPS OVER 9876543210 LAZY DOGS'' to make +sure we show all the upper-case letters and digits? Such a paragraph would +hardly be typical! Then there's ligatures (try and fit in words like +fluffy, waffle, firefly, difficult) and examples of kerning (boxer, cooked, +vowel). Not to mention the various accents and other special letters: +prot\'eg\'e, r\^ole, na\"\i ve, \AE sop's \OE vres en fran\c cais. +But how do we put all this stuff into a paragraph that makes sense!? + +\bigskip +\timesr +Our task is to create a paragraph illustrating what a typical piece of text +looks like in a particular \TeX\ font. It should be stressed that not all +\TeX\ fonts can be used for typesetting text. We need to show most of the +characters in this font---for instance, something like ``the quick brown fox +jumps over a lazy dog'' would use all the lower-case letters. Hmmm \dots\ +how about ``THE QUICK BROWN FOX JUMPS OVER 9876543210 LAZY DOGS'' to make +sure we show all the upper-case letters and digits? Such a paragraph would +hardly be typical! Then there's ligatures (try and fit in words like +fluffy, waffle, firefly, difficult) and examples of kerning (boxer, cooked, +vowel). Not to mention the various accents and other special letters: +prot\'eg\'e, r\^ole, na\"\i ve, \AE sop's \OE vres en fran\c cais. +But how do we put all this stuff into a paragraph that makes sense!? + +\bigskip +\sf +Our task is to create a paragraph illustrating what a typical piece of text +looks like in a particular \TeX\ font. It should be stressed that not all +\TeX\ fonts can be used for typesetting text. We need to show most of the +characters in this font---for instance, something like ``the quick brown fox +jumps over a lazy dog'' would use all the lower-case letters. Hmmm \dots\ +how about ``THE QUICK BROWN FOX JUMPS OVER 9876543210 LAZY DOGS'' to make +sure we show all the upper-case letters and digits? Such a paragraph would +hardly be typical! Then there's ligatures (try and fit in words like +fluffy, waffle, firefly, difficult) and examples of kerning (boxer, cooked, +vowel). Not to mention the various accents and other special letters: +prot\'eg\'e, r\^ole, na\"\i ve, \AE sop's \OE vres en fran\c cais. +But how do we put all this stuff into a paragraph that makes sense!? + +\bigskip +\helv +Our task is to create a paragraph illustrating what a typical piece of text +looks like in a particular \TeX\ font. It should be stressed that not all +\TeX\ fonts can be used for typesetting text. We need to show most of the +characters in this font---for instance, something like ``the quick brown fox +jumps over a lazy dog'' would use all the lower-case letters. Hmmm \dots\ +how about ``THE QUICK BROWN FOX JUMPS OVER 9876543210 LAZY DOGS'' to make +sure we show all the upper-case letters and digits? Such a paragraph would +hardly be typical! Then there's ligatures (try and fit in words like +fluffy, waffle, firefly, difficult) and examples of kerning (boxer, cooked, +vowel). Not to mention the various accents and other special letters: +prot\'eg\'e, r\^ole, na\"\i ve, \AE sop's \OE vres en fran\c cais. +But how do we put all this stuff into a paragraph that makes sense!? + +\bigskip +\rm The cat sat on the mat. \timesr The cat sat on the mat. +\sf The cat sat on the mat. \helv The cat sat on the mat. + +\rm +\vfil\eject + +% DVI page 10 +\message{Verbatim tt strings.} +\input ../dv/verbatim +\begintt +-------------------------------------------------------------------------------- +- - +-------------------------------------------------------------------------------- +\endtt +\vfil\eject + +% DVI page 11 +\message{Page with all-white character.} +\font\cmtex=cmtex10 +\leftline{\cmtex a\char32 b} +\vfil\eject + +% REMAINING PAGES HAVE DELIBERATE ERRORS!!! + +% DVI page 12 +\pageno=100 +\message{Page with non-existent fonts.} +\font\FA=cmr5 scaled 500 +\font\FB=cmr5 scaled 3000 +\font\FC=cmr10 scaled 200 +\font\FD=cmr10 scaled 5000 +\font\FE=cmsl10 scaled 1 +\font\FF=cmsl10 scaled 10000 +\leftline{\FA CMR5 at mag 500 does not exist.} +\leftline{\FB CMR5 at mag 3000 does not exist.} +\leftline{\FC CMR10 at mag 200 does not exist.} +\leftline{\FD CMR10 at mag 5000 does not exist.} +\leftline{\FE CMSL10 at mag 1 does not exist.} +\leftline{\FF CMSL10 at mag 10000 does not exist.} +\vfil\eject + +% DVI page 13 +\message{Page beyond top and left edges of A4 paper.} +{% change page size and location +\voffset -3in +\hoffset -9in +\leftline{Page off paper.} +\vfil\eject +}% restore page size and location + +% DVI page 14 +\message{Page beyond bottom and right edges of A4 paper.} +{% change page size and location +\voffset 3in +\hoffset 9in +\null\vfil +\rightline{Page off paper.} +\eject +}% restore page size and location + +% DVI page 15 +\message{Page beyond all edges of A4 paper.} +{% change page size and location +\voffset -3in +\hoffset -3in +\vsize 15in +\hsize 15in +\line{Page off paper.\hfil Page off paper.} +\vfil +\line{Page off paper.\hfil Page off paper.} +\eject +}% restore page size and location + +% DVI page 16 +\message{Page with illegal special files.} +\null +\special{} +\special{This is not a file name.} +\special{% +12345678901234567890123456789012345678901234567890% +1234567890123456789012345678901} +% one character too many (see string in globals.h) +\vfil\eject + +% DVI page 17 +\message{Page with bad special file.} +\null +\special{bad.ps} % bad.ps has deliberate PostScript error +\vfil\eject + +% DVI page 18 +% PostScript printers can get 1 pixel rounding errors which show up in TeX +% math extension symbols made up of rules and cmex characters. +% tex.ps tries to minimize such problems by using setmatrix to +% define a device-specific coordinate system, and making slight adjustments +% to the height, width and positioning of rules. + +\message{Page with possible rounding problems.} + +\hrule width 2in height 1mm +\bigskip + +\def\prob{$$\shift +\sqrt{1+\sqrt{1+\sqrt{1+\sqrt{1+\sqrt{1+\sqrt{1+\sqrt{1+x}}}}}}} +\quad +\{\underbrace{\overbrace{\mathstrut a,\ldots,a} + ^{k\;{\tenit a's}}, +\overbrace{\mathstrut b,\ldots,b} + ^{l\;{\tenit b's}}}_{k+l\rm\;elements}\}. +\quad +\left\{\vbox to 27pt{}\left\{\vbox to 24pt{}\left\{ +\vbox to 21pt{}\Biggl\{\biggl\{\Bigl\{ +\bigl\{{\bf t}\bigr\}\Bigr\}\biggr\} +\Biggr\}\right\}\right\}\right\} +$$} + +\def\shift{} +\prob +\bigskip + +\def\shift{\hskip 10pt} +\prob +\bigskip\bigskip + +\def\shift{\hskip 20pt} +\prob +\bigskip\bigskip\bigskip + +\def\shift{\hskip 30pt} +\prob + +\vfil\eject + +% DVI page 19 +\message{Page will exceed VM in LaserWriter 2.0.} +\font\huge=cminch +\font\bigrm=cmr10 scaled\magstep5 +\font\bigbf=cmbx10 scaled\magstep5 +\font\bigit=cmti10 scaled\magstep5 +\font\bigsl=cmsl10 scaled\magstep5 +\font\bigtt=cmtt10 scaled\magstep5 +\hrule +\vfil +\centerline{\huge ABCDE} +\vfil +\centerline{\bigrm This is the largest ROMAN} +\centerline{\bigbf This is the largest BOLD} +\centerline{\bigit This is the largest ITALIC} +\centerline{\bigsl This is the largest SLANTED} +\centerline{\bigtt This is the largest TYPEWRITER} +\vfil +\rm +abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789\hfil\break +Some ligatures: fluffy, difficult, deftly. Some kerning: book, box, AVATAR. +Here is a paragraph using the PLAIN output format. +Let us hope we see some improvement. If not, think again. +The cat sat on the mat. +\bigskip +\bf +abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789\hfil\break +Some ligatures: fluffy, difficult, deftly. Some kerning: book, box, AVATAR. +Here is a paragraph using the PLAIN output format. +Let us hope we see some improvement. If not, think again. +The cat sat on the mat. +\bigskip +\it +abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789\hfil\break +Some ligatures: fluffy, difficult, deftly. Some kerning: book, box, AVATAR. +Here is a paragraph using the PLAIN output format. +Let us hope we see some improvement. If not, think again. +The cat sat on the mat. +\bigskip +\sl +abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789\hfil\break +Some ligatures: fluffy, difficult, deftly. Some kerning: book, box, AVATAR. +Here is a paragraph using the PLAIN output format. +Let us hope we see some improvement. If not, think again. +The cat sat on the mat. +\bigskip +\tt +{\obeylines +abcdefghijklmnopqrstuvwxyz +ABCDEFGHIJKLMNOPQRSTUVWXYZ +0123456789 + +} +\rm +\vfil +\hrule +\eject + +\bye diff --git a/dviware/psprint/unix/options.h b/dviware/psprint/unix/options.h new file mode 100644 index 0000000000..8750573ca3 --- /dev/null +++ b/dviware/psprint/unix/options.h @@ -0,0 +1,44 @@ +(* Options *) + +TYPE + validunits = (ic,cm,mm,pc,pt,bp,px); + +VAR + resolution, (* pixels per inch *) + mag, (* override DVI mag; 0 = use DVI mag *) + hoffset, (* horizontal margin shift in pixels *) + voffset, (* vertical margin shift in pixels *) + paperwd, (* paper width in pixels *) + paperht (* paper height in pixels *) + : INTEGER; + tfmdir, (* location of PostScript TFMs *) + psprefix, (* prefix for all PostScript fonts *) + fontdir, (* location of PK files *) + dummyfont, (* dummy PK file *) + DVIname (* DVI file name *) + : string; + + (* The above options are also available with DVItoVDU. + The following options are only available with PSDVI. + *) + + units (* defines how dimensions will be displayed *) + : validunits; + stats, (* show some statistics? *) + reverse, (* output pages in reverse order? *) + conserveVM, (* conserve virtual memory? *) + subrange (* user has selected a subrange of pages? *) + : BOOLEAN; + firstDVIpage, (* first DVI page selected (0 if TeX page) *) + finalDVIpage, (* final DVI page selected (0 if TeX page) *) + increment (* further restricts page selection *) + : INTEGER; + firstTeXpage, (* first TeX page selected *) + finalTeXpage, (* final TeX page selected *) + header, (* header file prefixed to output *) + PSname (* explicit file name for PostScript output *) + : string; + +PROCEDURE InitOptions; EXTERNAL; +FUNCTION Cap (ch : CHAR) : CHAR; EXTERNAL; +FUNCTION Len (str : string) : INTEGER; EXTERNAL; diff --git a/dviware/psprint/unix/options.p b/dviware/psprint/unix/options.p new file mode 100644 index 0000000000..05a6adb908 --- /dev/null +++ b/dviware/psprint/unix/options.p @@ -0,0 +1,469 @@ +(* This module initializes the DVI file parameter and command line options. + Highly SYSDEP! +*) + +#include 'globals.h'; +#include 'options.h'; + +VAR + option : CHAR; (* current command option *) + value : string; (* current option's value *) + vlength : INTEGER; (* current value's length *) + argnum : INTEGER; (* 0..argc-1; used in argv calls *) + +FUNCTION sscanf (VAR s, format : string; VAR r : real) : integer; +EXTERNAL; + +(******************************************************************************) + +FUNCTION Cap (ch : CHAR) : CHAR; + +(* If ch is in 'a'..'z' then return capitalized letter else return ch. *) + +BEGIN +IF (ch < 'a') OR (ch > 'z') THEN Cap := ch ELSE Cap := CHR(ORD(ch) - 32); +END; (* Cap *) + +(******************************************************************************) + +FUNCTION Len (str : string) : INTEGER; + +(* Return length of given string, assumed to be padded with blanks. *) + +LABEL 888; + +VAR i : INTEGER; + +BEGIN +i := maxstring; +WHILE i > 0 DO BEGIN + IF str[i-1] <> ' ' THEN goto 888; + i := i - 1; +END; +888: +Len := i; +END; (* Len *) + +(******************************************************************************) + +FUNCTION ExplicitExt (fname : string; len : INTEGER) : BOOLEAN; + +(* SYSDEP: Check for an extension of the form ".*" where * is any string + not containing "/". len is length of fname. + If "." found then TRUE is returned, otherwise FALSE. +*) + +LABEL 999; + +BEGIN +WHILE len > 0 DO BEGIN (* search backwards looking for . *) + len := len - 1; + IF fname[len] = '/' THEN BEGIN (* handle file names like ../myfiles/foo *) + ExplicitExt := FALSE; + goto 999; + END + ELSE IF fname[len] = '.' THEN BEGIN + ExplicitExt := TRUE; + goto 999; + END; +END; +ExplicitExt := FALSE; +999: +END; (* ExplicitExt *) + +(******************************************************************************) + +PROCEDURE GetValue; + +(* Get parameter following current option and store in value. *) + +VAR i : integer; + +BEGIN +IF vlength > 2 THEN BEGIN (* allow things like -m1000 *) + FOR i := 0 TO vlength - 1 DO + value[i] := value[i+2]; (* shift value left 2 places *) + vlength := vlength - 2; +END +ELSE BEGIN + (* option should be followed by value *) + value := ' '; + IF argnum < argc THEN argv(argnum,value); + vlength := Len(value); (* 0 if no more args *) + argnum := argnum + 1; + IF vlength <= 0 THEN BEGIN + writeln('Missing value after -',option); + exit(1); + END; +END; +END; (* GetValue *) + +(******************************************************************************) + +PROCEDURE GetCardinal (VAR n : INTEGER); + +(* If current value represents a positive integer then return via n. *) + +VAR result : integer; r : real; fmt : string; + +BEGIN +fmt := '%f'; +result := sscanf(value,fmt,r); +n := trunc(r); +IF (ABS(result) <> 1) OR (n <= 0) THEN BEGIN + writeln('Bad -',option,' value: ',value:vlength); + writeln('Specify a positive integer.'); + exit(1); +END; +END; (* GetCardinal *) + +(******************************************************************************) + +PROCEDURE GetPosDimen (VAR r : REAL; VAR un : validunits); + +(* A valid +ve dimension consists of a positive integer or real number followed + by a two-letter unit: cm, mm, in, pc, pt, bp or px (or in uppercase). + If current value represents a valid +ve dimension, we return number part + in r and validunits part in un. +*) + +VAR i, result : INTEGER; ch1, ch2 : CHAR; fmt : string; + +BEGIN +(* extract un *) +IF vlength > 1 THEN i := vlength-1 ELSE i := 1; +IF (Cap(value[i-1]) = 'I') AND (Cap(value[i]) = 'N') THEN + un := ic +ELSE IF (Cap(value[i-1]) = 'C') AND (Cap(value[i]) = 'M') THEN + un := cm +ELSE IF (Cap(value[i-1]) = 'M') AND (Cap(value[i]) = 'M') THEN + un := mm +ELSE IF (Cap(value[i-1]) = 'P') AND (Cap(value[i]) = 'C') THEN + un := pc +ELSE IF (Cap(value[i-1]) = 'P') AND (Cap(value[i]) = 'T') THEN + un := pt +ELSE IF (Cap(value[i-1]) = 'B') AND (Cap(value[i]) = 'P') THEN + un := bp +ELSE IF (Cap(value[i-1]) = 'P') AND (Cap(value[i]) = 'X') THEN + un := px +ELSE BEGIN + writeln('Bad units in -',option,' value: ',value:vlength); + writeln('Last two letters should be cm, mm, in, pc, pt, bp or px.'); + exit(1); +END; +ch1 := value[i-1]; (* remember letters in units *) +ch2 := value[i]; +value[i] := ' '; (* remove units *) +value[i-1] := ' '; +fmt := '%f'; +result := sscanf(value,fmt,r); +IF (ABS(result) <> 1) OR (r <= 0.0) THEN BEGIN + value[i-1] := ch1; (* restore units *) + value[i] := ch2; + writeln('Bad -',option,' value: ',value:vlength); + writeln('Specify a positive dimension.'); + exit(1); +END; +END; (* GetPosDimen *) + +(******************************************************************************) + +PROCEDURE GetDimen (VAR r : REAL; VAR un : validunits); + +(* A valid dimension consists of an integer or real number followed + by a two-letter unit: cm, mm, in, pc, pt, bp or px (or in uppercase). + If current value represents a valid dimension, we return number part + in r and validunits part in un. +*) + +VAR i, result : INTEGER; ch1, ch2 : CHAR; fmt : string; + +BEGIN +(* extract un *) +IF vlength > 1 THEN i := vlength-1 ELSE i := 1; +IF (Cap(value[i-1]) = 'I') AND (Cap(value[i]) = 'N') THEN + un := ic +ELSE IF (Cap(value[i-1]) = 'C') AND (Cap(value[i]) = 'M') THEN + un := cm +ELSE IF (Cap(value[i-1]) = 'M') AND (Cap(value[i]) = 'M') THEN + un := mm +ELSE IF (Cap(value[i-1]) = 'P') AND (Cap(value[i]) = 'C') THEN + un := pc +ELSE IF (Cap(value[i-1]) = 'P') AND (Cap(value[i]) = 'T') THEN + un := pt +ELSE IF (Cap(value[i-1]) = 'B') AND (Cap(value[i]) = 'P') THEN + un := bp +ELSE IF (Cap(value[i-1]) = 'P') AND (Cap(value[i]) = 'X') THEN + un := px +ELSE BEGIN + writeln('Bad units in -',option,' value: ',value:vlength); + writeln('Last two letters should be cm, mm, in, pc, pt, bp or px.'); + exit(1); +END; +ch1 := value[i-1]; (* remember letters in units *) +ch2 := value[i]; +value[i] := ' '; (* remove units *) +value[i-1] := ' '; +fmt := '%f'; +result := sscanf(value,fmt,r); +IF (ABS(result) <> 1) THEN BEGIN + value[i-1] := ch1; (* restore units *) + value[i] := ch2; + writeln('Bad -',option,' value: ',value:vlength); + writeln('Specify a dimension.'); + exit(1); +END; +END; (* GetDimen *) + +(******************************************************************************) + +PROCEDURE GetUnits; + +(* Make sure current value is valid and set units if so. *) + +VAR ch1, ch2 : CHAR; + +BEGIN +ch1 := Cap(value[0]); +ch2 := Cap(value[1]); +IF (ch1 = 'I') AND (ch2 = 'N') THEN + units := ic +ELSE IF (ch1 = 'C') AND (ch2 = 'M') THEN + units := cm +ELSE IF (ch1 = 'M') AND (ch2 = 'M') THEN + units := mm +ELSE IF (ch1 = 'P') AND (ch2 = 'C') THEN + units := pc +ELSE IF (ch1 = 'P') AND (ch2 = 'T') THEN + units := pt +ELSE IF (ch1 = 'B') AND (ch2 = 'P') THEN + units := bp +ELSE IF (ch1 = 'P') AND (ch2 = 'X') THEN + units := px +ELSE BEGIN + writeln('Bad -',option,' value: ',value:vlength); + writeln('Specify cm, mm, in, pc, pt, bp or px.'); + exit(1); +END; +END; (* GetUnits *) + +(******************************************************************************) + +PROCEDURE GetPages; + +(* Parse -p value. If valid then subrange will become TRUE. + -p can have any value of the form "first:final" where first and/or + final can be a DVI page (positive integer), or TeX page ([i0. ... .i9]), + or empty. If first empty then firstDVIpage = 1; if final empty then + finalDVIpage = maxint. If ":final" is omitted then + finalDVIpage = firstDVIpage. + If first/final is a TeX page specification (i.e., starts with '[') + then first/finalDVIpage is set to 0 and first/finalTeXpage contains the + given string (and parsing is done by the main module). +*) + +LABEL 888; + +VAR i, j, result : INTEGER; r : real; fmt : string; + +BEGIN +subrange := TRUE; +firstTeXpage := ' '; +finalTeXpage := ' '; +i := 0; +(* extract first page *) +WHILE i < vlength DO BEGIN + IF value[i] = ':' THEN goto 888; + firstTeXpage[i] := value[i]; + i := i + 1; +END; +888: +IF value[0] = ':' THEN (* first page not given *) + firstDVIpage := 1 +ELSE IF firstTeXpage[0] = '[' THEN (* TeX page given *) + firstDVIpage := 0 +ELSE BEGIN (* DVI page given *) + fmt := '%f'; + result := sscanf(firstTeXpage,fmt,r); + firstDVIpage := trunc(r); + IF (ABS(result) <> 1) OR (firstDVIpage <= 0) THEN BEGIN + writeln('Bad first page in -',option,' value: ',value:vlength); + writeln('Specify a positive integer.'); + exit(1); + END; +END; +IF i = vlength THEN BEGIN (* no colon; n or [t] *) + IF firstTeXpage[0] = '[' THEN BEGIN + finalTeXpage := firstTeXpage; (* [t] = [t]:[t] *) + finalDVIpage := 0; + END + ELSE + finalDVIpage := firstDVIpage; (* n = n:n *) +END +ELSE BEGIN (* value[i] = ':' *) + i := i + 1; + j := 0; + WHILE i < vlength DO BEGIN (* extract final page *) + finalTeXpage[j] := value[i]; + i := i + 1; + j := j + 1; + END; + IF j = 0 THEN (* no page after ':' *) + finalDVIpage := maxint + ELSE IF finalTeXpage[0] = '[' THEN (* TeX page given *) + finalDVIpage := 0 + ELSE BEGIN (* DVI page given *) + fmt := '%f'; + result := sscanf(finalTeXpage,fmt,r); + finalDVIpage := trunc(r); + IF (ABS(result) <> 1) OR (finalDVIpage <= 0) THEN BEGIN + writeln('Bad final page in -',option,' value: ',value:vlength); + writeln('Specify a positive integer.'); + exit(1); + END; + END; +END; +END; (* GetPages *) + +(******************************************************************************) + +FUNCTION DimenPixels (r : REAL; u : validunits) : INTEGER; + +(* Return given dimension in terms of pixels. *) + +BEGIN +CASE u OF + ic : DimenPixels := TRUNC(r * resolution + 0.5); + cm : DimenPixels := TRUNC((r / 2.54) * resolution + 0.5); + mm : DimenPixels := TRUNC((r / 25.4) * resolution + 0.5); + bp : DimenPixels := TRUNC((r / 72.0) * resolution + 0.5); + pt : DimenPixels := TRUNC((r / 72.27) * resolution + 0.5); + pc : DimenPixels := TRUNC((r / 72.27) * 12.0 * resolution + 0.5); + px : DimenPixels := TRUNC(r + 0.5) +END; +END; (* DimenPixels *) + +(******************************************************************************) + +PROCEDURE InitOptions; + +(* Get DVI file and any options from command line. + If an option appears more than once then we return the last value. +*) + +VAR + hoffu, voffu, xu, yu : validunits; + hoffr, voffr, xr, yr : REAL; + landscape : boolean; + temp, strlen, i : integer; + str : string; + +BEGIN +(* initialize option values with defaults; note that the psprint script can + set up different defaults +*) +resolution := 300; (* LaserWriter resolution *) +hoffu := ic; +voffu := ic; +hoffr := 0.0; (* no margin shifting *) +voffr := 0.0; +xu := ic; (* paper dimensions in inches *) +yu := ic; +xr := 8.3; (* A4 paper is 8.3" wide *) +yr := 11.7; (* A4 paper is 11.7" high *) +mag := 0; (* use DVI mag *) +fontdir := '/tex/pk/'; (* location of PK files *) +dummyfont := 'cmr10.300pk'; (* typical font *) +tfmdir := '/tex/fonts/'; (* location of PS TFM files *) +psprefix := 'ps-'; (* prefix in PS font names *) +DVIname := ' '; (* SYSDEP: empty string *) +(* above are same as DVItoVDU options *) +header := '/usr/users/applied/staff/atrevorr/psdvi/tex.ps'; +PSname := 'out.ps'; (* output file (-o) *) +units := ic; (* inches (-u) *) +stats := FALSE; (* display stats? (-s) *) +reverse := FALSE; (* reverse page order? (-b) *) +conserveVM := FALSE; (* conserve VM? (-c) *) +landscape := FALSE; (* reverse -x and -y? (-l) *) +subrange := FALSE; (* -p value given? *) +firstDVIpage := 0; +finalDVIpage := 0; +firstTeXpage := '[]'; +finalTeXpage := '[]'; +argnum := 1; (* 0 is command *) +WHILE argnum < argc DO BEGIN + value := ' '; + argv(argnum,value); + vlength := Len(value); + argnum := argnum + 1; + IF value[0] = '-' THEN BEGIN + IF vlength > 1 THEN option := value[1] ELSE option := ' '; + CASE option OF + 'r' : BEGIN GetValue; GetCardinal(resolution); END; + 'm' : BEGIN GetValue; GetCardinal(mag); END; + 'i' : BEGIN GetValue; GetCardinal(increment); END; + 'x' : BEGIN GetValue; GetPosDimen(xr,xu); END; + 'y' : BEGIN GetValue; GetPosDimen(yr,yu); END; + 'H' : BEGIN GetValue; GetDimen(hoffr,hoffu); END; + 'V' : BEGIN GetValue; GetDimen(voffr,voffu); END; + 'T' : BEGIN GetValue; tfmdir := value; END; + 'P' : BEGIN GetValue; psprefix := value; END; + 'd' : BEGIN GetValue; dummyfont := value; END; + 'f' : BEGIN GetValue; fontdir := value; END; + 'h' : BEGIN GetValue; header := value; END; + 'o' : BEGIN GetValue; PSname := value; END; + 'u' : BEGIN GetValue; GetUnits; END; + 'p' : BEGIN GetValue; GetPages; END; + 's' : stats := TRUE; + 'b' : reverse := TRUE; + 'c' : conserveVM := TRUE; + 'l' : landscape := TRUE; + (* bad string values will be detected in other modules *) + OTHERWISE + writeln('Unknown option: -',option); + exit(1); + END; + END + ELSE BEGIN + (* value doesn't start with '-', so assume it is DVI file *) + DVIname := value; + IF NOT ExplicitExt(DVIname,vlength) THEN (* append .dvi *) + IF vlength + 3 < maxstring THEN BEGIN + DVIname[vlength] := '.'; + DVIname[vlength+1] := 'd'; + DVIname[vlength+2] := 'v'; + DVIname[vlength+3] := 'i'; + END + ELSE BEGIN (* user has given a mighty long file name *) + writeln('DVI file name too long: ',DVIname:maxstring); + exit(1); + END; + (* bad DVIname will be detected upon open in main module *) + END; +END; +IF DVIname[0] = ' ' THEN BEGIN (* no file name on command line *) + writeln('DVI file not given!'); + exit(1); +END; +(* prepend fontdir to dummyfont *) +str := fontdir; +strlen := Len(fontdir); +FOR i := 1 TO Len(dummyfont) DO BEGIN + IF strlen < maxstring THEN BEGIN + str[strlen] := dummyfont[i-1]; + strlen := strlen + 1; + END; +END; +dummyfont := str; +(* set h/voffset and paperwd/ht only after resolution has been decided *) +hoffset := DimenPixels(hoffr,hoffu); +voffset := DimenPixels(voffr,voffu); +paperwd := DimenPixels(xr,xu); +paperht := DimenPixels(yr,yu); +IF landscape THEN BEGIN (* swap paperwd and paperht *) + temp := paperwd; + paperwd := paperht; + paperht := temp; +END; +IF increment = 0 THEN increment := 1; (* do normal page selection *) +END; (* InitOptions *) diff --git a/dviware/psprint/unix/piechart.ps b/dviware/psprint/unix/piechart.ps new file mode 100644 index 0000000000..1d9d6137ea --- /dev/null +++ b/dviware/psprint/unix/piechart.ps @@ -0,0 +1,68 @@ +% This file is inserted into the PSPRINT User Guide using \special. +% It draws a simple pie chart (based on p.187 of the PostScript Cookbook). + +/DrawSlice +{ % this routine expects 3 parameters on stack: + /endangle exch def + /startangle exch def + /thelabel exch def + newpath 0 0 moveto + 0 0 radius startangle endangle arc + closepath + 1.415 setmiterlimit % bevel the lines joining in the centre + 0.01 Inch setlinewidth + stroke + gsave + % calculate starting position for label + startangle endangle add 2 div rotate + radius labelps add 0 translate + 0 0 transform + grestore + itransform + /y exch def /x exch def + x y moveto + x 0 lt { thelabel stringwidth pop neg 0 rmoveto } if % move label left + y 0 lt { 0 labelps neg rmoveto } if % move label down + thelabel show +} def + +/DrawPieChart +{ % this routine expects 5 parameters on stack: + /radius exch def + /ycenter exch def + /xcenter exch def + /PieArray exch def + /labelps exch def + xcenter ycenter translate + /Helvetica findfont labelps scalefont setfont + /curangle 0 def + PieArray + { /slicearray exch def + slicearray aload pop + /percent exch def + /label exch def + /perangle percent 100 div 360 mul def + label curangle curangle perangle add DrawSlice + /curangle curangle perangle add def + } forall % repeat above procedure for each element in PieArray +} def + +/Inch { 72 mul } def % converts inches to points + +% ----- MAIN PROGRAM ----- + +8 % label point size +[ % PieArray is an array of arrays + [ (Blueberry) 12 ] + [ (Apple) 30 ] + [ (Cherry) 12 ] % include any number of label, percentage pairs + [ (Raspberry) 16 ] % but make sure the numbers add up to 100 + [ (Apricot) 24 ] + [ (Other) 6 ] +] +3.15 Inch 1.0 Inch % x,y center of pie chart + % (3.15in * 2 = 6.3in = text width in User Guide) +.7 Inch % radius +DrawPieChart % draw pie chart using above arguments + +showpage diff --git a/dviware/psprint/unix/ps.ps b/dviware/psprint/unix/ps.ps new file mode 100644 index 0000000000..83021f4df6 --- /dev/null +++ b/dviware/psprint/unix/ps.ps @@ -0,0 +1,20 @@ +% Prologue for a PostScript job. +% It assumes psprint has defined land and dev. + +land % only do something if /landscape given +{ dev (LINO) eq % Linotronic allows different page sizes + { initgraphics + newpath clippath pathbbox % push LLx LLy URx URy + pop % URy + 0 translate % move origin right by URx (= page image width) + pop % LLy + pop % LLx + 90 rotate % rotate axes 90deg anticlockwise + } + { % dev = LW or PS40 + 8.3 72 mul 0 translate % move origin right by 8.3in (= A4 width) + 90 rotate % rotate axes 90deg anticlockwise + } ifelse +} if + +% The above transformations can be overridden by initgraphics/initmatrix etc. diff --git a/dviware/psprint/unix/ps40_fonts.ps b/dviware/psprint/unix/ps40_fonts.ps new file mode 100644 index 0000000000..a24e0651ff --- /dev/null +++ b/dviware/psprint/unix/ps40_fonts.ps @@ -0,0 +1,39 @@ +% This file converts TFM font names into the actual PrintServer 40 font names: + + % These fonts are resident in all PostScript printers: +/ps-courier-b /Courier-Bold def +/ps-courier-bo /Courier-BoldOblique def +/ps-courier-o /Courier-Oblique def +/ps-courier /Courier def +/ps-helv-b /Helvetica-Bold def +/ps-helv-bo /Helvetica-BoldOblique def +/ps-helv-o /Helvetica-Oblique def +/ps-helv /Helvetica def +/ps-symbol /Symbol def +/ps-times-b /Times-Bold def +/ps-times-bi /Times-BoldItalic def +/ps-times-i /Times-Italic def +/ps-times-r /Times-Roman def + + % This font will be constructed from Times-Roman: +/ps-times-s /Times-Slanted def + + % These fonts are also resident in PrintServer 40: +/ps-avantg-b /AvantGarde-Book def +/ps-avantg-bo /AvantGarde-BookOblique def +/ps-avantg-d /AvantGarde-Demi def +/ps-avantg-do /AvantGarde-DemiOblique def +/ps-ncs-b /NewCenturySchlbk-Bold def +/ps-ncs-bo /NewCenturySchlbk-BoldItalic def +/ps-ncs-i /NewCenturySchlbk-Italic def +/ps-ncs-r /NewCenturySchlbk-Roman def + + % These fonts don't have TFM files for them as yet: +% /??? /Souvenir-Demi def +% /??? /Souvenir-DemiItalic def +% /??? /Souvenir-Light def +% /??? /Souvenir-LightItalic def +% /??? /LubalinGraph-Book def +% /??? /LubalinGraph-BookOblique def +% /??? /LubalinGraph-Demi def +% /??? /LubalinGraph-DemiOblique def diff --git a/dviware/psprint/unix/ps40_header.ps b/dviware/psprint/unix/ps40_header.ps new file mode 100644 index 0000000000..524d07137b --- /dev/null +++ b/dviware/psprint/unix/ps40_header.ps @@ -0,0 +1,67 @@ +% For the PrintServer 40 we don't need to produce a banner page. +% We still redefine the error handler though: + +/@errpage 64 dict def +@errpage begin +/prnt + {dup type/stringtype ne{=string cvs}if dup length 6 mul/tx exch def/ty 10 def + currentpoint/toy exch def/tox exch def 1 setgray newpath + tox toy 2 sub moveto 0 ty rlineto tx 0 rlineto 0 ty neg rlineto + closepath fill tox toy moveto 0 setgray show}bind def +/nl{currentpoint exch pop lmargin exch moveto 0 -10 rmoveto}def +/=={/cp 0 def typeprint nl}def +/typeprint{dup type dup currentdict exch known + {exec}{unknowntype}ifelse}readonly def +/lmargin 72 def/rmargin 72 def +/tprint{dup length cp add rmargin gt{nl/cp 0 def}if + dup length cp add/cp exch def prnt}readonly def +/cvsprint{=string cvs tprint( )tprint}readonly def +/unknowntype{exch pop cvlit(??)tprint cvsprint}readonly def +/integertype{cvsprint}readonly def +/realtype{cvsprint}readonly def +/booleantype{cvsprint}readonly def +/operatortype{(//)tprint cvsprint}readonly def +/marktype{pop(-mark- )tprint}readonly def +/dicttype{pop(-dictionary- )tprint}readonly def +/nulltype{pop(-null- )tprint}readonly def +/filetype{pop(-filestream- )tprint}readonly def +/savetype{pop(-savelevel- )tprint}readonly def +/fonttype{pop(-fontid- )tprint}readonly def +/nametype{dup xcheck not{(/)tprint}if cvsprint}readonly def +/stringtype + {dup rcheck{(\()tprint tprint(\))tprint}{pop(-string- )tprint}ifelse + }readonly def +/arraytype + {dup rcheck{dup xcheck + {({)tprint{typeprint}forall(})tprint} + {([)tprint{typeprint}forall(])tprint}ifelse}{pop(-array- )tprint}ifelse + }readonly def +/packedarraytype + {dup rcheck{dup xcheck + {({)tprint{typeprint}forall(})tprint} + {([)tprint{typeprint}forall(])tprint}ifelse}{pop(-packedarray- )tprint}ifelse + }readonly def +/courier /Courier findfont 10 scalefont def +/@oldhandleerror errordict /handleerror get def +end + +errordict /handleerror +{ systemdict begin $error begin @errpage begin + newerror + { /newerror false store + vmstatus pop pop 0 ne { grestoreall } if + initgraphics courier setfont + lmargin 792 moveto + (POSTSCRIPT ERROR: ) prnt errorname prnt nl + (OFFENDING COMMAND: ) prnt /command load prnt nl + $error /ostack known + { (OPERAND STACK:) prnt nl + $error /ostack get aload length {==} repeat + } if + /#copies 1 store + systemdict /showpage get exec + /newerror true store + /@oldhandleerror load end end end exec } + { end end end } + ifelse +} dup 0 systemdict put dup 4 @errpage put bind readonly put diff --git a/dviware/psprint/unix/psdvi.p b/dviware/psprint/unix/psdvi.p new file mode 100644 index 0000000000..ad3e365cc7 --- /dev/null +++ b/dviware/psprint/unix/psdvi.p @@ -0,0 +1,859 @@ +PROGRAM PSDVI (output); + +CONST version = 'This is PSDVI, version 3.0'; + +(* Author: Andrew Trevorrow + Implementation: Pyramid Pascal + + Description: + This program is run by the psprint script to read a DVI file + and create an equivalent PostScript file. + + Notes: + - See AAAREAD.ME for revision history. + - Debugging code is bracketed by { DEBUG } ... { GUBED }. + This code will be commented out in the final working version. + - System-dependent code is indicated by the string "SYSDEP". + - Uncertain code is indicated by the string "???". + - Unfinished code is indicated by the string "!!!". + - Goto 999 is used to emulate a RETURN (from procedure) statement. + - Goto <= 888 is used to emulate an EXIT (from loop) statement. + - The above notes are also true for all separately compiled modules. +*) + +#include 'globals.h'; +#include 'options.h'; +#include 'dvireader.h'; +#include 'fontreader.h'; +#include 'pswriter.h'; + +CONST + pagesperline = 10; (* number of pages displayed per line *) + +VAR + papertop, + paperleft, + paperbottom, + paperright, (* these define the edges of the paper *) + pagecount : INTEGER; (* count of pages actually output *) + unusedfont : fontinfoptr; (* first unused font in sorted fontlist *) + +(******************************************************************************) + +PROCEDURE Initialize; + +BEGIN +(* top left corner of paper is fixed at (-1",-1") *) +papertop := -resolution; +paperleft := -resolution; +paperbottom := papertop + paperht - 1; +paperright := paperleft + paperwd - 1; +warncount := 0; +pagecount := 0; +END; (* Initialize *) + +(**********************************************************************) + +PROCEDURE ShowUnits; + +BEGIN +CASE units OF + ic : write('in') ; + cm : write('cm') ; + mm : write('mm') ; + pc : write('pc') ; + pt : write('pt') ; + bp : write('bp') ; + px : write('px') ; +END; +END; (* ShowUnits *) + +(******************************************************************************) + +PROCEDURE ShowDimension (pixels : INTEGER); + +(* Show the given pixel dimension in terms of units. *) + +LABEL 999; + +VAR realdim : REAL; fracpart : INTEGER; + +BEGIN +CASE units OF + ic : realdim := pixels / resolution ; + cm : realdim := pixels / resolution * 2.54 ; + mm : realdim := pixels / resolution * 25.4 ; + pc : realdim := pixels / resolution * 72.27 / 12.0 ; + pt : realdim := pixels / resolution * 72.27 ; + bp : realdim := pixels / resolution * 72.0 ; + px : BEGIN write(pixels:1, 'px'); goto 999 END; +END; +(* show realdim to an accuracy of 1 decimal place *) +IF ABS(realdim) < 0.05 THEN + write('0.0') +ELSE BEGIN + IF realdim < 0.0 THEN BEGIN + write('-'); + realdim := ABS(realdim); + END; + realdim := realdim + 0.05; (* round up to 1 decimal place *) + write(TRUNC(realdim):1); (* whole part *) + write('.'); + fracpart := TRUNC((realdim - TRUNC(realdim)) * 10.0); + (* fracpart is now 0..9 *) + write(fracpart:1); +END; +ShowUnits; +999: +END; (* ShowDimension *) + +(******************************************************************************) + +PROCEDURE ShowOptions; + +(* Show DVI file name and option values. *) + +BEGIN +writeln(version); writeln; +writeln('DVI file = ', DVIname:Len(DVIname)); +writeln('PostScript file = ', PSname:Len(PSname)); +writeln('Header file = ', header:Len(header)); +writeln('Resolution = ', resolution:1, ' pixels per inch'); +write ('Magnification = ', mag:1); +IF mag <> DVImag THEN + writeln(' (DVI mag of ', DVImag:1, ' was overridden)') +ELSE + writeln(' (DVI mag)'); +writeln('TFM directory = ', tfmdir:Len(tfmdir)); +writeln('PS font prefix = ', psprefix:Len(psprefix)); +writeln('Font directory = ', fontdir:Len(fontdir)); +writeln('Dummy font = ', dummyfont:Len(dummyfont)); +write ('Horizontal offset = '); ShowDimension(hoffset); writeln; +write ('Vertical offset = '); ShowDimension(voffset); writeln; +write ('Paper width = '); ShowDimension(paperwd); writeln; +write ('Paper height = '); ShowDimension(paperht); writeln; +write ('Units = '); ShowUnits; writeln; +write ('Reverse = '); +IF reverse THEN writeln('true') ELSE writeln('false'); +write ('Stats = '); +IF stats THEN writeln('true') ELSE writeln('false'); +write ('Conserve VM = '); +IF conserveVM THEN writeln('true') ELSE writeln('false'); +write ('Pages = '); +IF subrange THEN BEGIN + IF firstDVIpage = 0 THEN write(firstTeXpage:Len(firstTeXpage)) + ELSE write(firstDVIpage:1); + write(':'); + IF finalDVIpage = 0 THEN write(finalTeXpage:Len(finalTeXpage)) + ELSE write(finalDVIpage:1); +END +ELSE + write('all pages'); +IF increment > 1 THEN write(', but with an increment of ',increment:1); +writeln; +writeln; +END; (* ShowOptions *) + +(******************************************************************************) + +FUNCTION GetInteger (VAR str : string; (* in *) + strlen : INTEGER; (* in *) + VAR pos : INTEGER; (* in/out *) + VAR n : INTEGER (* out *) + ) : BOOLEAN; + +(* Extract an integer from given str starting at given pos. + pos is also used to return the position after the integer. + If no integer is found then set n to 0 and return FALSE (pos will only + change if leading spaces were skipped). + If ABS(n) > limit then set n to sign * limit. + Valid syntax is +{digit} or -{digit} or digit{digit}. + Note that a + or - by itself is valid and sets n to 0. +*) + +LABEL 777, 888; + +CONST limit = 2147483647; (* 2^31 - 1 *) + threshold = limit DIV 10; (* nearing overflow *) + +VAR absval, last : INTEGER; + sign : INTEGER; + inttoobig : BOOLEAN; + +BEGIN +WHILE pos < strlen DO BEGIN (* skip any spaces *) + IF str[pos] <> ' ' THEN goto 888; + pos := pos + 1; +END; +888: +absval := 0; sign := 1; last := pos; +inttoobig := FALSE; +IF pos < strlen THEN BEGIN + IF str[pos] = '-' THEN BEGIN + sign := -1; + last := last + 1; + END + ELSE IF str[pos] = '+' THEN + last := last + 1; + WHILE last < strlen DO BEGIN + IF (str[last] < '0') OR (str[last] > '9') THEN goto 777; + IF (absval > threshold) OR ((absval = threshold) AND (str[last] > '7')) + THEN + inttoobig := TRUE + ELSE + absval := absval * 10 + (ORD(str[last]) - ORD('0')); + last := last + 1; + END; + 777: +END; +IF pos = last THEN BEGIN + n := 0; + GetInteger := FALSE; +END +ELSE BEGIN + pos := last; + IF inttoobig THEN absval := limit; + n := sign * absval; + GetInteger := TRUE; +END; +END; (* GetInteger *) + +(******************************************************************************) + +FUNCTION ParseTeXPage (VAR pagestring : string; + VAR newTeXpage : TeXpageinfo) : BOOLEAN; + +(* Return TRUE if TeX page specification in pagestring is valid. If so then + newTeXpage will contain the appropriate information for CurrMatchesNew. + The syntax of a TeX page specification is [n{.n}] where n is any integer as + defined by GetInteger. Up to 10 integers may be given and are separated by + periods, even if absent. Trailing periods may be omitted. Spaces before + and after integers and periods are skipped. The 10 positions correspond to + the \count0, \count1, ... ,\count9 values that TeX stores with every page. +*) + +LABEL 555, 666, 777, 888, 999; + +VAR pos, len : INTEGER; + +BEGIN +WITH newTeXpage DO BEGIN + pos := 0; + IF pagestring[pos] <> '[' THEN BEGIN + writeln('[ expected!'); + ParseTeXPage := FALSE; + goto 999; + END; + lastvalue := 0; + len := 0; + WHILE len < maxstring DO + IF pagestring[len] = ' ' THEN goto 888 ELSE len := len + 1; + 888: + WHILE TRUE DO BEGIN + pos := pos + 1; + present[lastvalue] := GetInteger(pagestring, len, pos, value[lastvalue]); + (* pos now at len, space, period, non-digit or ']' *) + WHILE pos < len DO BEGIN + IF pagestring[pos] <> ' ' THEN goto 777; + pos := pos + 1; (* skip any spaces *) + END; + 777: + IF pos = len THEN BEGIN (* check this first! *) + writeln('] expected!'); + ParseTeXPage := FALSE; + goto 999; + END; + IF pagestring[pos] = ']' THEN (* end of TeX page specification *) + goto 666; + IF lastvalue < 9 THEN + lastvalue := lastvalue + 1 + ELSE BEGIN + writeln('] expected after 10 integers!'); + ParseTeXPage := FALSE; + goto 999; + END; + IF pagestring[pos] <> '.' THEN BEGIN + writeln('Period, integer or ] expected!'); + ParseTeXPage := FALSE; + goto 999; + END; + END; + 666: + WHILE lastvalue > 0 DO BEGIN + IF present[lastvalue] THEN goto 555; + lastvalue := lastvalue - 1; + END; + 555: +END; +ParseTeXPage := TRUE; +999: +END; (* ParseTeXPage *) + +(******************************************************************************) + +PROCEDURE CheckPageRange; + +(* If user requested a page subrange then we make sure it is valid. *) + +LABEL 777, 888; + +VAR newTeXpage : TeXpageinfo; + +BEGIN +IF NOT subrange THEN BEGIN (* translate all pages *) + firstDVIpage := 1; + finalDVIpage := totalpages; +END +ELSE BEGIN + IF firstDVIpage = 0 THEN (* parse and locate firstTeXpage *) + IF ParseTeXPage(firstTeXpage,newTeXpage) THEN BEGIN + MoveToDVIPage(1); + (* go forwards until newTeXpage matches currTeXpage *) + WHILE TRUE DO BEGIN + IF CurrMatchesNew(newTeXpage) THEN BEGIN + firstDVIpage := currDVIpage; + goto 888; + END + ELSE IF currDVIpage = totalpages THEN BEGIN + writeln('First TeX page does not exist!'); + exit(1); + END + ELSE + MoveToDVIPage(currDVIpage + 1); + END; + 888: + END + ELSE BEGIN + writeln('Error in first TeX page!'); + exit(1); + END; + IF finalDVIpage = 0 THEN (* parse and locate finalTeXpage *) + IF ParseTeXPage(finalTeXpage,newTeXpage) THEN BEGIN + MoveToDVIPage(totalpages); + (* go backwards until newTeXpage matches currTeXpage *) + WHILE TRUE DO BEGIN + IF CurrMatchesNew(newTeXpage) THEN BEGIN + finalDVIpage := currDVIpage; + goto 777; + END + ELSE IF currDVIpage = 1 THEN BEGIN + writeln('Final TeX page does not exist!'); + exit(1); + END + ELSE + MoveToDVIPage(currDVIpage - 1); + END; + 777: + END + ELSE BEGIN + writeln('Error in final TeX page!'); + exit(1); + END; + IF firstDVIpage > finalDVIpage THEN BEGIN + writeln('First page > final page!'); + exit(1); + END + ELSE IF firstDVIpage > totalpages THEN BEGIN + writeln('First page > total number of pages!'); + exit(1); + END; + (* allow user to give a final page > totalpages *) + IF finalDVIpage > totalpages THEN finalDVIpage := totalpages; +END; +END; (* CheckPageRange *) + +(******************************************************************************) + +PROCEDURE ShowTeXPage; + +(* Show current TeX page counter(s). *) + +LABEL 888; + +VAR i, lastnonzero : INTEGER; + +BEGIN +write('['); +lastnonzero := 9; +WHILE lastnonzero > 0 DO BEGIN + IF currTeXpage[lastnonzero] <> 0 THEN goto 888; + lastnonzero := lastnonzero - 1; (* find last counter with non-zero value *) +END; +888: +(* always show \count0 but don't show trailing 0 counters *) +FOR i := 0 TO lastnonzero DO BEGIN + write(currTeXpage[i]:1); + IF i <> lastnonzero THEN write('.'); +END; +write(']'); +END; (* ShowTeXPage *) + +(******************************************************************************) + +PROCEDURE PageOffPaper; + +(* One or more page edges do not fall within the paper edges. + We show user just how bad the problem is. +*) + +BEGIN +warncount := warncount + 1; +writeln; +write('Page off paper (paper is '); +ShowDimension(paperwd); write(' wide by '); +ShowDimension(paperht); write(' high)'); +writeln; +IF minhp < paperleft THEN BEGIN + write('Beyond left edge by '); + ShowDimension(paperleft - minhp); + writeln; +END; +IF maxhp > paperright THEN BEGIN + write('Beyond right edge by '); + ShowDimension(maxhp - paperright); + writeln; +END; +IF minvp < papertop THEN BEGIN + write('Above top edge by '); + ShowDimension(papertop - minvp); + writeln; +END; +IF maxvp > paperbottom THEN BEGIN + write('Below bottom edge by '); + ShowDimension(maxvp - paperbottom); + writeln; +END; +END; (* PageOffPaper *) + +(******************************************************************************) + +PROCEDURE OpenFont (thisfontinfo : fontinfoptr); + +BEGIN +WITH thisfontinfo^ DO + IF OpenFontFile(fontspec) THEN + { DEBUG + BEGIN + writeln; + writeln('Loading characters for ', fontspec:fontspeclen); + END + GUBED } + ELSE BEGIN + (* this should never happen since we avoid loading dummy font chars *) + writeln; + writeln('Bug in OpenFont! Could not open: ', fontspec:fontspeclen); + exit(1); + END; +END; (* OpenFont *) + +(******************************************************************************) + +PROCEDURE LoadFonts; + +(* For each bitmapped font that is used (and exists) on the current page, + go thru charlist and call LoadBitmap for each character that hasn't yet + been downloaded. BeginBitmapFont will only be called if necessary. +*) + +VAR + thisfontinfo : fontinfoptr; (* current font info in fontlist *) + thischarinfo : charinfoptr; (* current char info in charlist *) + thischar : INTEGER; (* current index into current chartable *) + fontopen : BOOLEAN; (* is thisfontinfo^.fontspec open? *) + +BEGIN +thisfontinfo := fontlist; +WHILE thisfontinfo <> unusedfont DO +(* SortFonts makes sure we only consider used fonts *) +WITH thisfontinfo^ DO BEGIN + (* do nothing if resident PostScript font or bitmapped font doesn't exist *) + IF (NOT psfont) AND fontexists THEN BEGIN + fontopen := FALSE; (* avoid opening font unnecessarily *) + thischarinfo := charlist; + WHILE thischarinfo <> NIL DO (* process unloaded chars in chartable *) + WITH thischarinfo^ DO BEGIN + thischar := 0; + WHILE thischar < charcount DO BEGIN + WITH chartable[thischar] DO + WITH pixelptr^[code] DO + IF (NOT loaded) AND (mapadr > 0) THEN BEGIN (* load bitmap *) + IF NOT fontopen THEN BEGIN + OpenFont(thisfontinfo); + BeginBitmapFont(fontid); + fontopen := TRUE; (* only open once *) + END; + LoadBitmap(thisfontinfo,code); + loaded := TRUE; (* only load once *) + END; + thischar := thischar + 1; + END; + thischarinfo := nextchar; + END; + IF fontopen THEN CloseFontFile; + END; + thisfontinfo := nextfont; +END; +END; (* LoadFonts *) + +(******************************************************************************) + +PROCEDURE DoSpecials; + +(* Call OutputSpecial for each \special command on the current page. + (The speciallist is built during InterpretPage.) +*) + +VAR temp : specialinfoptr; + +BEGIN +temp := speciallist; +WHILE temp <> NIL DO + WITH temp^ DO BEGIN + (* The \special bytes are treated as a file name, possibly followed by + a space and additional PostScript text. + PSWriter will read this file and copy it verbatim to the output file. + The optional text is prefixed to the file as a separate line. + *) + IF NOT OutputSpecial(special,hp,vp) THEN BEGIN + warncount := warncount + 1; + writeln; + writeln('Couldn''t open \special file: ', special:Len(special)); + END + ELSE IF stats THEN BEGIN + writeln; + write('\special command at ('); + ShowDimension(hp); write(','); + ShowDimension(vp); write('): '); + write(special:Len(special)); writeln; + END; + temp := nextspecial; + END; +END; (* DoSpecials *) + +(******************************************************************************) + +PROCEDURE DoFonts; + +(* For each font that is used (and exists) on the current page, + call the appropriate sequence of PSWriter routines depending on + the conserveVM flag and whether the font is bitmapped or resident. +*) + +VAR + thisfontinfo : fontinfoptr; (* current font info in fontlist *) + thischarinfo : charinfoptr; (* current char info in charlist *) + thischar : INTEGER; (* current index into current chartable *) + +BEGIN +thisfontinfo := fontlist; +WHILE thisfontinfo <> unusedfont DO +(* SortFonts makes sure we only consider used fonts! *) +WITH thisfontinfo^ DO BEGIN + IF fontexists THEN BEGIN (* won't be dummy font info *) + IF psfont THEN + BeginPostScriptFont(fontname,scaledsize,mag) + ELSE BEGIN + IF conserveVM THEN SaveVM(fontid); + BeginBitmapFont(fontid); + END; + + IF conserveVM AND (NOT psfont) THEN BEGIN (* download bitmaps *) + OpenFont(thisfontinfo); + thischarinfo := charlist; + WHILE thischarinfo <> NIL DO (* process unique chars *) + WITH thischarinfo^ DO BEGIN + thischar := 0; + WHILE thischar < charcount DO BEGIN + WITH chartable[thischar] DO + WITH pixelptr^[code] DO + IF (NOT loaded) AND (mapadr > 0) THEN BEGIN + LoadBitmap(thisfontinfo,code); + loaded := TRUE; (* but only once *) + END; + thischar := thischar + 1; + END; + thischarinfo := nextchar; + END; + CloseFontFile; + (* reset loaded flags to FALSE for next page *) + FOR thischar := 0 TO maxTeXchar DO + pixelptr^[thischar].loaded := FALSE; + END; + + IF psfont THEN BEGIN + thischarinfo := charlist; + WHILE thischarinfo <> NIL DO + WITH thischarinfo^ DO BEGIN + thischar := 0; + WHILE thischar < charcount DO BEGIN + WITH chartable[thischar] DO + WITH pixelptr^[code] DO + IF mapadr > 0 THEN (* char exists *) + SetPostScriptChar(CHR(code), + hp,vp, (* reference point *) + pwidth); (* advance width *) + thischar := thischar + 1; + END; + thischarinfo := nextchar; + END; + END + ELSE BEGIN + thischarinfo := charlist; + WHILE thischarinfo <> NIL DO + WITH thischarinfo^ DO BEGIN + thischar := 0; + WHILE thischar < charcount DO BEGIN + WITH chartable[thischar] DO + WITH pixelptr^[code] DO + IF mapadr > 0 THEN (* char exists *) + SetBitmapChar(CHR(code), + hp,vp, (* reference point *) + pwidth); (* advance width *) + thischar := thischar + 1; + END; + thischarinfo := nextchar; + END; + END; + EndFont; + + IF conserveVM AND (NOT psfont) THEN RestoreVM; + END; + thisfontinfo := nextfont; +END; +END; (* DoFonts *) + +(******************************************************************************) + +PROCEDURE DoRules; + +(* Call SetRule for each rule on the current page. *) + +VAR thisrule : INTEGER; thisruleinfo : ruleinfoptr; + +BEGIN +thisruleinfo := rulelist; +WHILE thisruleinfo <> NIL DO + WITH thisruleinfo^ DO BEGIN + thisrule := 0; + WHILE thisrule < rulecount DO BEGIN + WITH ruletable[thisrule] DO SetRule(wd,ht,hp,vp); + thisrule := thisrule + 1; + END; + thisruleinfo := nextrule; + END; +END; (* DoRules *) + +(******************************************************************************) + +PROCEDURE DoPage; + +(* Interpret the current DVI page and fill in DVIReader's data structures. + PSWriter routines are called at appropriate times to output + the PostScript description of the current page. +*) + +BEGIN +pagecount := pagecount + 1; +write(currDVIpage:1); (* show the current DVI page *) +write('/'); ShowTeXPage; (* and TeX page *) +flush(output); (* SYSDEP: show page immediately *) +IF pagecount MOD pagesperline = 0 THEN writeln ELSE write(' '); + +BeginPage(currDVIpage); +InterpretPage; (* PixelTableRoutine calls NewBitmapFont *) +IF pageempty THEN BEGIN + OutputPage(currDVIpage); (* must be called even if no chars/rules *) + DoSpecials; +END +ELSE BEGIN + (* check that the page edges are within the paper edges *) + IF (minhp < paperleft) OR (minvp < papertop) OR + (maxhp > paperright) OR (maxvp > paperbottom) THEN + PageOffPaper; + (* Sort fonts in order of increasing totalchars and + return pointer to first unused font (for LoadFonts and DoFonts). + *) + SortFonts(unusedfont); + IF NOT conserveVM THEN LoadFonts; + OutputPage(currDVIpage); + DoSpecials; + DoFonts; + DoRules; +END; +EndPage(currDVIpage); (* final PostScript for current page *) +END; (* DoPage *) + +(******************************************************************************) + +PROCEDURE ShowPtSize (scaledsize : INTEGER); + +(* Show given font size (in DVI units) in terms of (possibly magnified) pts. *) + +VAR realdim : REAL; fracpart : INTEGER; + +BEGIN +write(' at '); +realdim := (scaledsize / 16#10000) * (mag / 1000.0); +(* show realdim to an accuracy of 1 decimal place *) +IF ABS(realdim) < 0.05 THEN + write('0') +ELSE BEGIN + IF realdim < 0.0 THEN BEGIN + write('-'); + realdim := ABS(realdim); + END; + realdim := realdim + 0.05; (* round up to 1 decimal place *) + write(TRUNC(realdim):1); (* whole part *) + fracpart := TRUNC((realdim - TRUNC(realdim)) * 10.0); (* 0..9 *) + IF fracpart > 0 THEN + write('.', fracpart:1); +END; +write('pt'); +END; (* ShowPtSize *) + +(******************************************************************************) + +PROCEDURE ShowPageStats; + +(* Show rule/font/character statistics for current page. *) + +VAR fontcount : INTEGER; thisfontinfo : fontinfoptr; + +BEGIN +writeln; +writeln('Total rules on current page = ', totalrules:1); +writeln('Fonts on current page:'); +fontcount := 0; +thisfontinfo := fontlist; +WHILE thisfontinfo <> NIL DO + WITH thisfontinfo^ DO BEGIN + IF fontused THEN BEGIN + write(fontspec:fontspeclen); + IF psfont THEN ShowPtSize(scaledsize); + IF NOT fontexists THEN write(' DOES NOT EXIST!'); + fontcount := fontcount + 1; + writeln(' total chars = ', totalchars:1); + END; + thisfontinfo := nextfont; + END; +writeln('Total fonts on current page = ', fontcount:1); +writeln; +END; (* ShowPageStats *) + +(******************************************************************************) + +PROCEDURE ShowFinalStats; + +(* Show some overall statistics. *) + +VAR fontsused, c, loadcount, loadtotal, bitmapbytes : INTEGER; + thisfontinfo : fontinfoptr; + +BEGIN +writeln('Summary'); +writeln('======='); +writeln; +writeln('Total pages output = ', pagecount:1); +writeln('Total pages in DVI file = ', totalpages:1); +writeln('Total fonts in DVI file = ', totalfonts:1); +(* go thru fontlist showing info for EVERY font *) +fontsused := 0; +loadtotal := 0; +bitmapbytes := 0; +thisfontinfo := fontlist; +WHILE thisfontinfo <> NIL DO + WITH thisfontinfo^ DO BEGIN + IF fontspeclen > 0 THEN BEGIN + write(fontspec:fontspeclen); + IF psfont THEN ShowPtSize(scaledsize); + IF fontexists THEN BEGIN + fontsused := fontsused + 1; + IF (NOT conserveVM) AND (NOT psfont) THEN BEGIN + loadcount := 0; + FOR c := 0 TO maxTeXchar DO + WITH pixelptr^[c] DO + IF loaded AND (mapadr > 0) THEN BEGIN + loadcount := loadcount + 1; + bitmapbytes := bitmapbytes + (ht * ((wd + 7) DIV 8)); + END; + write(' loaded chars = ', loadcount:1); + loadtotal := loadtotal + loadcount; + END; + END + ELSE + write(' DOES NOT EXIST!'); + END + ELSE BEGIN + write(fontname:fontnamelen, ' scaled '); + write(TRUNC(mag * (scaledsize / designsize) + 0.5):1); + write(' not used'); + END; + writeln; + thisfontinfo := nextfont; + END; +writeln('Total fonts actually used = ', fontsused:1); +IF NOT conserveVM THEN BEGIN + writeln('Total characters loaded = ', loadtotal:1); + writeln('Hex digits in loaded bitmaps = 2 * ', bitmapbytes:1); +END; +END; (* ShowFinalStats *) + +(******************************************************************************) + +PROCEDURE TopLevel; + +LABEL 888; + +BEGIN +InitOptions; (* init DVIname and options *) +InitDVIReader; +InitFontReader; +OpenDVIFile(DVIname); (* and read DVImag etc. *) +IF mag = 0 THEN mag := DVImag; (* use DVImag *) +SetConversionFactor(resolution,mag); (* for DVIReader *) +Initialize; +IF stats THEN ShowOptions; +CheckPageRange; (* set firstDVIpage, finalDVIpage *) +IF NOT OpenOutput(PSname) THEN BEGIN + writeln('Couldn''t open output file: ', PSname:Len(PSname)); + exit(1); +END; +IF header[0] <> ' ' THEN (* output header file first *) + IF NOT OutputHeader(header) THEN BEGIN + writeln('Couldn''t open header file: ', header:Len(header)); + exit(1); + END; +IF increment > 1 THEN (* finalDVIpage may need reducing *) + WHILE (finalDVIpage - firstDVIpage) MOD increment > 0 DO + finalDVIpage := finalDVIpage - 1; +IF reverse THEN BEGIN + MoveToDVIPage(finalDVIpage); (* start with finalDVIpage *) + finalDVIpage := firstDVIpage; (* and end with firstDVIpage *) +END +ELSE + MoveToDVIPage(firstDVIpage); (* start with firstDVIpage *) +WHILE TRUE DO BEGIN + DoPage; (* do at least one page *) + IF stats THEN ShowPageStats; + IF currDVIpage = finalDVIpage THEN goto 888; + IF reverse THEN + MoveToDVIPage(currDVIpage - increment) + ELSE + MoveToDVIPage(currDVIpage + increment); +END; +888: +IF pagecount MOD pagesperline > 0 THEN writeln; +IF stats THEN ShowFinalStats; +CloseDVIFile; +CloseOutput; +IF warncount > 0 THEN + exit(2) +ELSE + exit(0); +END; (* TopLevel *) + +(******************************************************************************) + +BEGIN +TopLevel; +END. (* PSDVI *) diff --git a/dviware/psprint/unix/psfonts.tex b/dviware/psprint/unix/psfonts.tex new file mode 100644 index 0000000000..11e55aec2a --- /dev/null +++ b/dviware/psprint/unix/psfonts.tex @@ -0,0 +1,69 @@ +% This TeX source file illustrates the use (and abuse) of PostScript fonts. + +\input pstext % defines \PStext and \CMtext + +\nopagenumbers +\parindent=0pt +\parskip=\bigskipamount + +The following fonts should be available in all PostScript printers: + +\font\courb=ps-courier-b at 10pt +\font\courbo=ps-courier-bo at 10pt +\font\couro=ps-courier-o at 10pt +\font\cour=ps-courier at 10pt +\font\helvb=ps-helv-b at 10pt +\font\helvbo=ps-helv-bo at 10pt +\font\helvo=ps-helv-o at 10pt +\font\helv=ps-helv at 10pt +\font\tb=ps-times-b at 10pt +\font\tbi=ps-times-bi at 10pt +\font\ti=ps-times-i at 10pt +\font\ts=ps-times-s at 10pt +\font\tr=ps-times-r at 10pt +\font\sy=ps-symbol at 10pt + +\bigskip +\leftline{\courb Courier-Bold} +\leftline{\courbo Courier-BoldOblique} +\leftline{\couro Courier-Oblique} +\leftline{\cour Courier} +\leftline{\helvb Helvetica-Bold} +\leftline{\helvbo Helvetica-BoldOblique} +\leftline{\helvo Helvetica-Oblique} +\leftline{\helv Helvetica} +\leftline{\tb Times-Bold} +\leftline{\tbi Times-BoldItalic} +\leftline{\ti Times-Italic} +\leftline{\ts Times-Slanted} +\leftline{\tr Times-Roman} +\leftline{\sy Symbol \rm (Symbol)} + +A PostScript font can be used at any desired size: + +\font\trA=ps-times-r at 12pt +\font\trB=ps-times-r at 20pt +\font\trC=ps-times-r at 34.5pt + +\bigskip +\leftline{\tr Times-Roman at 10pt} +\leftline{\trA Times-Roman at 12pt} +\leftline{\trB Times-Roman at 20pt} +\leftline{\trC Times-Roman at 34.5pt} + +\def\sometext +{\'o \`o \^o \"o \~o \=o \.o \u o \v o \H o \t oo \c o \d o \b o +\oe\ \OE\ \ae\ \AE\ \aa\ \AA\ \o\ \O\ \l\ \L\ \ss\ \i\ \j} + +\rm +Standard \TeX\ accents and foreign letters: +\sometext + +PostScript accents and foreign letters: +\PStext \tr \sometext \CMtext % \t \aa \AA \j will generate error messages + +\rm +A PostScript font usually appears {\tr darker and larger} than +an ``equivalent'' Computer Modern font. + +\bye diff --git a/dviware/psprint/unix/psprint b/dviware/psprint/unix/psprint new file mode 100644 index 0000000000..776f2a2708 --- /dev/null +++ b/dviware/psprint/unix/psprint @@ -0,0 +1,403 @@ +#!/bin/csh -f +# +# Andrew Trevorrow, October 1988 +# This shell script can print a DVI file, PostScript program, or text file +# on an Apple LaserWriter, DEC PrintServer 40 or Linotronic 300. +# Search for SYSDEP to locate site-specific values that you may want to change. +# +set tex_ps = (/usr/users/applied/staff/atrevorr/ps) # SYSDEP +set tfminfo = (-T /usr/local/lib/tex/fonts/ -P ps-) # SYSDEP +set dev = lw # SYSDEP: use LaserWriter if no -dev value +# +# DON'T change these values unless you know what you're doing: +# +set filename # changed by last argument without "-" prefix +set filetype = UNKNOWN # changed by -dvi/-ps/-text/-two/-wide or filename +set ps_queue = default # use device-specific default if no -q value +set conserve = default # use device-specific default if no -con or -nocon +set rev = default # use device-specific default if no -rev or -norev +set copies = 1 # changed by -c value +set output # changed by -o value +set note # changed by -n value +set hoff # changed by -ho value +set voff # changed by -vo value +set pages # changed by -p value +set inc # changed by -i value +set mag # changed by -m value +set units # changed by -u value +set stats # changed by -s +set landscape # changed by -l +set linores = 1270 # changed by -lowres (to 635) +set size = a4p # changed by -size value +set cutmarks = true # -cut = do cut marks; changed by -nocut +set flag = true # -flag = flag page enabled; changed by -noflag +set manual = false # no manual feed; changed by -manual +# +# Parse command line and set various parameters. +# +@ i = 1 +while ($i <= $#argv) + set arg = "$argv[$i]" + if ("$arg" =~ -*) then # arg must be an option + if ("$arg" == '-dvi') then + set filetype = DVI + else if ("$arg" == '-ps') then + set filetype = PS + else if ("$arg" == '-text') then + set filetype = TEXT + else if ("$arg" == '-two') then + set filetype = TWO + else if ("$arg" == '-wide') then + set filetype = WIDE + else if ("$arg" == '-dev' | "$arg" == '-device') then + @ i++ + if ($i > $#argv) then + echo 'Missing string after -dev\!' + exit(1) + endif + set dev = "$argv[$i]" + else if ("$arg" == '-o') then + @ i++ + if ($i > $#argv) then + echo 'Missing file after -o\!' + exit(1) + endif + set output = "$argv[$i]" + else if ("$arg" == '-n') then + @ i++ + if ($i > $#argv) then + echo 'Missing string after -n\!' + exit(1) + endif + set note = "$argv[$i]" + else if ("$arg" == '-ho') then + @ i++ + if ($i > $#argv) then + echo 'Missing dimension after -ho\!' + exit(1) + endif + set hoff = (-H"$argv[$i]") + else if ("$arg" == '-vo') then + @ i++ + if ($i > $#argv) then + echo 'Missing dimension after -vo\!' + exit(1) + endif + set voff = (-V"$argv[$i]") + else if ("$arg" == '-c') then + @ i++ + if ($i > $#argv) then + echo 'Missing integer after -c\!' + exit(1) + endif + set copies = "$argv[$i]" + if ("$copies" !~ [0,1,2,3,4,5,6,7,8,9]*) then + echo 'Bad -c value:' $copies + echo 'Specify a positive integer.' + exit(1) + else if ("$copies" < 1 | "$copies" > 25) then + echo 'Bad -c value:' $copies + echo 'Specify a positive integer from 1 to 25.' + exit(1) + endif + else if ("$arg" == '-i') then + @ i++ + if ($i > $#argv) then + echo 'Missing integer after -i\!' + exit(1) + endif + set inc = (-i"$argv[$i]") + else if ("$arg" == '-m') then + @ i++ + if ($i > $#argv) then + echo 'Missing integer after -m\!' + exit(1) + endif + set mag = (-m"$argv[$i]") + else if ("$arg" == '-u') then + @ i++ + if ($i > $#argv) then + echo 'Missing units after -u\!' + exit(1) + endif + set units = (-u"$argv[$i]") + else if ("$arg" == '-p') then + @ i++ + if ($i > $#argv) then + echo 'Missing page range after -p\!' + exit(1) + endif + set pages = (-p"$argv[$i]") + else if ("$arg" == '-s') then + set stats = -s # show stats (if DVI) + else if ("$arg" == '-con' | "$arg" == '-conserve') then + set conserve = -c # conserve VM (if DVI) + else if ("$arg" == '-nocon' | "$arg" == '-noconserve') then + set conserve # don't conserve VM + else if ("$arg" == '-rev' | "$arg" == '-reverse') then + set rev = -b # reverse page order (if DVI) + else if ("$arg" == '-norev' | "$arg" == '-noreverse') then + set rev # don't reverse + else if ("$arg" == '-l') then + set landscape = -l # swap paper dimens (if DVI) + else if ("$arg" == '-f' | "$arg" == '-flag') then + set flag = true # we want a flag page (if lw) + else if ("$arg" == '-nof' | "$arg" == '-noflag') then + set flag = false # no flag page + else if ("$arg" == '-man' | "$arg" == '-manual') then + set manual = true # wait for manual feed (if lw) + else if ("$arg" == '-low' | "$arg" == '-lowres') then + set linores = 635 # low resolution (if lino) + else if ("$arg" == '-cut' | "$arg" == '-cutmarks') then + set cutmarks = true # show cut marks (if lino) + else if ("$arg" == '-nocut' | "$arg" == '-nocutmarks') then + set cutmarks = false # no cut marks + else if ("$arg" == '-size') then + @ i++ + if ($i > $#argv) then + echo 'Missing value after -size\!' + exit(1) + endif + set size = "$argv[$i]" + else if ("$arg" == '-q') then + @ i++ + if ($i > $#argv) then + echo 'Missing queue after -q\!' + exit(1) + endif + set ps_queue = "$argv[$i]" + else + echo 'Unknown option:' $arg + exit(1) + endif + else + # arg does not start with '-' so assume it is filename + set filename = "$arg" + endif + @ i++ +end +if ($filename == '') then + echo 'File not given\!' + exit(1) +endif +# +# If filetype is still UNKNOWN then we check filename to determine filetype. +# Note that if foo and foo.dvi exist then "psprint foo" will use foo.dvi +# (and "psprint foo -text" will use foo): +# +if ($filetype == 'UNKNOWN') then + if ($filename =~ *.ps) then + set filetype = PS + else if ($filename =~ *.dvi) then + set filetype = DVI + else if (-e {$filename}.dvi) then + set filename = {$filename}.dvi + set filetype = DVI + else + set filetype = TEXT + endif +endif +# +# Check that file exists: +# +if (-e $filename) then + # file exists +else + echo File not found: $filename + exit(1) +endif +# +# Check for valid device; if ok then set up some device-specific values: +# +if ("$dev" == 'lw') then + if ("$ps_queue" == 'default') then + set ps_queue = ps_local # SYSDEP: default LaserWriter queue + else + # SYSDEP: test for valid queue? + endif + if ("$rev" == 'default') set rev = -b # default is reverse pages + if ("$conserve" == 'default') set conserve # default is don't conserve VM + set papersize = "-x 210mm -y 297mm" # SYSDEP: A4 + set res = 300 + set dummyfont = (-d cmr10.300pk) # SYSDEP + set pkdir = (-f /usr/local/bin/dvitovdu/pk/) # SYSDEP +else if ("$dev" == 'lino') then + if ("$ps_queue" == 'default') then + set ps_queue = lino_queue # SYSDEP: default Linotronic queue + else + # SYSDEP: test for valid queue? + endif + if ("$rev" == 'default') set rev # default is don't reverse + if ("$conserve" == 'default') set conserve = -c # default is conserve VM + if ("$size" == 'a3l') then + set pagesetup = A3Lsetup # defined in lino_header.ps + set papersize = "-x 297mm -y 420mm" # A3 + else if ("$size" == 'a4p') then + set pagesetup = A4Psetup + set papersize = "-x 210mm -y 297mm" # A4 + else if ("$size" == 'a4l') then + set pagesetup = A4Lsetup + set papersize = "-x 210mm -y 297mm" + else if ("$size" == 'a5p') then + set pagesetup = A5Psetup + set papersize = "-x 148mm -y 210mm" # A5 + else if ("$size" == 'a5l') then + set pagesetup = A5Lsetup + set papersize = "-x 148mm -y 210mm" + else if ("$size" == 'b5p') then + set pagesetup = B5Psetup + set papersize = "-x 176mm -y 250mm" # B5 + else if ("$size" == 'b5l') then + set pagesetup = B5Lsetup + set papersize = "-x 176mm -y 250mm" + else + echo 'Unknown -size value:' "$size" '(use a3l,a4p,a4l,a5p,a5l,b5p,b5l)' + exit(1) + endif + set res = $linores # 635 or 1270 + set dummyfont = (-d cmr10.{$res}pk) # SYSDEP + set pkdir = (-f /usr/local/tex/linopk/) # SYSDEP +else if ("$dev" == 'ps40') then + if ("$ps_queue" == 'default') then + set ps_queue = ps40_queue # SYSDEP: default PrintServer queue + else + # SYSDEP: test for valid queue? + endif + if ("$rev" == 'default') set rev # default is don't reverse pages + if ("$conserve" == 'default') set conserve # default is don't conserve VM + set papersize = "-x 210mm -y 297mm" # SYSDEP: A4 + set res = 300 + set dummyfont = (-d cmr10.300pk) # SYSDEP + set pkdir = (-f /usr/local/tex/write-white/) # SYSDEP +else + echo 'Unknown device:' "$dev" '(specify lw, lino or ps40)' + exit(1) +endif +# +# Linotronic should only be used to print DVI or PS files: +# +if ("$dev" == 'lino') then + if ($filetype != 'DVI' & $filetype != 'PS') then + echo 'Linotronic should not be used to print a text file\!' + exit(1) + endif +endif +# +# Build temporary file in current directory: +# +set tmpfile = (psprint.tmp) +echo Creating $tmpfile +if ("$dev" == 'lw') then + # + # We no longer start with ^D because of problems encountered when + # a LaserWriter is connected to an X25 pad (due to echoing of ^D): + # + cp $tex_ps/lw_header.ps $tmpfile + echo '/@USER (USER :' $user ') def' >> $tmpfile + echo '/@NODE (NODE :' $HOST ') def' >> $tmpfile + echo '/@FILE (FILE :' $filename ') def' >> $tmpfile + echo '/@FORMAT (FORMAT :' $filetype ') def' >> $tmpfile + echo '/@QUEUED (QUEUED :' `date` ') def' >> $tmpfile + echo '/@NOTE (NOTE :' $note ') def' >> $tmpfile + if ($flag != 'true') then + echo '/@bannerpage { } def' >> $tmpfile # no flag page + endif + if ($manual == 'true') then + echo 'statusdict begin /manualfeed true def end' >> $tmpfile + endif +else if ("$dev" == 'lino') then + echo '/@USER ('$user' '$filename') def' >> $tmpfile + echo '/@DATE ('`date`') def' >> $tmpfile + echo '/@NOTE ('$note') def' >> $tmpfile + cat $tex_ps/lino_header.ps >> $tmpfile + echo $pagesetup >> $tmpfile # call page setup procedure + if ($cutmarks != 'true') then + echo '/@cutmarks { } def' >> $tmpfile # no cutmarks + endif +else # "$dev" must be 'ps40' + cp $tex_ps/ps40_header.ps $tmpfile +endif +# +# The value of #copies will be used by PostScript's showpage operator to +# print multiple copies of each page: +# +echo '/#copies '$copies' def' >> $tmpfile +# +# Here are some definitions used in the various prologues: +# +if ("$dev" == 'lw') echo '/dev (LW) def' >> $tmpfile +if ("$dev" == 'lino') echo '/dev (LINO) def' >> $tmpfile +if ("$dev" == 'ps40') echo '/dev (PS40) def' >> $tmpfile +echo '/res '$res' def' >> $tmpfile +echo '/fspec ('$filename') def' >> $tmpfile # used in two.ps and wide.ps +if ("$landscape" == '-l') then + echo '/land true def' >> $tmpfile +else + echo '/land false def' >> $tmpfile +endif +# +# Each type of file has its own prologue: +# +if ($filetype == 'DVI') cat $tex_ps/tex.ps $tex_ps/{$dev}_fonts.ps >> $tmpfile +if ($filetype == 'PS') cat $tex_ps/ps.ps >> $tmpfile +if ($filetype == 'TEXT') cat $tex_ps/text.ps >> $tmpfile +if ($filetype == 'TWO') cat $tex_ps/two.ps >> $tmpfile +if ($filetype == 'WIDE') cat $tex_ps/wide.ps >> $tmpfile +# +# If DVI file then run psdvi and check exit status: +# +if ($filetype == 'DVI') then + set psdvifile = (psdvi.tmp) + $tex_ps/psdvi \ + $rev $landscape $stats $conserve $pkdir $dummyfont $tfminfo \ + "$pages" $inc $mag $units $hoff $voff $papersize \ + -h $tmpfile -o $psdvifile -r $res \ + $filename # best if last argument + # + # psdvi can exit with 0=success, 1=error, 2=warning: + # + if ($status >= '1') then # psdvi saw warning(s) or fatal error + rm $tmpfile # delete temporary header + echo 'Printing aborted due to error(s). '$tmpfile deleted. + if (-e $psdvifile) then # psdvi output file exists + rm $psdvifile # so delete it + endif + exit(1) + else # no errors + rm $tmpfile # delete header + mv $psdvifile $tmpfile # and use psdvi output as temporary file + endif +endif +# +# Complete temporary file: +# +if ("$dev" == 'lw') then + if ($filetype == 'DVI') then + cat $tex_ps/lw_trailer.ps $tex_ps/ctrld >> $tmpfile + else if ($filetype == 'PS') then + cat $filename $tex_ps/lw_trailer.ps $tex_ps/ctrld >> $tmpfile + else # TEXT/TWO/WIDE + cat $filename $tex_ps/ctrld >> $tmpfile + endif +else if ("$dev" == 'lino') then + if ($filetype == 'DVI') then + cat $tex_ps/lino_trailer.ps $tex_ps/ctrld >> $tmpfile + else if ($filetype == 'PS') then + cat $filename $tex_ps/lino_trailer.ps $tex_ps/ctrld >> $tmpfile + else # TEXT/TWO/WIDE not supported on Linotronic + endif +else + # dev = 'ps40'; no trailer file or ^D needed for PrintServer +endif +# +# If -o used then rename temporary file, else print it: +# +if ("$output" == '') then + lpr -P$ps_queue -h $tmpfile + echo Your output has been sent to $ps_queue + # echo debug: lpr '-P'$ps_queue '-h' $tmpfile + rm $tmpfile +else + mv $tmpfile $output + echo PostScript code saved in $output +endif diff --git a/dviware/psprint/unix/psprint.man b/dviware/psprint/unix/psprint.man new file mode 100644 index 0000000000..ae6cbedc00 --- /dev/null +++ b/dviware/psprint/unix/psprint.man @@ -0,0 +1,358 @@ +PSPRINT can be used to print a DVI file produced by TeX (or LaTeX), +a raw PostScript file, or an ordinary text file, on a variety of PostScript +printers. The currently supported devices include the Apple LaserWriter, +the Linotronic 300 and DEC's PrintServer 40. + +USAGE: psprint file + [-dev[ice] printer_type] + [-dvi] [-ps] [-text] [-two] [-wide] + [-o file] [-q queue] [-n note] [-c copies] [-l] + [-low[res]] [-[no]cut[marks]] [-size page_setup] + [-man[ual]] [-[no]f[lag]] + [-m magnification] [-u units] + [-s] [-[no]rev[erse]] [-[no]con[serve]] + [-p first:final] [-i increment] [-ho dimension] [-vo dimension] + +TeX Output +---------- +PSPRINT looks for a DVI file by default. To print foo.dvi, simply type: + + psprint foo + +PSPRINT translates foo.dvi into a temporary PostScript file. +The order in which pages are translated depends on the type of printer. +(The default order can be overridden by -reverse or -noreverse.) +If no errors are found, the temporary file is sent to an appropriate +print queue and then deleted. + +PostScript Output +----------------- +PostScript is a complete programming language with a powerful set of +operators for manipulating text and graphics. A PostScript program is an +ordinary text file. If you give it a name like foo.ps then sending it to +the printer is simple: + + psprint foo.ps + +If you decide to use some other file extension you'll have to add the -ps +option. The PSPRINT User Guide explains how to include PostScript +graphics in a TeX or LaTeX document. + +People who want to write PostScript programs will need to get the +PostScript Language Reference Manual and PostScript Language Tutorial +and Cookbook. Both books are by Adobe Systems Incorporated and +published by Addison-Wesley. + +Text Output +----------- +To print a normal text file, just use any file type except .dvi or .ps: + + psprint foo.lis + +Your output will have 66 lines per page, and any lines more than 80 +characters long will be truncated. Use the -l option to rotate the paper +so that you can have lines up to 132 characters long +(but only 50 lines per page). + +Type "psprint foo.ps -text" if you want to print a PostScript program +rather than have it interpreted. You'll also have to use -text if you +want to print a text file called foo but foo.dvi also exists. + +The -two and -wide options also print text files but format the +output so that two "pages" appear on each sheet of paper. +In both cases there will be 60 lines per page, but for -two each line +can be up to 80 characters long, or up to 132 characters for -wide. + +These text file facilities may not be available on all types of +printers, especially the Linotronic. + +Options +------- + +-device printer_type + +This option tells PSPRINT which type of PostScript printer is to be used. +The currently supported devices are: + + lw --- for an Apple LaserWriter (the default) + lino --- for a Linotronic 300 + ps40 --- for DEC's PrintServer 40 + +-dvi + +Force PSPRINT to assume the input file is a DVI file. + +-ps + +Force PSPRINT to assume the input file is a PostScript program. + +-text + +Force PSPRINT to assume the input file is an ordinary text file. + +-two + +Like -text but the output is formatted so that two "pages" +(both 60 lines by 80 columns) appear on each sheet of paper. + +-wide + +Like -text but the output is formatted so that two wide "pages" +(both 60 lines by 132 columns) appear on each sheet of paper. + +-flag or -noflag (only if LaserWriter) + +By default PSPRINT produces a flag page for each job sent to +a LaserWriter. Use -noflag if you don't want such a page. + +-manual (only if LaserWriter) + +Use this option if you want to manually feed paper into the LaserWriter. +As soon as the printer sees your job it will wait for you to feed in each +sheet of paper (it will normally wait up to a minute). + +-lowres (only for a DVI file and if Linotronic) + +By default, TeX output on the Linotronic is printed at 1270 dots per inch. +The temporary file created by PSPRINT will typically be very large. +If -lowres is given then 635 dots per inch will be used, reducing both the +size of the temporary file (by roughly three quarters) and the likelihood +of memory problems. The print quality will of course be poorer but you'll +probably need a magnifying glass to clearly see the difference. + +-size page_setup (only if Linotronic) + +This option specifies the page image size and orientation. +Possible values are a4p (the default), a4l, a5p, a5l, b5p, b5l and a3l. +The "p" stands for portrait and the "l" for landscape. +(Don't confuse the landscape orientation with the -l option which rotates +the output within the page image, regardless of the -size value.) + +-cutmarks or -nocutmarks (only if Linotronic) + +This option controls the appearance of cut marks on Linotronic output. +These marks define the edges of the page image. -cutmarks is the default; +use -nocutmarks to suppress them. + +-p first:final (only for a DVI file) + +Print a selected subrange of pages from the DVI file. +"first" and "final" can select either DVI page numbers (positive integers) +or TeX page numbers. + +Assuming TeX generated the pages "[0] [1] [2.1] [2.2] [3]" +(DVI pages 1 to 5), here are some examples of how you could use -p: + + psprint foo -p 2 --- prints the 2nd DVI page (=[1]) + psprint foo -p '[2]' --- prints [2.1] and [2.2] + psprint foo -p :4 --- prints the first four pages + psprint foo -p '1:[2]' --- also prints the first four pages + psprint foo -p 4: --- prints the last two pages + psprint foo -p '[2.2]:' --- also prints the last two pages + +Note the need to enclose a TeX page specification in single quotes. +Note also that "first" and "final" are optional; they default to +the first and last DVI pages respectively. +Omitting ":final" entirely sets "final" equal to "first". + +A TeX page specification is of the form [i0.i1...i9]. i0 to i9 are +integers separated by periods and represent the 10 counter values that +TeX stores with each DVI page. Any number of these integers may be absent +and trailing periods may be omitted. An absent integer will match any +value in the corresponding counter. +Note that more than one DVI page may match a particular TeX page +specification. If "first" is a TeX page then the LOWEST matching DVI page +is selected, and if "final" then the HIGHEST matching page is selected. + +-i increment (only for a DVI file) + +Assuming f is the first DVI page selected (where f is either 1 or the start +of a -p subrange) then an increment of i tells PSPRINT to print pages +f, f+i, f+2i, f+3i, ... , f+ni, where f+ni is <= the final DVI page selected. +The primary use of -i is to simplify the printing of a document on +both sides of the paper. For example, if foo.dvi has 8 pages then the +following steps will produce a two-sided document on a LaserWriter: + + 1. psprint foo -i 2 -noflag # prints DVI pages 7, 5, 3, 1 + Note that -reverse is the default printing order for a LaserWriter. + + 2. Remove the 4 pages from the output tray and carefully put them back + into the input cassette so that page 1 remains face up and its + top edge goes into the printer first. (If foo.dvi had 7 pages then + you would only need to remove the top 3 pages from the output tray.) + + 3. psprint foo -i 2 -p 2: -norev # prints DVI pages 2, 4, 6, 8 + +Note that the use of -rev or -norev with -i has no effect on WHICH pages +are printed; it simply changes the ORDER in which they are done. + +-reverse or -noreverse (only for a DVI file) + +Use -reverse to force PSPRINT to print pages in descending order, +or -noreverse to force PSPRINT to print pages in ascending order. +By default PSPRINT prints DVI pages in an order determined by the type of +printer you are using. The Apple LaserWriter stacks output sheets face up, +so PSPRINT normally prints pages in reverse order so that your output will +be automatically collated. The PrintServer 40 stacks the output face down, +so PSPRINT normally prints pages in ascending order. The default order +on the Linotronic is largely irrelevant, since this printer produces pages +on a continuous roll of paper (the default used is ascending order). + +-conserve or -noconserve (only for a DVI file) + +Use -conserve to force PSPRINT to conserve the printer's virtual memory +at the expense of creating a larger output file (character bitmaps will be +downloaded more often). On a Linotronic -conserve is the default; +on a LaserWriter or PrintServer -noconserve is the default. + +-ho dimension and -vo dimension (only for a DVI file) + +These options allow you to shift the printed location of each page +according to the given dimensions. For example, "-ho -.5in" would +move each printed page half an inch to the left. +A "dimension" is any integer or real number (possibly negative) followed +by a two-letter unit: in,cm,mm,pc,pt,bp,px (same as those for -u). + +-m number (only for a DVI file) + +Override the DVI magnification with a number 1000 times the desired +magnification. The given number should correspond to one of +TeX's \magstep values; see chapter 4 of The TeXbook. + +-u units (only for a DVI file) + +Set the units of dimensions displayed in some PSPRINT messages +(e.g., if the page is off the paper). Legal units are: + in for inches (the default) + cm for centimetres (2.54cm = 1in) + mm for millimetres (25.4mm = 1in) + pt for points (72.27pt = 1in) + pc for picas (12pc = 1pt) + bp for big points (72bp = 1in) + px for pixels (the Apple LaserWriter has 300 pixels per inch) + +-s (only for a DVI file) + +Display statistics on the number of rules/fonts/characters on each page. + +-l + +To get "landscaped" output instead of the normal "portrait" output. +If given a DVI file, PSPRINT will check each page to make sure it fits +within the rotated paper. + +-c number + +To specify up to 25 copies. +Use of this facility is not encouraged. Note in particular that +copies of a multiple-page document will NOT be collated. + +-n string (only if LaserWriter or Linotronic) + +To include the given string on your flag page. + +-q string + +To override the default queue used by PSPRINT. +(Some sites may have more than one printer of the same type.) + +-o file + +To send the PostScript code generated by PSPRINT to a file rather than +to a printer. Since PSPRINT generates device-specific PostScript code +you should only send this file to a PostScript printer of the type +that PSPRINT intended to use. + +Errors +------ +PSPRINT may detect certain errors while translating a DVI file. +The sort of errors you are most likely to see include: + + Page off paper (paper is ... + The current page contains material beyond one or more paper edges. + Use DVItoVDU to see where the problem lies. + + Couldn't open font file: ... + Your DVI file uses a font at a non-existent magnification. + Try a different font magnification in your source file. + + Couldn't open \special file: ... + PSPRINT could not locate the given \special file. + Check the file's spelling and/or directory location. + +Error messages apply to the most recently displayed DVI/TeX page. +Any message that does not make sense probably indicates some sort of bug. +Please save a copy of the input file and report the problem to your +local TeXnician. + +If a DVI file uses a large number of fonts (or a few very large fonts) +then you might get an error page with the message "VMerror". +This indicates that PostScript's "virtual memory" has been exhausted, +and the rest of your job will be flushed. +This problem is unlikely to worry most people, particularly on the +PrintServer 40 which has much more VM than the LaserWriter or Linotronic. +If the problem does occur, there are a few things you can try: + + --- On a LaserWriter or PrintServer 40, try printing a few pages + at a time, or use -conserve. + --- On a Linotronic, try using -lowres. + (Note that -conserve is the default for this device.) + +An error in a PostScript program should produce some sort of message on +your printed output. If this happens a lot, go back and read the +PostScript Reference Manual more carefully. + +PostScript Fonts +---------------- +PSPRINT allows the use of PostScript fonts in a TeX or LaTeX document. +Such fonts can be used at any desired size and no character bitmaps need +to be downloaded since the shape information is resident in the printer. +The necessary typesetting information required by PSPRINT is extracted +from TFM files (TeX Font Metric files). A TFM file name beginning +with "ps-" is used to indicate a resident PostScript font. + +Each type of PostScript printer provides a different set of fonts. +To be able to use a particular PostScript font you need to know the +name of its corresponding TFM file and whether it actually exists in +the printer you want to use. For each PostScript printer currently +supported there exists a file containing just such information: + + $tex_ps/lw_fonts.ps --- converts TFM names into LaserWriter fonts + $tex_ps/lino_fonts.ps --- converts TFM names into Linotronic 300 fonts + $tex_ps/ps40_fonts.ps --- converts TFM names into PrintServer 40 fonts + +PSPRINT also uses these files, so you can be reasonably confident +about the validity of their contents. +(The above file names assume that the environment variable tex_ps points +to the public directory in which various PSPRINT-related files reside. +To discover what tex_ps is at your site, type "which psprint" and +examine the first few lines of the indicated file.) + +There are some important differences between PostScript fonts and +the Computer Modern fonts normally used with TeX: + + --- PostScript fonts usually contain up to 256 characters, with many + empty locations. Computer Modern fonts also have up to 256 characters + but typically use only the first 128 locations (with very few empty). + --- When a PostScript font is scaled to the same design size as a CM font + it tends to look darker and larger. You need to be a bit careful + when mixing the two font designs. + --- The standard TeX commands for accents and foreign letters need to be + redefined for a PostScript text font. The file $tex_ps/pstext.tex + contains the required macro definitions; note that a few commands + (\j, \aa, \AA, \t) cannot be used at all. Another file, + $tex_ps/psfonts.tex, inputs these macros and illustrates the use + (and abuse) of PostScript fonts in a TeX document. + +PostScript Graphics +------------------- +PSPRINT allows the inclusion of PostScript graphics using TeX's \special +command. The \special argument is interpreted as a file name, possibly +followed by a space and additional PostScript text that will be treated +as a separate line at the start of the given file. +For example, "\special{figure.ps 2 1 scale}" will cause PSPRINT to copy +a line containing "2 1 scale" to the temporary output file, followed by +the contents of figure.ps, a file assumed to be in your current directory +and containing some sort of PostScript program. (The figure will be +twice as wide as one included by \special{figure.ps}.) +The PSPRINT User Guide has more details. diff --git a/dviware/psprint/unix/pstext.tex b/dviware/psprint/unix/pstext.tex new file mode 100644 index 0000000000..4c0f6bf272 --- /dev/null +++ b/dviware/psprint/unix/pstext.tex @@ -0,0 +1,73 @@ +% \PStext should be used before switching to a PostScript text font. +% It allows the use of the standard macros for foreign letters and accents. +% \PStext is best used inside a group so that these macro definitions +% automatically revert to the standard definitions at the end of the group. +% If it is undesirable to place \PStext inside a group then \CMtext should +% be called before using a Computer Modern text font. + +\def\PStext +{% PostScript foreign language locations: +\chardef\ss="FB% +\chardef\ae="F1% +\chardef\oe="FA% +\chardef\o="F9% +\chardef\AE="E1% +\chardef\OE="EA% +\chardef\O="E9% +\chardef\i="F5% +\chardef\l="F8% +\chardef\L="E8% +\def\j{\write16{No dotless j in this font!}}% +\def\aa{\write16{No a-with-circle in this font!}}% +\def\AA{\write16{No A-with-circle in this font!}}% +% PostScript accent locations: +\def\`##1{{\accent193 ##1}}% +\def\'##1{{\accent194 ##1}}% +\def\v##1{{\accent207 ##1}}% +\def\u##1{{\accent198 ##1}}% +\def\=##1{{\accent197 ##1}}% +\def\^##1{{\accent195 ##1}}% +\def\.##1{{\accent199 ##1}}% +\def\H##1{{\accent205 ##1}}% +\def\~##1{{\accent196 ##1}}% +\def\"##1{{\accent200 ##1}}% +\def\b##1{\oalign{##1\crcr\hidewidth% +\vbox to.2ex{\hbox{\char197}\vss}\hidewidth}}% +\def\c##1{\setbox0\hbox{##1}\ifdim\ht0=1ex\accent203 ##1% +\else{\ooalign{\hidewidth\char203\hidewidth\crcr\unhbox0}}\fi}% +\def\t{\write16{No tie accent in this font!}}% +} + +\def\CMtext +{% Computer Modern foreign language locations: +\chardef\ss="19% +\chardef\ae="1A% +\chardef\oe="1B% +\chardef\o="1C% +\chardef\AE="1D% +\chardef\OE="1E% +\chardef\O="1F% +\chardef\i="10% +\chardef\j="11% +\def\l{\char32l}% +\def\L{\leavevmode\setbox0\hbox{L}\hbox to\wd0{\hss\char32L}}% +\def\aa{\accent23a}% +\def\AA{\leavevmode\setbox0\hbox{h}\dimen0\ht0\advance\dimen0-1ex% +\rlap{\raise.67\dimen0\hbox{\char'27}}A}% +% Computer Modern accent locations: +\def\`##1{{\accent18 ##1}}% +\def\'##1{{\accent19 ##1}}% +\def\v##1{{\accent20 ##1}}\let\^^_=\v% +\def\u##1{{\accent21 ##1}}\let\^^S=\u% +\def\=##1{{\accent22 ##1}}% +\def\^##1{{\accent94 ##1}}\let\^^D=\^% +\def\.##1{{\accent95 ##1}}% +\def\H##1{{\accent"7D ##1}}% +\def\~##1{{\accent"7E ##1}}% +\def\"##1{{\accent"7F ##1}}% +\def\b##1{\oalign{##1\crcr\hidewidth% +\vbox to.2ex{\hbox{\char22}\vss}\hidewidth}}% +\def\c##1{\setbox0\hbox{##1}\ifdim\ht0=1ex\accent24 ##1% +\else{\ooalign{\hidewidth\char24\hidewidth\crcr\unhbox0}}\fi}% +\def\t##1{{\edef\next{\the\font}\the\textfont1\accent"7F\next##1}}% +} diff --git a/dviware/psprint/unix/pswriter.h b/dviware/psprint/unix/pswriter.h new file mode 100644 index 0000000000..25de3d095d --- /dev/null +++ b/dviware/psprint/unix/pswriter.h @@ -0,0 +1,58 @@ +(* PSWriter routines are used by PSDVI to create the PostScript output file. + The following calling sequence is largely determined by the PostScript + definitions that must be prepended to the output: + + OpenOutput + if -h used then OutputHeader + for each page selected do + BeginPage + if not conserving VM then + for each new bitmap font do NewBitmapFont + for each bitmap font used on this page do + BeginBitmapFont + for each new character do LoadBitmap + end + end + OutputPage + for each \special on this page do OutputSpecial + for each font used on this page do + if (conserving VM) and (not PostScript font) then SaveVM + if PostScript font then BeginPostScriptFont else BeginBitmapFont + if (conserving VM) and (not PostScript font) then + for each character used do LoadBitmap + end + if PostScript font then + for each character used do SetPostScriptChar + else + for each character used do SetBitmapChar + end + EndFont + if (conserving VM) and (not PostScript font) then RestoreVM + end + for each rule on this page do SetRule + EndPage + end + CloseOutput +*) + +VAR PSfile : text; (* LoadBitmap routine in FontReader requires access to + output file to write out PostScript char definitions. *) + +FUNCTION OpenOutput (name : string) : BOOLEAN; EXTERNAL; +FUNCTION OutputHeader (name : string) : BOOLEAN; EXTERNAL; +PROCEDURE BeginPage (DVIpage : INTEGER); EXTERNAL; +PROCEDURE NewBitmapFont (VAR fontid : string); EXTERNAL; +PROCEDURE OutputPage (DVIpage : INTEGER); EXTERNAL; +FUNCTION OutputSpecial (VAR name : string; + hpos, vpos : INTEGER) : BOOLEAN; EXTERNAL; +PROCEDURE SaveVM (VAR fontid : string); EXTERNAL; +PROCEDURE BeginBitmapFont (VAR fontid : string); EXTERNAL; +PROCEDURE BeginPostScriptFont (VAR fontname : string; + scaledsize, mag : INTEGER); EXTERNAL; +PROCEDURE SetBitmapChar (ch : CHAR; hpos, vpos, pwidth : INTEGER); EXTERNAL; +PROCEDURE SetPostScriptChar (ch : CHAR; hpos, vpos, pwidth : INTEGER); EXTERNAL; +PROCEDURE EndFont; EXTERNAL; +PROCEDURE RestoreVM; EXTERNAL; +PROCEDURE SetRule (wd, ht, hpos, vpos : INTEGER); EXTERNAL; +PROCEDURE EndPage (DVIpage : INTEGER); EXTERNAL; +PROCEDURE CloseOutput; EXTERNAL; diff --git a/dviware/psprint/unix/pswriter.p b/dviware/psprint/unix/pswriter.p new file mode 100644 index 0000000000..88c71f270f --- /dev/null +++ b/dviware/psprint/unix/pswriter.p @@ -0,0 +1,340 @@ +(* PSWriter defines PostScript output routines used by PSDVI. + The output file consists of calls to various PostScript procedures + defined in a header file prefixed to the output. + Some of the PostScript procedures expect integer arguments that represent + page positions in TeX's coordinate system. Units are in "dots" + (i.e., device pixels, where resolution defines the number of dots per inch). + The origin (0,0) is a dot 1 inch in from both the top and left paper edges. + Horizontal coordinates increase to the right and vertical coordinates + increase down the page. The header file contains the necessary matrix + transformations to convert TeX coordinates back into device coordinates. +*) + +#include 'globals.h'; +#include 'options.h'; +#include 'pswriter.h'; + +CONST O_RDONLY = 0; (* SYSDEP: read-only flag for open *) + maxrbuf = 256; + +TYPE rbuf = PACKED ARRAY [1..maxrbuf] OF CHAR; + +FUNCTION open (VAR path : string; flags, mode : integer) : integer; EXTERNAL; +FUNCTION read (f : integer; VAR buf : rbuf; n : integer) : integer; EXTERNAL; +FUNCTION close(f : integer) : integer; EXTERNAL; + +VAR + curh, curv, (* for SetBitmapChar and SetPostScriptChar *) + stringlen : INTEGER; (* ditto; current string length *) + pendingch : CHAR; (* ditto; terminates current string *) + +(******************************************************************************) + +FUNCTION OpenOutput (name : string) : BOOLEAN; + +(* Returns TRUE if given file can be opened for output. *) + +BEGIN +rewrite(PSfile,name); (* create a new file and open it for writing *) +OpenOutput := TRUE; (* assume given file is created *) +END; (* OpenOutput *) + +(******************************************************************************) + +FUNCTION OutputHeader (name : string) : BOOLEAN; + +(* Returns TRUE if given file can be copied to output. + Returns FALSE if file could not be opened. +*) + +VAR f, length, result, buflen : integer; buf : rbuf; + +BEGIN +(* try and open existing file for reading *) +length := Len(name); +IF length < maxstring THEN name[length] := CHR(0); (* terminate with NULL *) +f := open(name, O_RDONLY, 0); (* read only *) +IF length < maxstring THEN name[length] := ' '; (* restore space *) +IF f >= 0 THEN BEGIN + (* copy f to PSfile *) + REPEAT + buflen := read(f,buf,maxrbuf); + IF buflen > 0 THEN write(PSfile,buf:buflen); + UNTIL buflen <= 0; + result := close(f); + OutputHeader := TRUE; +END +ELSE + OutputHeader := FALSE; (* couldn't open given file *) +END; (* OutputHeader *) + +(******************************************************************************) + +PROCEDURE BeginPage (DVIpage : INTEGER); + +BEGIN +writeln(PSfile,DVIpage:1,' @bop0'); +END; (* BeginPage *) + +(******************************************************************************) + +PROCEDURE NewBitmapFont (VAR fontid : string); + +BEGIN +writeln(PSfile,'/',fontid:Len(fontid),' @newfont'); +END; (* NewBitmapFont *) + +(******************************************************************************) + +PROCEDURE OutputPage (DVIpage : INTEGER); + +BEGIN +writeln(PSfile,DVIpage:1,' @bop1'); +END; (* OutputPage *) + +(******************************************************************************) + +FUNCTION OutputSpecial (VAR name : string; + hpos, vpos : INTEGER) : BOOLEAN; + +(* Returns TRUE if given file can be copied to output. + Returns FALSE if file could not be opened. + name can also include a space and additional PostScript text that will + be prefixed to the given file as a separate line. This allows users to + include a command like "\special{foo.ps 2 2 scale}" in their TeX source. + name is declared to be a variable parameter for efficiency reasons. + hpos and vpos define the page position of the \special command. + It's a good idea to do all specials on a page BEFORE chars and rules so that + users can do nifty things like overlaying TeX text onto a shaded box. +*) + +LABEL 888, 999; + +VAR f, i, j, result, buflen : INTEGER; buf : rbuf; fspec : string; + +BEGIN +(* check name for optional space (indicating additional PostScript text) *) +i := 0; +fspec := ' '; (* SYSDEP: fill with spaces *) +WHILE i < maxstring DO BEGIN + IF name[i] = ' ' THEN goto 888; + fspec[i] := name[i]; (* extract file spec from name *) + i := i + 1; +END; +888: +(* SYSDEP: test if i = 0 otherwise open will succeed and we'll read + some file (fspec = all spaces) full of mildly interesting junk! +*) +IF i = 0 THEN BEGIN + OutputSpecial := FALSE; goto 999; +END; +(* try and open existing file for reading *) +IF i < maxstring THEN fspec[i] := CHR(0); (* terminate with NULL *) +f := open(fspec, O_RDONLY, 0); (* read only *) +IF i < maxstring THEN fspec[i] := ' '; (* restore space *) +IF f >= 0 THEN BEGIN + writeln(PSfile, hpos:1, ' ', vpos:1, ' p'); + writeln(PSfile, '@bsp'); + (* use j to see if there is optional text after file name *) + j := maxstring - 1; + WHILE name[j] = ' ' DO j := j - 1; + j := j + 1; + IF i < j THEN BEGIN + (* name[i] is first ' '; skip this and copy rest of name to output *) + i := i + 1; + WHILE i < j DO BEGIN + write(PSfile,name[i]); + i := i + 1; + END; + writeln(PSfile); (* text becomes first line of file *) + END; + (* copy f to PSfile *) + REPEAT + buflen := read(f,buf,maxrbuf); + IF buflen > 0 THEN write(PSfile,buf:buflen); + UNTIL buflen <= 0; + result := close(f); + writeln(PSfile, '@esp'); + OutputSpecial := TRUE; +END +ELSE + OutputSpecial := FALSE; (* couldn't open given file *) +999: +END; (* OutputSpecial *) + +(******************************************************************************) + +PROCEDURE SaveVM (VAR fontid : string); + +BEGIN +writeln(PSfile,'/',fontid:Len(fontid),' @saveVM'); +END; (* SaveVM *) + +(******************************************************************************) + +PROCEDURE BeginPostScriptFont (VAR fontname : string; + scaledsize, mag : INTEGER); + +(* Output PostScript code to scale and set a resident PostScript font. + The fontname will be the name of a TFM file (beginning with psprefix value). + This TFM name will need to be converted into a PostScript font name. + The scaledsize and mag parameters represent the desired size of the font. +*) + +BEGIN +(* sp will convert scaled points to dots *) +writeln(PSfile, scaledsize:1, ' sp ', mag:1, ' 1000 div mul ', + fontname:Len(fontname), ' PSfont'); +(* initialize some globals for first SetPostScriptChar in this font *) +curh := 999999999; +curv := 999999999; +stringlen := 0; +pendingch := '?'; +END; (* BeginPostScriptFont *) + +(******************************************************************************) + +PROCEDURE SetPostScriptChar (ch : CHAR; hpos, vpos, pwidth : INTEGER); + +(* Similar to SetBitmapChar but we cannot use RELATIVE horizontal positioning + because the advance widths of characters in a PostScript font are not + an integral number of dots, and we must avoid accumulated rounding errors. +*) + +BEGIN +IF curv = vpos THEN BEGIN (* don't update v position *) + IF curh <> hpos THEN BEGIN (* update h position *) + stringlen := 0; + writeln(PSfile,')',pendingch); + write(PSfile,hpos:1,'('); + pendingch := 'H'; + END; +END +ELSE BEGIN (* update h and v position *) + IF stringlen > 0 THEN BEGIN + stringlen := 0; + writeln(PSfile,')',pendingch); + END; + write(PSfile,hpos:1,' ',vpos:1,'('); + pendingch := 'S'; +END; +IF (ch >= ' ') AND (ch < CHR(127)) THEN BEGIN + IF (ch = '(') OR (ch = ')') OR (ch = '\') THEN (* prefix (,),\ with \ *) + write(PSfile,'\',ch) + ELSE + write(PSfile,ch); +END +ELSE + (* put out 3 octal digits representing ch *) + write(PSfile,'\', CHR(ORD('0') + (ORD(ch) DIV 64)), + CHR(ORD('0') + ((ORD(ch) DIV 8) MOD 8)), + CHR(ORD('0') + (ORD(ch) MOD 8)) ); +(* update current page position and string length for next call *) +curh := hpos + pwidth; +curv := vpos; +stringlen := stringlen + 1; +IF (stringlen MOD 72) = 0 THEN writeln(PSfile,'\'); +END; (* SetPostScriptChar *) + +(******************************************************************************) + +PROCEDURE BeginBitmapFont (VAR fontid : string); + +BEGIN +writeln(PSfile,fontid:Len(fontid),' sf'); +(* Initialize some globals for first SetBitmapChar in this font. + This is not relevant when BeginBitmapFont is used before OutputPage. +*) +curh := 999999999; +curv := 999999999; +stringlen := 0; +pendingch := '?'; +END; (* BeginBitmapFont *) + +(******************************************************************************) + +PROCEDURE SetBitmapChar (ch : CHAR; hpos, vpos, pwidth : INTEGER); + +BEGIN +IF curv = vpos THEN BEGIN (* don't update v position *) + IF curh <> hpos THEN BEGIN (* update h position (kern or space) *) + stringlen := 0; + writeln(PSfile,')',pendingch); + write(PSfile,hpos-curh:1,'('); + pendingch := 'h'; + END; +END +ELSE BEGIN (* update h and v position *) + IF stringlen > 0 THEN BEGIN + stringlen := 0; + writeln(PSfile,')',pendingch); + END; + write(PSfile,hpos:1,' ',vpos:1,'('); + pendingch := 's'; +END; +IF (ch >= ' ') AND (ch < CHR(127)) THEN BEGIN + IF (ch = '(') OR (ch = ')') OR (ch = '\') THEN (* prefix (,),\ with \ *) + write(PSfile,'\',ch) + ELSE + write(PSfile,ch); +END +ELSE + (* put out 3 octal digits representing ch *) + write(PSfile,'\', CHR(ORD('0') + (ORD(ch) DIV 64)), + CHR(ORD('0') + ((ORD(ch) DIV 8) MOD 8)), + CHR(ORD('0') + (ORD(ch) MOD 8)) ); +(* update current page position and string length for next call *) +curh := hpos + pwidth; +curv := vpos; +stringlen := stringlen + 1; +IF (stringlen MOD 72) = 0 THEN writeln(PSfile,'\'); +END; (* SetBitmapChar *) + +(******************************************************************************) + +PROCEDURE EndFont; + +(* Terminate the last "h v(..." or "dh(..." for the current font. *) + +BEGIN +IF stringlen > 0 THEN writeln(PSfile,')',pendingch); +END; (* EndFont *) + +(******************************************************************************) + +PROCEDURE RestoreVM; + +BEGIN +writeln(PSfile,'@restoreVM'); +END; (* RestoreVM *) + +(******************************************************************************) + +PROCEDURE SetRule (wd, ht, hpos, vpos : INTEGER); + +(* Output some PostScript to set the given rule at the given position. *) + +BEGIN +writeln(PSfile, wd:1, ' ', ht:1, ' ', hpos:1, ' ', vpos:1, ' r'); +END; (* SetRule *) + +(******************************************************************************) + +PROCEDURE EndPage (DVIpage : INTEGER); + +(* Output some PostScript to end the current page. *) + +BEGIN +writeln(PSfile, DVIpage:1, ' @eop'); +END; (* EndPage *) + +(******************************************************************************) + +PROCEDURE CloseOutput; + +(* Output some final PostScript. *) + +BEGIN +writeln(PSfile, '@end'); +(* no need to close PSfile *) +END; (* CloseOutput *) diff --git a/dviware/psprint/unix/random.ps b/dviware/psprint/unix/random.ps new file mode 100644 index 0000000000..3e69f4c16d --- /dev/null +++ b/dviware/psprint/unix/random.ps @@ -0,0 +1,39 @@ +% This file is inserted into the PSPRINT User Guide using \special. +% It plots 100 random dots. + +72 72 scale % units now inches + +% uncomment the next line if you want to "psprint random.ps" +% 2 2 translate + +/xlen 1.3 def % length of x axis +/ylen 1.3 def % length of y axis +newpath +0 0 moveto xlen 0 rlineto % x axis +0 0 moveto 0 ylen rlineto % y axis +.01 setlinewidth +stroke % draw axes + +/fontsize 10 72 div def % use 10pt font for labels +/Helvetica findfont +fontsize scalefont setfont +fontsize neg dup moveto (0) show +fontsize neg ylen moveto (1) show +xlen fontsize 2 div add fontsize neg moveto (1) show + +% draw 100 random dots + +/randlim 2 31 exp 1 sub def % rand will return integer from 0 to 2^31 - 1 +newpath +1 1 100 % do the following procedure 100 times +{ pop % we don't use control variable + /x rand randlim div xlen mul def % x is real number from 0 to xlen + /y rand randlim div ylen mul def % y is real number from 0 to ylen + x y moveto + x y lineto % create a dot +} for +1 setlinecap % round line ends +.04 setlinewidth % diameter of dots +stroke % draw all dots + +showpage diff --git a/dviware/psprint/unix/setmargins.ps b/dviware/psprint/unix/setmargins.ps new file mode 100644 index 0000000000..e43acacd9d --- /dev/null +++ b/dviware/psprint/unix/setmargins.ps @@ -0,0 +1,7 @@ +% Permanently change LaserWriter's margin settings. +% Use info.ps to see the current margin settings. + +serverdict begin 0 exitserver +statusdict begin + 20 -10 setmargins % increase top by 20px and reduce left by 10px +end diff --git a/dviware/psprint/unix/test.tex b/dviware/psprint/unix/test.tex new file mode 100644 index 0000000000..2811adcdc9 --- /dev/null +++ b/dviware/psprint/unix/test.tex @@ -0,0 +1,13 @@ +% A small test file: the top left corner of the upper rule should be +% 1in from both the top and left edges of the paper. + +\nopagenumbers +\topskip=0pt + +\hrule width 2in height 1mm + +\vskip 4in + +\hrule width 4in height 1mm + +\bye diff --git a/dviware/psprint/unix/tex.ps b/dviware/psprint/unix/tex.ps new file mode 100644 index 0000000000..5e7de3fb8c --- /dev/null +++ b/dviware/psprint/unix/tex.ps @@ -0,0 +1,236 @@ +% Prologue for a DVI job. +% It assumes psprint has defined dev (string), land (bool) and res (int). + +dev (LW) eq % LaserWriter? +{ land + { % /landscape given + % rotate/scale/translate can cause scaling problems, so use setmatrix: + version cvr 38.0 le + { [ 0 -1 1 0 245 3135 ] setmatrix } % LaserWriter + { version cvr 47.0 lt + { [ 0 -1 1 0 235 3130 ] setmatrix } % LaserWriter Plus + { [ 0 -1 1 0 235 3160 ] setmatrix } % LaserWriter II NTX + % add y to move origin down by y pixels + % add x to move origin left by x pixels + ifelse } ifelse + } + { % /landscape not given + % scale/translate can cause scaling problems, so use setmatrix: + version cvr 38.0 le + { [ 1 0 0 1 235 190 ] setmatrix } % LaserWriter + { version cvr 47.0 lt + { [ 1 0 0 1 235 215 ] setmatrix } % LaserWriter Plus + { [ 1 0 0 1 235 265 ] setmatrix } % LaserWriter II NTX + % add x to move origin right by x pixels + % add y to move origin down by y pixels + ifelse } ifelse + } ifelse +} if + +dev (PS40) eq % PrintServer? +{ land + { [ 1 0 0 1 300 300 ] setmatrix % /landscape given + } + { [ 0 1 -1 0 3210 300 ] setmatrix % /landscape not given + } ifelse +} if + +dev (LINO) eq % Linotronic? +{ land + { initmatrix % /landscape given + 90 rotate % rotate axes 90deg anticlockwise + 72 res div dup neg scale % units now dots (y increases to right) + res res translate % move to TeX origin + + % setmatrix won't work properly with a3/a4/a5/b5 page setups + % [1 0 0 1 1270 margin 72 div 1270 mul add 1270] setmatrix % res=1270 + % [2 0 0 2 1270 margin 72 div 1270 mul add 1270] setmatrix % res=635 + } + { initmatrix % /landscape not given + newpath clippath pathbbox % push LLx LLy URx URy + /paperht exch 72 div def % paper height in inches (URy = ht in pts) + pop pop pop % URx LLy LLx + 72 res div dup neg scale % units now dots (y increases down page) + res paperht res mul neg res add + translate % move to TeX origin + + % setmatrix won't work properly with a3/a4/a5/b5 page setups + % [0 1 -1 0 paperht 1270 mul 1270 sub % res=1270 + % margin 72 div 1270 mul add 1270] setmatrix + % [0 2 -2 0 paperht 1270 mul 1270 sub % res=635 + % margin 72 div 1270 mul add 1270] setmatrix + } ifelse +} if + +/mtrx 6 array def +mtrx currentmatrix pop % save our new transformation matrix + +/@newfont % initialize new font dict +{ /fontid exch def + fontid 7 dict def + fontid load begin + /FontType 3 def + /FontMatrix [1 0 0 -1 0 0] def % -1 because y scale is negative + /FontBBox [0 0 1 1] def + /BitMaps 128 array def + /BuildChar {CharBuilder} def + /Encoding 128 array def + 0 1 127 {Encoding exch /.notdef put} for + end + fontid fontid load definefont pop +} def + +% @saveVM and @restoreVM are only used if we are conserving VM +% by downloading font bitmaps more often: + +/@saveVM % save state of VM before using font +{ /prefontVM save def + @newfont +} def + +/@restoreVM {prefontVM restore} def + +% The char data, a bitmap descriptor, is an array with 6 elements: + +/ch-image {ch-data 0 get} def % the hex string image +/ch-width {ch-data 1 get} def % the number of pixels across +/ch-height {ch-data 2 get} def % the number of pixels tall +/ch-xoff {ch-data 3 get} def % number of pixels to left of origin +/ch-yoff {ch-data 4 get} def % number of pixels below origin +/ch-advw {ch-data 5 get} def % advance width + +% The following character builder looks up the char data in the BitMaps array +% and paints the character: + +/CharBuilder % image one char +{ /ch-code exch def % save the char code + /font-dict exch def % and the font dict + /ch-data font-dict /BitMaps get + ch-code get def + ch-advw 0 + ch-xoff neg ch-height ch-yoff sub 1 sub neg % -xo , -(ht-yo-1) + ch-width ch-xoff sub 1 sub ch-yoff % (wd-xo-1) , yo + setcachedevice + ch-width ch-height true + [1 0 0 -1 ch-xoff ch-yoff] % bitmap sent top to bottom + {ch-image} + imagemask +} def + +/sf {setfont} def % set current font + +/dc % define new character +{ /ch-code exch def + /ch-data exch def + + % The following code should be enabled if you have an old LaserWriter. + % It attempts to overcome a bug that causes the printer to crash + % and print a test page rather then report a VMerror. + % + % vmstatus % returns: savelevel vmused vmmax + % 10000 sub gt % is vmused > (vmmax-10000)? + % { pop VMERROR } % causes error message (avoiding crash) + % { pop } % pop savelevel + % ifelse + + currentfont /BitMaps get ch-code ch-data put + currentfont /Encoding get ch-code + dup ( ) cvs cvn put % generate unique name +} bind def + +/@bop0 {pop} def % begin DVI page n + +/@bop1 % begin setting DVI page n +{ pop % throw away page number + initgraphics % start with a clean slate + mtrx setmatrix % switch to our TeX coordinate system + /prepageVM save def % save state of VM at start of page +} def + +/@eop % end DVI page n +{ pop % throw away page number + prepageVM restore % restore VM to state at start of page + showpage +} def + +/@end { } def % end of file + +% h and s are used to typeset downloaded bitmap fonts: + +/h {exch 0 rmoveto show} bind def % move right by dh and show (...) + +/s {3 1 roll moveto show} bind def % move to h,v and show (...) + +% H and S are used to typeset resident PostScript fonts. +% We can't use relative horizontal positioning because the advance widths in +% a PostScript font are not integers and rounding errors would accumulate: + +/H {exch v moveto show} bind def % move to h,v and show (...) + +/S % ditto, and save v position +{ 3 1 roll dup /v exch def + moveto show +} bind def + +% Some fine-tuning of the code used to draw a rule is necessary: + +dev (LW) eq % LaserWriter? +version cvr 38.0 le and % and version <= 38.0? +{ + /r % set a wd by ht rule at h,v + { newpath + 1 add moveto % move to h,v+1 (don't ask me why) + /ht exch 1 sub def % reduce height by 1 + /wd exch 1 sub def % ditto for width + wd 0 rlineto + 0 ht neg rlineto + wd neg 0 rlineto + fill + } bind def +} +{ + /r % set a wd by ht rule at h,v + { newpath + moveto % move to h,v + /ht exch 1 sub def % reduce height by 1 + /wd exch 1 sub def % ditto for width + wd 0 rlineto + 0 ht neg rlineto + wd neg 0 rlineto + fill + } bind def +} ifelse + +% Following procedures are invoked as the result of a \special command. +% We change all scaling and graphics back to defaults, but shift the origin +% to the current position on the page: + +/p {moveto} bind def % move to h,v + +/@bsp % begin special mode +{ gsave + /prespecialVM save def % save showpage, TeX procedures etc. + currentpoint transform + initgraphics itransform translate + land { 90 rotate } if % rotate axes if /landscape given + /showpage { } def % user does not have to remove showpage +} bind def + +/@esp % end special mode +{ prespecialVM restore % restore saved showpage value etc. + grestore +} bind def + +% Here are the definitions needed to handle resident PostScript fonts: + +/sp % scaled pts to dots +{ 16#10000 div % scaled pts to pts + res mul 72.27 div % pts to dots +} bind def + +/PSfont % uses dot size and TFM name +{ dup /Times-Slanted eq + {pop /Times-Roman findfont [1 0 .268 -1 0 0] makefont exch scalefont setfont} + {findfont [1 0 0 -1 0 0] makefont exch scalefont setfont} + ifelse +} bind def diff --git a/dviware/psprint/unix/text.ps b/dviware/psprint/unix/text.ps new file mode 100644 index 0000000000..d3ff19e932 --- /dev/null +++ b/dviware/psprint/unix/text.ps @@ -0,0 +1,83 @@ +% Prologue for a -text job. +% It assumes psprint has defined land and dev. +% Every character after this file (until ^D) will be treated as a printing +% character (or control character) instead of being interpreted as PostScript. + +land +{ /setlocation % if /landscape + { 0 11.7 72 mul translate % shift origin up 11.7in + -90 rotate % rotate axes 90deg clockwise + 72 0 translate % 1in left margin + 0 535 moveto % start of top line + /line 0 def % initialize line counter + /char 0 def % initialize chars/line counter + } bind def + /maxline 50 def % maximum lines per page + /maxchar 132 def % maximum chars per line + /interline -10 def % baseline skip + /Courier findfont 9 scalefont setfont % use 9pt Courier +} +{ /setlocation % if no /landscape + { 72 0 translate % 1in left margin + 0 764 moveto % start of top line + /line 0 def % initialize line counter + /char 0 def % initialize chars/line counter + } bind def + /maxline 66 def % maximum lines per page + /maxchar 80 def % maximum chars per line + /interline -11 def % baseline skip + /Courier findfont 10 scalefont setfont % use 10pt Courier +} ifelse + +/formfeed { line 0 gt { showpage setlocation } if } bind def + +/linefeed +{ /char 0 def % reset chars/line counter + /line line 1 add def % increment line counter + line maxline eq % line = max lines per page? + { formfeed } % if so, show page + { currentpoint pop neg interline rmoveto } % else start next line + ifelse +} bind def + +/backspace +{ /char char 1 sub def + char 0 ge { charwidth neg 0 rmoveto } if % move back one character +} def + +/showchar +{ currentchar 0 thischar put % put thischar into 1-char string + /char char 1 add def % increment chars/line counter + char maxchar le { currentchar show } if % ignore chars > maxchar +} bind def + +/eachchar +{ infile read not {exit} if % get next char + /thischar exch def % save it in thischar + thischar 32 ge % thischar >= space? + { showchar } % if so, show it + { thischar 8 eq % or does thischar = backspace? + { backspace } + { thischar 10 eq % or does thischar = linefeed? + { linefeed } + { thischar 12 eq % or does thischar = formfeed? + { formfeed } + { % ignore any other control char + } ifelse + } ifelse + } ifelse + } ifelse +} bind def + +(%stdin) (r) file /infile exch def +/currentchar 1 string def +setlocation +/charwidth (a) stringwidth pop def + +/charloop +{ {eachchar} loop + line 0 gt { showpage } if % flush last page if necessary + dev (LW) eq { @bannerpage } if % print banner page if LaserWriter +} def + +charloop diff --git a/dviware/psprint/unix/two.ps b/dviware/psprint/unix/two.ps new file mode 100644 index 0000000000..e2ecde4bf7 --- /dev/null +++ b/dviware/psprint/unix/two.ps @@ -0,0 +1,119 @@ +% Prologue for a -two job. +% It assumes psprint has defined fspec and dev. +% The following definitions produce two logical pages (80 cols by 60 lines) +% on a single landscaped sheet of A4 paper. +% Both pages have a headline showing fspec and page #. +% Every character after this file (until ^D) will be treated as a printing +% character (or control character) instead of being interpreted as PostScript. + +/maxlines 60 def % maximum lines per logical page +/maxchar 80 def % maximum chars per line +/interline -8 def % baseline skip +/Courier findfont % Courier font (fixed-width chars) +7 scalefont setfont % at 7pt +/inch { 72 mul } def % convert inches to big points +/topline { 7.3 inch } def % vertical location of top line (not headline) + +/page1pos +{ 0 11.7 inch translate % shift origin up 11.7 inch (= A4 width) + -90 rotate % rotate axes 90deg clockwise + 1 inch 0 translate % 1 inch left margin for 1st logical page + 0 topline moveto % start of first line + /line 0 def % initialize line counter + /char 0 def % initialize chars/line counter +} bind def + +/page2pos +{ 5.1 inch 0 translate % set up left margin for 2nd logical page + 0 topline moveto % start of first line + /line maxlines def % in case formfeed occurred in 1st logical page +} bind def + +/pagenum 0 def % initialize logical page number + +/headline +{ gsave % save current pos and font + /Courier-Bold findfont 10 scalefont setfont % use Courier-Bold at 10pt + 0 topline moveto % move to top left corner + 0 interline 3 mul neg rmoveto % move up 3 lines + fspec show + % increment page number and show it right justified + /pagenum pagenum 1 add def + /pagestr pagenum 10 string cvs def + charwidth maxchar mul topline moveto % move to top right corner + (p.) stringwidth pop + pagestr stringwidth pop add neg % move left by page # width + interline 3 mul neg % move up 3 lines + rmoveto + (p.) show pagestr show + grestore % restore pos and font +} bind def + +/formfeed % start next logical page unless already there +{ line 0 gt + { line maxlines lt + { headline page2pos } % 0 < line < maxlines + { line maxlines gt + line maxlines 2 mul lt and + { headline showpage page1pos } if % maxlines < line < 2 * maxlines + } ifelse + } if +} bind def + +/linefeed +{ /char 0 def % reset chars/line counter + /line line 1 add def % increment line counter + line maxlines eq % if end of 1st page + { headline % show 1st headline + page2pos } % and start 2nd page + { line maxlines 2 mul eq % elsif end of 2nd page + { headline % then show 2nd headline + showpage page1pos } % and show both pages + { currentpoint pop neg interline rmoveto % else start next line + } ifelse + } ifelse +} bind def + +/backspace +{ /char char 1 sub def + char 0 ge { charwidth neg 0 rmoveto } if % move back one character +} def + +/showchar +{ currentchar 0 thischar put % put thischar into 1-char string + /char char 1 add def % increment chars/line counter + char maxchar le { currentchar show } if % ignore chars > maxchar +} bind def + +/eachchar +{ infile read not {exit} if % get next char + /thischar exch def % save it in thischar + thischar 32 ge % thischar >= space? + { showchar } % if so, show it + { thischar 8 eq % or does thischar = backspace? + { backspace } + { thischar 10 eq % or does thischar = linefeed? + { linefeed } + { thischar 12 eq % or does thischar = formfeed? + { formfeed } + { % ignore any other control char + } ifelse + } ifelse + } ifelse + } ifelse +} bind def + +(%stdin) (r) file /infile exch def +/currentchar 1 string def +/charwidth ( ) stringwidth pop def % assume fixed-width font +page1pos % start 1st page + +/charloop +{ {eachchar} loop + line 0 gt + { headline showpage } % flush last sheet with only 1st logical page + if + dev (LW) eq { @bannerpage } if % print banner page if LaserWriter +} def + +charloop diff --git a/dviware/psprint/unix/userguide.tex b/dviware/psprint/unix/userguide.tex new file mode 100644 index 0000000000..fe3accffbf --- /dev/null +++ b/dviware/psprint/unix/userguide.tex @@ -0,0 +1,563 @@ +% LaTeX source for PSPRINT User Guide. +% System-dependent details are indicated by the string "SYSDEP". +% Cross references are indicated by the string "XREF". +% Feel free to make modifications applicable to your site. + +\documentstyle[11pt]{article} + +\nofiles % no auxiliary output + +% make sure leading/trailing spaces work correctly in \verb +{\obeyspaces\gdef {\leavevmode\null\enskip\null}} + +% 1 inch margins at left and right: +\oddsidemargin=0in +\evensidemargin=0in +\textwidth=6.25truein % A4 paper is 8.25in wide + +% 1 inch margins at top and bottom: +\headheight=0pt +\headsep=0pt +\topmargin=0in +\textheight=9.7in % A4 paper is 11.7in high + +\parindent=0pt +\parskip=\medskipamount +\renewcommand\labelitemii{ } % don't use en-dash in nested itemize +\itemsep=0pt + +\def\DVItoVDU{DVIto\kern-.15em VDU} +\def\aligneddots{\leaders\hbox to .75em{\hss.\hss}\hfill} + +\begin{document} + +\vspace*{\fill} + +\begin{center} +\Huge\bf PSPRINT User Guide\\ [3mm] +\normalsize\bf Version 3.0 for Pyramid/OSx\\ +\bf Andrew Trevorrow, October 1988 +\end{center} + +\bigskip +\bigskip + +The PSPRINT command drives a variety of PostScript printers +and can be used to print a DVI file (produced by \TeX\ or \LaTeX), +a raw PostScript file, or an ordinary text file. +The currently supported printers include the Apple LaserWriter, +the Linotronic~300 and DEC's PrintServer~40. + +\bigskip +\begin{center} +\bf Contents +\end{center} + + % XREF: check that page #s are up-to-date +\TeX\ Output \aligneddots\ 1\\ +PostScript Output \aligneddots\ 1\\ +Text Output \aligneddots\ 1\\ +Command Options \aligneddots\ 2\\ +Error Messages \aligneddots\ 5\\ +Using PostScript Fonts \aligneddots\ 6\\ +Using PostScript Graphics \aligneddots\ 7 + +\vspace*{\fill} + +\thispagestyle{empty} + +\newpage +\setcounter{page}{1} + +\subsection*{\TeX\ Output} + +PSPRINT looks for a DVI file by default. To print \verb|foo.dvi|, simply type: +\begin{center} +\verb|psprint foo| +\end{center} +PSPRINT will translate \verb|foo.dvi| into +a temporary PostScript file called \verb|foo.tmp|. +The DVI and \TeX\ page numbers are displayed as each page is translated. +(The order in which pages are translated depends on the PostScript +device being used.) +If no errors are found, the temporary file is automatically sent to the +appropriate queue where it is printed (and then deleted). + +\subsection*{PostScript Output} + +PostScript is a complete programming language with a powerful set of operators +for manipulating text and graphics. A PostScript program is an ordinary text +file. If you give it a name like \verb|foo.ps| then sending +it to the printer is simple: +\begin{center} +\verb|psprint foo.ps| +\end{center} +If you decide to use some other file extension you'll have to add the +\verb|-ps| option. +The final section in this document % XREF +describes how to merge a PostScript file with a \TeX\ source file. +People who want to write PostScript programs will need to get the +{\sl PostScript Language Reference Manual\/} and the +{\sl PostScript Language Tutorial and Cookbook}. Both books are by +Adobe Systems Incorporated and published by Addison-Wesley. + +\subsection*{Text Output} + +To print a normal text file, just use any file extension except +\verb|.dvi| or \verb|.ps|: +\begin{center} +\verb|psprint foo.lis|~~~or~~~\verb|psprint foo.dat|~~~or~~~\dots +\end{center} +The output is {\em not\/} collated. +By default you get 66 lines per page, and any lines more than 80 +characters long are truncated. The \verb|-l| option will +rotate the paper so that you can have lines up to 132 characters long +(but only 50 lines per page). + +Type `\verb|psprint foo.ps -text|' if you want to print a PostScript file +rather than have it interpreted. You'll also have to use \verb|-text| if you +want to print a text file called \verb|foo| but \verb|foo.dvi| also exists. + +The \verb|-two| and \verb|-wide| options are variants of \verb|-text| +that use a smaller font to fit two logical pages on each sheet of +paper. + +These text file facilities may not be available on all types of +printers, especially the Linotronic. + + +\newpage + +\subsection*{Command Options} + +The PSPRINT command can be followed by a variety of options: +\begin{itemize} +\item \verb|-device printer_type| --- +tells PSPRINT which type of PostScript printer to use. +The currently supported \verb|printer_type| values are: + \begin{itemize} + \item + \verb|lw | --- for an Apple LaserWriter (the default)\\ % SYSDEP + \verb|lino| --- for a Linotronic~300\\ + \verb|ps40| --- for DEC's PrintServer~40 + \end{itemize} +\end{itemize} + +These options only take effect if \verb|-device lw|: +\begin{itemize} + +\item \verb|-noflag| --- +prevents PSPRINT producing a flag page. + +\item \verb|-manual| --- +assumes you want to manually feed paper into the LaserWriter. +As soon as the printer sees your job it will wait for you to feed in each +sheet of paper (it will normally wait up to a minute). + +\end{itemize} + +These options only take effect if \verb|-device lino|: +\begin{itemize} + +\item \verb|-lowres| --- +prints a DVI file at low resolution (635 dots per inch). +By default, \TeX\ output on the Linotronic is printed at 1270 dots per inch. +The temporary file created by PSPRINT will typically be very large. +Using \verb|-lowres| reduces both the size of the temporary file +(by roughly three quarters) and the likelihood of memory problems. +The print quality will of course be poorer but you'll +probably need a magnifying glass to see the difference. + +\item \verb|-size page_size| --- +sets the Linotronic page size and orientation. +Possible \verb|page_size| values are +\verb|A4P| (the default), \verb|A4L|, \verb|A5P|, \verb|A5L|, +\verb|B5P|, \verb|B5L| and \verb|A3L|. +The \verb|P| stands for portrait and the \verb|L| for landscape. +(Don't confuse the landscape orientation with \verb|-l| which rotates +the output within the page image, regardless of the \verb|-size| value.) +The portrait orientations are less wasteful of paper. + +\item \verb|-cutmarks| --- +produces small cut marks at the corners of the page image +on Linotronic output. +\verb|-cutmarks| is the default; use \verb|-nocutmarks| to suppress them. + +\end{itemize} + +The following five options override PSPRINT's assumptions +about the format of the input file based on the given file specification: +\begin{itemize} +\item \verb|-dvi | --- for a DVI file. +\item \verb|-ps | --- for a PostScript program. +\item \verb|-text| --- for an ordinary text file. +\item \verb|-two | --- +like \verb|-text| but the output is formatted so that two ``pages'' +(both 60 lines by 80 columns) appear on each sheet of paper. +\item \verb|-wide| --- +like \verb|-text| but the output is formatted so that two wide ``pages'' +(both 60 lines by 132 columns) appear on each sheet of paper. +\end{itemize} + +\newpage + +Some options can only be used with a DVI file: +\begin{itemize} + +\item \verb|-p first:final| --- selects a subrange of pages for printing. +\verb|first| and \verb|final| can select either DVI page numbers +(positive integers) or \TeX\ page numbers. + +A \TeX\ page specification is of the form \verb|[i0.i1...i9]| where +\verb|i0| to \verb|i9| are integers separated by periods and represent the +10 counter values that \TeX\ stores with each DVI page. +Any number of these integers may be absent and trailing periods may be omitted. +An absent integer will match any value in the corresponding counter. +Many DVI pages may match a particular \TeX\ page specification; +if \verb|first| is a \TeX\ page then the {\em lowest\/} +matching DVI page is selected, and if \verb|final| is a \TeX\ page then +the {\em highest\/} matching page is selected. + +Assuming \TeX\ generated the 5 DVI pages `\verb|[0] [1] [2.1] [2.2] [3]|', +here are some examples of how you could use \verb|-p|: + \begin{itemize} + \item + \verb|psprint foo -p 2 | --- prints the 2nd DVI page + (\TeX\ page \verb|[1]|)\\ + \verb|psprint foo -p :4 | --- prints the first four pages\\ + \verb|psprint foo -p 4: | --- prints the last two pages\\ + \verb|psprint foo -p '[2]' | --- prints \verb|[2.1]| and \verb|[2.2]|\\ + \verb|psprint foo -p 1:'[2]' | --- prints the first four pages\\ + \verb|psprint foo -p '[2.2]':| --- prints the last two pages + \end{itemize} +Note that \verb|first| and \verb|final| are optional; they default to +the first and last DVI pages respectively. +Omitting `\verb|:final|' entirely sets \verb|final| equal to \verb|first|. +Note also the need for quote marks around a \TeX\ page specification. + +\item \verb|-i i| --- +prints pages $f,f+i,f+2i,f+3i,\ldots,f+ni$, where +$f$ is the first DVI page selected (either 1 or the start +of a \verb|-p| subrange) and $f+ni$ is less than or equal to +the final DVI page selected. + +The primary use of \verb|-i| is to simplify the printing of a document +on both sides of the paper. For example, if \verb|foo.dvi| has 8 pages then the +following steps will produce a double-sided document on a LaserWriter: + \begin{enumerate} + \item + \verb|psprint foo -i 2 -noflag | --- prints DVI pages 7, 5, 3, 1 + \item + Remove the 4 pages from the output tray and carefully put them back + into the input cassette so that page 1 remains face up and its + top edge goes into the printer first. + (If \verb|foo.dvi| had 7 pages then you would only need to remove the + top 3 pages from the output tray.) + \item + \verb|psprint foo -i 2 -p 2: -norev| --- prints DVI pages 2, 4, 6, 8 + \end{enumerate} +Note that the use of \verb|-reverse| with \verb|-i| has no effect on +{\em which\/} pages are printed; it simply changes the {\em order\/} in +which they are done. + +\item \verb|-reverse| or \verb|-noreverse| --- +forces PSPRINT to print pages in descending or ascending order respectively. +By default PSPRINT prints DVI pages in an order determined by the type of +printer you are using. The Apple LaserWriter stacks output sheets face up, +so PSPRINT normally prints pages in reverse order so that your output will +be automatically collated. The PrintServer 40 stacks the output face down, +so PSPRINT normally prints pages in ascending order. The default order +on the Linotronic is largely irrelevant, since this printer produces pages +on a continuous roll of paper (the default used is ascending order). + +\item \verb|-m n| --- +overrides the DVI magnification; \verb|n| is a positive integer 1000 times +the desired magnification and should match one of \TeX's \verb|\magstep| +values (see chapter 4 of {\sl The \TeX book\/}). + +\item \verb|-s| --- +shows statistics on the rules, fonts, characters and \verb|\special| commands +used on each page. + +\item \verb|-conserve| --- +forces PSPRINT to conserve the printer's virtual memory at the +expense of creating a larger output file (character bitmaps will be +downloaded more often). +If \verb|-device lino| then \verb|-conserve| is the default; +if \verb|-device lw| or \verb|ps40| then \verb|-noconserve| is the default. + +\item \verb|-u xx| --- +sets the units of dimensions displayed in some PSPRINT messages +(e.g., if the page is off the paper). +\verb|xx| can be one of: + \begin{itemize} + \item + \verb|in| --- for inches (the default)\\ % SYSDEP + \verb|cm| --- for centimetres (2.54\,cm = 1\,in)\\ + \verb|mm| --- for millimetres (25.4\,mm = 1\,in)\\ + \verb|pt| --- for points (72.27\,pt = 1\,in)\\ + \verb|pc| --- for picas (1\,pc = 12\,pt)\\ + \verb|bp| --- for big points (PostScript's default units; 72\,bp = 1\,in)\\ + \verb|px| --- for pixels (depends on resolution of printer) + \end{itemize} + +\item \verb|-ho dimen| and \verb|-vo dimen| --- +allow you to shift the printed location of each page. +For example, \verb|-ho -0.5in| would +shift each page half an inch to the left. +A \verb|dimen| is any integer or real number, possibly negative, followed +by a two-letter unit (the same as for \verb|-u|). + +\end{itemize} + +The remaining options apply to all types of input files: +\begin{itemize} + +\item \verb|-l| --- specifies landscaped output +\begin{picture}(10,7) +\put(0,0){\framebox(10,7){}} +\end{picture}\,, +instead of the default portrait output +\begin{picture}(7,10) +\put(0,0){\framebox(7,10){}} +\end{picture}\,. +If~a DVI file, PSPRINT will check each page to make sure it fits +within the rotated paper. + +\item \verb|-c n| --- specifies up to 100 copies. +Use of this facility is not encouraged. Note in particular that +copies of a multiple-page document will {\em not\/} be collated. + +\item \verb|-n string| --- includes a note on your flag page. + +\item \verb|-q string| --- overrides the default queue used by PSPRINT\@. +(Some sites may have more than one printer of the same type). % SYSDEP + +\item \verb|-o file| --- sends the PostScript code generated by PSPRINT +to a file rather than to a printer. Since some of this code is device-specific +you should only send the file to a PostScript printer of the type that +PSPRINT intended to use. + +\end{itemize} + +\newpage + +\subsection*{Error Messages} + +If PSPRINT detects one or more errors while translating a DVI file then +the temporary PostScript file is automatically deleted and nothing +is printed --- not even a flag page. +The sort of errors you are most likely to see include: +\begin{itemize} +\item +\verb|Page off paper (paper is ...| --- +the current page contains material beyond one or more paper edges. +Use \DVItoVDU\ to see where the problem lies. +\item +\verb|Couldn't open font file: ...| --- +your DVI file uses a font at a non-existent size. +Try a different font magnification in your source file. +\item +\verb|Couldn't open \special file: ...| --- +PSPRINT could not locate the given \verb|\special| file. +Check the file's spelling and/or directory location. +\end{itemize} +Error messages apply to the most recently displayed DVI/\TeX\ page. +Any message that does not make sense probably indicates some sort of bug. +Please save a copy of the input file and report the problem to your +local \TeX nician. + +If your DVI file uses a large number of fonts or a few very large fonts then +you might get an error page with the message ``\verb|VMerror|''. +This indicates that PostScript's virtual memory has been exhausted, +and the rest of your job will be flushed. +This problem is unlikely to worry most people, particularly on the +PrintServer~40 which has much more VM than the LaserWriter or Linotronic. +If the problem does occur, there are a few things you can try: +\begin{enumerate} +\item +On a LaserWriter or PrintServer, use \verb|-conserve| +or print a few pages at a time. +\item +On a Linotronic, use \verb|-lowres|. +(\verb|-conserve| is the default for this device.) +\end{enumerate} +If you are sending your own PostScript program then an error should +produce some sort of message on the printed output. + +\newpage + +\subsection*{Using PostScript Fonts} + +PSPRINT allows the use of PostScript fonts within a \TeX\ or \LaTeX\ document. +Such fonts can be used at any desired size and no character bitmaps need +to be downloaded since the shape information is resident in the printer. +The necessary typesetting information required by PSPRINT is extracted +from TFM files (\TeX\ Font Metric files). +A TFM file name beginning with ``\verb|ps-|'' is used to indicate a resident +PostScript font. % SYSDEP; this prefix is set in psprint + +Each type of PostScript printer provides a different set of fonts. +To be able to use a particular PostScript font you need to know the +name of its corresponding TFM file and whether it actually exists in +the printer you want to use. For each PostScript printer currently +supported there exists a file containing just such information: +\begin{itemize} +\item [ ] +\verb|$tex_ps/lw_fonts.ps | --- converts TFM names into LaserWriter fonts\\ +\verb|$tex_ps/lino_fonts.ps| --- converts TFM names into Linotronic~300 fonts\\ +\verb|$tex_ps/ps40_fonts.ps| --- converts TFM names into PrintServer~40 fonts +\end{itemize} +PSPRINT also uses these files, so you can be reasonably confident +about the validity of their contents. +To print a list of the PostScript fonts available in your printer you can type +the command `\verb|psprint $tex_ps/fontlist.ps|'. + +(The above file names assume that the environment variable \verb|tex_ps| +points to the public directory in which various PSPRINT-related files reside. +To discover what \verb|tex_ps| is at your site, type `\verb|which psprint|' +and examine the first few lines of the indicated file.) + +There are some important differences between PostScript fonts and +the Computer Modern fonts normally used with \TeX: +\begin{enumerate} +\item +When asking for a PostScript font it is best to use an `\verb|at| $dimen$' +size specification (e.g., \verb|\font\helv=ps-helv at 13.5pt|) otherwise you +might end up with a default 1pt font! +\item +PostScript fonts usually contain up to 256 characters, with many +empty locations. Computer Modern fonts can also contain up to 256 characters +but typically use only the first 128 locations (with very few empty). +\item +When a PostScript font is scaled to the same design size as a CM font +it tends to look darker and larger. You need to be a bit careful +when mixing the two font designs. +\item +The standard \TeX\ commands for accents and foreign letters need to be +redefined for a PostScript text font. The file \verb|$tex_ps/pstext.tex| +contains the required macro definitions; note that a few commands +(\verb|\j|, \verb|\aa|, \verb|\AA|, \verb|\t|) cannot be used at all. +Another file, \verb|$tex_ps/psfonts.tex|, inputs these macros and illustrates +the use (and abuse) of PostScript fonts in a \TeX\ document. +\end{enumerate} + +\newpage + +\subsection*{Using PostScript Graphics} + +Creating figures and illustrations with \TeX\ is very difficult. +Although it is theoretically possible to place small dots +anywhere on a page and build up an arbitrarily complex picture, +time and memory limitations make such a scheme impractical. +(\LaTeX\ provides a \verb|picture| environment, but it is very inefficient +and only suitable for small, simple diagrams.) +PSPRINT allows you to merge PostScript graphics with \TeX\ or \LaTeX\@. + +Let's assume you have a file called \verb|fig.ps| that contains +suitable PostScript commands for generating some sort of figure. +To include this figure in a \TeX\ or \LaTeX\ document, just type +`\verb|\special{fig.ps}|' after leaving sufficient space: +\begin{verbatim} + % in a TeX source file % in a LaTeX source file + \midinsert \begin{figure}[ht] + \vskip 3in \vspace{3in} + \special{fig.ps} \special{fig.ps} + \centerline{Figure 1: Pie Sales} \caption{Pie Sales} + \endinsert \end{figure} +\end{verbatim} +It may take a little practice to position the figure correctly. +When you print a raw PostScript file (e.g., `\verb|psprint fig.ps|') +the default origin is at the bottom left corner of the paper. +However, when you include this file in a \TeX\ document the origin is +automatically moved to the position of the \verb|\special| command. + +\verb|\special| can appear almost anywhere in your source file. +It behaves like an invisible box of zero height and width. +\TeX\ simply stores the given argument in the DVI file along with the current +page position. PSPRINT interprets the argument as a file name and then +includes this file in the information sent to the printer. +(The included file is bracketed by \verb|save| and \verb|restore| commands +to prevent any interference to the surrounding typesetting commands.) + +You can move the figure about by shifting the \verb|\special| position, +or by including a \verb|translate| command in the PostScript file. +The latter option is faster because you don't have to run \TeX\ again. +For example, `\verb|72 36 translate|' at the start of \verb|fig.ps| would +move the figure 1\,in right and 0.5\,in up +(PostScript's default units are ``big points'' where 72\,bp = 1\,in). + +Alternatively, you may prefer to place your figure at an absolute position +on the paper (i.e., at the same position produced by `\verb|psprint fig.ps|'). +Simply include an \verb|initgraphics| command at the start of \verb|fig.ps|. +The position of the \verb|\special| command then becomes irrelevant; +just make sure it's on the right page! + +The hardest part of the scheme is creating the PostScript file in the first +place. You are faced with two possibilities: +\begin{enumerate} +\item +Learn enough PostScript to be able to draw your own figures. +You'll need to get the PostScript books mentioned on page~1. +\item +Use a program to convert an existing graphics file +into a corresponding PostScript file. +This assumes you are able to produce graphics of some sort +(e.g., a Zeta plot file) and have access to a suitable conversion program. +Ask your local graphics wizard whether any such programs are available. +\end{enumerate} +\DVItoVDU\ is unable to preview a PostScript file. All it can do is +tell you the page position of the \verb|\special| command and display the +given file name. + +\newpage + +Let's look at a few examples. The public directory \verb|$tex_ps| contains +the \LaTeX\ source file for this User Guide, as well as a few PostScript +files used to produce the figures below. +These figures were created by calling +\begin{verbatim} + \special{piechart.ps} + \special{greybox.ps} + \special{random.ps} +\end{verbatim} +at appropriate points in the source file. + +\begin{figure}[h] % produce figure here + \vspace{2.1in} + \special{piechart.ps} % origin at left margin of text + \caption{Pie Sales} +\end{figure} + +\begin{figure}[h] % produce figure here + \begin{center} + \begin{minipage}{4in} + \special{greybox.ps} % origin at top left of minipage box + The text in this paragraph box was typeset by \LaTeX\@. + The shaded rectangle was created by PostScript. + \end{minipage} + \end{center} + \bigskip % leave additional room for shaded box + \caption{Shaded Text Box} +\end{figure} + +\begin{figure}[h] % produce figure here + \begin{center} + \setlength{\unitlength}{1in} + \begin{picture}(1.3,1.3) % dimensions match axis lengths in random.ps + \put(0,0){\special{random.ps}} % origin at bottom left corner + \end{picture} + \end{center} + \caption{Random Dots} +\end{figure} + +PSPRINT allows arbitrary PostScript text to appear after the file name in a +\verb|\special| command. At least one space must be used to terminate the file +name; further characters are included as a new line at the {\em start\/} of +the given file. There is a limit of about 80 characters. +For example, `\verb|\special{fig.ps 2 1 scale}|' could be used to double +the width of the figure in \verb|fig.ps|. +Note that it is possible to include the same PostScript file more than once, +but with a different starting line each time. + +\end{document} diff --git a/dviware/psprint/unix/wide.ps b/dviware/psprint/unix/wide.ps new file mode 100644 index 0000000000..50b16b0de7 --- /dev/null +++ b/dviware/psprint/unix/wide.ps @@ -0,0 +1,117 @@ +% Prologue for a -wide job. +% It assumes psprint has defined fspec and dev. +% The following definitions produce two logical pages (132 cols by 60 lines) +% on a single portrait sheet of A4 paper. +% Both pages have a headline showing fspec and page #. +% Every character after this file (until ^D) will be treated as a printing +% character (or control character) instead of being interpreted as PostScript. + +/maxlines 60 def % maximum lines per logical page +/maxchar 132 def % maximum chars per line +/interline -6 def % baseline skip +/Courier findfont % Courier font (fixed-width chars) +6 scalefont setfont % at 6pt +/inch { 72 mul } def % convert inches to big points + +/page1pos +{ 1 inch 0 translate % 1 inch left margin + /topline { 10.9 inch } def % vertical location of top line (not headline) + 0 topline moveto % start of first line + /line 0 def % initialize line counter + /char 0 def % initialize chars/line counter +} bind def + +/page2pos +{ /topline { 5.4 inch } def % vertical location of top line (not headline) + 0 topline moveto % start of first line + /line maxlines def % in case formfeed occurred in 1st logical page +} bind def + +/pagenum 0 def % initialize logical page number + +/headline +{ gsave % save current pos and font + /Courier-Bold findfont 9 scalefont setfont % use Courier-Bold at 9pt + 0 topline moveto % move to top left corner + 0 interline 2 mul neg rmoveto % move up 2 lines + fspec show + % increment page number and show it right justified + /pagenum pagenum 1 add def + /pagestr pagenum 10 string cvs def + charwidth maxchar mul topline moveto % move to top right corner + (p.) stringwidth pop + pagestr stringwidth pop add neg % move left by page # width + interline 2 mul neg % move up 2 lines + rmoveto + (p.) show pagestr show + grestore % restore pos and font +} bind def + +/formfeed % start next logical page unless already there +{ line 0 gt + { line maxlines lt + { headline page2pos } % 0 < line < maxlines + { line maxlines gt + line maxlines 2 mul lt and + { headline showpage page1pos } if % maxlines < line < 2 * maxlines + } ifelse + } if +} bind def + +/linefeed +{ /char 0 def % reset chars/line counter + /line line 1 add def % increment line counter + line maxlines eq % if end of 1st page + { headline % show 1st headline + page2pos } % and start 2nd page + { line maxlines 2 mul eq % elsif end of 2nd page + { headline % then show 2nd headline + showpage page1pos } % and show both pages + { currentpoint pop neg interline rmoveto % else start next line + } ifelse + } ifelse +} bind def + +/backspace +{ /char char 1 sub def + char 0 ge { charwidth neg 0 rmoveto } if % move back one character +} def + +/showchar +{ currentchar 0 thischar put % put thischar into 1-char string + /char char 1 add def % increment chars/line counter + char maxchar le { currentchar show } if % ignore chars > maxchar +} bind def + +/eachchar +{ infile read not {exit} if % get next char + /thischar exch def % save it in thischar + thischar 32 ge % thischar >= space? + { showchar } % if so, show it + { thischar 8 eq % or does thischar = backspace? + { backspace } + { thischar 10 eq % or does thischar = linefeed? + { linefeed } + { thischar 12 eq % or does thischar = formfeed? + { formfeed } + { % ignore any other control char + } ifelse + } ifelse + } ifelse + } ifelse +} bind def + +(%stdin) (r) file /infile exch def +/currentchar 1 string def +/charwidth ( ) stringwidth pop def % assume fixed-width font +page1pos % start 1st page + +/charloop +{ {eachchar} loop + line 0 gt + { headline showpage } % flush last sheet with only 1st logical page + if + dev (LW) eq { @bannerpage } if % print banner page if LaserWriter +} def + +charloop -- cgit v1.2.3