Imported from antiword-0.37.tar.gz.
[antiword.git] / hdrftrlist.c
blobc16418882e337e0804d4b25c538de0e1d64d3074
1 /*
2 * hdrftrlist.c
3 * Copyright (C) 2004,2005 A.J. van Os; Released under GNU GPL
5 * Description:
6 * Build, read and destroy list(s) of Word Header/footer information
7 */
9 #include <string.h>
10 #include "antiword.h"
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
21 * Private structures to hide the way the information
22 * is stored from the rest of the program
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;
35 /* Variables needed to write the Header/footer Information List */
36 static hdrftr_mem_type *pHdrFtrList = NULL;
37 static size_t tHdrFtrLen = 0;
41 * vDestroyHdrFtrInfoList - destroy the Header/footer Information List
43 void
44 vDestroyHdrFtrInfoList(void)
46 hdrftr_mem_type *pRecord;
47 output_type *pCurr, *pNext;
48 size_t tHdrFtr, tIndex;
50 DBG_MSG("vDestroyHdrFtrInfoList");
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;
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;
70 pHdrFtrList = xfree(pHdrFtrList);
71 /* Reset all control variables */
72 tHdrFtrLen = 0;
73 } /* end of vDestroyHdrFtrInfoList */
76 * vCreat8HdrFtrInfoList - Create the Header/footer Information List
78 void
79 vCreat8HdrFtrInfoList(const ULONG *aulCharPos, size_t tLength)
81 hdrftr_mem_type *pListMember;
82 size_t tHdrFtr, tIndex, tMainIndex;
84 fail(aulCharPos == NULL);
86 DBG_DEC(tLength);
87 if (tLength <= 1) {
88 return;
90 tHdrFtrLen = tLength / 12;
91 if (tLength % 12 != 0 && tLength % 12 != 1) {
92 tHdrFtrLen++;
94 DBG_DEC(tHdrFtrLen);
96 pHdrFtrList = xcalloc(tHdrFtrLen, sizeof(hdrftr_mem_type));
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];
115 } /* end of vCreat8HdrFtrInfoList */
118 * vCreat6HdrFtrInfoList - Create the Header/footer Information List
120 void
121 vCreat6HdrFtrInfoList(const ULONG *aulCharPos, size_t tLength)
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,
127 hdrftr_mem_type *pListMember;
128 size_t tHdrFtr, tTmp, tIndex, tMainIndex, tBit;
129 UCHAR ucDopSpecification, ucSepSpecification;
131 fail(aulCharPos == NULL);
133 DBG_DEC(tLength);
134 if (tLength <= 1) {
135 return;
137 tHdrFtrLen = tGetNumberOfSections();
138 if (tHdrFtrLen == 0) {
139 tHdrFtrLen = 1;
141 DBG_DEC(tHdrFtrLen);
143 pHdrFtrList = xcalloc(tHdrFtrLen, sizeof(hdrftr_mem_type));
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++;
154 DBG_DEC(tMainIndex);
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;
165 for (tBit = 7; tBit >= 2; tBit--) {
166 if (tMainIndex >= tLength) {
167 break;
169 if ((ucSepSpecification & BIT(tBit)) == 0) {
170 continue;
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];
183 tMainIndex++;
186 } /* end of vCreat6HdrFtrInfoList */
189 * vCreat2HdrFtrInfoList - Create the Header/footer Information List
191 void
192 vCreat2HdrFtrInfoList(const ULONG *aulCharPos, size_t tLength)
194 vCreat6HdrFtrInfoList(aulCharPos, tLength);
195 } /* end of vCreat2HdrFtrInfoList */
198 * pGetHdrFtrInfo - get the Header/footer information
200 const hdrftr_block_type *
201 pGetHdrFtrInfo(int iSectionIndex,
202 BOOL bWantHeader, BOOL bOddPage, BOOL bFirstInSection)
204 hdrftr_mem_type *pCurr;
206 fail(iSectionIndex < 0);
207 fail(pHdrFtrList == NULL && tHdrFtrLen != 0);
209 if (pHdrFtrList == NULL || tHdrFtrLen == 0) {
210 /* No information */
211 return NULL;
214 if (iSectionIndex < 0) {
215 iSectionIndex = 0;
216 } else if (iSectionIndex >= (int)tHdrFtrLen) {
217 iSectionIndex = (int)(tHdrFtrLen - 1);
220 pCurr = pHdrFtrList + iSectionIndex;
222 if (bFirstInSection) {
223 if (bWantHeader) {
224 return &pCurr->atElement[HDR_FIRST_PAGE].tInfo;
225 } else {
226 return &pCurr->atElement[FTR_FIRST_PAGE].tInfo;
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;
235 } else {
236 if (bOddPage) {
237 return &pCurr->atElement[FTR_ODD_PAGES].tInfo;
238 } else {
239 return &pCurr->atElement[FTR_EVEN_PAGES].tInfo;
243 } /* end of pGetHdrFtrInfo */
246 * lComputeHdrFtrHeight - compute the height of a header or footer
248 * Returns the height in DrawUnits
250 static long
251 lComputeHdrFtrHeight(const output_type *pAnchor)
253 const output_type *pCurr;
254 long lTotal;
255 USHORT usFontSizeMax;
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;
269 if (pCurr->szStorage[0] == HARD_RETURN) {
270 /* End of a line */
271 lTotal += lComputeLeading(usFontSizeMax);
272 usFontSizeMax = 0;
273 continue;
276 if (pCurr->usFontSize > usFontSizeMax) {
277 usFontSizeMax = pCurr->usFontSize;
280 if (usFontSizeMax != 0) {
281 /* Height of the last paragraph */
282 lTotal += lComputeLeading(usFontSizeMax);
284 return lTotal;
285 } /* end of lComputeHdrFtrHeight */
288 * vPrepareHdrFtrText - prepare the header/footer text
290 void
291 vPrepareHdrFtrText(FILE *pFile)
293 hdrftr_mem_type *pCurr, *pPrev;
294 hdrftr_local_type *pTmp;
295 output_type *pText;
296 size_t tHdrFtr, tIndex;
298 fail(pFile == NULL);
299 fail(pHdrFtrList == NULL && tHdrFtrLen != 0);
301 if (pHdrFtrList == NULL || tHdrFtrLen == 0) {
302 /* No information */
303 return;
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;
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;
338 pTmp = &pHdrFtrList->atElement[HDR_EVEN_PAGES];
339 if (!pTmp->bUseful) {
340 *pTmp = pHdrFtrList->atElement[HDR_FIRST_PAGE];
341 pTmp->bTextOriginal = FALSE;
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;
350 pTmp = &pHdrFtrList->atElement[FTR_EVEN_PAGES];
351 if (!pTmp->bUseful) {
352 *pTmp = pHdrFtrList->atElement[FTR_FIRST_PAGE];
353 pTmp->bTextOriginal = FALSE;
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;
371 } /* end of vPrepareHdrFtrText */