]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/antiword/hdrftrlist.c
change icanhasvmx to report extra info only with -v
[plan9front.git] / sys / src / cmd / aux / antiword / hdrftrlist.c
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
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
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
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
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 *
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
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
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 */