source: trunk/minix/commands/cawf/pass3.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 12.9 KB
Line 
1/*
2 * pass3.c - cawf(1) pass 3 function
3 */
4
5/*
6 * Copyright (c) 1991 Purdue University Research Foundation,
7 * West Lafayette, Indiana 47907. All rights reserved.
8 *
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.
12 *
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:
16 *
17 * 1. The author is not responsible for any consequences of use of
18 * this software, even if they arise from flaws in it.
19 *
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.
23 *
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.
27 *
28 * 4. This notice may not be removed or altered.
29 */
30
31#include "cawf.h"
32
33void
34Pass3(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 */
39{
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 */
54
55 vsp = 0;
56 if (word != NULL)
57 wl = strlen((char *)word);
58 /*
59 * If not a special command, process a word.
60 */
61 if (len >= 0 && Outll < 0) {
62 /*
63 * Enter first word.
64 */
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)) {
71 /*
72 * The word fits, so enter it.
73 */
74 if ((Contlen + len) > 0) {
75line_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;
89 }
90 }
91 if (len > 0) {
92 (void) strcpy((char *)&Outln[Outlx],
93 (char *)word);
94 Outlx += wl;
95 }
96 }
97 }
98 Outll += Contlen + len;
99 } else if (len == NOBREAK || len == MESSAGE) {
100 /*
101 * Do nothing (equivalent to break)
102 */
103 } else if (len == DOBREAK && strcmp((char *)word, "need") == 0
104 && (Nxtln + narg) < (Pglen + 1 - Botmarg)) {
105 /*
106 * Do nothing, because there is room on the page.
107 */
108 } else if (len == DOBREAK && strcmp((char *)word, "toindent") == 0
109 && (Ind + Tind + Outll) < Ind) {
110 /*
111 * Move to indent position with line - there is room.
112 */
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)) {
124 /*
125 * A non-empty line or a "need" forces output.
126 */
127 vsp = 0;
128
129print_line:
130 if (Nxtln == 1) {
131 /*
132 * We're at the top of the page, so issue the header.
133 */
134 if (Thispg > 1)
135 Charput((int)'\f');
136 for (i = (Topmarg - 1)/2; i > 0; i--) {
137 Charput((int)'\n');
138 Nxtln++;
139 }
140 /*
141 * Print the page header, as required.
142 */
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++;
168 }
169 }
170 /*
171 * Add a trailing hyphen, if mecessary.
172 */
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;
180 }
181 /*
182 * Trim trailing spaces from the output line.
183 */
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--;
192 }
193 if (Outlx == 0)
194 Charput((int)'\n');
195 else if (len == DOBREAK && strcmp((char *)word, "center") == 0)
196 {
197 /*
198 * Center the output line.
199 */
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))) {
209 /*
210 * No right margin adjustment - disabled, inappropriate
211 * (line ended by break) or impossible.
212 */
213 for (i = 0; i < (Pgoff + Ind + Tind); i++)
214 Charput((int)' ');
215 Stringput(Outln);
216 Charput((int)'\n');
217 } else if (Adj == BOTHADJ) {
218 /*
219 * Adjust right margin.
220 */
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)' ');
240 }
241 while (*s1)
242 Charput((int)*s1++);
243 Charput((int)'\n');
244 Padfrom = (Padfrom == PADLEFT) ? PADRIGHT : PADLEFT;
245 }
246 /*
247 * End of line housekeeping
248 */
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) {
257 /*
258 * Break caused by "need" - satisfy it.
259 */
260 while (Nxtln < (Pglen + 1 - Botmarg)) {
261 Charput((int)'\n');
262 Nxtln++;
263 }
264 }
265 if (Nxtln >= (Pglen + 1 - Botmarg)) {
266 /*
267 * Footer required
268 */
269 for (i = (Botmarg - 1)/2; i > 0; i--) {
270 Charput((int)'\n');
271 Nxtln++;
272 }
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++;
291 /*
292 * The last blank line on the page is suppressed to assist
293 * printers that can't look ahead to the following FF.
294 */
295 while (Nxtln < Pglen) {
296 Charput((int)'\n');
297 Nxtln++;
298 }
299 Nxtln = 1;
300 Thispg++;
301 Nospmode = 1;
302 Padfrom = PADRIGHT;
303 }
304 /*
305 * Initiate any extra vertical spacing.
306 */
307 if (++vsp < Vspace)
308 goto print_line;
309 /*
310 * Save any input word that might have forced output.
311 */
312 if (len >= 0) {
313 (void) strcpy((char *)Outln, (char *)word);
314 Outll = len;
315 Outlx = wl;
316 Padx = 0;
317 }
318 }
319 /*
320 * A break causes padding reversal.
321 */
322 if (len == DOBREAK)
323 Padfrom = PADRIGHT;
324 if (len >= 0 || strcmp((char *)word, "nohyphen") == 0) {
325 /*
326 * Reset continuation and hyphenation.
327 */
328 if (Contlen != 1 || Cont[0] != ' ') {
329 Free(&Cont);
330 Cont = Newstr((unsigned char *)" ");
331 Contlen = 1;
332 }
333 if (Eollen > 0) {
334 Free(&Eol);
335 Eollen = 0;
336 }
337 return;
338 }
339 /*
340 * Now post-process any special commands.
341 */
342 if (len == MESSAGE) {
343 Error3(len, (char *)word, (char *)sarg, narg, NULL);
344 return;
345 }
346
347 switch (*word) {
348
349 case 'b': /* both */
350 /*
351 * Adjust on both margins.
352 */
353 Adj = BOTHADJ;
354 return;
355
356 case 'c': /* center */
357 return;
358
359 case 'e': /* errsto */
360 /*
361 * "errsto" comes from awf.
362 */
363 return;
364
365 case 'f': /* flush and fph */
366 if (word[1] == 'l')
367 return;
368 else if (word[1] == 'p') {
369 /*
370 * First page header status
371 */
372 Fph = narg;
373 return;
374 }
375 break;
376
377 case 'g': /* gap */
378 /*
379 * Increase word gap. (Space is not paddable.)
380 */
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++;
387 }
388 }
389 return;
390
391 case 'h': /* hyphen */
392 /*
393 * Set discretionary hyphen.
394 */
395 Free(&Cont);
396 Contlen = 0;
397 Free(&Eol);
398 Eol = (sarg != NULL) ? Newstr(sarg) : NULL;
399 Eollen = narg;
400 return;
401
402 case 'i': /* indent */
403 /*
404 * Set indentation.
405 */
406 Ind = narg;
407 return;
408
409 case 'l': /* left or linelen */
410 if (word[1] == 'e') {
411 /*
412 * Adjust on left margin.
413 */
414 Adj = LEFTADJ;
415 return;
416 } else if (word[1] == 'i') {
417 /*
418 * Set line length.
419 */
420 LL = narg;
421 return;
422 }
423 break;
424
425 case 'n': /* need or nospace */
426 if (word[1] == 'e')
427 return; /* need */
428 else if (word[1] == 'o') {
429 /*
430 * Set no space mode.
431 */
432 Nospmode = 1;
433 return;
434 }
435 break;
436
437 case 'p': /* pagelen or pageoffset */
438 if (strncmp((char *)&word[1], "age", 3) != 0)
439 break;
440 if (word[4] == 'l') {
441 /*
442 * Set page length.
443 */
444 Pglen = narg;
445 return;
446 } else if (word[4] == 'o') {
447 /*
448 * Set page offset.
449 */
450 Pgoff = narg;
451 return;
452 }
453 break;
454
455 case 's': /* space */
456 if (sp) {
457
458 /*
459 * Restore values after NOBREAK spacing ("^'sp").
460 */
461 Outlx = sp_Outlx;
462 Outln[0] = sp_Outln;
463 Padx = sp_Padx;
464 Outll = sp_Outll;
465 Tind = sp_Tind;
466 return;
467 }
468 if (Nospmode == 0) {
469 if (len == NOBREAK) {
470
471 /*
472 * Set up for NOBREAK spacing.
473 */
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;
481 }
482 /*
483 * Generate a blank line.
484 */
485 Outlx = 0;
486 Outln[0] = '\0';
487 Padx = 0;
488 Outll = LL - 1;
489 if (sp)
490 goto print_line;
491 }
492 return;
493
494 case 't': /* tabto, tempindent, or
495 * toindent */
496 if (word[1] == 'a') {
497 /*
498 * Move to TAB stop.
499 */
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;
511 }
512 return;
513 } else if (word[1] == 'e') {
514 /*
515 * Set temporary indentation.
516 */
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;
525
526 case 'u': /* userhyphen */
527 /*
528 * Set line length.
529 */
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;
536
537 case 'v': /* vspace */
538 /*
539 * Set vertical spacing.
540 */
541 Vspace = (narg == 0) ? 1 : narg;
542 return;
543
544 case 'y': /* yesspace */
545 /*
546 * Set space mode.
547 */
548 Nospmode = 0;
549 return;
550 } /* end of switch(*word) */
551 /*
552 * Locate header and footer defintions.
553 */
554 if (regexec(Pat[14].pat, word)) {
555 if (strcmp((char *)word, "LH") == 0) {
556 /*
557 * Left header
558 */
559 Free(&Hdl);
560 if (sarg != NULL)
561 Hdl = Newstr(sarg);
562 return;
563 }
564 if (strcmp((char *)word, "CH") == 0) {
565 /*
566 * Center header
567 */
568 Free(&Hdc);
569 if (sarg != NULL)
570 Hdc = Newstr(sarg);
571 return;
572 }
573 if (strcmp((char *)word, "RH") == 0) {
574 /*
575 * Right header
576 */
577 Free(&Hdr);
578 if (sarg != NULL)
579 Hdr = Newstr(sarg);
580 return;
581 }
582 if (strcmp((char *)word, "LF") == 0) {
583 /*
584 * Left footer
585 */
586 Free(&Ftl);
587 if (sarg != NULL)
588 Ftl = Newstr(sarg);
589 return;
590 }
591 if (strcmp((char *)word, "CF") == 0) {
592 /*
593 * Center footer
594 */
595 Free(&Ftc);
596 if (sarg != NULL)
597 Ftc = Newstr(sarg);
598 return;
599 }
600 if (strcmp((char *)word, "RF") == 0) {
601 /*
602 * Right footer
603 */
604 Free(&Ftr);
605 if (sarg != NULL)
606 Ftr = Newstr(sarg);
607 return;
608 }
609 }
610 /*
611 * Error on unknown arguments
612 */
613 Error3(len, (char *)word, (char *)sarg, narg, "unknown request");
614}
Note: See TracBrowser for help on using the repository browser.