2 * pass3.c - cawf(1) pass 3 function
6 * Copyright (c) 1991 Purdue University Research Foundation,
7 * West Lafayette, Indiana 47907. All rights reserved.
9 * Written by Victor A. Abell <abe@mace.cc.purdue.edu>, Purdue
10 * University Computing Center. Not derived from licensed software;
11 * derived from awf(1) by Henry Spencer of the University of Toronto.
13 * Permission is granted to anyone to use this software for any
14 * purpose on any computer system, and to alter it and redistribute
15 * it freely, subject to the following restrictions:
17 * 1. The author is not responsible for any consequences of use of
18 * this software, even if they arise from flaws in it.
20 * 2. The origin of this software must not be misrepresented, either
21 * by explicit claim or by omission. Credits must appear in the
24 * 3. Altered versions must be plainly marked as such, and must not
25 * be misrepresented as being the original software. Credits must
26 * appear in the documentation.
28 * 4. This notice may not be removed or altered.
34 Pass3(len
, word
, sarg
, narg
)
35 int len
; /* length (negative is special) */
36 unsigned char *word
; /* word */
37 unsigned char *sarg
; /* string argument */
38 int narg
; /* numeric argument */
40 int addto
; /* spaces to add to all words */
41 int i
, j
, k
; /* temporary index */
42 unsigned char msg
[MAXLINE
]; /* message buffer */
43 int n
; /* temporary number */
44 unsigned char *s1
; /* temporary string pointer */
45 int sp
= 0; /* no-break spacing switch */
46 int sp_Outll
; /* sp-saved Outll */
47 char sp_Outln
; /* sp-saved Outln[0] */
48 int sp_Outlx
; /* sp-saved Outlx */
49 int sp_Padx
; /* sp-saved Padx */
50 int sp_Tind
; /* sp-saved Tind */
51 int wl
; /* real word length */
52 int xsp
; /* extra spaces to add */
53 int vsp
; /* vertical spacing status */
57 wl
= strlen((char *)word
);
59 * If not a special command, process a word.
61 if (len
>= 0 && Outll
< 0) {
65 (void) strcpy((char *)Outln
, (char *)word
);
70 && (Outll
+Contlen
+len
+narg
) <= (LL
-Pgoff
-Ind
-Tind
)) {
72 * The word fits, so enter it.
74 if ((Contlen
+ len
) > 0) {
76 if ((Outlx
+ Contlen
+ wl
) >= MAXOLL
) {
77 Error3(len
, (char *)word
, (char *)sarg
, narg
,
78 "output line too big");
81 if (Contlen
> 0 && Cont
!= NULL
) {
82 if (Contlen
== 1 && *Cont
== ' ') {
83 Padchar
[Padx
++] = Outlx
;
86 (void) strcpy((char *)&Outln
[Outlx
],
92 (void) strcpy((char *)&Outln
[Outlx
],
98 Outll
+= Contlen
+ len
;
99 } else if (len
== NOBREAK
|| len
== MESSAGE
) {
101 * Do nothing (equivalent to break)
103 } else if (len
== DOBREAK
&& strcmp((char *)word
, "need") == 0
104 && (Nxtln
+ narg
) < (Pglen
+ 1 - Botmarg
)) {
106 * Do nothing, because there is room on the page.
108 } else if (len
== DOBREAK
&& strcmp((char *)word
, "toindent") == 0
109 && (Ind
+ Tind
+ Outll
) < Ind
) {
111 * Move to indent position with line - there is room.
113 n
= Ind
- (Ind
+ Tind
+Outll
);
115 if ((Outlx
+ n
) >= MAXOLL
)
118 Outln
[Outlx
++] = ' ';
122 } else if (Outll
>= 0
123 || (len
== DOBREAK
&& strcmp((char *)word
, "need") == 0)) {
125 * A non-empty line or a "need" forces output.
132 * We're at the top of the page, so issue the header.
136 for (i
= (Topmarg
- 1)/2; i
> 0; i
--) {
141 * Print the page header, as required.
143 if (Fph
|| Thispg
> 1) {
144 i
= LenprtHF(Hdc
, Thispg
, 0)
145 + LenprtHF(Hdl
, Thispg
, 0)
146 + LenprtHF(Hdr
, Thispg
, 0) + 2;
147 j
= (LL
- i
- Pgoff
) / 2 + 1;
148 n
= LL
- Pgoff
- i
- j
+ 2;
149 for (k
= 0; k
< Pgoff
; k
++)
152 LenprtHF(Hdl
, Thispg
, 1);
156 LenprtHF(Hdc
, Thispg
, 1);
160 LenprtHF(Hdr
, Thispg
, 1);
165 while(Nxtln
<= Topmarg
) {
171 * Add a trailing hyphen, if mecessary.
173 if (vsp
== 0 && Eollen
> 0 && Eol
!= NULL
) {
174 i
= strlen((char *)Eol
);
175 if ((Outlx
+ i
) >= MAXOLL
)
177 (void) strcpy((char *)&Outln
[Outlx
], (char *)Eol
);
182 * Trim trailing spaces from the output line.
185 if (Outln
[Outlx
- 1] != ' ')
187 if (Padx
> 0 && (Outlx
- 1) == Padchar
[Padx
- 1])
195 else if (len
== DOBREAK
&& strcmp((char *)word
, "center") == 0)
198 * Center the output line.
200 i
= (LL
- Pgoff
- Outll
) / 2;
203 for (j
= (Pgoff
+ Ind
+ Tind
+ i
); j
; j
--)
207 } else if (Adj
== LEFTADJ
208 || (Adj
== BOTHADJ
&& (len
< 0 || Padx
== 0))) {
210 * No right margin adjustment - disabled, inappropriate
211 * (line ended by break) or impossible.
213 for (i
= 0; i
< (Pgoff
+ Ind
+ Tind
); i
++)
217 } else if (Adj
== BOTHADJ
) {
219 * Adjust right margin.
221 for (i
= 0; i
< (Pgoff
+ Ind
+ Tind
); i
++)
223 i
= LL
- (Pgoff
+ Ind
+ Tind
);
225 addto
= Padx
? (j
/ Padx
) : 0;
226 xsp
= j
- (Padx
* addto
);
227 for (i
= 0, s1
= Outln
; i
< Padx
; i
++) {
228 while (*s1
&& (s1
- Outln
) <= Padchar
[i
])
233 if (Padfrom
== PADLEFT
) {
236 } else if (i
>= (Padx
- xsp
))
244 Padfrom
= (Padfrom
== PADLEFT
) ? PADRIGHT
: PADLEFT
;
247 * End of line housekeeping
255 if (vsp
== 0 && len
== DOBREAK
256 && strcmp((char *)word
, "need") == 0) {
258 * Break caused by "need" - satisfy it.
260 while (Nxtln
< (Pglen
+ 1 - Botmarg
)) {
265 if (Nxtln
>= (Pglen
+ 1 - Botmarg
)) {
269 for (i
= (Botmarg
- 1)/2; i
> 0; i
--) {
273 i
= LenprtHF(Ftl
, Thispg
, 0) + LenprtHF(Ftc
, Thispg
, 0)
274 + LenprtHF(Ftr
, Thispg
, 0) + 2;
275 j
= (LL
- i
- Pgoff
) / 2 + 1;
276 n
= LL
- Pgoff
- i
- j
+ 2;
277 for (k
= 0; k
< Pgoff
; k
++)
280 LenprtHF(Ftl
, Thispg
, 1);
284 LenprtHF(Ftc
, Thispg
, 1);
288 LenprtHF(Ftr
, Thispg
, 1);
292 * The last blank line on the page is suppressed to assist
293 * printers that can't look ahead to the following FF.
295 while (Nxtln
< Pglen
) {
305 * Initiate any extra vertical spacing.
310 * Save any input word that might have forced output.
313 (void) strcpy((char *)Outln
, (char *)word
);
320 * A break causes padding reversal.
324 if (len
>= 0 || strcmp((char *)word
, "nohyphen") == 0) {
326 * Reset continuation and hyphenation.
328 if (Contlen
!= 1 || Cont
[0] != ' ') {
330 Cont
= Newstr((unsigned char *)" ");
340 * Now post-process any special commands.
342 if (len
== MESSAGE
) {
343 Error3(len
, (char *)word
, (char *)sarg
, narg
, NULL
);
351 * Adjust on both margins.
356 case 'c': /* center */
359 case 'e': /* errsto */
361 * "errsto" comes from awf.
365 case 'f': /* flush and fph */
368 else if (word
[1] == 'p') {
370 * First page header status
379 * Increase word gap. (Space is not paddable.)
382 if ((Outlx
+ narg
- 1) >= MAXOLL
)
384 for (i
= 0; i
< (narg
- 1); i
++) {
385 Outln
[Outlx
++] = ' ';
391 case 'h': /* hyphen */
393 * Set discretionary hyphen.
398 Eol
= (sarg
!= NULL
) ? Newstr(sarg
) : NULL
;
402 case 'i': /* indent */
409 case 'l': /* left or linelen */
410 if (word
[1] == 'e') {
412 * Adjust on left margin.
416 } else if (word
[1] == 'i') {
425 case 'n': /* need or nospace */
428 else if (word
[1] == 'o') {
437 case 'p': /* pagelen or pageoffset */
438 if (strncmp((char *)&word
[1], "age", 3) != 0)
440 if (word
[4] == 'l') {
446 } else if (word
[4] == 'o') {
455 case 's': /* space */
459 * Restore values after NOBREAK spacing ("^'sp").
469 if (len
== NOBREAK
) {
472 * Set up for NOBREAK spacing.
483 * Generate a blank line.
494 case 't': /* tabto, tempindent, or
496 if (word
[1] == 'a') {
502 if ((n
= narg
- Outll
) > 0) {
503 if ((Outlx
+ n
) >= MAXOLL
)
506 for (i
= n
; i
> 0; i
--)
507 Outln
[Outlx
++] = ' ';
513 } else if (word
[1] == 'e') {
515 * Set temporary indentation.
517 if (*sarg
== '\0' && narg
>= 0)
520 Tind
= ((Ind
+ narg
) >= 0) ? narg
: -Ind
;
522 } else if (word
[1] == 'o')
523 return; /* toindent */
526 case 'u': /* userhyphen */
532 Contlen
= Eollen
= narg
;
533 Cont
= (sarg
== NULL
) ? NULL
: Newstr(sarg
);
534 Eol
= (sarg
== NULL
) ? NULL
: Newstr(sarg
);
537 case 'v': /* vspace */
539 * Set vertical spacing.
541 Vspace
= (narg
== 0) ? 1 : narg
;
544 case 'y': /* yesspace */
550 } /* end of switch(*word) */
552 * Locate header and footer defintions.
554 if (regexec(Pat
[14].pat
, word
)) {
555 if (strcmp((char *)word
, "LH") == 0) {
564 if (strcmp((char *)word
, "CH") == 0) {
573 if (strcmp((char *)word
, "RH") == 0) {
582 if (strcmp((char *)word
, "LF") == 0) {
591 if (strcmp((char *)word
, "CF") == 0) {
600 if (strcmp((char *)word
, "RF") == 0) {
611 * Error on unknown arguments
613 Error3(len
, (char *)word
, (char *)sarg
, narg
, "unknown request");