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