1 //                  ROFF for Multics
  2 //
  3 //  Last modified on 05/30/74 at 18:44:49 by R F Mabee.
  4 //
  5 //  This file contains the following miscellaneous routines used for ROFF:
  6 //
  7 //        Need                Eject paper if less than n lines at current spacing on page.
  8 //        NeedSS              Eject paper if less than n lines on page.
  9 //        Newline             Upspace paper n lines.
 10 //        SetLinesLeft        Keep track of lines left on page.
 11 //        Blank               Store n blanks into output.
 12 //        WriteChar           Write a character.
 13 //        PrinterIndent       Make output for printer start indented twenty spaces.
 14 //        StoreArabic         Convert number to character, decimal arabic numerals.
 15 //        StoreRoman          Convert number to roman numeral representation.
 16 //        StoreDate           Convert current date to character representation.
 17 //        ReadName            Read name from control line and pack into vector.
 18 //        Skiptolabel         Scan through input for particular label line.
 19 //        InsertFile          Use new input file.
 20 //  All are declared external.
 21 
 22 //  Copyright (c) 1974 by Massachusetts Institute of Technology and Honeywell Information Systems, Inc.
 23 
 24 //  General permission is granted to copy and use this program, but not to sell it, provided that the above
 25 //  copyright statement is given.  Contact Information Processing Services, MIT, for further information.
 26 //  Please contact R F Mabee at MIT for information on this program and versions for other machines.
 27 
 28 get "runoff_head"   // Declarations for ROFF.
 29 
 30 
 31 let Need (n) be     // Eject paper if less than n lines left.
 32           if n * Ms > LinesLeft do Eject ()
 33 
 34 and NeedSS (n) be   // Need for n lines, regardless of double spacing
 35           if n > LinesLeft do Eject ()
 36 
 37 and Newline (n) be  // Print n 'newline' characters.
 38      {    for i = 1 to n do
 39                {    test Ft
 40                     then $(   let P = Newvec (Fc + 1)
 41                               for j = 1 to Fc do P!(j + 1) := Footbuf!j
 42                               P!0, P!1 := 0, Fc
 43                               test FootListBase = 0
 44                               then FootListBase := P
 45                               or FootList!0 := P
 46                               FootList := P
 47                               Fl := Fl + 1
 48                               Fc := 0
 49                          $)
 50                     or   $(   WriteChar ('*n')
 51                               Nl := Nl + 1
 52                          $)
 53                }
 54           SetLinesLeft ()
 55      }
 56 
 57 and SetLinesLeft () be
 58           LinesLeft := Pl - Nl - Ma3 - Ma4 - Fl - (OddPage -> Of, Ef)!0
 59 
 60 and Blank (n) be
 61           for i = 1 to n do WriteChar ('*s')
 62 
 63 and WriteChar (c) be          // Write 'c' into output stream or footnote buffer.
 64      {    test Ft
 65           then {    Footbuf[Fc + 1] := c
 66                     Fc := Fc + 1
 67                }
 68           else if Print do
 69                {    if Charsw do WrCh (TrTable!c)
 70                     let Cc = Conv[c]
 71                     if Cc = Skip return
 72           //  Partially canonicalize output by eliminating space-backspace pairs.
 73           //  This is necessary because the printer DIM can't handle them.
 74           //  Whenever a space or backspace arrives, we delay printing it
 75           //  until the next character arrives.  Then if the two form a space-backspace
 76           //  pair, we don't put out either.  If the second is some other character,
 77           //  the held character has to be forced out first.
 78                     test Cc = '*s' | Cc = '*b'
 79                     then test SavedCc = 0
 80                               then $(   SavedCc := Cc
 81                                         return
 82                                    $)
 83                               or if SavedCc ne Cc do
 84                                    $(   SavedCc := 0
 85                                         return
 86                                    $)
 87                     or unless SavedCc = 0 do
 88                          $(   Writech (Output, SavedCc)
 89                               SavedCc := 0
 90                          $)
 91                     Writech (Output, Cc)
 92                 }
 93      }
 94 
 95 
 96 and PrinterIndent () be
 97   if Print logor Ft do
 98      $(   let p = 0
 99           if PrintLineNumbers do
100                $(   let v = vec 20
101                     StoreArabic (InputLines, v)
102                     p := v!0
103                     for i = p to 5 do WriteChar ('*s')
104                     for i = 1 to p do WriteChar (v!i)
105                     if p < 10 do
106                          $(   WriteChar ('*t')
107                               p := 10
108                          $)
109                $)
110           unless ExtraMargin = 0 do
111                $(   while p / 10 < ExtraMargin / 10 do
112                          $(   WriteChar ('*t')
113                               p := p + 10 - p rem 10
114                          $)
115                     while p < ExtraMargin do
116                          $(   WriteChar ('*s')
117                               p := p + 1
118                          $)
119                $)
120      $)
121 
122 and StoreArabic (n, v) be
123      $(   let w = vec 20
124           Unpackstring (ConvertNtoS (n, w), v)
125      $)
126 and StoreRoman (n, v) be
127      $(   let i, Wa, Wb = 0, vec 3, vec 3
128           let Ta, Tb = (table 'i', 'x', 'c', 'm') - 1, (table 'v', 'l', 'd') - 1
129           if n < 0 do n := -n
130           for j = 1 to 3 do
131                $(   let r = n rem 10
132                     Wa!j, Wb!j := r rem 5, r / 5
133                     n := n / 10
134                $)
135           if n > 20 do n := 20
136 
137           for j = 1 to n do
138                $(   i := i + 1
139                     v!i := 'm'
140                $)
141           for j = 3 to 1 by -1 do
142                     test Wa!j = 4
143                     then $(   i := i + 1
144                               v!i := Ta!j
145                               i := i + 1
146                               v!i := Wb!j = 0 -> Tb!j, Ta!(j + 1)
147                          $)
148                     or   $(   unless Wb!j = 0 do
149                                    $(   i := i + 1
150                                         v!i := Tb!j
151                                    $)
152                               for k = 1 to Wa!j do
153                                    $(   i := i + 1
154                                         v!i := Ta!j
155                                    $)
156                          $)
157           v!0 := i
158      $)
159 
160 let StoreDate (v) be
161      $(   let w = vec 10
162           FormDate (TimeNow, w, false)
163           v!1, v!2 := w!0 / 10 + '0', w!0 rem 10 + '0'
164           v!3 := '/'
165           v!4, v!5 := w!2 / 10 + '0', w!2 rem 10 + '0'
166           v!6 := '/'
167           v!7, v!8 := w!3 / 10 rem 10 + '0', w!3 rem 10 + '0'
168           v!0 := 8
169      $)
170 and ReadName (v) = valof
171      $(   let i = 0
172           let w = vec Maxline
173           while Nrx < Nr & Rawchar!Nrx ne '*s' do
174                $(   i := i + 1
175                     w!i := Rawchar!Nrx
176                     Nrx := Nrx + 1
177                $)
178           while Nrx < Nr & Rawchar!Nrx = '*s' do Nrx := Nrx + 1
179           w!0 := i
180           Packstring (w, v)
181           resultis i
182      $)
183 let Skiptolabel (Forward) be
184      $(   let L, v = Nr - 1, vec Maxline
185           for i = 1 to L do v!i := Rawchar!i
186           v!2, v!3 := 'l', 'a'
187           JumpLine := InputLines
188           unless Forward do Nx_reset ()
189 
190 Loop:     Nr := 0
191           Readline ()
192           if JumpLine < 0 do
193                $(   Nr := Nr + 1
194                     Report ("Target label not found")
195                     return
196                $)
197           unless Nr = L goto Loop
198           for i = 1 to L do unless v!i = Rawchar!i goto Loop
199           JumpLine := -1
200      $)
201 let InsertFile () be
202      $(   let v = vec Maxline / 4
203           if ReadName (v) = 0 do
204                $(   Report ("Missing file name")
205                     return
206                $)
207           Nx_open (v)
208           if Nrx < Nr do UpdateSymbol ("Parameter")
209      $)