%! This is a PostScript library meant to be printed only with other files %%% %% Postscript Code by Jonathan Monsarrat Copyright 1992 %% permission given for anything except selling this or deleting the header. %% This is the LameTeX Formatter, uses the LaTeX language % Depends on "EndPage" and "StartPage" to be set up by a page formatter /formatdict 100 dict def % This should be 77? formatdict begin /wlist 100 array def % Maximum of 100 words on a line %% Better give these variables default values in case we try to %% do an EndPage but they have not yet been defined /baselineskip 200 def /wlen 0 def /baselineskip 0 def /bottommargin 0 def /parindent 0 def /justify 0 def /rightmargin 0 def /leftmargin 0 def /topmargin 0 def /parskip 0 def /newfontcmd 1 def /para 0 def /vtotal 0 def /wordlen 0 def /ypos 0 def /ytemp 0 def %%%%%%%%%%%%%%%% num InitWord - %%%%%%%%%%%%%%%%%%%%%%% % InitWord takes an setflat values and flattens the current path % It also defines some globals that will get "NextWord" up and running /InitWord { /xpos currentflat def % Save current flatness PageShape setflat flattenpath % gsave stroke grestore % Uncomment this line to show the margin path /coords Approx def pathbbox % It the current path is bigger than the margins, widen them! dup TM gt { /TM exch def } { pop } ifelse dup RM gt { /RM exch def } { pop } ifelse dup BM lt { /BM exch def } { pop } ifelse dup LM lt { /LM exch def } { pop } ifelse xpos setflat % Restore flatness. false fontnames newfontcmd get cvx exec /xlocs [ ] def /welem 1 def /wlen 0 def /woids 0 def /eslot LM def /ypos TM topmargin sub def /vtotal 0 def /xpos 0 def /nxpos 0 def wlist 0 [ newfontcmd false ] put /wtemp 0 def NextSpace pop } bind def %%%%%%%%%%%%%%%%%%%%% - NewXSpace bool %%%%%%%%%%%%%%%%%%%%%% % If there's "room on the bottom" as defined by xlocs, check to see if % there's "room on the top" as defined by NewXSpace. Returns success boolean. /NewXSpace { nxpos newxlocs length 1 sub lt { newxlocs nxpos 2 getinterval {} forall exch /nxpos nxpos 2 add def % If there's any intersection of top and bottom 'good places' set bslot, eslot dup xa le { pop xa } if leftmargin add /bslot exch def dup xb ge { pop xb } if rightmargin sub /eslot exch def bslot eslot lt { true } { NewXSpace } ifelse } { false } ifelse } bind def %%%%%%%%%%%%%%% - NextSpace bool %%%%%%%%%%%%%%%%%%%%%% % NextSpace defines the next space available for writing by % setting ypos to the Y location and bslot and eslot to the beginning % and end of the next open text writing area. Returns success boolean. /NextSpace { xpos xlocs length 1 sub lt % are there any X's left on current line { /xa xlocs xpos get def /xb xlocs xpos 1 add get def NewXSpace { true } { /nxpos 0 def /xpos xpos 2 add def NextSpace } ifelse } { ypos % Leave on the stack for later comparison /ypos ypos vspace 0 eq { baselineskip para { parskip add } if /vtotal baselineskip def } { vspace /vspace 0 def } ifelse sub def ypos BM bottommargin add ge { /newxlocs coords 3 -1 roll 4 add true CheeseWhiz def /xlocs coords ypos 4 sub true CheeseWhiz def /xpos 0 def /nxpos 0 def NextSpace } { pop false } ifelse } ifelse % if we're doing a paragraph and the NextSpace isn't big enough % for the indentation, then choose a new space. % if found-space and para and justify dup para justify 102 eq and and % 102 is ascii 'f' for FULL JUSTIFY { /bslot bslot parindent add def bslot eslot gt { pop NextSpace pop } if } if /para false def } bind def %%%%%%%%%%%%%%%%%%%%%%% - PrintWordList - %%%%%%%%%%%%%%%%%%%%%%%%%%%% % PrintWordList prints the words stored in array "wlist" at Y location ypos % with full justification between X locations bslot and eslot. /PrintWordList { /vtotal 0 def woids 0 ne { % Legal values for /justify are (l)eft (r)ight (f)ull (c)enter in ASCII justify 99 eq % 99 is ascii 'c' for CENTERED { bslot eslot bslot sub wlen sub 2 div add ypos moveto } { bslot justify 114 eq { eslot bslot sub wlen sub add } if % 114 is 'r' ypos moveto } ifelse /sp eslot bslot sub wlen sub woids div def 0 1 welem 1 sub { wlist exch get dup type /stringtype eq { SHOWIT ( ) stringwidth pop 0 rmoveto justify 102 eq { sp 0 rmoveto } if % 102 is ascii 'f' } { dup type /arraytype eq { { } forall { ( ) stringwidth pop neg 0 rmoveto justify 102 eq { sp neg 0 rmoveto } if % 102 is ascii 'f' } if fontnames exch get cvx true exch exec } { 0 rmoveto } ifelse } ifelse } for wlist 0 [ newfontcmd false ] put /welem 1 def /wlen 0 def /woids 0 def } if } def %%%%%%%%%%%%%%%%%%%%%%%%% - PrintClose - %%%%%%%%%%%%%%%%%%%%%%%% % PrintClose prints the words stored in the array "wlist" at Y location ypos % starting at X location bslot with left justification. /PrintClose { justify 102 eq % 102 is ascii 'f' { /justify 108 def % 108 is ascii 'l' for flushleft PrintWordList /justify 102 def } { PrintWordList } ifelse } bind def %%%%%%%%%%%%%%%% string Parse - %%%%%%%%%%%%%%%%%%%%%%%% % Parse breaks a string into words based on spaces, passing each to NextWord /Parse { dup length 0 eq % kill extra spaces by shaving them until null string { pop } { ( ) search { Parse pop Parse } { NW } ifelse } ifelse } bind def %%%%%%%%%%%%%%%%%%%%%%% string NextWord - %%%%%%%%%%%%%%%%%%%%%% % NextWord appends the string to an array of words % and tries to place the text inside an arbitrary path (which was analyzed % by InitWord). It's meant to be an iterative part of a long list of % "string NextWord" sets which justifies text inside any closed path. /NextWord { /word exch def word stringwidth pop /wordlen exch def GrabSpace } bind def %%%%%%%%%% Takes a horizontal distance and a string for positioning /GrabSpace { wordlen wlen add eslot bslot sub gt { PrintWordList word type /stringtype ne { /welem 0 def } if NextSpace { GrabSpace } { % Have reached end of page ENDPAGE STARTPAGE /ypos baselineskip ypos add def /vtotal baselineskip def NEWLINE GrabSpace } ifelse } { word type /stringtype eq { wlist welem word put /welem welem 1 add def /wlen wlen ( ) stringwidth pop add def /woids woids 1 add def } if /wlen wlen wordlen add def } ifelse } def %%%%%%%%%%%%%%%% xwidth HSpace - %%%%%%%%%%%%%% % Adds to the current wlen and adds the right thing in the wlist array /HSpace { dup wlen add /wlen exch def wlist welem 3 -1 roll put /welem welem 1 add def } bind def %%%%%%%%%%%%%%%%% size type NewFont %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % NewFont sets a new font, given a type and size /NewFont { { } forall /word exch def /newfontcmd exch def word wlist welem [ newfontcmd 5 -1 roll ] put /welem welem 1 add def false fontnames newfontcmd get cvx exec word true eq woids 0 gt and { /wlen wlen ( ) stringwidth pop sub def } if } bind def %%%%%%%%%%%%%% x y READJUST %%%%%%%%%%%%%% % Readjusts the line down by given amountif big fonts are being placed % in a small vertical space, and across if a horizontal space is being added. /READJUST { wtemp type /arraytype eq % Don't do recursive READJUSTs { pop pop } { /vspace exch def /wordlen exch def /welem welem 1 sub def GrabSpace vspace 0 ne { SKIPLINE } if % Skip to a new page if needed /wtemp wlist def /woids 0 def /wlen 0 def 0 1 welem /welem 0 def { wtemp exch get dup type /stringtype eq { NextWord } { dup type /arraytype eq { NewFont } { HSpace } ifelse } ifelse } for wordlen HSpace /wtemp 0 def } ifelse } bind def %%%% Skipline skips a given amount of vertical space /SKIPLINE { vspace 0 eq vspace vtotal gt or { vspace vtotal gt { /vspace vspace vtotal sub /vtotal vspace def def } if /ytemp ypos def true 20 % repeat { NextSpace not % did it get a new line successfully? { ENDPAGE STARTPAGE /ypos baselineskip ypos add def /vtotal baselineskip def NEWLINE } if ypos ytemp ne { pop false exit } if } repeat { % Did the repeat "fail" by falling off the end? erasepage grestoreall /Times-Roman findfont 20 scalefont setfont 50 100 moveto (Could not place words anywhere on the virtual page) show showpage quit } if } if } bind def %%%%%%%%%%%%%%%%%%%%% % Some startup definitions /para true def /vspace 0 def % User command definitions, meant to be called from outside /NW { NextWord } bind def /SHOWIT { show } bind def /NEWLINE { PrintWordList NextSpace pop } def /NEWPARA { PrintClose /para true def SKIPLINE } bind def /ENUMERATE { dup stringwidth pop 9 add bslot exch sub ypos moveto show } bind def /BULLET { newpath bslot 9 sub ( ) stringwidth pop 1.7 div dup ypos add exch 0 360 arc currentgray 0 setgray fill setgray } bind def /TIMESROMAN { pop /Times-Roman findfont 10 scalefont setfont } bind def /BASELINESKIP { /baselineskip exch def } bind def /STARTPAGE { end /savetype save def StartPage formatdict begin InitWord } def /ENDPAGE { PrintClose % Put all the variables we want to save on the stack baselineskip bottommargin parindent justify rightmargin leftmargin topmargin parskip newfontcmd para wordlen ypos ytemp word type /stringtype eq { mark word {} forall true } { word false } ifelse end savetype restore formatdict begin { counttomark string /word exch def counttomark 1 sub -1 0 { exch word 3 1 roll put % Builds word out of individual characters } for pop } { /word exch def } ifelse % Recover all the variables /ytemp exch def /ypos exch def /wordlen exch def /para exch def /newfontcmd exch def /parskip exch def /topmargin exch def /leftmargin exch def /rightmargin exch def /justify exch def /parindent exch def /bottommargin exch def /baselineskip exch def end EndPage formatdict begin } def