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