1 /*
2 * Copyright (C) 1991,1992 NEC Corporation.
3 */
4 #ifndef lint
5 static char rcsid[]=
6 "$Id: headfoot.c,v 2.9 1994/04/19 10:16:22 uchida Exp $ (NEC)";
7 #endif
8
9 #include <stdio.h>
10 #include <ctype.h>
11 #include "plain2.h"
12 /*
13 * Extract Page boundaries (including header & footer) from input text.
14 */
15 #define HF_DISTANCE 3 /* Max header/footer distance from ^L */
16 #define HF_MAXLEN 64 /* Max length of header/footer string */
17 /*
18 * - xx -
19 * ^L
20 * plain2 1990/12/24
21 */
22 struct headerLine {
23 char left[HF_MAXLEN];
24 char right[HF_MAXLEN];
25 char center[HF_MAXLEN];
26 } origHeader, origFooter, curHeader, curFooter;
27 int footerPos;
28 int headerPos;
29 /*
30 * Look for header/footer lines from page boundary (^L)
31 */
pickUpLine(l,headerp,footerp,begin,end)32 pickUpLine(l, headerp, footerp, begin, end)
33 int l;
34 char **headerp;
35 char **footerp;
36 int begin;
37 int end;
38 {
39 int d;
40 for (d = 1; d < HF_DISTANCE && l - d > begin; d++)
41 if (!texts[l - d]->blank) {
42 *footerp = texts[l - d]->body;
43 break;
44 }
45 footerPos = d;
46 for (d = 1; d < HF_DISTANCE && l + d < end; d++)
47 if (!texts[l + d]->blank) {
48 *headerp = texts[l + d]->body;
49 break;
50 }
51 headerPos = d;
52 }
53 /*
54 * Two strings have same header/footer format
55 * (two lines are same except for page number field)
56 */
sameFormat2(s1,s2)57 sameFormat2(s1, s2)
58 char *s1;
59 char *s2;
60 {
61 char *t1, *t2;
62 int len1, len2;
63 char *s;
64 DBG2(4, "sameFormat2 <%s><%s>", s1, s2);
65 len1 = strlen(s1);
66 len2 = strlen(s2);
67 t1 = s1 + len1 - 1;
68 t2 = s2 + len2 - 1;
69 /*
70 * from left to right
71 */
72 for (; *s1 && * s2; s1++, s2++)
73 if (*s1 != *s2)
74 break;
75 /*
76 * from right to left
77 */
78 for (; t1 >= s1 && t2 >= s2; t1--, t2--)
79 if (*t1 != *t2)
80 break;
81 for (s = s1; s <= t1; s++)
82 if (!isdigit(*s))
83 return 0;
84 for (s = s2; s <= t2; s++)
85 if (!isdigit(*s))
86 return 0;
87 return 1;
88 }
89 sameFormat(hdr1, hdr2)
90 struct headerLine *hdr1;
91 struct headerLine *hdr2;
92 {
93 return (sameFormat2(hdr1->left, hdr2->left)
94 && sameFormat2(hdr1->center, hdr2->center)
95 && sameFormat2(hdr1->right, hdr2->right));
96 }
97 /*
98 * Build a Header field
99 */
headerFields(str,hdrp)100 headerFields(str, hdrp)
101 char *str;
102 struct headerLine *hdrp;
103 {
104 char *s, *t, *save;
105 char *centerLeft, *centerRight;
106 /*
107 * from Center to Both side
108 */
109 for (centerLeft = str + rightMargin * 2 / 5;
110 centerLeft >= str; centerLeft--) {
111 if (centerLeft - 3 >= str
112 && !strncmp(centerLeft - 3, " ", 3))
113 break;
114 }
115 for (; centerLeft < str + strlen(str) ; centerLeft++)
116 if (*centerLeft != ' ')
117 break;
118 if (centerLeft <= str || centerLeft > str + rightMargin * 3 / 5) {
119 centerLeft = str + rightMargin / 5;
120 centerRight = str + rightMargin / 2;
121 *hdrp->center = '\0';
122 }
123 else {
124 for (centerRight = centerLeft;
125 centerRight < str + strlen(str) ; centerRight++) {
126 if (!strncmp(centerRight, " ", 3)
127 || *centerRight == '\0')
128 break;
129 }
130 for (save = hdrp->center, t = centerLeft;
131 t < centerRight; t++, save++)
132 *save = *t;
133 *save = '\0';
134 }
135 /*
136 * from Left to Center
137 */
138 for (s = str; *s && s < centerLeft; s++) {
139 if (!strncmp(s, " ", 3))
140 break;
141 }
142 for (save = hdrp->left, t = str; t < s; t++, save++)
143 *save = *t;
144 *save = '\0';
145 /*
146 * from Right to Center
147 */
148 for (s = str + strlen(str) - 1; s > centerRight; s--) {
149 if (s - 3 >= str && !strncmp(s - 3, " ", 3))
150 break;
151 }
152 for (save = hdrp->right, t = s; t > centerRight
153 && t < str + strlen(str); t++, save++)
154 *save = *t;
155 *save = '\0';
156 }
build(str1,str2,fstr1,fstr2)157 build(str1, str2, fstr1, fstr2)
158 char *str1;
159 char *str2;
160 char *fstr1;
161 char *fstr2;
162 {
163 char *t1, *t2;
164 char *s1, *s2;
165 int len1, len2;
166 char *s;
167
168 len1 = strlen(str1);
169 len2 = strlen(str2);
170 t1 = str1 + len1 - 1;
171 t2 = str2 + len2 - 1;
172
173 for (s1 = str1, s2 = str2, s = fstr1; *s1 && * s2; s1++, s2++) {
174 if (*s1 != *s2)
175 break;
176 *s++ = *s1;
177 }
178 *s = '\0';
179 if (*s1 == '\0' && *s2 == '\0') {
180 /* str1 */
181 return 0;
182 }
183 for (; s > fstr1; s--)
184 if (!isdigit(*(s - 1)))
185 break;
186 *s = '\0';
187 for (; t1 >= s1 && t2 >= s2; t1--, t2--) {
188 if (*t1 != *t2)
189 break;
190 }
191 for(; *t1; t1++)
192 if (!isdigit(*t1))
193 break;
194 for (s = fstr2; *t1; t1++)
195 *s++ = *t1;
196 *s = '\0';
197 /*
198 * left [page str] right
199 */
200 return 1;
201 }
headerFooter(begin,end)202 headerFooter(begin, end)
203 int begin;
204 int end;
205 {
206 struct textBlock *pbp;
207 char *headerStr, *footerStr;
208 char *header, *footer;
209
210 if (pageBp == NULL)
211 return;
212 pickUpLine(pageBp->rbegin, &headerStr, &footerStr, begin, end);
213 DBG4(3, "%d:1st-Header <%s>\n%d:1-stFooter<%s>\n",
214 pbp->rbegin, headerStr,
215 pbp->rbegin, footerStr);
216
217 if (headerStr == NULL && footerStr == NULL) {
218 /* No Header/Footer */
219 overwritePaging(begin, end, 0, 0);
220 return;
221 }
222
223 if (headerStr)
224 headerFields(headerStr, &origHeader);
225 if (footerStr)
226 headerFields(footerStr, &origFooter);
227
228 for (pbp = pageBp->nextBlock; pbp; pbp = pbp->nextBlock) {
229 pickUpLine(pbp->rbegin, &header, &footer, begin, end);
230 DBG4(3, "%d:Header <%s>\n%d:Footer<%s>\n",
231 pbp->rbegin, header,
232 pbp->rbegin, footer);
233 if (headerStr && header != NULL) {
234 headerFields(header, &curHeader);
235 if (!sameFormat(&origHeader, &curHeader)) {
236 overwritePaging(begin, end, 0, 0);
237 return;
238 }
239 }
240 if (footerStr && footer != NULL){
241 headerFields(footer, &curFooter);
242 if (!sameFormat(&origFooter, &curFooter)) {
243 overwritePaging(begin, end, 0, 0);
244 return;
245 }
246 }
247 }
248 overwritePaging(begin, end, headerPos, footerPos);
249 }
250 /*
251 * Register Paging (including header/footer) as a NULL text block.
252 * NULL block will not be analyzed and printed anymore.
253 */
overwritePaging(begin,end,hpos,fpos)254 overwritePaging(begin, end, hpos, fpos)
255 int begin;
256 int end;
257 int hpos;
258 int fpos;
259 {
260 struct textBlock *pbp;
261 int l, l1, l2;
262 fprintf (stderr, "Followin Header & Footer Lines ignored\n");
263 for (pbp = pageBp; pbp; pbp = pbp->nextBlock) {
264 for (l1 = pbp->rbegin - fpos - 1;
265 l1 >= begin && l1 >= pbp->rbegin - fpos - 4; l1--)
266 if (!texts[l1]->blank)
267 break;
268 for (l2 = pbp->rbegin + hpos + 1;
269 l2 < end && l2 <pbp->rbegin + hpos + 4; l2++)
270 if (!texts[l2]->blank)
271 break;
272 for (l = l1 + 1 ; l < l2; l++) {
273 texts[l]->block = pbp;
274 texts[l]->indent = rightMargin;
275 if (!texts[l]->blank)
276 fprintf (stderr, "%d:%s\n", l, texts[l]->body);
277 }
278 pbp->rbegin = l1 + 1;
279 pbp->rend = l2;
280 pbp->type = TB_COMMENT;
281 }
282 }
283 /*
284 * Build and print Header/Footer string for troff output
285 * (Note: This function returns a pointer to a static buffer which will be
286 * re-written at next call)
287 */
288 extern struct transTable roffTransQ[];
289 char *
roffHdrStr(pat1,pat2)290 roffHdrStr(pat1, pat2)
291 char *pat1, *pat2;
292 {
293 char left[HF_MAXLEN];
294 char right[HF_MAXLEN];
295 static char ret[64];
296 if (build(pat1, pat2, left, right)) {
297 (void)strcpy(ret, codeCvt(textQuote(left, roffTransQ)));
298 (void)strcat(ret, "\\\\\\\\nP");
299 (void)strcat(ret, codeCvt(textQuote(right, roffTransQ)));
300 return ret;
301 }
302 else
303 return codeCvt(textQuote(left, roffTransQ));
304 }
roffPutHeader()305 roffPutHeader()
306 {
307 if (headerPos) {
308 printf(".PH \"'");
309 printf ("%s'", roffHdrStr(origHeader.left, curHeader.left));
310 printf ("%s'", roffHdrStr(origHeader.center,curHeader.center));
311 printf ("%s'\"\n",roffHdrStr(origHeader.right, curHeader.right));
312 }
313 if (footerPos) {
314 printf(".PF \"'");
315 printf ("%s'", roffHdrStr(origFooter.left, curFooter.left));
316 printf ("%s'", roffHdrStr(origFooter.center,curFooter.center));
317 printf ("%s'\"\n", roffHdrStr(origFooter.right, curFooter.right));
318 }
319 }
320