diff options
Diffstat (limited to 'dviware/psprint/vms')
59 files changed, 12335 insertions, 0 deletions
diff --git a/dviware/psprint/vms/00readme.txt b/dviware/psprint/vms/00readme.txt new file mode 100644 index 0000000000..3aa15672e4 --- /dev/null +++ b/dviware/psprint/vms/00readme.txt @@ -0,0 +1,79 @@ +PSPRINT 3.1 for VAX/VMS, 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 (any model), +DEC's PrintServer 40 and the Linotronic 300. + +The absolutely essential files in this directory are: + +USERGUIDE.TEX - LaTeX source for PSPRINT User Guide +USERGUIDE.DVI - ready for users to print; it uses these \special files: + PIECHART.PS - to produce Figure 1 + GREYBOX.PS - to produce Figure 2 + RANDOM.PS - to produce Figure 3 +PSDVI.CLD - DCL interface to PSDVI command +PSDVI.EXE - PSDVI image built under VAX/VMS 5.1 +PSPRINT.CLD - DCL interface to PSPRINT command +PSPRINT.EXE - PSPRINT image built under VAX/VMS 5.1 + +EMPTY.PS - empty file (used in all *_PRINT.COM files and NASTY.TEX) +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.DAT - contains ^D (sent at end of each LW/LINO job) + +LW_PRINT.COM - run by PSPRINT/DEVICE=LW +LW_HEADER.PS - defines @bannerpage and error handler +LW_TRAILER.PS - calls @bannerpage +LW_FONTS.PS - converts TFM names to resident LaserWriter font names + +LINO_PRINT.COM - run by PSPRINT/DEVICE=LINO +LINO_HEADER.PS - defines @bannerpage, @footerpage, error handler, etc. +LINO_TRAILER.PS - calls @footerpage +LINO_FONTS.PS - converts TFM names to resident Linotronic font names + +PS40_PRINT.COM - run by PSPRINT/DEVICE=PS40 +PS40_HEADER.PS - defines error handler +PS40_FONTS.PS - converts TFM names to resident PrintServer font names + +PSFONTS.TEX - illustrates use of PostScript fonts in a TeX document +PSTEXT.TEX - used in PSFONTS.TEX (defines \PStext and \CMtext) +PSNAMES.TEX - used in PSFONTS.TEX (defines macros for PostScript TFMs) + +Other important files are: + +SYSGUIDE.TEX - LaTeX source for PSPRINT System Guide +INSTALL.COM - commands to install the PSPRINT system +PSPRINT.MOD - Modula-2 source file for PSPRINT +PSPRINT.HLP - on-line help for PSPRINT +BUILD.COM - builds PSPRINT.EXE and/or PSDVI.EXE + +PSDVI.MOD - Modula-2 source file for PSDVI's main module +OPTIONS.* - used by PSDVI to extract options from command line +DVIREADER.* - used by PSDVI to access DVI files +FONTREADE.* - used by PSDVI to access font files +TERMOUT.* - used by PSDVI to do terminal output +PSWRITER.* - used by PSDVI to create PostScript file +PSDVI.HLP - on-line help for PSDVI + +LASERPREP70.PS - Modified Laser Prep v70 (for use with /PREP) +LASERPREP68.PS - Modified Laser Prep v68 (ditto) +LASERPREP65.PS - Modified Laser Prep v65 (ditto) +GLOBAL.PS - shows how to get an image printed on every DVI page +FONTLIST.PS - prints a list of the available fonts in your printer +PS40_LIST.PS - lists PrintServer 40 fonts on your terminal +LINO_PAGES.PS - tests various page setups available on Linotronic +INFO.PS - to discover some printer details +CLIP.PS - to discover the page image area (useful for LaserWriter) +PASS.PS - to verify/change a PostScript printer's system password +LINES.DAT - an ordinary text file with 66 lines +TEST.TEX - TeX source for TEST.DVI (tests origin position) +NASTY.TEX - TeX source for NASTY.DVI; it uses these \special files: + BAD.PS - contains deliberate PostScript error + BOX.PS - draws a box + EMPTY.PS - empty file diff --git a/dviware/psprint/vms/bad.ps b/dviware/psprint/vms/bad.ps new file mode 100644 index 0000000000..8c7de0b8e2 --- /dev/null +++ b/dviware/psprint/vms/bad.ps @@ -0,0 +1,19 @@ +% This file contains a deliberate error (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/vms/box.ps b/dviware/psprint/vms/box.ps new file mode 100644 index 0000000000..33f5e0fa91 --- /dev/null +++ b/dviware/psprint/vms/box.ps @@ -0,0 +1,17 @@ +72 72 scale % units are now inches instead of big points + +userdict /@eop known % are we in a TeX job? +not +{ 1 1 translate % if not then move origin away from corner +} if + +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 is included in TeX \special diff --git a/dviware/psprint/vms/build.com b/dviware/psprint/vms/build.com new file mode 100644 index 0000000000..f56e2bd5a7 --- /dev/null +++ b/dviware/psprint/vms/build.com @@ -0,0 +1,44 @@ +$! Build PSPRINT.EXE and/or PSDVI.EXE +$ +$ on warning then goto stop +$ inquire/nopunct yes "Compile and link PSPRINT?" +$ if .not. yes then goto psdvi +$ set ver +$ mod/nocheck/log PSPRINT +$ define/user lnk$library mod$system:modula.olb +$ link/notrace PSPRINT +$ set nover +$ +$psdvi: +$ inquire/nopunct yes "Compile modules used by PSDVI?" +$ if .not. yes then goto justmain +$ set ver +$ mod/nocheck/log TERMOUT.DEF +$ mod/nocheck/log TERMOUT +$ mod/nocheck/log OPTIONS.DEF +$ mod/nocheck/log OPTIONS +$ mod/nocheck/log DVIREADER.DEF +$ mod/nocheck/log DVIREADER +$ mod/nocheck/log PSWRITER.DEF +$ mod/nocheck/log PSWRITER +$ mod/nocheck/log FONTREADE.DEF +$ mod/nocheck/log FONTREADE +$ set nover +$ +$justmain: +$ inquire/nopunct yes "Compile PSDVI?" +$ if .not. yes then goto link +$ set ver +$ mod/nocheck/log PSDVI +$ set nover +$ +$link: +$ inquire/nopunct yes "Link PSDVI?" +$ if .not. yes then goto stop +$ set ver +$ define/user lnk$library mod$system:modula.olb +$ link/notrace PSDVI, TERMOUT, OPTIONS, DVIREADER, FONTREADE, PSWRITER +$ set nover +$ +$stop: +$ set nover diff --git a/dviware/psprint/vms/clip.ps b/dviware/psprint/vms/clip.ps new file mode 100644 index 0000000000..0bc77936ce --- /dev/null +++ b/dviware/psprint/vms/clip.ps @@ -0,0 +1,5 @@ +% Send this program to determine the extent of the imaging area. + +initgraphics +newpath clippath stroke +showpage diff --git a/dviware/psprint/vms/ctrld.dat b/dviware/psprint/vms/ctrld.dat new file mode 100644 index 0000000000..ce9a8a9d59 --- /dev/null +++ b/dviware/psprint/vms/ctrld.dat @@ -0,0 +1 @@ + diff --git a/dviware/psprint/vms/dvireader.def b/dviware/psprint/vms/dvireader.def new file mode 100644 index 0000000000..e57909144b --- /dev/null +++ b/dviware/psprint/vms/dvireader.def @@ -0,0 +1,392 @@ +DEFINITION MODULE DVIReader; + +(* Author: Andrew Trevorrow + Implementation: University of Hamburg Modula-2 under VAX/VMS version 4 + Date Started: August, 1984 + + Description: + DVIReader exports routines and data structures for moving about randomly + in a TeX82 DVI file and interpreting pages. + + Revised: + August, 1986 + - The SpecialRoutine has two new parameters to pass the current page position. + - The pixeltable record has a new flag that indicates if the character's + bitmap has been loaded. + - The fontinfo record has a new flag that indicates if the font exists, + and a new string that stores a unique font identifier needed by PostScript. + - Export CurrMatchesNew to help locate TeX page subrange. + + December, 1986 + - Increased maxTeXchar from 127 to 255. + - Lowered maxfontspec from 80 to 64. + + November, 1987 (while at The Open University) + - Added psfont flag in fontinfo record. It is used to indicate a resident + PostScript font (for which character bitmaps do not exist). + For such a font, character metrics will have to be read from the TFM file. + + Limitations: + - DVIReader does not look at the preamble and so ignores any comments there. + - DVIReader does not do any terminal i/o, even upon detecting a fatal error. + The client must write a DVIErrorRoutine that will be invoked at the time + an error is detected. See below for details. + - DVIReader knows nothing about the format of font files. + It only knows they contain crucial information for typesetting a DVI file. + The client must write a PixelTableRoutine to read some sort of font file + and fill in the pixel table information used to interpret a DVI page. + See below for details. + - The data structures used to represent an interpreted DVI page are best + suited to a client whose output device is randomly addressable. + Some clients may need to convert the information in the data structures + into a more suitable format. + + Algorithm for a simple DVI translator: + < initialize the DVIErrorRoutine used to handle various errors > + < initialize filespec, resolution, etc. > + OpenDVIFile(filespec); + < initialize magnification, probably with DVImag > + SetConversionFactor(resolution,magnification); + < initialize the SpecialRoutine used in InterpretPage > + < initialize the PixelTableRoutine used in InterpretPage > + FOR p := 1 TO totalpages DO + MoveToDVIPage(p); + InterpretPage; + IF pageempty THEN + < process an empty page > + ELSE + < check that the page edges are within the paper edges > + < process the rule list > + < process the character list for each font used on the page > + END; + END; + CloseDVIFile; +*) + + +CONST + ruletablesize = 300; (* maximum number of rules in a ruletable *) + chartablesize = 3000; (* maximum number of chars in a chartable *) + maxfontspec = 64; (* maximum length of a font file specification *) + maxTeXchar = 255; (* ignore character codes > 255 *) + + +TYPE + (* The major page structures are defined first. + 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. This is done so that when the client + 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 = POINTER TO ruleinfo; + ruleinfo = (* a node in a list of ruletables *) + RECORD + rulecount : CARDINAL; (* number of rules in ruletable *) + ruletable : ARRAY [0..ruletablesize-1] 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 = POINTER TO charinfo; + charinfo = (* a node in list of chartables *) + RECORD + charcount : CARDINAL; (* number of chars in chartable *) + chartable : ARRAY [0..chartablesize-1] 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; + + (* pixeltable must be filled in by the client's PixelTableRoutine. + 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. + *) + pixeltableptr = POINTER TO 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 : CARDINAL; (* starting address of bitmap info in font file + (could be a word or byte offset) *) + loaded : BOOLEAN; (* has bitmap been downloaded? *) + END; + + fontstring = ARRAY [0..maxfontspec-1] OF CHAR; + fontinfoptr = POINTER TO 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 : CARDINAL; (* scaled font size in DVI units *) + designsize : CARDINAL; (* design size in DVI units *) + fontarea : fontstring; (* explicit font directory *) + fontarealen : CARDINAL; (* length of fontarea *) + fontname : fontstring; (* font name; e.g., "amr10" *) + fontnamelen : CARDINAL; (* length of font name *) + fontspec : fontstring; (* client's font file specification *) + fontspeclen : CARDINAL; (* length of fontspec *) + fontexists : BOOLEAN; (* could fontspec be opened? *) + fontid : fontstring; (* unique font identifier *) + totalchars : CARDINAL; (* 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; + + (* For the parameter in client's DVIErrorRoutine: *) + DVIerrorcodes = ( + DVIunopened, (* OpenDVIFile could not open the given file *) + DVIempty, (* OpenDVIFile detected an empty file *) + DVIbadid, (* OpenDVIFile detected an invalid TeX82 DVI file *) + DVIstackoverflow, (* OpenDVIFile found DVIReader's stack is too small *) + DVIbadchar, (* InterpretPage is ignoring a char code > maxTeXchar + (detected while processing currfont^) *) + DVIcatastrophe); (* DVIReader detected a situation that should never + occur; client should scream for help and halt *) + + (* For the function parameter in client's SpecialRoutine: *) + GetByteFunction = PROCEDURE () : INTEGER; (* returns next DVI byte *) + + +VAR + (* Most of these should be treated as read-only parameters: *) + DVImag : CARDINAL; (* magnification stored in DVI file *) + totalpages : CARDINAL; (* number of pages in DVI file *) + totalfonts : CARDINAL; (* number of fonts in DVI file *) + currDVIpage : CARDINAL; (* updated by MoveTo... calls *) + currTeXpage : TeXcounters; (* ditto *) + totalrules : CARDINAL; (* number of rules on current page *) + rulelist : ruleinfoptr; (* head 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 *) + + DVIErrorRoutine : PROCEDURE (DVIerrorcodes); + (* The client MUST assign a procedure before the first OpenDVIFile call. + Various DVIReader routines will call this procedure if they detect some + sort of problem; the given argument will be one of the error codes + described above. + The client's routine can use this code to see what sort of error + has occurred and take appropriate action. Most errors detected by + DVIReader are fatal; the client should print some sort of message + and halt. See PSDVI for an example DVIErrorRoutine. + *) + + SpecialRoutine : PROCEDURE (INTEGER, INTEGER, INTEGER, GetByteFunction); + (* The client can assign a procedure before the first InterpretPage call. + InterpretPage will call this procedure to process the bytes belonging to + a \special command. The first two arguments give the (x,y) + pixel coordinates defining the position of the \special command. + The third argument gives the number of bytes; the last argument + argument is a function that returns the value of the next byte + (0..255, but usually the ordinal value of a displayable ASCII character). + If the client does not supply a SpecialRoutine, DVIReader will simply + ignore any \special bytes. + *) + + PixelTableRoutine : PROC; + (* The client MUST assign a procedure before the first InterpretPage call. + InterpretPage will call this procedure immediately after allocating a + pixel table for currfont^. This will only occur once per font (the + very first time the font is used). + DVIReader only knows about DVI files; the task of the PixelTableRoutine is + to fill in the current font's pixel table by reading the fontspec file. + (The fontspec string must first be built using the fontname.) + This file could be a PXL file, or some other type of font file. + *) + + +PROCEDURE OpenDVIFile (filespec : ARRAY OF CHAR); + +(* This must be the first DVIReader routine called. If the given filespec 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) +*) + +PROCEDURE SetConversionFactor (resolution, magnification : CARDINAL); + +(* This routine must be called before the first InterpretPage call. + DVIReader needs to know the client's resolution and magnification values + before it attempts to convert DVI dimensions into pixel values. +*) + +PROCEDURE MoveToDVIPage (n : CARDINAL); +PROCEDURE MoveToNextPage (ascending : BOOLEAN); +PROCEDURE MoveToTeXPage (VAR newTeXpage : TeXpageinfo) : BOOLEAN; + +(* Before calling InterpretPage, the client must position DVIReader to the + desired page by calling one of these MoveTo... routines. + + MoveToDVIPage will select the nth page in the DVI file; nothing will + happen if n is not in 1..totalpages. + + 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). + + 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. + The client will probably need to first convert 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. + + 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. +*) + +PROCEDURE CurrMatchesNew (VAR newTeXpage : TeXpageinfo) : BOOLEAN; + +(* Return TRUE iff currTeXpage matches the \count information in newTeXpage. *) + +PROCEDURE PixelRound (DVIunits : INTEGER) : INTEGER; + +(* Converts the given DVI dimension (+ve or -ve) into pixels. *) + +PROCEDURE InterpretPage; + +(* This routine will interpret the current DVI page and update the major + 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) + + 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 client'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 bitmap info (0 if absent or white) + loaded := FALSE + 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 AND all reference points 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. +*) + +PROCEDURE SortFonts (VAR unusedlist : fontinfoptr); + +(* This routine will sort fontlist in ascending order of totalchars. + The client may wish to do this after interpreting a page so that fonts + with the least number of characters on the page will be processed first. + The routine will also move all unused fonts to the end of fontlist so that + the client need only process fonts up to (but excluding) unusedlist + and not have to worry about checking the fontused flag. + For example: + SortFont(unusedlist); + thisfont := fontlist; + WHILE thisfont <> unusedlist DO + < process the font information in thisfont^ > + thisfont := thisfont^.nextfont; + END; + If unusedlist is NIL then either 1) all fonts are used on the current page + or 2) fontlist is also NIL (totalfonts = 0). +*) + +PROCEDURE CloseDVIFile; + +(* This routine closes the currently open DVI file; it is only mandatory if + OpenDVIFile is going to be called again. + All dynamic data structures are deallocated. +*) + +END DVIReader. diff --git a/dviware/psprint/vms/dvireader.mod b/dviware/psprint/vms/dvireader.mod new file mode 100644 index 0000000000..0ff1ac3fa8 --- /dev/null +++ b/dviware/psprint/vms/dvireader.mod @@ -0,0 +1,1474 @@ +IMPLEMENTATION MODULE DVIReader; + +(* Author: Andrew Trevorrow + Implementation: University of Hamburg Modula-2 under VAX/VMS version 4 + Date Started: August, 1984 + + Description: + Implements 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. + + Revised: + August, 1986 + - PSDVI requires that MoveToDVIPage no longer assumes InterpretPage has + been called after any previous MoveTo... routine. + + December, 1986 + - Initialize fontexists flag to FALSE when reading postamble. + + June--August, 1988 (while at Aston University) + - Import hoffset and voffset from Options to handle shifting of page. +*) + +FROM SYSTEM IMPORT + ADDRESS, (* byte address *) + ADR, BYTE; + +FROM Storage IMPORT + ALLOCATE, DEALLOCATE; (* need for NEW and DISPOSE *) + +FROM VMS IMPORT + SYS$OPEN, SYS$CRMPSC, SYS$DASSGN, SYS$DELTVA; + +FROM SSDefinitions IMPORT + SS$_ENDOFFILE; + +FROM SECDefinitions IMPORT + SEC$V_EXPREG; + +FROM RMS IMPORT + FAB, InitFab, + FOPset, FOPtype, + FACset, FACtype, + SHRset, SHRtype; + +(* DEBUG +(* DVIReader will only do terminal output while debugging. *) +FROM TermOut IMPORT + Write, WriteString, WriteLn, WriteInt, WriteCard, Halt; +GUBED *) + +FROM Options IMPORT + hoffset, voffset; + + +(******************************************************************************* + DECLARATIONS FOR RANDOMLY ACCESSING A DVI FILE + + A DVI file is considered to be an array of 8-bit bytes, ending with at + least 4 223 bytes and having a total length divisible by 4. + Under VAX/VMS a DVI file has fixed-length, 512-byte records (1 per block). + The last record/s will be padded with 223 bytes to ensure that the + above conditions hold. We will be randomly positioning to DVI bytes + by setting DVIoffset, and reading bytes via GetDVIByte, SignedDVIByte etc. +*) + +TYPE + (* DVI file should never have more than MAX(INTEGER) bytes! *) + DVIfile = ARRAY [0..MAX(INTEGER)] OF BYTE; + DVIpointer = POINTER TO DVIfile; (* never allocated! *) + +VAR + vas : ARRAY [0..1] OF ADDRESS; (* start and end virtual addresses *) + DVIstart : DVIpointer; + DVIoffset : CARDINAL; (* current byte offset in DVIfile *) + channel : CARDINAL; (* fab.STV returned by SYS$OPEN *) + gsdnam : ARRAY [0..42] OF CHAR; (* unused argument in SYS$CRPMSC *) + status : CARDINAL; + fab : FAB; + postpostid : CARDINAL; (* offset of postpost's id byte *) + +(******************************************************************************) + +PROCEDURE OpenDVIFile (name : ARRAY OF CHAR); + +(* If the given file can be opened and is a valid TeX82 DVI file then we + process the postamble and initialize currDVIpage and currTeXpage. +*) + +VAR i : CARDINAL; + +BEGIN +InitFab(fab); (* initialize fab *) +WITH fab DO + FNA := ADR(name); (* DVI file name *) + FNS := BYTE(LEN(name)); (* bytes in file name *) + FAC := FACset{FAC$BRO,FAC$GET}; (* read-only *) + SHR := SHRset{SHR$GET}; (* share file with other readers *) + FOP := FOPset{FOP$UFO}; (* need for SYS$CRMPSC *) + RTV := BYTE(-1); (* for more efficient mapping *) +END; +status := SYS$OPEN(ADR(fab),0,0); (* open the file *) +IF ODD(status) THEN + WITH fab DO + channel := STV; (* channel on which file is open *) + END; + (* now map entire DVI file into virtual address space *) + vas[0] := 0; + vas[1] := 0; + status := SYS$CRMPSC + (ADR(vas), (* starting and ending addresses *) + ADR(vas), (* addresses returned *) + 0, + {SEC$V_EXPREG}, (* pages mapped into 1st available space *) + gsdnam,0,0, + channel, (* channel on which file has been opened *) + 0,0,0, + 36 (* large page fault cluster size *) + ); + IF status = SS$_ENDOFFILE THEN + DVIErrorRoutine(DVIempty); (* given file is empty *) + ELSIF NOT ODD(status) THEN + (* DEBUG + WriteString('SYS$CRMPSC failed! status='); WriteCard(status); + WriteLn; Halt(2); + GUBED *) + DVIErrorRoutine(DVIcatastrophe); + ELSE + (* Now that the entire DVI file is mapped into virtual memory we can + access any DVI byte as an offset from the address in vas[0]. + *) + DVIstart := vas[0]; + (* move to last DVI byte *) + DVIoffset := CARDINAL(ADDRESS(vas[1]) - ADDRESS(DVIstart)); + (* check for trailing NULs first in case DVI file has come + from non-VMS environment + *) + WHILE (DVIoffset > 0) AND (CARDINAL(DVIstart^[DVIoffset]) = 0) DO + DEC(DVIoffset); (* skip NUL byte *) + END; + WHILE (DVIoffset > 0) AND (CARDINAL(DVIstart^[DVIoffset]) = 223) DO + DEC(DVIoffset); (* skip 223 byte *) + END; + postpostid := DVIoffset; (* remember position of id byte *) + IF GetDVIByte() <> 2 THEN + (* DEBUG + WriteString('Bad DVI file! id byte is not 2.'); WriteLn; + Halt(2); + GUBED *) + DVIErrorRoutine(DVIbadid); (* not a valid TeX82 DVI file *) + ELSE + 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; + END; +ELSE + DVIErrorRoutine(DVIunopened); (* given file could not be opened *) +END; +END OpenDVIFile; + +(******************************************************************************) + +(* Here are the functions used to get byte/s from DVIfile. + They are essentially the same as those used in DVITYPE. +*) + +PROCEDURE GetDVIByte () : INTEGER; + +(* Returns the value (unsigned) of the byte at DVIoffset and + advances DVIoffset for the next GetDVIByte. +*) + +VAR b : CARDINAL; + +BEGIN +b := CARDINAL(DVIstart^[DVIoffset]); INC(DVIoffset); +RETURN b; +END GetDVIByte; + +(******************************************************************************) + +PROCEDURE SignedDVIByte () : INTEGER; (* the next byte, signed *) + +VAR b : CARDINAL; + +BEGIN +b := CARDINAL(DVIstart^[DVIoffset]); INC(DVIoffset); +IF b < 128 THEN + RETURN b; +ELSE + RETURN b - 256; +END; +END SignedDVIByte; + +(******************************************************************************) + +PROCEDURE GetTwoDVIBytes () : INTEGER; (* the next 2 bytes, unsigned *) + +VAR a, b : CARDINAL; + +BEGIN +a := CARDINAL(DVIstart^[DVIoffset]); INC(DVIoffset); +b := CARDINAL(DVIstart^[DVIoffset]); INC(DVIoffset); +RETURN a * 256 + b; +END GetTwoDVIBytes; + +(******************************************************************************) + +PROCEDURE SignedDVIPair () : INTEGER; (* the next 2 bytes, signed *) + +VAR a, b : CARDINAL; + +BEGIN +a := CARDINAL(DVIstart^[DVIoffset]); INC(DVIoffset); +b := CARDINAL(DVIstart^[DVIoffset]); INC(DVIoffset); +IF a < 128 THEN + RETURN a * 256 + b; +ELSE + RETURN (a - 256) * 256 + b; +END; +END SignedDVIPair; + +(******************************************************************************) + +PROCEDURE GetThreeDVIBytes () : INTEGER; (* the next 3 bytes, unsigned *) + +VAR a, b, c : CARDINAL; + +BEGIN +a := CARDINAL(DVIstart^[DVIoffset]); INC(DVIoffset); +b := CARDINAL(DVIstart^[DVIoffset]); INC(DVIoffset); +c := CARDINAL(DVIstart^[DVIoffset]); INC(DVIoffset); +RETURN (a * 256 + b) * 256 + c; +END GetThreeDVIBytes; + +(******************************************************************************) + +PROCEDURE SignedDVITrio () : INTEGER; (* the next 3 bytes, signed *) + +VAR a, b, c : CARDINAL; + +BEGIN +a := CARDINAL(DVIstart^[DVIoffset]); INC(DVIoffset); +b := CARDINAL(DVIstart^[DVIoffset]); INC(DVIoffset); +c := CARDINAL(DVIstart^[DVIoffset]); INC(DVIoffset); +IF a < 128 THEN + RETURN (a * 256 + b) * 256 + c; +ELSE + RETURN ((a - 256) * 256 + b) * 256 + c; +END; +END SignedDVITrio; + +(******************************************************************************) + +PROCEDURE SignedDVIQuad () : INTEGER; (* the next 4 bytes, signed *) + +VAR a, b, c, d : CARDINAL; + +BEGIN +a := CARDINAL(DVIstart^[DVIoffset]); INC(DVIoffset); +b := CARDINAL(DVIstart^[DVIoffset]); INC(DVIoffset); +c := CARDINAL(DVIstart^[DVIoffset]); INC(DVIoffset); +d := CARDINAL(DVIstart^[DVIoffset]); INC(DVIoffset); +IF a < 128 THEN + RETURN ((a * 256 + b) * 256 + c) * 256 + d; +ELSE + RETURN (((a - 256) * 256 + b) * 256 + c) * 256 + d; +END; +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 : CARDINAL; + +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 + (* DEBUG + WriteString('Stack capacity exceeded! maxstack = '); + WriteCard(maxstack); + WriteString(' but maxstacksize only = '); WriteCard(maxstacksize); + WriteLn; + Halt(2); + GUBED *) + DVIErrorRoutine(DVIstackoverflow); + (* now we don't need to test for stack overflow in DoPush *) +END; +(* DEBUG + WriteString('postamble opcode ='); WriteInt(postamble); WriteLn; + WriteString('postion of last bop ='); WriteInt(lastbop); WriteLn; + WriteString('num ='); WriteInt(num); WriteLn; + WriteString('den ='); WriteInt(den); WriteLn; + WriteString('DVI mag ='); WriteInt(DVImag); WriteLn; + WriteString('ht+dp of tallest page='); WriteInt(pagehtplusdp); WriteLn; + WriteString('width of widest page ='); WriteInt(pagewidth); WriteLn; + WriteString('max stack depth ='); WriteInt(maxstack); WriteLn; + WriteString('total # of pages ='); WriteInt(totalpages); WriteLn; +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; + the client module must handle all this in its PixelTableRoutine.) + 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 : fontstring; (* 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 + 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 := ''; + FOR i := 0 TO a-1 DO (* read and store font area *) + ch := CHR(GetDVIByte()); + IF i < maxfontspec THEN farea[i] := ch END; + END; + fname := ''; + FOR i := 0 TO l-1 DO (* read and store font name *) + ch := CHR(GetDVIByte()); + IF i < maxfontspec THEN fname[i] := ch END; + END; + NEW(currfont); + WITH currfont^ DO + fontused := FALSE; + fontnum := f; + scaledsize := s; + designsize := d; + fontarea := farea; fontarealen := CARDINAL(a); + fontname := fname; fontnamelen := CARDINAL(l); + fontspec := ''; + fontspeclen := 0; (* fontspec has to be built by client *) + 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 *) + INC(totalfonts); + ELSIF DVIcommand = nop THEN + (* nop commands can occur between DVI commands *) + ELSIF DVIcommand = postpost THEN + (* we have reached end of postamble *) + ELSE + (* DEBUG + WriteString('Unexpected DVI command in postamble = '); + WriteCard(DVIcommand); WriteLn; + Halt(2); + GUBED *) + DVIErrorRoutine(DVIcatastrophe); + END; +UNTIL DVIcommand = postpost; +END ProcessFontDefs; + + +(******************************************************************************* + 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 : CARDINAL; (* position of last bop byte *) + prevbop : INTEGER; (* position of bop byte of previous page; + note that prevbop of first page = -1 *) + +(******************************************************************************) + +PROCEDURE MoveToNextPage (ascending : BOOLEAN); + +(* Move to next DVI page; whether we can will depend on the current DVI page + and if we are ascending or descending. +*) + +BEGIN +IF (currDVIpage = 1) AND (NOT ascending) THEN (* do nothing *) + RETURN; +ELSIF (currDVIpage = totalpages) AND ascending THEN (* do nothing *) + RETURN; +ELSIF currDVIpage = 0 THEN (* we haven't processed a page yet *) + IF ascending THEN (* get first page *) + ReadFirstBop; + ELSE (* 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 + (* move to bop pointed to by currbop's backpointer *) + currbop := prevbop; + DVIoffset := currbop + 1; (* move to byte after previous bop *) + DEC(currDVIpage); + END; +END; +ReadBopParameters; (* update currTeXpage and prevbop *) +END MoveToNextPage; + +(******************************************************************************) + +PROCEDURE ReadFirstBop; + +(* Read first bop by skipping past preamble; update currbop and currDVIpage. *) + +VAR k, i, dummy : CARDINAL; + +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 *) +END; +REPEAT (* skip any nops and fntdefs *) + DVIcommand := GetDVIByte(); + IF (DVIcommand = nop) OR (DVIcommand = bop) THEN + (* do nothing *) + ELSIF (DVIcommand >= fntdef1) AND (DVIcommand <= fntdef1+3) THEN + SkipFntdef(DVIcommand - fntdef1); + ELSE + (* DEBUG + WriteLn; + WriteString('Unexpected DVI command before first bop = '); + WriteCard(DVIcommand); WriteLn; + Halt(2); + GUBED *) + DVIErrorRoutine(DVIcatastrophe); + END; +UNTIL DVIcommand = bop; +currbop := DVIoffset - 1; (* position in DVI file of first bop *) +currDVIpage := 1; +END ReadFirstBop; + +(******************************************************************************) + +PROCEDURE SkipFntdef (which : CARDINAL); + +(* Read past a fntdef command without interpreting it. *) + +VAR dummy, a, l, i : CARDINAL; + +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 := 0 TO l+a-1 DO + dummy := GetDVIByte(); +END; +END SkipFntdef; + +(******************************************************************************) + +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 *) + ELSIF (DVIcommand >= fntdef1) AND (DVIcommand <= fntdef1+3) THEN + SkipFntdef(DVIcommand - fntdef1); + ELSE + (* DEBUG + WriteLn; + WriteString('Unexpected DVI command between eop and bop = '); + WriteCard(DVIcommand); WriteLn; + Halt(2); + GUBED *) + DVIErrorRoutine(DVIcatastrophe); + END; +UNTIL DVIcommand = bop; +currbop := DVIoffset - 1; (* position in DVI file of this bop *) +INC(currDVIpage); +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 : CARDINAL; + +BEGIN +FOR i := 0 TO 9 DO + currTeXpage[i] := SignedDVIQuad(); +END; +prevbop := SignedDVIQuad(); (* position of previous bop in DVI file *) +END ReadBopParameters; + +(******************************************************************************) + +PROCEDURE MoveToDVIPage (n : CARDINAL); + +(* Move to nth DVI page; n should be in 1..totalpages. *) + +BEGIN +IF (n < 1) OR (n > totalpages) THEN (* do nothing *) + RETURN; +END; +IF n = 1 THEN + (* Note that this test must come before next ELSIF 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). +ELSIF n = currDVIpage + 1 THEN + ReadNextBop; +*) +ELSE + IF n < currDVIpage THEN + currbop := prevbop; (* start searching backwards from previous page *) + DEC(currDVIpage); + ELSIF n > currDVIpage THEN + currbop := lastbop; (* start searching backwards from last page *) + currDVIpage := totalpages; + ELSE + (* n = currDVIpage so we'll just move back to currbop *) + END; + (* n is now <= currDVIpage so search by following backpointers *) + LOOP + IF n = currDVIpage THEN + DVIoffset := currbop + 1; (* move to byte after currbop *) + EXIT; + ELSE + DVIoffset := currbop + 41; (* move to location of backpointer *) + currbop := SignedDVIQuad(); (* get location of previous page *) + DEC(currDVIpage); + END; + END; +END; +ReadBopParameters; (* update currTeXpage and prevbop *) +END MoveToDVIPage; + +(******************************************************************************) + +PROCEDURE MoveToTeXPage (VAR newTeXpage : TeXpageinfo) (* in *) + : BOOLEAN; + +(* Return TRUE iff the given TeX page exists. + If so then we move to the lowest matching page. +*) + +VAR savecurrbop, savecurrDVIpage : CARDINAL; + nextbop : INTEGER; + i : CARDINAL; + 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 *) +END; +(* search backwards through all DVI pages for lowest matching page *) +atleastone := FALSE; +nextbop := lastbop; +FOR i := totalpages TO 1 BY -1 DO + DVIoffset := nextbop + 1; + ReadBopParameters; (* update currTeXpage and prevbop *) + IF CurrMatchesNew(newTeXpage) THEN + currbop := nextbop; + currDVIpage := i; + atleastone := TRUE; + END; + nextbop := prevbop; +END; +IF NOT atleastone THEN (* no match, so restore currDVIpage *) + currDVIpage := savecurrDVIpage; + IF currDVIpage <> 0 THEN (* 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; + RETURN FALSE; +ELSE (* we found lowest matching page *) + DVIoffset := currbop + 1; +END; +ReadBopParameters; (* update currTeXpage and prevbop *) +RETURN TRUE; +END MoveToTeXPage; + +(******************************************************************************) + +PROCEDURE CurrMatchesNew (VAR newTeXpage : TeXpageinfo) : BOOLEAN; + +(* Return TRUE iff currTeXpage matches newTeXpage. *) + +VAR i : [0..9]; + +BEGIN +WITH newTeXpage DO + FOR i := 0 TO lastvalue DO + IF present[i] AND (value[i] <> currTeXpage[i]) THEN + RETURN FALSE; + END; + END; +END; +RETURN TRUE; +END CurrMatchesNew; + + +(******************************************************************************* + 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 *) + + maxint = 2147483647; (* SYSDEP: 2^31 - 1 *) + maxstacksize = 100; (* maximum stack size for state values *) + maxdrift = 2; (* prevent hh & vv from drifting too far *) + +VAR + DVIcommand : [0..255]; (* holds next DVI command *) + maxstack, (* max pushes over pops in DVI file *) + num, (* DVI numerator *) + den : CARDINAL; (* 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, (* h and v in pixels *) + 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..maxstacksize-1] 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 *) + ruletail : ruleinfoptr; (* tail of rule information list *) + thischar : charinfoptr; (* temporary pointer to node in charlist *) + +(******************************************************************************) + +PROCEDURE SetConversionFactor (resolution, magnification : CARDINAL); + +(* Client module must help calculate conv, the number of pixels per DVI unit. *) + +BEGIN +conv := FLOAT(num)/254000.0 * FLOAT(resolution)/FLOAT(den) * + FLOAT(magnification)/1000.0; +END SetConversionFactor; + +(******************************************************************************) + +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 various data structures exported by DVIReader. +*) + +VAR param : 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: + <set1, w0, right3, push/pop, x0, w3, y0, fntnum25, right2, fntnum31, + down3, x2, right4, w2, x3, down4, z0, fntnum8, setrule, y3, etc. + *) + IF DVIcommand < set1 THEN DoSetChar(DVIcommand); (* 0..127 *) + ELSIF DVIcommand = w0 THEN DoRight(w); + ELSIF DVIcommand = right3 THEN DoRight(SignedDVITrio()); + ELSIF DVIcommand = push THEN DoPush; + ELSIF DVIcommand = pop THEN DoPop; + ELSIF DVIcommand = x0 THEN DoRight(x); + ELSIF DVIcommand = w3 THEN w := SignedDVITrio(); DoRight(w); + ELSIF DVIcommand = y0 THEN DoDown(y); + + ELSIF (DVIcommand > z4) AND (DVIcommand < fnt1) (* fntnum0..fntnum63 *) + THEN DoFont(DVIcommand - fntnum0); + + (* catch all the remaining movement commands *) + ELSIF (DVIcommand > pop) AND (DVIcommand < fntnum0) THEN + IF DVIcommand = right2 THEN DoRight(SignedDVIPair()); + ELSIF DVIcommand = right4 THEN DoRight(SignedDVIQuad()); + ELSIF DVIcommand = x2 THEN x := SignedDVIPair(); DoRight(x); + ELSIF DVIcommand = x3 THEN x := SignedDVITrio(); DoRight(x); + ELSIF DVIcommand = down3 THEN DoDown(SignedDVITrio()); + ELSIF DVIcommand = down4 THEN DoDown(SignedDVIQuad()); + ELSIF DVIcommand = w2 THEN w := SignedDVIPair(); DoRight(w); + ELSIF DVIcommand = z0 THEN DoDown(z); + ELSIF DVIcommand = y3 THEN y := SignedDVITrio(); DoDown(y); + ELSIF DVIcommand = z3 THEN z := SignedDVITrio(); DoDown(z); + ELSIF DVIcommand = down2 THEN DoDown(SignedDVIPair()); + (* the next DVI commands are used very rarely (by TeX 1.3 at least) *) + ELSIF DVIcommand = w1 THEN w := SignedDVIByte(); DoRight(w); + ELSIF DVIcommand = w4 THEN w := SignedDVIQuad(); DoRight(w); + ELSIF DVIcommand = x1 THEN x := SignedDVIByte(); DoRight(x); + ELSIF DVIcommand = x4 THEN x := SignedDVIQuad(); DoRight(x); + ELSIF DVIcommand = y1 THEN y := SignedDVIByte(); DoDown(y); + ELSIF DVIcommand = y2 THEN y := SignedDVIPair(); DoDown(y); + ELSIF DVIcommand = y4 THEN y := SignedDVIQuad(); DoDown(y); + ELSIF DVIcommand = z1 THEN z := SignedDVIByte(); DoDown(z); + ELSIF DVIcommand = z2 THEN z := SignedDVIPair(); DoDown(z); + ELSIF DVIcommand = z4 THEN z := SignedDVIQuad(); DoDown(z); + ELSIF DVIcommand = right1 THEN DoRight(SignedDVIByte()); + ELSIF DVIcommand = down1 THEN DoDown(SignedDVIByte()); + ELSE (* DEBUG + (* will only occur if we've missed a movement command *) + WriteLn; WriteString('Bug in InterpretPage!'); WriteLn; Halt(2); + GUBED *) + DVIErrorRoutine(DVIcatastrophe); + END; + + ELSIF DVIcommand = setrule THEN DoSetRule(SignedDVIQuad(),SignedDVIQuad()); + ELSIF DVIcommand = putrule THEN DoPutRule(SignedDVIQuad(),SignedDVIQuad()); + + ELSIF (DVIcommand >= put1) AND (DVIcommand <= put1+3) THEN + CASE DVIcommand - put1 OF + 0 : DoPutChar(GetDVIByte()) | + 1 : DoPutChar(GetTwoDVIBytes()) | + 2 : DoPutChar(GetThreeDVIBytes()) | + 3 : DoPutChar(SignedDVIQuad()) + END; + + ELSIF (DVIcommand >= set1) AND (DVIcommand <= set1+3) THEN + CASE DVIcommand - set1 OF + 0 : DoSetChar(GetDVIByte()) | + 1 : DoSetChar(GetTwoDVIBytes()) | + 2 : DoSetChar(GetThreeDVIBytes()) | + 3 : DoSetChar(SignedDVIQuad()) + END; + + ELSIF (DVIcommand >= fnt1) AND (DVIcommand <= fnt1+3) THEN + CASE DVIcommand - fnt1 OF + 0 : DoFont(GetDVIByte()) | + 1 : DoFont(GetTwoDVIBytes()) | + 2 : DoFont(GetThreeDVIBytes()) | + 3 : DoFont(SignedDVIQuad()) + END; + + ELSIF (DVIcommand >= xxx1) AND (DVIcommand <= xxx1+3) THEN + CASE DVIcommand - xxx1 OF + 0 : param := GetDVIByte() | + 1 : param := GetTwoDVIBytes() | + 2 : param := GetThreeDVIBytes() | + 3 : param := SignedDVIQuad() + END; + (* Pass current pixel position, number of bytes and + byte grabbing function for client to use. + We use IgnoreSpecial if client does not assign a procedure. + *) + SpecialRoutine(hh, vv, param, GetDVIByte); + + (* skip fntdef command since we've got this info from postamble *) + ELSIF (DVIcommand >= fntdef1) AND (DVIcommand <= fntdef1+3) + THEN SkipFntdef(DVIcommand - fntdef1); + + ELSIF DVIcommand = nop THEN (* do nothing *) + ELSIF DVIcommand = eop THEN (* do nothing *) + ELSE + (* DEBUG + WriteLn; + WriteString('Unexpected DVI command while interpreting page = '); + WriteCard(DVIcommand); WriteLn; + Halt(2); + GUBED *) + DVIErrorRoutine(DVIcatastrophe); + END; +UNTIL DVIcommand = eop; +(* save position of eop byte for use in MoveToTeXPage *) +curreop := DVIoffset - 1; +IF stackpos <> 0 THEN + (* DEBUG + WriteString('Stack not empty at eop!'); WriteLn; + Halt(2); + GUBED *) + DVIErrorRoutine(DVIcatastrophe); +END; +pageempty := (minhp = maxint) AND (minvp = maxint) AND + (maxhp = -maxint) AND (maxvp = -maxint); (* InitPage values *) +END InterpretPage; + +(******************************************************************************) + +PROCEDURE InitStateValues; + +(* Initialize the 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(FLOAT(hoffset) / conv + 0.5); +ELSE + h := - TRUNC(FLOAT(ABS(hoffset)) / conv + 0.5); +END; +IF voffset >= 0 THEN + v := TRUNC(FLOAT(voffset) / conv + 0.5); +ELSE + v := - TRUNC(FLOAT(ABS(voffset)) / conv + 0.5); +END; +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 structures so there are no fonts, no chars and no rules. *) + +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 + IF fontused THEN (* 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 + thischar := charlist; + charlist := thischar^.nextchar; + DISPOSE(thischar); + END; + chartail := NIL; + (* pixel table remains allocated *) + END; + currfont := nextfont; + END; +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 + thisrule := rulelist; + rulelist := thisrule^.nextrule; + DISPOSE(thisrule); +END; +rulelist^.rulecount := 0; (* no rules in this node *) +rulelist^.nextrule := NIL; +END InitPage; + +(******************************************************************************) + +PROCEDURE DoSetChar (ch : CARDINAL); + +(* Add char info to current chartable, update our horizontal + position on the page and check the page edges. +*) + +BEGIN +WITH currfont^ DO + IF ch > maxTeXchar THEN + DVIErrorRoutine(DVIbadchar); + RETURN; (* ignore ch *) + END; + WITH chartail^ DO + IF charcount = chartablesize THEN (* 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; + END; + WITH chartail^ DO (* may be new chartable *) + WITH chartable[charcount] DO + hp := hh; + vp := vv; + code := ch; + END; + WITH pixelptr^[ch] DO + (* do page edges increase? *) + IF vv - yo < minvp THEN minvp := vv - yo END; + IF hh - xo < minhp THEN minhp := hh - xo END; + IF vv + (ht - yo - 1) > maxvp THEN maxvp := vv + (ht - yo - 1) END; + IF hh + (wd - xo - 1) > maxhp THEN maxhp := hh + (wd - xo - 1) END; + (* the above checks ensure that page edges include all black + pixels in glyph, but we also want to include reference point *) + IF hh < minhp THEN minhp := hh END; + IF vv < minvp THEN minvp := vv END; + IF hh > maxhp THEN maxhp := hh END; + IF vv > maxvp THEN maxvp := vv END; + (* 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; + END; + END; + (* add DVI width calculated in PixelTableRoutine *) + h := h + dwidth; + END; + INC(totalchars); + INC(charcount); + END; +END; +END DoSetChar; + +(******************************************************************************) + +PROCEDURE DoPutChar (ch : CARDINAL); + +(* Exactly the same as DoSetChar, but we DON'T update the horizontal + position on the page. (We still have to check page edges.) +*) + +BEGIN +WITH currfont^ DO + IF ch > maxTeXchar THEN + DVIErrorRoutine(DVIbadchar); + RETURN; (* ignore ch *) + END; + WITH chartail^ DO + IF charcount = chartablesize THEN (* 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; + END; + WITH chartail^ DO (* may be new chartable *) + WITH chartable[charcount] DO + hp := hh; + vp := vv; + code := ch; + END; + WITH pixelptr^[ch] DO + (* do page edges increase? *) + IF vv - yo < minvp THEN minvp := vv - yo END; + IF hh - xo < minhp THEN minhp := hh - xo END; + IF vv + (ht - yo - 1) > maxvp THEN maxvp := vv + (ht - yo - 1) END; + IF hh + (wd - xo - 1) > maxhp THEN maxhp := hh + (wd - xo - 1) END; + (* the above checks ensure that page edges include all black + pixels in glyph, but we also want to include reference point *) + IF hh < minhp THEN minhp := hh END; + IF vv < minvp THEN minvp := vv END; + IF hh > maxhp THEN maxhp := hh END; + IF vv > maxvp THEN maxvp := vv END; + END; + INC(totalchars); + INC(charcount); + END; +END; +END DoPutChar; + +(******************************************************************************) + +PROCEDURE PixelRound (DVIunits : INTEGER) : INTEGER; + +(* Return the nearest number of pixels in the given DVI dimension. *) + +BEGIN +IF DVIunits > 0 THEN + RETURN TRUNC(conv * FLOAT(DVIunits) + 0.5); +ELSE + RETURN - TRUNC(conv * FLOAT(ABS(DVIunits)) + 0.5); +END; +END PixelRound; + +(******************************************************************************) + +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; +INC(stackpos); (* stackpos = next vacant position in stacks *) +END DoPush; + +(******************************************************************************) + +PROCEDURE DoPop; + +(* Pop state values from top of stack. *) + +BEGIN +(* DEBUG + IF stackpos = 0 THEN + WriteString('Stack empty!'); WriteLn; + Halt(2); + END; +GUBED *) +DEC(stackpos); +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 + 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; + END; +ELSE + hh := PixelRound(h + amount); +END; +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 + 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; + END; +ELSE + vv := PixelRound(v + amount); +END; +v := v + amount; +END DoDown; + +(******************************************************************************) + +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 + WITH ruletail^ DO + IF rulecount = ruletablesize THEN (* 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; + END; + WITH ruletail^ DO (* may be new ruletable *) + WITH ruletable[rulecount] DO + hp := hh; + vp := vv; + wd := RulePixels(width); + ht := RulePixels(height); + (* do page edges increase? *) + IF vv - (ht - 1) < minvp THEN minvp := vv - (ht - 1) END; + IF hh + (wd - 1) > maxhp THEN maxhp := hh + (wd - 1) END; + (* ref pt of rule is bottom left black pixel *) + IF vv > maxvp THEN maxvp := vv END; + IF hh < minhp THEN minhp := hh END; + 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; + END; + END; + h := h + width; + END; + INC(totalrules); + INC(rulecount); + 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 + WITH ruletail^ DO + IF rulecount = ruletablesize THEN (* 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; + END; + WITH ruletail^ DO (* may be new ruletable *) + WITH ruletable[rulecount] DO + hp := hh; + vp := vv; + wd := RulePixels(width); + ht := RulePixels(height); + (* do page edges increase? *) + IF vv - (ht - 1) < minvp THEN minvp := vv - (ht - 1) END; + IF hh + (wd - 1) > maxhp THEN maxhp := hh + (wd - 1) END; + (* ref pt of rule is bottom left black pixel *) + IF vv > maxvp THEN maxvp := vv END; + IF hh < minhp THEN minhp := hh END; + END; + INC(totalrules); + INC(rulecount); + END; +END; +END DoPutRule; + +(******************************************************************************) + +PROCEDURE 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 * FLOAT(DVIunits)); +IF FLOAT(n) < conv * FLOAT(DVIunits) THEN RETURN n + 1 ELSE RETURN n END; +END RulePixels; + +(******************************************************************************) + +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 client routine to fill it in. +*) + +BEGIN +currfont := fontlist; +WHILE (currfont <> NIL) AND (currfont^.fontnum <> externf) DO + currfont := currfont^.nextfont; +END; +IF currfont = NIL THEN + (* DEBUG + WriteLn; WriteString('Failed to find font #'); WriteInt(externf); + WriteLn; Halt(2); + GUBED *) + DVIErrorRoutine(DVIcatastrophe); +END; +WITH currfont^ DO + IF fontused THEN + (* do nothing since we've already used this font on this page *) + ELSE + fontused := TRUE; + NEW(charlist); (* allocate first chartable *) + WITH charlist^ DO + charcount := 0; (* for DoSet/PutChar *) + nextchar := NIL; (* this node is also last *) + END; + chartail := charlist; + IF pixelptr = NIL THEN (* first time we've seen this font requested *) + NEW(pixelptr); + PixelTableRoutine; (* call client routine to build pixel table *) + 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 IgnoreSpecial(xpos, ypos, (* in *) + specialbytes : INTEGER; (* in *) + GetNextByte : GetByteFunction); (* in *) + +(* Default SpecialRoutine simply skips bytes given to TeX's \special command. *) + +VAR i, unused : INTEGER; + +BEGIN +FOR i := 1 TO specialbytes DO + unused := GetNextByte(); +END; +END IgnoreSpecial; + +(******************************************************************************) + +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. +*) + +VAR newfontlist, prevfont, largest, prevlargest : fontinfoptr; + mostchars : CARDINAL; + +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 + prevfont := currfont; (* remember previous node *) + currfont := nextfont; + ELSE + (* move node from fontlist to head of newfontlist + and don't change prevfont + *) + IF prevfont = NIL THEN + fontlist := nextfont; (* remove first node in fontlist *) + nextfont := newfontlist; + newfontlist := currfont; + currfont := fontlist; + ELSE + prevfont^.nextfont := nextfont; + nextfont := newfontlist; + newfontlist := currfont; + currfont := prevfont^.nextfont; + END; + END; + END; +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 + prevfont := NIL; + currfont := fontlist; + prevlargest := NIL; + largest := fontlist; + mostchars := 0; + WHILE currfont <> NIL DO (* search for largest totalchars *) + WITH currfont^ DO + IF totalchars > mostchars THEN + prevlargest := prevfont; + largest := currfont; + mostchars := totalchars; + END; + prevfont := currfont; + currfont := nextfont; + END; + END; + (* move largest node from fontlist to head of newfontlist *) + WITH largest^ DO + IF prevlargest = NIL THEN + fontlist := nextfont; (* remove first node in fontlist *) + ELSE + prevlargest^.nextfont := nextfont; + END; + 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. *) + +BEGIN +status := SYS$DELTVA(ADR(vas),ADR(vas),0); +IF NOT ODD(status) THEN + (* DEBUG + WriteString('SYS$DELTVA failed! status='); WriteCard(status); + WriteLn; Halt(2); + GUBED *) + DVIErrorRoutine(DVIcatastrophe); +END; +status := SYS$DASSGN(channel); +IF NOT ODD(status) THEN + (* DEBUG + WriteString('SYS$DASSGN failed! status='); WriteCard(status); + WriteLn; Halt(2); + GUBED *) + DVIErrorRoutine(DVIcatastrophe); +END; +WHILE fontlist <> NIL DO + currfont := fontlist; + WITH currfont^ DO + WHILE charlist <> NIL DO (* deallocate char list *) + thischar := charlist; + charlist := thischar^.nextchar; + DISPOSE(thischar); + END; + IF pixelptr <> NIL THEN + DISPOSE(pixelptr); (* deallocate pixel table *) + END; + fontlist := nextfont; + END; + DISPOSE(currfont); (* deallocate font information *) +END; +(* Deallocate rule information except for one node (in case client opens + another DVI file). +*) +WHILE rulelist <> ruletail DO + thisrule := rulelist; + rulelist := thisrule^.nextrule; + DISPOSE(thisrule); +END; +END CloseDVIFile; + +(******************************************************************************) + +BEGIN +totalrules := 0; +NEW(rulelist); (* for first InitPage *) +ruletail := rulelist; (* ditto *) +fontlist := NIL; (* safer for CloseDVIFile *) +SpecialRoutine := IgnoreSpecial; (* client can reassign *) +END DVIReader. diff --git a/dviware/psprint/vms/fontlist.ps b/dviware/psprint/vms/fontlist.ps new file mode 100644 index 0000000000..5175bdf4e4 --- /dev/null +++ b/dviware/psprint/vms/fontlist.ps @@ -0,0 +1,20 @@ +% Produces a list of all known fonts currently available in printer. + +/showline { gsave show grestore 0 -12 rmoveto } def +/Times-Roman findfont 12 scalefont setfont +/s40 40 string def + +36 700 moveto +FontDirectory {pop s40 cvs showline} forall + +( ) showline +(Total memory: ) showline +vmstatus s40 cvs showline +(Memory used: ) showline +s40 cvs showline +pop +( Free memory: ) showline +vmstatus exch sub s40 cvs showline +pop + +showpage diff --git a/dviware/psprint/vms/fontreade.def b/dviware/psprint/vms/fontreade.def new file mode 100644 index 0000000000..43806cb203 --- /dev/null +++ b/dviware/psprint/vms/fontreade.def @@ -0,0 +1,52 @@ +DEFINITION MODULE FontReader; + +(* Author: Andrew Trevorrow + Implementation: University of Hamburg Modula-2 under VAX/VMS version 4 + Date Started: November, 1986 + + Description: + Routines for reading font files in a variety of formats. + + Revised: + December, 1986 + - GetBitmap is now called LoadBitmap and is used by PSDVI to send the + PostScript code representing the bitmap and metric information for a + given character from a given font. +*) + +FROM DVIReader IMPORT + fontinfoptr; + +VAR + FillPixelTable : PROC; + (* Fill currfont^.pixelptr with info from the currently open font file. *) + + LoadBitmap : PROCEDURE (fontinfoptr, (* for currently open font *) + CARDINAL); (* char code *) + (* Download PostScript bitmap and metrics for the given character + using raster info at mapadr in the currently open font file. + *) + +PROCEDURE InitFontReader; +(* Use the /FONT_DIRECTORY and /DUMMY_FONT values to assign appropriate + routines to the above procedure variables, and to decide on the format + of file specifications created by BuildFontSpec. +*) + +PROCEDURE BuildFontSpec (fontptr : fontinfoptr; VAR firstn, lastn : CARDINAL); +(* Build a complete file specification in fontptr^.fontspec and + return the starting and ending positions of the font size substring. + This will only be done once per font; fontspeclen will no longer be 0. + fontptr^.fontexists becomes TRUE if the file can be found. +*) + +PROCEDURE OpenFontFile (VAR filespec : ARRAY OF CHAR) : BOOLEAN; +(* Return TRUE if given font file is successfully opened. + The value of filespec is not changed; it is declared a VAR parameter + for efficiency reasons. +*) + +PROCEDURE CloseFontFile; +(* Close the currently open font file. *) + +END FontReader. diff --git a/dviware/psprint/vms/fontreade.mod b/dviware/psprint/vms/fontreade.mod new file mode 100644 index 0000000000..223b76cef4 --- /dev/null +++ b/dviware/psprint/vms/fontreade.mod @@ -0,0 +1,1242 @@ +IMPLEMENTATION MODULE FontReader; + +(* Author: Andrew Trevorrow + Implementation: University of Hamburg Modula-2 under VAX/VMS version 4 + Date Started: May, 1985 + + Description: + This module can extract font information from PXL, PK or TFM files. + (GF files are not handled; it is assumed that sites with GF files will + decide to convert them to PK files sooner or later!) + Each type of font file is considered to be an array of 8-bit bytes. + Only one font file is open at any time. We move to byte positions using + byteoffset and read bytes and words using GetByte, SignedQuad, etc. + + Revised: + June, 1985 + - Use Halt(2) instead of HALT. + + August, 1985 + - Use ScreenIO routines when debugging. + + September, 1985 + - Added GetPXLGlyph and associated glyph cacheing code. + + October, 1985 + - Removed above cacheing stuff! Now use SYS$CRMPSC to map an + entire PXL file into virtual memory where it is treated as an array of bytes. + + March, 1986 + - Amendments to Modula-2 language required a few minor syntactic changes. + + November, 1986 + - PXLReader has been expanded and is now called FontReader. + All font-dependent code has been moved out of PSDVI's main module. + A new font format can be handled just by adding code to FontReader. + - Reduced page fault cluster size from 36 to 16 because PK files are smaller. + - Always start fontspec with fontdir; fontarea is really only for TFM files. + + December, 1986 + - GetBitmap now called LoadBitmap and uses Put routines from PSWriter to + send bitmap and metric info directly to output file. + + November, 1987 (while at The Open University) + - Added charsperline code to LoadBitmap routines so that output lines + don't get too long. + - Added code to handle PostScript fonts (for which only TFM files exist). + BuildFontSpec now checks for a fontname beginning with "PS-" and sets the + font's psfont flag. If TRUE then we must construct a TFM filespec + (starting with tfmdir or fontarea if fontarealen > 0) and later fill + the font's pixeltable with character info from that TFM file. + - Renamed ConvertTFMWidth to FixToDVI. + - PXL/PKFillPixelTable now call TFMFillPixelTable if the font is + a PostScript font (and its TFM file could be opened). + + June--August, 1988 (while at Aston University) + - Now use /psprefix value to check for a PostScript font. + - Changed BuildFontSpec so that the fontsize substring no longer has to + be the same length in all font files. + + September--October, 1989 (while at Aston University, 2nd time) + - Fixed bug reported by Niel Kempson in FixToDVI. +*) + +FROM SYSTEM IMPORT + ADDRESS, ADR, BYTE, WORD; + +FROM VMS IMPORT + SYS$OPEN, SYS$CRMPSC, SYS$DASSGN, SYS$DELTVA; + +FROM SECDefinitions IMPORT + SEC$V_EXPREG; + +FROM RMS IMPORT + FAB, InitFab, + FOPset, FOPtype, + FACset, FACtype, + SHRset, SHRtype; + +FROM FileSystem IMPORT + File, Open, Done, Close; + +FROM Options IMPORT + psprefix, tfmdir, fontdir, dummyfont, mag, resolution, Cap; + +FROM DVIReader IMPORT + (* CONST *) + maxfontspec, maxTeXchar, + (* TYPE *) + fontstring, fontinfo, fontinfoptr, + pixeltable, pixeltableptr, + (* VAR *) + currfont, + (* PROCEDURE *) + PixelRound; + +FROM PSWriter IMPORT + Put, PutString, PutInt, PutCard; + +FROM TermOut IMPORT + WriteString, WriteCard, WriteInt, WriteLn, Halt; + +CONST + NULL = 0C; (* SYSDEP: used to terminate a string if not full *) + CR = 15C; (* used in LoadBitmap *) + +TYPE + (* font files should never have more than MAX(INTEGER) bytes! *) + fontfile = ARRAY [0..MAX(INTEGER)] OF BYTE; + filepointer = POINTER TO fontfile; (* never allocated! *) + +VAR + vas : ARRAY [0..1] OF ADDRESS; (* start and end virtual addresses *) + filestart : filepointer; (* pointer to starting address of file *) + byteoffset, (* byte offset from start of file *) + channel : CARDINAL; (* fab.STV returned by SYS$OPEN *) + gsdnam : ARRAY [0..42] OF CHAR; (* unused argument in SYS$CRPMSC *) + status : CARDINAL; + fab : FAB; + psprefixlen, (* length of psprefix string *) + fontdirlen, (* length of fontdir string *) + dummyfontlen : CARDINAL; (* length of dummyfont string *) + formatstr : ARRAY [0..2] OF CHAR; (* PXL or PK *) + formatlen : CARDINAL; (* 3 or 2 *) + xfactor : REAL; (* resolution/200 or resolution/1000 *) + hexdigs : ARRAY [0..15] OF CHAR; (* 0..9ABCDEF for LoadBitmap *) + gpower : ARRAY [0..8] OF BITSET; (* 0,1,11,111,1111,...,11111111 *) + CompleteFontSpec : (* used by BuildFontSpec *) + PROCEDURE (fontinfoptr, + CARDINAL, + CARDINAL, + VAR CARDINAL) : BOOLEAN; + +(******************************************************************************) + +PROCEDURE InitFontReader; + +(* Assign font-dependent routines to various procedure variables + according to information present in fontdir and dummyfont: + + - The last character in dummyfont defines the font format (PXL or PK). + All font files are assumed to be in the same format. + Note that the Options module has prefixed dummyfont with fontdir. + + - The last two characters in fontdir define the structure of each file spec. + If ".]" then all font files are assumed to reside in subdirectories of + fontdir, and the name of each subdirectory is the font size. + A typical dummyfont value would be TEX_DISK:[TEX.PXL.][1500]CMR10.PXL. + This is the storage scheme used in K&S's old VMS TeX distributions. + If not ".]" then all font files are assumed to be in kept in fontdir, + and the font size is included in the file type. + A typical dummyfont value would be TEX_DISK:[TEX.PK]CMR10.300PK. + This type of scheme is used in the latest VMS TeX distributions. + + - The dummyfont must contain a font size substring representing + an unmagnified font. Its value, along with /RESOLUTION, is used to + decide how to calculate the font sizes in all other font files. +*) + +VAR + i, + fontsizelen, (* length of n...n in dummyfont *) + dummyfontsize : CARDINAL; (* value of n...n in dummyfont *) + +BEGIN +hexdigs := "0123456789ABCDEF"; (* for LoadBitmap *) +dummyfontlen := LEN(dummyfont); +IF dummyfontlen = 0 THEN dummyfontlen := 1 END; (* last char will be NULL *) +CASE Cap(dummyfont[dummyfontlen-1]) OF (* last char defines format *) + 'L' : formatstr := 'pxl'; + formatlen := 3; + FillPixelTable := PXLFillPixelTable; + LoadBitmap := PXLLoadBitmap; + | 'K' : formatstr := 'pk'; + formatlen := 2; + FillPixelTable := PKFillPixelTable; + LoadBitmap := PKLoadBitmap; + gpower[0] := {}; + FOR i := 1 TO 8 DO + gpower[i] := gpower[i-1] + {i-1}; (* used in PKLoadBitmap *) + END; +ELSE + WriteString('/DUMMY_FONT value should end with PXL or PK.'); WriteLn; + Halt(2); +END; +psprefixlen := LEN(psprefix); +fontdirlen := LEN(fontdir); +IF (fontdirlen > 1) AND (fontdir[fontdirlen-2] = '.') AND + (fontdir[fontdirlen-1] = ']') THEN + (* assume font files are kept in subdirectories of fontdir + and have fontspecs like TEX_DISK:[TEX.subdir.][n...n]CMR10.fmt + *) + CompleteFontSpec := OldFontSpec; + i := fontdirlen + 1; (* first n after .][ *) +ELSE + (* assume font files are all kept in fontdir + and have fontspecs like TEX_DISK:[TEX.subdir]CMR10.n...nfmt + *) + CompleteFontSpec := NewFontSpec; + i := fontdirlen; (* first char after ] *) + WHILE (i < dummyfontlen) AND (dummyfont[i] <> '.') DO + INC(i); + END; + INC(i); (* first n after '.' *) +END; +fontsizelen := 0; +dummyfontsize := 0; +WHILE (i < dummyfontlen) AND (dummyfont[i] >= '0') AND (dummyfont[i] <= '9') DO + INC(fontsizelen); + dummyfontsize := dummyfontsize * 10 + (ORD(dummyfont[i]) - ORD('0')); + INC(i); +END; +IF fontsizelen > 0 THEN + (* The xfactor used to calculate fontsize in BuildFontSpec depends on the + fontsize in dummyfont (assumed to be an unmagnified font). + *) + IF FLOAT(dummyfontsize) / FLOAT(resolution) > 1.0 THEN + xfactor := FLOAT(resolution) / 200.0; (* old naming convention *) + ELSE + xfactor := FLOAT(resolution) / 1000.0; (* new naming convention *) + END; +ELSE + WriteString('/DUMMY_FONT value does not contain font size!'); WriteLn; + Halt(2); +END; +END InitFontReader; + +(******************************************************************************) + +PROCEDURE BuildFontSpec (fontptr : fontinfoptr; VAR firstn, lastn : CARDINAL); + +VAR + f : File; + i, j, next, fontsize, tempsize, tempsizelen : CARDINAL; + +BEGIN +WITH fontptr^ DO + (* 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; + LOOP + IF i = psprefixlen THEN EXIT END; + IF Cap(fontname[i]) <> Cap(psprefix[i]) THEN + psfont := FALSE; + EXIT; + END; + INC(i); + END; + IF psfont THEN + BuildTFMSpec(fontptr); (* build TFM file spec *) + RETURN; + END; + i := 0; + next := fontdirlen; + REPEAT + fontspec[i] := fontdir[i]; (* start fontspec with fontdir *) + INC(i); + UNTIL (i = next) OR (i > maxfontspec); + IF next >= maxfontspec THEN + fontspeclen := maxfontspec; + RETURN; (* fontspec truncated *) + END; + fontsize := TRUNC( FLOAT(mag) * (FLOAT(scaledsize) / FLOAT(designsize)) + * xfactor + 0.5 ); + IF fontsize = 0 THEN + INC(fontsize); (* allow for subtracting 1 *) + END; + tempsize := fontsize; + i := 1; + LOOP + (* Complete rest of fontspec starting at next + 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 + INC(tempsizelen); + j := j DIV 10; + END; + IF NOT CompleteFontSpec(fontptr, next, tempsizelen, firstn) THEN + RETURN; (* fontspec truncated *) + END; + lastn := firstn + tempsizelen - 1; + (* put tempsize into fontspec[firstn..lastn] *) + FOR j := lastn TO firstn BY -1 DO + fontspec[j] := CHR(ORD('0') + (tempsize MOD 10)); + tempsize := tempsize DIV 10; + END; + IF i > 3 THEN (* original fontsize has been restored *) + RETURN; (* could not open fontspec *) + END; + Open(f,fontspec,FALSE); (* SYSDEP: try to open for reading *) + IF Done() THEN + Close(f); + fontexists := TRUE; (* fontspec exists *) + RETURN; + ELSIF i = 1 THEN + tempsize := fontsize - 1; (* try fontsize - 1 *) + ELSIF i = 2 THEN + tempsize := fontsize + 1; (* try fontsize + 1 *) + ELSE + tempsize := fontsize; (* restore original fontsize *) + END; + INC(i); + END; +END; +END BuildFontSpec; + +(******************************************************************************) + +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. +*) + +VAR f : File; i, next : CARDINAL; + +BEGIN +WITH fontptr^ DO + i := 0; + IF fontarealen > 0 THEN + next := fontarealen; + REPEAT + fontspec[i] := fontarea[i]; (* start fontspec with fontarea *) + INC(i); + UNTIL (i = next) OR (i > maxfontspec); + ELSE + next := LEN(tfmdir); (* assume > 0 *) + REPEAT + fontspec[i] := tfmdir[i]; (* start fontspec with tfmdir *) + INC(i); + UNTIL (i = next) OR (i > maxfontspec); + END; + IF next >= maxfontspec THEN + fontspeclen := maxfontspec; + RETURN; (* fontspec truncated *) + END; + (* next is current length of fontspec; append fontname.tfm *) + i := 0; + WHILE (i < fontnamelen) AND (next < maxfontspec) DO + fontspec[next] := fontname[i]; (* append fontname *) + INC(i); + INC(next); + END; + IF next + 4 <= maxfontspec THEN (* append .tfm *) + fontspec[next] := '.'; INC(next); + fontspec[next] := 't'; INC(next); + fontspec[next] := 'f'; INC(next); + fontspec[next] := 'm'; INC(next); + ELSE + fontspeclen := maxfontspec; + RETURN; (* fontspec truncated *) + END; + fontspeclen := next; + (* SYSDEP: terminate fontspec with NULL *) + IF fontspeclen < maxfontspec THEN fontspec[fontspeclen] := NULL END; + Open(f,fontspec,FALSE); (* SYSDEP: try to open for reading *) + IF Done() THEN + Close(f); + fontexists := TRUE; (* fontspec exists *) + END; +END; +END BuildTFMSpec; + +(******************************************************************************) + +PROCEDURE OldFontSpec (fontptr : fontinfoptr; + next : CARDINAL; + fontsizelen : CARDINAL; + VAR firstn : CARDINAL) : BOOLEAN; + +(* Return TRUE if we can append "[n...n]fontname.fmt" to fontspec. + Such a scheme is used in old TeX distributions from Kellerman and Smith. +*) + +VAR i : CARDINAL; + +BEGIN +WITH fontptr^ DO + firstn := next + 1; (* position of 1st n *) + IF next + fontsizelen + 1 < maxfontspec THEN (* append [n...n] *) + fontspec[next] := '['; + INC(next,fontsizelen + 1); (* skip n...n *) + fontspec[next] := ']'; + INC(next); + ELSE + fontspeclen := maxfontspec; + RETURN FALSE; (* fontspec truncated *) + END; + i := 0; + WHILE (i < fontnamelen) AND (next < maxfontspec) DO + fontspec[next] := fontname[i]; (* append fontname *) + INC(i); + INC(next); + END; + IF next + formatlen < maxfontspec THEN (* append .fmt *) + fontspec[next] := '.'; INC(next); + i := 0; + REPEAT + fontspec[next] := formatstr[i]; + INC(i); + INC(next); + UNTIL i = formatlen; + ELSE + fontspeclen := maxfontspec; + RETURN FALSE; (* fontspec truncated *) + END; + fontspeclen := next; + (* SYSDEP: terminate fontspec with NULL *) + IF fontspeclen < maxfontspec THEN fontspec[fontspeclen] := NULL END; + RETURN TRUE; +END; +END OldFontSpec; + +(******************************************************************************) + +PROCEDURE NewFontSpec (fontptr : fontinfoptr; + next : CARDINAL; + fontsizelen : CARDINAL; + VAR firstn : CARDINAL) : BOOLEAN; + +(* Return TRUE if we can append "fontname.n...nfmt" to fontspec. + Such a scheme is used in the latest TeX distributions. +*) + +VAR i : CARDINAL; + +BEGIN +WITH fontptr^ DO + i := 0; + WHILE (i < fontnamelen) AND (next < maxfontspec) DO + fontspec[next] := fontname[i]; (* append fontname *) + INC(i); + INC(next); + END; + firstn := next + 1; (* position of 1st n *) + IF next + fontsizelen + formatlen < maxfontspec THEN (* append .n...nfmt *) + fontspec[next] := '.'; + INC(next,fontsizelen + 1); (* skip n...n *) + i := 0; + REPEAT + fontspec[next] := formatstr[i]; + INC(i); + INC(next); + UNTIL i = formatlen; + ELSE + fontspeclen := maxfontspec; + RETURN FALSE; (* fontspec truncated *) + END; + fontspeclen := next; + (* SYSDEP: terminate fontspec with NULL *) + IF fontspeclen < maxfontspec THEN fontspec[fontspeclen] := NULL END; + RETURN TRUE; +END; +END NewFontSpec; + +(******************************************************************************) + +PROCEDURE OpenFontFile (VAR fspec : ARRAY OF CHAR) : BOOLEAN; + +(* Return TRUE iff given file can be opened and mapped into virtual memory. *) + +BEGIN +InitFab(fab); (* initialize fab *) +WITH fab DO + FNA := ADR(fspec); (* file specification *) + FNS := BYTE(LEN(fspec)); (* bytes in file name *) + FAC := FACset{FAC$BRO,FAC$GET}; (* read-only *) + SHR := SHRset{SHR$GET}; (* share file with other readers *) + FOP := FOPset{FOP$UFO}; (* need for SYS$CRMPSC *) + RTV := BYTE(-1); (* for more efficient mapping *) +END; +status := SYS$OPEN(ADR(fab),0,0); (* open the file *) +IF ODD(status) THEN + channel := fab.STV; (* channel on which file is open *) + vas[0] := 0; + vas[1] := 0; + status := SYS$CRMPSC (* map file into virtual address space *) + (ADR(vas), (* starting and ending addresses *) + ADR(vas), (* addresses returned *) + 0, + {SEC$V_EXPREG}, (* pages mapped into 1st available space *) + gsdnam,0,0, + channel, (* channel on which file has been opened *) + 0,0,0, + 16 (* page fault cluster size *) + ); + IF NOT ODD(status) THEN + (* DEBUG + WriteString('SYS$CRMPSC failed in OpenFontFile! status='); + WriteCard(status); WriteLn; Halt(2); + GUBED *) + RETURN FALSE; + ELSE + (* The entire file is mapped into virtual memory so we can + access any byte as an offset from the address in vas[0]. + *) + filestart := vas[0]; + RETURN TRUE; + END; +ELSE + RETURN FALSE; +END; +END OpenFontFile; + +(******************************************************************************) + +(* Here are the functions used to get byte/s from fontfile. *) + +PROCEDURE GetByte () : CARDINAL; + +(* Return the value (unsigned) of the byte at byteoffset in fontfile and + advance byteoffset for the next GetByte. +*) + +VAR b : CARDINAL; + +BEGIN +b := CARDINAL(filestart^[byteoffset]); INC(byteoffset); +RETURN b; +END GetByte; + +(******************************************************************************) + +PROCEDURE SignedByte () : INTEGER; + +(* Return the next byte, possibly signed. *) + +VAR b : CARDINAL; + +BEGIN +b := CARDINAL(filestart^[byteoffset]); INC(byteoffset); +IF b < 128 THEN + RETURN b; +ELSE + RETURN b - 256; +END; +END SignedByte; + +(******************************************************************************) + +PROCEDURE GetTwoBytes () : CARDINAL; + +(* Return the next 2 bytes, unsigned. *) + +VAR a, b : CARDINAL; + +BEGIN +a := CARDINAL(filestart^[byteoffset]); INC(byteoffset); +b := CARDINAL(filestart^[byteoffset]); INC(byteoffset); +RETURN a * 256 + b; +END GetTwoBytes; + +(******************************************************************************) + +PROCEDURE SignedPair () : INTEGER; + +(* Return the next 2 bytes, possibly signed. *) + +VAR a, b : CARDINAL; + +BEGIN +a := CARDINAL(filestart^[byteoffset]); INC(byteoffset); +b := CARDINAL(filestart^[byteoffset]); INC(byteoffset); +IF a < 128 THEN + RETURN a * 256 + b; +ELSE + RETURN (a - 256) * 256 + b; +END; +END SignedPair; + +(******************************************************************************) + +PROCEDURE GetThreeBytes () : CARDINAL; + +(* Return the next 3 bytes, unsigned. *) + +VAR a, b, c : CARDINAL; + +BEGIN +a := CARDINAL(filestart^[byteoffset]); INC(byteoffset); +b := CARDINAL(filestart^[byteoffset]); INC(byteoffset); +c := CARDINAL(filestart^[byteoffset]); INC(byteoffset); +RETURN (a * 256 + b) * 256 + c; +END GetThreeBytes; + +(******************************************************************************) + +PROCEDURE SignedQuad () : INTEGER; + +(* Return the value (possibly signed) of the 4 bytes at byteoffset and + advance byteoffset by 4. +*) + +VAR overlay : RECORD + CASE :BOOLEAN OF + TRUE : i : INTEGER | + FALSE : a,b,c,d : BYTE + END; + END; + +BEGIN +WITH overlay DO + (* SYSDEP: on a VAX, d is at least significant end of word *) + d := filestart^[byteoffset]; INC(byteoffset); + c := filestart^[byteoffset]; INC(byteoffset); + b := filestart^[byteoffset]; INC(byteoffset); + a := filestart^[byteoffset]; INC(byteoffset); + RETURN i; +END; +END SignedQuad; + +(******************************************************************************) + +PROCEDURE CloseFontFile; + +(* Close the currently open font file. *) + +BEGIN +status := SYS$DELTVA(ADR(vas),ADR(vas),0); +IF NOT ODD(status) THEN + (* DEBUG + WriteString('SYS$DELTVA failed in CloseFontFile! status='); + WriteCard(status); WriteLn; Halt(2); + GUBED *) +END; +status := SYS$DASSGN(channel); +IF NOT ODD(status) THEN + (* DEBUG + WriteString('SYS$DASSGN failed in CloseFontFile! status='); + WriteCard(status); WriteLn; Halt(2); + GUBED *) +END; +END CloseFontFile; + +(******************************************************************************) +(* Here are the routines for reading PXL files: *) +(******************************************************************************) + +PROCEDURE PXLFillPixelTable; + +(* Fill the pixeltable for currfont^ using the font directory info + in the currently open PXL file. +*) + +VAR i, b0, b1, b2, b3 : CARDINAL; (* 4 bytes in TFM width *) + +BEGIN +WITH currfont^ DO + IF psfont AND fontexists THEN + TFMFillPixelTable; (* use TFM file instead *) + RETURN; + END; + (* to find font directory we first move to last byte in PXL file *) + byteoffset := CARDINAL(ADDRESS(vas[1]) - ADDRESS(filestart)); + (* skip back over any 0 bytes *) + WHILE (byteoffset > 0) AND (CARDINAL(filestart^[byteoffset]) = 0) DO + DEC(byteoffset); + END; + (* move to byte at start of last non-zero word *) + WHILE byteoffset MOD 4 <> 0 DO + DEC(byteoffset); + END; + IF SignedQuad() <> 1001 THEN + WriteLn; + WriteString('Bad PXL file! id word <> 1001.'); + WriteLn; Halt(2); + END; + DEC(byteoffset,4); (* SignedQuad will have added 4 *) + DEC(byteoffset,516 * 4); (* starting byte of font directory *) + FOR i := 128 TO maxTeXchar DO + pixelptr^[i].mapadr := 0; (* PXL files only have 128 chars *) + pixelptr^[i].loaded := FALSE; + END; + FOR i := 0 TO 127 DO + WITH pixelptr^[i] DO + wd := GetTwoBytes(); + ht := GetTwoBytes(); + xo := SignedPair(); + yo := SignedPair(); + loaded := FALSE; (* bitmap not yet downloaded *) + mapadr := SignedQuad(); (* word offset in PXL file *) + IF (wd = 0) OR (ht = 0) THEN + mapadr := 0; (* in case PXL file is incorrect *) + END; + b0 := GetByte(); (* should be 0 or 255 *) + b1 := GetByte(); + b2 := GetByte(); + b3 := GetByte(); + dwidth := FixToDVI(b0,b1,b2,b3); + pwidth := PixelRound(dwidth); (* convert DVI units to pixels *) + END; + END; +END; +END PXLFillPixelTable; + +(******************************************************************************) + +PROCEDURE FixToDVI (b0, b1, b2, b3 : CARDINAL) : INTEGER; + +(* Convert the given fixword (made up of 4 bytes) into DVI units + using the method recommended in DVITYPE. +*) + +VAR alpha, beta, s : CARDINAL; temp : INTEGER; + +BEGIN +s := currfont^.scaledsize; (* so we don't change scaledsize! *) +alpha := 16 * s; +beta := 16; +WHILE s >= 40000000B DO (* 2^23sp = 128pt *) + s := s DIV 2; + beta := beta DIV 2; +END; +temp := (((((b3 * s) DIV 400B) + (b2 * s)) DIV 400B) + (b1 * s)) DIV beta; +IF b0 > 0 THEN + IF b0 = 255 THEN + RETURN temp - INTEGER(alpha); + ELSE + WriteLn; + WriteString('Bad fixword! 1st byte='); WriteCard(b0); + WriteLn; Halt(2); + END; +ELSE + RETURN temp; +END; +END FixToDVI; + +(******************************************************************************) + +PROCEDURE PXLLoadBitmap (fontptr : fontinfoptr; code : CARDINAL); + +(* Download bitmap using raster information starting at mapadr + in currently open PXL file. +*) + +VAR b, r, thisbyte, bytesperrow, usedperrow, charsperline : CARDINAL; + +BEGIN +WITH fontptr^.pixelptr^[code] DO +bytesperrow := ((wd + 31) DIV 32) * 4; (* words per row * 4 *) +usedperrow := (wd + 7) DIV 8; (* not all bytes might be needed *) +charsperline := 0; +PutString('[<'); +(* output (ht * usedperrow * 2) hex digits, starting at top row of bitmap *) +byteoffset := mapadr * 4; (* mapadr = word offset *) +b := 0; (* byte count for one row *) +r := 0; (* row count *) +LOOP + INC(charsperline,2); + IF charsperline >= 72 THEN + Put(CR); + charsperline := 0; + END; + thisbyte := GetByte(); (* and increment byteoffset *) + Put(hexdigs[ thisbyte DIV 16 ]); + Put(hexdigs[ thisbyte MOD 16 ]); + INC(b); + IF b = usedperrow THEN + INC(r); + IF r = CARDINAL(ht) THEN EXIT END; + INC(byteoffset,bytesperrow - b); (* move to start of next row *) + b := 0; (* reset byte count *) + END; +END; +Put('>'); Put(CR); +PutCard(usedperrow * 8); Put(' '); +PutInt(ht); Put(' '); +PutInt(xo); Put(' '); +PutInt(yo); Put(' '); (* offset of origin from top row *) +PutInt(pwidth); +PutString('] '); +PutCard(code); +PutString(' dc'); Put(CR); +END; (* WITH *) +END PXLLoadBitmap; + +(******************************************************************************) +(* Here are the routines for reading PK files: *) +(******************************************************************************) + +PROCEDURE PKFillPixelTable; + +(* Fill the pixeltable for currfont^ using the font directory info + in the currently open PK file. +*) + +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 : CARDINAL; (* 4 bytes in TFM width *) + +BEGIN +WITH currfont^ DO + IF psfont AND fontexists THEN + TFMFillPixelTable; (* use TFM file instead *) + RETURN; + END; + byteoffset := 0; (* move to first byte *) + IF GetByte() <> pkpre THEN + WriteLn; + WriteString('Bad pre command in '); + WriteString(fontspec); WriteLn; Halt(2); + END; + IF GetByte() <> pkid THEN + WriteLn; + WriteString('Bad id byte in '); + WriteString(fontspec); WriteLn; Halt(2); + END; + j := GetByte(); (* length of comment *) + INC(byteoffset,j + 16); (* skip rest of preamble *) + FOR i := 0 TO maxTeXchar DO + WITH pixelptr^[i] DO + mapadr := 0; (* all chars absent initially *) + loaded := FALSE; (* bitmap not yet downloaded *) + END; + END; + LOOP + flagpos := byteoffset; (* remember position of flagbyte *) + flagbyte := GetByte(); + IF flagbyte < 240 THEN (* read character definition *) + flagbyte := flagbyte MOD 8; (* value of bottom 3 bits *) + IF flagbyte < 4 THEN (* short char preamble *) + packetlen := flagbyte * 256 + GetByte(); + chcode := GetByte(); + endofpacket := packetlen + byteoffset; + WITH pixelptr^[chcode] DO + b1 := GetByte(); + b2 := GetByte(); + b3 := GetByte(); + dwidth := FixToDVI(0,b1,b2,b3); (* b0 = 0 *) + pwidth := GetByte(); + wd := GetByte(); + ht := GetByte(); + xo := SignedByte(); + yo := SignedByte(); + END; + ELSIF flagbyte < 7 THEN (* extended short char preamble *) + packetlen := (flagbyte - 4) * 65536 + GetTwoBytes(); + chcode := GetByte(); + endofpacket := packetlen + byteoffset; + WITH pixelptr^[chcode] DO + b1 := GetByte(); + b2 := GetByte(); + b3 := GetByte(); + dwidth := FixToDVI(0,b1,b2,b3); (* b0 = 0 *) + pwidth := GetTwoBytes(); + wd := GetTwoBytes(); + ht := GetTwoBytes(); + xo := SignedPair(); + yo := SignedPair(); + END; + ELSE (* long char preamble *) + packetlen := SignedQuad(); + chcode := SignedQuad(); + endofpacket := packetlen + byteoffset; + WITH pixelptr^[chcode] DO + b0 := GetByte(); + b1 := GetByte(); + b2 := GetByte(); + b3 := GetByte(); + dwidth := FixToDVI(b0,b1,b2,b3); + pwidth := SignedQuad() DIV 65536; (* dx in pixels *) + INC(byteoffset,4); (* skip dy *) + wd := SignedQuad(); + ht := SignedQuad(); + xo := SignedQuad(); + yo := SignedQuad(); + END; + END; + WITH pixelptr^[chcode] DO + IF (wd = 0) OR (ht = 0) THEN + mapadr := 0; (* no bitmap *) + ELSE + mapadr := flagpos; (* position of flagbyte *) + END; + END; + byteoffset := endofpacket; (* skip raster info *) + ELSE + CASE flagbyte OF + 240..243 : i := 0; + FOR j := 240 TO flagbyte DO i := 256 * i + GetByte() END; + INC(byteoffset,i); (* skip special parameter *) + | 244 : INC(byteoffset,4); (* skip numspecial parameter *) + | pknoop : (* do nothing *) + | pkpost : EXIT; (* no more character definitions *) + ELSE + WriteLn; + WriteString('Bad flag byte in '); + WriteString(fontspec); WriteLn; Halt(2); + END; + END; + END; (* LOOP; flagbyte = pkpost *) +END; +END PKFillPixelTable; + +(******************************************************************************) + +(* Routines to unpack raster info need some global variables: *) + +VAR + turnon : BOOLEAN; (* is current run black? *) + dynf, (* dynamic packing variable *) + repeatcount, (* how many times to repeat the next row *) + inputbyte, (* the current input byte *) + bitweight : CARDINAL; (* for getting bits or nybbles from inputbyte *) + +(******************************************************************************) + +PROCEDURE PKLoadBitmap (fontptr : fontinfoptr; code : CARDINAL); + +(* Download bitmap using information from character definition at mapadr + in currently open PK file. +*) + +VAR i, j, flagbyte, bitpos, bytesperrow, + rowsleft, hbit, count, rp, charsperline : CARDINAL; + byte : BITSET; + row : ARRAY [0..400] OF BYTE; (* SYSDEP: max glyph width = 3200 bits *) + +BEGIN +WITH fontptr^.pixelptr^[code] DO +bytesperrow := (wd + 7) DIV 8; (* bytes in one row *) +byteoffset := mapadr; (* mapadr = flagbyte offset in PK file *) +flagbyte := GetByte(); (* 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 *) + INC(byteoffset,10); +ELSIF flagbyte < 7 THEN (* skip extended short char preamble *) + INC(byteoffset,16); +ELSE (* skip long char preamble *) + INC(byteoffset,36); +END; +charsperline := 0; +PutString('[<'); (* start of hex string *) +bitweight := 0; (* to get 1st inputbyte *) +IF dynf = 14 THEN + (* raster info is a string of bits in the next (wd * ht + 7) DIV 8 bytes *) + FOR i := 1 TO CARDINAL(ht) DO + byte := {}; (* set all bits to 0 *) + bitpos := 7; (* leftmost bit *) + FOR j := 1 TO CARDINAL(wd) DO + IF bitweight = 0 THEN + (* next 2 lines equal inputbyte := GetByte(); *) + inputbyte := CARDINAL(filestart^[byteoffset]); + INC(byteoffset); + bitweight := 8; + END; + DEC(bitweight); (* 7..0 *) + IF bitweight IN BITSET(inputbyte) THEN + INCL(byte,bitpos); (* set bit *) + END; + IF bitpos > 0 THEN + DEC(bitpos); (* next bit *) + ELSE + INC(charsperline,2); + IF charsperline >= 72 THEN + Put(CR); + charsperline := 0; + END; + Put(hexdigs[ CARDINAL(byte) DIV 16 ]); (* high nybble *) + Put(hexdigs[ CARDINAL(byte) MOD 16 ]); (* low nybble *) + byte := {}; + bitpos := 7; + END; + END; + IF bitpos < 7 THEN + INC(charsperline,2); + IF charsperline >= 72 THEN + Put(CR); + charsperline := 0; + END; + Put(hexdigs[ CARDINAL(byte) DIV 16 ]); + Put(hexdigs[ CARDINAL(byte) MOD 16 ]); + END; + END; +ELSE + (* raster info is encoded as run and repeat counts *) + rowsleft := ht; + hbit := wd; + repeatcount := 0; + rp := 1; + bitpos := 8; + byte := {}; + WHILE rowsleft > 0 DO + count := PackedNum(); + WHILE count > 0 DO + IF (count < bitpos) AND (count < hbit) THEN + IF turnon THEN + byte := byte + gpower[bitpos] - gpower[bitpos - count]; + END; + DEC(hbit,count); + DEC(bitpos,count); + count := 0; + ELSIF (count >= hbit) AND (hbit <= bitpos) THEN + IF turnon THEN + byte := byte + gpower[bitpos] - gpower[bitpos - hbit]; + END; + row[rp] := BYTE(byte); + (* end of current row, so send it repeatcount+1 times *) + FOR i := 0 TO repeatcount DO + FOR j := 1 TO bytesperrow DO + INC(charsperline,2); + IF charsperline >= 72 THEN + Put(CR); + charsperline := 0; + END; + Put(hexdigs[ CARDINAL(row[j]) DIV 16 ]); + Put(hexdigs[ CARDINAL(row[j]) MOD 16 ]); + END; + END; + DEC(rowsleft,repeatcount + 1); + repeatcount := 0; + rp := 1; + byte := {}; + bitpos := 8; + DEC(count,hbit); + hbit := wd; + ELSE + IF turnon THEN byte := byte + gpower[bitpos] END; + row[rp] := BYTE(byte); + INC(rp); (* we assume rp never overflows! *) + byte := {}; + DEC(count,bitpos); + DEC(hbit,bitpos); + bitpos := 8; + END; + END; + turnon := NOT turnon; + END; +END; +Put('>'); Put(CR); +PutCard(bytesperrow * 8); Put(' '); +PutInt(ht); Put(' '); +PutInt(xo); Put(' '); +PutInt(yo); Put(' '); (* offset of origin from top row *) +PutInt(pwidth); +PutString('] '); +PutCard(code); +PutString(' dc'); Put(CR); +END; (* WITH *) +END PKLoadBitmap; + +(******************************************************************************) + +PROCEDURE PackedNum () : CARDINAL; + +(* 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 : CARDINAL; + +BEGIN +i := GetNyb(); +IF i = 0 THEN + REPEAT j := GetNyb(); INC(i) UNTIL j <> 0; + WHILE i > 0 DO j := j * 16 + GetNyb(); DEC(i) END; + RETURN j - 15 + (13 - dynf) * 16 + dynf; +ELSIF i <= dynf THEN + RETURN i; +ELSIF i < 14 THEN + RETURN (i - dynf - 1) * 16 + GetNyb() + dynf + 1; +ELSE + IF i = 14 THEN + repeatcount := PackedNum(); (* recursive *) + ELSE + repeatcount := 1; (* nybble = 15 *) + END; + RETURN PackedNum(); (* recursive *) +END; +END PackedNum; + +(******************************************************************************) + +PROCEDURE GetNyb () : CARDINAL; + +(* Return next nybble in PK file. *) + +BEGIN +IF bitweight = 0 THEN + (* next 2 lines equal inputbyte := GetByte(); *) + inputbyte := CARDINAL(filestart^[byteoffset]); + INC(byteoffset); + bitweight := 16; (* for next call of GetNyb *) + RETURN inputbyte DIV 16; (* high nybble *) +ELSE + bitweight := 0; (* for next call of GetNyb *) + RETURN inputbyte MOD 16; (* low nybble *) +END; +END GetNyb; + +(******************************************************************************) +(* Here are the declarations and routines for reading TFM files: *) +(******************************************************************************) + +VAR + lf, lh, bc, ec, nw, nh : INTEGER; + charinfo : ARRAY [0..255] OF + RECORD + wdindex, htindex, dpindex : INTEGER; + END; + charmetrics : ARRAY [0..255] OF + RECORD + (* 4 bytes making up fixword *) + width, height, depth : ARRAY [0..3] OF INTEGER; + END; + +(******************************************************************************) + +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 charinfo array *) +ReadTFMCharMetrics; (* fill charmetrics array *) +WITH currfont^ DO + FOR c := 0 TO bc - 1 DO + pixelptr^[c].mapadr := 0; (* chars < bc don't exist *) + END; + FOR c := ec + 1 TO 255 DO + pixelptr^[c].mapadr := 0; (* chars > ec don't exist *) + END; + FOR c := bc TO ec DO + WITH pixelptr^[c] DO + WITH charmetrics[c] DO + 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; + DEC(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 *) + END; + loaded := FALSE; (* no bitmap available *) + END; + END; + END; +END; +END TFMFillPixelTable; + +(******************************************************************************) + +PROCEDURE ReadTFMIntegers; + +(* Read the first 6 16-bit integers in the TFM file. See TFtoPL section 8. *) + +BEGIN +byteoffset := 0; (* start reading at 1st byte in TFM file *) +lf := GetTwoBytes(); +lh := GetTwoBytes(); +bc := GetTwoBytes(); +ec := GetTwoBytes(); +nw := GetTwoBytes(); +nh := GetTwoBytes(); +END ReadTFMIntegers; + +(******************************************************************************) + +PROCEDURE ReadTFMCharInfo; + +(* Read the charinfo array. See TFtoPL section 11. *) + +VAR c, i : INTEGER; + +BEGIN +byteoffset := 24 + (lh * 4); (* offset of charinfo array *) +FOR c := bc TO ec DO + WITH charinfo[c] DO + wdindex := GetByte() * 4; (* offset from start of width array *) + i := GetByte(); (* 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 *) + INC(byteoffset,2); (* skip itindex and remainder bytes *) + END; +END; +END ReadTFMCharInfo; + +(******************************************************************************) + +PROCEDURE ReadTFMCharMetrics; + +(* Read the charmetrics array using the indices in charinfo. *) + +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 charinfo[c] DO + WITH charmetrics[c] DO + byteoffset := wdbase + wdindex; + FOR b := 0 TO 3 DO width[b] := GetByte() END; + byteoffset := htbase + htindex; + FOR b := 0 TO 3 DO height[b] := GetByte() END; + byteoffset := dpbase + dpindex; + FOR b := 0 TO 3 DO depth[b] := GetByte() END; + END; + END; +END; +END ReadTFMCharMetrics; + +(******************************************************************************) + +BEGIN +END FontReader. diff --git a/dviware/psprint/vms/global.ps b/dviware/psprint/vms/global.ps new file mode 100644 index 0000000000..ed026888ee --- /dev/null +++ b/dviware/psprint/vms/global.ps @@ -0,0 +1,18 @@ +% When printing a DVI file, PSPRINT looks for a file called GLOBAL.PS +% in your current directory and appends it to the PostScript prologue. +% Copy this file to your current directory and uncomment the following +% example code to print "DRAFT" in the same location on every DVI page. + +% /@bop0 % redefine @bop0 (see TEX_PS:TEX.PS) +% { pop % throw away page number +% /mysave save def +% gsave +% initgraphics % use PostScript's default coordinates +% /Helvetica-Bold findfont +% 72 scalefont setfont +% 36 36 moveto +% 0.95 setgray +% (DRAFT) show +% grestore +% mysave restore +% } def diff --git a/dviware/psprint/vms/greybox.ps b/dviware/psprint/vms/greybox.ps new file mode 100644 index 0000000000..220564810a --- /dev/null +++ b/dviware/psprint/vms/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/vms/info.ps b/dviware/psprint/vms/info.ps new file mode 100644 index 0000000000..86b4b82b27 --- /dev/null +++ b/dviware/psprint/vms/info.ps @@ -0,0 +1,99 @@ +% Print page showing various status values. + +/oldusertime usertime def + +initgraphics +72 0 translate % move origin to the right +/vpos 720 def % initial vertical pos +0 vpos moveto % start near top left corner + +/str 12 string def + +/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 + 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 str cvs show newline + (DISK STATUS = ) show str cvs show + ( ) show str cvs show newline + (USER DISK % = ) show str cvs show newline +} if + +(PRODUCT = ) show show newline +(REVISION = ) show str cvs show newline +(VERSION = ) show version show newline + +version cvr 25.0 gt % PS version >= 25.0 ? +{ + newline + currentpacking % bool + (CURRENT PACKING = ) show + str cvs show newline + + newline + currentcacheparams % mark lower upper + (CURRENT CACHE PARAMS) show newline + counttomark + { str cvs show newline } + repeat + pop % remove mark +} if + +newline +(DEFAULTMATRIX = ) show +matrix defaultmatrix % [ ? ? ? ? ? ? ] +dup 0 get str cvs show ( ) show +dup 1 get str cvs show ( ) show +dup 2 get str cvs show ( ) show +dup 3 get str cvs show ( ) show +dup 4 get str cvs show ( ) show +dup 5 get str cvs show ( ) show +newline +pop + +newline +currentscreen pop % freq angle proc +(CURRENT ANGLE = ) show str cvs show newline +(CURRENT FREQUENCY = ) show str cvs show newline + +newline +(CACHE STATUS) show newline +cachestatus % bsize bmax msize mmax csize cmax blimit +(blimit = ) show str cvs show newline +(cmax = ) show str cvs show newline +(csize = ) show str cvs show newline +(mmax = ) show str cvs show newline +(msize = ) show str cvs show newline +(bmax = ) show str cvs show newline +(bsize = ) show str cvs show newline + +newline +(VM STATUS) show newline +vmstatus % savelevel vmused vmmax +(vm max = ) show str cvs show newline +(vm used = ) show str cvs show newline +(save level = ) show str cvs show newline + +newline +(JOB TIME (secs) = ) show +usertime oldusertime sub 1000 div str cvs show newline + +showpage diff --git a/dviware/psprint/vms/install.com b/dviware/psprint/vms/install.com new file mode 100644 index 0000000000..fcac389a4d --- /dev/null +++ b/dviware/psprint/vms/install.com @@ -0,0 +1,37 @@ +$! READ THE PSPRINT USER AND SYSTEM GUIDES FIRST. +$! Before running this command file you may want to make some changes. +$! See the "CHANGE" comments below. +$! Some of the steps may need to be copied to SYS$MANAGER:SYSTARTUP.COM, +$! depending on how you want to set up the PSPRINT and PSDVI commands. +$ +$! Terminal characteristics for serial line to LaserWriter/Linotronic: +$ +$ set proc/priv=log_io +$ set terminal/permanent/fulldup/speed=9600 - + /nohang/notype_ahead/nobroad/nomodem/noecho/pasthru/noform/nowrap - + TXD6: ! CHANGE device!? +$ +$! Define the postscript form for LaserWriter/Linotronic: +$ +$ define/form postscript 30 - ! CHANGE number!? (must be unique) + /description="Default for PostScript device" - + /notruncate/nowrap ! prevents spurious newline characters +$ +$! Initialize the print queue for LaserWriter/Linotronic: +$ +$ init/queue/form=postscript/default=(nofeed,form=postscript) - + /prot=(s:wred,g:rw,w:rw)/on=TXD6: QNAME ! CHANGE device and queue!? +$ +$! Make sure you turn on the LaserWriter/Linotronic BEFORE starting the queue, +$! otherwise pending jobs will just disappear. +$ +$! Define TEX_PS and set up the PSPRINT & PSDVI commands: +$ +$ def/sys tex_ps TEX_DISK:[TEX.PS] ! CHANGE directory!? +$ set command /tables=sys$library:dcltables /output=sys$library:dcltables - + TEX_PS:PSPRINT.CLD, TEX_PS:PSDVI.CLD ! CHANGE qualifier defaults!? +$ set proc/priv=cmkrnl +$ run sys$system:install +sys$library:dcltables/replace +/exit +$ exit diff --git a/dviware/psprint/vms/laserprep65.ps b/dviware/psprint/vms/laserprep65.ps new file mode 100644 index 0000000000..53a4584d7f --- /dev/null +++ b/dviware/psprint/vms/laserprep65.ps @@ -0,0 +1,450 @@ +% When printing a document on a PostScript printer, most Macintosh applications +% will dump their PostScript code into a file called PostScript0 if you press +% Command-F immediately after selecting OK in the Print dialogue box. +% The PostScript code relies on definitions stored in a Mac system file called +% Laser Prep. A modified version of Laser Prep (like the one you're reading) +% must be included with PSPRINT's /PREP qualifier if you want to send +% Command-F files via DVI \special commands. +% +% Since Apple keep changing Laser Prep, you might need to create your own +% modified version some day. Here's how: +% 1. Use a Mac application (such as MacWrite) to create a very small document. +% 2. Print it, but immediately after selecting OK hold down Command-K. +% Instead of printing the document, you should get a file called PostScript0 +% which contains Laser Prep prefixed to the Command-F code. +% 3. Open the file with a text editor and remove the Command-F code by finding +% the first occurrence of %%EOF and deleting everything below it. +% 4. Duplicate the changes I've made to this file (search for %AKT). +% 5. It's probably a good idea to rename PostScript0 to LaserPrepxx.ps where +% xx is the version number appearing in comments at the top of the file. +% 6. Type "PSPRINT /PREP=LaserPrepxx.ps ..." with your fingers crossed. + +%%Title: "Laser Prep -- The Apple PostScript Dictionary (md)" +%%Creator: Apple Software Engineering +%%CreationDate: Thursday, March 19, 1987 +%{appledict version #65 +% CopyRight Apple Computer, Inc. 1984,1985,1986,1987 All Rights Reserved. +%%EndComments +%%BeginProcSet: "(AppleDict md)" 65 0 +systemdict/currentpacking known{currentpacking true setpacking}if +/LW{save statusdict/product get(LaserWriter)anchorsearch +exch pop{length 0 eq{1}{2}ifelse}{0}ifelse exch restore}bind def +/LW+{LW 2 eq}bind def +/ok{systemdict/statusdict known dup{LW 0 gt and}if}bind def + +%AKT ok{statusdict begin 9 sccinteractive 3 ne exch 0 ne or{9 0 3 setsccinteractive}if end}if + +/md 250 dict def md begin +/av 65 def +/T true def/F false def/mtx matrix def/s75 75 string def/s8 8 string def/s1 ( ) def/pxs 1 def/pys 1 def +1 0 mtx defaultmatrix dtransform exch atan/pa exch def/nlw .24 def/ppr [-32 -29.52 762 582.48] def +/pgs 1 def/por true def/xb 500 array def/so true def/fillflag false def/pnm 1 def/fmv true def +/sfl false def/ma 0 def/invertflag false def/xflip false def/yflip false def/noflips true def/scaleby96 false def/fNote true def/fBitStretch true def +/fg (Rvd\001\001\000\000\177) def +/bdf{bind def}bind def +/xdf{exch def}bdf +/xl{neg exch neg translate}bdf +/fp{pnsh 0 ne pnsv 0 ne and}bdf +/nop{}bdf/lnop[/nop load]cvx bdf +/vrb[ +{fp{gsave 1 setlinewidth pnsh pnsv scale stroke grestore}if newpath}bind +/eofill load +dup +/newpath load +2 index +dup +{clip newpath}bind +{}bind +dup +2 copy +]def +currentscreen/spf xdf/rot xdf/freq xdf +/doop{vrb exch get exec}bdf +/psu{/fNote xdf/fBitStretch xdf/scaleby96 xdf/yflip xdf/xflip xdf/invertflag xdf xflip yflip or{/noflips false def}if +/pgs xdf 2 index .72 mul exch div/pys xdf div .72 mul/pxs xdf ppr astore pop/por xdf sn and/so xdf}bdf +/txpose{fNote{smalls}{bigs}ifelse pgs get exec pxs pys scale ppr aload pop por{noflips{pop exch neg exch translate pop 1 -1 scale}if +xflip yflip and{pop exch neg exch translate 180 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg translate}if +xflip yflip not and{pop exch neg exch translate pop 180 rotate ppr 3 get ppr 1 get neg sub neg 0 translate}if yflip xflip not and{ppr 1 get neg ppr 0 get neg translate}if} +{noflips{translate pop pop 270 rotate 1 -1 scale}if xflip yflip and{translate pop pop 90 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg translate}if +xflip yflip not and{translate pop pop 90 rotate ppr 3 get ppr 1 get neg sub neg 0 translate}if yflip xflip not and{translate pop pop 270 rotate ppr 2 get ppr 0 get neg sub neg 0 exch translate}if}ifelse +statusdict begin waittimeout 300 lt{/waittimeout 300 def}if end scaleby96{ppr aload pop 4 -1 roll add 2 div 3 1 roll add 2 div 2 copy translate .96 dup scale neg exch neg exch translate}if}bdf +/fr{3 index 3 index xl ppr aload pop 3 -1 roll 2 mul add 3 1 roll exch 2 mul add +6 2 roll 3 -1 roll sub 3 1 roll exch sub 3 1 roll exch 3 -1 roll div 3 1 roll div exch scale} bdf +/lws{show}bdf +/tv{show pop pop}bdf +/obl{{0.212557 mul}{pop 0}ifelse}bdf +/sfd{ps fg 5 -1 roll get mul 100 div 0 ps 5 -1 roll obl ps neg 0 0 6a astore makefont setfont}bdf +/fnt{findfont sfd}bdf +/bt{sa 3 1 roll 3 index and put}bdf +/sa(\000\000\000\000\000\000\000\000\000\000)def +/fs{0 1 bt 1 2 bt 2 4 bt 3 8 bt 4 16 bt 5 32 bt 6 64 bt 7 128 bt sa exch 8 exch put}bdf +/mx1 matrix def +/mx2 matrix def +/mx3 matrix def +/bu{currentpoint currentgray currentlinewidth currentlinecap currentlinejoin currentdash exch aload length +fg 5 sfl{1}{0}ifelse put pnsv pnsh +2t aload pop 3a aload pop mx2 aload pop mx1 aload pop mtx currentmatrix aload pop +mx3 aload pop ps pm restore/ps xdf mx3 astore pop}bdf +/bn{/pm save def mx3 setmatrix newpath 0 0 moveto ct dup 39 get 0 exch getinterval cvx exec +mtx astore setmatrix mx1 astore pop mx2 astore pop 3a astore pop +2t astore pop/pnsh xdf/pnsv xdf gw +/sfl fg 5 get 0 ne def array astore exch setdash setlinejoin setlinecap +setlinewidth setgray moveto}bdf +/fc{save vmstatus exch sub 50000 lt +{(%%[|0|]%%)=print flush}if pop restore}bdf +/tc{32768 div add 3 1 roll 32768 div add 2t astore pop}bdf +/3a [0 0 0] def +/2t 2 array def +/tp{3a astore pop}bdf +/tt{mx2 currentmatrix pop currentpoint 2 copy 2t aload pop qa 2 copy translate 3a aload pop exch dup 0 eq +{pop}{1 eq{-1 1}{1 -1}ifelse scale}ifelse rotate pop neg exch neg exch translate moveto}bdf +/te{mx2 setmatrix}bdf +/th{3 -1 roll div 3 1 roll exch div 2 copy mx1 scale pop scale/sfl true def}bdf +/tu{1 1 mx1 itransform scale/sfl false def}bdf +/ts{1 1 mx1 transform scale/sfl true def}bdf +/fz{/ps xdf}bdf +/dv{dup 0 ne{div}{pop}ifelse}bdf +/pop4{pop pop pop pop}bdf +/it{sfl{mx1 itransform}if}bdf +/gm{exch it moveto}bdf/rm{it rmoveto}bdf +/lm{currentpoint sfl{mx1 transform}if exch pop sub 0 exch it rmoveto}bdf +/fm{statusdict/manualfeed known}bdf +/se{statusdict exch/manualfeed exch put}bdf +/mf +{dup /ma exch def % Copy argument to /ma. + 0 gt % Eat argument and push boolean (arg > 0). + {fm se + /t1 5 st % Define value t1 + ok ma 1 gt and + {/t2 0 st % Define value t2. + /t3 0 st % Define value t3. + statusdict /manualfeedtimeout 3600 put % Set timeout value. + } if + } if +} bdf +/jn {/statusdict where exch pop{statusdict exch /jobname exch put}if} bdf +/pen{pnm mul/pnsh xdf pnm mul/pnsv xdf pnsh setlinewidth}bdf +/min{2 copy gt{exch}if pop}bdf +/max{2 copy lt{exch}if pop}bdf +/dh{fg 6 1 put array astore exch pop exch pop exch setdash}bdf +/ih[currentdash]def +/rh{fg 6 0 put ih aload pop setdash}bdf +/dl{gsave nlw pys div setlinewidth 0 setgray}bdf +/dlin{exch currentpoint currentlinewidth 2 div dup +translate newpath moveto lineto currentpoint stroke grestore moveto}bdf +/lin{fg 6 get 0 ne{exch lineto currentpoint 0 doop moveto} +{exch currentpoint/pnlv xdf/pnlh xdf gsave newpath/@1 xdf/@2 xdf fp{pnlh @2 lt{pnlv @1 ge +{pnlh pnlv moveto @2 @1 lineto pnsh 0 rlineto +0 pnsv rlineto pnlh pnsh add pnlv pnsv add lineto pnsh neg 0 rlineto} +{pnlh pnlv moveto pnsh 0 rlineto @2 pnsh add @1 lineto 0 pnsv rlineto +pnsh neg 0 rlineto pnlh pnlv pnsv add lineto}ifelse}{pnlv @1 gt +{@2 @1 moveto pnsh 0 rlineto pnlh pnsh add pnlv lineto 0 pnsv rlineto +pnsh neg 0 rlineto @2 @1 pnsv add lineto}{pnlh pnlv moveto pnsh 0 rlineto +0 pnsv rlineto @2 pnsh add @1 pnsv add lineto pnsh neg 0 rlineto +0 pnsv neg rlineto}ifelse}ifelse +closepath fill}if @2 @1 grestore moveto}ifelse}bdf +/gw{/pnm fg 3 get fg 4 get div def}bdf +/lw{fg exch 4 exch put fg exch 3 exch put gw pnsv pnsh pen}bdf +/barc{/@1 xdf/@2 xdf/@3 xdf/@4 xdf/@5 xdf +/@6 xdf/@7 xdf/@8 xdf gsave +@5 @7 add 2 div @6 @8 add 2 div translate newpath 0 0 moveto +@5 @7 sub @6 @8 sub mtx currentmatrix pop scale @1{newpath}if +0 0 0.5 @4 @3 arc @4 @3 sub abs 360 ge{closepath}if +mtx setmatrix @2 doop grestore}bdf +/ar{dup 0 eq barc}bdf +/ov{0 exch 360 exch true barc}bdf +/rc{/@t xdf currentpoint 6 2 roll newpath 4 copy 4 2 roll exch moveto +6 -1 roll lineto lineto lineto closepath @t doop moveto}bdf +/mup{dup pnsh 2 div le exch pnsv 2 div le or}bdf +/rr{/@1 xdf 2. div/@2 xdf 2. div/@3 xdf +/@4 xdf/@5 xdf/@6 xdf/@7 xdf +@7 @5 eq @6 @4 eq @2 mup or or{@7 @6 @5 @4 @1 rc} +{@4 @6 sub 2. div dup @2 lt{/@2 xdf}{pop}ifelse +@5 @7 sub 2. div dup @2 lt{/@2 xdf}{pop}ifelse +@1 0 eq{/@2 @2 pnsh 2 div 2 copy gt{sub def}{0 pop4}ifelse}if +currentpoint newpath +@4 @6 add 2. div @7 moveto +@4 @7 @4 @5 @2 arcto pop4 +@4 @5 @6 @5 @2 arcto pop4 +@6 @5 @6 @7 @2 arcto pop4 +@6 @7 @4 @7 @2 arcto pop4 +closepath @1 doop moveto}ifelse}bdf +/pr{gsave newpath/pl{exch moveto/pl{exch lineto}def}def}bdf +/pl{exch lineto}bdf +/ep{dup 0 eq{{moveto}{exch lin}{}{(%%[|1|]%%)= flush}pathforall +pop grestore}{doop grestore}ifelse currentpoint newpath moveto}bdf +/gr{64. div setgray}bdf +/pat{s8 copy pop 9.375 pa por not{90 add}if{1 add 4 mul cvi s8 exch get exch 1 add 4 mul cvi 7 sub bitshift 1 and}setscreen gr}bdf +/sg{freq rot/spf load setscreen gr}bdf +/dc{transform round .5 sub exch round .5 sub exch itransform}bdf +/sn{userdict/smooth4 known}bdf +/x8{3 bitshift}bdf +/x4{2 bitshift}bdf +/d4{-2 bitshift}bdf +/d8{-3 bitshift}bdf +/rb{15 add -4 bitshift 1 bitshift}bdf +/db{/@7 save def/@1 xdf/@2 xdf/@3 xdf/@4 xdf/@5 xdf/@6 @5 @3 4 add mul def +dc translate scale/xdbit 1 1 idtransform abs/ydbit exch def abs def{0 0 1 ydbit add 1 10 rc clip}if +@1 0 eq @1 4 eq or{1 setgray ydbit 0 1 ydbit add 1 2 rc}if +@1 3 eq @1 7 eq or{1}{0}ifelse setgray/@9 @1 0 eq @1 1 eq @1 3 eq or or invertflag xor def/@13 @6 def +@2 fBitStretch or{/@10 @4 x4 def/@11 @3 x4 def/@12 @10 rb def/@13 @12 @11 mul def/@15 1 1 dtransform abs/calcY 1 index def round cvi/@14 exch def +abs/calcX 1 index def round cvi scaleby96 not{1 add}if def/@16 @15 rb def/@17 @16 @14 mul def}if +sn @13 60000 lt and @2 fBitStretch or and{mtx currentmatrix dup 1 get exch 2 get 0. eq exch 0. eq and @17 60000 lt and fBitStretch and{@16 3 bitshift @14 @9 [calcX 0 0 calcY 0 0]{@17 string @13 string +currentfile @6 string readhexstring pop 1 index @4 @3 @5 @12 @2 smooth4 +@10 @11 @12 dup string 5 index @15 @14 @16 dup string stretch}imagemask}{@12 x8 @11 @9 [@10 0 0 @11 0 0]{@13 string +currentfile @6 string readhexstring pop 1 index @4 @3 @5 @12 @2 smooth4}imagemask}ifelse}{@5 3 bitshift @3 4 add @9 [@4 0 0 @3 0 2]{currentfile @6 string readhexstring pop}imagemask}ifelse +@7 restore}bdf +/wd 16 dict def +/mfont 14 dict def +/mdf{mfont wcheck not{/mfont 14 dict def}if mfont begin xdf end}bdf +/cf{{1 index/FID ne{def}{pop pop}ifelse}forall}bdf +/rf{/@1 exch def/@2 exch def +FontDirectory @2 known{cleartomark pop}{findfont dup begin dup length @1 add dict begin +cf {/Encoding macvec def}{Encoding dup length array copy/Encoding exch def +counttomark 2 idiv{Encoding 3 1 roll put}repeat}ifelse +pop +exec currentdict end end @2 exch definefont pop}ifelse}bdf +/bmbc{exch begin wd begin +/cr xdf +save +CharTable cr 6 mul 6 getinterval{}forall +/bitheight xdf/bitwidth xdf +.96 div/width xdf +Gkernmax add/XOffset xdf Gdescent add/YOffset xdf/rowbytes xdf +rowbytes 255 eq{0 0 0 0 0 0 setcachedevice} +{Gnormsize dup scale +width 0 XOffset YOffset bitwidth XOffset add bitheight YOffset add +setcachedevice +rowbytes 0 ne{ +XOffset YOffset translate newpath 0 0 moveto +bitwidth bitheight scale +sn{ +/xSmt bitwidth x4 def +/ySmt bitheight x4 def +/rSmt xSmt rb def +rSmt x8 ySmt true +[xSmt 0 0 ySmt neg 0 ySmt] +{rSmt ySmt mul string CharData cr get +1 index bitwidth bitheight rowbytes rSmt so smooth4} +}{rowbytes 3 bitshift bitheight 4 add true +[bitwidth 0 0 bitheight neg 0 bitheight 2 add] +{CharData cr get} +}ifelse +imagemask +}if +}ifelse +restore +end end +}bdf +/bb{.96 exch div/Gnormsize mdf 2 index +/Gkernmax mdf 1 index/Gdescent mdf +3 index div 4 1 roll +2 index div 1. 5 2 roll +exch div 4 1 roll +4 array astore/FontBBox mdf +}bdf +/cdf{mfont/CharData get 3 1 roll put}bdf +/bf{ +mfont begin +/FontType 3 def +/FontMatrix [1 0 0 1 0 0] def +/Encoding macvec def +/BuildChar/bmbc load def +end +mfont definefont pop +}bdf +/wi LW 1 eq{{gsave 0 0 0 0 0 0 0 0 moveto lineto lineto lineto closepath clip stringwidth grestore}bind}{/stringwidth load}ifelse def +/aps{0 get 124 eq}bdf +/xc{s75 cvs dup}bdf +/xp{put cvn}bdf +/scs{xc 3 67 put dup 0 95 xp}bdf +/sos{xc 3 79 xp}bdf +/sbs{xc 1 66 xp}bdf +/sis{xc 2 73 xp}bdf +/sob{xc 2 79 xp}bdf +/sss{xc 4 83 xp}bdf +/dd{exch 1 index add 3 1 roll add exch}bdf +/smc{moveto dup lws}bdf +/kwn{FontDirectory 1 index known{findfont exch pop}}bdf +/gl{1 currentgray sub setgray}bdf +/mm{/mfont 10 dict def mfont begin +/FontMatrix [1 0 0 1 0 0] def +/FontType 3 def +/Encoding macvec def +/df 4 index findfont def +/FontBBox [0 0 1 1] def +/xda xdf/mbc xdf +/BuildChar{wd begin/cr xdf/fd xdf/cs s1 dup 0 cr put def fd/mbc get exec end}def +exec end mfont definefont}bdf +/ac{dup scs kwn{exch findfont dup length 1 add dict begin +cf fmv{/Encoding macvec def}if/StrokeWidth nlw 1000 mul pys div ps div dup 12 lt{pop 12}if def +/PaintType 2 def currentdict /UniqueID known{/UniqueID UniqueID 16#A80000 xor def}if currentdict end definefont}ifelse}bdf +/mb{dup sbs kwn{exch{pop}{bbc}{}mm}ifelse sfd}bdf +/mo{dup sos kwn{exch{pop}{boc}{}mm}ifelse sfd}bdf +/ms{dup sss kwn{exch{pop}{bsc}{}mm}ifelse sfd}bdf +/ou{dup sos kwn{exch dup ac pop{scs findfont /df2 xdf}{aoc}{}mm}ifelse sfd}bdf +/su{dup sss kwn{exch dup ac pop{scs findfont /df2 xdf}{asc}{}mm}ifelse sfd}bdf +/ao{/fmv true def ou}bdf/as{/fmv true def su}bdf +/vo{/fmv false def ou}bdf/vs{/fmv false def su}bdf +/bbc{/da .03 def fd/df get setfont +gsave cs wi 1 index 0 ne{exch da add exch}if grestore setcharwidth +cs 0 0 smc da 0 smc da da smc 0 da moveto lws}bdf +/boc{/da 1 ps div def fd/df get setfont +gsave cs wi 1 index 0 ne{exch da add exch}if grestore setcharwidth +cs 0 0 smc da 0 smc da da smc 0 da smc gl da 2. div dup moveto lws}bdf +/bsc{/da 1 ps div def +/ds .05 def/da2 da 2. div def fd/df get setfont +gsave cs wi 1 index 0 ne{exch ds add da2 add exch}if grestore setcharwidth +cs ds da2 add .01 add 0 smc 0 ds da2 sub translate 0 0 smc +da 0 smc da da smc 0 da smc gl da 2. div dup moveto lws}bdf +/aoc{fd/df get setfont +gsave cs wi grestore setcharwidth +gl cs 0 0 smc fd/df2 get setfont gl 0 0 moveto lws}bdf +/asc{/da .05 def fd/df get setfont +gsave cs wi 1 index 0 ne{exch da add exch}if grestore setcharwidth +cs da .01 add 0 smc 0 da translate gl 0 0 smc gl fd/df2 get setfont 0 0 moveto lws}bdf +/st +{1000 mul usertime add % arg=1000*arg+usertime + dup 2147483647 gt {2147483647 sub} if % arg=arg mod (2^31) + def % Define +} bdf +/the{usertime sub dup 0 lt exch -2147483648 gt and}bdf +/6a 6 array def +/2a 2 array def +/3q 3 array def +/qs{3 -1 roll sub exch 3 -1 roll sub exch}bdf +/qa{3 -1 roll add exch 3 -1 roll add exch}bdf +/qm{3 -1 roll 1 index mul 3 1 roll mul}bdf +/qn{6a exch get mul}bdf +/qA .166667 def/qB .833333 def/qC .5 def +/qx{6a astore pop +qA 0 qn qB 2 qn add qA 1 qn qB 3 qn add +qB 2 qn qA 4 qn add qB 3 qn qA 5 qn add +qC 2 qn qC 4 qn add qC 3 qn qC 5 qn add}bdf +/qp{6 copy 12 -2 roll pop pop}bdf +/qc{exch qp qx curveto}bdf +/qi{{exch 4 copy 2a astore aload pop qa .5 qm newpath moveto}{exch 2 copy 6 -2 roll 2 qm qs 4 2 roll}ifelse}bdf +/qq{{qc 2a aload pop qx curveto}{exch 4 copy qs qa qx curveto}ifelse}bdf +/pt{currentpoint newpath moveto}bdf +/qf{/fillflag true def}bdf +/ec{1 and 0 ne{0 doop}if grestore currentpoint newpath moveto/fillflag false def}bdf +/eu{currentpoint fp{0 ep}{grestore newpath}ifelse moveto/fillflag false def}bdf +/bp{currentpoint newpath 2 copy moveto}bdf +/ef{gsave fillflag{gsave eofill grestore}if}bdf +/sm{0 exch{@1 eq{1 add}if}forall}bdf +/lshow{4 1 roll exch/@1 exch def{1 index wi pop sub 1 index sm dv 0 @1 4 -1 roll widthshow}{1 index wi pop sub +1 index dup sm 10 mul exch length 1 sub add dv dup 10. mul 0 @1 4 -1 roll 0 6 -1 roll awidthshow}ifelse}bdf +/setTxMode{sa 9 2 index put 3 eq{1}{0}ifelse setgray}bdf +/SwToSym{{}mark false/Symbol/|______Symbol 0 rf 0 sa 6 get 0 ne{pop 1}{sa 7 get 0 eq{pop 2}if}ifelse +sa 1 get 0 ne/|______Symbol +sa 4 get 0 ne{vs}{sa 3 get 0 ne{vo}{fnt}ifelse}ifelse}bdf +/mc{0 3 1 roll transform neg exch pop}bdf +/ul{dup 0 ne sa 2 get 0 ne and{gsave 0 0 +/UnderlinePosition kif{mc}{ps -10 div}ifelse/UnderlineThickness kif{mc}{ps 15 div}ifelse +abs setlinewidth neg rmoveto +sa 4 get 0 ne{gsave currentlinewidth 2. div dup rmoveto currentpoint newpath moveto +2 copy rlineto stroke grestore}if +sa 3 get sa 4 get or 0 ne{gsave gl 2 copy rlineto stroke grestore rlineto strokepath nlw pys div setlinewidth}{rlineto}ifelse +stroke grestore}{pop}ifelse}bdf +/sgt{2 copy known{get true}{pop pop false}ifelse}bdf +/kif{currentfont dup/FontMatrix get exch/FontInfo sgt{true}{currentfont/df sgt +{dup/FontInfo sgt{3 1 roll/FontMatrix get mtx concatmatrix exch true}{pop pop pop false} +ifelse}{pop pop false}ifelse}ifelse{3 -1 roll sgt{exch true}{pop false}ifelse}{false}ifelse}bdf +/blank/Times-Roman findfont/CharStrings get/space get def +/macvec 256 array def +/NUL/SOH/STX/ETX/EOT/ENQ/ACK/BEL/BS/HT/LF/VT/FF/CR/SO/SI +/DLE/DC1/DC2/DC3/DC4/NAK/SYN/ETB/CAN/EM/SUB/ESC/FS/GS/RS/US +macvec 0 32 getinterval astore pop +macvec 32/Times-Roman findfont/Encoding get +32 96 getinterval putinterval macvec dup 39/quotesingle put 96/grave put +/Adieresis/Aring/Ccedilla/Eacute/Ntilde/Odieresis/Udieresis/aacute +/agrave/acircumflex/adieresis/atilde/aring/ccedilla/eacute/egrave +/ecircumflex/edieresis/iacute/igrave/icircumflex/idieresis/ntilde/oacute +/ograve/ocircumflex/odieresis/otilde/uacute/ugrave/ucircumflex/udieresis +/dagger/degree/cent/sterling/section/bullet/paragraph/germandbls +/registered/copyright/trademark/acute/dieresis/notequal/AE/Oslash +/infinity/plusminus/lessequal/greaterequal/yen/mu/partialdiff/summation +/product/pi/integral/ordfeminine/ordmasculine/Omega/ae/oslash +/questiondown/exclamdown/logicalnot/radical/florin/approxequal/Delta/guillemotleft +/guillemotright/ellipsis/blank/Agrave/Atilde/Otilde/OE/oe +/endash/emdash/quotedblleft/quotedblright/quoteleft/quoteright/divide/lozenge +/ydieresis/Ydieresis/fraction/currency/guilsinglleft/guilsinglright/fi/fl +/daggerdbl/periodcentered/quotesinglbase/quotedblbase/perthousand/Acircumflex/Ecircumflex/Aacute +/Edieresis/Egrave/Iacute/Icircumflex/Idieresis/Igrave/Oacute/Ocircumflex +/apple/Ograve/Uacute/Ucircumflex/Ugrave/dotlessi/circumflex/tilde +/macron/breve/dotaccent/ring/cedilla/hungarumlaut/ogonek/caron +macvec 128 128 getinterval astore pop +{}mark true/Courier/|______Courier 0 rf +{/Metrics 21 dict begin/zero 600 def/one 600 def/two 600 def/three 600 def/four 600 def/five 600 def/six 600 def/seven 600 def/eight 600 def +/nine 600 def/comma 600 def/period 600 def/dollar 600 def/numbersign 600 def/percent 600 def/plus 600 def/hyphen 600 def/E 600 def/parenleft 600 def/parenright 600 def/space 600 def +currentdict end def currentdict/UniqueID known{/UniqueID 16#800000 def}if/FontBBox FontBBox 4 array astore def}mark true/Helvetica/|______Seattle 1 rf +/oldsettransfer/settransfer load def +/concatprocs{/proc2 exch cvlit def/proc1 exch cvlit def/newproc proc1 length proc2 length add array def +newproc 0 proc1 putinterval newproc proc1 length proc2 putinterval newproc cvx}def +/settransfer{currenttransfer concatprocs oldsettransfer}def +/PaintBlack{{1 exch sub}settransfer gsave newpath clippath 1 setgray fill grestore}def +/od +{ + %AKT (Rvd\001\001\000\000\177) fg copy pop txpose + 1 -1 scale %AKT + 1 0 mtx defaultmatrix dtransform exch atan /pa exch def + newpath + clippath + mark + {transform {itransform moveto}} + {transform {itransform lineto}} + {6 -2 roll transform + 6 -2 roll transform + 6 -2 roll transform + {itransform + 6 2 roll itransform + 6 2 roll itransform + 6 2 roll curveto + } + } + {{closepath}} + pathforall + newpath + counttomark array astore /gc xdf pop ct 39 0 put + 10 fz 0 fs 2 F/|______Courier fnt invertflag {PaintBlack} if +} bdf +/cd {} bdf +/op +{/sfl false def + /pm save def +} bdf +/cp +{ + pop pop %AKT ignore arguments to cp + pm restore +} bdf +/px{0 3 1 roll tp tt}bdf +/psb{/us save def}bdf +/pse{us restore}bdf +/ct 40 string def +/nc{currentpoint initclip newpath gc{dup type dup/arraytype eq exch/packedarraytype eq or{exec}if} +forall clip newpath moveto}bdf +/kp{ct 0 2 index length 2 index 39 2 index put getinterval copy cvx exec mx3 currentmatrix pop}bdf +end +LW 1 eq userdict/a4small known not and{/a4small +[[300 72 div 0 0 -300 72 div -120 3381] +280 3255 +{statusdict/jobstate (printing) put 0 setblink +margins +exch 196 add exch 304 add 8 div round cvi frametoroket +statusdict/jobstate (busy) put +1 setblink} +/framedevice load +60 45{dup mul exch dup mul add 1.0 exch sub}/setscreen load +{}/settransfer load/initgraphics load/erasepage load]cvx +statusdict begin bind end readonly def}if +md begin/bigs[lnop lnop/legal load userdict/a4 known{/a4 load}{lnop}ifelse lnop lnop lnop lnop lnop]def +/smalls[lnop userdict/note known{/note load}{dup}ifelse lnop userdict/a4small known{/a4small load}{lnop}ifelse 2 index lnop lnop lnop lnop ]def end +systemdict/currentpacking known{setpacking}if + +%AKT Removed /stretch and /smooth4 eexec patches to avoid flushfile problem +%AKT if md previously downloaded. + +%%EndProcSet + +%%EOF diff --git a/dviware/psprint/vms/laserprep68.ps b/dviware/psprint/vms/laserprep68.ps new file mode 100644 index 0000000000..d41199cb57 --- /dev/null +++ b/dviware/psprint/vms/laserprep68.ps @@ -0,0 +1,405 @@ +% This modified LaserPrep came from Henning Schulzrinne (HGSCHULZ@edu.umass.cs). + +%%Title: "Laser Prep -- The Apple PostScript Dictionary (md)" +%%Creator: Apple Software Engineering +%%CreationDate: Thursday, March 19, 1987 +%{appledict version #68 0 +% ) CopyRight Apple Computer, Inc. 1984,1985,1986,1987,1988 All Rights Reserved. +%%EndComments +%%BeginProcSet: "(AppleDict md)" 68 0 +currentfile statusdict begin +/sc {60 45 {abs exch abs 2 copy add 1 gt{1.0 sub dup mul exch 1.0 sub dup mul add 1.0 sub}{dup mul exch dup mul add 1.0 exch sub} +ifelse}setscreen} bind def statusdict begin product(LaserWriter II)anchorsearch end +{pop pop/letter [/letter load /exec load /sc load /exec load]cvx def/legal [/legal load /exec load /sc load /exec load]cvx def/a4 [/a4 load /exec load /sc load /exec load]cvx def/b5 [/b5 load /exec load /sc load /exec load]cvx def +/lettersmall [/lettersmall load /exec load /sc load /exec load]cvx def/a4small [/a4small load /exec load /sc load /exec load]cvx def/note [/note load /exec load /sc load /exec load]cvx def}{pop}ifelse +systemdict/currentpacking known{currentpacking true setpacking}if +/LW{save statusdict/product get(LaserWriter)anchorsearch +exch pop{length 0 eq{1}{2}ifelse}{0}ifelse exch restore}bind def +/LW+{LW 2 eq}bind def +/ok{systemdict/statusdict known dup{LW 0 gt and}if}bind def +%-hsr-% ok{statusdict begin 9 sccinteractive 3 ne exch 0 ne or{9 0 3 setsccinteractive}if end}if +/md 250 dict def md begin +/av 0 def +/T true def/F false def/mtx matrix def/s75 75 string def/s8 8 string def/s1 ( ) def/pxs 1 def/pys 1 def +1 0 mtx defaultmatrix dtransform exch atan/pa exch def/nlw .24 def/ppr [-32 -29.52 762 582.48] def +/pgs 1 def/por true def/xb 500 array def/so true def/tso true def/fillflag false def/pnm 1 def/fmv true def +/sfl false def/ma 0 def/invertflag false def/dbinvertflag false def/xflip false def/yflip false def/noflips true def/scaleby96 false def/fNote true def/fBitStretch true def +/fg (Rvd\001\001\000\000\177) def +/bdf{bind def}bind def +/xdf{exch def}bdf +/xl{neg exch neg translate}bdf +/fp{pnsh 0 ne pnsv 0 ne and}bdf +/nop{}bdf/lnop[/nop load]cvx bdf +/vrb[ +{fp{fg 6 get 0 ne{gsave stroke grestore}{gsave 1 setlinewidth pnsh pnsv scale stroke grestore}ifelse}if newpath}bind +/eofill load +dup +/newpath load +2 index +dup +{clip newpath}bind +{}bind +dup +2 copy +]def +currentscreen/spf xdf/rot xdf/freq xdf +/doop{vrb exch get exec}bdf +/psu{/tso xdf /fNote xdf/fBitStretch xdf/scaleby96 xdf/yflip xdf/xflip xdf +/invertflag xdf/dbinvertflag invertflag statusdict begin version cvr 47.0 ge product (LaserWriter) eq not and end invertflag and {not}if def +xflip yflip or{/noflips false def}if +/pgs xdf 2 index .72 mul exch div/pys xdf div .72 mul/pxs xdf ppr astore pop/por xdf sn and/so xdf}bdf +/tab{statusdict /11x17 known{statusdict begin /11x17 load end}{statusdict /setpage known{statusdict begin 792 1224 1 setpage end}{statusdict /setpageparams known{statusdict begin 792 1224 0 1 setpageparams end}if}ifelse}ifelse}bdf +/txpose{fNote{smalls}{bigs}ifelse pgs get exec pxs pys scale ppr aload pop por{noflips{pop exch neg exch translate pop 1 -1 scale}if +xflip yflip and{pop exch neg exch translate 180 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg translate}if +xflip yflip not and{pop exch neg exch translate pop 180 rotate ppr 3 get ppr 1 get neg sub neg 0 translate}if yflip xflip not and{ppr 1 get neg ppr 0 get neg translate}if} +{noflips{translate pop pop 270 rotate 1 -1 scale}if xflip yflip and{translate pop pop 90 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg translate}if +xflip yflip not and{translate pop pop 90 rotate ppr 3 get ppr +1 get neg sub neg 0 translate}if yflip xflip +not and{translate pop pop 270 rotate ppr 2 get ppr 0 +get neg sub neg 0 exch translate}if}ifelse +%-hsr-% statusdict begin waittimeout 300 lt{/waittimeout 300 def}if end +scaleby96{ppr aload pop 4 -1 roll add 2 div 3 1 roll +add 2 div 2 copy translate .96 dup scale neg exch neg exch translate}if}bdf +/fr{4 copy ppr aload pop 3 -1 roll add 3 1 roll exch add 6 2 roll 3 -1 roll +sub 3 1 roll exch sub 3 -1 roll exch div 3 1 roll div exch scale pop pop xl}bdf +/obl{{0.212557 mul}{pop 0}ifelse}bdf +/sfd{ps fg 5 -1 roll get mul 100 div 0 ps 5 -1 roll obl ps neg 0 0 6a astore makefont setfont}bdf +/fnt{findfont sfd}bdf +/bt{sa 3 1 roll 3 index and put}bdf +/sa(\000\000\000\000\000\000\000\000\000\000)def +/fs{0 1 bt 1 2 bt 2 4 bt 3 8 bt 4 16 bt 5 32 bt 6 64 bt 7 128 bt sa exch 8 exch put}bdf +/mx1 matrix def +/mx2 matrix def +/mx3 matrix def +/bu{currentpoint currentgray currentlinewidth currentlinecap currentlinejoin currentdash exch aload length +fg 5 sfl{1}{0}ifelse put pnsv pnsh +2t aload pop 3a aload pop mx2 aload pop mx1 aload pop mtx currentmatrix aload pop +mx3 aload pop ps pm restore/ps xdf mx3 astore pop}bdf +/bn{/pm save def mx3 setmatrix newpath 0 0 moveto ct dup 39 get 0 exch getinterval cvx exec +mtx astore setmatrix mx1 astore pop mx2 astore pop 3a astore pop +2t astore pop/pnsh xdf/pnsv xdf gw +/sfl fg 5 get 0 ne def array astore exch setdash setlinejoin setlinecap +setlinewidth setgray moveto}bdf +/fc{save vmstatus exch sub 50000 lt +{(%%[|0|]%%)=print flush}if pop restore}bdf +/tc{32768 div add 3 1 roll 32768 div add 2t astore pop}bdf +/3a [0 0 0] def +/2t 2 array def +/tp{3a astore pop}bdf +/tt{mx2 currentmatrix pop currentpoint 2 copy 2t aload pop qa 2 copy translate 3a aload pop exch dup 0 eq +{pop}{1 eq{-1 1}{1 -1}ifelse scale}ifelse rotate pop neg exch neg exch translate moveto}bdf +/te{mx2 setmatrix}bdf +/th{3 -1 roll div 3 1 roll exch div 2 copy mx1 scale pop scale/sfl true def}bdf +/tu{1 1 mx1 itransform scale/sfl false def}bdf +/ts{1 1 mx1 transform scale/sfl true def}bdf +/fz{/ps xdf}bdf +/dv{dup 0 ne{div}{pop}ifelse}bdf +/pop4{pop pop pop pop}bdf +/it{sfl{mx1 itransform}if}bdf +/gm{exch it moveto}bdf/rm{it rmoveto}bdf +/lm{currentpoint sfl{mx1 transform}if exch pop sub 0 exch it rmoveto}bdf +/fm{statusdict/manualfeed known}bdf +/se{statusdict exch/manualfeed exch put}bdf +/mf{dup/ma exch def 0 gt{fm se/t1 5 st ok ma 1 gt and{/t2 0 st/t3 0 st +statusdict/manualfeedtimeout 3600 put +}if}if}bdf +/jn{/statusdict where exch pop{statusdict exch /jobname exch put}if}bdf +/pen{pnm mul/pnsh xdf pnm mul/pnsv xdf pnsh setlinewidth}bdf +/min{2 copy gt{exch}if pop}bdf +/max{2 copy lt{exch}if pop}bdf +/dh{fg 6 1 put array astore dup {1 pxs div mul exch}forall astore exch pop exch pop exch setdash}bdf +/ih[currentdash]def +/rh{fg 6 0 put ih aload pop setdash}bdf +/dl{gsave nlw pys div setlinewidth 0 setgray}bdf +/dlin{exch currentpoint currentlinewidth 2 div dup +translate newpath moveto lineto currentpoint stroke grestore moveto}bdf +/lin{fg 6 get 0 ne{exch lineto currentpoint 0 doop moveto} +{exch currentpoint/pnlv xdf/pnlh xdf gsave newpath/@1 xdf/@2 xdf fp{pnlh @2 lt{pnlv @1 ge +{pnlh pnlv moveto @2 @1 lineto pnsh 0 rlineto +0 pnsv rlineto pnlh pnsh add pnlv pnsv add lineto pnsh neg 0 rlineto} +{pnlh pnlv moveto pnsh 0 rlineto @2 pnsh add @1 lineto 0 pnsv rlineto +pnsh neg 0 rlineto pnlh pnlv pnsv add lineto}ifelse}{pnlv @1 gt +{@2 @1 moveto pnsh 0 rlineto pnlh pnsh add pnlv lineto 0 pnsv rlineto +pnsh neg 0 rlineto @2 @1 pnsv add lineto}{pnlh pnlv moveto pnsh 0 rlineto +0 pnsv rlineto @2 pnsh add @1 pnsv add lineto pnsh neg 0 rlineto +0 pnsv neg rlineto}ifelse}ifelse +closepath fill}if @2 @1 grestore moveto}ifelse}bdf +/gw{/pnm fg 3 get fg 4 get div def}bdf +/lw{fg exch 4 exch put fg exch 3 exch put gw pnsv pnsh pen}bdf +/barc{/@1 xdf/@2 xdf/@3 xdf/@4 xdf/@5 xdf +/@6 xdf/@7 xdf/@8 xdf gsave +@5 @7 add 2 div @6 @8 add 2 div translate newpath 0 0 moveto +@5 @7 sub @6 @8 sub mtx currentmatrix pop scale @1{newpath}if +0 0 0.5 @4 @3 arc @4 @3 sub abs 360 ge{closepath}if +mtx setmatrix @2 doop grestore}bdf +/ar{dup 0 eq barc}bdf +/ov{0 exch 360 exch true barc}bdf +/rc{/@t xdf currentpoint 6 2 roll newpath 4 copy 4 2 roll exch moveto +6 -1 roll lineto lineto lineto closepath @t doop moveto}bdf +/mup{dup pnsh 2 div le exch pnsv 2 div le or}bdf +/rr{/@1 xdf 2. div/@2 xdf 2. div/@3 xdf +/@4 xdf/@5 xdf/@6 xdf/@7 xdf +@7 @5 eq @6 @4 eq @2 mup or or{@7 @6 @5 @4 @1 rc} +{@4 @6 sub 2. div dup @2 lt{/@2 xdf}{pop}ifelse +@5 @7 sub 2. div dup @2 lt{/@2 xdf}{pop}ifelse +@1 0 eq{/@2 @2 pnsh 2 div 2 copy gt{sub def}{0 pop4}ifelse}if +currentpoint newpath +@4 @6 add 2. div @7 moveto +@4 @7 @4 @5 @2 arcto pop4 +@4 @5 @6 @5 @2 arcto pop4 +@6 @5 @6 @7 @2 arcto pop4 +@6 @7 @4 @7 @2 arcto pop4 +closepath @1 doop moveto}ifelse}bdf +/pr{gsave newpath/pl{exch moveto/pl{exch lineto}def}def}bdf +/pl{exch lineto}bdf +/ep{dup 0 eq{{moveto}{exch lin}{}{(%%[|1|]%%)= flush}pathforall +pop grestore}{doop grestore}ifelse currentpoint newpath moveto}bdf +/gr{64. div setgray}bdf +/pat{s8 copy pop 9.375 pa por not{90 add}if{1 add 4 mul cvi s8 exch get exch 1 add 4 mul cvi 7 sub bitshift 1 and}setscreen gr}bdf +/sg{freq rot/spf load setscreen gr}bdf +/dc{transform round .5 sub exch round .5 sub exch itransform}bdf +/sn{userdict/smooth4 known}bdf +/x8{3 bitshift}bdf +/x4{2 bitshift}bdf +/d4{-2 bitshift}bdf +/d8{-3 bitshift}bdf +/rb{15 add -4 bitshift 1 bitshift}bdf +/db{/@7 save def/@1 xdf/@2 xdf/@3 xdf/@4 xdf/@5 xdf/@6 @5 @3 4 add mul def +dc translate scale/xdbit 1 1 idtransform abs/ydbit exch def abs def{0 0 1 ydbit add 1 10 rc clip}if +@1 0 eq @1 4 eq or{1 setgray ydbit 0 1 ydbit add 1 2 rc}if +@1 3 eq @1 7 eq or{1}{0}ifelse setgray/@9 @1 0 eq @1 1 eq @1 3 eq or or dbinvertflag xor def/@13 @6 def +@2 fBitStretch or{/@10 @4 x4 def/@11 @3 x4 def/@12 @10 rb def/@13 @12 @11 mul def/@15 1 1 dtransform abs/calcY 1 index def round cvi/@14 exch def +abs/calcX 1 index def round cvi scaleby96 not{1 add}if def/@16 @15 rb def/@17 @16 @14 mul def}if +sn @13 60000 lt and @2 fBitStretch or and{mtx currentmatrix dup 1 get exch 2 get 0. eq exch 0. eq and @17 60000 lt and fBitStretch and{@16 3 bitshift @14 @9 [calcX 0 0 calcY 0 0]{@17 string @13 string +currentfile @6 string readhexstring pop 1 index @4 @3 @5 @12 @2 smooth4 +@10 @11 @12 dup string 5 index @15 @14 @16 dup string stretch}imagemask}{@12 x8 @11 @9 [@10 0 0 @11 0 0]{@13 string +currentfile @6 string readhexstring pop 1 index @4 @3 @5 @12 @2 smooth4}imagemask}ifelse}{@5 3 bitshift @3 4 add @9 [@4 0 0 @3 0 2]{currentfile @6 string readhexstring pop}imagemask}ifelse +@7 restore}bdf +/multibit{/mbdeep exch def/mbY exch def/mbX exch def +save mbX mbY mbdeep[mbX 0 0 mbY 0 0]{currentfile picstr readhexstring pop}image +restore}bdf +/wd 16 dict def +/mfont 14 dict def +/mdf{mfont wcheck not{/mfont 14 dict def}if mfont begin xdf end}bdf +/cf{{1 index/FID ne{def}{pop pop}ifelse}forall}bdf/rf{/@1 exch def/@2 exch def +FontDirectory @2 known{cleartomark pop}{findfont dup begin dup length @1 add dict begin +cf{/Encoding macvec def}{Encoding dup length array copy/Encoding exch def +counttomark 2 idiv{Encoding 3 1 roll put}repeat}ifelse +pop +exec currentdict end end @2 exch definefont pop}ifelse}bdf +/bmbc{exch begin wd begin +/cr xdf +save +CharTable cr 6 mul 6 getinterval{}forall +/bitheight xdf/bitwidth xdf +.96 div/width xdf +Gkernmax add/XOffset xdf Gdescent add/YOffset xdf/rowbytes xdf +rowbytes 255 eq{0 0 0 0 0 0 setcachedevice} +{Gnormsize dup scale +width 0 XOffset YOffset bitwidth XOffset add bitheight YOffset add +setcachedevice +rowbytes 0 ne{ +XOffset YOffset translate newpath 0 0 moveto +bitwidth bitheight scale +sn{ +/xSmt bitwidth x4 def +/ySmt bitheight x4 def +/rSmt xSmt rb def +rSmt x8 ySmt true +[xSmt 0 0 ySmt neg 0 ySmt] +{rSmt ySmt mul string CharData cr get +1 index bitwidth bitheight rowbytes rSmt tso smooth4} +}{rowbytes 3 bitshift bitheight 4 add true +[bitwidth 0 0 bitheight neg 0 bitheight 2 add] +{CharData cr get} +}ifelse +imagemask +}if +}ifelse +restore +end end +}bdf +/bb{.96 exch div/Gnormsize mdf 2 index +/Gkernmax mdf 1 index/Gdescent mdf +3 index div 4 1 roll +2 index div 1. 5 2 roll +exch div 4 1 roll +4 array astore/FontBBox mdf +}bdf +/cdf{mfont/CharData get 3 1 roll put}bdf +/bf{ +mfont begin +/FontType 3 def +/FontMatrix [1 0 0 1 0 0] def +/Encoding macvec def +/BuildChar/bmbc load def +end +mfont definefont pop +}bdf +/wi LW 1 eq{{gsave 0 0 0 0 0 0 0 0 moveto lineto lineto lineto closepath clip stringwidth grestore}bind}{/stringwidth load}ifelse def +/aps{0 get 124 eq}bdf +/xc{s75 cvs dup}bdf +/xp{put cvn}bdf +/scs{xc 3 67 put dup 0 95 xp}bdf +/sos{xc 3 79 xp}bdf +/sbs{xc 1 66 xp}bdf +/sis{xc 2 73 xp}bdf +/sob{xc 2 79 xp}bdf +/sss{xc 4 83 xp}bdf +/dd{exch 1 index add 3 1 roll add exch}bdf +/smc{moveto dup show}bdf +/kwn{FontDirectory 1 index known{findfont exch pop}}bdf +/gl{1 currentgray sub setgray}bdf +/mm{/mfont 10 dict def mfont begin +/FontMatrix [1 0 0 1 0 0] def +/FontType 3 def +/Encoding macvec def +/df 4 index findfont def +/FontBBox [0 0 1 1] def +/xda xdf/mbc xdf +/BuildChar{wd begin/cr xdf/fd xdf/cs s1 dup 0 cr put def fd/mbc get exec end}def +exec end mfont definefont}bdf +/ac{dup scs kwn{exch findfont dup length 1 add dict begin{1 index/FID ne 2 index/UniqueID ne and{def}{pop pop}ifelse}forall +fmv{/Encoding macvec def}if/StrokeWidth nlw 1000 mul pys div ps div dup 12 lt{pop 12}if def +/PaintType 2 def currentdict end definefont}ifelse}bdf +/mb{dup sbs kwn{exch{pop}{bbc}{}mm}ifelse sfd}bdf +/mo{dup sos kwn{exch{pop}{boc}{}mm}ifelse sfd}bdf +/ms{dup sss kwn{exch{pop}{bsc}{}mm}ifelse sfd}bdf +/ou{dup sos kwn{exch dup ac pop{scs findfont /df2 xdf}{aoc}{}mm}ifelse sfd}bdf +/su{dup sss kwn{exch dup ac pop{scs findfont /df2 xdf}{asc}{}mm}ifelse sfd}bdf +/ao{/fmv true def ou}bdf/as{/fmv true def su}bdf +/vo{/fmv false def ou}bdf/vs{/fmv false def su}bdf +/bbc{/da .03 def fd/df get setfont +gsave cs wi 1 index 0 ne{exch da add exch}if grestore setcharwidth +cs 0 0 smc da 0 smc da da smc 0 da moveto show}bdf +/boc{/da 1 ps div def fd/df get setfont +gsave cs wi 1 index 0 ne{exch da add exch}if grestore setcharwidth +cs 0 0 smc da 0 smc da da smc 0 da smc gl da 2. div dup moveto show}bdf +/bsc{/da 1 ps div def +/ds .05 def/da2 da 2. div def fd/df get setfont +gsave cs wi 1 index 0 ne{exch ds add da2 add exch}if grestore setcharwidth +cs ds da2 add .01 add 0 smc 0 ds da2 sub translate 0 0 smc +da 0 smc da da smc 0 da smc gl da 2. div dup moveto show}bdf +/aoc{fd/df get setfont +gsave cs wi grestore setcharwidth +gl cs 0 0 smc fd/df2 get setfont gl 0 0 moveto show}bdf +/asc{/da .05 def fd/df get setfont +gsave cs wi 1 index 0 ne{exch da add exch}if grestore setcharwidth +cs da .01 add 0 smc 0 da translate gl 0 0 smc gl fd/df2 get setfont 0 0 moveto show}bdf +/st{1000 mul usertime add dup 2147483647 gt{2147483647 sub}if def}bdf +/the{usertime sub dup 0 lt exch -2147483648 gt and}bdf +/6a 6 array def +/2a 2 array def +/3q 3 array def +/qs{3 -1 roll sub exch 3 -1 roll sub exch}bdf +/qa{3 -1 roll add exch 3 -1 roll add exch}bdf +/qm{3 -1 roll 1 index mul 3 1 roll mul}bdf +/qn{6a exch get mul}bdf +/qA .166667 def/qB .833333 def/qC .5 def +/qx{6a astore pop +qA 0 qn qB 2 qn add qA 1 qn qB 3 qn add +qB 2 qn qA 4 qn add qB 3 qn qA 5 qn add +qC 2 qn qC 4 qn add qC 3 qn qC 5 qn add}bdf +/qp{6 copy 12 -2 roll pop pop}bdf +/qc{exch qp qx curveto}bdf +/qi{{exch 4 copy 2a astore aload pop qa .5 qm newpath moveto}{exch 2 copy 6 -2 roll 2 qm qs 4 2 roll}ifelse}bdf +/qq{{qc 2a aload pop qx curveto}{exch 4 copy qs qa qx curveto}ifelse}bdf +/pt{currentpoint newpath moveto}bdf +/qf{/fillflag true def}bdf +/ec{1 and 0 ne{0 doop}if grestore currentpoint newpath moveto/fillflag false def}bdf +/eu{currentpoint fp{0 ep}{grestore newpath}ifelse moveto/fillflag false def}bdf +/bp{currentpoint newpath 2 copy moveto}bdf +/ef{gsave fillflag{gsave eofill grestore}if}bdf +/sm{0 exch{@1 eq{1 add}if}forall}bdf +/lshow{4 1 roll exch/@1 exch def{1 index wi pop sub 1 index sm dv 0 @1 4 -1 roll widthshow}{1 index wi pop sub +1 index dup sm 10 mul exch length 1 sub add dv dup 10. mul 0 @1 4 -1 roll 0 6 -1 roll awidthshow}ifelse}bdf +/setTxMode{sa 9 2 index put 3 eq{1}{0}ifelse setgray}bdf +/SwToSym{{}mark false/Symbol/|______Symbol 0 rf 0 sa 6 get 0 ne{pop 1}{sa 7 get 0 eq{pop 2}if}ifelse +sa 1 get 0 ne/|______Symbol +sa 4 get 0 ne{vs}{sa 3 get 0 ne{vo}{fnt}ifelse}ifelse}bdf +/mc{0 3 1 roll transform neg exch pop}bdf +/ul{dup 0 ne sa 2 get 0 ne and{gsave 0 0 +/UnderlinePosition kif{mc}{ps -10 div}ifelse/UnderlineThickness kif{mc}{ps 15 div}ifelse +abs setlinewidth neg rmoveto +sa 4 get 0 ne{gsave currentlinewidth 2. div dup rmoveto currentpoint newpath moveto +2 copy rlineto stroke grestore}if +sa 3 get sa 4 get or 0 ne{gsave gl 2 copy rlineto stroke grestore rlineto strokepath nlw pys div setlinewidth}{rlineto}ifelse +stroke grestore}{pop}ifelse}bdf +/sgt{2 copy known{get true}{pop pop false}ifelse}bdf +/kif{currentfont dup/FontMatrix get exch/FontInfo sgt{true}{currentfont/df sgt +{dup/FontInfo sgt{3 1 roll/FontMatrix get mtx concatmatrix exch true}{pop pop pop false} +ifelse}{pop pop false}ifelse}ifelse{3 -1 roll sgt{exch true}{pop false}ifelse}{false}ifelse}bdf +/blank/Times-Roman findfont/CharStrings get/space get def +/macvec 256 array def +/NUL/SOH/STX/ETX/EOT/ENQ/ACK/BEL/BS/HT/LF/VT/FF/CR/SO/SI +/DLE/DC1/DC2/DC3/DC4/NAK/SYN/ETB/CAN/EM/SUB/ESC/FS/GS/RS/US +macvec 0 32 getinterval astore pop +macvec 32/Times-Roman findfont/Encoding get +32 96 getinterval putinterval macvec dup 39/quotesingle put 96/grave put +/Adieresis/Aring/Ccedilla/Eacute/Ntilde/Odieresis/Udieresis/aacute +/agrave/acircumflex/adieresis/atilde/aring/ccedilla/eacute/egrave +/ecircumflex/edieresis/iacute/igrave/icircumflex/idieresis/ntilde/oacute +/ograve/ocircumflex/odieresis/otilde/uacute/ugrave/ucircumflex/udieresis +/dagger/degree/cent/sterling/section/bullet/paragraph/germandbls +/registered/copyright/trademark/acute/dieresis/notequal/AE/Oslash +/infinity/plusminus/lessequal/greaterequal/yen/mu/partialdiff/summation +/product/pi/integral/ordfeminine/ordmasculine/Omega/ae/oslash +/questiondown/exclamdown/logicalnot/radical/florin/approxequal/Delta/guillemotleft +/guillemotright/ellipsis/blank/Agrave/Atilde/Otilde/OE/oe +/endash/emdash/quotedblleft/quotedblright/quoteleft/quoteright/divide/lozenge +/ydieresis/Ydieresis/fraction/currency/guilsinglleft/guilsinglright/fi/fl +/daggerdbl/periodcentered/quotesinglbase/quotedblbase/perthousand/Acircumflex/Ecircumflex/Aacute +/Edieresis/Egrave/Iacute/Icircumflex/Idieresis/Igrave/Oacute/Ocircumflex +/apple/Ograve/Uacute/Ucircumflex/Ugrave/dotlessi/circumflex/tilde +/macron/breve/dotaccent/ring/cedilla/hungarumlaut/ogonek/caron +macvec 128 128 getinterval astore pop +{}mark true/Courier/|______Courier 0 rf +{/Metrics 21 dict begin/zero 600 def/one 600 def/two 600 def/three 600 def/four 600 def/five 600 def/six 600 def/seven 600 def/eight 600 def +/nine 600 def/comma 600 def/period 600 def/dollar 600 def/numbersign 600 def/percent 600 def/plus 600 def/hyphen 600 def/E 600 def/parenleft 600 def/parenright 600 def/space 600 def +currentdict end def currentdict/UniqueID known{/UniqueID 16#800000 def}if/FontBBox FontBBox 4 array astore def}mark true/Helvetica/|______Seattle 1 rf +/oldsettransfer/settransfer load def +/concatprocs{/proc2 exch cvlit def/proc1 exch cvlit def/newproc proc1 length proc2 length add array def +newproc 0 proc1 putinterval newproc proc1 length proc2 putinterval newproc cvx}def +/settransfer{currenttransfer concatprocs oldsettransfer}def +/PaintBlack{{1 exch sub}settransfer gsave newpath clippath 1 setgray fill grestore}def +/od{1 -1 scale %-AKT-% (Rvd\001\001\000\000\177) fg copy pop txpose +1 0 mtx defaultmatrix dtransform exch atan/pa exch def +newpath clippath mark +{transform{itransform moveto}}{transform{itransform lineto}} +{6 -2 roll transform 6 -2 roll transform 6 -2 roll transform +{itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll curveto}} +{{closepath}}pathforall newpath counttomark array astore/gc xdf pop ct 39 0 put +10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack}if}bdf +/cd{}bdf +/op{/sfl false def/pm save def}bdf +/cp{not{userdict/#copies 0 put}if ma 0 gt{{t1 the{exit}if}loop}if{copypage}{showpage}ifelse pm restore}def +/px{0 3 1 roll tp tt}bdf +/psb{/us save def}bdf +/pse{us restore}bdf +/ct 40 string def +/nc{currentpoint initclip newpath gc{dup type dup/arraytype eq exch/packedarraytype eq or{exec}if} +forall clip newpath moveto}def +/kp{ct 0 2 index length 2 index 39 2 index put getinterval copy cvx exec mx3 currentmatrix pop}bdf +/av 68 def +end +LW 1 eq userdict/a4small known not and{/a4small +[[300 72 div 0 0 -300 72 div -120 3381] +280 3255 +{statusdict/jobstate (printing) put 0 setblink +margins +exch 196 add exch 304 add 8 div round cvi frametoroket +statusdict/jobstate (busy) put +1 setblink} +/framedevice load +60 45{dup mul exch dup mul add 1.0 exch sub}/setscreen load +{}/settransfer load/initgraphics load/erasepage load]cvx +statusdict begin bind end readonly def}if +md begin/bigs[lnop userdict/letter known{/letter load}{lnop}ifelse userdict/legal known{/legal load}{lnop}ifelse userdict/a4 known{/a4 load}{lnop}ifelse userdict/b5 known{/b5 load}{lnop}ifelse +lnop lnop lnop /tab load]def +/smalls[lnop userdict/lettersmall known{/lettersmall load}{userdict/note known{/note load}{lnop}ifelse}ifelse +userdict/legal known{/legal load}{lnop}ifelse userdict/a4small known{/a4small load}{lnop}ifelse +userdict/b5 known{/b5 load}{userdict/note known{/note load}{lnop}ifelse}ifelse lnop lnop lnop /tab load]def end +systemdict/currentpacking known{setpacking}if +%%EndProcSet + +%%EOF diff --git a/dviware/psprint/vms/laserprep70.ps b/dviware/psprint/vms/laserprep70.ps new file mode 100644 index 0000000000..c7c8316f44 --- /dev/null +++ b/dviware/psprint/vms/laserprep70.ps @@ -0,0 +1,480 @@ +% When printing a document on a PostScript printer, most Macintosh applications +% will dump their PostScript code into a file called PostScript0 if you press +% Command-F immediately after selecting OK in the Print dialogue box. +% The PostScript code relies on definitions stored in a Mac system file called +% Laser Prep. A modified version of Laser Prep (like the one you're reading) +% must be included with PSPRINT's /PREP qualifier if you want to send +% Command-F files via DVI \special commands. +% +% Since Apple keep changing Laser Prep, you might need to create your own +% modified version some day. Here's how: +% 1. Use a Mac application (such as MacWrite) to create a very small document. +% 2. Print it, but immediately after selecting OK hold down Command-K. +% Instead of printing the document, you should get a file called PostScript0 +% which contains Laser Prep prefixed to the Command-F code. +% 3. Open the file with a text editor and remove the Command-F code by finding +% the first occurrence of %%EOF and deleting everything below it. +% 4. Duplicate the changes I've made to this file (search for %AKT). +% 5. It's probably a good idea to rename PostScript0 to LaserPrepxx.ps where +% xx is the version number appearing in comments at the top of the file. +% 6. Type "PSPRINT /PREP=LaserPrepxx.ps ..." with your fingers crossed. + +%%Title: "Laser Prep -- The Apple PostScript Dictionary (md)" +%%Creator: Apple Software Engineering +%%CreationDate: Thursday, March 19, 1987 +%{appledict version #70 0 +% CopyRight Apple Computer, Inc. 1984-89 All Rights Reserved. +%%EndComments +%%BeginProcSet: "(AppleDict md)" 70 0 +statusdict begin product(LaserWriter II NT)eq revision 1 eq and +{userdict begin/oldcds/cleardictstack load def/cleardictstack{31 sendpcmd 4 eq tonerlight/oldcds load exec}bind def +end +currentfile eexec +}{save currentfile 359 string readhexstring pop pop restore}ifelse +35de8eabfc7fa5eac0431edc501ad43f5fcbdf9fdd321cce93b525f4439dd94696bf56ac13a0a2aad1e6bcf444711e941d7217138d20ae0500145f815439cc14e697ad201df728ea4ccad4ac +331aa03a7aacde10760bf4ee12bbf73c77cdcbf1796f26f0dd255d2407e1ac41 +d27489a69d6b69c6a841468b46720b75ad65650700e0c528e7af61e7e3e821b59445c44b69831ebc9deaf0e3aecc14b7a1c2e18bc1fa42a59219f1e36f236e3d6c89114b1f231999c3dbce6b43f3e2918fcb85575941a9d1e65c86aa08e6eea86cc66ce90e5e4add57f2585e +7b1c0b5203cfc46868d6e3c0d66db79174e7091e32e307679732da062e440e41dabd36a161b611a7e4523a49694026206803dbfd5be5c5fe433f0f18a40057db6f1302848c8da4a10a7f14c6 +3d512806362b1be092ad5dbd36d75fe63e4cae2ba9b72390f580cac344a08bdf6eb9e36ec45bad2a0b82829a72e0efa2d87332c482196e690361168271c55053341ab3 +end +/sc {60 45 {abs exch abs 2 copy add 1 gt{1.0 sub dup mul exch 1.0 sub dup mul add 1.0 sub} +{dup mul exch dup mul add 1.0 exch sub} +ifelse}setscreen} bind def statusdict begin product(LaserWriter II)anchorsearch end +{pop pop/letter [/letter load /exec load /sc load /exec load]cvx def/legal [/legal load /exec +load /sc load /exec load]cvx def/a4 [/a4 load /exec load /sc load /exec load]cvx def +/b5 [/b5 load /exec load /sc load /exec load]cvx def +/lettersmall [/lettersmall load /exec load /sc load /exec load]cvx def +/a4small [/a4small load /exec load /sc load /exec load]cvx def +/note [/note load /exec load /sc load /exec load]cvx def}{pop}ifelse +systemdict/currentpacking known{currentpacking true setpacking}if +/LW{save statusdict/product get(LaserWriter)anchorsearch +exch pop{length 0 eq{1}{2}ifelse}{0}ifelse exch restore}bind def +/LW+{LW 2 eq}bind def +/ok{systemdict/statusdict known dup{LW 0 gt and}if}bind def + +%AKT ok{statusdict begin 9 sccinteractive 3 ne exch 0 ne or{9 0 3 setsccinteractive}if end}if + +/md 270 dict def md begin +/av 0 def +/T true def/F false def/mtx matrix def/s75 75 string def/sa8 8 string def/sb8 8 string def +/sc8 8 string def/sd8 8 string def/s1 ( ) def/pxs 1 def/pys 1 def +/ns false def +1 0 mtx defaultmatrix dtransform exch atan/pa exch def/nlw .24 def/ppr [-32 -29.52 762 582.48] def +/pgr [0 0 0 0] def +/pgs 1 def/por true def/xb 500 array def/so true def/tso true def/fillflag false def/pnm 1 def/fmv true def +/sfl false def/ma 0 def/invertflag false def/dbinvertflag false def/xflip false def/yflip false def/noflips true def/scaleby96 false def/fNote true def/fBitStretch true def +/4colors false def/3colors false def/2colors false def +/wtkey false def +statusdict begin/waittimeout where{pop waittimeout 300 lt{md /wtkey true put}if}if end +wtkey{statusdict begin/setdefaulttimeouts where{pop 0 60 300 setdefaulttimeouts}if end}if +/fg (Rvd\001\001\000\000\177) def +/bdf{bind def}bind def +/xdf{exch def}bdf +/xl{neg exch neg translate}bdf +/fp{pnsh 0 ne pnsv 0 ne and}bdf +/nop{}bdf/lnop[/nop load]cvx bdf +/vrb[ +{fp{fg 6 get 0 ne{gsave stroke grestore}{gsave 1 setlinewidth pnsh pnsv scale stroke grestore}ifelse}if newpath}bind +/eofill load +dup +/newpath load +2 index +dup +{clip newpath}bind +{}bind +dup +2 copy +]def +systemdict/currentcolorscreen known{currentcolorscreen/dkspf xdf/dkrot xdf/dkfreq xdf/dyspf xdf/dyrot xdf/dyfreq xdf/dmspf xdf/dmrot xdf/dmfreq xdf +/dcspf xdf/dcrot xdf/dcfreq xdf}{currentscreen/spf xdf/rot xdf/freq xdf}ifelse +/doop{vrb exch get exec}bdf +/psu{/udf xdf/tso xdf /fNote xdf/fBitStretch xdf/scaleby96 xdf/yflip xdf/xflip xdf +/invertflag xdf/dbinvertflag invertflag statusdict begin +version cvr 47.0 ge product (LaserWriter) eq not and end invertflag and {not}if def +xflip yflip or{/noflips false def}if +/pgs xdf 2 index .72 mul exch div/pys xdf div .72 mul/pxs xdf ppr astore pop pgr astore pop/por xdf sn and/so xdf}bdf +/tab{statusdict /11x17 known{statusdict begin /11x17 load end}{statusdict /setpage known{statusdict begin 792 1224 1 setpage end}{statusdict /setpageparams known{statusdict begin 792 1224 0 1 setpageparams end}if}ifelse}ifelse}bdf +/a3Size{statusdict /a3 known{statusdict begin /a3 load end}{statusdict /setpageparams known{statusdict begin 842 1191 0 1 setpageparams end}if}ifelse}bdf +/txpose{fNote{smalls}{bigs}ifelse pgs get exec pxs pys scale ppr aload pop por{noflips{pop exch neg exch translate pop 1 -1 scale}if +xflip yflip and{pop exch neg exch translate 180 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg translate}if +xflip yflip not and{pop exch neg exch translate pop 180 rotate ppr 3 get ppr 1 get neg sub neg 0 translate}if yflip xflip not and{ppr 1 get neg ppr 0 get neg translate}if} +{noflips{translate pop pop 270 rotate 1 -1 scale}if xflip yflip and{translate pop pop 90 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg translate}if +xflip yflip not and{translate pop pop 90 rotate ppr 3 get ppr 1 get neg sub neg 0 translate}if yflip xflip not and{translate pop pop 270 rotate ppr 2 get ppr 0 get neg sub neg 0 exch translate}if}ifelse +wtkey{statusdict/waittimeout 300 put}if +scaleby96{ppr aload pop 4 -1 roll add 2 div 3 1 roll add 2 div 2 copy translate .96 dup scale neg exch neg exch translate}if}bdf +/fr{4 copy pgr aload pop 3 -1 roll add 3 1 roll exch add 6 2 roll 3 -1 roll +sub 3 1 roll exch sub 3 -1 roll exch div 3 1 roll div exch scale pop pop xl}bdf +/obl{{0.212557 mul}{pop 0}ifelse}bdf +/sfd{ps fg 5 -1 roll get mul 100 div 0 ps 5 -1 roll obl ps neg 0 0 6a astore makefont setfont}bdf +/fnt{findfont sfd}bdf +/bt{sa 3 1 roll 3 index and put}bdf +/sa(\000\000\000\000\000\000\000\000\000\000)def +/fs{0 1 bt 1 2 bt 2 4 bt 3 8 bt 4 16 bt 5 32 bt 6 64 bt 7 128 bt sa exch 8 exch put}bdf +/mx1 matrix def +/mx2 matrix def +/mx3 matrix def +/bu{currentpoint 4colors{currentcmykcolor}{currentrgbcolor}ifelse currentlinewidth currentlinecap currentlinejoin +currentdash exch aload length fg 5 sfl{1}{0}ifelse put pnsv pnsh +2t aload pop 3a aload pop mx2 aload pop mx1 aload pop mtx currentmatrix aload pop +mx3 aload pop ps pm restore/ps xdf mx3 astore pop}bdf +/bn{/pm save def mx3 setmatrix newpath 0 0 moveto ct dup 39 get 0 exch getinterval cvx exec mtx astore setmatrix mx1 astore pop mx2 astore pop 3a +astore pop 2t astore pop/pnsh xdf/pnsv xdf gw +/sfl fg 5 get 0 ne def array astore exch setdash setlinejoin setlinecap +setlinewidth 4colors{setcmykcolor}{setrgbcolor}ifelse moveto}bdf +/fc{save vmstatus exch sub 50000 lt +{(%%[|0|]%%)=print flush}if pop restore}bdf +/tc{32768 div add 3 1 roll 32768 div add 2t astore pop}bdf +/3a [0 0 0] def +/2t 2 array def +/tp{3a astore pop}bdf +/tt{mx2 currentmatrix pop currentpoint 2 copy 2t aload pop qa 2 copy translate 3a aload pop exch dup 0 eq +{pop}{1 eq{-1 1}{1 -1}ifelse scale}ifelse rotate pop neg exch neg exch translate moveto}bdf +/te{mx2 setmatrix}bdf +/th{3 -1 roll div 3 1 roll exch div 2 copy mx1 scale pop scale/sfl true def}bdf +/tu{1 1 mx1 itransform scale/sfl false def}bdf +/ts{1 1 mx1 transform scale/sfl true def}bdf +/fz{/ps xdf}bdf +/dv{dup 0 ne{div}{pop}ifelse}bdf +/pop4{pop pop pop pop}bdf +/it{sfl{mx1 itransform}if}bdf +/gm{exch it moveto}bdf/rm{it rmoveto}bdf +/lm{currentpoint sfl{mx1 transform}if exch pop sub 0 exch it rmoveto}bdf +/fm{statusdict/manualfeed known}bdf +/se{statusdict exch/manualfeed exch put}bdf +/mf{dup/ma exch def 0 gt{fm se/t1 5 st ok ma 1 gt and{/t2 0 st/t3 0 st +statusdict/manualfeedtimeout 3600 put +}if}if}bdf +/jn{/statusdict where exch pop{statusdict exch /jobname exch put}if}bdf +/pen{pnm mul/pnsh xdf pnm mul/pnsv xdf pnsh setlinewidth}bdf +/min{2 copy gt{exch}if pop}bdf +/max{2 copy lt{exch}if pop}bdf +/dh{fg 6 1 put array astore dup {1 pxs div mul exch}forall astore exch pop exch pop exch setdash}bdf +/ih[currentdash]def +/rh{fg 6 0 put ih aload pop setdash}bdf +/dl{gsave nlw pys div setlinewidth 0 setgray}bdf +/dlin{exch currentpoint currentlinewidth 2 div dup +translate newpath moveto lineto currentpoint stroke grestore moveto}bdf +/lin{fg 6 get 0 ne{exch lineto currentpoint 0 doop moveto} +{exch currentpoint/pnlv xdf/pnlh xdf gsave newpath/@1 xdf/@2 xdf fp{pnlh @2 lt{pnlv @1 ge +{pnlh pnlv moveto @2 @1 lineto pnsh 0 rlineto +0 pnsv rlineto pnlh pnsh add pnlv pnsv add lineto pnsh neg 0 rlineto} +{pnlh pnlv moveto pnsh 0 rlineto @2 pnsh add @1 lineto 0 pnsv rlineto +pnsh neg 0 rlineto pnlh pnlv pnsv add lineto}ifelse}{pnlv @1 gt +{@2 @1 moveto pnsh 0 rlineto pnlh pnsh add pnlv lineto 0 pnsv rlineto +pnsh neg 0 rlineto @2 @1 pnsv add lineto}{pnlh pnlv moveto pnsh 0 rlineto +0 pnsv rlineto @2 pnsh add @1 pnsv add lineto pnsh neg 0 rlineto +0 pnsv neg rlineto}ifelse}ifelse +closepath fill}if @2 @1 grestore moveto}ifelse}bdf +/gw{/pnm fg 3 get fg 4 get div def}bdf +/lw{fg exch 4 exch put fg exch 3 exch put gw pnsv pnsh pen}bdf +/barc{/@1 xdf/@2 xdf/@3 xdf/@4 xdf/@5 xdf +/@6 xdf/@7 xdf/@8 xdf gsave +@5 @7 add 2 div @6 @8 add 2 div translate newpath 0 0 moveto +@5 @7 sub @6 @8 sub mtx currentmatrix pop scale @1{newpath}if +0 0 0.5 @4 @3 arc @4 @3 sub abs 360 ge{closepath}if +mtx setmatrix @2 doop grestore}bdf +/ar{dup 0 eq barc}bdf +/ov{0 exch 360 exch true barc}bdf +/rc{/@t xdf currentpoint 6 2 roll newpath 4 copy 4 2 roll exch moveto +6 -1 roll lineto lineto lineto closepath @t doop moveto}bdf +/mup{dup pnsh 2 div le exch pnsv 2 div le or}bdf +/rr{/@1 xdf 2. div/@2 xdf 2. div/@3 xdf +/@4 xdf/@5 xdf/@6 xdf/@7 xdf +@7 @5 eq @6 @4 eq @2 mup or or{@7 @6 @5 @4 @1 rc} +{@4 @6 sub 2. div dup @2 lt{/@2 xdf}{pop}ifelse +@5 @7 sub 2. div dup @2 lt{/@2 xdf}{pop}ifelse +@1 0 eq{/@2 @2 pnsh 2 div 2 copy gt{sub def}{0 pop4}ifelse}if +currentpoint newpath +@4 @6 add 2. div @7 moveto +@4 @7 @4 @5 @2 arcto pop4 +@4 @5 @6 @5 @2 arcto pop4 +@6 @5 @6 @7 @2 arcto pop4 +@6 @7 @4 @7 @2 arcto pop4 +closepath @1 doop moveto}ifelse}bdf +/pr{gsave newpath/pl{exch moveto/pl{exch lineto}def}def}bdf +/pl{exch lineto}bdf +/ep{dup 0 eq{{moveto}{exch lin}{}{(%%[|1|]%%)= flush}pathforall +pop grestore}{doop grestore}ifelse currentpoint newpath moveto}bdf +/gr{64. div setgray}bdf +/savescreen{ns not{/ns true def systemdict/currentcolorscreen known{currentcolorscreen/pkspf xdf/pkrot xdf/pkfreq xdf/pyspf xdf/pyrot xdf/pyfreq xdf/pmspf xdf/pmrot xdf/pmfreq xdf +/pcspf xdf/pcrot xdf/pcfreq xdf}{currentscreen/sspf xdf/srot xdf/sfreq xdf}ifelse}if}bdf +/restorescreen{/ns false def systemdict/setcolorscreen known{pcfreq pcrot/pcspf load pmfreq pmrot/pmspf load pyfreq pyrot/pyspf load +pkfreq pkrot/pkspf load setcolorscreen}{sfreq srot/sspf load setscreen}ifelse}bdf +/pat{savescreen sa8 +copy pop 9.375 pa por not{90 add}if{1 add 4 mul cvi sa8 exch get exch 1 add 4 mul cvi 7 sub bitshift 1 and}setscreen exch not{gr}{pop}ifelse}bdf +/sg{restorescreen gr}bdf +/cpat{savescreen 10 2 roll 7 -1 roll sa8 copy pop 9.375 pa por not{90 add}if{1 add 4 mul cvi sa8 exch get exch 1 add 4 mul cvi 7 sub bitshift 1 and}8 -1 roll sb8 copy pop 9.375 pa por not{90 add}if{1 add 4 mul cvi sb8 +exch get exch 1 add 4 mul cvi 7 sub bitshift 1 and}9 -1 roll sc8 copy pop 9.375 pa por not{90 add}if{1 add 4 mul cvi sc8 exch get exch 1 add 4 mul cvi 7 sub bitshift 1 and} %AKT broke long line +10 -1 roll sd8 copy pop 9.375 pa por not{90 add}if{1 add 4 mul cvi sd8 +exch get exch 1 add 4 mul cvi 7 sub bitshift 1 and}psuedo1 dsc 4{4 -1 roll 1 exch 64 div sub}repeat setcmykcolor pop pop}bdf +systemdict/setcolorscreen known{/psuedo1 lnop bdf/dsc/setcolorscreen load def}{/psuedo1{16{pop}repeat sa8 copy pop 9.375 pa por not{90 add}if{1 add 4 mul cvi sa8 exch get exch 1 add 4 mul cvi 7 sub bitshift 1 and}}bdf +/bwsc{setscreen dup gr 0 exch 0 exch 64 exch 64 exch 64 exch}bdf/dsc/bwsc load def +}ifelse +systemdict/setcmykcolor known not{/setcmykcolor{1 sub 4 1 roll 3{3 index add neg dup 0 lt{pop 0}if 3 1 roll}repeat setrgbcolor pop}bdf}if +/dc{transform round .5 sub exch round .5 sub exch itransform}bdf +/sn{userdict/smooth4 known}bdf +/x8{3 bitshift}bdf +/x4{2 bitshift}bdf +/d4{-2 bitshift}bdf +/d8{-3 bitshift}bdf +/rb{15 add -4 bitshift 1 bitshift}bdf +/db{/@7 save def/@1 xdf/@2 xdf/@3 xdf/@4 xdf/@5 xdf/@6 @5 @3 4 add mul def +dc translate scale/xdbit 1 1 idtransform abs/ydbit exch def abs def{0 0 1 ydbit add 1 10 rc clip}if +@1 0 eq @1 4 eq or{currentrgbcolor 1 setgray ydbit 0 1 ydbit add 1 2 rc setrgbcolor}if +@1 3 eq @1 7 eq or{1 setgray}{currentrgbcolor 2 index eq exch 2 index eq and exch pop{0 setgray}if}ifelse/@9 @1 0 eq @1 1 eq @1 3 eq or or dbinvertflag xor def/@13 @6 def +@2 fBitStretch or{/@10 @4 x4 def/@11 @3 x4 def/@12 @10 rb def/@13 @12 @11 mul def/@15 1 1 dtransform abs/calcY 1 index def round cvi/@14 exch def +abs/calcX 1 index def round cvi scaleby96 not{1 add}if def/@16 @15 rb def/@17 @16 @14 mul def}if +sn @13 60000 lt and @2 fBitStretch or and{mtx currentmatrix dup 1 get exch 2 get 0. eq exch 0. eq and @17 60000 lt and fBitStretch and{@16 3 bitshift @14 @9 [calcX 0 0 calcY 0 0]{@17 string @13 string +currentfile @6 string readhexstring pop 1 index @4 @3 @5 @12 @2 smooth4 +@10 @11 @12 dup string 5 index @15 @14 @16 dup string stretch}imagemask}{@12 x8 @11 @9 [@10 0 0 @11 0 0]{@13 string +currentfile @6 string readhexstring pop 1 index @4 @3 @5 @12 @2 smooth4}imagemask}ifelse}{@5 3 bitshift @3 4 add @9 [@4 0 0 @3 0 2]{currentfile @6 string readhexstring pop}imagemask}ifelse +@7 restore}bdf +systemdict/setcmykcolor known{/psuedo lnop bdf/di/colorimage load def}{/routines[{.3 mul add 1}bind{.59 mul add 2}bind{.11 mul add round cvi str exch i exch put/i i 1 add def 0 0}bind]def +/psuedo{/i 0 def 0 exch 0 exch{exch routines exch get exec}forall pop pop str}bdf/bwi{pop pop image}bdf/di/bwi load def}ifelse +/cdb{/@7 save def/@1 xdf/@2 xdf/@3 xdf/@4 xdf/@5 xdf +systemdict/setcmykcolor known not{dc}if translate scale /@6 xdf +/@18 @5 dup 60000 ge{pop 60000}if string def @6 not{/str @18 0 @18 length 3 idiv getinterval def}if @4 @3 8 [@4 0 0 @3 0 0]@6{{currentfile @18 readhexstring pop}image} %AKT broke long line +{{currentfile @18 readhexstring pop psuedo}false 3 di}ifelse @7 restore}bdf +/wd 16 dict def +/mfont 14 dict def +/mdf{mfont wcheck not{/mfont 14 dict def}if mfont begin xdf end}bdf +/cf{{1 index/FID ne{def}{pop pop}ifelse}forall}bdf/rf{/@1 exch def/@2 exch def +FontDirectory @2 known{cleartomark pop}{findfont dup begin dup length @1 add dict begin +cf{/Encoding macvec def}{Encoding dup length array copy/Encoding exch def +counttomark 2 idiv{Encoding 3 1 roll put}repeat}ifelse +pop +exec currentdict end end @2 exch definefont pop}ifelse}bdf +/bmbc{exch begin wd begin +/cr xdf +save +CharTable cr 6 mul 6 getinterval{}forall +/bitheight xdf/bitwidth xdf +.96 div/width xdf +Gkernmax add/XOffset xdf Gdescent add/YOffset xdf/rowbytes xdf +rowbytes 255 eq{0 0 0 0 0 0 setcachedevice} +{Gnormsize dup scale +width 0 XOffset YOffset bitwidth XOffset add bitheight YOffset add +setcachedevice +rowbytes 0 ne{ +XOffset YOffset translate newpath 0 0 moveto +bitwidth bitheight scale +sn{ +/xSmt bitwidth x4 def +/ySmt bitheight x4 def +/rSmt xSmt rb def +rSmt x8 ySmt true +[xSmt 0 0 ySmt neg 0 ySmt] +{rSmt ySmt mul string CharData cr get +1 index bitwidth bitheight rowbytes rSmt tso smooth4} +}{rowbytes 3 bitshift bitheight 4 add true +[bitwidth 0 0 bitheight neg 0 bitheight 2 add] +{CharData cr get} +}ifelse +imagemask +}if +}ifelse +restore +end end +}bdf +/bb{.96 exch div/Gnormsize mdf 2 index +/Gkernmax mdf 1 index/Gdescent mdf +3 index div 4 1 roll +2 index div 1. 5 2 roll +exch div 4 1 roll +4 array astore/FontBBox mdf +}bdf +/cdf{mfont/CharData get 3 1 roll put}bdf +/bf{ +mfont begin +/FontType 3 def +/FontMatrix [1 0 0 1 0 0] def +/Encoding macvec def +/MFontType 0 def +/BuildChar/bmbc load def +end +mfont definefont pop +}bdf +/wi LW 1 eq{{gsave 0 0 0 0 0 0 0 0 moveto lineto lineto lineto closepath clip stringwidth grestore}bind}{/stringwidth load}ifelse def +/aps{0 get 124 eq}bdf +/xc{s75 cvs dup}bdf +/xp{put cvn}bdf +/scs{xc 3 67 put dup 0 95 xp}bdf +/sos{xc 3 79 xp}bdf +/sbs{xc 1 66 xp}bdf +/sis{xc 2 73 xp}bdf +/sob{xc 2 79 xp}bdf +/sss{xc 4 83 xp}bdf +/dd{exch 1 index add 3 1 roll add exch}bdf +/smc{moveto dup show}bdf +/ndf2{udf{dup /FontType get 0 eq{/FDepVector get{dup /FontType get 0 eq{ndf2}{dup /df2 known{begin df2 0 null put end +}{pop}ifelse}ifelse}forall}{/df2 known{dup begin df2 0 null put end}if}ifelse}{pop}ifelse}bdf +/kwn{FontDirectory 1 index known{findfont dup ndf2 exch pop}}bdf +/gl{1 currentgray sub setgray}bdf +/newmm{dup /FontType get 0 eq{dup maxlength dict begin{1 index/FID ne 2 index/UniqueID ne and{def}{pop pop}ifelse}forall currentdict end +dup /FDepVector 2 copy get[exch 6 index exch 6 index exch{newmm 3 1 roll}forall pop pop] put dup +}{/mfont 10 dict def mfont begin/FontMatrix [1 0 0 1 0 0] def +/FontType 3 def/Encoding macvec def/df 1 index def/df2 1 array def/FontBBox [0 0 1 1] def/StyleCode 2 index def +/mbc{bcarray StyleCode get}def/BuildChar{exch begin wd begin/cr exch def/cs s1 dup 0 cr put def df /MFontType known not{ +df2 0 get null eq{df dup length 2 add dict begin{1 index/FID ne 2 index/UniqueID ne and{def}{pop pop}ifelse}forall +/StrokeWidth nlw 1000 mul pys div ps div dup 12 lt{pop 12}if def/PaintType 2 def currentdict end +/q exch definefont df2 exch 0 exch put}if}if mbc exec end end}def end mfont}ifelse +3 index exch definefont exch pop}bdf +/mb{dup sbs kwn{0 2 index findfont newmm exch pop exch pop exch pop}ifelse sfd}bdf +/mo{dup sos kwn{2 2 index findfont newmm exch pop exch pop exch pop}ifelse sfd}bdf +/ms{dup sss kwn{4 2 index findfont newmm exch pop exch pop exch pop}ifelse sfd}bdf +/ou{dup sos kwn{mfont/df2 known{mfont begin df2 0 null put end}if 3 2 index findfont newmm exch pop exch pop exch pop}ifelse sfd}bdf +/su{dup sss kwn{mfont/df2 known{mfont begin df2 0 null put end}if 5 2 index findfont newmm exch pop exch pop exch pop}ifelse sfd}bdf +/ao{/fmv true def ou}bdf/as{/fmv true def su}bdf +/vo{/fmv false def ou}bdf/vs{/fmv false def su}bdf +/c{currentrgbcolor dup 4 1 roll eq 3 1 roll eq and/gray xdf}bdf +/bcarray[{/da .03 def df setfont gsave cs wi 1 index 0 ne{exch da add exch}if grestore setcharwidth +cs 0 0 smc da 0 smc da da smc 0 da moveto show}bind dup{/da 1 ps div def df setfont gsave cs wi 1 index 0 ne{exch da add exch}if grestore setcharwidth +cs 0 0 smc da 0 smc da da smc 0 da smc c gray{gl}{1 setgray}ifelse da 2. div dup moveto show}bind +{df setfont gsave cs wi grestore setcharwidth c gray{gl}{currentrgbcolor 1 setgray}ifelse cs 0 0 smc df2 0 get setfont +gray{gl}{4 1 roll setrgbcolor}ifelse 0 0 moveto show}bind +{/da 1 ps div def/ds .05 def/da2 da 2. div def df setfont gsave cs wi 1 index 0 ne{exch ds add da2 add exch}if grestore setcharwidth +cs ds da2 add .01 add 0 smc 0 ds da2 sub translate 0 0 smc da 0 smc da da smc 0 da smc c gray{gl}{1 setgray}ifelse da 2. div dup moveto show}bind +{/da .05 def df setfont gsave cs wi 1 index 0 ne{exch da add exch}if grestore setcharwidth c cs da .01 add 0 smc 0 da translate +gray{gl}{currentrgbcolor 1 setgray 4 -1 roll}ifelse 0 0 smc gray{gl}{4 1 roll setrgbcolor}ifelse df2 0 get setfont 0 0 moveto show}bind]def +/st{1000 mul usertime add dup 2147483647 gt{2147483647 sub}if def}bdf +/the{usertime sub dup 0 lt exch -2147483648 gt and}bdf +/6a 6 array def +/2a 2 array def +/3q 3 array def +/qs{3 -1 roll sub exch 3 -1 roll sub exch}bdf +/qa{3 -1 roll add exch 3 -1 roll add exch}bdf +/qm{3 -1 roll 1 index mul 3 1 roll mul}bdf +/qn{6a exch get mul}bdf +/qA .166667 def/qB .833333 def/qC .5 def +/qx{6a astore pop +qA 0 qn qB 2 qn add qA 1 qn qB 3 qn add +qB 2 qn qA 4 qn add qB 3 qn qA 5 qn add +qC 2 qn qC 4 qn add qC 3 qn qC 5 qn add}bdf +/qp{6 copy 12 -2 roll pop pop}bdf +/qc{exch qp qx curveto}bdf +/qi{{exch 4 copy 2a astore aload pop qa .5 qm newpath moveto}{exch 2 copy 6 -2 roll 2 qm qs 4 2 roll}ifelse}bdf +/qq{{qc 2a aload pop qx curveto}{exch 4 copy qs qa qx curveto}ifelse}bdf +/pt{currentpoint newpath moveto}bdf +/qf{/fillflag true def}bdf +/ec{dup 4 and 0 ne{closepath}if 1 and 0 ne{0 doop}if grestore currentpoint newpath moveto/fillflag false def}bdf +/eu{currentpoint fp{0 ep}{grestore newpath}ifelse moveto/fillflag false def}bdf +/bp{currentpoint newpath 2 copy moveto}bdf +/ef{gsave fillflag{gsave eofill grestore}if}bdf +/sm{0 exch{@1 eq{1 add}if}forall}bdf +/lshow{4 1 roll exch/@1 exch def{1 index wi pop sub 1 index sm dv 0 @1 4 -1 roll widthshow}{1 index wi pop sub +1 index dup sm 10 mul exch length 1 sub add dv dup 10. mul 0 @1 4 -1 roll 0 6 -1 roll awidthshow}ifelse}bdf +/setTxMode{sa 9 2 index put exch not{3 eq{1}{0}ifelse setgray}{pop}ifelse}bdf +/SwToSym{{}mark false/Symbol/|______Symbol 0 rf 0 sa 6 get 0 ne{pop 1}{sa 7 get 0 eq{pop 2}if}ifelse +sa 1 get 0 ne/|______Symbol +sa 4 get 0 ne{vs}{sa 3 get 0 ne{vo}{fnt}ifelse}ifelse}bdf +/mc{0 3 1 roll transform neg exch pop}bdf +/ul{dup 0 ne sa 2 get 0 ne and{gsave 0 0 +/UnderlinePosition kif{mc}{ps -10 div}ifelse/UnderlineThickness kif{mc}{ps 15 div}ifelse +abs setlinewidth neg rmoveto +sa 4 get 0 ne{gsave currentlinewidth 2. div dup rmoveto currentpoint newpath moveto +2 copy rlineto stroke grestore}if +sa 3 get sa 4 get or 0 ne{gsave currentrgbcolor dup 4 1 roll eq 3 1 roll eq and{gl}{1 setgray}ifelse 2 copy rlineto stroke grestore rlineto strokepath nlw pys div setlinewidth}{rlineto}ifelse +stroke grestore}{pop}ifelse}bdf +/sgt{2 copy known{get true}{pop pop false}ifelse}bdf +/kif{currentfont dup/FontMatrix get exch/FontInfo sgt{true}{currentfont/df sgt +{dup/FontInfo sgt{3 1 roll/FontMatrix get mtx concatmatrix exch true}{pop pop pop false} +ifelse}{pop pop false}ifelse}ifelse{3 -1 roll sgt{exch true}{pop false}ifelse}{false}ifelse}bdf +/blank/Times-Roman findfont/CharStrings get/space get def +/macvec 256 array def +/NUL/SOH/STX/ETX/EOT/ENQ/ACK/BEL/BS/HT/LF/VT/FF/CR/SO/SI +/DLE/DC1/DC2/DC3/DC4/NAK/SYN/ETB/CAN/EM/SUB/ESC/FS/GS/RS/US +macvec 0 32 getinterval astore pop +macvec 32/Times-Roman findfont/Encoding get +32 96 getinterval putinterval macvec dup 39/quotesingle put 96/grave put +/Adieresis/Aring/Ccedilla/Eacute/Ntilde/Odieresis/Udieresis/aacute +/agrave/acircumflex/adieresis/atilde/aring/ccedilla/eacute/egrave +/ecircumflex/edieresis/iacute/igrave/icircumflex/idieresis/ntilde/oacute +/ograve/ocircumflex/odieresis/otilde/uacute/ugrave/ucircumflex/udieresis +/dagger/degree/cent/sterling/section/bullet/paragraph/germandbls +/registered/copyright/trademark/acute/dieresis/notequal/AE/Oslash +/infinity/plusminus/lessequal/greaterequal/yen/mu/partialdiff/summation +/product/pi/integral/ordfeminine/ordmasculine/Omega/ae/oslash +/questiondown/exclamdown/logicalnot/radical/florin/approxequal/Delta/guillemotleft +/guillemotright/ellipsis/blank/Agrave/Atilde/Otilde/OE/oe +/endash/emdash/quotedblleft/quotedblright/quoteleft/quoteright/divide/lozenge +/ydieresis/Ydieresis/fraction/currency/guilsinglleft/guilsinglright/fi/fl +/daggerdbl/periodcentered/quotesinglbase/quotedblbase/perthousand/Acircumflex/Ecircumflex/Aacute +/Edieresis/Egrave/Iacute/Icircumflex/Idieresis/Igrave/Oacute/Ocircumflex +/apple/Ograve/Uacute/Ucircumflex/Ugrave/dotlessi/circumflex/tilde +/macron/breve/dotaccent/ring/cedilla/hungarumlaut/ogonek/caron +macvec 128 128 getinterval astore pop +{}mark true/Courier/|______Courier 0 rf +{/Metrics 21 dict begin/zero 600 def/one 600 def/two 600 def/three 600 def/four 600 def/five 600 def/six 600 def/seven 600 def/eight 600 def +/nine 600 def/comma 600 def/period 600 def/dollar 600 def/numbersign 600 def/percent 600 def/plus 600 def/hyphen 600 def/E 600 def/parenleft 600 def/parenright 600 def/space 600 def +currentdict end def currentdict/UniqueID known{/UniqueID 16#800000 def}if/FontBBox FontBBox 4 array astore def}mark true/Helvetica/|______Seattle 1 rf +/oldsettransfer/settransfer load def +/concatprocs{/proc2 exch cvlit def/proc1 exch cvlit def/newproc proc1 length proc2 length add array def +newproc 0 proc1 putinterval newproc proc1 length proc2 putinterval newproc cvx}def +/settransfer{currenttransfer concatprocs oldsettransfer}def +/PaintBlack{{1 exch sub}settransfer gsave newpath clippath 1 setgray fill grestore}def +/od{ + +%AKT replace this line: (Rvd\001\001\000\000\177) fg copy pop txpose +1 -1 scale %AKT with this + +1 0 mtx defaultmatrix dtransform exch atan/pa exch def +newpath clippath mark +{transform{itransform moveto}}{transform{itransform lineto}} +{6 -2 roll transform 6 -2 roll transform 6 -2 roll transform +{itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll curveto}} +{{closepath}}pathforall newpath counttomark array astore/gc xdf pop ct 39 0 put +10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack}if +statusdict/processcolors known{statusdict begin processcolors end dup 4 eq +{/4colors true def pop}{3 eq{/3colors true def}{/2color true def}ifelse}ifelse} +{/2colors true def}ifelse}bdf +/cd{}bdf +/op{/sfl false def systemdict/currentcolorscreen known{dcfreq dcrot/dcspf load +dmfreq dmrot/dmspf load dyfreq dyrot/dyspf load +dkfreq dkrot/dkspf load setcolorscreen}{freq rot/spf load setscreen}ifelse savescreen +/ns false def/pm save def}bdf +/cp{not{userdict/#copies 0 put}if ma 0 gt +{{t1 the{exit}if}loop}if{copypage}{showpage}ifelse pm restore}def %AKT was }bdf +/px{0 3 1 roll tp tt}bdf +/psb{/us save def}bdf +/pse{us restore}bdf +/ct 40 string def +/nc{currentpoint initclip newpath gc{dup type dup/arraytype eq exch/packedarraytype eq or{exec}if} +forall clip newpath moveto}def +/kp{ct 0 2 index length 2 index 39 2 index put getinterval copy cvx exec mx3 currentmatrix pop}bdf +/av 70 def +end +LW 1 eq userdict/a4small known not and{/a4small +[[300 72 div 0 0 -300 72 div -120 3381] +280 3255 +{statusdict/jobstate (printing) put 0 setblink +margins +exch 196 add exch 304 add 8 div round cvi frametoroket +statusdict/jobstate (busy) put +1 setblink} +/framedevice load +60 45{dup mul exch dup mul add 1.0 exch sub}/setscreen load +{}/settransfer load/initgraphics load/erasepage load]cvx +statusdict begin bind end readonly def}if +md begin/bigs[lnop userdict/letter known{/letter load}{lnop}ifelse userdict/legal known{/legal load}{lnop}ifelse userdict/a4 known{/a4 load}{lnop}ifelse userdict/b5 known{/b5 load}{lnop}ifelse +lnop lnop lnop /tab load/a3Size load]def +/smalls[lnop userdict/lettersmall known{/lettersmall load}{userdict/note known{/note load}{lnop}ifelse}ifelse +userdict/legal known{/legal load}{lnop}ifelse userdict/a4small known{/a4small load}{lnop}ifelse +userdict/b5 known{/b5 load}{userdict/note known{/note load}{lnop}ifelse}ifelse lnop lnop lnop /tab load/a3Size load]def end +systemdict/currentpacking known{setpacking}if + +%AKT /checkload{{currentfile eexec} {/junk save def/mystring 65000 string def +%AKT /endexec (%endeexec) def{currentfile mystring readline not{stop}if endexec eq{exit}if}loop junk restore}ifelse}bind def +%AKT ok userdict/stretch known not and checkload +%AKT ... +%AKT (removed long lines of hex data) +%AKT ... +%AKT cleartomark +%AKT ok userdict/smooth4 known not and checkload +%AKT ... +%AKT (removed long lines of hex data) +%AKT ... +%AKT cleartomark + +%%EndProcSet + +%%EOF diff --git a/dviware/psprint/vms/lines.dat b/dviware/psprint/vms/lines.dat new file mode 100644 index 0000000000..d358a72637 --- /dev/null +++ b/dviware/psprint/vms/lines.dat @@ -0,0 +1,66 @@ +1 This text file has 66 lines, one of which is 132 characters wide. +2 +3 +123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012 +5 +6 +7 +8 +9 +10 +1 +2 +3 +4 +5 +6 +7 +8 +9 +20 +1 +2 +3 +4 +5 +6 +7 +8 +9 +30 +1 +2 +3 +4 +5 +6 +7 +8 +9 +40 +1 +2 +3 +4 +5 +6 +7 +8 +9 +50 +1 +2 +3 +4 +5 +6 +7 +8 +9 +60 +1 +2 +3 +4 +5 +6 diff --git a/dviware/psprint/vms/lino_fonts.ps b/dviware/psprint/vms/lino_fonts.ps new file mode 100644 index 0000000000..e0c18a2fcc --- /dev/null +++ b/dviware/psprint/vms/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/vms/lino_header.ps b/dviware/psprint/vms/lino_header.ps new file mode 100644 index 0000000000..0ef14bdeb4 --- /dev/null +++ b/dviware/psprint/vms/lino_header.ps @@ -0,0 +1,267 @@ +% 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 +{ 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 + 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 + +% margin is offset (in pts) from paper edge. +% LINO_PRINT.COM 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 + +% LINO_PRINT.COM will override this default if user asks for /NOCUTMARKS: + +/@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/vms/lino_pages.ps b/dviware/psprint/vms/lino_pages.ps new file mode 100644 index 0000000000..f9af8a3913 --- /dev/null +++ b/dviware/psprint/vms/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/vms/lino_print.com b/dviware/psprint/vms/lino_print.com new file mode 100644 index 0000000000..9e5219280e --- /dev/null +++ b/dviware/psprint/vms/lino_print.com @@ -0,0 +1,153 @@ +$! This command file is run by PSPRINT/DEV=LINO with the following parameters: +$! P1 = complete file specification +$! P2 = file format (DVI or PS or TEXT or TWO or WIDE) +$! P3 = options for PSDVI +$! P4 = options for PRINT +$! P5 = /NOTE value ("" if not used) +$! P6 = /COPIES value (1 if not used) +$! P7 = /OUTPUT value ("" if not used) +$! P8 = "bbbbbsss<prep>" where b = Y or N and represents the status of the +$! boolean qualifiers /DELETE, /LANDSCAPE, /CUTMARKS, /LOWRES, /BANNER +$! and sss = /SIZE value (one of those defined in PSPRINT.CLD) +$! and <prep> is the /PREP value, possibly empty +$ +$ on control_y then exit +$ set symbol/scope=(nolocal,noglobal) ! avoid symbol collision +$ +$! Don't allow text files to be printed on Linotronic: +$ if (p2 .eqs. "DVI") .or. (p2 .eqs. "PS") then goto CONT0 +$ write sys$output "Linotronic should not be used to print text files." +$ exit +$ +$ CONT0: +$ delflag = f$extract(0,1,p8) ! Y or N +$ landflag = f$extract(1,1,p8) ! Y or N +$ cutflag = f$extract(2,1,p8) ! Y or N +$ lowflag = f$extract(3,1,p8) ! Y or N +$ bannerflag = f$extract(4,1,p8) ! Y or N +$ size = f$extract(5,3,p8) ! /SIZE value +$ prepfile = f$extract(8,999,p8) ! /PREP value +$ pagesetup = "" +$ if size .eqs. "A3L" then pagesetup = "A3Lsetup" ! defined in lino_header.ps +$ if size .eqs. "A4P" then pagesetup = "A4Psetup" ! ditto +$ if size .eqs. "A4L" then pagesetup = "A4Lsetup" ! ditto +$ if size .eqs. "A5P" then pagesetup = "A5Psetup" ! ditto +$ if size .eqs. "A5L" then pagesetup = "A5Lsetup" ! ditto +$ if size .eqs. "B5P" then pagesetup = "B5Psetup" ! ditto +$ if size .eqs. "B5L" then pagesetup = "B5Lsetup" ! ditto +$ if pagesetup .nes. "" then goto CONT1 +$! CLD file should prevent us ever getting here: +$ write sys$output "Unknown /SIZE value: " + size +$ exit +$ +$ CONT1: +$ if (p6 .gt. 0) .and. (p6 .lt. 101) then goto CONT2 +$ write sys$output "Bad /COPIES value. Specify 1 to 100." +$ exit +$ +$ CONT2: +$ copies = f$string(p6) +$ job = f$parse(p1,,,"NAME") +$ +$ copy tex_ps:empty.ps sys$scratch:'job'.tmp +$ tmpfile = f$search("sys$scratch:''job'.tmp") +$ write sys$output - + "Creating SYS$SCRATCH:''job'.TMP" + f$parse(tmpfile,,,"VERSION") +$ open/append tmp 'tmpfile' +$ write tmp "/@USER (" + f$getjpi(0,"USERNAME") - + + " " + f$trnlnm("SYS$NODE") + p1 + ") def" +$ write tmp "/@DATE (" + f$time() + ") def" +$ write tmp "/@NOTE (" + p5 + ") def" +$ close tmp +$ append tex_ps:lino_header.ps 'tmpfile' ! uses above definitions +$ +$ open/append tmp 'tmpfile' +$ write tmp "/dev (LINO) def" +$ res = "1270" +$ if lowflag .eqs. "Y" then res = "635" ! res also used below +$ write tmp "/res " + res + " def" +$ write tmp "/fspec (" + p1 + ") def" +$ if landflag .eqs. "Y" then write tmp "/land true def" +$ if landflag .eqs. "N" then write tmp "/land false def" +$ if bannerflag .eqs. "N" then write tmp "/@bannerpage { } def" +$ if bannerflag .eqs. "N" then write tmp "/@footerpage { } def" +$ write tmp "@bannerpage" +$ write tmp "/@oldpagecount statusdict begin pagecount end def" +$ write tmp "/#copies " + copies + " def" ! set # of copies +$ write tmp pagesetup ! call page setup procedure +$ if cutflag .eqs. "N" then - + write tmp "/@cutmarks { } def" ! override default +$ close tmp +$ +$ if p2 .eqs. "DVI" then append tex_ps:tex.ps, tex_ps:lino_fonts.ps 'tmpfile' +$ if p2 .eqs. "PS" then append tex_ps:ps.ps 'tmpfile' +$ +$ if prepfile .eqs. "" then goto SKIPPREP +$ write sys$output "Including " + prepfile +$ append 'prepfile' 'tmpfile' +$ SKIPPREP: +$ +$ global = f$search("global.ps") +$ if (global .eqs. "") .or. (p2 .nes. "DVI") then goto SKIPGLOBAL +$ write sys$output "Including GLOBAL.PS" +$ append 'global' 'tmpfile' +$ SKIPGLOBAL: +$ +$ if p2 .nes. "DVI" then goto PRINT ! skip DVI processing +$ +$ ver = 1 +$ LOOP: +$ psdvifile = "sys$scratch:psdvi.tmp;''f$string(ver)'" +$ if f$search(psdvifile) .eqs. "" then goto ENDLOOP +$ ver = ver + 1 +$ goto LOOP +$ +$ ENDLOOP: +$ if size .eqs. "A3L" then land = "/x=297mm/y=420mm" +$ if size .eqs. "A4P" then land = "/x=210mm/y=297mm" +$ if size .eqs. "A4L" then land = "/x=210mm/y=297mm" +$ if size .eqs. "A5P" then land = "/x=148mm/y=210mm" +$ if size .eqs. "A5L" then land = "/x=148mm/y=210mm" +$ if size .eqs. "B5P" then land = "/x=176mm/y=250mm" +$ if size .eqs. "B5L" then land = "/x=176mm/y=250mm" +$! offset: 012345678901 +$! If /LANDSCAPE given then we have to swap /xsize and /ysize values. +$! Following stmt assumes /x value starts at offset 3 and /y value at offset 11. +$ if landflag .eqs. "Y" then - + land = "/x=" + f$extract(11,5,land) + "/y=" + f$extract(3,5,land) +$ on warning then goto BADDVI +$ PSDVI 'p1' 'land' /HEADER='tmpfile' - + /OUTPUT='psdvifile' - + /RES='res' - + /FONT=disk$utils:[utilities.tex.'res'pk] - + /DUMMY=cmr10.'res'pk - + /CONSERVE - + /NOREVERSE 'p3' +$ delete/nolog 'tmpfile' +$ rename/nolog 'psdvifile' 'tmpfile' +$ goto PRINT +$ +$ BADDVI: +$ delete/nolog 'tmpfile' +$ if f$search(psdvifile) .nes. "" then delete/nolog 'psdvifile' +$ write sys$output "" +$ write sys$output "Printing aborted due to error(s). Temporary file deleted." +$ exit +$ +$ PRINT: +$ on error then exit +$ if p2 .eqs. "PS" then append 'p1' 'tmpfile' +$ ctrld = "tex_ps:ctrld.dat" +$ if p7 .nes. "" then ctrld = "tex_ps:empty.ps" +$ append tex_ps:lino_trailer.ps, 'ctrld' 'tmpfile' +$ +$ if p7 .eqs. "" then goto PRINTJOB +$ copy tex_ps:empty.ps, 'tmpfile' 'p7' +$ delete/log 'tmpfile' +$ write sys$output "" +$ write sys$output "Nothing printed. PostScript saved in " + p7 +$ exit +$ +$ PRINTJOB: +$ print/queue=LINOTRONICS/form=postscript/name='job' 'tmpfile'/delete 'p4' +$ if delflag .eqs. "Y" then delete/log 'p1' diff --git a/dviware/psprint/vms/lino_trailer.ps b/dviware/psprint/vms/lino_trailer.ps new file mode 100644 index 0000000000..26534f7984 --- /dev/null +++ b/dviware/psprint/vms/lino_trailer.ps @@ -0,0 +1 @@ +@footerpage % print footer page at end of Linotronic job diff --git a/dviware/psprint/vms/lw_fonts.ps b/dviware/psprint/vms/lw_fonts.ps new file mode 100644 index 0000000000..56589c8cd0 --- /dev/null +++ b/dviware/psprint/vms/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/vms/lw_header.ps b/dviware/psprint/vms/lw_header.ps new file mode 100644 index 0000000000..66da648430 --- /dev/null +++ b/dviware/psprint/vms/lw_header.ps @@ -0,0 +1,138 @@ +% LW_PRINT.COM 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.1 **********************) show newline + @USER show newline + @ACCOUNT show newline + @JOB 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 500 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/vms/lw_print.com b/dviware/psprint/vms/lw_print.com new file mode 100644 index 0000000000..fc07e54199 --- /dev/null +++ b/dviware/psprint/vms/lw_print.com @@ -0,0 +1,178 @@ +$! This command file is run by PSPRINT/DEV=LW with the following parameters: +$! P1 = complete file specification +$! P2 = file format (DVI or PS or TEXT or TWO or WIDE) +$! P3 = options for PSDVI +$! P4 = options for PRINT +$! P5 = /NOTE value ("" if not used) +$! P6 = /COPIES value (1 if not used) +$! P7 = /OUTPUT value ("" if not used) +$! P8 = "bbbb<prep>" where b = Y or N and represents the status of the +$! boolean qualifiers /DELETE, /LANDSCAPE, /BANNER, /MANUALFEED +$! and <prep> is the /PREP value, possibly empty +$ +$ on control_y then exit +$ set symbol/scope=(nolocal,noglobal) ! avoid symbol collision +$ delflag = f$extract(0,1,p8) ! Y or N +$ landflag = f$extract(1,1,p8) ! Y or N +$ bannerflag = f$extract(2,1,p8) ! Y or N +$ manualflag = f$extract(3,1,p8) ! Y or N +$ prepfile = f$extract(4,999,p8) ! /PREP value +$ +$! We arbitrarily restrict /COPIES to <= 100. Other sites might want to +$! increase this limit or restrict it even further: +$ +$ if (p6 .gt. 0) .and. (p6 .lt. 101) then goto CONTINUE +$ write sys$output "Bad /COPIES value. Specify 1 to 100." +$ exit +$ +$ CONTINUE: +$ copies = f$string(p6) +$ job = f$parse(p1,,,"NAME") +$ +$! Build temporary file in sys$scratch. +$! We no longer start with ^D because of problems encountered when +$! a LaserWriter is connected to an X25 pad (due to echoing of ^D). +$! We now assume that any previous job has been terminated. +$! (The LaserWriter server uses ^D to end a job and restore virtual memory.) +$ +$ copy tex_ps:lw_header.ps sys$scratch:'job'.tmp +$ tmpfile = f$search("sys$scratch:''job'.tmp") ! include version number +$ write sys$output - + "Creating SYS$SCRATCH:''job'.TMP" + f$parse(tmpfile,,,"VERSION") +$ +$! tex_ps:lw_header.ps defines @bannerpage and a PostScript error handler. +$! It also stores the current LaserWriter page count; when @bannerpage +$! is finally called we can work out how many pages were printed. +$! Now append various strings that will eventually appear on banner page: +$ +$ open/append tmp 'tmpfile' +$ write tmp "/@USER (USER : " + f$getjpi(0,"USERNAME") + ") def" +$ write tmp "/@ACCOUNT (ACCOUNT : " + f$getjpi(0,"ACCOUNT") + ") def" +$ write tmp "/@JOB (JOB : " + job + ") def" +$ write tmp "/@NODE (NODE : " + f$trnlnm("SYS$NODE")-"::" + ") def" +$ write tmp "/@FILE (FILE : " + p1 + ") def" +$ write tmp "/@FORMAT (FORMAT : " + p2 + ") def" +$ write tmp "/@QUEUED (QUEUED : " + f$time() + ") def" +$ +$! Note that PSPRINT.MOD has prefixed each (,),\ in p5 with \. +$! Such characters should never occur in the above strings!!! +$ +$ write tmp "/@NOTE (NOTE : " + p5 + ") def" +$ +$! The value of #copies will be used by PostScript's showpage operator to +$! print multiple copies of each page. +$! This is very efficient but means that copies are not collated. +$! (Good; we don't want the LaserWriter to be treated like a copier.) +$ +$ write tmp "/#copies " + copies + " def" +$ +$! Check for /NOBANNER and /MANUALFEED: +$ +$ if bannerflag .eqs. "N" then write tmp "/@bannerpage { } def" +$ if manualflag .eqs. "Y" then write tmp - + "statusdict begin /manualfeed true def end" +$ +$! Here are the definitions used in the job prologues: +$ +$ write tmp "/dev (LW) def" +$ write tmp "/res 300 def" +$ write tmp "/fspec (" + p1 + ") def" +$ if landflag .eqs. "Y" then write tmp "/land true def" +$ if landflag .eqs. "N" then write tmp "/land false def" +$ +$ close tmp +$ +$! Each type of job requires its own prologue: +$ +$ if p2 .eqs. "DVI" then append tex_ps:tex.ps, tex_ps:lw_fonts.ps 'tmpfile' +$ if p2 .eqs. "PS" then append tex_ps:ps.ps 'tmpfile' +$ if p2 .eqs. "TEXT" then append tex_ps:text.ps 'tmpfile' +$ if p2 .eqs. "TWO" then append tex_ps:two.ps 'tmpfile' +$ if p2 .eqs. "WIDE" then append tex_ps:wide.ps 'tmpfile' +$ +$! /PREP qualifier is only allowed for DVI or PS job: +$ +$ if (p2 .nes. "DVI") .and. (p2 .nes. "PS") then goto SKIPPREP +$ if prepfile .eqs. "" then goto SKIPPREP +$ write sys$output "Including " + prepfile +$ append 'prepfile' 'tmpfile' +$ SKIPPREP: +$ +$! If global.ps exists in the user's current directory then append it +$! to the prologue for a DVI job: +$ +$ global = f$search("global.ps") +$ if (global .eqs. "") .or. (p2 .nes. "DVI") then goto SKIPGLOBAL +$ write sys$output "Including GLOBAL.PS" +$ append 'global' 'tmpfile' +$ SKIPGLOBAL: +$ +$ if p2 .nes. "DVI" then goto PRINT ! skip PSDVI if non-DVI file +$ +$! Else run PSDVI. +$! psdvifile must be a completely new file spec to avoid file name conflicts: +$ +$ ver = 1 +$ LOOP: +$ psdvifile = "sys$scratch:psdvi.tmp;''f$string(ver)'" +$ if f$search(psdvifile) .eqs. "" then goto ENDLOOP +$ ver = ver + 1 +$ goto LOOP +$ +$ ENDLOOP: ! psdvifile does not exist +$ land = "" +$ if landflag .eqs. "Y" then land = "/xsize=297mm /ysize=210mm" ! rotated A4 +$ on warning then goto BADDVI +$ PSDVI 'p1' 'land' /HEADER='tmpfile' - + /OUTPUT='psdvifile' - + /RES=300 - + /FONT="disk$utils:[utilities.tex.300pk]" - + /DUMMY="cmr10.300pk" - + /NOCONSERVE - + /NOREVERSE 'p3' ! p3 may override above defaults +$ delete/nolog 'tmpfile' +$ rename/nolog 'psdvifile' 'tmpfile' +$ goto PRINT ! output file is okay +$ +$! We decide not to print anything if the DVI file has errors. +$! Sites that don't care about wasting paper may wish to do something else. +$ +$ BADDVI: +$ delete/nolog 'tmpfile' ! delete header +$ if f$search(psdvifile) .nes. "" then - ! delete bad output file +$ delete/nolog 'psdvifile' +$ write sys$output "" +$ write sys$output "Printing aborted due to error(s). Temporary file deleted." +$ exit +$ +$ PRINT: +$ on error then exit +$ +$! Now complete tmpfile. +$! For TEXT/TWO/WIDE jobs we must end with ^D. +$! For DVI/PS jobs we must end with tex_ps:lw_trailer.ps before ^D. +$! But if /OUTPUT is used we don't append ^D. +$ +$ ctrld = "tex_ps:ctrld.dat" +$ if p7 .nes. "" then ctrld = "tex_ps:empty.ps" +$ +$ if (p2 .eqs. "TEXT") .or. (p2 .eqs. "TWO") .or. (p2 .eqs. "WIDE") then - + append 'p1', 'ctrld' 'tmpfile' +$ if p2 .eqs. "PS" then - + append 'p1', tex_ps:lw_trailer.ps, 'ctrld' 'tmpfile' +$ if p2 .eqs. "DVI" then - + append tex_ps:lw_trailer.ps, 'ctrld' 'tmpfile' +$ +$! If /OUTPUT given then rename tmpfile instead of sending it to printer. +$! Use copy & delete rather than rename since tmpfile may be on another disk: +$ +$ if p7 .eqs. "" then goto PRINTJOB ! /OUTPUT not used +$ copy tex_ps:empty.ps, 'tmpfile' 'p7' ! empty.ps avoids version conflict +$ delete/log 'tmpfile' +$ write sys$output "" +$ write sys$output "Nothing printed. PostScript saved in " + p7 +$ exit +$ +$ PRINTJOB: +$ print/queue=APPLE/form=postscript/name='job' 'tmpfile'/delete 'p4' +$ if delflag .eqs. "Y" then delete/log 'p1' diff --git a/dviware/psprint/vms/lw_trailer.ps b/dviware/psprint/vms/lw_trailer.ps new file mode 100644 index 0000000000..6ab5dcd5e2 --- /dev/null +++ b/dviware/psprint/vms/lw_trailer.ps @@ -0,0 +1 @@ +@bannerpage diff --git a/dviware/psprint/vms/nasty.tex b/dviware/psprint/vms/nasty.tex new file mode 100644 index 0000000000..bd13f4ad93 --- /dev/null +++ b/dviware/psprint/vms/nasty.tex @@ -0,0 +1,352 @@ +% 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 [-.dvitovdu]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% +12345678901234567890123456789012345678901234567890% +12345678901234567890123456789012345678901234567890% +12345678901234567890123456789012345678901234567890% +12345678901234567890123456789012345678901234567890% +1234567} % one character too many (see specialstring in PSWRITER.DEF) +\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 and TEXLAND.PS try 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/vms/options.def b/dviware/psprint/vms/options.def new file mode 100644 index 0000000000..349158f7e0 --- /dev/null +++ b/dviware/psprint/vms/options.def @@ -0,0 +1,64 @@ +DEFINITION MODULE Options; + +(* Author: Andrew Trevorrow + Implementation: University of Hamburg Modula-2 under VAX/VMS version 4 + Date Started: August, 1986 + + Description: + Exports the DVI file name and qualifier values given in the PSDVI command + line. Syntax checking is done by DCL according to PSDVI.CLD. + + Revised: + November, 1987 (while at The Open University) + - Added tfmdir qualifier that indicates the default location of TFM files. + This allows PSDVI to handle resident PostScript fonts. + - Added conserveVM qualifier which tells PSDVI to conserve PostScript's + "virtual memory" at the expense of downloading character bitmaps more often. + + June--August, 1988 (while at Aston University) + - Added psprefix qualifier that specifies the prefix in TFM file names + for resident PostScript fonts. + - Added increment qualifier that allows user to choose every ith page from + (and including) the first page selected for printing. Users can easily + select all odd pages or all even pages (for duplex printing). + - Added hoffset and voffset qualifiers to allow shifting of page. +*) + +TYPE + validunits = (in,cm,mm,pc,pt,bp,px); + stringvalue = ARRAY [0..127] OF CHAR; + +VAR + units (* /UNITS value defines how dimensions will be displayed *) + : validunits; + conserveVM, (* /CONSERVE_VM indicates to conserve virtual memory *) + stats, (* /STATS indicates to show some statistics *) + reverse, (* /REVERSE indicates to output pages in reverse order *) + subrange (* /PAGES has been used to select a subrange *) + : BOOLEAN; + firstDVIpage, (* first DVI page number given to /PAGES (0 if TeX page) *) + finalDVIpage, (* final DVI page number given to /PAGES (0 if TeX page) *) + increment, (* /INCREMENT value further restricts page selection *) + resolution, (* /RESOLUTION value defines pixels per inch *) + mag, (* /MAGNIFICATION value replaces DVI mag; 0 = use DVI mag *) + paperwd, (* /XSIZE value defines paper width; converted to pixels *) + paperht (* /YSIZE value defines paper height; converted to pixels *) + : CARDINAL; + hoffset, (* /HOFFSET value is horizontal shift in pixels *) + voffset (* /VOFFSET value is vertical shift in pixels *) + : INTEGER; + firstTeXpage, (* first TeX page specification given to /PAGES *) + finalTeXpage, (* final TeX page specification given to /PAGES *) + psprefix, (* /PSPREFIX value defines TFM files for PostScript fonts *) + tfmdir, (* /TFM_DIRECTORY value defines location of TFM files *) + fontdir, (* /FONT_DIRECTORY value defines location of font files *) + dummyfont, (* /DUMMY_FONT value defines dummy font file *) + header, (* /HEADER value defines header file prefixed to output *) + PSname, (* /OUTPUT value gives expicit name to PostScript output *) + DVIname (* DVI file specification *) + : stringvalue; + +PROCEDURE Cap (ch : CHAR) : CHAR; +(* If ch is in 'a'..'z' then return capitalized version, else return ch. *) + +END Options. diff --git a/dviware/psprint/vms/options.mod b/dviware/psprint/vms/options.mod new file mode 100644 index 0000000000..b5e0bfad23 --- /dev/null +++ b/dviware/psprint/vms/options.mod @@ -0,0 +1,499 @@ +IMPLEMENTATION MODULE Options; + +(* Author: Andrew Trevorrow + Implementation: University of Hamburg Modula-2 under VAX/VMS version 4 + Date Started: August, 1986 + + Description: + This module uses CLI routines to extract the DVI file parameter + and qualifier values from the PSDVI command line. + + Revised: + November, 1987 (while at The Open University) + - Added /TFM_DIRECTORY and /CONSERVE_VM qualifiers. + + June--August, 1988 (while at Aston University) + - Added /PSPREFIX, /INCREMENT, /HOFFSET and /VOFFSET qualifiers. +*) + +FROM CommandLanguageInterface IMPORT + CLI$PRESENT, + CLI$GET_VALUE; + +FROM Conversions IMPORT + StringToCard, StringToReal, Done; + +FROM TermOut IMPORT + Write, WriteString, WriteLn, Halt; + +CONST + NULL = 0C; (* SYSDEP: terminates a string *) + +VAR + value : stringvalue; (* temporary string *) + +(******************************************************************************) + +PROCEDURE GetDVIFile; + +(* Get DVI file name from command line. *) + +VAR i, status : CARDINAL; + +BEGIN +DVIname := ''; +status := CLI$GET_VALUE('FILESPEC',DVIname); (* CLD ensures it is there *) +i := HIGH(DVIname); +WHILE (i > 0) AND (DVIname[i] = ' ') DO (* remove trailing blanks *) + DVIname[i] := NULL; (* SYSDEP: pad with NULLs *) + DEC(i); +END; +IF DVIname[i] = ':' THEN (* assume logical name *) + (* no need to translate *) +ELSE + INC(i); (* = LEN(DVIname) *) + IF NOT ExplicitExt(DVIname) THEN (* append .DVI *) + IF i + 3 <= HIGH(DVIname) THEN + DVIname[i] := '.'; + DVIname[i+1] := 'D'; + DVIname[i+2] := 'V'; + DVIname[i+3] := 'I'; + ELSE (* user has given a mighty long file spec! *) + WriteString('DVI file specification is too long!'); WriteLn; + WriteString(DVIname); WriteLn; + Halt(2); + END; + END; +END; +(* bad DVIname will be detected upon open in main module *) +END GetDVIFile; + +(******************************************************************************) + +PROCEDURE ExplicitExt (fname : ARRAY OF CHAR) : BOOLEAN; + +(* SYSDEP: VAX/VMS files have an extension of the form ".xxx", also known as + the file type. If given file specification contains an extension then + TRUE is returned, otherwise FALSE. +*) + +VAR pos : CARDINAL; ch : CHAR; + +BEGIN +pos := LEN(fname); +WHILE pos > 0 DO (* search backwards looking for . or : or ] *) + DEC(pos); + ch := fname[pos]; + IF ch = '.' THEN + RETURN TRUE + ELSIF (ch = ':') OR (ch = ']') THEN (* don't need to look further *) + RETURN FALSE + END; +END; +RETURN FALSE; +END ExplicitExt; + +(******************************************************************************) + +PROCEDURE GetCardinal (qualifier : ARRAY OF CHAR; VAR n : CARDINAL); + +(* Check if qualifier is present. If so, then make sure given value is + a positive integer, and return via n. If not present then return 0. +*) + +VAR i, status : CARDINAL; + +BEGIN +IF ODD(CLI$PRESENT(qualifier)) THEN (* CLD ensures it has a value *) + status := CLI$GET_VALUE(qualifier,value); + i := HIGH(value); + WHILE (i > 0) AND (value[i] = ' ') DO (* remove trailing blanks *) + value[i] := NULL; (* SYSDEP: pad with NULLs *) + DEC(i); + END; + n := StringToCard(value); + IF Done() AND (n > 0) THEN + (* return *) + ELSE + WriteString('Bad /'); WriteString(qualifier); + WriteString(' value: '); WriteString(value); WriteLn; + WriteString('Specify a positive integer.'); WriteLn; + Halt(2); + END; +ELSE + n := 0; (* qualifier not present *) +END; +END GetCardinal; + +(******************************************************************************) + +PROCEDURE GetPosDimension (qualifier : ARRAY OF CHAR; VAR pixels : CARDINAL); + +(* Check if qualifier is present. If so, then make sure given value is + a valid positive dimension, convert and return via pixels. + A valid positive dimension consists of a positive integer or real number + followed by a two-letter unit in any case. +*) + +VAR + i, status : CARDINAL; + r : REAL; + ch1, ch2 : CHAR; + units : validunits; + +BEGIN +IF ODD(CLI$PRESENT(qualifier)) THEN (* CLD ensures it has a value *) + status := CLI$GET_VALUE(qualifier,value); + i := HIGH(value); + WHILE (i > 0) AND (value[i] = ' ') DO (* remove trailing blanks *) + value[i] := NULL; (* SYSDEP: pad with NULLs *) + DEC(i); + END; + IF i = 0 THEN i := 1 END; + (* extract units *) + IF (Cap(value[i-1]) = 'I') AND (Cap(value[i]) = 'N') THEN + units := in; + ELSIF (Cap(value[i-1]) = 'C') AND (Cap(value[i]) = 'M') THEN + units := cm; + ELSIF (Cap(value[i-1]) = 'M') AND (Cap(value[i]) = 'M') THEN + units := mm; + ELSIF (Cap(value[i-1]) = 'P') AND (Cap(value[i]) = 'C') THEN + units := pc; + ELSIF (Cap(value[i-1]) = 'P') AND (Cap(value[i]) = 'T') THEN + units := pt; + ELSIF (Cap(value[i-1]) = 'B') AND (Cap(value[i]) = 'P') THEN + units := bp; + ELSIF (Cap(value[i-1]) = 'P') AND (Cap(value[i]) = 'X') THEN + units := px; + ELSE + WriteString('Bad units in /'); WriteString(qualifier); + WriteString(' dimension: '); WriteString(value); WriteLn; + WriteString('Last two letters should be IN, CM, MM, PC, PT, BP or PX.'); + WriteLn; + Halt(2); + END; + ch1 := value[i-1]; (* remember letters in units *) + ch2 := value[i]; + value[i] := NULL; (* remove units *) + value[i-1] := NULL; + r := StringToReal(value); + IF Done() AND (r > 0.0) THEN (* convert r to pixels *) + CASE units OF + in : pixels := TRUNC(r * FLOAT(resolution) + 0.5) | + cm : pixels := TRUNC((r / 2.54) * FLOAT(resolution) + 0.5) | + mm : pixels := TRUNC((r / 25.4) * FLOAT(resolution) + 0.5) | + pc : pixels := TRUNC((r / 72.27) * 12.0 * FLOAT(resolution) + 0.5) | + pt : pixels := TRUNC((r / 72.27) * FLOAT(resolution) + 0.5) | + bp : pixels := TRUNC((r / 72.0) * FLOAT(resolution) + 0.5) | + px : pixels := TRUNC(r + 0.5) + END; + ELSE + value[i-1] := ch1; (* restore units *) + value[i] := ch2; + WriteString('Bad /'); WriteString(qualifier); + WriteString(' value: '); WriteString(value); WriteLn; + WriteString('Specify a positive dimension.'); WriteLn; + Halt(2); + END; +ELSE + pixels := 0; (* qualifier not present *) +END; +END GetPosDimension; + +(******************************************************************************) + +PROCEDURE GetDimension (qualifier : ARRAY OF CHAR; VAR pixels : INTEGER); + +(* Check if qualifier is present. If so, then make sure given value is + a valid dimension, convert and return via pixels. + A valid dimension consists of an integer or real number (possibly negative) + followed by a two-letter unit in any case. +*) + +VAR + i, status : CARDINAL; + r : REAL; + ch1, ch2 : CHAR; + units : validunits; + +BEGIN +IF ODD(CLI$PRESENT(qualifier)) THEN (* CLD ensures it has a value *) + status := CLI$GET_VALUE(qualifier,value); + i := HIGH(value); + WHILE (i > 0) AND (value[i] = ' ') DO (* remove trailing blanks *) + value[i] := NULL; (* SYSDEP: pad with NULLs *) + DEC(i); + END; + IF i = 0 THEN i := 1 END; + (* extract units *) + IF (Cap(value[i-1]) = 'I') AND (Cap(value[i]) = 'N') THEN + units := in; + ELSIF (Cap(value[i-1]) = 'C') AND (Cap(value[i]) = 'M') THEN + units := cm; + ELSIF (Cap(value[i-1]) = 'M') AND (Cap(value[i]) = 'M') THEN + units := mm; + ELSIF (Cap(value[i-1]) = 'P') AND (Cap(value[i]) = 'C') THEN + units := pc; + ELSIF (Cap(value[i-1]) = 'P') AND (Cap(value[i]) = 'T') THEN + units := pt; + ELSIF (Cap(value[i-1]) = 'B') AND (Cap(value[i]) = 'P') THEN + units := bp; + ELSIF (Cap(value[i-1]) = 'P') AND (Cap(value[i]) = 'X') THEN + units := px; + ELSE + WriteString('Bad units in /'); WriteString(qualifier); + WriteString(' dimension: '); WriteString(value); WriteLn; + WriteString('Last two letters should be IN, CM, MM, PC, PT, BP or PX.'); + WriteLn; + Halt(2); + END; + ch1 := value[i-1]; (* remember letters in units *) + ch2 := value[i]; + value[i] := NULL; (* remove units *) + value[i-1] := NULL; + r := StringToReal(value); + IF Done() THEN (* convert r to pixels *) + CASE units OF + in : pixels := TRUNC(ABS(r) * FLOAT(resolution) + 0.5) | + cm : pixels := TRUNC((ABS(r)/2.54) * FLOAT(resolution) + 0.5) | + mm : pixels := TRUNC((ABS(r)/25.4) * FLOAT(resolution) + 0.5) | + pc : pixels := TRUNC((ABS(r)/72.27) * 12.0 * FLOAT(resolution) + 0.5) | + pt : pixels := TRUNC((ABS(r)/72.27) * FLOAT(resolution) + 0.5) | + bp : pixels := TRUNC((ABS(r)/72.0) * FLOAT(resolution) + 0.5) | + px : pixels := TRUNC(ABS(r) + 0.5) + END; + IF r < 0.0 THEN pixels := -pixels END; + ELSE + value[i-1] := ch1; (* restore units *) + value[i] := ch2; + WriteString('Bad /'); WriteString(qualifier); + WriteString(' value: '); WriteString(value); WriteLn; + WriteString('Specify a valid dimension.'); WriteLn; + Halt(2); + END; +ELSE + pixels := 0; (* qualifier not present *) +END; +END GetDimension; + +(******************************************************************************) + +PROCEDURE Cap (ch : CHAR) : CHAR; + +(* Hamburg's CAP is stupid; do my own. *) + +BEGIN +IF (ch < 'a') OR (ch > 'z') THEN + RETURN ch; +ELSE + RETURN CAP(ch); +END; +END Cap; + +(******************************************************************************) + +PROCEDURE GetString (qualifier : ARRAY OF CHAR; + VAR s : ARRAY OF CHAR); + +(* Check if qualifier is present. If so, then get value and return via s. + If qualifier not present then return empty string. +*) + +VAR i, status : CARDINAL; + +BEGIN +IF ODD(CLI$PRESENT(qualifier)) THEN (* CLD ensures it has a value *) + status := CLI$GET_VALUE(qualifier,s); + i := HIGH(s); + WHILE (i > 0) AND (s[i] = ' ') DO (* remove trailing blanks *) + s[i] := NULL; (* SYSDEP: pad with NULLs *) + DEC(i); + END; +ELSE + s[0] := NULL; (* SYSDEP: LEN(s) will be 0 *) +END; +(* the main module will detect bad s value sooner or later *) +END GetString; + +(******************************************************************************) + +PROCEDURE Append (VAR s1 : ARRAY OF CHAR; s2 : ARRAY OF CHAR); + +(* Append s2 to s1. *) + +VAR i, j : CARDINAL; + +BEGIN +i := LEN(s1); (* SYSDEP: assumes s1 ends with NULL, unless full *) +j := 0; +WHILE (i <= HIGH(s1)) AND (j <= HIGH(s2)) AND (s2[j] <> NULL) DO + s1[i] := s2[j]; + INC(i); + INC(j); +END; +(* DEBUG +IF (i > HIGH(s1)) AND (j <= HIGH(s2)) AND (s2[j] <> NULL) THEN + WriteString('No room to append '); WriteString(s2); WriteLn; + Halt(2); +END; +GUBED *) +IF i <= HIGH(s1) THEN s1[i] := NULL END; +END Append; + +(******************************************************************************) + +PROCEDURE GetUnits; + +(* Check if /UNITS is present. If so, then make sure given value is + valid and set units. +*) + +VAR i, status : CARDINAL; ch1, ch2 : CHAR; + +BEGIN +IF ODD(CLI$PRESENT('UNITS')) THEN (* CLD ensures it has a value *) + status := CLI$GET_VALUE('UNITS',value); + i := HIGH(value); + WHILE (i > 0) AND (value[i] = ' ') DO (* remove trailing blanks *) + value[i] := NULL; (* SYSDEP: pad with NULLs *) + DEC(i); + END; + ch1 := Cap(value[0]); + ch2 := Cap(value[1]); + IF (ch1 = 'I') AND (ch2 = 'N') THEN + units := in; + ELSIF (ch1 = 'C') AND (ch2 = 'M') THEN + units := cm; + ELSIF (ch1 = 'M') AND (ch2 = 'M') THEN + units := mm; + ELSIF (ch1 = 'P') AND (ch2 = 'C') THEN + units := pc; + ELSIF (ch1 = 'P') AND (ch2 = 'T') THEN + units := pt; + ELSIF (ch1 = 'B') AND (ch2 = 'P') THEN + units := bp; + ELSIF (ch1 = 'P') AND (ch2 = 'X') THEN + units := px; + ELSE + WriteString('Bad /UNITS value: '); WriteString(value); WriteLn; + WriteString('Specify IN, CM, MM, PC, PT, BP or PX.'); WriteLn; + Halt(2); + END; +ELSE + units := px; (* if /UNITS not present *) +END; +END GetUnits; + +(******************************************************************************) + +PROCEDURE GetPages; + +(* Check if /PAGES is present. If so then subrange will be TRUE. + /PAGES can accept 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 = MAX(CARDINAL). 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). +*) + +VAR i, j, status, len : CARDINAL; + +BEGIN +IF ODD(CLI$PRESENT('PAGES')) THEN (* CLD ensures it has a value *) + status := CLI$GET_VALUE('PAGES',value); + i := HIGH(value); + WHILE (i > 0) AND (value[i] = ' ') DO (* remove trailing blanks *) + value[i] := NULL; (* SYSDEP: pad with NULLs *) + DEC(i); + END; + len := i + 1; (* length of value *) + firstTeXpage := ''; + finalTeXpage := ''; + i := 0; + WHILE (i < len) AND (value[i] <> ':') DO (* extract first page *) + firstTeXpage[i] := value[i]; + INC(i); + END; + IF value[0] = ':' THEN (* first page not given *) + firstDVIpage := 1; + ELSIF firstTeXpage[0] = '[' THEN (* TeX page given *) + firstDVIpage := 0; + ELSE (* DVI page given *) + firstDVIpage := StringToCard(firstTeXpage); + IF NOT Done() OR (firstDVIpage = 0) THEN + WriteString('/PAGES error! Bad first page: '); + WriteString(firstTeXpage); WriteLn; + Halt(2); + END; + END; + IF i = len THEN (* no colon; /PAGES=n or [t] *) + IF firstTeXpage[0] = '[' THEN + finalTeXpage := firstTeXpage; (* [t] = [t]:[t] *) + finalDVIpage := 0; + ELSE + finalDVIpage := firstDVIpage; (* n = n:n *) + END; + ELSE (* value[i] = ':' *) + INC(i); + j := 0; + WHILE i < len DO (* extract final page *) + finalTeXpage[j] := value[i]; + INC(i); INC(j); + END; + IF j = 0 THEN (* no page after ':' *) + finalDVIpage := MAX(CARDINAL); + ELSIF finalTeXpage[0] = '[' THEN (* TeX page given *) + finalDVIpage := 0; + ELSE (* DVI page given *) + finalDVIpage := StringToCard(finalTeXpage); + IF NOT Done() OR (finalDVIpage = 0) THEN + WriteString('/PAGES error! Bad final page: '); + WriteString(finalTeXpage); WriteLn; + Halt(2); + END; + END; + END; + subrange := TRUE; (* main module will check page range *) +ELSE + subrange := FALSE; (* if /PAGES not present *) +END; +END GetPages; + +(******************************************************************************) + +(* SYSDEP: CLD file must supply some qualifiers with default values. *) + +BEGIN +GetDVIFile; (* initialize DVIname *) +GetString('OUTPUT',PSname); (* initialize PSname *) +IF LEN(PSname) = 0 THEN (* /OUTPUT not specified *) + PSname := 'OUT.PS'; + (* It would be nicer to use DVIname with .PS instead of .DVI but + things get messy if DVIname is a logical name or includes a directory. + Note that PSPRINT.COM specifies an explicit /OUTPUT file. + *) +END; +GetCardinal('MAGNIFICATION',mag); (* 0 if no /MAG override *) +GetCardinal('RESOLUTION',resolution); (* get resolution BEFORE dimens *) +GetPosDimension('XSIZE',paperwd); +GetPosDimension('YSIZE',paperht); +GetDimension('HOFFSET',hoffset); (* 0 if not given *) +GetDimension('VOFFSET',voffset); (* ditto *) +GetString('HEADER',header); (* empty string if no /HEADER *) +GetString('PSPREFIX',psprefix); +GetString('TFM_DIRECTORY',tfmdir); +GetString('FONT_DIRECTORY',fontdir); +GetString('DUMMY_FONT',value); +dummyfont := fontdir; (* prefix dummyfont with fontdir *) +Append(dummyfont,value); +GetUnits; (* initialize units *) +GetPages; (* initialize subrange etc. *) +GetCardinal('INCREMENT',increment); (* 0 if /INC not used *) +IF increment = 0 THEN increment := 1 END; (* do normal page selection *) +stats := ODD(CLI$PRESENT('STATS')); +reverse := ODD(CLI$PRESENT('REVERSE')); +conserveVM := ODD(CLI$PRESENT('CONSERVE_VM')); +END Options. diff --git a/dviware/psprint/vms/pass.ps b/dviware/psprint/vms/pass.ps new file mode 100644 index 0000000000..9910654ad4 --- /dev/null +++ b/dviware/psprint/vms/pass.ps @@ -0,0 +1,22 @@ +% Verify and/or change a LaserWriter's system password. +% The following code would also work on a Linotronic but not on a +% PrintServer 40 (which uses a string instead of an integer). + +72 72 translate 0 0 moveto +/Times-Roman findfont 10 scalefont setfont + +0 % current system password? +serverdict begin +statusdict begin + checkpassword + { (Password correct. ) show } + { (Password incorrect! ) show } + ifelse +% uncomment to change the password to 999999 (use some other large number!) +% 0 999999 setpassword +% { (Password changed.) show } +% { (Password NOT changed!) show } +% ifelse +end + +showpage diff --git a/dviware/psprint/vms/piechart.ps b/dviware/psprint/vms/piechart.ps new file mode 100644 index 0000000000..1d9d6137ea --- /dev/null +++ b/dviware/psprint/vms/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/vms/ps.ps b/dviware/psprint/vms/ps.ps new file mode 100644 index 0000000000..a4de517297 --- /dev/null +++ b/dviware/psprint/vms/ps.ps @@ -0,0 +1,20 @@ +% Prologue for a PostScript job. +% It assumes *_print.com 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/vms/ps40_fonts.ps b/dviware/psprint/vms/ps40_fonts.ps new file mode 100644 index 0000000000..a24e0651ff --- /dev/null +++ b/dviware/psprint/vms/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/vms/ps40_header.ps b/dviware/psprint/vms/ps40_header.ps new file mode 100644 index 0000000000..524d07137b --- /dev/null +++ b/dviware/psprint/vms/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/vms/ps40_list.ps b/dviware/psprint/vms/ps40_list.ps new file mode 100644 index 0000000000..a13412eea2 --- /dev/null +++ b/dviware/psprint/vms/ps40_list.ps @@ -0,0 +1,19 @@ +% Type PSPRINT/DEV=PS40/NOTIFY <this file> +% to see (on terminal) a list of all known PrintServer fonts, and memory usage. + +/showline { print (\n) print } def +/Times-Roman findfont 12 scalefont setfont +/s40 40 string def + +36 700 moveto +FontDirectory {pop s40 cvs showline} forall + +( ) showline +(Total memory: ) showline +vmstatus s40 cvs showline +(Memory used: ) showline +s40 cvs showline +pop +( Free memory: ) showline +vmstatus exch sub s40 cvs showline +pop diff --git a/dviware/psprint/vms/ps40_print.com b/dviware/psprint/vms/ps40_print.com new file mode 100644 index 0000000000..58e205b803 --- /dev/null +++ b/dviware/psprint/vms/ps40_print.com @@ -0,0 +1,109 @@ +$! This command file is run by PSPRINT/DEV=PS40 with the following parameters: +$! P1 = complete file specification +$! P2 = file format (DVI or PS or TEXT or TWO or WIDE) +$! P3 = options for PSDVI +$! P4 = options for PRINT +$! P5 = /NOTE value ("" if not used) +$! P6 = /COPIES value (1 if not used) +$! P7 = /OUTPUT value ("" if not used) +$! P8 = "bb<prep>" where b = Y or N and represents the status of the +$! boolean qualifiers /DELETE, /LANDSCAPE +$! and <prep> is the /PREP value, possibly empty +$! +$! This file is much like LW_PRINT.COM, but differs in the following ways: +$! * ^D cannot be sent to the PS40. +$! * No banner page need be created since the PS40 produces one (and a trailer). +$! * /NOTIFY will send PostScript messages back to the user. +$! * PSDVI uses write-white fonts appropriate for a Ricoh engine. +$! * /BANNER and /MANUALFEED are not implemented. +$ +$ on control_y then exit +$ set symbol/scope=(nolocal,noglobal) +$ delflag = f$extract(0,1,p8) +$ landflag = f$extract(1,1,p8) +$ prepfile = f$extract(2,999,p8) +$ +$ if (p6 .gt. 0) .and. (p6 .lt. 101) then goto CONTINUE +$ write sys$output "Bad /COPIES value. Specify 1 to 100." +$ exit +$ +$ CONTINUE: +$ copies = f$string(p6) +$ job = f$parse(p1,,,"NAME") +$ +$ copy tex_ps:ps40_header.ps sys$scratch:'job'.tmp +$ tmpfile = f$search("sys$scratch:''job'.tmp") +$ write sys$output - + "Creating SYS$SCRATCH:''job'.TMP" + f$parse(tmpfile,,,"VERSION") +$ open/append tmp 'tmpfile' +$ write tmp "/#copies " + copies + " def" +$ write tmp "/dev (PS40) def" +$ write tmp "/res 300 def" +$ write tmp "/fspec (" + p1 + ") def" +$ if landflag .eqs. "Y" then write tmp "/land true def" +$ if landflag .eqs. "N" then write tmp "/land false def" +$ close tmp +$ +$ if p2 .eqs. "DVI" then append tex_ps:tex.ps, tex_ps:ps40_fonts.ps 'tmpfile' +$ if p2 .eqs. "PS" then append tex_ps:ps.ps 'tmpfile' +$ if p2 .eqs. "TEXT" then append tex_ps:text.ps 'tmpfile' +$ if p2 .eqs. "TWO" then append tex_ps:two.ps 'tmpfile' +$ if p2 .eqs. "WIDE" then append tex_ps:wide.ps 'tmpfile' +$ +$ if (p2 .nes. "DVI") .and. (p2 .nes. "PS") then goto SKIPPREP +$ if prepfile .eqs. "" then goto SKIPPREP +$ write sys$output "Including " + prepfile +$ append 'prepfile' 'tmpfile' +$ SKIPPREP: +$ +$ global = f$search("global.ps") +$ if (global .eqs. "") .or. (p2 .nes. "DVI") then goto SKIPGLOBAL +$ write sys$output "Including GLOBAL.PS" +$ append 'global' 'tmpfile' +$ SKIPGLOBAL: +$ +$ if p2 .nes. "DVI" then goto PRINT +$ +$ ver = 1 +$ LOOP: +$ psdvifile = "sys$scratch:psdvi.tmp;''f$string(ver)'" +$ if f$search(psdvifile) .eqs. "" then goto ENDLOOP +$ ver = ver + 1 +$ goto LOOP +$ +$ ENDLOOP: +$ land = "" +$ if landflag .eqs. "Y" then land = "/xsize=297mm /ysize=210mm" +$ on warning then goto BADDVI +$ PSDVI 'p1' 'land' /HEADER='tmpfile' - + /OUTPUT='psdvifile' - + /RES=300 - + /FONT="write_white_fonts:" - + /DUMMY="cmr10.300pk" - + /NOCONSERVE - + /NOREVERSE 'p3' +$ delete/nolog 'tmpfile' +$ rename/nolog 'psdvifile' 'tmpfile' +$ goto PRINT +$ +$ BADDVI: +$ delete/nolog 'tmpfile' +$ if f$search(psdvifile) .nes. "" then delete/nolog 'psdvifile' +$ write sys$output "" +$ write sys$output "Printing aborted due to error(s). Temporary file deleted." +$ exit +$ +$ PRINT: +$ on error then exit +$ if p2 .nes. "DVI" then append 'p1' 'tmpfile' +$ +$ if p7 .eqs. "" then goto PRINTJOB +$ copy tex_ps:empty.ps, 'tmpfile' 'p7' +$ delete/log 'tmpfile' +$ write sys$output "" +$ write sys$output "Nothing printed. PostScript saved in " + p7 +$ exit +$ +$ PRINTJOB: +$ print/note="''p5'"/queue=PS40/name='job' 'tmpfile'/delete 'p4' +$ if delflag .eqs. "Y" then delete/log 'p1' diff --git a/dviware/psprint/vms/psdvi.cld b/dviware/psprint/vms/psdvi.cld new file mode 100644 index 0000000000..4f9c03e5d2 --- /dev/null +++ b/dviware/psprint/vms/psdvi.cld @@ -0,0 +1,64 @@ +define verb PSDVI +image TEX_PS:PSDVI.EXE + parameter p1,label=filespec,prompt="DVI file",value(required,type=$infile) + qualifier output, value(required,type=$file) ! default is OUT.PS + qualifier header, value(required,type=$file) ! default is no header + qualifier pages, value(required) ! default is all pages + qualifier increment, value(required,type=$number) ! default is 1 + qualifier magnification, value(required,type=$number) ! default is DVI mag + qualifier stats, ! default is FALSE + qualifier reverse, ! default is FALSE + qualifier conserve_VM, ! default is FALSE + qualifier hoffset, value(required) ! default is 0 + qualifier voffset, value(required) ! default is 0 + qualifier units, nonnegatable,default, + value(default=IN) ! IN,CM,MM,PC,PT,BP,PX + qualifier resolution, nonnegatable,default, + value(default=300) ! for LaserWriter + qualifier xsize, nonnegatable,default, + value(default=210MM) ! A4 width + qualifier ysize, nonnegatable,default, + value(default=297MM) ! A4 height + qualifier psprefix, nonnegatable,default, + value(default="ps-") + qualifier tfm_directory, nonnegatable,default, + value(default="disk$utils:[utilities.tex.fonts]") + qualifier font_directory, nonnegatable,default, + value(default="disk$utils:[utilities.tex.300pk]") + qualifier dummy_font, nonnegatable,default, + value(default="cmr10.300pk") +! +! The Options module automatically prefixes dummy_font with font_directory. +! The FontReader module then uses the font_directory and dummy_font values +! to decide on the location, format and naming convention of all font files. +! The above values assume you use PK files and keep them in one big directory. +! Note that the dummy_font file type has a font size equal to the resolution. +! If you are using Kellerman & Smith's old TeX system in which PXL files are +! kept in separate subdirectories then you'll need something like: +! +! qualifier font_directory, nonnegatable,default, +! value(default="tex_disk:[tex.fonts.]") +! qualifier dummy_font, nonnegatable,default, +! value(default="[1500]cmr10.pxl") +! +! Note the important differences: +! 1. The font_directory value ends with ".]". +! 2. The dummy_font value ends with "PXL". +! 3. The font size is NOT in the file type; it is the subdirectory name. +! 4. The font size = resolution * 1000 / 200. +! +! PSDVI can handle any font scheme that obeys the following rules: +! - The dummy_font value ends in either "PXL" or "PK" and all font files +! use the same coding format. +! - If the font_directory value ends in ".]" then all font files reside in +! various subdirectories of font_directory. Each subdirectory name is +! a different font size and dummy_font must start with "[fontsize]". +! - If the font_directory value does NOT end in ".]" then all font files +! reside in font_directory. Each file type begins with a font size and +! dummy_font must start with "fontname.fontsize". +! - The dummy_font value must represent an unmagnified font. Its font size +! substring matches either the resolution or (resolution * 1000 / 200). +! +! The above hackery is an attempt to cope with the various font schemes +! used by VAX/VMS TeX sites. Note that GF files are not handled; I figured +! any sites using GF files would convert them to PK files sooner or later. diff --git a/dviware/psprint/vms/psdvi.hlp b/dviware/psprint/vms/psdvi.hlp new file mode 100644 index 0000000000..fce1d8363f --- /dev/null +++ b/dviware/psprint/vms/psdvi.hlp @@ -0,0 +1,200 @@ +1 PSDVI + +USAGE: PSDVI filename[.DVI] [qualifiers] + +PSDVI is not really meant to be used by itself; it is part of the PSPRINT +system. PSDVI reads a given DVI file (produced by TeX or LaTeX) and +creates a PostScript output file called OUT.PS (unless /OUTPUT is used +to specify some other name). The output file uses PostScript procedures +whose definitions must be sent to the printer first. The /HEADER qualifier +can be used to include an appropriate file of definitions at the start of +the output. PSDVI displays the DVI page number and TeX page counter(s) +as each page is translated. + +2 Errors + +PSDVI can 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 size. + Try a different \magstep value in your TeX source file. + + Couldn't open \special file: ... + PSDVI 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. + +2 Graphics + +PSDVI allows the inclusion of PostScript graphics using TeX's \special +command. The given 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 PSDVI to write a +line containing "2 1 scale" to the output file, then copy the contents +of FIGURE.PS. (Such a figure will be twice as wide as one included +by \special{figure.ps}.) The PSPRINT User Guide has more details. + +2 Qualifiers + +/OUTPUT=file +(default=OUT.PS) + +Give an explicit file specification to the output file. + +/HEADER=file +(default=no header) + +Include the given file at the start of the output file. + +/PAGES=first:final +(default=all pages) + +Translate 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 5 DVI pages `[0] [1] [2.1] [2.2] [3]', +here are some examples of how you could use /PAGES: + + $ PSDVI FOO /PAGES=2 --- translates the second DVI page ([1]) + $ PSDVI FOO /PAGES=2: --- translates the last four pages + $ PSDVI FOO /PAGES=:4 --- translates the first four pages + $ PSDVI FOO /PAGES=[2] --- translates [2.1] and [2.2] + $ PSDVI FOO /PAGES=1:[2] --- translates the first four pages + $ PSDVI FOO /PAGES=[2.2]: --- translates the last two pages + +Note that "first" and "final" are optional; they default to +the first and last DVI pages respectively. + +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. Many DVI pages 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. + +/INCREMENT=i +(default=1) + +Assuming f is the first DVI page selected (where f is either 1 or the +start of a /PAGE subrange) then an increment of i tells PSDVI to translate +pages f, f+i, f+2i, f+3i, ... , f+ni, where f+ni is <= the final DVI page +selected. The primary use of /INCREMENT is to simplify the printing of a +document on both sides of the paper. E.g., if FOO.DVI has 7 pages then: + + $ PSDVI FOO /INC=2 --- will translate DVI pages 1, 3, 5, 7 + $ PSDVI FOO /INC=2 /PAG=2: --- will translate DVI pages 2, 4, 6 + $ PSDVI FOO /INC=2 /PAG=2: /REV --- will translate DVI pages 6, 4, 2 + +Note that the use of /REVERSE with /INCREMENT has no effect on WHICH pages +are translated; it simply changes the ORDER in which they are done. + +/MAGNIFICATION=i +(default=use DVI magnification) + +Override the DVI magnification with a number representing 1000 times the +desired magnification. The given integer should correspond to +TeX's \magstep values; see chapter 4 of The TeXbook. + +/UNITS=XX +(default=IN) + +Set the units of dimensions displayed in some PSDVI messages +(e.g., if the page is off the paper). XX can be one of: + + 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 (e.g., an Apple LaserWriter has 300 pixels per inch) + +/REVERSE +/NOREVERSE +(default=/noreverse) + +By default PSDVI translates pages in ascending order. +Use /REVERSE to translate pages in descending order. + +/STATS +/NOSTATS +(default=/nostats) + +Use /STATS to see statistics on the number of rules/fonts/characters +appearing on each page, and other useful(?) information. + +/CONSERVE_VM +/NOCONSERVE_VM +(default=/noconserve_vm) + +Use /CONSERVE_VM if your document won't print because of a "VM error" +(i.e., Virtual Memory is exhausted). This qualifier will tell PSDVI to +conserve VM at the expense of downloading character bitmaps more often +(resulting in a larger output file that takes longer to print). + +/RESOLUTION=i +(default=300) + +i is a positive integer specifying the resolution of your printer +in pixels per inch (horizontally and vertically). + +/HOFFSET=dimension +/VOFFSET=dimension +(default=0in) +(default=0in) + +These qualifiers allow you to shift the printed location of each page +according to the given dimensions. For example, "/hoffset=-0.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 /UNITS). + +/XSIZE=posdimen +/YSIZE=posdimen +(default=210mm) +(default=297mm) + +PSDVI will automatically check each DVI page to make sure it fits +within the given paper dimensions. The default values describe +A4 paper with the usual "portrait" orientation. +Swap these values if you plan to use "landscaped" paper. +A "posdimen" is any positive integer or real number followed by a +two-letter unit: IN,CM,MM,PC,PT,BP,PX (same as those for /UNITS). + +/PSPREFIX=string +(default="ps-") + +PSDVI needs to read TFM files if your document uses resident PostScript +fonts (for which bitmapped information does not exist). +All such fonts must have names beginning with this prefix. + +/TFM_DIRECTORY=directory +(default=disk$utils:[utilities.tex.fonts]) + +Specifies the location of TFM files for resident PostScript fonts. + +/FONT_DIRECTORY=directory +(default=disk$utils:[utilities.tex.300pk]) + +PSDVI gets all its character bitmap information from font files located +in the given directory. + +/DUMMY_FONT=file +(default=cmr10.300pk) + +This qualifier indicates the naming convention and format of all font files. +PSDVI will warn you about non-existent fonts. Rather than abort, it will +use the font file specified by /DUMMY_FONT and continue as best it can. +Unlike DVItoVDU, dummy font characters do NOT appear in the output. + +! See PSDVI.CLD for details on how these last two qualifiers are used by PSDVI +! to determine the location, naming convention and format of font files. diff --git a/dviware/psprint/vms/psdvi.mod b/dviware/psprint/vms/psdvi.mod new file mode 100644 index 0000000000..79c664ab3c --- /dev/null +++ b/dviware/psprint/vms/psdvi.mod @@ -0,0 +1,1207 @@ +MODULE PSDVI; + +(* Author: Andrew Trevorrow + Implementation: University of Hamburg Modula-2 under VAX/VMS version 4 + Date Started: August, 1986 + Released: September, 1986 (version 1.0) + + Description: + PSDVI reads a TeX DVI file and creates a corresponding PostScript file. + This output file needs to be prefixed with some PostScript code. + The /HEADER option can be used to include any desired file. + PSDVI can be used by itself (see PSDVI.HLP) or as part of the + PSPRINT system (see the PSPRINT User Guide and System Guide). + Much of the code has been borrowed from DVItoVDU. + + Notes: + - Debugging code is bracketed by (* DEBUG *) ... (* GUBED *). + This code will be disabled in the final working version. + - System-dependent code is indicated by the string "SYSDEP". + - Uncertain or unfinished code is indicated by the strings "???" and "!!!". + - Procedures are defined in a top-down manner: each procedure is usually + defined as soon as possible after its first use. + - The above notes also apply to the local modules used by PSDVI. + + Revised: + December, 1986 + - PXLReader has become FontReader and can handle other font formats. + All font-dependent code has been moved into FontReader. + - Use LoadBitmap from FontReader instead of LoadPSChar from PSWriter + to output PostScript code for each character bitmap. + Unlike DVItoVDU, PSDVI does not need to store each bitmap for later use. + - Released version 1.1 in January, 1987 + + November, 1987 (while at The Open University) + - Import tfmdir (for display in ShowOptions) and conserveVM from Options. + - Import SaveVM and RestoreVM from PSWriter. + - Import SetPostScriptChar from PSWriter; it is used (instead of + SetBitmapChar) to typeset characters from a resident PostScript font. + - Use conserveVM flag to call a different sequence of PSWriter + routines if the user wants to conserve virtual memory. + - Use psfont flag (set in BuildFontSpec in FontReader) to control the + sequence of PSWriter routines for resident PostScript fonts. + - Added ShowPtSize routine to show requested pt size for PostScript fonts. + - Added PSDVI banner line to start of ShowOptions showing version number. + - Released version 2.0 in December, 1987 + + June--August, 1988 (while at Aston University) + - Added /psprefix qualifier so that sites have some flexibility in choosing + the prefix that indicates a PostScript font. + - Added /increment qualifier to enhance page selection for duplex printing. + - Added /hoffset and /voffset qualifiers to allow shifting of page. + - Removed "Creating ..." message due to changes in *_PRINT.COM files. + - No longer use StartLn/WriteBuffer/pagesperline. + Page numbers now appear on separate lines. + - Released version 3.0 in August, 1988 + + September--October, 1989 (while at Aston University, 2nd time) + - \special info now added to tail of speciallist. + - Released version 3.1 in October, 1989 +*) + + +FROM Storage IMPORT + ALLOCATE, DEALLOCATE; (* for NEW and DISPOSE *) + + +(* SYSDEP: Modula-2 avoids the problem of system dependence by simply + not providing any input/output routines etc. The above importations + are highly system-dependent. + + The following modules are kept with the file you are now reading. + See the .DEF files for details on how the imported identifiers should be + used; implementation details can be found in the corresponding .MOD files. +*) + + +(* The TermOut module is used to do all terminal output. *) +FROM TermOut IMPORT + Write, WriteString, WriteInt, WriteCard, WriteLn, Halt; + + +(* The Options module carries out the task of reading the DCL command + line and extracting the DVI file parameter and qualifiers. +*) +FROM Options IMPORT + validunits, units, + reverse, stats, conserveVM, + subrange, firstTeXpage, finalTeXpage, firstDVIpage, finalDVIpage, + increment, resolution, mag, paperwd, paperht, hoffset, voffset, + psprefix, tfmdir, fontdir, dummyfont, header, PSname, DVIname; + + +(* PSDVI uses the routines and data structures defined in DVIReader to move + about randomly in the DVI file and to interpret pages. + The reference points of characters and rules on a page are stored as + pairs of horizontal and vertical pixel coordinates. + The coordinate scheme is described in detail in DVIREADER.DEF. +*) +FROM DVIReader IMPORT + ruletablesize, chartablesize, maxfontspec, maxTeXchar, + ruleinfo, ruleinfoptr, + fontstring, fontinfo, fontinfoptr, + charinfo, charinfoptr, pixeltable, pixeltableptr, + TeXcounters, TeXpageinfo, + DVIerrorcodes, GetByteFunction, + DVImag, totalpages, totalfonts, + currDVIpage, currTeXpage, + rulelist, totalrules, fontlist, currfont, + minhp, minvp, maxhp, maxvp, pageempty, + DVIErrorRoutine, SpecialRoutine, PixelTableRoutine, + OpenDVIFile, SetConversionFactor, MoveToDVIPage, CurrMatchesNew, + PixelRound, InterpretPage, SortFonts, CloseDVIFile; + + +(* PSDVI gets character metrics and bitmaps from font files. + The FontReader module can handle a variety of different font formats. + No more than one font file will be open at any given time. +*) +FROM FontReader IMPORT + FillPixelTable, LoadBitmap, + InitFontReader, BuildFontSpec, + OpenFontFile, CloseFontFile; + + +(* The PSWriter routines are used to create an output file containing + the appropriate PostScript code. +*) +FROM PSWriter IMPORT + OpenOutput, OutputHeader, BeginPage, NewBitmapFont, + OutputPage, specialstring, OutputSpecial, + SaveVM, BeginPostScriptFont, SetPostScriptChar, + BeginBitmapFont, SetBitmapChar, EndFont, RestoreVM, + SetRule, EndPage, CloseOutput; + + +(******************************************************************************* + GLOBAL DECLARATIONS +*) + +CONST + NULL = 0C; (* SYSDEP: NULL terminates a string, unless full *) + warning = 0; (* SYSDEP: Halt parameter to set VMS $SEVERITY *) + success = 1; (* ditto *) + error = 2; (* ditto *) + +TYPE + specialinfoptr = POINTER TO specialinfo; + specialinfo = RECORD + special : specialstring; + hp, vp : INTEGER; + nextspecial : specialinfoptr; + END; + +VAR + speciallist : specialinfoptr; (* for storing \special info *) + specialtail : specialinfoptr; (* tail of speciallist *) + papertop, + paperleft, + paperbottom, + paperright : INTEGER; (* these define the edges of the paper *) + warncount, (* count of problems detected *) + pagecount : CARDINAL; (* count of pages actually output *) + unusedfont : fontinfoptr; (* first unused font in sorted fontlist *) + + +(******************************************************************************) + +PROCEDURE TopLevel; + +(* Note that the implementation blocks of all imported modules have already + been executed. In particular, the Options module has read the DCL command + line and initialized the DVI file parameter and qualifier values. +*) + +VAR i : CARDINAL; + +BEGIN +Initialize; +DVIErrorRoutine := MyDVIErrorRoutine; (* called by DVIReader *) +OpenDVIFile(DVIname); (* and read DVImag etc. *) +IF mag = 0 THEN mag := DVImag END; (* no /MAG value so use DVImag *) +SetConversionFactor(resolution,mag); (* for DVIReader *) +SpecialRoutine := MySpecialRoutine; (* called by InterpretPage *) +PixelTableRoutine := MyPixelTableRoutine; (* called by InterpretPage *) +InitFontReader; (* assign font-dependent routines *) +IF stats THEN ShowOptions END; +CheckPageRange; (* set firstDVIpage, finalDVIpage *) +IF OpenOutput(PSname) THEN + (* DEBUG + WriteString('Creating '); + WriteString(PSname); + WriteLn; + GUBED *) +ELSE + WriteString("Couldn't open output file: "); + WriteString(PSname); + WriteLn; + Halt(error); +END; +IF LEN(header) > 0 THEN (* output header file first *) + IF NOT OutputHeader(header) THEN + WriteString("Couldn't open header file: "); + WriteString(header); + WriteLn; + Halt(error); + END; +END; +IF increment > 1 THEN (* finalDVIpage may need reducing *) + WHILE (finalDVIpage - firstDVIpage) MOD increment > 0 DO + DEC(finalDVIpage); + END; +END; +IF reverse THEN + MoveToDVIPage(finalDVIpage); (* start with finalDVIpage *) + finalDVIpage := firstDVIpage; (* and end with firstDVIpage *) +ELSE + MoveToDVIPage(firstDVIpage); (* start with firstDVIpage *) +END; +LOOP + DoPage; (* do at least one page *) + IF stats THEN ShowPageStats END; + IF currDVIpage = finalDVIpage THEN EXIT END; + IF reverse THEN + MoveToDVIPage(currDVIpage - increment); + ELSE + MoveToDVIPage(currDVIpage + increment); + END; +END; +IF stats THEN ShowFinalStats END; +CloseDVIFile; +CloseOutput; +IF warncount > 0 THEN + Halt(warning); +ELSE + Halt(success); +END; +END TopLevel; + +(******************************************************************************) + +PROCEDURE Initialize; + +BEGIN +(* we don't bother checking for crazy resolution/paperht/paperwd values *) +(* top left corner of paper is fixed at (-1",-1") *) +papertop := -INTEGER(resolution); +paperleft := -INTEGER(resolution); +paperbottom := papertop + INTEGER(paperht) - 1; +paperright := paperleft + INTEGER(paperwd) - 1; +warncount := 0; +pagecount := 0; +speciallist := NIL; (* for first MySpecialRoutine *) +END Initialize; + +(******************************************************************************) + +PROCEDURE MyDVIErrorRoutine (DVIerror : DVIerrorcodes); + +(* DVIErrorRoutine for DVIReader; see DVIREADER.DEF. *) + +BEGIN +CASE DVIerror OF +(* these errors are detected in OpenDVIFile; they are considered fatal *) + DVIunopened : + WriteString("Couldn't open DVI file: "); + WriteString(DVIname); WriteLn; + Halt(error); | + DVIempty : + WriteString(DVIname); + WriteString(' is empty!'); WriteLn; + Halt(error); | + DVIbadid : + WriteString(DVIname); + WriteString(' is not a valid DVI file!'); WriteLn; + Halt(error); | + DVIstackoverflow : + WriteString('Stack capacity exceeded!'); WriteLn; + PleaseReport; + Halt(error); | +(* this error is detected in InterpretPage; we warn user but continue *) + DVIbadchar : + WITH currfont^ DO + WriteString('Ignoring unknown character from '); + WriteString(fontspec); Write('!'); + WriteLn; + END; | +(* this error should never happen *) + DVIcatastrophe : + WriteLn; + WriteString('Something awful has happened!'); WriteLn; + PleaseReport; + Halt(error); +ELSE + (* this will only happen if we've missed a DVI error *) + WriteLn; + WriteString('Bug in MyDVIErrorRoutine!'); WriteLn; + PleaseReport; + Halt(error); +END; +END MyDVIErrorRoutine; + +(******************************************************************************) + +PROCEDURE PleaseReport; + +BEGIN +WriteString('Please tell your local TeXnician.'); WriteLn; +END PleaseReport; + +(******************************************************************************) + +PROCEDURE MySpecialRoutine (hpos, vpos, + totalbytes : INTEGER; + NextDVIByte : GetByteFunction); + +(* DVIReader has seen a \special command while interpreting the current page. + It will call this routine and pass the current page position, the number + of bytes in the command and a function to return their values one at a time. + Instead of calling OutputSpecial directly, we have to save the necessary + info away for later use (see DoPage). +*) + +VAR i, flush : INTEGER; temp : specialinfoptr; + +BEGIN +NEW(temp); +WITH temp^ DO + special := ''; (* SYSDEP: fill with NULLs *) + FOR i := 0 TO totalbytes-1 DO + IF i <= HIGH(special) THEN + special[i] := CHR(NextDVIByte()); + END; + END; + (* DVIReader demands that we read ALL the \special bytes *) + IF totalbytes > HIGH(special) + 1 THEN + INC(warncount); + WriteString('\special command is too long: '); + WriteString(special); + WriteLn; + WriteString('Truncating: '); + FOR i := 1 TO totalbytes - (HIGH(special) + 1) DO + Write(CHR(NextDVIByte())); (* display the truncated bytes *) + END; + WriteLn; + END; + hp := hpos; + vp := vpos; + nextspecial := NIL; +END; +(* add new node to tail of list *) +IF speciallist = NIL THEN + speciallist := temp; +ELSE + specialtail^.nextspecial := temp; +END; +specialtail := temp; +END MySpecialRoutine; + +(******************************************************************************) + +PROCEDURE ShowDimension (pixels : INTEGER); + +(* Show the given pixel dimension in terms of units. *) + +VAR realdim : REAL; fracpart : CARDINAL; + +BEGIN +CASE units OF + in : realdim := FLOAT(pixels) / FLOAT(resolution) | + cm : realdim := FLOAT(pixels) / FLOAT(resolution) * 2.54 | + mm : realdim := FLOAT(pixels) / FLOAT(resolution) * 25.4 | + pc : realdim := FLOAT(pixels) / FLOAT(resolution) * 72.27 / 12.0 | + pt : realdim := FLOAT(pixels) / FLOAT(resolution) * 72.27 | + bp : realdim := FLOAT(pixels) / FLOAT(resolution) * 72.0 | + px : WriteInt(pixels); WriteString('px'); RETURN; +END; +(* show realdim to an accuracy of 1 decimal place *) +IF ABS(realdim) < 0.05 THEN + WriteString('0.0'); +ELSE + IF realdim < 0.0 THEN + Write('-'); + realdim := ABS(realdim); + END; + realdim := realdim + 0.05; (* round up to 1 decimal place *) + WriteCard(TRUNC(realdim)); (* whole part *) + Write('.'); + fracpart := TRUNC((realdim - FLOAT(TRUNC(realdim))) * 10.0); + (* fracpart is now 0..9 *) + WriteCard(fracpart); +END; +ShowUnits; +END ShowDimension; + +(**********************************************************************) + +PROCEDURE ShowUnits; + +BEGIN +CASE units OF + in : WriteString('in') | + cm : WriteString('cm') | + mm : WriteString('mm') | + pc : WriteString('pc') | + pt : WriteString('pt') | + bp : WriteString('bp') | + px : WriteString('px') | +END; +END ShowUnits; + +(******************************************************************************) + +PROCEDURE MyPixelTableRoutine; + +(* PixelTableRoutine for DVIReader which has just allocated a new pixeltable + for currfont^. DVIReader 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. + 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 : CARDINAL; + +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 + IF OpenFontFile(fontspec) THEN + (* only need fontid for a bitmapped font *) + IF NOT psfont THEN + fontid := fontname; + fontsizelen := lastn - firstn + 1; + IF fontnamelen + fontsizelen < maxfontspec THEN + (* append ".fontsize" to fontid *) + fontid[fontnamelen] := '.'; + FOR i := 1 TO fontsizelen DO + fontid[fontnamelen + i] := fontspec[firstn + i - 1]; + END; + IF fontnamelen + fontsizelen + 1 < maxfontspec THEN + fontid[fontnamelen + fontsizelen + 1] := NULL; + END; + ELSE + (* in the unlikely event that there is no room to append ".fontsize" + we simply leave fontid = fontname and hope it's unique *) + WriteString("fontname too long: "); WriteString(fontname); WriteLn; + WriteString("Increase maxfontspec in DVIReader."); WriteLn; + END; + IF NOT conserveVM THEN + NewBitmapFont(fontid); + END; + END; + (* DEBUG + WriteString('Reading font data from '); WriteString(fontspec); WriteLn; + GUBED *) + ELSIF OpenFontFile(dummyfont) THEN + (* fontid is left undefined; it will not be used *) + INC(warncount); + WriteString("Couldn't open font file: "); WriteString(fontspec); WriteLn; + (* use dummy font info instead *) + ELSE + WriteString("Couldn't open dummy font: "); WriteString(dummyfont); + WriteLn; Halt(error); + END; + FillPixelTable; + CloseFontFile; +END; +END MyPixelTableRoutine; + +(******************************************************************************) + +PROCEDURE ShowOptions; + +(* Show DVI file name and qualifier values set in Options module. *) + +BEGIN +WriteString('This is PSDVI, version 3.1'); +WriteLn; WriteLn; +WriteString('DVI file = '); WriteString(DVIname); +WriteLn; +WriteString('PostScript file = '); WriteString(PSname); +WriteLn; +WriteString('Header file = '); WriteString(header); +WriteLn; +WriteString('Resolution = '); WriteCard(resolution); +WriteString(' pixels per inch'); +WriteLn; +WriteString('Magnification = '); WriteCard(mag); +IF mag <> DVImag THEN + WriteString(' (DVI mag of '); WriteCard(DVImag); + WriteString(' was overridden)'); +ELSE + WriteString(' (DVI mag)'); +END; +WriteLn; +WriteString('TFM directory = '); WriteString(tfmdir); +WriteLn; +WriteString('PS font prefix = '); WriteString(psprefix); +WriteLn; +WriteString('Font directory = '); WriteString(fontdir); +WriteLn; +WriteString('Dummy font = '); WriteString(dummyfont); +WriteLn; +WriteString('Horizontal offset = '); ShowDimension(hoffset); +WriteLn; +WriteString('Vertical offset = '); ShowDimension(voffset); +WriteLn; +WriteString('Paper width = '); ShowDimension(paperwd); +WriteLn; +WriteString('Paper height = '); ShowDimension(paperht); +WriteLn; +WriteString('Units = '); ShowUnits; +WriteLn; +WriteString('Reverse = '); +IF reverse THEN WriteString('true') ELSE WriteString('false') END; +WriteLn; +WriteString('Stats = '); +IF stats THEN WriteString('true') ELSE WriteString('false') END; +WriteLn; +WriteString('Conserve VM = '); +IF conserveVM THEN WriteString('true') ELSE WriteString('false') END; +WriteLn; +WriteString('Pages = '); +IF subrange THEN + IF firstDVIpage = 0 THEN + WriteString(firstTeXpage); + ELSE + WriteCard(firstDVIpage); + END; + Write(':'); + IF finalDVIpage = 0 THEN + WriteString(finalTeXpage); + ELSE + WriteCard(finalDVIpage); + END; +ELSE + WriteString('all pages'); +END; +IF increment > 1 THEN + WriteString(', but with an increment of '); + WriteCard(increment); +END; +WriteLn; +WriteLn; +END ShowOptions; + +(******************************************************************************) + +PROCEDURE CheckPageRange; + +(* If user requested a page subrange then we make sure it is valid. *) + +VAR newTeXpage : TeXpageinfo; + +BEGIN +IF NOT subrange THEN (* translate all pages *) + firstDVIpage := 1; + finalDVIpage := totalpages; +ELSE + IF firstDVIpage = 0 THEN (* parse and locate firstTeXpage *) + IF ParseTeXPage(firstTeXpage,newTeXpage) THEN + MoveToDVIPage(1); + (* go forwards until newTeXpage matches currTeXpage *) + LOOP + IF CurrMatchesNew(newTeXpage) THEN + firstDVIpage := currDVIpage; + EXIT; + ELSIF currDVIpage = totalpages THEN + WriteString('First TeX page does not exist!'); WriteLn; + Halt(error); + ELSE + MoveToDVIPage(currDVIpage + 1); + END; + END; + ELSE + WriteString('Error in first TeX page!'); WriteLn; + Halt(error); + END; + END; + IF finalDVIpage = 0 THEN (* parse and locate finalTeXpage *) + IF ParseTeXPage(finalTeXpage,newTeXpage) THEN + MoveToDVIPage(totalpages); + (* go backwards until newTeXpage matches currTeXpage *) + LOOP + IF CurrMatchesNew(newTeXpage) THEN + finalDVIpage := currDVIpage; + EXIT; + ELSIF currDVIpage = 1 THEN + WriteString('Final TeX page does not exist!'); WriteLn; + Halt(error); + ELSE + MoveToDVIPage(currDVIpage - 1); + END; + END; + ELSE + WriteString('Error in final TeX page!'); WriteLn; + Halt(error); + END; + END; + IF firstDVIpage > finalDVIpage THEN + WriteString('First page > final page!'); WriteLn; Halt(error); + ELSIF firstDVIpage > totalpages THEN + WriteString('First page > total number of pages!'); WriteLn; Halt(error); + END; + (* allow user to give a final page > totalpages *) + IF finalDVIpage > totalpages THEN finalDVIpage := totalpages END; +END; +END CheckPageRange; + +(******************************************************************************) + +PROCEDURE ParseTeXPage (VAR pagestring : ARRAY OF CHAR; + 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. +*) + +VAR pos, len : CARDINAL; + +BEGIN +WITH newTeXpage DO + pos := 0; + IF pagestring[pos] <> '[' THEN + WriteString('[ expected!'); WriteLn; + RETURN FALSE; + END; + lastvalue := 0; + len := LEN(pagestring); + LOOP + INC(pos); + present[lastvalue] := GetInteger(pagestring, len, pos, value[lastvalue]); + (* pos now at len, space, period, non-digit or ']' *) + WHILE (pos < len) AND (pagestring[pos] = ' ') DO + INC(pos); (* skip any spaces *) + END; + IF pos = len THEN (* check this first! *) + WriteString('] expected!'); WriteLn; + RETURN FALSE; + END; + IF pagestring[pos] = ']' THEN (* end of TeX page specification *) + EXIT; + END; + IF lastvalue < 9 THEN + INC(lastvalue); + ELSE + WriteString("] expected after 10 integers!"); WriteLn; + RETURN FALSE; + END; + IF pagestring[pos] <> '.' THEN + WriteString('Period, integer or ] expected!'); WriteLn; + RETURN FALSE; + END; + END; + WHILE (lastvalue > 0) AND (NOT present[lastvalue]) DO + DEC(lastvalue); + END; +END; +RETURN TRUE; +END ParseTeXPage; + +(******************************************************************************) + +PROCEDURE GetInteger (VAR str : ARRAY OF CHAR; (* in *) + strlen : CARDINAL; (* in *) + VAR pos : CARDINAL; (* 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. +*) + +CONST limit = 2147483647; (* 2^31 - 1 *) + threshold = limit DIV 10; (* nearing overflow *) + +VAR absval, last : CARDINAL; + sign : INTEGER; + inttoobig : BOOLEAN; + +BEGIN +WHILE (pos < strlen) AND (str[pos] = ' ') DO (* skip any spaces *) + INC(pos); +END; +absval := 0; sign := 1; last := pos; +inttoobig := FALSE; +IF pos < strlen THEN + IF str[pos] = '-' THEN + sign := -1; INC(last); + ELSIF str[pos] = '+' THEN + INC(last); + END; + WHILE (last < strlen) AND + (str[last] >= '0') AND (str[last] <= '9') DO + IF (absval > threshold) OR ((absval = threshold) AND (str[last] > '7')) + THEN + inttoobig := TRUE; + ELSE + absval := absval * 10 + (ORD(str[last]) - ORD('0')); + END; + INC(last); + END; +END; +IF pos = last THEN + n := 0; + RETURN FALSE; +ELSE + pos := last; + IF inttoobig THEN absval := limit END; + n := sign * INTEGER(absval); + RETURN TRUE; +END; +END GetInteger; + +(******************************************************************************) + +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 +INC(pagecount); +WriteCard(currDVIpage); (* show the current DVI page *) +Write('/'); ShowTeXPage; (* and TeX page *) +WriteLn; + +BeginPage(currDVIpage); +InterpretPage; (* MyPixelTableRoutine calls NewBitmapFont *) +IF pageempty THEN + OutputPage(currDVIpage); (* must be called even if no chars/rules *) + DoSpecials; +ELSE + (* check that the page edges are within the paper edges *) + IF (minhp < paperleft) OR (minvp < papertop) OR + (maxhp > paperright) OR (maxvp > paperbottom) THEN + PageOffPaper; + END; + (* 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; + END; + OutputPage(currDVIpage); + DoSpecials; + DoFonts; + DoRules; +END; +EndPage(currDVIpage); (* final PostScript for current page *) +END DoPage; + +(******************************************************************************) + +PROCEDURE ShowTeXPage; + +(* Show current TeX page counter(s). *) + +VAR i, lastnonzero : CARDINAL; + +BEGIN +Write('['); +lastnonzero := 9; +WHILE (lastnonzero > 0) AND (currTeXpage[lastnonzero] = 0) DO + DEC(lastnonzero); (* find last counter with non-zero value *) +END; +(* always show \count0 but don't show trailing 0 counters *) +FOR i := 0 TO lastnonzero DO + WriteInt(currTeXpage[i]); + IF i <> lastnonzero THEN + Write('.'); + END; +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 +INC(warncount); +WriteString('Page off paper (paper is '); +ShowDimension(paperwd); WriteString(' wide by '); +ShowDimension(paperht); WriteString(' high)'); +WriteLn; +IF minhp < paperleft THEN + WriteString('Beyond left edge by '); + ShowDimension(paperleft - minhp); + WriteLn; +END; +IF maxhp > paperright THEN + WriteString('Beyond right edge by '); + ShowDimension(maxhp - paperright); + WriteLn; +END; +IF minvp < papertop THEN + WriteString('Above top edge by '); + ShowDimension(papertop - minvp); + WriteLn; +END; +IF maxvp > paperbottom THEN + WriteString('Below bottom edge by '); + ShowDimension(maxvp - paperbottom); + WriteLn; +END; +END PageOffPaper; + +(******************************************************************************) + +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 : CARDINAL; (* 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 + (* do nothing if resident PostScript font or bitmapped font doesn't exist *) + IF (NOT psfont) AND fontexists THEN + fontopen := FALSE; (* avoid opening font unnecessarily *) + thischarinfo := charlist; + WHILE thischarinfo <> NIL DO (* process unloaded chars in chartable *) + WITH thischarinfo^ DO + thischar := 0; + WHILE thischar < charcount DO + WITH chartable[thischar] DO + WITH pixelptr^[code] DO + IF (NOT loaded) AND (mapadr > 0) THEN (* load bitmap *) + IF NOT fontopen THEN + OpenFont(thisfontinfo); + BeginBitmapFont(fontid); + fontopen := TRUE; (* only open once *) + END; + LoadBitmap(thisfontinfo,code); + loaded := TRUE; (* only load once *) + END; + END; + END; + INC(thischar); + END; + thischarinfo := nextchar; + END; + END; + IF fontopen THEN CloseFontFile END; + END; + thisfontinfo := nextfont; +END; (* WITH *) +END; (* WHILE *) +END LoadFonts; + +(******************************************************************************) + +PROCEDURE OpenFont (thisfontinfo : fontinfoptr); + +BEGIN +WITH thisfontinfo^ DO + IF OpenFontFile(fontspec) THEN + (* DEBUG + WriteString("Loading characters for "); + WriteString(fontspec); + WriteLn; + GUBED *) + ELSE + (* this should never happen since we avoid loading dummy font chars *) + WriteLn; + WriteString('Bug in OpenFont! Could not open: '); + WriteString(fontspec); + WriteLn; Halt(error); + END; +END; +END OpenFont; + +(******************************************************************************) + +PROCEDURE DoSpecials; + +(* Call OutputSpecial for each \special command on the current page. + (The speciallist is built by MySpecialRoutine during InterpretPage.) +*) + +VAR temp : specialinfoptr; + +BEGIN +WHILE speciallist <> NIL DO + WITH speciallist^ DO + (* 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 + INC(warncount); + WriteString("Couldn't open \special file: "); + WriteString(special); (* includes optional text *) + WriteLn; + ELSIF stats THEN + WriteString('\special command at ('); + ShowDimension(hp); Write(','); + ShowDimension(vp); WriteString('): '); + WriteString(special); WriteLn; + END; + temp := speciallist; + speciallist := nextspecial; + DISPOSE(temp); (* speciallist must be NIL for next page *) + END; +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. + See PSWRITER.DEF for details. +*) + +VAR + thisfontinfo : fontinfoptr; (* current font info in fontlist *) + thischarinfo : charinfoptr; (* current char info in charlist *) + thischar : CARDINAL; (* current index into current chartable *) + +BEGIN +thisfontinfo := fontlist; +WHILE thisfontinfo <> unusedfont DO +(* SortFonts makes sure we only consider used fonts! *) +WITH thisfontinfo^ DO + IF fontexists THEN (* won't be dummy font info *) + IF psfont THEN + BeginPostScriptFont(fontname,scaledsize,mag); + ELSE + IF conserveVM THEN SaveVM(fontid) END; + BeginBitmapFont(fontid); + END; + + IF conserveVM AND (NOT psfont) THEN (* download bitmaps *) + OpenFont(thisfontinfo); + thischarinfo := charlist; + WHILE thischarinfo <> NIL DO (* process unique chars *) + WITH thischarinfo^ DO + thischar := 0; + WHILE thischar < charcount DO + WITH chartable[thischar] DO + WITH pixelptr^[code] DO + IF (NOT loaded) AND (mapadr > 0) THEN (* load bitmap *) + LoadBitmap(thisfontinfo,code); + loaded := TRUE; (* but only once *) + END; + END; + END; + INC(thischar); + END; + thischarinfo := nextchar; + END; + END; + CloseFontFile; + (* reset loaded flags to FALSE for next page *) + FOR thischar := 0 TO maxTeXchar DO + pixelptr^[thischar].loaded := FALSE; + END; + END; + + IF psfont THEN + thischarinfo := charlist; + WHILE thischarinfo <> NIL DO + WITH thischarinfo^ DO + thischar := 0; + WHILE thischar < charcount DO + WITH chartable[thischar] DO + WITH pixelptr^[code] DO + IF mapadr > 0 THEN (* char exists *) + SetPostScriptChar(CHR(code), + hp,vp, (* reference point *) + pwidth); (* advance width *) + END; + END; + END; + INC(thischar); + END; + thischarinfo := nextchar; + END; + END; + ELSE + thischarinfo := charlist; + WHILE thischarinfo <> NIL DO + WITH thischarinfo^ DO + thischar := 0; + WHILE thischar < charcount DO + WITH chartable[thischar] DO + WITH pixelptr^[code] DO + IF mapadr > 0 THEN (* char exists *) + SetBitmapChar(CHR(code), + hp,vp, (* reference point *) + pwidth); (* advance width *) + END; + END; + END; + INC(thischar); + END; + thischarinfo := nextchar; + END; + END; + END; + EndFont; + + IF conserveVM AND (NOT psfont) THEN RestoreVM END; + END; + thisfontinfo := nextfont; +END; (* WITH *) +END; (* WHILE *) +END DoFonts; + +(******************************************************************************) + +PROCEDURE DoRules; + +(* Call SetRule for each rule on the current page. *) + +VAR thisrule : CARDINAL; + thisruleinfo : ruleinfoptr; + +BEGIN +thisruleinfo := rulelist; +WHILE thisruleinfo <> NIL DO + WITH thisruleinfo^ DO + thisrule := 0; + WHILE thisrule < rulecount DO + WITH ruletable[thisrule] DO + SetRule(wd,ht, (* width and height of rule *) + hp,vp); (* bottom left corner of rule *) + END; + INC(thisrule); + END; + thisruleinfo := nextrule; + END; +END; +END DoRules; + +(******************************************************************************) + +PROCEDURE ShowPageStats; + +(* Show rule/font/character statistics for current page. *) + +VAR fontcount : CARDINAL; + thisfontinfo : fontinfoptr; + +BEGIN +WriteString('Total rules on current page = '); WriteCard(totalrules); +WriteLn; +WriteString('Fonts on current page:'); +WriteLn; +fontcount := 0; +thisfontinfo := fontlist; +WHILE thisfontinfo <> NIL DO + WITH thisfontinfo^ DO + IF fontused THEN + WriteString(fontspec); + IF psfont THEN ShowPtSize(scaledsize) END; + IF NOT fontexists THEN WriteString(' DOES NOT EXIST!') END; + INC(fontcount); + WriteString(' total chars = '); WriteCard(totalchars); WriteLn; + END; + thisfontinfo := nextfont; + END; +END; +WriteString('Total fonts on current page = '); WriteCard(fontcount); +WriteLn; +WriteLn; +END ShowPageStats; + +(******************************************************************************) + +PROCEDURE ShowFinalStats; + +(* Show some overall statistics. *) + +VAR fontsused, c, loadcount, loadtotal, bitmapbytes : CARDINAL; + thisfontinfo : fontinfoptr; + +BEGIN +WriteString('Summary'); WriteLn; +WriteString('======='); WriteLn; +WriteLn; +WriteString('Total pages output = '); WriteCard(pagecount); +WriteLn; +WriteString('Total pages in DVI file = '); WriteCard(totalpages); +WriteLn; +WriteString('Total fonts in DVI file = '); WriteCard(totalfonts); +WriteLn; +(* go thru fontlist showing info for EVERY font *) +fontsused := 0; +loadtotal := 0; +bitmapbytes := 0; +thisfontinfo := fontlist; +WHILE thisfontinfo <> NIL DO + WITH thisfontinfo^ DO + IF fontspeclen > 0 THEN + WriteString(fontspec); + IF psfont THEN ShowPtSize(scaledsize) END; + IF fontexists THEN + INC(fontsused); + IF (NOT conserveVM) AND (NOT psfont) THEN + loadcount := 0; + FOR c := 0 TO maxTeXchar DO + WITH pixelptr^[c] DO + IF loaded AND (mapadr > 0) THEN + INC(loadcount); + INC(bitmapbytes, ht * ((wd + 7) DIV 8) ); + END; + END; + END; + WriteString(' loaded chars = '); WriteCard(loadcount); + INC(loadtotal,loadcount); + END; + ELSE + WriteString(' DOES NOT EXIST!'); + END; + ELSE + WriteString(fontname); + WriteString(' scaled '); + WriteCard(TRUNC( FLOAT(mag) * + FLOAT(scaledsize)/FLOAT(designsize) + 0.5 )); + WriteString(' not used'); + END; + WriteLn; + thisfontinfo := nextfont; + END; +END; +WriteString('Total fonts actually used = '); WriteCard(fontsused); +WriteLn; +IF NOT conserveVM THEN + WriteString('Total characters loaded = '); WriteCard(loadtotal); + WriteLn; + WriteString('Hex digits in loaded bitmaps = 2 * '); WriteCard(bitmapbytes); + WriteLn; +END; +END ShowFinalStats; + +(******************************************************************************) + +PROCEDURE ShowPtSize (scaledsize : INTEGER); + +(* Show given font size (in DVI units) in terms of (possibly magnified) pts. *) + +VAR realdim : REAL; fracpart : CARDINAL; + +BEGIN +WriteString(' at '); +realdim := (FLOAT(scaledsize) / FLOAT(10000H)) * (FLOAT(mag) / 1000.0); +(* show realdim to an accuracy of 1 decimal place *) +IF ABS(realdim) < 0.05 THEN + WriteString('0'); +ELSE + IF realdim < 0.0 THEN + Write('-'); + realdim := ABS(realdim); + END; + realdim := realdim + 0.05; (* round up to 1 decimal place *) + WriteCard(TRUNC(realdim)); (* whole part *) + fracpart := TRUNC((realdim - FLOAT(TRUNC(realdim))) * 10.0); (* 0..9 *) + IF fracpart > 0 THEN + Write('.'); + WriteCard(fracpart); + END; +END; +WriteString('pt'); +END ShowPtSize; + +(******************************************************************************) + +BEGIN +TopLevel; +END PSDVI. diff --git a/dviware/psprint/vms/psfonts.tex b/dviware/psprint/vms/psfonts.tex new file mode 100644 index 0000000000..6df7ba02d4 --- /dev/null +++ b/dviware/psprint/vms/psfonts.tex @@ -0,0 +1,71 @@ +% This TeX source file illustrates the use (and abuse) of PostScript fonts. + +\input psnames % defines macros for names of PostScript fonts used by PSPRINT +\input pstext % defines \PStext and \CMtext + +\nopagenumbers +\parindent=0pt +\parskip=\bigskipamount + +The following fonts should be available in all PostScript printers: + +\font\cour=\Courier at 10pt +\font\courb=\CourierB at 10pt +\font\couro=\CourierO at 10pt +\font\courbo=\CourierBO at 10pt +\font\helv=\Helv at 10pt +\font\helvb=\HelvB at 10pt +\font\helvo=\HelvO at 10pt +\font\helvbo=\HelvBO at 10pt +\font\ts=\TimesS at 10pt +\font\tr=\TimesR at 10pt +\font\tb=\TimesB at 10pt +\font\ti=\TimesI at 10pt +\font\tbi=\TimesBI at 10pt +\font\sy=\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=\TimesR at 12pt +\font\trB=\TimesR at 20.5pt +\font\trC=\TimesR at 144pt + +\bigskip +\leftline{\trA Times-Roman at 12pt} +\leftline{\trB Times-Roman at 20.5pt} +\leftline{\trC At 144pt} + +\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 % \t, \aa, \AA and \j will generate error messages +\CMtext + +\rm +A PostScript font usually appears {\tr darker and larger} than +an ``equivalent'' Computer Modern font. + +\bye diff --git a/dviware/psprint/vms/psnames.tex b/dviware/psprint/vms/psnames.tex new file mode 100644 index 0000000000..f715278d9f --- /dev/null +++ b/dviware/psprint/vms/psnames.tex @@ -0,0 +1,41 @@ +% Macros for PostScript TFM names used by PSPRINT under VAX/VMS. +% The space after the TFM name allows users to do things like +% "\font\hugetr=\TimesR at 50pt". +% This file should be put into TeX's default input directory. +% +\def\Symbol {ps-symbol } % Symbol +\def\Courier {ps-courier } % Courier +\def\CourierB {ps-courier-b } % Courier-Bold +\def\CourierO {ps-courier-o } % Courier-Oblique +\def\CourierBO {ps-courier-bo } % Courier-BoldOblique +\def\Helv {ps-helv } % Helvetica +\def\HelvB {ps-helv-b } % Helvetica-Bold +\def\HelvO {ps-helv-o } % Helvetica-Oblique +\def\HelvBO {ps-helv-bo } % Helvetica-BoldOblique +\def\TimesR {ps-times-r } % Times-Roman +\def\TimesS {ps-times-s } % Times-Slanted +\def\TimesB {ps-times-b } % Times-Bold +\def\TimesI {ps-times-i } % Times-Italic +\def\TimesBI {ps-times-bi } % Times-BoldItalic +\def\AvantB {ps-avantg-b } % AvantGarde-Book +\def\AvantBO {ps-avantg-bo } % AvantGarde-BookOblique +\def\AvantD {ps-avantg-d } % AvantGarde-Demi +\def\AvantDO {ps-avantg-do } % AvantGarde-DemiOblique +\def\BookD {ps-bookman-d } % Bookman-Demi +\def\BookDI {ps-bookman-di } % Bookman-DemiItalic +\def\BookL {ps-bookman-l } % Bookman-Light +\def\BookLI {ps-bookman-li } % Bookman-LightItalic +\def\HelvN {ps-helv-n } % Helvetica-Narrow +\def\HelvNB {ps-helv-nb } % Helvetica-Narrow-Bold +\def\HelvNO {ps-helv-no } % Helvetica-Narrow-Oblique +\def\HelvNBO {ps-helv-nbo } % Helvetica-Narrow-BoldOblique +\def\NCSR {ps-ncs-r } % NewCenturySchlbk-Roman +\def\NCSB {ps-ncs-b } % NewCenturySchlbk-Bold +\def\NCSI {ps-ncs-i } % NewCenturySchlbk-Italic +\def\NCSBI {ps-ncs-bo } % NewCenturySchlbk-BoldItalic +\def\PalR {ps-pal-r } % Palatino-Roman +\def\PalB {ps-pal-b } % Palatino-Bold +\def\PalI {ps-pal-i } % Palatino-Italic +\def\PalBI {ps-pal-bi } % Palatino-BoldItalic +\def\ZapfChMI {ps-zapfch-mi } % ZapfChancery-MediumItalic +\def\ZapfD {ps-zapfdb } % ZapfDingbats diff --git a/dviware/psprint/vms/psprint.cld b/dviware/psprint/vms/psprint.cld new file mode 100644 index 0000000000..e34844f7c2 --- /dev/null +++ b/dviware/psprint/vms/psprint.cld @@ -0,0 +1,95 @@ +define verb PSPRINT +image TEX_PS:PSPRINT.EXE + parameter p1,label=filespec,prompt="File",value(required,type=$infile) + qualifier prep, value(type=$infile,default="TEX_PS:LASERPREP70.PS") + qualifier output, value(required,type=$infile) ! default is print + qualifier landscape, nonnegatable ! default is portrait +! +! User can override the selection of file format based on file extension: +! + qualifier dvi, nonnegatable + qualifier ps, nonnegatable + qualifier text, nonnegatable + qualifier two, nonnegatable + qualifier wide, nonnegatable + disallow any2(dvi,ps,text,two,wide) +! +! PSPRINT only provides a few of the normal PRINT qualifiers: +! + qualifier delete, ! default is /NODELETE + qualifier notify, ! default is /NONOTIFY + qualifier copies, value(required,type=$number) ! default is 1 + qualifier note, value(required) + qualifier form, value(required) + qualifier queue, value(required) +! +! We currently do not use different forms. Other sites might want to use +! /FORM to handle transparencies, manual feeding, proof/final copy, etc: +! + disallow form +! +! Here are the allowed PSDVI qualifiers (default values are set in PSDVI.CLD): +! + qualifier pages, nonnegatable,value(required) + qualifier increment, nonnegatable,value(required,type=$number) + qualifier magnification, nonnegatable,value(required,type=$number) + qualifier resolution, nonnegatable,value(required,type=$number) + qualifier units, nonnegatable,value(required) + qualifier hoffset, nonnegatable,value(required) + qualifier voffset, nonnegatable,value(required) + qualifier xsize, nonnegatable,value(required) + qualifier ysize, nonnegatable,value(required) + qualifier psprefix, nonnegatable,value(required) + qualifier tfm_directory, nonnegatable,value(required) + qualifier font_directory, nonnegatable,value(required) + qualifier dummy_font, nonnegatable,value(required) + qualifier stats, +! +! The /CONSERVE_VM and /REVERSE qualifiers are handled differently because +! we want PSPRINT to use default settings that depend on the /DEVICE value: +! + qualifier conserve_vm, nonnegatable + qualifier noconserve_vm, nonnegatable + disallow conserve_vm and noconserve_vm +! + qualifier reverse, nonnegatable + qualifier noreverse, nonnegatable + disallow reverse and noreverse +! +! +! PSPRINT runs a different command file for each different PostScript device: +! + qualifier device, nonnegatable,default,value(type=psprinter,required) +! +! This qualifier is only relevant if /DEVICE=LW or LINO: +! + qualifier banner, default ! default is print banner page +! +! This qualifier is only relevant if /DEVICE=LW: +! + qualifier manualfeed, nonnegatable ! default is auto feed +! +! These qualifiers are only relevant if /DEVICE=LINO: +! + qualifier cutmarks, default ! default is do them + qualifier lowres, nonnegatable ! default is high-res + qualifier size, nonnegatable,default,value(type=pagesize,required) +! +! The Linotronic supports a number of different page sizes and orientations. +! The /SIZE values defined below are used in LINO_PRINT.COM: +! +define type pagesize + keyword A3L ! A3 page size with landscape orientation + keyword A4P, default ! A4 page size with portrait orientation + keyword A4L ! A4 page size with landscape orientation + keyword A5P ! A5 page size with portrait orientation + keyword A5L ! A5 page size with landscape orientation + keyword B5P ! B5 page size with portrait orientation + keyword B5L ! B5 page size with landscape orientation +! +! Here are the different /DEVICE values currently supported: +! +define type psprinter + keyword LW , default ! LaserWriter + keyword LINO ! Linotronic 300 + keyword PS40 ! PrintServer 40 diff --git a/dviware/psprint/vms/psprint.hlp b/dviware/psprint/vms/psprint.hlp new file mode 100644 index 0000000000..f80a58e9d0 --- /dev/null +++ b/dviware/psprint/vms/psprint.hlp @@ -0,0 +1,438 @@ +1 PSPRINT + +USAGE: PSPRINT file [qualifiers] + +The PSPRINT command 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. + +To print your own copy of the "PSPRINT User Guide" just type: + + $ PSPRINT TEX_PS:USERGUIDE + +2 TeX_Output + +PSPRINT looks for a DVI file by default. To print FOO.DVI, simply type: + + $ PSPRINT FOO + +PSPRINT first translates FOO.DVI into a temporary PostScript file called +FOO.TMP. The order in which pages are translated depends on the printer +(the default order can be overridden by the /REVERSE or /NOREVERSE options). +If no errors are found, FOO.TMP is sent to an appropriate queue +where it is printed (and then deleted). + +2 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 +qualifier. 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. + +2 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 /LANDSCAPE qualifier 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. + +The /TWO and /WIDE qualifiers also print text files but format the +output so that two "pages" appear on each sheet of paper; each page +has a header line showing the file name and page number. +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. + +2 Errors + +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 banner page. +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_VM. + - On a Linotronic, try using /LOWRES. + (Note that /CONSERVE_VM is the default for this device.) + +If you are sending your own PostScript program then an error should +produce some sort of message on the printed output. +If you are using a PrintServer 40 then specify /NOTIFY to get all +PostScript messages sent back to your terminal. + +2 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. + +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. + +2 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 write +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. + +2 Qualifiers + +/DEVICE=printer_type + +This qualifier 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, +along with a header line showing the file name and page number. + +/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, +along with a header line showing the file name and page number. + +/BANNER +(only if /DEVICE=LW or LINO) + +By default PSPRINT produces a banner page for each job sent to +a LaserWriter or Linotronic. Use /NOBANNER if you don't want such a page. + +/MANUALFEED +(only if /DEVICE=LW) + +Use this qualifier 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 /DEVICE=LINO) + +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_size +(only if /DEVICE=LINO) + +This qualifier 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 /LANDSCAPE which rotates +the output within the page image, regardless of the /SIZE value.) + +/CUTMARKS +(only if /DEVICE=LINO) + +This qualifier 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. + +/CONSERVE_VM +(only for a DVI file) + +Use /CONSERVE_VM 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). If /DEVICE=LINO then /CONSERVE_VM is the default; +if /DEVICE=LW or PS40 then /NOCONSERVE_VM is the default. + +/PAGES=first:final +(only for a DVI file) + +Print a selected subrange from the DVI file. "first" and "final" can +select either DVI page numbers (positive integers) or TeX page numbers. +Assuming TeX generated the 5 pages `[0] [1] [2.1] [2.2] [3]', here are some +examples of how you could use /PAGES: + + $ PSPRINT FOO /PAGES=2 --- prints the 2nd DVI page (as would [1]) + $ PSPRINT FOO /PAGES=4: --- prints the last two pages + $ PSPRINT FOO /PAGES=:4 --- prints the first four pages + $ PSPRINT FOO /PAGES=[2] --- prints [2.1] and [2.2] + $ PSPRINT FOO /PAGES=1:[2] --- prints the first four pages + $ PSPRINT FOO /PAGES=[2.2]: --- prints the last two pages + +Note 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. Many DVI pages 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. + +/INCREMENT=i +(only for a DVI file) + +Assuming f is the first DVI page selected (where f is either 1 or the start +of a /PAGES 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 /INCREMENT 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 /INC=2 /REV /NOBANNER ! prints DVI pages 7, 5, 3, 1 + + 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 /INC=2 /PAG=2: /NOREV ! prints DVI pages 2, 4, 6, 8 + +Note that the use of /REVERSE with /INCREMENT has no effect on WHICH pages +are printed; it simply changes the ORDER in which they are done. + +If you intend doing a lot of two-sided printing then it is a good idea to +define some symbols in your LOGIN.COM file to avoid making mistakes: + + $ ODDPAGES :== PSPRINT/PAG=1:/INC=2/REV/NOBANNER + $ EVENPAGES :== PSPRINT/PAG=2:/INC=2/NOREV + +/REVERSE +(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. /NOREVERSE is the default for all devices +currently supported by PSPRINT. + +/MAGNIFICATION=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. + +/UNITS=xx +(only for a DVI file) + +Set the units of dimensions displayed in some PSPRINT messages +(e.g., if the page is off the paper). "xx" can be one of: + + 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 (depends on resolution of printer) + +/STATS +(only for a DVI file) + +Display statistics on the rules, fonts, characters and \special commands +used on each page. + +/RESOLUTION=i +(only for a DVI file) + +i is a positive integer specifying the resolution of your printer +in pixels per inch (horizontally and vertically). + +/HOFFSET=dimension +/VOFFSET=dimension +(only for a DVI file) + +These qualifiers allow you to shift the printed location of each page +according to the given dimensions. For example, "/hoffset=-0.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 /UNITS). + +/XSIZE=posdimen +/YSIZE=posdimen +(only for a DVI file) + +PSPRINT will automatically check each DVI page to make sure it fits +within the given paper dimensions. +A "posdimen" is any positive integer or real number followed by a +two-letter unit: IN,CM,MM,PC,PT,BP,PX (same as those for /UNITS). + +/PSPREFIX=string +(only for a DVI file) + +PSPRINT needs to read TFM files if your DVI file uses printer-resident +PostScript fonts (for which bitmapped information does not exist). +All such fonts must have names beginning with the given prefix. + +/TFM_DIRECTORY=directory +(only for a DVI file) + +Specifies the location of TFM files for printer-resident PostScript fonts. + +/DUMMY_FONT=file +(only for a DVI file) + +This qualifier indicates the naming convention and format of all font files. +The given file must represent an unmagnified font. + +/FONT_DIRECTORY=directory +(only for a DVI file) + +Use this qualifier to override the default directory from which PSPRINT +gets all its character bitmap information. You'll probably never need to +use this facility, but it might come in handy if you are using Metafont +to create your own fonts or modify existing ones. The following commands +tell PSPRINT to first search for fonts in the current directory ([]) before +looking in the default directory (assumed to be TEX_DISK:[TEX.PK]): + + $ DEFINE DIRLIST [],TEX_DISK:[TEX.PK] + $ PSPRINT FOO.DVI /FONT="DIRLIST:" + +Use /STATS to see the default font directory at your site. + +/LANDSCAPE + +To get "landscaped" output. +(Normal output is said to have a "portrait" orientation.) +If given a DVI file, PSPRINT will check each page to make sure it fits +within the rotated paper. + +/DELETE + +To delete the input file after printing. + +/NOTIFY + +To be notified when the print job has finished. +On the PrintServer 40 you'll also see any PostScript messages, +a particularly useful feature when debugging a PostScript program. + +/COPIES=number + +To specify up to 100 copies. +Use of this facility is not encouraged. Note in particular that +copies of a multiple-page document will NOT be collated. + +/NOTE=string + +To include a note on your banner page. For example, to get your output +put in box 99, just type `PSPRINT /NOTE="BOX 99" ...'. + +/QUEUE=string + +To override the default queue used by PSPRINT. +(Some sites may have more than one printer of the same type.) + +/OUTPUT=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. + +/PREP=file +(only for a DVI or PS file) + +To include a modified Laser Prep file that will allow you to send +PostScript files created on a Macintosh by the Command-F method. +If you just type /PREP then a default file (TEX_PS:LASERPREP70.PS) will +be used. diff --git a/dviware/psprint/vms/psprint.mod b/dviware/psprint/vms/psprint.mod new file mode 100644 index 0000000000..80661b1e23 --- /dev/null +++ b/dviware/psprint/vms/psprint.mod @@ -0,0 +1,603 @@ +MODULE PSPRINT; + +(* Author: Andrew Trevorrow + Implementation: University of Hamburg Modula-2 under VAX/VMS version 4.x + Date Started: July, 1986 + Released: September, 1986 (version 1.0) + + Description: + PSPRINT can print a variety of file formats on a range of PostScript + printers. See the PSPRINT User Guide and System Guide for more details. + Much of the command line parsing is done by DCL according to PSPRINT.CLD. + Most of the semantic checking is done here. If everything seems okay then + we run a device-specific command file. + + If /DEVICE=LW then we do @TEX_PS:LW_PRINT P1 P2 P3 P4 P5 P6 P7 P8 + where + P1 = complete file specification + P2 = file format (DVI or PS or TEXT or TWO or WIDE) + P3 = options for PSDVI + P4 = options for PRINT + P5 = /NOTE value ("" if not used) + P6 = /COPIES value (1 if not used) + P7 = /OUTPUT value ("" if not used) + P8 = "bbbb<prep>" where b = Y or N and represents the status of the + boolean qualifiers /DELETE, /LANDSCAPE, /BANNER, /MANUALFEED + and <prep> is the /PREP value + + If /DEVICE=PS40 then we do @TEX_PS:PS40_PRINT P1 P2 P3 P4 P5 P6 P7 P8 + where P1 to P7 are as above but + P8 = "bb<prep>" where b = Y or N and represents the status of the + boolean qualifiers /DELETE, /LANDSCAPE + and <prep> is the /PREP value + + If /DEVICE=LINO then we do @TEX_PS:LINO_PRINT P1 P2 P3 P4 P5 P6 P7 P8 + where P1 to P7 are as above but + P8 = "bbbbbsss<prep>" where b = Y or N and represents the status of the + boolean qualifiers /DELETE, /LANDSCAPE, /CUTMARKS, /LOWRES, /BANNER + and sss = /SIZE value (PSPRINT.CLD defines legal values and default) + and <prep> is the /PREP value + + Note that DCL allows a maximum of 8 parameters, so a lot of information + has to be packed into P8. + + Revised: + January, 1987 + - The /REVERSE qualifier is no longer used. The order in which DVI pages + are translated (by PSDVI) is best left specified in the COM file. + (Note that /NOREVERSE on PSPRINT never actually worked!) + - Released version 1.1 in January, 1987 + + November, 1987 (while at The Open University) + - Added /DEVICE qualifier. PSPRINT needs to run a different command file + for each type of PostScript printer currently supported. + - Added /CONSERVE_VM and /NOCONSERVE_VM qualifiers. If neither is present + then a default setting is used that depends on the /DEVICE value. + - Added Linotronic-specific qualifiers (/CUTMARKS, /LOWRES, /SIZE). + These are simply ignored if /DEVICE does not equal LINO. + - Released version 2.0 in December, 1987 + + June--August, 1988 (while at Aston University) + - Added /QUEUE qualifier for sites with more than one printer. + - Added /BANNER and /MANUALFEED qualifiers for LW. + - Added /TWO and /WIDE text formats. + - Added /OUTPUT qualifer so user can save PostScript output in a given file + rather than send it to a print queue. + - The /REVERSE qualifier is back in again! It is treated like /CONSERVE_VM. + - Added /INCREMENT qualifier to simplify both-sided printing. + - Added /FONT_DIRECTORY qualifier to allow users to override the default + font directory used by PSDVI. This could be handy for Metafont users. + - Added more PSDVI qualifiers: /HOFFSET, /VOFFSET, /XSIZE, /YSIZE, + /RESOLUTION, /PSPREFIX, /TFM_DIRECTORY and /DUMMY_FONT. + Most users will never need to use any of these. + - All these new qualifiers have required some reorganisation of the + parameters passed into the various command files. + - Released version 3.0 in August, 1988 + + September--October, 1989 (while at Aston University, 2nd time) + - Added /BANNER qualifier for LINO. + - Added /PREP qualifier so user can include a modified Laser Prep. + - /REVERSE and /CONSERVE_VM defaults are now specified in the + device-specific COM files. + - Released version 3.1 in October, 1989 +*) + +FROM VMS IMPORT + SYS$EXIT; + +FROM CommandLanguageInterface IMPORT + CLI$PRESENT, CLI$GET_VALUE; + +FROM CommonInputOutputProcedures IMPORT + LIB$DO_COMMAND; + +FROM FileSystem IMPORT + File, Open, Name, Done, Close; + +FROM InOut IMPORT + Write, WriteString, WriteLn; + + +CONST + NULL = 0C; (* SYSDEP: terminates a non-full string *) + +TYPE + string = ARRAY [0..79] OF CHAR; + +VAR + filespec, ext, device, value : string; + status : CARDINAL; + f : File; + command : ARRAY [0..255] OF CHAR; + format : (dvifile,psfile,textfile,twofile,widefile); + printer : (LINO,LW,PS40); + + +(******************************************************************************) + +PROCEDURE GetValue (qualifier : ARRAY OF CHAR; + VAR s : ARRAY OF CHAR) : BOOLEAN; + +(* GetValue should only be called for those qualifiers that have a value. + If given qualifier is present then we get value and return TRUE, + otherwise FALSE. +*) + +VAR i, status : CARDINAL; + +BEGIN +IF ODD(CLI$PRESENT(qualifier)) THEN + status := CLI$GET_VALUE(qualifier,s); (* PSPRINT.CLD ensures value *) + i := HIGH(s); + WHILE (i > 0) AND (s[i] = ' ') DO (* remove trailing blanks *) + s[i] := NULL; (* SYSDEP: pad with NULLs *) + DEC(i); + END; + RETURN TRUE; +ELSE + s[0] := NULL; + RETURN FALSE; +END; +END GetValue; + +(******************************************************************************) + +PROCEDURE ExplicitExt (fname : ARRAY OF CHAR; + VAR ext : ARRAY OF CHAR) : BOOLEAN; + +(* SYSDEP: VAX/VMS files have an extension of the form ".xxx...xxx;version". + If the given file specification contains an extension then + TRUE is returned (and ext will be string after '.' but before any ';'). +*) + +VAR i, l, pos : CARDINAL; ch : CHAR; + +BEGIN +pos := LEN(fname); +l := pos; +ext[0] := NULL; +WHILE pos > 0 DO (* search backwards looking for . or : or ] *) + DEC(pos); + ch := fname[pos]; + IF ch = '.' THEN (* extract extension *) + i := 0; + INC(pos); + WHILE (pos <= HIGH(fname)) + AND (fname[pos] <> NULL) AND (fname[pos] <> ';') DO + ext[i] := fname[pos]; + INC(i); INC(pos); + END; + IF i <= HIGH(ext) THEN ext[i] := NULL END; + RETURN TRUE; + ELSIF (ch = ':') OR (ch = ']') THEN (* don't need to look further *) + RETURN FALSE; + END; +END; +RETURN FALSE; +END ExplicitExt; + +(******************************************************************************) + +PROCEDURE Append (VAR s1 : ARRAY OF CHAR; s2 : ARRAY OF CHAR); + +(* Append s2 to s1. *) + +VAR i, j : CARDINAL; + +BEGIN +i := LEN(s1); +j := 0; +WHILE (i <= HIGH(s1)) AND (j <= HIGH(s2)) AND (s2[j] <> NULL) DO + s1[i] := s2[j]; + INC(i); + INC(j); +END; +(* check for overflow *) +IF (i > HIGH(s1)) AND (j <= HIGH(s2)) AND (s2[j] <> NULL) THEN + WriteString('No room to append '); WriteString(s2); WriteLn; + ErrorHalt; +END; +IF i <= HIGH(s1) THEN s1[i] := NULL END; +END Append; + +(******************************************************************************) + +PROCEDURE Equal (s1 : ARRAY OF CHAR; s2 : ARRAY OF CHAR) : BOOLEAN; + +(* Return TRUE iff s1 = s2. *) + +VAR i : CARDINAL; + +BEGIN +i := 0; +LOOP + IF (i > HIGH(s1)) OR (s1[i] = NULL) THEN (* end of s1 *) + RETURN (i > HIGH(s2)) OR (s2[i] = NULL); + ELSIF (i > HIGH(s2)) OR (s2[i] = NULL) THEN (* end of s2 *) + RETURN s1[i] = NULL; + ELSIF s1[i] <> s2[i] THEN + RETURN FALSE; + END; + INC(i); +END; +END Equal; + +(******************************************************************************) + +PROCEDURE ErrorHalt; + +(* Call SYS$EXIT with a magic number that will set ERROR status without + causing any spurious CLI message. +*) + +VAR dummy : CARDINAL; + +BEGIN +dummy := SYS$EXIT(10000002H); +END ErrorHalt; + +(******************************************************************************) + +PROCEDURE AppendFilespec; + +BEGIN +IF GetValue('FILESPEC',filespec) THEN + IF NOT ExplicitExt(filespec,ext) THEN (* assume DVI file if no extension *) + Append(filespec,'.DVI'); (* append .DVI *) + format := dvifile; + ELSIF Equal(ext,'DVI') THEN + format := dvifile; + ELSIF Equal(ext,'PS') THEN + format := psfile; (* PostScript file *) + ELSE + format := textfile; (* ordinary text file *) + END; + Open(f,filespec,FALSE); + IF Done() THEN (* given file exists *) + Name(f,filespec); (* full file specification *) + Append(command,filespec); + Close(f); + ELSE + WriteString("Couldn't open "); + WriteString(filespec); Write('!'); WriteLn; + ErrorHalt; + END; +ELSE + (* PSPRINT.CLD should prevent this ever happening, but play safe *) + WriteString('File not given!'); WriteLn; + ErrorHalt; +END; +END AppendFilespec; + +(******************************************************************************) + +PROCEDURE AppendFormat; + +(* /DVI, /PS, /TEXT, /TWO or /WIDE can override the implicit file format. + PSPRINT.CLD should ensure that only one of these is allowed. +*) + +BEGIN +IF ODD(CLI$PRESENT('DVI')) THEN + format := dvifile; +ELSIF ODD(CLI$PRESENT('PS')) THEN + format := psfile; +ELSIF ODD(CLI$PRESENT('TEXT')) THEN + format := textfile; +ELSIF ODD(CLI$PRESENT('TWO')) THEN + format := twofile; +ELSIF ODD(CLI$PRESENT('WIDE')) THEN + format := widefile; +END; +CASE format OF + dvifile : Append(command,' DVI'); + | psfile : Append(command,' PS'); + | textfile : Append(command,' TEXT'); + | twofile : Append(command,' TWO'); + | widefile : Append(command,' WIDE'); +ELSE + WriteString('BUG! Unknown file format!'); WriteLn; + ErrorHalt; +END; +END AppendFormat; + +(******************************************************************************) + +PROCEDURE DVIcheck (qual : ARRAY OF CHAR); + +(* The given qualifier is only allowed with a DVI file. *) + +BEGIN +IF format <> dvifile THEN + WriteString(qual); + WriteString(' is only allowed with a DVI file!'); WriteLn; + ErrorHalt; +END; +END DVIcheck; + +(******************************************************************************) + +PROCEDURE AppendPSDVIoptions; + +(* Check for the PSDVI qualifiers allowed by PSPRINT.CLD. *) + +BEGIN +Append(command,' "'); +IF GetValue('PAGES',value) THEN + DVIcheck('/PAGES'); Append(command,'/PAG='); Append(command,value); +END; +IF GetValue('INCREMENT',value) THEN + DVIcheck('/INC'); Append(command,'/INC='); Append(command,value); +END; +IF GetValue('MAGNIFICATION',value) THEN + DVIcheck('/MAG'); Append(command,'/MAG='); Append(command,value); +END; +IF GetValue('UNITS',value) THEN + DVIcheck('/UNITS'); Append(command,'/UN='); Append(command,value); +END; +IF GetValue('HOFFSET',value) THEN + DVIcheck('/HOFF'); Append(command,'/HOFF='); Append(command,value); +END; +IF GetValue('VOFFSET',value) THEN + DVIcheck('/VOFF'); Append(command,'/VOFF='); Append(command,value); +END; +IF GetValue('XSIZE',value) THEN + DVIcheck('/XSIZE'); Append(command,'/XSIZ='); Append(command,value); +END; +IF GetValue('YSIZE',value) THEN + DVIcheck('/YSIZE'); Append(command,'/YSIZ='); Append(command,value); +END; +IF GetValue('TFM_DIRECTORY',value) THEN + DVIcheck('/TFM'); Append(command,'/TFM='); Append(command,value); +END; +IF GetValue('PSPREFIX',value) THEN + DVIcheck('/PSPRE'); Append(command,'/PSPR='); Append(command,value); +END; +IF GetValue('FONT_DIRECTORY',value) THEN + DVIcheck('/FONT'); Append(command,'/FONT='); Append(command,value); +END; +IF GetValue('DUMMY_FONT',value) THEN + DVIcheck('/DUMMY'); Append(command,'/DUMM='); Append(command,value); +END; +IF GetValue('RESOLUTION',value) THEN + DVIcheck('/RES'); Append(command,'/RES='); Append(command,value); +END; +IF ODD(CLI$PRESENT('STATS')) THEN + DVIcheck('/STATS'); Append(command,'/ST'); +END; +IF ODD(CLI$PRESENT('CONSERVE_VM')) THEN + DVIcheck('/CONS'); Append(command,'/CONS'); +ELSIF ODD(CLI$PRESENT('NOCONSERVE_VM')) THEN + DVIcheck('/NOCONS'); Append(command,'/NOCONS'); +END; +IF ODD(CLI$PRESENT('REVERSE')) THEN + DVIcheck('/REV'); Append(command,'/REV'); +ELSIF ODD(CLI$PRESENT('NOREVERSE')) THEN + DVIcheck('/NOREV'); Append(command,'/NOREV'); +END; +Append(command,'"'); +END AppendPSDVIoptions; + +(******************************************************************************) + +PROCEDURE AppendPRINToptions; + +BEGIN +Append(command,' "'); +IF ODD(CLI$PRESENT('NOTIFY')) THEN (* /NOTIFY given *) + Append(command,'/NOTI'); +ELSE + Append(command,'/NONOTI'); +END; +IF GetValue('FORM',value) THEN (* /FORM=formtype given *) + Append(command,'/FORM='); + Append(command,value); +END; +IF GetValue('QUEUE',value) THEN (* /QUEUE=qname given *) + Append(command,'/QUE='); + Append(command,value); +END; +Append(command,'"'); +END AppendPRINToptions; + +(******************************************************************************) + +PROCEDURE AppendNote; + +VAR i : INTEGER; + +BEGIN +Append(command,' "'); +IF GetValue('NOTE',value) THEN + IF printer = PS40 THEN + (* PrintServer 40 handles any (,),\ characters in /NOTE value *) + Append(command,value); + ELSE + (* For LaserWriter and Linotronic we must + make sure that any (,),\ characters are prefixed with \ + otherwise we'll probably get a PostScript error when storing + the /NOTE value into a string. This kludge should not be necessary + for the other string values that appear on the banner page. + *) + FOR i := 0 TO LEN(value)-1 DO + CASE value[i] OF + '(' : Append(command,'\('); + | ')' : Append(command,'\)'); + | '\' : Append(command,'\\'); + ELSE Append(command,value[i]); + END; + END; + END; +END; +Append(command,'"'); +END AppendNote; + +(******************************************************************************) + +PROCEDURE AppendCopies; + +BEGIN +IF GetValue('COPIES',value) THEN + Append(command,' '); + Append(command,value); +ELSE + Append(command,' 1'); +END; +END AppendCopies; + +(******************************************************************************) + +PROCEDURE AppendOutput; + +BEGIN +IF GetValue('OUTPUT',value) THEN + Append(command,' '); + Append(command,value); +ELSE + Append(command,' ""'); +END; +END AppendOutput; + +(******************************************************************************) + +PROCEDURE AppendPrep; + +BEGIN +IF GetValue('PREP',value) THEN + Append(command,value); +END; +END AppendPrep; + +(******************************************************************************) + +PROCEDURE AppendLWFlags; + +BEGIN +Append(command,' "'); +IF ODD(CLI$PRESENT('DELETE')) THEN + Append(command,'Y'); (* /DELETE *) +ELSE + Append(command,'N'); +END; +IF ODD(CLI$PRESENT('LANDSCAPE')) THEN + Append(command,'Y'); (* /LANDSCAPE *) +ELSE + Append(command,'N'); +END; +IF ODD(CLI$PRESENT('BANNER')) THEN + Append(command,'Y'); (* /BANNER *) +ELSE + Append(command,'N'); +END; +IF ODD(CLI$PRESENT('MANUALFEED')) THEN + Append(command,'Y'); (* /MANUALFEED *) +ELSE + Append(command,'N'); +END; +AppendPrep; (* /PREP *) +Append(command,'"'); +END AppendLWFlags; + +(******************************************************************************) + +PROCEDURE AppendLINOFlags; + +BEGIN +Append(command,' "'); +IF ODD(CLI$PRESENT('DELETE')) THEN + Append(command,'Y'); (* /DELETE *) +ELSE + Append(command,'N'); +END; +IF ODD(CLI$PRESENT('LANDSCAPE')) THEN + Append(command,'Y'); (* /LANDSCAPE *) +ELSE + Append(command,'N'); +END; +IF ODD(CLI$PRESENT('CUTMARKS')) THEN + Append(command,'Y'); (* /CUTMARKS *) +ELSE + Append(command,'N'); +END; +IF ODD(CLI$PRESENT('LOWRES')) THEN + Append(command,'Y'); (* /LOWRES *) +ELSE + Append(command,'N'); +END; +IF ODD(CLI$PRESENT('BANNER')) THEN + Append(command,'Y'); (* /BANNER *) +ELSE + Append(command,'N'); +END; +IF GetValue('SIZE',value) THEN (* /SIZE value *) + Append(command,value); +ELSE + Append(command,'???'); (* PSPRINT.CLD should prevent this *) +END; +AppendPrep; (* /PREP *) +Append(command,'"'); +END AppendLINOFlags; + +(******************************************************************************) + +PROCEDURE AppendPS40Flags; + +BEGIN +Append(command,' "'); +IF ODD(CLI$PRESENT('DELETE')) THEN + Append(command,'Y'); (* /DELETE *) +ELSE + Append(command,'N'); +END; +IF ODD(CLI$PRESENT('LANDSCAPE')) THEN + Append(command,'Y'); (* /LANDSCAPE *) +ELSE + Append(command,'N'); +END; +AppendPrep; (* /PREP *) +Append(command,'"'); +END AppendPS40Flags; + +(******************************************************************************) + +BEGIN +IF GetValue('DEVICE',device) THEN + IF Equal(device,'LW') THEN + printer := LW; + command := '@TEX_PS:LW_PRINT '; + ELSIF Equal(device,'LINO') THEN + printer := LINO; + command := '@TEX_PS:LINO_PRINT '; + ELSIF Equal(device,'PS40') THEN + printer := PS40; + command := '@TEX_PS:PS40_PRINT '; + ELSE + (* PSPRINT.CLD should prevent this ever happening, but play safe *) + WriteString('Unexpected /DEVICE value: '); + WriteString(device); WriteLn; + ErrorHalt; + END; +ELSE + (* PSPRINT.CLD should prevent this ever happening, but play safe *) + WriteString('/DEVICE value not present!'); WriteLn; + ErrorHalt; +END; +AppendFilespec; (* P1 *) +AppendFormat; (* P2 *) +AppendPSDVIoptions; (* P3 *) +AppendPRINToptions; (* P4 *) +AppendNote; (* P5 *) +AppendCopies; (* P6 *) +AppendOutput; (* P7 *) +CASE printer OF (* P8 is device-specific *) + LW : AppendLWFlags; +| LINO : AppendLINOFlags; +| PS40 : AppendPS40Flags; +END; +(* DEBUG +WriteString(command); WriteLn; +GUBED *) +status := LIB$DO_COMMAND(command); +(* we should never get here *) +WriteString('BUG! Error in DO_COMMAND!'); WriteLn; ErrorHalt; +END PSPRINT. diff --git a/dviware/psprint/vms/pstext.tex b/dviware/psprint/vms/pstext.tex new file mode 100644 index 0000000000..4c0f6bf272 --- /dev/null +++ b/dviware/psprint/vms/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/vms/pswriter.def b/dviware/psprint/vms/pswriter.def new file mode 100644 index 0000000000..714564fcac --- /dev/null +++ b/dviware/psprint/vms/pswriter.def @@ -0,0 +1,167 @@ +DEFINITION MODULE PSWriter; + +(* Author: Andrew Trevorrow + Implementation: University of Hamburg Modula-2 under VAX/VMS version 4 + Date Started: August, 1986 + + Description: + These 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 (possibly by /HEADER) to the output: + + OpenOutput + if /HEADER given then OutputHeader end + for each page selected do + BeginPage + if not conserving VM then + for each new bitmap font do NewBitmapFont end + for each bitmap font used on this page do + BeginBitmapFont + for each new character do LoadBitmap end + end + end + OutputPage + for each \special on this page do OutputSpecial end + for each font used on this page do + if (conserving VM) and (not PostScript font) then SaveVM end + if PostScript font then BeginPostScriptFont else BeginBitmapFont end + if (conserving VM) and (not PostScript font) then + for each character used do LoadBitmap end + end + if PostScript font then + for each character used do SetPostScriptChar end + else + for each character used do SetBitmapChar end + end + EndFont + if (conserving VM) and (not PostScript font) then RestoreVM end + end + for each rule on this page do SetRule end + EndPage + end + CloseOutput + + Revised: + December, 1986 + - LoadPSChar has been replaced by LoadBitmap from FontReader. + Various Put routines are now exported so that LoadBitmap can use them + to send PostScript code to the output file. + + November, 1987 (while at The Open University) + - Renamed most routines to make a clear distinction between routines + applicable to bitmap fonts or to resident PostScript fonts. + - Added BeginPostScriptFont to generate appropriate code for switching + to a resident PostScript font. The main module should call this routine + after OutputPage for a font whose psfont flag is TRUE. + - Added SetPostScriptChar to position and show a character from a resident + PostScript font. We cannot use SetBitmapChar because the advance widths + for PostScript fonts are not an integer number of pixels + (and we'd get accumulated rounding errors). + - Added SaveVM and RestoreVM routines. The main module should call these + routines around bitmap fonts when conserving virtual memory. + + June--August, 1988 (while at Aston University) + - EndBitmapFont now called EndFont as it is used for both font types. +*) + +PROCEDURE OpenOutput (name : ARRAY OF CHAR) : BOOLEAN; +(* Return TRUE if given file can be opened for output. *) + +PROCEDURE OutputHeader (name : ARRAY OF CHAR) : BOOLEAN; +(* Return TRUE if given file can be copied to output. + Return FALSE if file could not be opened. +*) + +PROCEDURE BeginPage (DVIpage : CARDINAL); +(* Output some PostScript to indicate the start of a new page. *) + +PROCEDURE NewBitmapFont (VAR fontid : ARRAY OF CHAR); +(* Output some PostScript to define a new bitmap font. + The string parameter is declared to be a variable for efficiency reasons; + PSWriter will never change its value. +*) + +(* Here are the Put routines needed by LoadBitmap in FontReader: *) +PROCEDURE Put (ch : CHAR); +PROCEDURE PutString (s : ARRAY OF CHAR); +PROCEDURE PutInt (i : INTEGER); +PROCEDURE PutCard (c : CARDINAL); + +PROCEDURE OutputPage (DVIpage : CARDINAL); +(* Output some PostScript to prepare showing specials, chars and rules on + the current page. +*) + +TYPE specialstring = ARRAY [0..255] OF CHAR; + +PROCEDURE OutputSpecial (VAR name : specialstring; + hpos, vpos : INTEGER) : BOOLEAN; +(* Return TRUE if given file can be copied to output. + Return 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. +*) + +PROCEDURE SaveVM (VAR fontid : ARRAY OF CHAR); +(* Output some PostScript to remember the current state of VM just before + downloading the given bitmap font. + The main module should only call this routine if /CONSERVE_VM is given. + The string parameter is declared to be a variable for efficiency reasons; + PSWriter will never change its value. +*) + +PROCEDURE BeginBitmapFont (VAR fontid : ARRAY OF CHAR); +(* Output some PostScript to switch to the given bitmap font. + The string parameter is declared to be a variable for efficiency reasons; + PSWriter will never change its value. +*) + +PROCEDURE BeginPostScriptFont (VAR fontname : ARRAY OF CHAR; + scaledsize, mag : INTEGER); +(* Output some PostScript to switch to the given resident PostScript font. + The string parameter is declared to be a variable for efficiency reasons; + PSWriter will never change its value. + The scaledsize and mag parameters are needed to determine the requested + font scale. +*) + +PROCEDURE SetBitmapChar (ch : CHAR; hpos, vpos, pwidth : INTEGER); +(* Output some PostScript to set the given character at the given position. + pwidth (the advance width in pixels) is used to output PostScript strings, + minimizing the need to position single characters. +*) + +PROCEDURE SetPostScriptChar (ch : CHAR; hpos, vpos, pwidth : INTEGER); +(* Output some PostScript to set the given character at the given position. + pwidth (the advance width in pixels) is used to output PostScript strings, + but we have to generate slightly different PostScript code to avoid + accumulated rounding errors since the true advance width is not + necessarily an integer number of pixels. +*) + +PROCEDURE EndFont; +(* Output some PostScript to end the current font. This routine must appear + after the last SetBitmap/PostScriptChar call for this font. +*) + +PROCEDURE RestoreVM; +(* Output some PostScript to restore VM to the state saved by the most recent + SaveVM call. + The main module should only call this routine if /CONSERVE_VM is given. +*) + +PROCEDURE SetRule (wd, ht : CARDINAL; hpos, vpos : INTEGER); +(* Output some PostScript to set the given rule at the given position. *) + +PROCEDURE EndPage (DVIpage : CARDINAL); +(* Output some PostScript to end the current page. *) + +PROCEDURE CloseOutput; +(* Output any final PostScript and close the file. *) + +END PSWriter. diff --git a/dviware/psprint/vms/pswriter.mod b/dviware/psprint/vms/pswriter.mod new file mode 100644 index 0000000000..a18ccc2df1 --- /dev/null +++ b/dviware/psprint/vms/pswriter.mod @@ -0,0 +1,405 @@ +IMPLEMENTATION MODULE PSWriter; + +(* Author: Andrew Trevorrow + Implementation: University of Hamburg Modula-2 under VAX/VMS version 4 + Date Started: August, 1986 + + Description: + PostScript output routines used by PSDVI. + The output file consists of calls to various PostScript procedures + defined in a header file that must be prepended 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 must contain the necessary matrix + transformations to convert TeX coordinates back into device coordinates. + + Revised: + November, 1987 (while at The Open University) + - Output file is now normal text file rather than fixed-length record file. + - Added SaveVM and RestoreVM routines to support the conserveVM flag + used by the main module. + - Added SetPostScriptChar to overcome rounding problems if we try to + use SetBitmapChar for a PostScript font. + + June--August, 1988 (while at Aston University) + - Modified SetPostScriptChar to output strings like SetBitmapChar. + - EndBitmapFont now called EndFont as it is used for both font types. + + September--October, 1989 (while at Aston University, 2nd time) + - Modified SendBitmapChar and SetPostScriptChar so they can't create + a string too long for WriteChar's output buffer. + Adrian Clark can now use his half-tone font with PSPRINT. +*) + +FROM FileSystem IMPORT + File, Create, Open, Done, + ReadChar, WriteChar, + Eof, Close; + +CONST + NULL = 0C; + CR = 15C; + DEL = 177C; + +VAR + PSfile : File; (* output file *) + curh, curv : INTEGER; (* for SetBitmapChar and SetPostScriptChar *) + stringlen : CARDINAL; (* ditto; current string length *) + pendingch : CHAR; (* ditto; terminates current string *) + +(******************************************************************************) + +PROCEDURE OpenOutput (name : ARRAY OF CHAR) : BOOLEAN; + +BEGIN +(* SYSDEP: create a normal VAX/VMS text file *) +Create(PSfile,name,TRUE,TRUE); +RETURN Done(); +END OpenOutput; + +(******************************************************************************) + +PROCEDURE OutputHeader (name : ARRAY OF CHAR) : BOOLEAN; + +VAR f : File; ch : CHAR; + +BEGIN +Open(f,name,FALSE); (* SYSDEP: read only *) +IF Done() THEN + LOOP + ReadChar(f,ch); (* next char or Eof *) + IF Eof(f) THEN + EXIT; + ELSE + Put(ch); (* copy verbatim, including any ctrl chars *) + END; + END; + Close(f); + RETURN TRUE; +ELSE + RETURN FALSE; (* couldn't open given file *) +END; +END OutputHeader; + +(******************************************************************************) + +PROCEDURE BeginPage (DVIpage : CARDINAL); + +BEGIN +PutCard(DVIpage); PutString(' @bop0'); Put(CR); +END BeginPage; + +(******************************************************************************) + +PROCEDURE NewBitmapFont (VAR fontid : ARRAY OF CHAR); + +BEGIN +Put('/'); PutString(fontid); PutString(' @newfont'); Put(CR); +END NewBitmapFont; + +(******************************************************************************) + +PROCEDURE OutputPage (DVIpage : CARDINAL); + +BEGIN +PutCard(DVIpage); PutString(' @bop1'); Put(CR); +END OutputPage; + +(******************************************************************************) + +PROCEDURE OutputSpecial (VAR name : specialstring; + hpos, vpos : INTEGER) : BOOLEAN; + +VAR f : File; fspec : specialstring; ch : CHAR; i : CARDINAL; + +BEGIN +(* check name for optional space (indicating additional PostScript text) *) +i := 0; +fspec := ''; (* SYSDEP: fill with NULLs *) +WHILE (i <= HIGH(name)) AND (name[i] <> ' ') DO + fspec[i] := name[i]; (* extract file spec from name *) + INC(i); +END; +Open(f,fspec,FALSE); (* SYSDEP: read only *) +IF Done() THEN + PutInt(hpos); Put(' '); PutInt(vpos); PutString(' p'); Put(CR); + PutString('@bsp'); Put(CR); + IF i <= HIGH(name) THEN + (* name[i] is first ' '; skip this and copy rest of name to output *) + INC(i); + WHILE (i <= HIGH(name)) AND (name[i] <> NULL) DO + Put(name[i]); + INC(i); + END; + Put(CR); (* text becomes first line of file *) + END; + LOOP + ReadChar(f,ch); (* next char or Eof *) + IF Eof(f) THEN + EXIT; + ELSE + Put(ch); (* copy verbatim, including any ctrl chars *) + END; + END; + Close(f); + PutString('@esp'); Put(CR); + RETURN TRUE; +ELSE + RETURN FALSE; (* couldn't open given file *) +END; +END OutputSpecial; + +(******************************************************************************) + +PROCEDURE SaveVM (VAR fontid : ARRAY OF CHAR); + +BEGIN +Put('/'); PutString(fontid); PutString(' @saveVM'); Put(CR); +END SaveVM; + +(******************************************************************************) + +PROCEDURE BeginPostScriptFont (VAR fontname : ARRAY OF CHAR; + 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 *) +PutInt(scaledsize); PutString(' sp '); +PutInt(mag); PutString(' 1000 div mul '); +PutString(fontname); PutString(' PSfont'); Put(CR); +(* initialize some globals for first SetPostScriptChar in this font *) +curh := MAX(INTEGER); +curv := MAX(INTEGER); +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 (* don't update v position *) + IF curh <> hpos THEN (* update h position *) + stringlen := 0; + Put(')'); Put(pendingch); Put(CR); + PutInt(hpos); Put('('); + pendingch := 'H'; + END; +ELSE (* update h and v position *) + IF stringlen > 0 THEN + stringlen := 0; + Put(')'); Put(pendingch); Put(CR); + END; + PutInt(hpos); Put(' '); PutInt(vpos); Put('('); + pendingch := 'S'; +END; +IF (ch >= ' ') AND (ch < DEL) THEN + IF (ch = '(') OR (ch = ')') OR (ch = '\') THEN (* prefix (,),\ with \ *) + Put('\'); Put(ch); + ELSE + Put(ch); + END; +ELSE + Put('\'); + (* and put out 3 octal digits representing ch *) + Put( CHR(ORD('0') + (ORD(ch) DIV 64)) ); + Put( CHR(ORD('0') + ((ORD(ch) DIV 8) MOD 8)) ); + Put( CHR(ORD('0') + (ORD(ch) MOD 8)) ); +END; +(* update current page position and string length for next call *) +curh := hpos + pwidth; +curv := vpos; +INC(stringlen); +IF (stringlen MOD 72) = 0 THEN Put('\'); Put(CR) END; +END SetPostScriptChar; + +(******************************************************************************) + +PROCEDURE BeginBitmapFont (VAR fontid : ARRAY OF CHAR); + +BEGIN +PutString(fontid); PutString(' sf'); Put(CR); +(* Initialize some globals for first SetBitmapChar in this font. + This is not relevant when BeginBitmapFont is used before OutputPage. +*) +curh := MAX(INTEGER); +curv := MAX(INTEGER); +stringlen := 0; +pendingch := '?'; +END BeginBitmapFont; + +(******************************************************************************) + +PROCEDURE SetBitmapChar (ch : CHAR; hpos, vpos, pwidth : INTEGER); + +BEGIN +IF curv = vpos THEN (* don't update v position *) + IF curh <> hpos THEN (* update h position (kern or space) *) + stringlen := 0; + Put(')'); Put(pendingch); Put(CR); + PutInt(hpos-curh); Put('('); + pendingch := 'h'; + END; +ELSE (* update h and v position *) + IF stringlen > 0 THEN + stringlen := 0; + Put(')'); Put(pendingch); Put(CR); + END; + PutInt(hpos); Put(' '); PutInt(vpos); Put('('); + pendingch := 's'; +END; +IF (ch >= ' ') AND (ch < DEL) THEN + IF (ch = '(') OR (ch = ')') OR (ch = '\') THEN (* prefix (,),\ with \ *) + Put('\'); Put(ch); + ELSE + Put(ch); + END; +ELSE + Put('\'); + (* and put out 3 octal digits representing ch *) + Put( CHR(ORD('0') + (ORD(ch) DIV 64)) ); + Put( CHR(ORD('0') + ((ORD(ch) DIV 8) MOD 8)) ); + Put( CHR(ORD('0') + (ORD(ch) MOD 8)) ); +END; +(* update current page position and string length for next call *) +curh := hpos + pwidth; +curv := vpos; +INC(stringlen); +IF (stringlen MOD 72) = 0 THEN Put('\'); Put(CR) END; +END SetBitmapChar; + +(******************************************************************************) + +PROCEDURE EndFont; + +(* Terminate the last "h v(..." or "dh(..." for the current font. *) + +BEGIN +IF stringlen > 0 THEN + Put(')'); Put(pendingch); Put(CR); +END; +END EndFont; + +(******************************************************************************) + +PROCEDURE RestoreVM; + +BEGIN +PutString('@restoreVM'); Put(CR); +END RestoreVM; + +(******************************************************************************) + +PROCEDURE SetRule (wd, ht : CARDINAL; hpos, vpos : INTEGER); + +BEGIN +PutCard(wd); Put(' '); PutCard(ht); Put(' '); +PutInt(hpos); Put(' '); PutInt(vpos); +PutString(' r'); Put(CR); +END SetRule; + +(******************************************************************************) + +PROCEDURE EndPage (DVIpage : CARDINAL); + +BEGIN +PutCard(DVIpage); PutString(' @eop'); Put(CR); +END EndPage; + +(******************************************************************************) + +PROCEDURE CloseOutput; + +BEGIN +PutString('@end'); Put(CR); +Close(PSfile); +END CloseOutput; + +(******************************************************************************) + +PROCEDURE Put (ch : CHAR); + +BEGIN +WriteChar(PSfile,ch); +END Put; + +(******************************************************************************) + +PROCEDURE PutString (s : ARRAY OF CHAR); + +VAR i : INTEGER; + +BEGIN +(* SYSDEP: LEN assumes end of string is first NULL, or string is full *) +FOR i := 0 TO LEN(s) - 1 DO + WriteChar(PSfile,s[i]); +END; +END PutString; + +(******************************************************************************) + +PROCEDURE PutInt (i : INTEGER); + +(* We call PutCard after writing any '-' sign. *) + +BEGIN +IF i < 0 THEN + WriteChar(PSfile,'-'); + i := ABS(i); +END; +PutCard(CARDINAL(i)); +END PutInt; + +(******************************************************************************) + +PROCEDURE PutCard (c : CARDINAL); + +(* Since the majority of given values will be < 10,000 we avoid + recursion until c >= 10,000. +*) + +BEGIN +IF c < 10 THEN + WriteChar(PSfile, CHR(ORD('0') + c) ); +ELSIF c < 100 THEN + WriteChar(PSfile, CHR(ORD('0') + (c DIV 10)) ); c := c MOD 10; + WriteChar(PSfile, CHR(ORD('0') + c) ); +ELSIF c < 1000 THEN + WriteChar(PSfile, CHR(ORD('0') + (c DIV 100)) ); c := c MOD 100; + WriteChar(PSfile, CHR(ORD('0') + (c DIV 10)) ); c := c MOD 10; + WriteChar(PSfile, CHR(ORD('0') + c) ); +ELSIF c < 10000 THEN + WriteChar(PSfile, CHR(ORD('0') + (c DIV 1000)) ); c := c MOD 1000; + WriteChar(PSfile, CHR(ORD('0') + (c DIV 100)) ); c := c MOD 100; + WriteChar(PSfile, CHR(ORD('0') + (c DIV 10)) ); c := c MOD 10; + WriteChar(PSfile, CHR(ORD('0') + c) ); +ELSE + PutCard(c DIV 10000); (* recursive if c >= 10000 *) + c := c MOD 10000; + WriteChar(PSfile, CHR(ORD('0') + (c DIV 1000)) ); c := c MOD 1000; + WriteChar(PSfile, CHR(ORD('0') + (c DIV 100)) ); c := c MOD 100; + WriteChar(PSfile, CHR(ORD('0') + (c DIV 10)) ); c := c MOD 10; + WriteChar(PSfile, CHR(ORD('0') + c) ); +END; +END PutCard; + +(******************************************************************************) + +BEGIN +END PSWriter. diff --git a/dviware/psprint/vms/random.ps b/dviware/psprint/vms/random.ps new file mode 100644 index 0000000000..3e69f4c16d --- /dev/null +++ b/dviware/psprint/vms/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/vms/sysguide.tex b/dviware/psprint/vms/sysguide.tex new file mode 100644 index 0000000000..f0ae07de6e --- /dev/null +++ b/dviware/psprint/vms/sysguide.tex @@ -0,0 +1,563 @@ +% LaTeX source for PSPRINT System Guide. +% Cross references are indicated by the string "XREF". + +\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 +\itemsep=0pt + +\def\DVItoVDU{DVIto\kern-.15em VDU} +\def\Modula{\hbox{Modula-2}} +\def\aligneddots{\leaders\hbox to .75em{\hss.\hss}\hfill} + +\begin{document} + +\vspace*{\fill} + +\begin{center} +\Huge\bf PSPRINT System Guide\\ [3mm] +\normalsize\bf Version 3.1 for VAX/VMS\\ +\bf Andrew Trevorrow, October 1989 +\end{center} + +\bigskip +\bigskip + +This document explains how to install or modify PSPRINT, a PostScript +driver that runs under VAX/VMS\@. +Currently supported printers include the Apple LaserWriter, +the Linotronic~300 and DEC's PrintServer~40. +The PSPRINT command can be used to print a DVI file, a PostScript program, +or an ordinary text file. +The {\sl PSPRINT User Guide\/} has details on how to use the program. + +\bigskip +\begin{center} +\bf Contents +\end{center} + + % XREF: make sure page #s are up-to-date +Overview \aligneddots\ 1\\ +Installing PSPRINT \aligneddots\ 2\\ +Testing PSPRINT \aligneddots\ 3\\ +Adding a New Device \aligneddots\ 4\\ +Existing Problems \aligneddots\ 5\\ +Changes to Version 1.1 \aligneddots\ 6\\ +Changes to Version 2.0 \aligneddots\ 7\\ +Changes to Version 3.0 \aligneddots\ 8 + +\vspace*{\fill} + +\thispagestyle{empty} + +\newpage +\setcounter{page}{1} + +\subsection*{Overview} + +PSPRINT is a mixture of \Modula, DCL and PostScript. All the necessary +files, including documentation and source code, are kept in a directory +referred to by the logical name \verb|tex_ps|. The file \verb|aaaread.me| +gives a brief description of each file. + +The following sequence of events occurs when a user runs PSPRINT: +\begin{enumerate} +\item +\verb|psprint.exe| is invoked. This \Modula\ program extracts the +file parameter and qualifier values from the command line according +to \verb|psprint.cld|. +If everything seems okay then a device-specific command file is activated: + \begin{itemize} + \item [ ] + \verb|tex_ps:lw_print.com | --- if \verb|/device=LW|\\ + \verb|tex_ps:lino_print.com| --- if \verb|/device=LINO|\\ + \verb|tex_ps:ps40_print.com| --- if \verb|/device=PS40| + \end{itemize} +The CLD file specifies the allowed \verb|/device| values and the default +value (currently \verb|LW| for LaserWriter). + +\item +These command files handle most of the messy system-dependent details. +Each can process one of five file types: +a DVI file, a PostScript program, or one of three text file types. +(A DVI file is translated into a temporary PostScript file by +PSDVI, another \Modula\ program. +Each command file uses a different set of qualifiers to specify the +printer's resolution, the location and format of bitmapped fonts, +the order in which to translate pages, etc.) + +\item +Each type of file is bracketed by device-specific header and trailer +information before being sent to an appropriate print queue. +\end{enumerate} +Note that much of the behaviour of PSPRINT can be changed by simply +editing command files and/or PostScript text files. +Such flexibility is of particular benefit to sites without \Modula. +You'll probably need the {\sl PostScript Language Reference Manual\/} by +Adobe if you run into problems or wish to make substantial changes. + +\newpage + +\subsection*{Installing PSPRINT} + +Let's assume you've dumped all the necessary files into a suitable directory. +Attach yourself to this directory and carry out the following steps: +\begin{enumerate} +\item +Check \verb|psprint.cld| and \verb|psdvi.cld| for any site-dependent changes. +Also check the \hbox{PSDVI} qualifiers in each of the \verb|*_print.com| files. + +\item +Examine the file \verb|install.com| and make the necessary changes to suit +your site. Running this command file will perform the following steps: +\begin{itemize} + \item + Set terminal characteristics for a LaserWriter or Linotronic. + These printers are assumed to be connected to your VAX via a serial line. + The LaserWriter should have its mode switch set to 9600 baud. + The PrintServer~40 should be set up as described in the DEC documentation. + \item + Define the PostScript form type (used by LaserWriter and Linotronic). + \item + Initialize the print queue(s). + \item + Define \verb|tex_ps| to be a system logical name pointing to + the public-access directory. + \item + Install the PSPRINT and PSDVI commands. +\end{itemize} +Some of the above steps must be copied into appropriate +system files if you want PSPRINT to work the next time you reboot. + +\item +Start the appropriate print queue(s). +Note that print jobs will disappear if the LaserWriter +is switched off or its mode switch is incorrectly set. +Similar warnings apply to the Linotronic~300. +Both these devices use the standard VAX/VMS print symbiont. +The symbiont for the PrintServer~40 is much more intelligent; +it is able to interpret PostScript messages and can even send them +back to the user's terminal (if \verb|/notify| is specified). + +\item +Each PostScript printer has a system password that allows you to change +persistent parameters. +In an open-access environment it's probably a good idea to +change the initial password. +Make the appropriate changes to \verb|pass.ps| and then send it to the printer +by typing `\verb|psprint pass.ps|' (with an appropriate \verb|/device| value). +Then delete all reference to the new password! +Note that the PrintServer~40 uses a string for the password; +the other devices use an integer. + +\item +\verb|psprint.hlp| is provided as a suitable source for on-line help. +Feel free to make any changes to suit your site. +Changes may also be needed in \verb|userguide.tex|; the likely locations +are flagged by a ``\verb|SYSDEP|'' comment. + +\item +Check the installation by logging out, then logging in as a normal user +and trying PSPRINT on various DVI/PostScript/text files. + +\end{enumerate} + +\newpage + +\subsection*{Testing PSPRINT} + +There are a number of useful files in \verb|tex_ps| for testing PSPRINT: + +\begin{itemize} + +\item +Type `\verb|psprint test|'. +The top left corner of the first rule should appear +1~inch in from the top and left paper edges. +If not, then you'll need to modify \verb|tex.ps|. +You should only need to carry out such changes for a LaserWriter. +The last two integers of the \verb|setmatrix| array are pixel values that +adjust the horizontal and vertical position of the origin. +Also type `\verb|psprint test/land|' to test the positioning +of landscaped output. +(Note that the \verb|/hoffset| and \verb|/voffset| qualifiers allow +users to shift the output as well.) + +\item +Type `\verb|psprint lines.dat|' and `\verb|psprint lines.dat/land|' +to check the output format of ordinary text files. + +\item +Type `\verb|psprint clip.ps|' to produce some lines indicating +the default clipping region; nothing can be printed outside this region. + +\item +Type `\verb|psprint psfonts|' to test the use of resident PostScript fonts +in a \TeX\ document (assuming you have the necessary TFM files). +The fonts used in this test should be available in all PostScript printers. + +\item +The file \verb|nasty.dvi| is also useful for testing rarely used code +in PSDVI\@. Try some of these pages: + \begin{itemize} + \item [ ] + \verb|psprint nasty/page=1 | --- empty page\\ + \verb|psprint nasty/page=3 | --- page with \verb|\special| commands\\ + \verb|psprint nasty/page=10| --- tests long verbatim \verb|\tt| strings\\ + \verb|psprint nasty/page=18| --- tests rules in math extension characters + \end{itemize} + +\end{itemize} + +\newpage + +\subsection*{Adding a New Device} + +Here are the steps required to support a new type of PostScript printer: +\begin{enumerate} + +\item +Create a new \verb|/device| value by adding a \verb|psprinter| keyword, +say \verb|XXX|, at the bottom of \verb|psprint.cld|. + +\item +Modify \verb|psprint.mod| to handle the new device value. +Locate all occurrences of an existing device, say \verb|LW|, and duplicate +the code. Type `\verb|@build|' to create a new version of PSPRINT\@. +This assumes you have a Modula-2 compiler; if you don't then you could +quite easily translate \verb|psprint.mod| into Pascal. +It is a reasonably small and simple program. +Note that no changes to PSDVI are needed. + +\item +Create \verb|xxx_print.com| using one of the existing \verb|*_print.com| +files as a starting point. This new command file will be activated when +a user types `\verb|psprint/dev=xxx ...|'. + +\item +Create \verb|xxx_header.ps|, \verb|xxx_trailer.ps| and \verb|xxx_fonts.ps| +as required. Again, base these new files on the nearest equivalents for +an existing device. + +\item +Make any necessary changes to the job prologues: +\verb|tex.ps|, \verb|ps.ps|, \verb|text.ps|, \verb|two.ps| and \verb|wide.ps|. +Search these files for occurrences of \verb|dev|, \verb|res| and \verb|land| +and add any code needed for the new device. +Note that \verb|xxx_print.com| must make sure the definitions for these +PostScript variables come {\em before\/} the prologue file. + +\item +Connect the new printer to the VAX host and create a suitable queue. +See \verb|install.com| for details. + +\item +Type `\verb|set command psprint|' and +test the new version of PSPRINT on a variety of files. +% XREF +The previous section describes some useful tests. + +\item +Finally, update the user documentation in \verb|userguide.tex| +and \verb|psprint.hlp|. +If you plan to pass on your changes to other people +it would be polite to update the system documentation as well +(in \verb|sysguide.tex| and \verb|aaaread.me|). + +\end{enumerate} + +\newpage + +\subsection*{Existing Problems} + +\begin{itemize} + +\item +PSPRINT is {\em not\/} a print symbiont. +It cannot, for example, report any LaserWriter problems to an operator. +Jobs will just disappear if the LaserWriter is turned off or +its mode switch is on some setting other than 9600. +The print queue should be started {\em after\/} turning on the LaserWriter +and stopped {\em before\/} turning it off. + +\item +Some DVI jobs may exceed PostScript's virtual memory, depending on the +number and size of downloaded characters, and the amount of VM available. +For reasons unknown, early versions of the LaserWriter can crash +(and then restart by printing a test page) rather than show a ``VMerror'' +message. No banner page is printed. +The ``\verb|VMERROR|'' code in \verb|tex.ps| +attempts to overcome this problem by producing an error message if the +VM usage reaches some threshold value. +Enable this code if your LaserWriter suffers from such a problem. + +\item +PSPRINT cannot handle FORTRAN carriage-control files nor RUNOFF output. + +\item +PostScript printers can get occasional one-pixel rounding errors when +drawing rules. +The problem can sometimes be visible in a \TeX\ document, usually in large +math extension characters containing one or more rules. +The use of device-specific \verb|setmatrix| code in +\verb|tex.ps| minimizes these errors. +Some ``fine-tuning'' of the PostScript rule-drawing code may also be necessary. +For example, in some versions of the LaserWriter I've had to +add 1 to the vertical position of each rule. +Page 18 of \verb|nasty.dvi| is a good test sheet; try printing it +in both portrait and landscape orientation. + +\item +To be able to use PostScript fonts with \TeX\ you must have the necessary +TFM files. PSDVI requires that their names all begin with the +\verb|/psprefix| value. The default prefix of ``\verb|ps-|'' +is set in \verb|psdvi.cld|. If you decide to use some other prefix then +you'll need to edit \verb|*_fonts.ps| and update the user documentation. + +\item +When using a PostScript text font, users need to be aware that +the standard \TeX\ commands for accents and foreign letters must be redefined +(and reinstated when switching back to a Computer Modern text font). +See \verb|psfonts.tex| and \verb|pstext.tex| for one possible solution. + +\item +If you are using any CM fonts with 256 characters then +you'll have to change a few numbers appearing in the definition of +\verb|@newfont| in \verb|tex.ps|. +Change the two occurrences of 128 to 256 and the single 127 to 255. +A warning: jobs that used to print okay may now exceed VM. + +\item +The \verb|\special| facility provided by PSDVI (i.e., file inclusion with +optional starting text) is quite primitive compared +with other DVI-to-PostScript translators. +The reason is that all \verb|\special| commands on a page are gathered +together and sent all at once, as are all the fonts and rules. +A significant advantage of this method is printing speed: by minimizing the +number of font switches we keep character images in the font cache for as +long as possible. + +\end{itemize} + +\newpage + +\subsection*{Changes to Version 1.1} + +\begin{itemize} + +\item +These changes were made while I was working in the UK at The Open University. +The current version of PSPRINT (and PSDVI) has leapt to 2.0 to coincide +with the latest version of \DVItoVDU. + +\item +PSPRINT now supports a variety of PostScript printers. +The new \verb|/device| qualifier indicates which type of printer to use; +a default device is specified in \verb|psprint.cld|. +A separate command file exists for each device: see \verb|*_print.com|. +Each device also requires slightly different PostScript code +for each type of input file. +The introduction of different devices has meant a major file-renaming exercise. + +\item +PSPRINT has a number of new qualifiers --- \verb|/size|, \verb|/lowres| and +\verb|/cutmarks| --- that only take effect if \verb|/device=LINO|. +See the {\sl PSPRINT User Guide\/} for details. + +\item +Temporary files are now created in \verb|sys$scratch|. +This can easily be changed by editing the \verb|*_print.com| files. + +\item +PSDVI can now handle resident PostScript fonts. +Such fonts must have TFM file names beginning with ``\verb|ps-|''. +The new \verb|/tfm_directory| qualifier specifies the default location of +these TFM files. For each \verb|/device| value there exists a +\verb|*_fonts.ps| file that maps the TFM names into the PostScript font names +used in that type of printer. +(Each PostScript printer has a different set of resident fonts.) + +\item +PSDVI has a new \verb|/conserve_vm| qualifier. This can be used to conserve +PostScript's virtual memory at the expense of downloading character bitmaps +more often (resulting in a larger output file). +PSPRINT makes \verb|/conserve_vm| the default for the Linotronic~300 +and \verb|/noconserve_vm| the default for the LaserWriter and PrintServer~40. + +\item +PSDVI now creates an ordinary text file. Although slightly less efficient +than creating a fixed-length-record file, the advantages of being able +to easily edit/view/transmit a text file were considered more important. + +\end{itemize} + +\newpage + +\subsection*{Changes to Version 2.0} + +\begin{itemize} + +\item +These changes were made while I was working at Aston University. +The current version of PSPRINT (and PSDVI) is now 3.0. + +\item +Added a number of new qualifiers to PSPRINT: +\verb|/queue| allows users at sites with more than one printer of the +same type to override the default queue; +\verb|/output| copies the PostScript code generated by PSPRINT into a +given file rather than sending it to a printer; +\verb|/two| and \verb|/wide| are variants of \verb|/text| that print +two ``pages'' (60 lines by 80/132 columns) on each sheet of paper; +\verb|/nobanner| and \verb|/manualfeed| have been implemented for +the LaserWriter; +\verb|/reverse| and \verb|/noreverse| override the device-specific +order in which pages are printed; +\verb|/resolution|, +\verb|/font_directory|, +\verb|/dummy_font|, +\verb|/tfm_directory|, +\verb|/psprefix|, +\verb|/xsize| and \verb|/ysize| +can be used to override the device-specific default values used by PSDVI +(although most users should never need to use them). + +\item +Added \verb|/psprefix| qualifier to PSDVI so that sites can specify the +TFM file name prefix used to indicate PostScript fonts. +(The default prefix is ``\verb|ps-|''. If you decide to change this then +you'll need to change the various \verb|*_fonts.ps| files; it's also +mentioned in the user documentation.) + +\item +Added \verb|/increment| qualifier to PSDVI and PSPRINT to simplify the +printing of documents on both sides of the paper; +see the {\sl User Guide\/} for details. + +\item +Added \verb|/hoffset| and \verb|/voffset| qualifiers to PSDVI and PSPRINT +to allow shifting of each page. This should be useful for sites with many +printers of the same type, each with different margin settings. + +\item +Reduced both the size and execution time of the PostScript code generated +by PSDVI when setting resident PostScript fonts. + +\item +Modified the \verb|BuildFontSpec| routine in PSDVI's \verb|FontReader| module +to remove the limitation requiring all font files to contain a size substring +of the same length. Sites that had to include a leading zero +in some font names to overcome this limitation must now +rename them (e.g., \verb|$rename *.0635pk *.635pk|). + +\item +PSDVI's \verb|Terminal| module is now called \verb|TermOut| and no longer +calls \verb|SYS$ASSIGN| to assign \verb|TT|. +This change allows terminal output to be captured in a file --- +very important when PSPRINT is used in a batch job! +A side-effect is that page numbers now appear on separate lines. + +\item +There is now a single prologue file for each type of job: +\verb|tex.ps|, \verb|ps.ps|, \verb|text.ps|, \verb|two.ps| and \verb|wide.ps|. +They rely on a few PostScript definitions created in \verb|*_print.com| to +handle different devices, landscaping, etc. + +\item +The \verb|*_print.com| files now put a single temporary file in the print +queue. This simplifies the code required in \verb|text.ps| and +overcomes problems caused by print symbionts adding unwanted characters +(such as formfeeds/linefeeds) between files in a multi-file print job. +A side-effect of this change is that the format characters in a +FORTRAN carriage-control file are no longer obeyed +(they will now be printed!). + +\item +The CTRL-D sent at the start of each \verb|LW|/\verb|LINO| print job has +been removed to avoid problems (involving the echoing of such characters) +when a PostScript printer is connected to an X.25 pad. + +\end{itemize} + +\newpage + +\subsection*{Changes to Version 3.0} + +\begin{itemize} + +\item +These changes were made while I was working at Aston University +(for a second time). +The current version of PSPRINT (and PSDVI) is now 3.1. + +\item +Any \verb|\special|s on a page are now processed in the order they +appear in the DVI file (instead of in reverse order). + +\item +Fixed bug in \verb|FixToDVI| routine in \verb|FontReader.MOD| that +prevented fonts being scaled to more than 128pt. +Thanks to Niel Kempson for spotting this. + +\item +Added code to \verb|PSWriter.MOD| to make sure that very long PostScript +strings are correctly broken over multiple lines. +This problem was spotted by Adrian Clark when using halftone fonts. + +\item +Added support for Macintosh-generated PostScript files created +by pressing Command-F after clicking OK in the Print dialogue. +A new \verb|/prep=file| qualifier allows users to include a +modified Laser Prep file at the end of the normal prologue. +This is necessary when printing a DVI file that uses \verb|\special| to include +a Command-F PostScript file. +If only \verb|/prep| is given then a default file (specified in +\verb|psprint.cld|) is included. The current default is +\verb|tex_ps:laserprep70.ps| but other versions are provided in \verb|tex_ps|. +These files contain comments describing how they were created. + +\item +Allow \verb|/nobanner| on a Linotronic job. + +\item +\verb|*_print.com| no longer append CTRL-D if \verb|/output| is used. + +\item +Fixed \verb|*_print.com| so that CTRL-Y won't clobber a user's symbols. + +\item +For a DVI job, if a file called \verb|global.ps| exists in the user's +current directory then its contents will be included after the prologue. +The example \verb|global.ps| file in \verb|tex_ps| +shows how to get the word ``DRAFT'' printed in the background on every page. + +\item +Added \verb|psnames.tex| and illustrated its use in \verb|psfonts.tex|. +This might be a useful approach for people with access to more +than one set of PostScript TFM files. + +\item +\verb|/noreverse| is now the default for all devices. +The default setting for this qualifier (and for \verb|/conserve_vm|) +is now specified in \verb|*_print.com| rather than in \verb|psprint.mod|. + +\end{itemize} + +\end{document} diff --git a/dviware/psprint/vms/termout.def b/dviware/psprint/vms/termout.def new file mode 100644 index 0000000000..7528d5eb33 --- /dev/null +++ b/dviware/psprint/vms/termout.def @@ -0,0 +1,46 @@ +DEFINITION MODULE TermOut; + +(* Author: Andrew Trevorrow + Implementation: University of Hamburg Modula-2 under VAX/VMS version 4 + Date Started: August, 1986 + + Description: + These terminal output routines have been targeted at just one client: PSDVI. + NB: + - Halt will NOT display any message, unlike Hamburg's HALT. + It will also set the VMS $SEVERITY value: + Halt(0) exits and sets $SEVERITY to Warning. + Halt(1) exits and sets $SEVERITY to Success. + Halt(2) exits and sets $SEVERITY to Error. + - Output will only be updated after a WriteLn. + + Revised: + June--August, 1988 (while at Aston University) + - No longer export WriteBuffer/StartLn. + - My Terminal module had to be renamed to TermOut to avoid collision with + standard library module. +*) + +PROCEDURE Write (ch: CHAR); +(* Write given character to output. *) + +PROCEDURE WriteString (s: ARRAY OF CHAR); +(* Write given string of characters to output. + s is terminated by first NULL (unless full). +*) + +PROCEDURE WriteInt (i : INTEGER); +(* Write given integer to output. *) + +PROCEDURE WriteCard (c : CARDINAL); +(* Write given cardinal to output. *) + +PROCEDURE WriteLn; +(* Write end-of-line and update output. *) + +PROCEDURE Halt (status : CARDINAL); +(* Terminate program with given status: 0 = warning, 1 = success, 2 = error. + No message is generated. +*) + +END TermOut. diff --git a/dviware/psprint/vms/termout.mod b/dviware/psprint/vms/termout.mod new file mode 100644 index 0000000000..b352bcf094 --- /dev/null +++ b/dviware/psprint/vms/termout.mod @@ -0,0 +1,77 @@ +IMPLEMENTATION MODULE TermOut; + +(* Author: Andrew Trevorrow + Implementation: University of Hamburg Modula-2 under VAX/VMS version 4 + Date Started: August, 1986 + + Description: + Implements terminal output routines used by PSDVI. + + Revised: + June--August, 1988 (while at Aston University) + - No longer use buffering/SYS$ASSIGN/SYS$QIOW since it did not allow the + output to be captured in a file (which is pretty important if users want + to run PSPRINT in a batch job and still see any error messages!). +*) + +FROM VMS IMPORT + SYS$EXIT; + +IMPORT InOut; + +(******************************************************************************) + +PROCEDURE Write (ch : CHAR); + +BEGIN +InOut.Write(ch); +END Write; + +(******************************************************************************) + +PROCEDURE WriteString (s: ARRAY OF CHAR); + +BEGIN +InOut.WriteString(s); +END WriteString; + +(******************************************************************************) + +PROCEDURE WriteInt (i : INTEGER); + +BEGIN +InOut.WriteInt(i,1); +END WriteInt; + +(******************************************************************************) + +PROCEDURE WriteCard (c : CARDINAL); + +BEGIN +InOut.WriteCard(c,1); +END WriteCard; + +(******************************************************************************) + +PROCEDURE WriteLn; + +BEGIN +InOut.WriteLn; +END WriteLn; + +(******************************************************************************) + +PROCEDURE Halt (status : CARDINAL); + +VAR result : CARDINAL; + +BEGIN +(* SYSDEP: set high order bit so that no CLI message will be seen *) +status := status + 10000000H; +result := SYS$EXIT(status); +END Halt; + +(******************************************************************************) + +BEGIN +END TermOut. diff --git a/dviware/psprint/vms/test.tex b/dviware/psprint/vms/test.tex new file mode 100644 index 0000000000..2811adcdc9 --- /dev/null +++ b/dviware/psprint/vms/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/vms/tex.ps b/dviware/psprint/vms/tex.ps new file mode 100644 index 0000000000..36ac9cc08d --- /dev/null +++ b/dviware/psprint/vms/tex.ps @@ -0,0 +1,236 @@ +% Prologue for a DVI job. +% It assumes *_print.com 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 235 3100 ] 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/vms/text.ps b/dviware/psprint/vms/text.ps new file mode 100644 index 0000000000..c331cef192 --- /dev/null +++ b/dviware/psprint/vms/text.ps @@ -0,0 +1,74 @@ +% Prologue for a /text job. +% It assumes *_print.com 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 + +/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 10 eq % or does thischar = linefeed? + { linefeed } + { thischar 12 eq % or does thischar = formfeed? + { formfeed } + { } % ignore any other control char + ifelse } + ifelse } + ifelse +} bind def + +(%stdin) (r) file /infile exch def +/currentchar 1 string def +setlocation + +/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/vms/two.ps b/dviware/psprint/vms/two.ps new file mode 100644 index 0000000000..e2c57cf397 --- /dev/null +++ b/dviware/psprint/vms/two.ps @@ -0,0 +1,111 @@ +% Prologue for a /two job. +% It assumes *_print.com 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 + +/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 10 eq % or does thischar = linefeed? + { linefeed } + { thischar 12 eq % or does thischar = formfeed? + { formfeed } + { % ignore any other control char + } 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/vms/userguide.tex b/dviware/psprint/vms/userguide.tex new file mode 100644 index 0000000000..492f7ba132 --- /dev/null +++ b/dviware/psprint/vms/userguide.tex @@ -0,0 +1,648 @@ +% 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.1 for VAX/VMS\\ +\bf Andrew Trevorrow, October 1989 +\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 +Temporary Files \aligneddots\ 1\\ +\TeX\ Output \aligneddots\ 1\\ +PostScript Output \aligneddots\ 1\\ +Text Output \aligneddots\ 1\\ +Command Qualifiers \aligneddots\ 2\\ +Error Messages \aligneddots\ 5\\ +Including Global PostScript \aligneddots\ 6\\ +Using PostScript Fonts \aligneddots\ 6\\ +Using PostScript Graphics \aligneddots\ 7 + +\vspace*{\fill} + +\thispagestyle{empty} + +\newpage +\setcounter{page}{1} + +\subsection*{Temporary Files} + +For each type of input file, PSPRINT will create a temporary file +in \verb|sys$scratch|. % SYSDEP +This file has a \verb|.tmp| extension and +contains the PostScript commands required to print your job. +It is automatically deleted once printed; +you will only need to delete it if you decide to delete your job +from the print queue. + +\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| qualifier. +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|/landscape| qualifier will +rotate the paper so that you can have lines up to 132 characters long +(but only 50 lines per page). +The \verb|/two| and \verb|/wide| qualifiers are variants of \verb|/text| +that use a smaller font to fit two logical pages on each sheet of +paper. + +Type `\verb|psprint foo.ps /text|' if you want to print a PostScript file. + +\newpage + +\subsection*{Command Qualifiers} + +The PSPRINT command can be followed by a variety of qualifiers: +\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} +If you have access to more than one type of printer, it may be a good idea +to define some symbols in your \verb|login.com| file: + \begin{itemize} + \item + \verb|$lw*print :== psprint/dev=LW ! for LaserWriter|\\ + \verb|$lino*print :== psprint/dev=LINO ! for Linotronic 300|\\ + \verb|$ps40*print :== psprint/dev=PS40 ! for PrintServer 40| + \end{itemize} +\end{itemize} + +Some qualifiers only apply to certain devices: +\begin{itemize} + +\item \verb|/nobanner| (only if \verb|/device=LW| or \verb|LINO|) --- +prevents PSPRINT producing a banner page. + +\item \verb|/manualfeed| (only if \verb|/device=LW|) --- +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 qualifiers 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|/landscape| 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 qualifiers 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 qualifiers can only be used with a DVI file: +\begin{itemize} + +\item \verb|/pages=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|/pages|: + \begin{itemize} + \item + \verb|$ psprint foo /pages=2 | --- prints the 2nd DVI page + (\TeX\ page \verb|[1]|)\\ + \verb|$ psprint foo /pages=:4 | --- prints the first four pages\\ + \verb|$ psprint foo /pages=4: | --- prints the last two pages\\ + \verb|$ psprint foo /pages=[2] | --- prints \verb|[2.1]| and \verb|[2.2]|\\ + \verb|$ psprint foo /pages=1:[2] | --- prints the first four pages\\ + \verb|$ psprint foo /pages=[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|. + +\item \verb|/increment=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|/pages| subrange) and $f+ni$ is less than or equal to +the final DVI page selected. + +The primary use of \verb|/increment| 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 /inc=2 /nobanner /rev| --- 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 /inc=2 /pag=2: /norev| --- prints DVI pages 2, 4, 6, 8 + \end{enumerate} +Note that the use of \verb|/reverse| with \verb|/increment| has no effect on +{\em which\/} pages are printed; it simply changes the {\em order\/} in +which they are done. + +If you intend doing a lot of two-sided printing then it is a good idea to +define some symbols in your \verb|login.com| file to avoid making mistakes: + \begin{itemize} + \item + \verb|$ oddpages :== psprint/pag=1:/inc=2/rev/nobanner|\\ + \verb|$ evenpages :== psprint/pag=2:/inc=2/norev| + \end{itemize} + +\item \verb|/reverse| or \verb|/noreverse| --- +forces PSPRINT to print pages in descending or ascending order respectively. +By default PSPRINT prints DVI pages in ascending order. + +\item \verb|/magnification=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|/stats| --- +shows statistics on the rules, fonts, characters and \verb|\special| commands +used on each page. + +\item \verb|/conserve_vm| --- +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_vm| is the default; +if \verb|/device=LW| or \verb|PS40| then \verb|/noconserve_vm| is the default. + +\item \verb|/units=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|/hoffset=dimen| and \verb|/voffset=dimen| --- +allow you to shift the printed location of each page. +For example, \verb|/hoffset=-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|/units|). + +\end{itemize} + +The following qualifiers also apply to a DVI file, but are really for +system wizards. Most users should never need to use them since their +default values are normally defined once at installation time and +are presumably correct: +\begin{itemize} + +\item \verb|/resolution=n| --- +specifies the resolution of your printer in pixels per inch; +\verb|n| must be a positive integer. + +\item \verb|/xsize=dimen| and \verb|/ysize=dimen| --- +specify the paper size. +PSPRINT will check that each DVI page fits within the given dimensions. +A \verb|dimen| is any positive integer or real number followed by a +two-letter unit (the same as for \verb|/units|). + +\item \verb|/psprefix=string| --- +defines the TFM file name prefix that PSPRINT uses to recognize a +PostScript font. + +\item \verb|/tfm_directory=directory| --- +specifies the location of TFM files for PostScript fonts. + +\item \verb|/font_directory=directory| --- +specifies the default directory from which PSPRINT +gets all its character bitmap information. +This might come in handy if you are using Metafont +to create your own fonts or modify existing ones. +For example, the following commands +tell PSPRINT to first search for fonts in the current directory (\verb|[]|) +before looking in the default directory +(assumed to be \verb|tex_disk:[tex.pk]|): + \begin{itemize} + \item + \verb|$ define dirlist [],tex_disk:[tex.pk]|\\ + \verb|$ psprint foo.dvi /font="dirlist:"| + \end{itemize} +Use \verb|/stats| to see the default font directory at your site. + +\item \verb|/dummy_font=file| --- +indicates the naming convention and format of all font files. +The given file must represent an unmagnified font. + +\end{itemize} + +\newpage + +The \verb|/prep| qualifier only applies to a DVI or PS file: +\begin{itemize} + +\item \verb|/prep=file| --- +specifies a file to be included at the end of the normal prologue. +This file will normally be a modified version of Apple's Laser Prep. +If no file is specified then a default file, +\verb|tex_ps:laserprep70.ps|, is included. +Such a file is needed to support PostScript files created by pressing Command-F +after clicking OK in the Print dialogue of most Macintosh applications. +The PostScript code generated by this method relies on the +procedures defined in Laser Prep, so if you want to include such code +(via a \verb|\special| command for instance) you need to use \verb|/prep| to +make sure the appropriate Laser Prep code is loaded first. + +Command-F files contain comments at the top that indicate which version of +Laser Prep they require. Try and choose the nearest matching Laser Prep file +provided with PSPRINT; see \verb|tex_ps:laserprep*.ps|. +These files contain comments describing how they were created, just in case +you need to generate a new version. + +\end{itemize} + +The remaining qualifiers apply to all types of input files: +\begin{itemize} + +\item \verb|/landscape| --- 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|/delete| --- deletes the input file after printing. + +\item \verb|/notify| --- notifies you when the print job has finished. +On the PrintServer~40 you'll also see any PostScript messages, +a particularly useful feature when debugging a PostScript program. + +\item \verb|/copies=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|/note=string| --- includes a note on your banner page. +For example, to get your output put in box 99, just type +`\verb|psprint/note="box 99" ...|'. + +\item \verb|/queue=string| --- overrides the default queue used by PSPRINT\@. +(Some sites may have more than one printer of the same type). + +\item \verb|/output=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} + +\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 banner 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_vm| +or print a few pages at a time. +\item +On a Linotronic, use \verb|/lowres|. +(\verb|/conserve_vm| 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. +If you are using a PrintServer~40 then specify \verb|/notify| to get all +PostScript messages sent back to your terminal. + +\subsection*{Including Global PostScript} + +When printing a DVI file, PSPRINT looks in your current directory for +a file called \verb|global.ps|. +If it exists then its contents will be included after the normal prologue. +The example \verb|global.ps| file supplied in \verb|tex_ps| +shows how to get the word ``DRAFT'' printed in the background on every page. + +\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; determined by /psprefix value in psdvi.cld + +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 --- +see \verb|tex_ps:*_fonts.ps|. + +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|'. + +There are some important differences between PostScript fonts and +the Computer Modern fonts normally used with \TeX: +\begin{enumerate} +\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} + +\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 have a couple of choices: +\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 another program to create the graphic image +and then convert it into a corresponding PostScript file. +The Macintosh is a particularly nice machine for this purpose. +Many applications can either dump an EPS (Encapsulated PostScript) file, +or you can use the Command-F method mentioned earlier in the discussion +of PSPRINT's \verb|/prep| qualifier. +\end{enumerate} + +\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{tex_ps:piechart.ps} + \special{tex_ps:greybox.ps} + \special{tex_ps:random.ps} +\end{verbatim} +at appropriate points in the source file. +The directory location is given with each PostScript file +so you can print a copy of the User Guide from any directory. +If the \verb|\special| command is only given a file name then +PSPRINT assumes the file is in your current directory. + +\begin{figure}[h] % produce figure here + \vspace{2.1in} + \special{tex_ps: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{tex_ps: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{tex_ps: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 200 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/vms/wide.ps b/dviware/psprint/vms/wide.ps new file mode 100644 index 0000000000..4b7e97eb54 --- /dev/null +++ b/dviware/psprint/vms/wide.ps @@ -0,0 +1,109 @@ +% Prologue for a /wide job. +% It assumes *_print.com 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 + +/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 10 eq % or does thischar = linefeed? + { linefeed } + { thischar 12 eq % or does thischar = formfeed? + { formfeed } + { % ignore any other control char + } 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 |