⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 blocklist.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 + -