📄 blocklist.c
字号:
/* * blocklist.c * Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL * * Description: * Build, read and destroy the lists of Word "text" blocks */#include <stdlib.h>#include "antiword.h"/* * Private structure to hide the way the information * is stored from the rest of the program */typedef struct list_mem_tag { text_block_type tInfo; struct list_mem_tag *pNext;} list_mem_type;typedef struct readinfo_tag { list_mem_type *pBlockCurrent; ULONG ulBlockOffset; size_t tByteNext; UCHAR aucBlock[BIG_BLOCK_SIZE];} readinfo_type;/* Variables to describe the start of the block lists */static list_mem_type *pTextAnchor = NULL;static list_mem_type *pFootnoteAnchor = NULL;static list_mem_type *pHdrFtrAnchor = NULL;static list_mem_type *pMacroAnchor = NULL;static list_mem_type *pAnnotationAnchor = NULL;static list_mem_type *pEndnoteAnchor = NULL;static list_mem_type *pTextBoxAnchor = NULL;static list_mem_type *pHdrTextBoxAnchor = NULL;/* Variable needed to build the block list */static list_mem_type *pBlockLast = NULL;/* Variable needed to read the block lists */static readinfo_type tOthers = { NULL, 0, 0, };static readinfo_type tHdrFtr = { NULL, 0, 0, };static readinfo_type tFootnote = { NULL, 0, 0, };/* * pFreeOneList - free a text block list * * Will always return NULL */static list_mem_type *pFreeOneList(list_mem_type *pAnchor){ list_mem_type *pCurr, *pNext; pCurr = pAnchor; while (pCurr != NULL) { pNext = pCurr->pNext; pCurr = xfree(pCurr); pCurr = pNext; } return NULL;} /* end of pFreeOneList *//* * vDestroyTextBlockList - destroy the text block lists */voidvDestroyTextBlockList(void){ DBG_MSG("vDestroyTextBlockList"); /* Free the lists one by one */ pTextAnchor = pFreeOneList(pTextAnchor); pFootnoteAnchor = pFreeOneList(pFootnoteAnchor); pHdrFtrAnchor = pFreeOneList(pHdrFtrAnchor); pMacroAnchor = pFreeOneList(pMacroAnchor); pAnnotationAnchor = pFreeOneList(pAnnotationAnchor); pEndnoteAnchor = pFreeOneList(pEndnoteAnchor); pTextBoxAnchor = pFreeOneList(pTextBoxAnchor); pHdrTextBoxAnchor = pFreeOneList(pHdrTextBoxAnchor); /* Reset all the controle variables */ pBlockLast = NULL; tOthers.pBlockCurrent = NULL; tHdrFtr.pBlockCurrent = NULL; tFootnote.pBlockCurrent = NULL;} /* end of vDestroyTextBlockList *//* * bAdd2TextBlockList - add an element to the text block list * * returns: TRUE when successful, otherwise FALSE */BOOLbAdd2TextBlockList(const text_block_type *pTextBlock){ list_mem_type *pListMember; fail(pTextBlock == NULL); fail(pTextBlock->ulFileOffset == FC_INVALID); fail(pTextBlock->ulCharPos == CP_INVALID); fail(pTextBlock->ulLength == 0); fail(pTextBlock->bUsesUnicode && odd(pTextBlock->ulLength)); NO_DBG_MSG("bAdd2TextBlockList"); NO_DBG_HEX(pTextBlock->ulFileOffset); NO_DBG_HEX(pTextBlock->ulCharPos); NO_DBG_HEX(pTextBlock->ulLength); NO_DBG_DEC(pTextBlock->bUsesUnicode); NO_DBG_DEC(pTextBlock->usPropMod); if (pTextBlock->ulFileOffset == FC_INVALID || pTextBlock->ulCharPos == CP_INVALID || pTextBlock->ulLength == 0 || (pTextBlock->bUsesUnicode && odd(pTextBlock->ulLength))) { werr(0, "Software (textblock) error"); return FALSE; } /* * Check for continuous blocks of the same character size and * the same properties modifier */ if (pBlockLast != NULL && pBlockLast->tInfo.ulFileOffset + pBlockLast->tInfo.ulLength == pTextBlock->ulFileOffset && pBlockLast->tInfo.ulCharPos + pBlockLast->tInfo.ulLength == pTextBlock->ulCharPos && pBlockLast->tInfo.bUsesUnicode == pTextBlock->bUsesUnicode && pBlockLast->tInfo.usPropMod == pTextBlock->usPropMod) { /* These are continous blocks */ pBlockLast->tInfo.ulLength += pTextBlock->ulLength; return TRUE; } /* Make a new block */ pListMember = xmalloc(sizeof(list_mem_type)); /* Add the block to the list */ pListMember->tInfo = *pTextBlock; pListMember->pNext = NULL; if (pTextAnchor == NULL) { pTextAnchor = pListMember; } else { fail(pBlockLast == NULL); pBlockLast->pNext = pListMember; } pBlockLast = pListMember; return TRUE;} /* end of bAdd2TextBlockList *//* * vSpitList - Split the list in two */static voidvSpitList(list_mem_type **ppAnchorCurr, list_mem_type **ppAnchorNext, ULONG ulListLen){ list_mem_type *pCurr; long lCharsToGo, lBytesTooFar; fail(ppAnchorCurr == NULL); fail(ppAnchorNext == NULL); fail(ulListLen > (ULONG)LONG_MAX); pCurr = NULL; lCharsToGo = (long)ulListLen; lBytesTooFar = -1; if (ulListLen != 0) { DBG_DEC(ulListLen); for (pCurr = *ppAnchorCurr; pCurr != NULL; pCurr = pCurr->pNext) { NO_DBG_DEC(pCurr->tInfo.ulLength); fail(pCurr->tInfo.ulLength == 0); fail(pCurr->tInfo.ulLength > (ULONG)LONG_MAX); if (pCurr->tInfo.bUsesUnicode) { fail(odd(pCurr->tInfo.ulLength)); lCharsToGo -= (long)(pCurr->tInfo.ulLength / 2); if (lCharsToGo < 0) { lBytesTooFar = -2 * lCharsToGo; } } else { lCharsToGo -= (long)pCurr->tInfo.ulLength; if (lCharsToGo < 0) { lBytesTooFar = -lCharsToGo; } } if (lCharsToGo <= 0) { break; } } }/* Split the list */ if (ulListLen == 0) { /* Current blocklist is empty */ *ppAnchorNext = *ppAnchorCurr; *ppAnchorCurr = NULL; } else if (pCurr == NULL) { /* No blocks for the next list */ *ppAnchorNext = NULL; } else if (lCharsToGo == 0) { /* Move the integral number of blocks to the next list */ *ppAnchorNext = pCurr->pNext; pCurr->pNext = NULL; } else { /* Split the part current block list, part next block list */ DBG_DEC(lBytesTooFar); fail(lBytesTooFar <= 0); *ppAnchorNext = xmalloc(sizeof(list_mem_type)); DBG_HEX(pCurr->tInfo.ulFileOffset); (*ppAnchorNext)->tInfo.ulFileOffset = pCurr->tInfo.ulFileOffset + pCurr->tInfo.ulLength - lBytesTooFar; DBG_HEX((*ppAnchorNext)->tInfo.ulFileOffset); DBG_HEX(pCurr->tInfo.ulCharPos); (*ppAnchorNext)->tInfo.ulCharPos = pCurr->tInfo.ulCharPos + pCurr->tInfo.ulLength - lBytesTooFar; DBG_HEX((*ppAnchorNext)->tInfo.ulCharPos); (*ppAnchorNext)->tInfo.ulLength = (ULONG)lBytesTooFar; pCurr->tInfo.ulLength -= (ULONG)lBytesTooFar; (*ppAnchorNext)->tInfo.bUsesUnicode = pCurr->tInfo.bUsesUnicode; (*ppAnchorNext)->tInfo.usPropMod = pCurr->tInfo.usPropMod; /* Move the integral number of blocks to the next list */ (*ppAnchorNext)->pNext = pCurr->pNext; pCurr->pNext = NULL; }} /* end of vSpitList */#if defined(DEBUG) || defined(__riscos)/* * ulComputeListLength - compute the length of a list * * returns the list length in characters */static ULONGulComputeListLength(const list_mem_type *pAnchor){ const list_mem_type *pCurr; ULONG ulTotal; ulTotal = 0; for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) { fail(pCurr->tInfo.ulLength == 0); if (pCurr->tInfo.bUsesUnicode) { fail(odd(pCurr->tInfo.ulLength)); ulTotal += pCurr->tInfo.ulLength / 2; } else { ulTotal += pCurr->tInfo.ulLength; } } return ulTotal;} /* end of ulComputeListLength */#endif /* DEBUG || __riscos */#if defined(DEBUG)/* * vCheckList - check the number of bytes in a block list */static voidvCheckList(const list_mem_type *pAnchor, ULONG ulListLen, char *szMsg){ ULONG ulTotal; ulTotal = ulComputeListLength(pAnchor); DBG_DEC(ulTotal); if (ulTotal != ulListLen) { DBG_DEC(ulListLen); werr(1, szMsg); }} /* end of vCheckList */#endif /* DEBUG *//* * bIsEmptyBox - check to see if the given text box is empty */static BOOLbIsEmptyBox(FILE *pFile, const list_mem_type *pAnchor){ const list_mem_type *pCurr; size_t tIndex, tSize; UCHAR *aucBuffer; char cChar; fail(pFile == NULL); if (pAnchor == NULL) { return TRUE; } aucBuffer = NULL; for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) { fail(pCurr->tInfo.ulLength == 0); tSize = (size_t)pCurr->tInfo.ulLength;#if defined(__dos) && !defined(__DJGPP__) if (pCurr->tInfo.ulLength > 0xffffUL) { tSize = 0xffff; }#endif /* __dos && !__DJGPP__ */ fail(aucBuffer != NULL); aucBuffer = xmalloc(tSize); if (!bReadBytes(aucBuffer, tSize, pCurr->tInfo.ulFileOffset, pFile)) { aucBuffer = xfree(aucBuffer); return FALSE; } for (tIndex = 0; tIndex < tSize; tIndex++) { cChar = (char)aucBuffer[tIndex]; switch (cChar) { case '\0': case '\r': case '\n': case '\f': case '\t': case '\v': case ' ': break; default: aucBuffer = xfree(aucBuffer); return FALSE; } } aucBuffer = xfree(aucBuffer); } fail(aucBuffer != NULL); return TRUE;} /* end of bIsEmptyBox *//* * vSplitBlockList - split the block list in the various parts * * Split the blocklist in a Text block list, a Footnote block list, a * HeaderFooter block list, a Macro block list, an Annotation block list, * an Endnote block list, a TextBox list and a HeaderTextBox list. * * NOTE: * The various ul*Len input parameters are given in characters, but the * length of the blocks are in bytes. */voidvSplitBlockList(FILE *pFile, ULONG ulTextLen, ULONG ulFootnoteLen, ULONG ulHdrFtrLen, ULONG ulMacroLen, ULONG ulAnnotationLen, ULONG ulEndnoteLen, ULONG ulTextBoxLen, ULONG ulHdrTextBoxLen, BOOL bMustExtend){ list_mem_type *apAnchors[8]; list_mem_type *pGarbageAnchor, *pCurr; size_t tIndex; DBG_MSG("vSplitBlockList"); pGarbageAnchor = NULL; DBG_MSG_C(ulTextLen != 0, "Text block list"); vSpitList(&pTextAnchor, &pFootnoteAnchor, ulTextLen); DBG_MSG_C(ulFootnoteLen != 0, "Footnote block list"); vSpitList(&pFootnoteAnchor, &pHdrFtrAnchor, ulFootnoteLen); DBG_MSG_C(ulHdrFtrLen != 0, "Header/Footer block list"); vSpitList(&pHdrFtrAnchor, &pMacroAnchor, ulHdrFtrLen); DBG_MSG_C(ulMacroLen != 0, "Macro block list"); vSpitList(&pMacroAnchor, &pAnnotationAnchor, ulMacroLen); DBG_MSG_C(ulAnnotationLen != 0, "Annotation block list"); vSpitList(&pAnnotationAnchor, &pEndnoteAnchor, ulAnnotationLen); DBG_MSG_C(ulEndnoteLen != 0, "Endnote block list"); vSpitList(&pEndnoteAnchor, &pTextBoxAnchor, ulEndnoteLen); DBG_MSG_C(ulTextBoxLen != 0, "Textbox block list"); vSpitList(&pTextBoxAnchor, &pHdrTextBoxAnchor, ulTextBoxLen); DBG_MSG_C(ulHdrTextBoxLen != 0, "HeaderTextbox block list"); vSpitList(&pHdrTextBoxAnchor, &pGarbageAnchor, ulHdrTextBoxLen); /* Free the garbage block list, this should not be needed */ DBG_DEC_C(pGarbageAnchor != NULL, pGarbageAnchor->tInfo.ulLength); pGarbageAnchor = pFreeOneList(pGarbageAnchor);#if defined(DEBUG) vCheckList(pTextAnchor, ulTextLen, "Software error (Text)"); vCheckList(pFootnoteAnchor, ulFootnoteLen, "Software error (Footnote)"); vCheckList(pHdrFtrAnchor, ulHdrFtrLen, "Software error (Hdr/Ftr)"); vCheckList(pMacroAnchor, ulMacroLen, "Software error (Macro)"); vCheckList(pAnnotationAnchor, ulAnnotationLen, "Software error (Annotation)"); vCheckList(pEndnoteAnchor, ulEndnoteLen, "Software error (Endnote)"); vCheckList(pTextBoxAnchor, ulTextBoxLen, "Software error (TextBox)"); vCheckList(pHdrTextBoxAnchor, ulHdrTextBoxLen, "Software error (HdrTextBox)");#endif /* DEBUG */ /* Remove the list if the text box is empty */ if (bIsEmptyBox(pFile, pTextBoxAnchor)) { pTextBoxAnchor = pFreeOneList(pTextBoxAnchor); } if (bIsEmptyBox(pFile, pHdrTextBoxAnchor)) { pHdrTextBoxAnchor = pFreeOneList(pHdrTextBoxAnchor); } if (!bMustExtend) { return; } /* * All blocks (except the last one) must have a length that * is a multiple of the Big Block Size */ apAnchors[0] = pTextAnchor; apAnchors[1] = pFootnoteAnchor; apAnchors[2] = pHdrFtrAnchor; apAnchors[3] = pMacroAnchor; apAnchors[4] = pAnnotationAnchor; apAnchors[5] = pEndnoteAnchor; apAnchors[6] = pTextBoxAnchor; apAnchors[7] = pHdrTextBoxAnchor; for (tIndex = 0; tIndex < elementsof(apAnchors); tIndex++) { for (pCurr = apAnchors[tIndex]; pCurr != NULL; pCurr = pCurr->pNext) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -