/*
* 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 */
|