1 /*
2 * hdrftrlist.c
3 * Copyright (C) 2004,2005 A.J. van Os; Released under GNU GPL
4 *
5 * Description:
6 * Build, read and destroy list(s) of Word Header/footer information
7 */
8
9 #include <string.h>
10 #include "antiword.h"
11
12
13 #define HDR_EVEN_PAGES 0
14 #define HDR_ODD_PAGES 1
15 #define FTR_EVEN_PAGES 2
16 #define FTR_ODD_PAGES 3
17 #define HDR_FIRST_PAGE 4
18 #define FTR_FIRST_PAGE 5
19
20 /*
21 * Private structures to hide the way the information
22 * is stored from the rest of the program
23 */
24 typedef struct hdrftr_local_tag {
25 hdrftr_block_type tInfo;
26 ULONG ulCharPosStart;
27 ULONG ulCharPosNext;
28 BOOL bUseful;
29 BOOL bTextOriginal;
30 } hdrftr_local_type;
31 typedef struct hdrftr_mem_tag {
32 hdrftr_local_type atElement[6];
33 } hdrftr_mem_type;
34
35 /* Variables needed to write the Header/footer Information List */
36 static hdrftr_mem_type *pHdrFtrList = NULL;
37 static size_t tHdrFtrLen = 0;
38
39
40 /*
41 * vDestroyHdrFtrInfoList - destroy the Header/footer Information List
42 */
43 void
vDestroyHdrFtrInfoList(void)44 vDestroyHdrFtrInfoList(void)
45 {
46 hdrftr_mem_type *pRecord;
47 output_type *pCurr, *pNext;
48 size_t tHdrFtr, tIndex;
49
50 DBG_MSG("vDestroyHdrFtrInfoList");
51
52 /* Free the Header/footer Information List */
53 for (tHdrFtr = 0; tHdrFtr < tHdrFtrLen; tHdrFtr++) {
54 pRecord = pHdrFtrList + tHdrFtr;
55 for (tIndex = 0;
56 tIndex < elementsof(pRecord->atElement);
57 tIndex++) {
58 if (!pRecord->atElement[tIndex].bTextOriginal) {
59 continue;
60 }
61 pCurr = pRecord->atElement[tIndex].tInfo.pText;
62 while (pCurr != NULL) {
63 pCurr->szStorage = xfree(pCurr->szStorage);
64 pNext = pCurr->pNext;
65 pCurr = xfree(pCurr);
66 pCurr = pNext;
67 }
68 }
69 }
70 pHdrFtrList = xfree(pHdrFtrList);
71 /* Reset all control variables */
72 tHdrFtrLen = 0;
73 } /* end of vDestroyHdrFtrInfoList */
74
75 /*
76 * vCreat8HdrFtrInfoList - Create the Header/footer Information List
77 */
78 void
vCreat8HdrFtrInfoList(const ULONG * aulCharPos,size_t tLength)79 vCreat8HdrFtrInfoList(const ULONG *aulCharPos, size_t tLength)
80 {
81 hdrftr_mem_type *pListMember;
82 size_t tHdrFtr, tIndex, tMainIndex;
83
84 fail(aulCharPos == NULL);
85
86 DBG_DEC(tLength);
87 if (tLength <= 1) {
88 return;
89 }
90 tHdrFtrLen = tLength / 12;
91 if (tLength % 12 != 0 && tLength % 12 != 1) {
92 tHdrFtrLen++;
93 }
94 DBG_DEC(tHdrFtrLen);
95
96 pHdrFtrList = xcalloc(tHdrFtrLen, sizeof(hdrftr_mem_type));
97
98 for (tHdrFtr = 0; tHdrFtr < tHdrFtrLen; tHdrFtr++) {
99 pListMember = pHdrFtrList + tHdrFtr;
100 for (tIndex = 0, tMainIndex = tHdrFtr * 12;
101 tIndex < 6 && tMainIndex < tLength;
102 tIndex++, tMainIndex++) {
103 pListMember->atElement[tIndex].tInfo.pText = NULL;
104 pListMember->atElement[tIndex].ulCharPosStart =
105 aulCharPos[tMainIndex];
106 if (tMainIndex + 1 < tLength) {
107 pListMember->atElement[tIndex].ulCharPosNext =
108 aulCharPos[tMainIndex + 1];
109 } else {
110 pListMember->atElement[tIndex].ulCharPosNext =
111 aulCharPos[tMainIndex];
112 }
113 }
114 }
115 } /* end of vCreat8HdrFtrInfoList */
116
117 /*
118 * vCreat6HdrFtrInfoList - Create the Header/footer Information List
119 */
120 void
vCreat6HdrFtrInfoList(const ULONG * aulCharPos,size_t tLength)121 vCreat6HdrFtrInfoList(const ULONG *aulCharPos, size_t tLength)
122 {
123 static const size_t atIndex[] =
124 { SIZE_T_MAX, SIZE_T_MAX, FTR_FIRST_PAGE, HDR_FIRST_PAGE,
125 FTR_ODD_PAGES, FTR_EVEN_PAGES, HDR_ODD_PAGES, HDR_EVEN_PAGES,
126 };
127 hdrftr_mem_type *pListMember;
128 size_t tHdrFtr, tTmp, tIndex, tMainIndex, tBit;
129 UCHAR ucDopSpecification, ucSepSpecification;
130
131 fail(aulCharPos == NULL);
132
133 DBG_DEC(tLength);
134 if (tLength <= 1) {
135 return;
136 }
137 tHdrFtrLen = tGetNumberOfSections();
138 if (tHdrFtrLen == 0) {
139 tHdrFtrLen = 1;
140 }
141 DBG_DEC(tHdrFtrLen);
142
143 pHdrFtrList = xcalloc(tHdrFtrLen, sizeof(hdrftr_mem_type));
144
145 /* Get the start index in aulCharPos */
146 ucDopSpecification = ucGetDopHdrFtrSpecification();
147 DBG_HEX(ucDopSpecification & 0xe0);
148 tMainIndex = 0;
149 for (tBit = 7; tBit >= 5; tBit--) {
150 if ((ucDopSpecification & BIT(tBit)) != 0) {
151 tMainIndex++;
152 }
153 }
154 DBG_DEC(tMainIndex);
155
156 for (tHdrFtr = 0; tHdrFtr < tHdrFtrLen; tHdrFtr++) {
157 ucSepSpecification = ucGetSepHdrFtrSpecification(tHdrFtr);
158 DBG_HEX(ucSepSpecification & 0xfc);
159 pListMember = pHdrFtrList + tHdrFtr;
160 for (tTmp = 0;
161 tTmp < elementsof(pListMember->atElement);
162 tTmp++) {
163 pListMember->atElement[tTmp].tInfo.pText = NULL;
164 }
165 for (tBit = 7; tBit >= 2; tBit--) {
166 if (tMainIndex >= tLength) {
167 break;
168 }
169 if ((ucSepSpecification & BIT(tBit)) == 0) {
170 continue;
171 }
172 tIndex = atIndex[tBit];
173 fail(tIndex >= 6);
174 pListMember->atElement[tIndex].ulCharPosStart =
175 aulCharPos[tMainIndex];
176 if (tMainIndex + 1 < tLength) {
177 pListMember->atElement[tIndex].ulCharPosNext =
178 aulCharPos[tMainIndex + 1];
179 } else {
180 pListMember->atElement[tIndex].ulCharPosNext =
181 aulCharPos[tMainIndex];
182 }
183 tMainIndex++;
184 }
185 }
186 } /* end of vCreat6HdrFtrInfoList */
187
188 /*
189 * vCreat2HdrFtrInfoList - Create the Header/footer Information List
190 */
191 void
vCreat2HdrFtrInfoList(const ULONG * aulCharPos,size_t tLength)192 vCreat2HdrFtrInfoList(const ULONG *aulCharPos, size_t tLength)
193 {
194 vCreat6HdrFtrInfoList(aulCharPos, tLength);
195 } /* end of vCreat2HdrFtrInfoList */
196
197 /*
198 * pGetHdrFtrInfo - get the Header/footer information
199 */
200 const hdrftr_block_type *
pGetHdrFtrInfo(int iSectionIndex,BOOL bWantHeader,BOOL bOddPage,BOOL bFirstInSection)201 pGetHdrFtrInfo(int iSectionIndex,
202 BOOL bWantHeader, BOOL bOddPage, BOOL bFirstInSection)
203 {
204 hdrftr_mem_type *pCurr;
205
206 fail(iSectionIndex < 0);
207 fail(pHdrFtrList == NULL && tHdrFtrLen != 0);
208
209 if (pHdrFtrList == NULL || tHdrFtrLen == 0) {
210 /* No information */
211 return NULL;
212 }
213
214 if (iSectionIndex < 0) {
215 iSectionIndex = 0;
216 } else if (iSectionIndex >= (int)tHdrFtrLen) {
217 iSectionIndex = (int)(tHdrFtrLen - 1);
218 }
219
220 pCurr = pHdrFtrList + iSectionIndex;
221
222 if (bFirstInSection) {
223 if (bWantHeader) {
224 return &pCurr->atElement[HDR_FIRST_PAGE].tInfo;
225 } else {
226 return &pCurr->atElement[FTR_FIRST_PAGE].tInfo;
227 }
228 } else {
229 if (bWantHeader) {
230 if (bOddPage) {
231 return &pCurr->atElement[HDR_ODD_PAGES].tInfo;
232 } else {
233 return &pCurr->atElement[HDR_EVEN_PAGES].tInfo;
234 }
235 } else {
236 if (bOddPage) {
237 return &pCurr->atElement[FTR_ODD_PAGES].tInfo;
238 } else {
239 return &pCurr->atElement[FTR_EVEN_PAGES].tInfo;
240 }
241 }
242 }
243 } /* end of pGetHdrFtrInfo */
244
245 /*
246 * lComputeHdrFtrHeight - compute the height of a header or footer
247 *
248 * Returns the height in DrawUnits
249 */
250 static long
lComputeHdrFtrHeight(const output_type * pAnchor)251 lComputeHdrFtrHeight(const output_type *pAnchor)
252 {
253 const output_type *pCurr;
254 long lTotal;
255 USHORT usFontSizeMax;
256
257 lTotal = 0;
258 usFontSizeMax = 0;
259 for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
260 if (pCurr->tNextFree == 1) {
261 if (pCurr->szStorage[0] == PAR_END) {
262 /* End of a paragraph */
263 lTotal += lComputeLeading(usFontSizeMax);
264 lTotal += lMilliPoints2DrawUnits(
265 (long)pCurr->usFontSize * 200);
266 usFontSizeMax = 0;
267 continue;
268 }
269 if (pCurr->szStorage[0] == HARD_RETURN) {
270 /* End of a line */
271 lTotal += lComputeLeading(usFontSizeMax);
272 usFontSizeMax = 0;
273 continue;
274 }
275 }
276 if (pCurr->usFontSize > usFontSizeMax) {
277 usFontSizeMax = pCurr->usFontSize;
278 }
279 }
280 if (usFontSizeMax != 0) {
281 /* Height of the last paragraph */
282 lTotal += lComputeLeading(usFontSizeMax);
283 }
284 return lTotal;
285 } /* end of lComputeHdrFtrHeight */
286
287 /*
288 * vPrepareHdrFtrText - prepare the header/footer text
289 */
290 void
vPrepareHdrFtrText(FILE * pFile)291 vPrepareHdrFtrText(FILE *pFile)
292 {
293 hdrftr_mem_type *pCurr, *pPrev;
294 hdrftr_local_type *pTmp;
295 output_type *pText;
296 size_t tHdrFtr, tIndex;
297
298 fail(pFile == NULL);
299 fail(pHdrFtrList == NULL && tHdrFtrLen != 0);
300
301 if (pHdrFtrList == NULL || tHdrFtrLen == 0) {
302 /* No information */
303 return;
304 }
305
306 /* Fill text, text height and useful-ness */
307 for (tHdrFtr = 0; tHdrFtr < tHdrFtrLen; tHdrFtr++) {
308 pCurr = pHdrFtrList + tHdrFtr;
309 for (tIndex = 0;
310 tIndex < elementsof(pHdrFtrList->atElement);
311 tIndex++) {
312 pTmp = &pCurr->atElement[tIndex];
313 pTmp->bUseful =
314 pTmp->ulCharPosStart != pTmp->ulCharPosNext;
315 if (pTmp->bUseful) {
316 pText = pHdrFtrDecryptor(pFile,
317 pTmp->ulCharPosStart,
318 pTmp->ulCharPosNext);
319 pTmp->tInfo.pText = pText;
320 pTmp->tInfo.lHeight =
321 lComputeHdrFtrHeight(pText);
322 pTmp->bTextOriginal = pText != NULL;
323 } else {
324 pTmp->tInfo.pText = NULL;
325 pTmp->tInfo.lHeight = 0;
326 pTmp->bTextOriginal = FALSE;
327 }
328 }
329 }
330
331 /* Replace not-useful records by using inheritance */
332 if (pHdrFtrList->atElement[HDR_FIRST_PAGE].bUseful) {
333 pTmp = &pHdrFtrList->atElement[HDR_ODD_PAGES];
334 if (!pTmp->bUseful) {
335 *pTmp = pHdrFtrList->atElement[HDR_FIRST_PAGE];
336 pTmp->bTextOriginal = FALSE;
337 }
338 pTmp = &pHdrFtrList->atElement[HDR_EVEN_PAGES];
339 if (!pTmp->bUseful) {
340 *pTmp = pHdrFtrList->atElement[HDR_FIRST_PAGE];
341 pTmp->bTextOriginal = FALSE;
342 }
343 }
344 if (pHdrFtrList->atElement[FTR_FIRST_PAGE].bUseful) {
345 pTmp = &pHdrFtrList->atElement[FTR_ODD_PAGES];
346 if (!pTmp->bUseful) {
347 *pTmp = pHdrFtrList->atElement[FTR_FIRST_PAGE];
348 pTmp->bTextOriginal = FALSE;
349 }
350 pTmp = &pHdrFtrList->atElement[FTR_EVEN_PAGES];
351 if (!pTmp->bUseful) {
352 *pTmp = pHdrFtrList->atElement[FTR_FIRST_PAGE];
353 pTmp->bTextOriginal = FALSE;
354 }
355 }
356 for (tHdrFtr = 1, pCurr = &pHdrFtrList[1];
357 tHdrFtr < tHdrFtrLen;
358 tHdrFtr++, pCurr++) {
359 pPrev = pCurr - 1;
360 for (tIndex = 0;
361 tIndex < elementsof(pHdrFtrList->atElement);
362 tIndex++) {
363 if (!pCurr->atElement[tIndex].bUseful &&
364 pPrev->atElement[tIndex].bUseful) {
365 pCurr->atElement[tIndex] =
366 pPrev->atElement[tIndex];
367 pCurr->atElement[tIndex].bTextOriginal = FALSE;
368 }
369 }
370 }
371 } /* end of vPrepareHdrFtrText */
372