xref: /plan9/sys/src/cmd/aux/antiword/blocklist.c (revision 25b329d522281a8cdd35da0dcc08c3fc621059a9)
1f5736e95SDavid du Colombier /*
2f5736e95SDavid du Colombier  * blocklist.c
3*25b329d5SDavid du Colombier  * Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
4f5736e95SDavid du Colombier  *
5f5736e95SDavid du Colombier  * Description:
6f5736e95SDavid du Colombier  * Build, read and destroy the lists of Word "text" blocks
7f5736e95SDavid du Colombier  */
8f5736e95SDavid du Colombier 
9f5736e95SDavid du Colombier #include <stdlib.h>
10f5736e95SDavid du Colombier #include "antiword.h"
11f5736e95SDavid du Colombier 
12f5736e95SDavid du Colombier 
13f5736e95SDavid du Colombier /*
14f5736e95SDavid du Colombier  * Private structure to hide the way the information
15f5736e95SDavid du Colombier  * is stored from the rest of the program
16f5736e95SDavid du Colombier  */
17f5736e95SDavid du Colombier typedef struct list_mem_tag {
18f5736e95SDavid du Colombier 	text_block_type		tInfo;
19f5736e95SDavid du Colombier 	struct list_mem_tag	*pNext;
20f5736e95SDavid du Colombier } list_mem_type;
21f5736e95SDavid du Colombier 
22*25b329d5SDavid du Colombier typedef struct readinfo_tag {
23*25b329d5SDavid du Colombier 	list_mem_type		*pBlockCurrent;
24*25b329d5SDavid du Colombier 	ULONG			ulBlockOffset;
25*25b329d5SDavid du Colombier 	size_t			tByteNext;
26*25b329d5SDavid du Colombier 	UCHAR			aucBlock[BIG_BLOCK_SIZE];
27*25b329d5SDavid du Colombier } readinfo_type;
28*25b329d5SDavid du Colombier 
29f5736e95SDavid du Colombier /* Variables to describe the start of the block lists */
30f5736e95SDavid du Colombier static list_mem_type	*pTextAnchor = NULL;
31*25b329d5SDavid du Colombier static list_mem_type	*pFootnoteAnchor = NULL;
32f5736e95SDavid du Colombier static list_mem_type	*pHdrFtrAnchor = NULL;
33f5736e95SDavid du Colombier static list_mem_type	*pMacroAnchor = NULL;
34f5736e95SDavid du Colombier static list_mem_type	*pAnnotationAnchor = NULL;
35*25b329d5SDavid du Colombier static list_mem_type	*pEndnoteAnchor = NULL;
36f5736e95SDavid du Colombier static list_mem_type	*pTextBoxAnchor = NULL;
37f5736e95SDavid du Colombier static list_mem_type	*pHdrTextBoxAnchor = NULL;
38f5736e95SDavid du Colombier /* Variable needed to build the block list */
39f5736e95SDavid du Colombier static list_mem_type	*pBlockLast = NULL;
40*25b329d5SDavid du Colombier /* Variable needed to read the block lists */
41*25b329d5SDavid du Colombier static readinfo_type	tOthers = { NULL, 0, 0, };
42*25b329d5SDavid du Colombier static readinfo_type	tHdrFtr = { NULL, 0, 0, };
43*25b329d5SDavid du Colombier static readinfo_type	tFootnote = { NULL, 0, 0, };
44f5736e95SDavid du Colombier 
45f5736e95SDavid du Colombier 
46f5736e95SDavid du Colombier /*
47f5736e95SDavid du Colombier  * pFreeOneList - free a text block list
48f5736e95SDavid du Colombier  *
49f5736e95SDavid du Colombier  * Will always return NULL
50f5736e95SDavid du Colombier  */
51f5736e95SDavid du Colombier static list_mem_type *
pFreeOneList(list_mem_type * pAnchor)52f5736e95SDavid du Colombier pFreeOneList(list_mem_type *pAnchor)
53f5736e95SDavid du Colombier {
54f5736e95SDavid du Colombier 	list_mem_type	*pCurr, *pNext;
55f5736e95SDavid du Colombier 
56f5736e95SDavid du Colombier 	pCurr = pAnchor;
57f5736e95SDavid du Colombier 	while (pCurr != NULL) {
58f5736e95SDavid du Colombier 		pNext = pCurr->pNext;
59f5736e95SDavid du Colombier 		pCurr = xfree(pCurr);
60f5736e95SDavid du Colombier 		pCurr = pNext;
61f5736e95SDavid du Colombier 	}
62f5736e95SDavid du Colombier 	return NULL;
63f5736e95SDavid du Colombier } /* end of pFreeOneList */
64f5736e95SDavid du Colombier 
65f5736e95SDavid du Colombier /*
66f5736e95SDavid du Colombier  * vDestroyTextBlockList - destroy the text block lists
67f5736e95SDavid du Colombier  */
68f5736e95SDavid du Colombier void
vDestroyTextBlockList(void)69f5736e95SDavid du Colombier vDestroyTextBlockList(void)
70f5736e95SDavid du Colombier {
71f5736e95SDavid du Colombier 	DBG_MSG("vDestroyTextBlockList");
72f5736e95SDavid du Colombier 
73f5736e95SDavid du Colombier 	/* Free the lists one by one */
74f5736e95SDavid du Colombier 	pTextAnchor = pFreeOneList(pTextAnchor);
75*25b329d5SDavid du Colombier 	pFootnoteAnchor = pFreeOneList(pFootnoteAnchor);
76f5736e95SDavid du Colombier 	pHdrFtrAnchor = pFreeOneList(pHdrFtrAnchor);
77f5736e95SDavid du Colombier 	pMacroAnchor = pFreeOneList(pMacroAnchor);
78f5736e95SDavid du Colombier 	pAnnotationAnchor = pFreeOneList(pAnnotationAnchor);
79*25b329d5SDavid du Colombier 	pEndnoteAnchor = pFreeOneList(pEndnoteAnchor);
80f5736e95SDavid du Colombier 	pTextBoxAnchor = pFreeOneList(pTextBoxAnchor);
81f5736e95SDavid du Colombier 	pHdrTextBoxAnchor = pFreeOneList(pHdrTextBoxAnchor);
82f5736e95SDavid du Colombier 	/* Reset all the controle variables */
83f5736e95SDavid du Colombier 	pBlockLast = NULL;
84*25b329d5SDavid du Colombier 	tOthers.pBlockCurrent = NULL;
85*25b329d5SDavid du Colombier 	tHdrFtr.pBlockCurrent = NULL;
86*25b329d5SDavid du Colombier 	tFootnote.pBlockCurrent = NULL;
87f5736e95SDavid du Colombier } /* end of vDestroyTextBlockList */
88f5736e95SDavid du Colombier 
89f5736e95SDavid du Colombier /*
90f5736e95SDavid du Colombier  * bAdd2TextBlockList - add an element to the text block list
91f5736e95SDavid du Colombier  *
92f5736e95SDavid du Colombier  * returns: TRUE when successful, otherwise FALSE
93f5736e95SDavid du Colombier  */
94f5736e95SDavid du Colombier BOOL
bAdd2TextBlockList(const text_block_type * pTextBlock)95f5736e95SDavid du Colombier bAdd2TextBlockList(const text_block_type *pTextBlock)
96f5736e95SDavid du Colombier {
97f5736e95SDavid du Colombier 	list_mem_type	*pListMember;
98f5736e95SDavid du Colombier 
99f5736e95SDavid du Colombier 	fail(pTextBlock == NULL);
100f5736e95SDavid du Colombier 	fail(pTextBlock->ulFileOffset == FC_INVALID);
101f5736e95SDavid du Colombier 	fail(pTextBlock->ulCharPos == CP_INVALID);
102f5736e95SDavid du Colombier 	fail(pTextBlock->ulLength == 0);
103f5736e95SDavid du Colombier 	fail(pTextBlock->bUsesUnicode && odd(pTextBlock->ulLength));
104f5736e95SDavid du Colombier 
105f5736e95SDavid du Colombier 	NO_DBG_MSG("bAdd2TextBlockList");
106f5736e95SDavid du Colombier 	NO_DBG_HEX(pTextBlock->ulFileOffset);
107f5736e95SDavid du Colombier 	NO_DBG_HEX(pTextBlock->ulCharPos);
108f5736e95SDavid du Colombier 	NO_DBG_HEX(pTextBlock->ulLength);
109f5736e95SDavid du Colombier 	NO_DBG_DEC(pTextBlock->bUsesUnicode);
110f5736e95SDavid du Colombier 	NO_DBG_DEC(pTextBlock->usPropMod);
111f5736e95SDavid du Colombier 
112f5736e95SDavid du Colombier 	if (pTextBlock->ulFileOffset == FC_INVALID ||
113f5736e95SDavid du Colombier 	    pTextBlock->ulCharPos == CP_INVALID ||
114f5736e95SDavid du Colombier 	    pTextBlock->ulLength == 0 ||
115f5736e95SDavid du Colombier 	    (pTextBlock->bUsesUnicode && odd(pTextBlock->ulLength))) {
116f5736e95SDavid du Colombier 		werr(0, "Software (textblock) error");
117f5736e95SDavid du Colombier 		return FALSE;
118f5736e95SDavid du Colombier 	}
119f5736e95SDavid du Colombier 	/*
120f5736e95SDavid du Colombier 	 * Check for continuous blocks of the same character size and
121f5736e95SDavid du Colombier 	 * the same properties modifier
122f5736e95SDavid du Colombier 	 */
123f5736e95SDavid du Colombier 	if (pBlockLast != NULL &&
124f5736e95SDavid du Colombier 	    pBlockLast->tInfo.ulFileOffset +
125f5736e95SDavid du Colombier 	     pBlockLast->tInfo.ulLength == pTextBlock->ulFileOffset &&
126f5736e95SDavid du Colombier 	    pBlockLast->tInfo.ulCharPos +
127f5736e95SDavid du Colombier 	     pBlockLast->tInfo.ulLength == pTextBlock->ulCharPos &&
128f5736e95SDavid du Colombier 	    pBlockLast->tInfo.bUsesUnicode == pTextBlock->bUsesUnicode &&
129f5736e95SDavid du Colombier 	    pBlockLast->tInfo.usPropMod == pTextBlock->usPropMod) {
130f5736e95SDavid du Colombier 		/* These are continous blocks */
131f5736e95SDavid du Colombier 		pBlockLast->tInfo.ulLength += pTextBlock->ulLength;
132f5736e95SDavid du Colombier 		return TRUE;
133f5736e95SDavid du Colombier 	}
134f5736e95SDavid du Colombier 	/* Make a new block */
135f5736e95SDavid du Colombier 	pListMember = xmalloc(sizeof(list_mem_type));
136f5736e95SDavid du Colombier 	/* Add the block to the list */
137f5736e95SDavid du Colombier 	pListMember->tInfo = *pTextBlock;
138f5736e95SDavid du Colombier 	pListMember->pNext = NULL;
139f5736e95SDavid du Colombier 	if (pTextAnchor == NULL) {
140f5736e95SDavid du Colombier 		pTextAnchor = pListMember;
141f5736e95SDavid du Colombier 	} else {
142f5736e95SDavid du Colombier 		fail(pBlockLast == NULL);
143f5736e95SDavid du Colombier 		pBlockLast->pNext = pListMember;
144f5736e95SDavid du Colombier 	}
145f5736e95SDavid du Colombier 	pBlockLast = pListMember;
146f5736e95SDavid du Colombier 	return TRUE;
147f5736e95SDavid du Colombier } /* end of bAdd2TextBlockList */
148f5736e95SDavid du Colombier 
149f5736e95SDavid du Colombier /*
150f5736e95SDavid du Colombier  * vSpitList - Split the list in two
151f5736e95SDavid du Colombier  */
152f5736e95SDavid du Colombier static void
vSpitList(list_mem_type ** ppAnchorCurr,list_mem_type ** ppAnchorNext,ULONG ulListLen)153f5736e95SDavid du Colombier vSpitList(list_mem_type **ppAnchorCurr, list_mem_type **ppAnchorNext,
154f5736e95SDavid du Colombier 	ULONG ulListLen)
155f5736e95SDavid du Colombier {
156f5736e95SDavid du Colombier 	list_mem_type	*pCurr;
157f5736e95SDavid du Colombier 	long		lCharsToGo, lBytesTooFar;
158f5736e95SDavid du Colombier 
159f5736e95SDavid du Colombier 	fail(ppAnchorCurr == NULL);
160f5736e95SDavid du Colombier 	fail(ppAnchorNext == NULL);
161f5736e95SDavid du Colombier 	fail(ulListLen > (ULONG)LONG_MAX);
162f5736e95SDavid du Colombier 
163f5736e95SDavid du Colombier 	pCurr = NULL;
164f5736e95SDavid du Colombier 	lCharsToGo = (long)ulListLen;
165f5736e95SDavid du Colombier 	lBytesTooFar = -1;
166f5736e95SDavid du Colombier 	if (ulListLen != 0) {
167f5736e95SDavid du Colombier 		DBG_DEC(ulListLen);
168f5736e95SDavid du Colombier 		for (pCurr = *ppAnchorCurr;
169f5736e95SDavid du Colombier 		     pCurr != NULL;
170f5736e95SDavid du Colombier 		     pCurr = pCurr->pNext) {
171f5736e95SDavid du Colombier 			NO_DBG_DEC(pCurr->tInfo.ulLength);
172f5736e95SDavid du Colombier 			fail(pCurr->tInfo.ulLength == 0);
173f5736e95SDavid du Colombier 			fail(pCurr->tInfo.ulLength > (ULONG)LONG_MAX);
174f5736e95SDavid du Colombier 			if (pCurr->tInfo.bUsesUnicode) {
175f5736e95SDavid du Colombier 				fail(odd(pCurr->tInfo.ulLength));
176f5736e95SDavid du Colombier 				lCharsToGo -= (long)(pCurr->tInfo.ulLength / 2);
177f5736e95SDavid du Colombier 				if (lCharsToGo < 0) {
178f5736e95SDavid du Colombier 					lBytesTooFar = -2 * lCharsToGo;
179f5736e95SDavid du Colombier 				}
180f5736e95SDavid du Colombier 			} else {
181f5736e95SDavid du Colombier 				lCharsToGo -= (long)pCurr->tInfo.ulLength;
182f5736e95SDavid du Colombier 				if (lCharsToGo < 0) {
183f5736e95SDavid du Colombier 					lBytesTooFar = -lCharsToGo;
184f5736e95SDavid du Colombier 				}
185f5736e95SDavid du Colombier 			}
186f5736e95SDavid du Colombier 			if (lCharsToGo <= 0) {
187f5736e95SDavid du Colombier 				break;
188f5736e95SDavid du Colombier 			}
189f5736e95SDavid du Colombier 		}
190f5736e95SDavid du Colombier 	}
191f5736e95SDavid du Colombier /* Split the list */
192f5736e95SDavid du Colombier 	if (ulListLen == 0) {
193f5736e95SDavid du Colombier 		/* Current blocklist is empty */
194f5736e95SDavid du Colombier 		*ppAnchorNext = *ppAnchorCurr;
195f5736e95SDavid du Colombier 		*ppAnchorCurr = NULL;
196f5736e95SDavid du Colombier 	} else if (pCurr == NULL) {
197f5736e95SDavid du Colombier 		/* No blocks for the next list */
198f5736e95SDavid du Colombier 		*ppAnchorNext = NULL;
199f5736e95SDavid du Colombier 	} else if (lCharsToGo == 0) {
200f5736e95SDavid du Colombier 		/* Move the integral number of blocks to the next list */
201f5736e95SDavid du Colombier 		*ppAnchorNext = pCurr->pNext;
202f5736e95SDavid du Colombier 		pCurr->pNext = NULL;
203f5736e95SDavid du Colombier 	} else {
204f5736e95SDavid du Colombier 		/* Split the part current block list, part next block list */
205f5736e95SDavid du Colombier 		DBG_DEC(lBytesTooFar);
206f5736e95SDavid du Colombier 		fail(lBytesTooFar <= 0);
207f5736e95SDavid du Colombier 		*ppAnchorNext = xmalloc(sizeof(list_mem_type));
208f5736e95SDavid du Colombier 		DBG_HEX(pCurr->tInfo.ulFileOffset);
209f5736e95SDavid du Colombier 		(*ppAnchorNext)->tInfo.ulFileOffset =
210f5736e95SDavid du Colombier 				pCurr->tInfo.ulFileOffset +
211f5736e95SDavid du Colombier 				pCurr->tInfo.ulLength -
212f5736e95SDavid du Colombier 				lBytesTooFar;
213f5736e95SDavid du Colombier 		DBG_HEX((*ppAnchorNext)->tInfo.ulFileOffset);
214f5736e95SDavid du Colombier 		DBG_HEX(pCurr->tInfo.ulCharPos);
215f5736e95SDavid du Colombier 		(*ppAnchorNext)->tInfo.ulCharPos =
216f5736e95SDavid du Colombier 				pCurr->tInfo.ulCharPos +
217f5736e95SDavid du Colombier 				pCurr->tInfo.ulLength -
218f5736e95SDavid du Colombier 				lBytesTooFar;
219f5736e95SDavid du Colombier 		DBG_HEX((*ppAnchorNext)->tInfo.ulCharPos);
220f5736e95SDavid du Colombier 		(*ppAnchorNext)->tInfo.ulLength = (ULONG)lBytesTooFar;
221f5736e95SDavid du Colombier 		pCurr->tInfo.ulLength -= (ULONG)lBytesTooFar;
222f5736e95SDavid du Colombier 		(*ppAnchorNext)->tInfo.bUsesUnicode = pCurr->tInfo.bUsesUnicode;
223f5736e95SDavid du Colombier 		(*ppAnchorNext)->tInfo.usPropMod = pCurr->tInfo.usPropMod;
224f5736e95SDavid du Colombier 		/* Move the integral number of blocks to the next list */
225f5736e95SDavid du Colombier 		(*ppAnchorNext)->pNext = pCurr->pNext;
226f5736e95SDavid du Colombier 		pCurr->pNext = NULL;
227f5736e95SDavid du Colombier 	}
228f5736e95SDavid du Colombier } /* end of vSpitList */
229f5736e95SDavid du Colombier 
230f5736e95SDavid du Colombier #if defined(DEBUG) || defined(__riscos)
231f5736e95SDavid du Colombier /*
232f5736e95SDavid du Colombier  * ulComputeListLength - compute the length of a list
233f5736e95SDavid du Colombier  *
234f5736e95SDavid du Colombier  * returns the list length in characters
235f5736e95SDavid du Colombier  */
236f5736e95SDavid du Colombier static ULONG
ulComputeListLength(const list_mem_type * pAnchor)237f5736e95SDavid du Colombier ulComputeListLength(const list_mem_type *pAnchor)
238f5736e95SDavid du Colombier {
239f5736e95SDavid du Colombier 	const list_mem_type	*pCurr;
240f5736e95SDavid du Colombier 	ULONG		ulTotal;
241f5736e95SDavid du Colombier 
242f5736e95SDavid du Colombier 	ulTotal = 0;
243f5736e95SDavid du Colombier 	for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
244f5736e95SDavid du Colombier 		fail(pCurr->tInfo.ulLength == 0);
245f5736e95SDavid du Colombier 		if (pCurr->tInfo.bUsesUnicode) {
246f5736e95SDavid du Colombier 			fail(odd(pCurr->tInfo.ulLength));
247f5736e95SDavid du Colombier 			ulTotal += pCurr->tInfo.ulLength / 2;
248f5736e95SDavid du Colombier 		} else {
249f5736e95SDavid du Colombier 			ulTotal += pCurr->tInfo.ulLength;
250f5736e95SDavid du Colombier 		}
251f5736e95SDavid du Colombier 	}
252f5736e95SDavid du Colombier 	return ulTotal;
253f5736e95SDavid du Colombier } /* end of ulComputeListLength */
254f5736e95SDavid du Colombier #endif /* DEBUG || __riscos */
255f5736e95SDavid du Colombier 
256f5736e95SDavid du Colombier #if defined(DEBUG)
257f5736e95SDavid du Colombier /*
258f5736e95SDavid du Colombier  * vCheckList - check the number of bytes in a block list
259f5736e95SDavid du Colombier  */
260f5736e95SDavid du Colombier static void
vCheckList(const list_mem_type * pAnchor,ULONG ulListLen,char * szMsg)261f5736e95SDavid du Colombier vCheckList(const list_mem_type *pAnchor, ULONG ulListLen, char *szMsg)
262f5736e95SDavid du Colombier {
263f5736e95SDavid du Colombier 	ULONG		ulTotal;
264f5736e95SDavid du Colombier 
265f5736e95SDavid du Colombier 	ulTotal = ulComputeListLength(pAnchor);
266f5736e95SDavid du Colombier 	DBG_DEC(ulTotal);
267f5736e95SDavid du Colombier 	if (ulTotal != ulListLen) {
268f5736e95SDavid du Colombier 		DBG_DEC(ulListLen);
269f5736e95SDavid du Colombier 		werr(1, szMsg);
270f5736e95SDavid du Colombier 	}
271f5736e95SDavid du Colombier } /* end of vCheckList */
272f5736e95SDavid du Colombier #endif /* DEBUG */
273f5736e95SDavid du Colombier 
274f5736e95SDavid du Colombier /*
275f5736e95SDavid du Colombier  * bIsEmptyBox - check to see if the given text box is empty
276f5736e95SDavid du Colombier  */
277f5736e95SDavid du Colombier static BOOL
bIsEmptyBox(FILE * pFile,const list_mem_type * pAnchor)278f5736e95SDavid du Colombier bIsEmptyBox(FILE *pFile, const list_mem_type *pAnchor)
279f5736e95SDavid du Colombier {
280f5736e95SDavid du Colombier 	const list_mem_type	*pCurr;
281f5736e95SDavid du Colombier 	size_t	tIndex, tSize;
282f5736e95SDavid du Colombier 	UCHAR	*aucBuffer;
283f5736e95SDavid du Colombier 	char	cChar;
284f5736e95SDavid du Colombier 
285f5736e95SDavid du Colombier 	fail(pFile == NULL);
286f5736e95SDavid du Colombier 
287f5736e95SDavid du Colombier 	if (pAnchor == NULL) {
288f5736e95SDavid du Colombier 		return TRUE;
289f5736e95SDavid du Colombier 	}
290f5736e95SDavid du Colombier 
291f5736e95SDavid du Colombier 	aucBuffer = NULL;
292f5736e95SDavid du Colombier 	for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
293f5736e95SDavid du Colombier 		fail(pCurr->tInfo.ulLength == 0);
294f5736e95SDavid du Colombier 		tSize = (size_t)pCurr->tInfo.ulLength;
295*25b329d5SDavid du Colombier #if defined(__dos) && !defined(__DJGPP__)
296f5736e95SDavid du Colombier 		if (pCurr->tInfo.ulLength > 0xffffUL) {
297f5736e95SDavid du Colombier 			tSize = 0xffff;
298f5736e95SDavid du Colombier 		}
299*25b329d5SDavid du Colombier #endif /* __dos && !__DJGPP__ */
300*25b329d5SDavid du Colombier 		fail(aucBuffer != NULL);
301f5736e95SDavid du Colombier 		aucBuffer = xmalloc(tSize);
302f5736e95SDavid du Colombier 		if (!bReadBytes(aucBuffer, tSize,
303f5736e95SDavid du Colombier 				pCurr->tInfo.ulFileOffset, pFile)) {
304f5736e95SDavid du Colombier 			aucBuffer = xfree(aucBuffer);
305f5736e95SDavid du Colombier 			return FALSE;
306f5736e95SDavid du Colombier 		}
307f5736e95SDavid du Colombier 		for (tIndex = 0; tIndex < tSize; tIndex++) {
308f5736e95SDavid du Colombier 			cChar = (char)aucBuffer[tIndex];
309f5736e95SDavid du Colombier 			switch (cChar) {
310f5736e95SDavid du Colombier 			case '\0': case '\r': case '\n':
311f5736e95SDavid du Colombier 			case '\f': case '\t': case '\v':
312f5736e95SDavid du Colombier 			case ' ':
313f5736e95SDavid du Colombier 				break;
314f5736e95SDavid du Colombier 			default:
315f5736e95SDavid du Colombier 				aucBuffer = xfree(aucBuffer);
316f5736e95SDavid du Colombier 				return FALSE;
317f5736e95SDavid du Colombier 			}
318f5736e95SDavid du Colombier 		}
319f5736e95SDavid du Colombier 		aucBuffer = xfree(aucBuffer);
320*25b329d5SDavid du Colombier 	}
321*25b329d5SDavid du Colombier 	fail(aucBuffer != NULL);
322f5736e95SDavid du Colombier 	return TRUE;
323f5736e95SDavid du Colombier } /* end of bIsEmptyBox */
324f5736e95SDavid du Colombier 
325f5736e95SDavid du Colombier /*
326f5736e95SDavid du Colombier  * vSplitBlockList - split the block list in the various parts
327f5736e95SDavid du Colombier  *
328f5736e95SDavid du Colombier  * Split the blocklist in a Text block list, a Footnote block list, a
329f5736e95SDavid du Colombier  * HeaderFooter block list, a Macro block list, an Annotation block list,
330f5736e95SDavid du Colombier  * an Endnote block list, a TextBox list and a HeaderTextBox list.
331f5736e95SDavid du Colombier  *
332f5736e95SDavid du Colombier  * NOTE:
333f5736e95SDavid du Colombier  * The various ul*Len input parameters are given in characters, but the
334f5736e95SDavid du Colombier  * length of the blocks are in bytes.
335f5736e95SDavid du Colombier  */
336f5736e95SDavid du Colombier void
vSplitBlockList(FILE * pFile,ULONG ulTextLen,ULONG ulFootnoteLen,ULONG ulHdrFtrLen,ULONG ulMacroLen,ULONG ulAnnotationLen,ULONG ulEndnoteLen,ULONG ulTextBoxLen,ULONG ulHdrTextBoxLen,BOOL bMustExtend)337f5736e95SDavid du Colombier vSplitBlockList(FILE *pFile, ULONG ulTextLen, ULONG ulFootnoteLen,
338f5736e95SDavid du Colombier 	ULONG ulHdrFtrLen, ULONG ulMacroLen, ULONG ulAnnotationLen,
339f5736e95SDavid du Colombier 	ULONG ulEndnoteLen, ULONG ulTextBoxLen, ULONG ulHdrTextBoxLen,
340f5736e95SDavid du Colombier 	BOOL bMustExtend)
341f5736e95SDavid du Colombier {
342f5736e95SDavid du Colombier 	list_mem_type	*apAnchors[8];
343f5736e95SDavid du Colombier 	list_mem_type	*pGarbageAnchor, *pCurr;
344f5736e95SDavid du Colombier 	size_t		tIndex;
345f5736e95SDavid du Colombier 
346f5736e95SDavid du Colombier 	DBG_MSG("vSplitBlockList");
347f5736e95SDavid du Colombier 
348f5736e95SDavid du Colombier 	pGarbageAnchor = NULL;
349f5736e95SDavid du Colombier 
350f5736e95SDavid du Colombier 	DBG_MSG_C(ulTextLen != 0, "Text block list");
351*25b329d5SDavid du Colombier 	vSpitList(&pTextAnchor, &pFootnoteAnchor, ulTextLen);
352f5736e95SDavid du Colombier 	DBG_MSG_C(ulFootnoteLen != 0, "Footnote block list");
353*25b329d5SDavid du Colombier 	vSpitList(&pFootnoteAnchor, &pHdrFtrAnchor, ulFootnoteLen);
354f5736e95SDavid du Colombier 	DBG_MSG_C(ulHdrFtrLen != 0, "Header/Footer block list");
355f5736e95SDavid du Colombier 	vSpitList(&pHdrFtrAnchor, &pMacroAnchor, ulHdrFtrLen);
356f5736e95SDavid du Colombier 	DBG_MSG_C(ulMacroLen != 0, "Macro block list");
357f5736e95SDavid du Colombier 	vSpitList(&pMacroAnchor, &pAnnotationAnchor, ulMacroLen);
358f5736e95SDavid du Colombier 	DBG_MSG_C(ulAnnotationLen != 0, "Annotation block list");
359*25b329d5SDavid du Colombier 	vSpitList(&pAnnotationAnchor, &pEndnoteAnchor, ulAnnotationLen);
360f5736e95SDavid du Colombier 	DBG_MSG_C(ulEndnoteLen != 0, "Endnote block list");
361*25b329d5SDavid du Colombier 	vSpitList(&pEndnoteAnchor, &pTextBoxAnchor, ulEndnoteLen);
362f5736e95SDavid du Colombier 	DBG_MSG_C(ulTextBoxLen != 0, "Textbox block list");
363f5736e95SDavid du Colombier 	vSpitList(&pTextBoxAnchor, &pHdrTextBoxAnchor, ulTextBoxLen);
364f5736e95SDavid du Colombier 	DBG_MSG_C(ulHdrTextBoxLen != 0, "HeaderTextbox block list");
365f5736e95SDavid du Colombier 	vSpitList(&pHdrTextBoxAnchor, &pGarbageAnchor, ulHdrTextBoxLen);
366f5736e95SDavid du Colombier 
367f5736e95SDavid du Colombier 	/* Free the garbage block list, this should not be needed */
368f5736e95SDavid du Colombier 	DBG_DEC_C(pGarbageAnchor != NULL, pGarbageAnchor->tInfo.ulLength);
369f5736e95SDavid du Colombier 	pGarbageAnchor = pFreeOneList(pGarbageAnchor);
370f5736e95SDavid du Colombier 
371f5736e95SDavid du Colombier #if defined(DEBUG)
372f5736e95SDavid du Colombier 	vCheckList(pTextAnchor, ulTextLen, "Software error (Text)");
373*25b329d5SDavid du Colombier 	vCheckList(pFootnoteAnchor, ulFootnoteLen, "Software error (Footnote)");
374f5736e95SDavid du Colombier 	vCheckList(pHdrFtrAnchor, ulHdrFtrLen, "Software error (Hdr/Ftr)");
375f5736e95SDavid du Colombier 	vCheckList(pMacroAnchor, ulMacroLen, "Software error (Macro)");
376f5736e95SDavid du Colombier 	vCheckList(pAnnotationAnchor, ulAnnotationLen,
377f5736e95SDavid du Colombier 						"Software error (Annotation)");
378*25b329d5SDavid du Colombier 	vCheckList(pEndnoteAnchor, ulEndnoteLen, "Software error (Endnote)");
379f5736e95SDavid du Colombier 	vCheckList(pTextBoxAnchor, ulTextBoxLen, "Software error (TextBox)");
380f5736e95SDavid du Colombier 	vCheckList(pHdrTextBoxAnchor, ulHdrTextBoxLen,
381f5736e95SDavid du Colombier 						"Software error (HdrTextBox)");
382f5736e95SDavid du Colombier #endif /* DEBUG */
383f5736e95SDavid du Colombier 
384f5736e95SDavid du Colombier 	/* Remove the list if the text box is empty */
385f5736e95SDavid du Colombier 	if (bIsEmptyBox(pFile, pTextBoxAnchor)) {
386f5736e95SDavid du Colombier 		pTextBoxAnchor = pFreeOneList(pTextBoxAnchor);
387f5736e95SDavid du Colombier 	}
388f5736e95SDavid du Colombier 	if (bIsEmptyBox(pFile, pHdrTextBoxAnchor)) {
389f5736e95SDavid du Colombier 		pHdrTextBoxAnchor = pFreeOneList(pHdrTextBoxAnchor);
390f5736e95SDavid du Colombier 	}
391f5736e95SDavid du Colombier 
392f5736e95SDavid du Colombier 	if (!bMustExtend) {
393f5736e95SDavid du Colombier 		return;
394f5736e95SDavid du Colombier 	}
395f5736e95SDavid du Colombier 	/*
396f5736e95SDavid du Colombier 	 * All blocks (except the last one) must have a length that
397f5736e95SDavid du Colombier 	 * is a multiple of the Big Block Size
398f5736e95SDavid du Colombier 	 */
399f5736e95SDavid du Colombier 
400f5736e95SDavid du Colombier 	apAnchors[0] = pTextAnchor;
401*25b329d5SDavid du Colombier 	apAnchors[1] = pFootnoteAnchor;
402f5736e95SDavid du Colombier 	apAnchors[2] = pHdrFtrAnchor;
403f5736e95SDavid du Colombier 	apAnchors[3] = pMacroAnchor;
404f5736e95SDavid du Colombier 	apAnchors[4] = pAnnotationAnchor;
405*25b329d5SDavid du Colombier 	apAnchors[5] = pEndnoteAnchor;
406f5736e95SDavid du Colombier 	apAnchors[6] = pTextBoxAnchor;
407f5736e95SDavid du Colombier 	apAnchors[7] = pHdrTextBoxAnchor;
408f5736e95SDavid du Colombier 
409f5736e95SDavid du Colombier 	for (tIndex = 0; tIndex < elementsof(apAnchors); tIndex++) {
410f5736e95SDavid du Colombier 		for (pCurr = apAnchors[tIndex];
411f5736e95SDavid du Colombier 		     pCurr != NULL;
412f5736e95SDavid du Colombier 		     pCurr = pCurr->pNext) {
413f5736e95SDavid du Colombier 			if (pCurr->pNext != NULL &&
414f5736e95SDavid du Colombier 			    pCurr->tInfo.ulLength % BIG_BLOCK_SIZE != 0) {
415f5736e95SDavid du Colombier 				DBG_DEC(tIndex);
416f5736e95SDavid du Colombier 				DBG_HEX(pCurr->tInfo.ulFileOffset);
417f5736e95SDavid du Colombier 				DBG_HEX(pCurr->tInfo.ulCharPos);
418f5736e95SDavid du Colombier 				DBG_DEC(pCurr->tInfo.ulLength);
419f5736e95SDavid du Colombier 				pCurr->tInfo.ulLength /= BIG_BLOCK_SIZE;
420f5736e95SDavid du Colombier 				pCurr->tInfo.ulLength++;
421f5736e95SDavid du Colombier 				pCurr->tInfo.ulLength *= BIG_BLOCK_SIZE;
422f5736e95SDavid du Colombier 				DBG_DEC(pCurr->tInfo.ulLength);
423f5736e95SDavid du Colombier 			}
424f5736e95SDavid du Colombier 		}
425f5736e95SDavid du Colombier 	}
426f5736e95SDavid du Colombier } /* end of vSplitBlockList */
427f5736e95SDavid du Colombier 
428f5736e95SDavid du Colombier #if defined(__riscos)
429f5736e95SDavid du Colombier /*
430f5736e95SDavid du Colombier  * ulGetDocumentLength - get the total character length of the printable lists
431f5736e95SDavid du Colombier  *
432f5736e95SDavid du Colombier  * returns: The total number of characters
433f5736e95SDavid du Colombier  */
434f5736e95SDavid du Colombier ULONG
ulGetDocumentLength(void)435f5736e95SDavid du Colombier ulGetDocumentLength(void)
436f5736e95SDavid du Colombier {
437f5736e95SDavid du Colombier 	long		ulTotal;
438f5736e95SDavid du Colombier 
439f5736e95SDavid du Colombier 	DBG_MSG("ulGetDocumentLength");
440f5736e95SDavid du Colombier 
441f5736e95SDavid du Colombier 	ulTotal = ulComputeListLength(pTextAnchor);
442*25b329d5SDavid du Colombier 	ulTotal += ulComputeListLength(pFootnoteAnchor);
443*25b329d5SDavid du Colombier 	ulTotal += ulComputeListLength(pEndnoteAnchor);
444f5736e95SDavid du Colombier 	ulTotal += ulComputeListLength(pTextBoxAnchor);
445f5736e95SDavid du Colombier 	ulTotal += ulComputeListLength(pHdrTextBoxAnchor);
446f5736e95SDavid du Colombier 	DBG_DEC(ulTotal);
447f5736e95SDavid du Colombier 	return ulTotal;
448f5736e95SDavid du Colombier } /* end of ulGetDocumentLength */
449f5736e95SDavid du Colombier #endif /* __riscos */
450f5736e95SDavid du Colombier 
451*25b329d5SDavid du Colombier #if 0
452*25b329d5SDavid du Colombier /*
453*25b329d5SDavid du Colombier  * bExistsHdrFtr - are there headers and/or footers?
454*25b329d5SDavid du Colombier  */
455*25b329d5SDavid du Colombier BOOL
456*25b329d5SDavid du Colombier bExistsHdrFtr(void)
457*25b329d5SDavid du Colombier {
458*25b329d5SDavid du Colombier 	return pHdrFtrAnchor != NULL &&
459*25b329d5SDavid du Colombier 		pHdrFtrAnchor->tInfo.ulLength != 0;
460*25b329d5SDavid du Colombier } /* end of bExistsHdrFtr */
461*25b329d5SDavid du Colombier #endif
462*25b329d5SDavid du Colombier 
463f5736e95SDavid du Colombier /*
464f5736e95SDavid du Colombier  * bExistsTextBox - is there a text box?
465f5736e95SDavid du Colombier  */
466f5736e95SDavid du Colombier BOOL
bExistsTextBox(void)467f5736e95SDavid du Colombier bExistsTextBox(void)
468f5736e95SDavid du Colombier {
469f5736e95SDavid du Colombier 	return pTextBoxAnchor != NULL &&
470f5736e95SDavid du Colombier 		pTextBoxAnchor->tInfo.ulLength != 0;
471f5736e95SDavid du Colombier } /* end of bExistsTextBox */
472f5736e95SDavid du Colombier 
473f5736e95SDavid du Colombier /*
474f5736e95SDavid du Colombier  * bExistsHdrTextBox - is there a header text box?
475f5736e95SDavid du Colombier  */
476f5736e95SDavid du Colombier BOOL
bExistsHdrTextBox(void)477f5736e95SDavid du Colombier bExistsHdrTextBox(void)
478f5736e95SDavid du Colombier {
479f5736e95SDavid du Colombier 	return pHdrTextBoxAnchor != NULL &&
480f5736e95SDavid du Colombier 		pHdrTextBoxAnchor->tInfo.ulLength != 0;
481f5736e95SDavid du Colombier } /* end of bExistsHdrTextBox */
482*25b329d5SDavid du Colombier 
483f5736e95SDavid du Colombier /*
484f5736e95SDavid du Colombier  * usGetNextByte - get the next byte from the specified block list
485f5736e95SDavid du Colombier  */
486f5736e95SDavid du Colombier static USHORT
usGetNextByte(FILE * pFile,readinfo_type * pInfoCurrent,list_mem_type * pAnchor,ULONG * pulFileOffset,ULONG * pulCharPos,USHORT * pusPropMod)487*25b329d5SDavid du Colombier usGetNextByte(FILE *pFile, readinfo_type *pInfoCurrent, list_mem_type *pAnchor,
488f5736e95SDavid du Colombier 	ULONG *pulFileOffset, ULONG *pulCharPos, USHORT *pusPropMod)
489f5736e95SDavid du Colombier {
490f5736e95SDavid du Colombier 	ULONG	ulReadOff;
491f5736e95SDavid du Colombier 	size_t	tReadLen;
492f5736e95SDavid du Colombier 
493*25b329d5SDavid du Colombier 	fail(pInfoCurrent == NULL);
494*25b329d5SDavid du Colombier 
495*25b329d5SDavid du Colombier 	if (pInfoCurrent->pBlockCurrent == NULL ||
496*25b329d5SDavid du Colombier 	    pInfoCurrent->tByteNext >= sizeof(pInfoCurrent->aucBlock) ||
497*25b329d5SDavid du Colombier 	    pInfoCurrent->ulBlockOffset + pInfoCurrent->tByteNext >=
498*25b329d5SDavid du Colombier 				pInfoCurrent->pBlockCurrent->tInfo.ulLength) {
499*25b329d5SDavid du Colombier 		if (pInfoCurrent->pBlockCurrent == NULL) {
500f5736e95SDavid du Colombier 			/* First block, first part */
501*25b329d5SDavid du Colombier 			pInfoCurrent->pBlockCurrent = pAnchor;
502*25b329d5SDavid du Colombier 			pInfoCurrent->ulBlockOffset = 0;
503*25b329d5SDavid du Colombier 		} else if (pInfoCurrent->ulBlockOffset +
504*25b329d5SDavid du Colombier 				sizeof(pInfoCurrent->aucBlock) <
505*25b329d5SDavid du Colombier 				pInfoCurrent->pBlockCurrent->tInfo.ulLength) {
506f5736e95SDavid du Colombier 			/* Same block, next part */
507*25b329d5SDavid du Colombier 			pInfoCurrent->ulBlockOffset +=
508*25b329d5SDavid du Colombier 					sizeof(pInfoCurrent->aucBlock);
509f5736e95SDavid du Colombier 		} else {
510f5736e95SDavid du Colombier 			/* Next block, first part */
511*25b329d5SDavid du Colombier 			pInfoCurrent->pBlockCurrent =
512*25b329d5SDavid du Colombier 					pInfoCurrent->pBlockCurrent->pNext;
513*25b329d5SDavid du Colombier 			pInfoCurrent->ulBlockOffset = 0;
514f5736e95SDavid du Colombier 		}
515*25b329d5SDavid du Colombier 		if (pInfoCurrent->pBlockCurrent == NULL) {
516f5736e95SDavid du Colombier 			/* Past the last part of the last block */
517f5736e95SDavid du Colombier 			return (USHORT)EOF;
518f5736e95SDavid du Colombier 		}
519f5736e95SDavid du Colombier 		tReadLen = (size_t)
520*25b329d5SDavid du Colombier 			(pInfoCurrent->pBlockCurrent->tInfo.ulLength -
521*25b329d5SDavid du Colombier 			 pInfoCurrent->ulBlockOffset);
522*25b329d5SDavid du Colombier 		if (tReadLen > sizeof(pInfoCurrent->aucBlock)) {
523*25b329d5SDavid du Colombier 			tReadLen = sizeof(pInfoCurrent->aucBlock);
524f5736e95SDavid du Colombier 		}
525*25b329d5SDavid du Colombier 		ulReadOff = pInfoCurrent->pBlockCurrent->tInfo.ulFileOffset +
526*25b329d5SDavid du Colombier 				pInfoCurrent->ulBlockOffset;
527*25b329d5SDavid du Colombier 		if (!bReadBytes(pInfoCurrent->aucBlock,
528*25b329d5SDavid du Colombier 						tReadLen, ulReadOff, pFile)) {
529f5736e95SDavid du Colombier 			/* Don't read from this list any longer */
530*25b329d5SDavid du Colombier 			pInfoCurrent->pBlockCurrent = NULL;
531f5736e95SDavid du Colombier 			return (USHORT)EOF;
532f5736e95SDavid du Colombier 		}
533*25b329d5SDavid du Colombier 		pInfoCurrent->tByteNext = 0;
534f5736e95SDavid du Colombier 	}
535f5736e95SDavid du Colombier 	if (pulFileOffset != NULL) {
536*25b329d5SDavid du Colombier 		*pulFileOffset =
537*25b329d5SDavid du Colombier 			pInfoCurrent->pBlockCurrent->tInfo.ulFileOffset +
538*25b329d5SDavid du Colombier 			pInfoCurrent->ulBlockOffset +
539*25b329d5SDavid du Colombier 			pInfoCurrent->tByteNext;
540f5736e95SDavid du Colombier 	}
541f5736e95SDavid du Colombier 	if (pulCharPos != NULL) {
542*25b329d5SDavid du Colombier 		*pulCharPos =
543*25b329d5SDavid du Colombier 			pInfoCurrent->pBlockCurrent->tInfo.ulCharPos +
544*25b329d5SDavid du Colombier 			pInfoCurrent->ulBlockOffset +
545*25b329d5SDavid du Colombier 			pInfoCurrent->tByteNext;
546f5736e95SDavid du Colombier 	}
547f5736e95SDavid du Colombier 	if (pusPropMod != NULL) {
548*25b329d5SDavid du Colombier 		*pusPropMod = pInfoCurrent->pBlockCurrent->tInfo.usPropMod;
549f5736e95SDavid du Colombier 	}
550*25b329d5SDavid du Colombier 	return (USHORT)pInfoCurrent->aucBlock[pInfoCurrent->tByteNext++];
551f5736e95SDavid du Colombier } /* end of usGetNextByte */
552f5736e95SDavid du Colombier 
553*25b329d5SDavid du Colombier 
554f5736e95SDavid du Colombier /*
555f5736e95SDavid du Colombier  * usGetNextChar - get the next character from the specified block list
556f5736e95SDavid du Colombier  */
557f5736e95SDavid du Colombier static USHORT
usGetNextChar(FILE * pFile,list_id_enum eListID,ULONG * pulFileOffset,ULONG * pulCharPos,USHORT * pusPropMod)558*25b329d5SDavid du Colombier usGetNextChar(FILE *pFile, list_id_enum eListID,
559f5736e95SDavid du Colombier 	ULONG *pulFileOffset, ULONG *pulCharPos, USHORT *pusPropMod)
560f5736e95SDavid du Colombier {
561*25b329d5SDavid du Colombier 	readinfo_type	*pReadinfo;
562*25b329d5SDavid du Colombier 	list_mem_type	*pAnchor;
563f5736e95SDavid du Colombier 	USHORT	usLSB, usMSB;
564f5736e95SDavid du Colombier 
565*25b329d5SDavid du Colombier 	switch (eListID) {
566*25b329d5SDavid du Colombier 	case text_list:
567*25b329d5SDavid du Colombier 		pReadinfo = &tOthers;
568*25b329d5SDavid du Colombier 		pAnchor = pTextAnchor;
569*25b329d5SDavid du Colombier 		break;
570*25b329d5SDavid du Colombier 	case footnote_list:
571*25b329d5SDavid du Colombier 		pReadinfo = &tFootnote;
572*25b329d5SDavid du Colombier 		pAnchor = pFootnoteAnchor;
573*25b329d5SDavid du Colombier 		break;
574*25b329d5SDavid du Colombier 	case hdrftr_list:
575*25b329d5SDavid du Colombier 		pReadinfo = &tHdrFtr;
576*25b329d5SDavid du Colombier 		pAnchor = pHdrFtrAnchor;
577*25b329d5SDavid du Colombier 		break;
578*25b329d5SDavid du Colombier 	case endnote_list:
579*25b329d5SDavid du Colombier 		pReadinfo = &tOthers;
580*25b329d5SDavid du Colombier 		pAnchor = pEndnoteAnchor;
581*25b329d5SDavid du Colombier 		break;
582*25b329d5SDavid du Colombier 	case textbox_list:
583*25b329d5SDavid du Colombier 		pReadinfo = &tOthers;
584*25b329d5SDavid du Colombier 		pAnchor = pTextBoxAnchor;
585*25b329d5SDavid du Colombier 		break;
586*25b329d5SDavid du Colombier 	case hdrtextbox_list:
587*25b329d5SDavid du Colombier 		pReadinfo = &tOthers;
588*25b329d5SDavid du Colombier 		pAnchor = pHdrTextBoxAnchor;
589*25b329d5SDavid du Colombier 		break;
590*25b329d5SDavid du Colombier 	default:
591*25b329d5SDavid du Colombier 		DBG_DEC(eListID);
592*25b329d5SDavid du Colombier 		return (USHORT)EOF;
593*25b329d5SDavid du Colombier 	}
594*25b329d5SDavid du Colombier 
595*25b329d5SDavid du Colombier 	usLSB = usGetNextByte(pFile, pReadinfo, pAnchor,
596f5736e95SDavid du Colombier 				pulFileOffset, pulCharPos, pusPropMod);
597f5736e95SDavid du Colombier 	if (usLSB == (USHORT)EOF) {
598f5736e95SDavid du Colombier 		return (USHORT)EOF;
599f5736e95SDavid du Colombier 	}
600*25b329d5SDavid du Colombier 	fail(pReadinfo->pBlockCurrent == NULL);
601*25b329d5SDavid du Colombier 
602*25b329d5SDavid du Colombier 	if (pReadinfo->pBlockCurrent->tInfo.bUsesUnicode) {
603*25b329d5SDavid du Colombier 		usMSB = usGetNextByte(pFile,
604*25b329d5SDavid du Colombier 				pReadinfo, pAnchor, NULL, NULL, NULL);
605f5736e95SDavid du Colombier 	} else {
606f5736e95SDavid du Colombier 		usMSB = 0x00;
607f5736e95SDavid du Colombier 	}
608f5736e95SDavid du Colombier 	if (usMSB == (USHORT)EOF) {
609f5736e95SDavid du Colombier 		DBG_MSG("usGetNextChar: Unexpected EOF");
610f5736e95SDavid du Colombier 		DBG_HEX_C(pulFileOffset != NULL, *pulFileOffset);
611f5736e95SDavid du Colombier 		DBG_HEX_C(pulCharPos != NULL, *pulCharPos);
612f5736e95SDavid du Colombier 		return (USHORT)EOF;
613f5736e95SDavid du Colombier 	}
614f5736e95SDavid du Colombier 	return (usMSB << 8) | usLSB;
615f5736e95SDavid du Colombier } /* end of usGetNextChar */
616f5736e95SDavid du Colombier 
617f5736e95SDavid du Colombier /*
618f5736e95SDavid du Colombier  * usNextChar - get the next character from the given block list
619f5736e95SDavid du Colombier  */
620f5736e95SDavid du Colombier USHORT
usNextChar(FILE * pFile,list_id_enum eListID,ULONG * pulFileOffset,ULONG * pulCharPos,USHORT * pusPropMod)621f5736e95SDavid du Colombier usNextChar(FILE *pFile, list_id_enum eListID,
622f5736e95SDavid du Colombier 	ULONG *pulFileOffset, ULONG *pulCharPos, USHORT *pusPropMod)
623f5736e95SDavid du Colombier {
624f5736e95SDavid du Colombier 	USHORT	usRetVal;
625f5736e95SDavid du Colombier 
626f5736e95SDavid du Colombier 	fail(pFile == NULL);
627f5736e95SDavid du Colombier 
628*25b329d5SDavid du Colombier 	usRetVal = usGetNextChar(pFile, eListID,
629f5736e95SDavid du Colombier 				pulFileOffset, pulCharPos, pusPropMod);
630f5736e95SDavid du Colombier 	if (usRetVal == (USHORT)EOF) {
631f5736e95SDavid du Colombier 		if (pulFileOffset != NULL) {
632f5736e95SDavid du Colombier 			*pulFileOffset = FC_INVALID;
633f5736e95SDavid du Colombier 		}
634f5736e95SDavid du Colombier 		if (pulCharPos != NULL) {
635f5736e95SDavid du Colombier 			*pulCharPos = CP_INVALID;
636f5736e95SDavid du Colombier 		}
637f5736e95SDavid du Colombier 		if (pusPropMod != NULL) {
638f5736e95SDavid du Colombier 			*pusPropMod = IGNORE_PROPMOD;
639f5736e95SDavid du Colombier 		}
640f5736e95SDavid du Colombier 	}
641f5736e95SDavid du Colombier 	return usRetVal;
642f5736e95SDavid du Colombier } /* end of usNextChar */
643f5736e95SDavid du Colombier 
644f5736e95SDavid du Colombier /*
645*25b329d5SDavid du Colombier  * usToHdrFtrPosition - Go to a character position in header/foorter list
646*25b329d5SDavid du Colombier  *
647*25b329d5SDavid du Colombier  * Returns the character found on the specified character position
648*25b329d5SDavid du Colombier  */
649*25b329d5SDavid du Colombier USHORT
usToHdrFtrPosition(FILE * pFile,ULONG ulCharPos)650*25b329d5SDavid du Colombier usToHdrFtrPosition(FILE *pFile, ULONG ulCharPos)
651*25b329d5SDavid du Colombier {
652*25b329d5SDavid du Colombier 	ULONG	ulCharPosCurr;
653*25b329d5SDavid du Colombier 	USHORT	usChar;
654*25b329d5SDavid du Colombier 
655*25b329d5SDavid du Colombier 	tHdrFtr.pBlockCurrent = NULL;	/* To reset the header/footer list */
656*25b329d5SDavid du Colombier 	do {
657*25b329d5SDavid du Colombier 		usChar = usNextChar(pFile,
658*25b329d5SDavid du Colombier 				hdrftr_list, NULL, &ulCharPosCurr, NULL);
659*25b329d5SDavid du Colombier 	} while (usChar != (USHORT)EOF && ulCharPosCurr != ulCharPos);
660*25b329d5SDavid du Colombier 	return usChar;
661*25b329d5SDavid du Colombier } /* end of usToHdrFtrPosition */
662*25b329d5SDavid du Colombier 
663*25b329d5SDavid du Colombier /*
664*25b329d5SDavid du Colombier  * usToFootnotePosition - Go to a character position in footnote list
665*25b329d5SDavid du Colombier  *
666*25b329d5SDavid du Colombier  * Returns the character found on the specified character position
667*25b329d5SDavid du Colombier  */
668*25b329d5SDavid du Colombier USHORT
usToFootnotePosition(FILE * pFile,ULONG ulCharPos)669*25b329d5SDavid du Colombier usToFootnotePosition(FILE *pFile, ULONG ulCharPos)
670*25b329d5SDavid du Colombier {
671*25b329d5SDavid du Colombier 	ULONG	ulCharPosCurr;
672*25b329d5SDavid du Colombier 	USHORT	usChar;
673*25b329d5SDavid du Colombier 
674*25b329d5SDavid du Colombier 	tFootnote.pBlockCurrent = NULL;	/* To reset the footnote list */
675*25b329d5SDavid du Colombier 	do {
676*25b329d5SDavid du Colombier 		usChar = usNextChar(pFile,
677*25b329d5SDavid du Colombier 				footnote_list, NULL, &ulCharPosCurr, NULL);
678*25b329d5SDavid du Colombier 	} while (usChar != (USHORT)EOF && ulCharPosCurr != ulCharPos);
679*25b329d5SDavid du Colombier 	return usChar;
680*25b329d5SDavid du Colombier } /* end of usToFootnotePosition */
681*25b329d5SDavid du Colombier 
682*25b329d5SDavid du Colombier /*
683*25b329d5SDavid du Colombier  * Convert a character position to an offset in the file.
684f5736e95SDavid du Colombier  * Logical to physical offset.
685f5736e95SDavid du Colombier  *
686f5736e95SDavid du Colombier  * Returns:	FC_INVALID: in case of error
687f5736e95SDavid du Colombier  *		otherwise: the computed file offset
688f5736e95SDavid du Colombier  */
689f5736e95SDavid du Colombier ULONG
ulCharPos2FileOffsetX(ULONG ulCharPos,list_id_enum * peListID)690*25b329d5SDavid du Colombier ulCharPos2FileOffsetX(ULONG ulCharPos, list_id_enum *peListID)
691f5736e95SDavid du Colombier {
692*25b329d5SDavid du Colombier 	static list_id_enum	eListIDs[8] = {
693*25b329d5SDavid du Colombier 		text_list,	footnote_list,		hdrftr_list,
694*25b329d5SDavid du Colombier 		macro_list,	annotation_list,	endnote_list,
695*25b329d5SDavid du Colombier 		textbox_list,	hdrtextbox_list,
696*25b329d5SDavid du Colombier 	};
697*25b329d5SDavid du Colombier 	list_mem_type	*apAnchors[8];
698f5736e95SDavid du Colombier 	list_mem_type	*pCurr;
699*25b329d5SDavid du Colombier 	list_id_enum	eListGuess;
700f5736e95SDavid du Colombier 	ULONG		ulBestGuess;
701f5736e95SDavid du Colombier 	size_t		tIndex;
702f5736e95SDavid du Colombier 
703*25b329d5SDavid du Colombier 	fail(peListID == NULL);
704f5736e95SDavid du Colombier 
705*25b329d5SDavid du Colombier 	if (ulCharPos == CP_INVALID) {
706*25b329d5SDavid du Colombier 		*peListID = no_list;
707*25b329d5SDavid du Colombier 		return FC_INVALID;
708*25b329d5SDavid du Colombier 	}
709*25b329d5SDavid du Colombier 
710*25b329d5SDavid du Colombier 	apAnchors[0] = pTextAnchor;
711*25b329d5SDavid du Colombier 	apAnchors[1] = pFootnoteAnchor;
712*25b329d5SDavid du Colombier 	apAnchors[2] = pHdrFtrAnchor;
713*25b329d5SDavid du Colombier 	apAnchors[3] = pMacroAnchor;
714*25b329d5SDavid du Colombier 	apAnchors[4] = pAnnotationAnchor;
715*25b329d5SDavid du Colombier 	apAnchors[5] = pEndnoteAnchor;
716*25b329d5SDavid du Colombier 	apAnchors[6] = pTextBoxAnchor;
717*25b329d5SDavid du Colombier 	apAnchors[7] = pHdrTextBoxAnchor;
718*25b329d5SDavid du Colombier 
719*25b329d5SDavid du Colombier 	eListGuess = no_list;	  /* Best guess is no list */
720f5736e95SDavid du Colombier 	ulBestGuess = FC_INVALID; /* Best guess is "file offset not found" */
721f5736e95SDavid du Colombier 
722f5736e95SDavid du Colombier 	for (tIndex = 0; tIndex < elementsof(apAnchors); tIndex++) {
723f5736e95SDavid du Colombier 		for (pCurr = apAnchors[tIndex];
724f5736e95SDavid du Colombier 		     pCurr != NULL;
725f5736e95SDavid du Colombier 		     pCurr = pCurr->pNext) {
726f5736e95SDavid du Colombier 			if (ulCharPos == pCurr->tInfo.ulCharPos +
727f5736e95SDavid du Colombier 			     pCurr->tInfo.ulLength &&
728f5736e95SDavid du Colombier 			    pCurr->pNext != NULL) {
729f5736e95SDavid du Colombier 				/*
730f5736e95SDavid du Colombier 				 * The character position is one beyond this
731f5736e95SDavid du Colombier 				 * block, so we guess it's the first byte of
732f5736e95SDavid du Colombier 				 * the next block (if there is a next block)
733f5736e95SDavid du Colombier 				 */
734*25b329d5SDavid du Colombier 				eListGuess= eListIDs[tIndex];
735f5736e95SDavid du Colombier 				ulBestGuess = pCurr->pNext->tInfo.ulFileOffset;
736f5736e95SDavid du Colombier 			}
737f5736e95SDavid du Colombier 
738f5736e95SDavid du Colombier 			if (ulCharPos < pCurr->tInfo.ulCharPos ||
739f5736e95SDavid du Colombier 			    ulCharPos >= pCurr->tInfo.ulCharPos +
740f5736e95SDavid du Colombier 			     pCurr->tInfo.ulLength) {
741f5736e95SDavid du Colombier 				/* Character position is not in this block */
742f5736e95SDavid du Colombier 				continue;
743f5736e95SDavid du Colombier 			}
744f5736e95SDavid du Colombier 
745f5736e95SDavid du Colombier 			/* The character position is in the current block */
746*25b329d5SDavid du Colombier 			*peListID = eListIDs[tIndex];
747f5736e95SDavid du Colombier 			return pCurr->tInfo.ulFileOffset +
748f5736e95SDavid du Colombier 				ulCharPos - pCurr->tInfo.ulCharPos;
749f5736e95SDavid du Colombier 		}
750f5736e95SDavid du Colombier 	}
751f5736e95SDavid du Colombier 	/* Passed beyond the end of the last list */
752f5736e95SDavid du Colombier 	NO_DBG_HEX(ulCharPos);
753f5736e95SDavid du Colombier 	NO_DBG_HEX(ulBestGuess);
754*25b329d5SDavid du Colombier 	*peListID = eListGuess;
755f5736e95SDavid du Colombier 	return ulBestGuess;
756*25b329d5SDavid du Colombier } /* end of ulCharPos2FileOffsetX */
757*25b329d5SDavid du Colombier 
758*25b329d5SDavid du Colombier /*
759*25b329d5SDavid du Colombier  * Convert a character position to an offset in the file.
760*25b329d5SDavid du Colombier  * Logical to physical offset.
761*25b329d5SDavid du Colombier  *
762*25b329d5SDavid du Colombier  * Returns:	FC_INVALID: in case of error
763*25b329d5SDavid du Colombier  *		otherwise: the computed file offset
764*25b329d5SDavid du Colombier  */
765*25b329d5SDavid du Colombier ULONG
ulCharPos2FileOffset(ULONG ulCharPos)766*25b329d5SDavid du Colombier ulCharPos2FileOffset(ULONG ulCharPos)
767*25b329d5SDavid du Colombier {
768*25b329d5SDavid du Colombier 	list_id_enum	eListID;
769*25b329d5SDavid du Colombier 
770*25b329d5SDavid du Colombier 	return ulCharPos2FileOffsetX(ulCharPos, &eListID);
771f5736e95SDavid du Colombier } /* end of ulCharPos2FileOffset */
772f5736e95SDavid du Colombier 
773f5736e95SDavid du Colombier /*
774*25b329d5SDavid du Colombier  * Convert an offset in the header/footer list to a character position.
775*25b329d5SDavid du Colombier  *
776*25b329d5SDavid du Colombier  * Returns:	CP_INVALID: in case of error
777*25b329d5SDavid du Colombier  *		otherwise: the computed character position
778*25b329d5SDavid du Colombier  */
779*25b329d5SDavid du Colombier ULONG
ulHdrFtrOffset2CharPos(ULONG ulHdrFtrOffset)780*25b329d5SDavid du Colombier ulHdrFtrOffset2CharPos(ULONG ulHdrFtrOffset)
781*25b329d5SDavid du Colombier {
782*25b329d5SDavid du Colombier 	list_mem_type	*pCurr;
783*25b329d5SDavid du Colombier 	ULONG		ulOffset;
784*25b329d5SDavid du Colombier 
785*25b329d5SDavid du Colombier 	ulOffset = ulHdrFtrOffset;
786*25b329d5SDavid du Colombier 	for (pCurr = pHdrFtrAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
787*25b329d5SDavid du Colombier 		if (ulOffset >= pCurr->tInfo.ulLength) {
788*25b329d5SDavid du Colombier 			/* The offset is not in this block */
789*25b329d5SDavid du Colombier 			ulOffset -= pCurr->tInfo.ulLength;
790*25b329d5SDavid du Colombier 			continue;
791*25b329d5SDavid du Colombier 		}
792*25b329d5SDavid du Colombier 		return pCurr->tInfo.ulCharPos + ulOffset;
793*25b329d5SDavid du Colombier 	}
794*25b329d5SDavid du Colombier 	return CP_INVALID;
795*25b329d5SDavid du Colombier } /* end of ulHdrFtrOffset2CharPos */
796*25b329d5SDavid du Colombier 
797*25b329d5SDavid du Colombier /*
798f5736e95SDavid du Colombier  * Get the sequence number beloning to the given file offset
799f5736e95SDavid du Colombier  *
800f5736e95SDavid du Colombier  * Returns the sequence number
801f5736e95SDavid du Colombier  */
802f5736e95SDavid du Colombier ULONG
ulGetSeqNumber(ULONG ulFileOffset)803f5736e95SDavid du Colombier ulGetSeqNumber(ULONG ulFileOffset)
804f5736e95SDavid du Colombier {
805f5736e95SDavid du Colombier 	list_mem_type	*pCurr;
806f5736e95SDavid du Colombier 	ULONG		ulSeq;
807f5736e95SDavid du Colombier 
808f5736e95SDavid du Colombier 	if (ulFileOffset == FC_INVALID) {
809f5736e95SDavid du Colombier 		return FC_INVALID;
810f5736e95SDavid du Colombier 	}
811f5736e95SDavid du Colombier 
812f5736e95SDavid du Colombier 	ulSeq = 0;
813f5736e95SDavid du Colombier 	for (pCurr = pTextAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
814f5736e95SDavid du Colombier 		if (ulFileOffset >= pCurr->tInfo.ulFileOffset &&
815f5736e95SDavid du Colombier 		    ulFileOffset < pCurr->tInfo.ulFileOffset +
816f5736e95SDavid du Colombier 		     pCurr->tInfo.ulLength) {
817f5736e95SDavid du Colombier 			/* The file offset is within the current textblock */
818f5736e95SDavid du Colombier 			return ulSeq + ulFileOffset - pCurr->tInfo.ulFileOffset;
819f5736e95SDavid du Colombier 		}
820f5736e95SDavid du Colombier 		ulSeq += pCurr->tInfo.ulLength;
821f5736e95SDavid du Colombier 	}
822f5736e95SDavid du Colombier 	return FC_INVALID;
823f5736e95SDavid du Colombier } /* end of ulGetSeqNumber */
824