/* * hdrftrlist.c * Copyright (C) 2004,2005 A.J. van Os; Released under GNU GPL * * Description: * Build, read and destroy list(s) of Word Header/footer information */ #include #include "antiword.h" #define HDR_EVEN_PAGES 0 #define HDR_ODD_PAGES 1 #define FTR_EVEN_PAGES 2 #define FTR_ODD_PAGES 3 #define HDR_FIRST_PAGE 4 #define FTR_FIRST_PAGE 5 /* * Private structures to hide the way the information * is stored from the rest of the program */ typedef struct hdrftr_local_tag { hdrftr_block_type tInfo; ULONG ulCharPosStart; ULONG ulCharPosNext; BOOL bUseful; BOOL bTextOriginal; } hdrftr_local_type; typedef struct hdrftr_mem_tag { hdrftr_local_type atElement[6]; } hdrftr_mem_type; /* Variables needed to write the Header/footer Information List */ static hdrftr_mem_type *pHdrFtrList = NULL; static size_t tHdrFtrLen = 0; /* * vDestroyHdrFtrInfoList - destroy the Header/footer Information List */ void vDestroyHdrFtrInfoList(void) { hdrftr_mem_type *pRecord; output_type *pCurr, *pNext; size_t tHdrFtr, tIndex; DBG_MSG("vDestroyHdrFtrInfoList"); /* Free the Header/footer Information List */ for (tHdrFtr = 0; tHdrFtr < tHdrFtrLen; tHdrFtr++) { pRecord = pHdrFtrList + tHdrFtr; for (tIndex = 0; tIndex < elementsof(pRecord->atElement); tIndex++) { if (!pRecord->atElement[tIndex].bTextOriginal) { continue; } pCurr = pRecord->atElement[tIndex].tInfo.pText; while (pCurr != NULL) { pCurr->szStorage = xfree(pCurr->szStorage); pNext = pCurr->pNext; pCurr = xfree(pCurr); pCurr = pNext; } } } pHdrFtrList = xfree(pHdrFtrList); /* Reset all control variables */ tHdrFtrLen = 0; } /* end of vDestroyHdrFtrInfoList */ /* * vCreat8HdrFtrInfoList - Create the Header/footer Information List */ void vCreat8HdrFtrInfoList(const ULONG *aulCharPos, size_t tLength) { hdrftr_mem_type *pListMember; size_t tHdrFtr, tIndex, tMainIndex; fail(aulCharPos == NULL); DBG_DEC(tLength); if (tLength <= 1) { return; } tHdrFtrLen = tLength / 12; if (tLength % 12 != 0 && tLength % 12 != 1) { tHdrFtrLen++; } DBG_DEC(tHdrFtrLen); pHdrFtrList = xcalloc(tHdrFtrLen, sizeof(hdrftr_mem_type)); for (tHdrFtr = 0; tHdrFtr < tHdrFtrLen; tHdrFtr++) { pListMember = pHdrFtrList + tHdrFtr; for (tIndex = 0, tMainIndex = tHdrFtr * 12; tIndex < 6 && tMainIndex < tLength; tIndex++, tMainIndex++) { pListMember->atElement[tIndex].tInfo.pText = NULL; pListMember->atElement[tIndex].ulCharPosStart = aulCharPos[tMainIndex]; if (tMainIndex + 1 < tLength) { pListMember->atElement[tIndex].ulCharPosNext = aulCharPos[tMainIndex + 1]; } else { pListMember->atElement[tIndex].ulCharPosNext = aulCharPos[tMainIndex]; } } } } /* end of vCreat8HdrFtrInfoList */ /* * vCreat6HdrFtrInfoList - Create the Header/footer Information List */ void vCreat6HdrFtrInfoList(const ULONG *aulCharPos, size_t tLength) { static const size_t atIndex[] = { SIZE_T_MAX, SIZE_T_MAX, FTR_FIRST_PAGE, HDR_FIRST_PAGE, FTR_ODD_PAGES, FTR_EVEN_PAGES, HDR_ODD_PAGES, HDR_EVEN_PAGES, }; hdrftr_mem_type *pListMember; size_t tHdrFtr, tTmp, tIndex, tMainIndex, tBit; UCHAR ucDopSpecification, ucSepSpecification; fail(aulCharPos == NULL); DBG_DEC(tLength); if (tLength <= 1) { return; } tHdrFtrLen = tGetNumberOfSections(); if (tHdrFtrLen == 0) { tHdrFtrLen = 1; } DBG_DEC(tHdrFtrLen); pHdrFtrList = xcalloc(tHdrFtrLen, sizeof(hdrftr_mem_type)); /* Get the start index in aulCharPos */ ucDopSpecification = ucGetDopHdrFtrSpecification(); DBG_HEX(ucDopSpecification & 0xe0); tMainIndex = 0; for (tBit = 7; tBit >= 5; tBit--) { if ((ucDopSpecification & BIT(tBit)) != 0) { tMainIndex++; } } DBG_DEC(tMainIndex); for (tHdrFtr = 0; tHdrFtr < tHdrFtrLen; tHdrFtr++) { ucSepSpecification = ucGetSepHdrFtrSpecification(tHdrFtr); DBG_HEX(ucSepSpecification & 0xfc); pListMember = pHdrFtrList + tHdrFtr; for (tTmp = 0; tTmp < elementsof(pListMember->atElement); tTmp++) { pListMember->atElement[tTmp].tInfo.pText = NULL; } for (tBit = 7; tBit >= 2; tBit--) { if (tMainIndex >= tLength) { break; } if ((ucSepSpecification & BIT(tBit)) == 0) { continue; } tIndex = atIndex[tBit]; fail(tIndex >= 6); pListMember->atElement[tIndex].ulCharPosStart = aulCharPos[tMainIndex]; if (tMainIndex + 1 < tLength) { pListMember->atElement[tIndex].ulCharPosNext = aulCharPos[tMainIndex + 1]; } else { pListMember->atElement[tIndex].ulCharPosNext = aulCharPos[tMainIndex]; } tMainIndex++; } } } /* end of vCreat6HdrFtrInfoList */ /* * vCreat2HdrFtrInfoList - Create the Header/footer Information List */ void vCreat2HdrFtrInfoList(const ULONG *aulCharPos, size_t tLength) { vCreat6HdrFtrInfoList(aulCharPos, tLength); } /* end of vCreat2HdrFtrInfoList */ /* * pGetHdrFtrInfo - get the Header/footer information */ const hdrftr_block_type * pGetHdrFtrInfo(int iSectionIndex, BOOL bWantHeader, BOOL bOddPage, BOOL bFirstInSection) { hdrftr_mem_type *pCurr; fail(iSectionIndex < 0); fail(pHdrFtrList == NULL && tHdrFtrLen != 0); if (pHdrFtrList == NULL || tHdrFtrLen == 0) { /* No information */ return NULL; } if (iSectionIndex < 0) { iSectionIndex = 0; } else if (iSectionIndex >= (int)tHdrFtrLen) { iSectionIndex = (int)(tHdrFtrLen - 1); } pCurr = pHdrFtrList + iSectionIndex; if (bFirstInSection) { if (bWantHeader) { return &pCurr->atElement[HDR_FIRST_PAGE].tInfo; } else { return &pCurr->atElement[FTR_FIRST_PAGE].tInfo; } } else { if (bWantHeader) { if (bOddPage) { return &pCurr->atElement[HDR_ODD_PAGES].tInfo; } else { return &pCurr->atElement[HDR_EVEN_PAGES].tInfo; } } else { if (bOddPage) { return &pCurr->atElement[FTR_ODD_PAGES].tInfo; } else { return &pCurr->atElement[FTR_EVEN_PAGES].tInfo; } } } } /* end of pGetHdrFtrInfo */ /* * lComputeHdrFtrHeight - compute the height of a header or footer * * Returns the height in DrawUnits */ static long lComputeHdrFtrHeight(const output_type *pAnchor) { const output_type *pCurr; long lTotal; USHORT usFontSizeMax; lTotal = 0; usFontSizeMax = 0; for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) { if (pCurr->tNextFree == 1) { if (pCurr->szStorage[0] == PAR_END) { /* End of a paragraph */ lTotal += lComputeLeading(usFontSizeMax); lTotal += lMilliPoints2DrawUnits( (long)pCurr->usFontSize * 200); usFontSizeMax = 0; continue; } if (pCurr->szStorage[0] == HARD_RETURN) { /* End of a line */ lTotal += lComputeLeading(usFontSizeMax); usFontSizeMax = 0; continue; } } if (pCurr->usFontSize > usFontSizeMax) { usFontSizeMax = pCurr->usFontSize; } } if (usFontSizeMax != 0) { /* Height of the last paragraph */ lTotal += lComputeLeading(usFontSizeMax); } return lTotal; } /* end of lComputeHdrFtrHeight */ /* * vPrepareHdrFtrText - prepare the header/footer text */ void vPrepareHdrFtrText(FILE *pFile) { hdrftr_mem_type *pCurr, *pPrev; hdrftr_local_type *pTmp; output_type *pText; size_t tHdrFtr, tIndex; fail(pFile == NULL); fail(pHdrFtrList == NULL && tHdrFtrLen != 0); if (pHdrFtrList == NULL || tHdrFtrLen == 0) { /* No information */ return; } /* Fill text, text height and useful-ness */ for (tHdrFtr = 0; tHdrFtr < tHdrFtrLen; tHdrFtr++) { pCurr = pHdrFtrList + tHdrFtr; for (tIndex = 0; tIndex < elementsof(pHdrFtrList->atElement); tIndex++) { pTmp = &pCurr->atElement[tIndex]; pTmp->bUseful = pTmp->ulCharPosStart != pTmp->ulCharPosNext; if (pTmp->bUseful) { pText = pHdrFtrDecryptor(pFile, pTmp->ulCharPosStart, pTmp->ulCharPosNext); pTmp->tInfo.pText = pText; pTmp->tInfo.lHeight = lComputeHdrFtrHeight(pText); pTmp->bTextOriginal = pText != NULL; } else { pTmp->tInfo.pText = NULL; pTmp->tInfo.lHeight = 0; pTmp->bTextOriginal = FALSE; } } } /* Replace not-useful records by using inheritance */ if (pHdrFtrList->atElement[HDR_FIRST_PAGE].bUseful) { pTmp = &pHdrFtrList->atElement[HDR_ODD_PAGES]; if (!pTmp->bUseful) { *pTmp = pHdrFtrList->atElement[HDR_FIRST_PAGE]; pTmp->bTextOriginal = FALSE; } pTmp = &pHdrFtrList->atElement[HDR_EVEN_PAGES]; if (!pTmp->bUseful) { *pTmp = pHdrFtrList->atElement[HDR_FIRST_PAGE]; pTmp->bTextOriginal = FALSE; } } if (pHdrFtrList->atElement[FTR_FIRST_PAGE].bUseful) { pTmp = &pHdrFtrList->atElement[FTR_ODD_PAGES]; if (!pTmp->bUseful) { *pTmp = pHdrFtrList->atElement[FTR_FIRST_PAGE]; pTmp->bTextOriginal = FALSE; } pTmp = &pHdrFtrList->atElement[FTR_EVEN_PAGES]; if (!pTmp->bUseful) { *pTmp = pHdrFtrList->atElement[FTR_FIRST_PAGE]; pTmp->bTextOriginal = FALSE; } } for (tHdrFtr = 1, pCurr = &pHdrFtrList[1]; tHdrFtr < tHdrFtrLen; tHdrFtr++, pCurr++) { pPrev = pCurr - 1; for (tIndex = 0; tIndex < elementsof(pHdrFtrList->atElement); tIndex++) { if (!pCurr->atElement[tIndex].bUseful && pPrev->atElement[tIndex].bUseful) { pCurr->atElement[tIndex] = pPrev->atElement[tIndex]; pCurr->atElement[tIndex].bTextOriginal = FALSE; } } } } /* end of vPrepareHdrFtrText */