mirror of
https://github.com/simon987/antiword.git
synced 2025-04-10 13:06:41 +00:00
372 lines
9.1 KiB
C
372 lines
9.1 KiB
C
/*
|
|
* 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 <string.h>
|
|
#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 */
|