123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- /*
- * listlist.c
- * Copyright (C) 2002,2003 A.J. van Os; Released under GPL
- *
- * Description:
- * Build, read and destroy a list of Word list information
- *
- * Note:
- * This list only exists when the Word document is saved by Word 8 or later
- */
- #include "antiword.h"
- /*
- * Private structure to hide the way the information
- * is stored from the rest of the program
- */
- typedef struct list_desc_tag {
- list_block_type tInfo;
- ULONG ulListID;
- USHORT usIstd;
- UCHAR ucListLevel;
- struct list_desc_tag *pNext;
- } list_desc_type;
- typedef struct list_value_tag {
- USHORT usValue;
- USHORT usListIndex;
- UCHAR ucListLevel;
- struct list_value_tag *pNext;
- } list_value_type;
- /* Variables needed to describe the LFO list (pllfo) */
- static ULONG *aulLfoList = NULL;
- static USHORT usLfoLen = 0;
- /* Variables needed to write the List Information List */
- static list_desc_type *pAnchor = NULL;
- static list_desc_type *pBlockLast = NULL;
- /* Variable needed for numbering new lists */
- static list_value_type *pValues = NULL;
- /* Variables needed for numbering old lists */
- static int iOldListSeqNumber = 0;
- static USHORT usOldListValue = 0;
- /*
- * vDestroyListInfoList - destroy the List Information List
- */
- void
- vDestroyListInfoList(void)
- {
- list_desc_type *pCurr, *pNext;
- list_value_type *pValueCurr, *pValueNext;
- DBG_MSG("vDestroyListInfoList");
- /* Free the LFO list */
- usLfoLen = 0;
- aulLfoList = xfree(aulLfoList);
- /* Free the List Information List */
- pCurr = pAnchor;
- while (pCurr != NULL) {
- pNext = pCurr->pNext;
- pCurr = xfree(pCurr);
- pCurr = pNext;
- }
- pAnchor = NULL;
- /* Reset all control variables */
- pBlockLast = NULL;
- /* Free the values list */
- pValueCurr = pValues;
- while (pValueCurr != NULL) {
- pValueNext = pValueCurr->pNext;
- pValueCurr = xfree(pValueCurr);
- pValueCurr = pValueNext;
- }
- pValues = NULL;
- /* Reset the values for the old lists */
- iOldListSeqNumber = 0;
- usOldListValue = 0;
- } /* end of vDestroyListInfoList */
- /*
- * vBuildLfoList - build the LFO list (pllfo)
- */
- void
- vBuildLfoList(const UCHAR *aucBuffer, size_t tBufLen)
- {
- size_t tRecords;
- int iIndex;
- fail(aucBuffer == NULL);
- if (tBufLen < 4) {
- return;
- }
- tRecords = (size_t)ulGetLong(0, aucBuffer);
- NO_DBG_DEC(tRecords);
- if (4 + 16 * tRecords > tBufLen || tRecords >= 0x7fff) {
- /* Just a sanity check */
- DBG_DEC(tRecords);
- DBG_DEC(4 + 16 * tRecords);
- DBG_DEC(tBufLen);
- return;
- }
- aulLfoList = xcalloc(tRecords, sizeof(ULONG));
- for (iIndex = 0; iIndex < (int)tRecords; iIndex++) {
- aulLfoList[iIndex] = ulGetLong(4 + 16 * iIndex, aucBuffer);
- NO_DBG_HEX(aulLfoList[iIndex]);
- }
- usLfoLen = (USHORT)tRecords;
- } /* end of vBuildLfoList */
- /*
- * vAdd2ListInfoList - add an element to the List Information list
- */
- void
- vAdd2ListInfoList(ULONG ulListID, USHORT usIstd, UCHAR ucListLevel,
- const list_block_type *pListBlock)
- {
- list_desc_type *pListMember;
- fail(pListBlock == NULL);
- NO_DBG_HEX(ulListID);
- NO_DBG_DEC(usIstd);
- NO_DBG_DEC(ucListLevel);
- NO_DBG_DEC(pListBlock->ulStartAt);
- NO_DBG_DEC(pListBlock->bNoRestart);
- NO_DBG_DEC(pListBlock->sLeftIndent);
- NO_DBG_HEX(pListBlock->ucNFC);
- NO_DBG_HEX(pListBlock->usListChar);
- /* Create list member */
- pListMember = xmalloc(sizeof(list_desc_type));
- /* Fill the list member */
- pListMember->tInfo = *pListBlock;
- pListMember->ulListID = ulListID;
- pListMember->usIstd = usIstd;
- pListMember->ucListLevel = ucListLevel;
- pListMember->pNext = NULL;
- /* Correct the values where needed */
- if (pListMember->tInfo.ulStartAt > 0xffff) {
- DBG_DEC(pListMember->tInfo.ulStartAt);
- pListMember->tInfo.ulStartAt = 1;
- }
- /* Add the new member to the list */
- if (pAnchor == NULL) {
- pAnchor = pListMember;
- } else {
- fail(pBlockLast == NULL);
- pBlockLast->pNext = pListMember;
- }
- pBlockLast = pListMember;
- } /* end of vAdd2ListInfoList */
- /*
- * Get a matching record from the List Information List
- *
- * Returns NULL if no matching records is found
- */
- const list_block_type *
- pGetListInfo(USHORT usListIndex, UCHAR ucListLevel)
- {
- list_desc_type *pCurr;
- list_block_type *pNearMatch;
- ULONG ulListID;
- if (usListIndex == 0) {
- return NULL;
- }
- if (usListIndex - 1 >= usLfoLen || ucListLevel > 8) {
- DBG_DEC(usListIndex);
- DBG_DEC(ucListLevel);
- return NULL;
- }
- fail(aulLfoList == NULL);
- ulListID = aulLfoList[usListIndex - 1];
- NO_DBG_HEX(ulListID);
- pNearMatch = NULL;
- for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
- if (pCurr->ulListID != ulListID) {
- /* No match */
- continue;
- }
- if (pCurr->ucListLevel == ucListLevel) {
- /* Exact match */
- return &pCurr->tInfo;
- }
- if (pCurr->ucListLevel == 0) {
- /* Near match */
- pNearMatch = &pCurr->tInfo;
- }
- }
- /* No exact match, use a near match if any */
- return pNearMatch;
- } /* end of pGetListInfo */
- /*
- * Get a matching record from the List Information List
- *
- * Returns NULL if no matching records is found
- */
- const list_block_type *
- pGetListInfoByIstd(USHORT usIstd)
- {
- list_desc_type *pCurr;
- if (usIstd == ISTD_INVALID || usIstd == STI_NIL || usIstd == STI_USER) {
- return NULL;
- }
- for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
- if (pCurr->usIstd == usIstd) {
- return &pCurr->tInfo;
- }
- }
- return NULL;
- } /* end of pGetListInfoByIstd */
- /*
- * vRestartListValues - reset the less significant list levels
- */
- static void
- vRestartListValues(USHORT usListIndex, UCHAR ucListLevel)
- {
- list_value_type *pPrev, *pCurr, *pNext;
- int iCounter;
- iCounter = 0;
- pPrev = NULL;
- pCurr = pValues;
- while (pCurr != NULL) {
- if (pCurr->usListIndex != usListIndex ||
- pCurr->ucListLevel <= ucListLevel) {
- pPrev = pCurr;
- pCurr = pCurr->pNext;
- continue;
- }
- /* Reset the level by deleting the record */
- pNext = pCurr->pNext;
- if (pPrev == NULL) {
- pValues = pNext;
- } else {
- pPrev->pNext = pNext;
- }
- DBG_DEC(pCurr->usListIndex);
- DBG_DEC(pCurr->ucListLevel);
- pCurr = xfree(pCurr);
- pCurr = pNext;
- iCounter++;
- }
- DBG_DEC_C(iCounter > 0, iCounter);
- } /* end of vRestartListValues */
- /*
- * usGetListValue - Get the current value of the given list
- *
- * Returns the value of the given list
- */
- USHORT
- usGetListValue(int iListSeqNumber, int iWordVersion,
- const style_block_type *pStyle)
- {
- list_value_type *pCurr;
- USHORT usValue;
- fail(iListSeqNumber < 0);
- fail(iListSeqNumber < iOldListSeqNumber);
- fail(iWordVersion < 0);
- fail(pStyle == NULL);
- if (iListSeqNumber <= 0) {
- return 0;
- }
- if (iWordVersion < 8) {
- /* Old style list */
- if (iListSeqNumber == iOldListSeqNumber ||
- (iListSeqNumber == iOldListSeqNumber + 1 &&
- eGetNumType(pStyle->ucNumLevel) == level_type_sequence)) {
- if (!pStyle->bNumPause) {
- usOldListValue++;
- }
- } else {
- usOldListValue = pStyle->usStartAt;
- }
- iOldListSeqNumber = iListSeqNumber;
- return usOldListValue;
- }
- /* New style list */
- if (pStyle->usListIndex == 0 ||
- pStyle->usListIndex - 1 >= usLfoLen ||
- pStyle->ucListLevel > 8) {
- /* Out of range; no need to search */
- return 0;
- }
- for (pCurr = pValues; pCurr != NULL; pCurr = pCurr->pNext) {
- if (pCurr->usListIndex == pStyle->usListIndex &&
- pCurr->ucListLevel == pStyle->ucListLevel) {
- /* Record found; increment and return the value */
- pCurr->usValue++;
- usValue = pCurr->usValue;
- if (!pStyle->bNoRestart) {
- vRestartListValues(pStyle->usListIndex,
- pStyle->ucListLevel);
- }
- return usValue;
- }
- }
- /* Record not found; create it and add it to the front of the list */
- pCurr = xmalloc(sizeof(list_value_type));
- pCurr->usValue = pStyle->usStartAt;
- pCurr->usListIndex = pStyle->usListIndex;
- pCurr->ucListLevel = pStyle->ucListLevel;
- pCurr->pNext = pValues;
- pValues = pCurr;
- usValue = pCurr->usValue;
- if (!pStyle->bNoRestart) {
- vRestartListValues(pStyle->usListIndex, pStyle->ucListLevel);
- }
- return usValue;
- } /* end of usGetListValue */
|