minor fixes for safecopy & safemap tests
[minix.git] / commands / cawf / pass3.c
blobabacbfa3cb95a4eaf808f887272ff41b33a12a15
1 /*
2 * pass3.c - cawf(1) pass 3 function
3 */
5 /*
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
22 * documentation.
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.
31 #include "cawf.h"
33 void
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 */
55 vsp = 0;
56 if (word != NULL)
57 wl = strlen((char *)word);
59 * If not a special command, process a word.
61 if (len >= 0 && Outll < 0) {
63 * Enter first word.
65 (void) strcpy((char *)Outln, (char *)word);
66 Outll = len;
67 Outlx = wl;
68 Padx = 0;
69 } else if (len >= 0
70 && (Outll+Contlen+len+narg) <= (LL-Pgoff-Ind-Tind)) {
72 * The word fits, so enter it.
74 if ((Contlen + len) > 0) {
75 line_too_big:
76 if ((Outlx + Contlen + wl) >= MAXOLL) {
77 Error3(len, (char *)word, (char *)sarg, narg,
78 "output line too big");
79 return;
80 } else {
81 if (Contlen > 0 && Cont != NULL) {
82 if (Contlen == 1 && *Cont == ' ') {
83 Padchar[Padx++] = Outlx;
84 Outln[Outlx++] = ' ';
85 } else {
86 (void) strcpy((char *)&Outln[Outlx],
87 (char *)Cont);
88 Outlx += Contlen;
91 if (len > 0) {
92 (void) strcpy((char *)&Outln[Outlx],
93 (char *)word);
94 Outlx += wl;
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);
114 Outll += n;
115 if ((Outlx + n) >= MAXOLL)
116 goto line_too_big;
117 for (i = n; i; i--)
118 Outln[Outlx++] = ' ';
119 Padx = 0;
120 Free(&Cont);
121 Contlen = 0;
122 } else if (Outll >= 0
123 || (len == DOBREAK && strcmp((char *)word, "need") == 0)) {
125 * A non-empty line or a "need" forces output.
127 vsp = 0;
129 print_line:
130 if (Nxtln == 1) {
132 * We're at the top of the page, so issue the header.
134 if (Thispg > 1)
135 Charput((int)'\f');
136 for (i = (Topmarg - 1)/2; i > 0; i--) {
137 Charput((int)'\n');
138 Nxtln++;
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++)
150 Charput((int)' ');
151 if (Hdl)
152 LenprtHF(Hdl, Thispg, 1);
153 while (j-- > 0)
154 Charput((int)' ');
155 if (Hdc)
156 LenprtHF(Hdc, Thispg, 1);
157 while (n-- > 0)
158 Charput((int)' ');
159 if (Hdr)
160 LenprtHF(Hdr, Thispg, 1);
161 Charput((int)'\n');
162 } else
163 Charput((int)'\n');
164 Nxtln++;
165 while(Nxtln <= Topmarg) {
166 Charput((int)'\n');
167 Nxtln++;
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)
176 goto line_too_big;
177 (void) strcpy((char *)&Outln[Outlx], (char *)Eol);
178 Outlx += i;
179 Outll += Eollen;
182 * Trim trailing spaces from the output line.
184 while (Outlx > 0) {
185 if (Outln[Outlx - 1] != ' ')
186 break;
187 if (Padx > 0 && (Outlx - 1) == Padchar[Padx - 1])
188 Padx--;
189 Outlx--;
190 Outln[Outlx] = '\0';
191 Outll--;
193 if (Outlx == 0)
194 Charput((int)'\n');
195 else if (len == DOBREAK && strcmp((char *)word, "center") == 0)
198 * Center the output line.
200 i = (LL - Pgoff - Outll) / 2;
201 if (i < 0)
202 i = 0;
203 for (j = (Pgoff + Ind + Tind + i); j; j--)
204 Charput((int)' ');
205 Stringput(Outln);
206 Charput((int)'\n');
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++)
214 Charput((int)' ');
215 Stringput(Outln);
216 Charput((int)'\n');
217 } else if (Adj == BOTHADJ) {
219 * Adjust right margin.
221 for (i = 0; i < (Pgoff + Ind + Tind); i++)
222 Charput((int)' ');
223 i = LL - (Pgoff + Ind + Tind);
224 j = i - Outll;
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])
229 Charput((int)*s1++);
230 if (*s1 == '\0')
231 break;
232 j = addto;
233 if (Padfrom == PADLEFT) {
234 if (i < xsp)
235 j++;
236 } else if (i >= (Padx - xsp))
237 j++;
238 while (j-- > 0)
239 Charput((int)' ');
241 while (*s1)
242 Charput((int)*s1++);
243 Charput((int)'\n');
244 Padfrom = (Padfrom == PADLEFT) ? PADRIGHT : PADLEFT;
247 * End of line housekeeping
249 Nxtln++;
250 Outll = -1;
251 Outlx = 0;
252 Padx = 0;
253 Tind = 0;
254 Nospmode = 0;
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)) {
261 Charput((int)'\n');
262 Nxtln++;
265 if (Nxtln >= (Pglen + 1 - Botmarg)) {
267 * Footer required
269 for (i = (Botmarg - 1)/2; i > 0; i--) {
270 Charput((int)'\n');
271 Nxtln++;
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++)
278 Charput((int)' ');
279 if (Ftl)
280 LenprtHF(Ftl, Thispg, 1);
281 while (j-- > 0)
282 Charput((int)' ');
283 if (Ftc)
284 LenprtHF(Ftc, Thispg, 1);
285 while (n-- > 0)
286 Charput((int)' ');
287 if (Ftr)
288 LenprtHF(Ftr, Thispg, 1);
289 Charput((int)'\n');
290 Nxtln++;
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) {
296 Charput((int)'\n');
297 Nxtln++;
299 Nxtln = 1;
300 Thispg++;
301 Nospmode = 1;
302 Padfrom = PADRIGHT;
305 * Initiate any extra vertical spacing.
307 if (++vsp < Vspace)
308 goto print_line;
310 * Save any input word that might have forced output.
312 if (len >= 0) {
313 (void) strcpy((char *)Outln, (char *)word);
314 Outll = len;
315 Outlx = wl;
316 Padx = 0;
320 * A break causes padding reversal.
322 if (len == DOBREAK)
323 Padfrom = PADRIGHT;
324 if (len >= 0 || strcmp((char *)word, "nohyphen") == 0) {
326 * Reset continuation and hyphenation.
328 if (Contlen != 1 || Cont[0] != ' ') {
329 Free(&Cont);
330 Cont = Newstr((unsigned char *)" ");
331 Contlen = 1;
333 if (Eollen > 0) {
334 Free(&Eol);
335 Eollen = 0;
337 return;
340 * Now post-process any special commands.
342 if (len == MESSAGE) {
343 Error3(len, (char *)word, (char *)sarg, narg, NULL);
344 return;
347 switch (*word) {
349 case 'b': /* both */
351 * Adjust on both margins.
353 Adj = BOTHADJ;
354 return;
356 case 'c': /* center */
357 return;
359 case 'e': /* errsto */
361 * "errsto" comes from awf.
363 return;
365 case 'f': /* flush and fph */
366 if (word[1] == 'l')
367 return;
368 else if (word[1] == 'p') {
370 * First page header status
372 Fph = narg;
373 return;
375 break;
377 case 'g': /* gap */
379 * Increase word gap. (Space is not paddable.)
381 if (Outll >= 0) {
382 if ((Outlx + narg - 1) >= MAXOLL)
383 goto line_too_big;
384 for (i = 0; i < (narg - 1); i++) {
385 Outln[Outlx++] = ' ';
386 Outll++;
389 return;
391 case 'h': /* hyphen */
393 * Set discretionary hyphen.
395 Free(&Cont);
396 Contlen = 0;
397 Free(&Eol);
398 Eol = (sarg != NULL) ? Newstr(sarg) : NULL;
399 Eollen = narg;
400 return;
402 case 'i': /* indent */
404 * Set indentation.
406 Ind = narg;
407 return;
409 case 'l': /* left or linelen */
410 if (word[1] == 'e') {
412 * Adjust on left margin.
414 Adj = LEFTADJ;
415 return;
416 } else if (word[1] == 'i') {
418 * Set line length.
420 LL = narg;
421 return;
423 break;
425 case 'n': /* need or nospace */
426 if (word[1] == 'e')
427 return; /* need */
428 else if (word[1] == 'o') {
430 * Set no space mode.
432 Nospmode = 1;
433 return;
435 break;
437 case 'p': /* pagelen or pageoffset */
438 if (strncmp((char *)&word[1], "age", 3) != 0)
439 break;
440 if (word[4] == 'l') {
442 * Set page length.
444 Pglen = narg;
445 return;
446 } else if (word[4] == 'o') {
448 * Set page offset.
450 Pgoff = narg;
451 return;
453 break;
455 case 's': /* space */
456 if (sp) {
459 * Restore values after NOBREAK spacing ("^'sp").
461 Outlx = sp_Outlx;
462 Outln[0] = sp_Outln;
463 Padx = sp_Padx;
464 Outll = sp_Outll;
465 Tind = sp_Tind;
466 return;
468 if (Nospmode == 0) {
469 if (len == NOBREAK) {
472 * Set up for NOBREAK spacing.
474 sp_Outlx = Outlx;
475 sp_Outln = Outln[0];
476 sp_Padx = Padx;
477 sp_Outll = Outll;
478 sp_Tind = Tind;
479 vsp = Vspace + 1;
480 sp = 1;
483 * Generate a blank line.
485 Outlx = 0;
486 Outln[0] = '\0';
487 Padx = 0;
488 Outll = LL - 1;
489 if (sp)
490 goto print_line;
492 return;
494 case 't': /* tabto, tempindent, or
495 * toindent */
496 if (word[1] == 'a') {
498 * Move to TAB stop.
500 if (Outll < 0)
501 Outll = 0;
502 if ((n = narg - Outll) > 0) {
503 if ((Outlx + n) >= MAXOLL)
504 goto line_too_big;
505 Outll += n;
506 for (i = n; i > 0; i--)
507 Outln[Outlx++] = ' ';
508 Free(&Cont);
509 Contlen = 0;
510 Padx = 0;
512 return;
513 } else if (word[1] == 'e') {
515 * Set temporary indentation.
517 if (*sarg == '\0' && narg >= 0)
518 Tind = narg - Ind;
519 else
520 Tind = ((Ind + narg) >= 0) ? narg : -Ind;
521 return;
522 } else if (word[1] == 'o')
523 return; /* toindent */
524 break;
526 case 'u': /* userhyphen */
528 * Set line length.
530 Free(&Cont);
531 Free(&Eol);
532 Contlen = Eollen = narg;
533 Cont = (sarg == NULL) ? NULL : Newstr(sarg);
534 Eol = (sarg == NULL) ? NULL : Newstr(sarg);
535 return;
537 case 'v': /* vspace */
539 * Set vertical spacing.
541 Vspace = (narg == 0) ? 1 : narg;
542 return;
544 case 'y': /* yesspace */
546 * Set space mode.
548 Nospmode = 0;
549 return;
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) {
557 * Left header
559 Free(&Hdl);
560 if (sarg != NULL)
561 Hdl = Newstr(sarg);
562 return;
564 if (strcmp((char *)word, "CH") == 0) {
566 * Center header
568 Free(&Hdc);
569 if (sarg != NULL)
570 Hdc = Newstr(sarg);
571 return;
573 if (strcmp((char *)word, "RH") == 0) {
575 * Right header
577 Free(&Hdr);
578 if (sarg != NULL)
579 Hdr = Newstr(sarg);
580 return;
582 if (strcmp((char *)word, "LF") == 0) {
584 * Left footer
586 Free(&Ftl);
587 if (sarg != NULL)
588 Ftl = Newstr(sarg);
589 return;
591 if (strcmp((char *)word, "CF") == 0) {
593 * Center footer
595 Free(&Ftc);
596 if (sarg != NULL)
597 Ftc = Newstr(sarg);
598 return;
600 if (strcmp((char *)word, "RF") == 0) {
602 * Right footer
604 Free(&Ftr);
605 if (sarg != NULL)
606 Ftr = Newstr(sarg);
607 return;
611 * Error on unknown arguments
613 Error3(len, (char *)word, (char *)sarg, narg, "unknown request");