xref: /plan9/sys/src/cmd/aux/antiword/notes.c (revision 25b329d522281a8cdd35da0dcc08c3fc621059a9)
1f5736e95SDavid du Colombier /*
2f5736e95SDavid du Colombier  * notes.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  * Functions to tell the difference between footnotes and endnotes
7f5736e95SDavid du Colombier  */
8f5736e95SDavid du Colombier 
9f5736e95SDavid du Colombier #include "antiword.h"
10f5736e95SDavid du Colombier 
11*25b329d5SDavid du Colombier /*
12*25b329d5SDavid du Colombier  * Private structures to hide the way the information
13*25b329d5SDavid du Colombier  * is stored from the rest of the program
14*25b329d5SDavid du Colombier  */
15*25b329d5SDavid du Colombier typedef struct footnote_local_tag {
16*25b329d5SDavid du Colombier         footnote_block_type	tInfo;
17*25b329d5SDavid du Colombier         ULONG			ulCharPosStart;
18*25b329d5SDavid du Colombier         ULONG			ulCharPosNext;
19*25b329d5SDavid du Colombier         BOOL			bUseful;
20*25b329d5SDavid du Colombier } footnote_local_type;
21*25b329d5SDavid du Colombier 
22*25b329d5SDavid du Colombier /* Variables needed to write the Footnote and Endnote information */
23f5736e95SDavid du Colombier static ULONG	*aulFootnoteList = NULL;
24f5736e95SDavid du Colombier static size_t	tFootnoteListLength = 0;
25f5736e95SDavid du Colombier static ULONG	*aulEndnoteList = NULL;
26f5736e95SDavid du Colombier static size_t	tEndnoteListLength = 0;
27*25b329d5SDavid du Colombier /* Variables needed to write the Footnote Text */
28*25b329d5SDavid du Colombier static footnote_local_type	*pFootnoteText = NULL;
29*25b329d5SDavid du Colombier static size_t			tFootnoteTextLength = 0;
30f5736e95SDavid du Colombier 
31f5736e95SDavid du Colombier 
32f5736e95SDavid du Colombier /*
33f5736e95SDavid du Colombier  * Destroy the lists with footnote and endnote information
34f5736e95SDavid du Colombier  */
35f5736e95SDavid du Colombier void
vDestroyNotesInfoLists(void)36f5736e95SDavid du Colombier vDestroyNotesInfoLists(void)
37f5736e95SDavid du Colombier {
38*25b329d5SDavid du Colombier 	footnote_local_type	*pRecord;
39*25b329d5SDavid du Colombier 	size_t			tFootnote;
40*25b329d5SDavid du Colombier 
41*25b329d5SDavid du Colombier 	TRACE_MSG("vDestroyNotesInfoLists");
42f5736e95SDavid du Colombier 
43f5736e95SDavid du Colombier 	/* Free the lists and reset all control variables */
44f5736e95SDavid du Colombier 	aulEndnoteList = xfree(aulEndnoteList);
45f5736e95SDavid du Colombier 	aulFootnoteList = xfree(aulFootnoteList);
46f5736e95SDavid du Colombier 	tEndnoteListLength = 0;
47f5736e95SDavid du Colombier 	tFootnoteListLength = 0;
48*25b329d5SDavid du Colombier 	for (tFootnote = 0; tFootnote < tFootnoteTextLength; tFootnote++) {
49*25b329d5SDavid du Colombier 		pRecord = pFootnoteText + tFootnote;
50*25b329d5SDavid du Colombier 		pRecord->tInfo.szText = xfree(pRecord->tInfo.szText);
51*25b329d5SDavid du Colombier 	}
52*25b329d5SDavid du Colombier 	pFootnoteText = xfree(pFootnoteText);
53*25b329d5SDavid du Colombier 	tFootnoteTextLength = 0;
54f5736e95SDavid du Colombier } /* end of vDestroyNotesInfoLists */
55f5736e95SDavid du Colombier 
56f5736e95SDavid du Colombier /*
57*25b329d5SDavid du Colombier  * Build the list with footnote information for Word for DOS files
58*25b329d5SDavid du Colombier  */
59*25b329d5SDavid du Colombier static void
vGet0FootnotesInfoAndText(FILE * pFile,const UCHAR * aucHeader)60*25b329d5SDavid du Colombier vGet0FootnotesInfoAndText(FILE *pFile, const UCHAR *aucHeader)
61*25b329d5SDavid du Colombier {
62*25b329d5SDavid du Colombier 	footnote_local_type	*pCurr;
63*25b329d5SDavid du Colombier 	UCHAR	*aucBuffer;
64*25b329d5SDavid du Colombier 	ULONG	ulFileOffset, ulBeginOfText, ulOffset, ulBeginFootnoteInfo;
65*25b329d5SDavid du Colombier 	ULONG	ulCharPos, ulBeginNextBlock;
66*25b329d5SDavid du Colombier 	size_t	tFootnotes, tFootnoteInfoLen;
67*25b329d5SDavid du Colombier 	size_t	tIndex;
68*25b329d5SDavid du Colombier 	UCHAR   aucTmp[2];
69*25b329d5SDavid du Colombier 
70*25b329d5SDavid du Colombier 	TRACE_MSG("vGet0FootnotesInfoAndText");
71*25b329d5SDavid du Colombier 
72*25b329d5SDavid du Colombier 	fail(pFile == NULL || aucHeader == NULL);
73*25b329d5SDavid du Colombier 
74*25b329d5SDavid du Colombier 	ulBeginOfText = 128;
75*25b329d5SDavid du Colombier 	NO_DBG_HEX(ulBeginOfText);
76*25b329d5SDavid du Colombier 	ulBeginFootnoteInfo =  128 * (ULONG)usGetWord(0x14, aucHeader);
77*25b329d5SDavid du Colombier 	DBG_HEX(ulBeginFootnoteInfo);
78*25b329d5SDavid du Colombier 	ulBeginNextBlock = 128 * (ULONG)usGetWord(0x16, aucHeader);
79*25b329d5SDavid du Colombier 	DBG_HEX(ulBeginNextBlock);
80*25b329d5SDavid du Colombier 
81*25b329d5SDavid du Colombier 	if (ulBeginFootnoteInfo == ulBeginNextBlock) {
82*25b329d5SDavid du Colombier 		DBG_MSG("No Footnotes in this document");
83*25b329d5SDavid du Colombier 		return;
84*25b329d5SDavid du Colombier 	}
85*25b329d5SDavid du Colombier 
86*25b329d5SDavid du Colombier 	/* Read the the number of footnotes + 1 */
87*25b329d5SDavid du Colombier 	if (!bReadBytes(aucTmp, 2, ulBeginFootnoteInfo, pFile)) {
88*25b329d5SDavid du Colombier 		return;
89*25b329d5SDavid du Colombier 	}
90*25b329d5SDavid du Colombier 	tFootnotes = (size_t)usGetWord(0, aucTmp);
91*25b329d5SDavid du Colombier 	if (tFootnotes < 2) {
92*25b329d5SDavid du Colombier 		DBG_MSG("No Footnotes in this document (2)");
93*25b329d5SDavid du Colombier 	}
94*25b329d5SDavid du Colombier 	DBG_DEC(tFootnotes);
95*25b329d5SDavid du Colombier 	tFootnoteInfoLen =  8 * tFootnotes;
96*25b329d5SDavid du Colombier 
97*25b329d5SDavid du Colombier 	aucBuffer = xmalloc(tFootnoteInfoLen);
98*25b329d5SDavid du Colombier 	if (!bReadBytes(aucBuffer,
99*25b329d5SDavid du Colombier 			tFootnoteInfoLen, ulBeginFootnoteInfo + 4, pFile)) {
100*25b329d5SDavid du Colombier 		aucBuffer = xfree(aucBuffer);
101*25b329d5SDavid du Colombier 		return;
102*25b329d5SDavid du Colombier 	}
103*25b329d5SDavid du Colombier 	DBG_PRINT_BLOCK(aucBuffer, tFootnoteInfoLen);
104*25b329d5SDavid du Colombier 
105*25b329d5SDavid du Colombier 	/* Get footnote information */
106*25b329d5SDavid du Colombier 	fail(tFootnoteListLength != 0);
107*25b329d5SDavid du Colombier 	tFootnoteListLength = tFootnotes - 1;
108*25b329d5SDavid du Colombier 	fail(tFootnoteListLength == 0);
109*25b329d5SDavid du Colombier 
110*25b329d5SDavid du Colombier 	fail(aulFootnoteList != NULL);
111*25b329d5SDavid du Colombier 	aulFootnoteList = xcalloc(tFootnoteListLength, sizeof(ULONG));
112*25b329d5SDavid du Colombier 
113*25b329d5SDavid du Colombier 	for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
114*25b329d5SDavid du Colombier 		ulOffset = ulGetLong(tIndex * 8, aucBuffer);
115*25b329d5SDavid du Colombier 		DBG_HEX(ulOffset);
116*25b329d5SDavid du Colombier 		ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
117*25b329d5SDavid du Colombier 		DBG_HEX(ulFileOffset);
118*25b329d5SDavid du Colombier 		aulFootnoteList[tIndex] = ulFileOffset;
119*25b329d5SDavid du Colombier 	}
120*25b329d5SDavid du Colombier 
121*25b329d5SDavid du Colombier 	/* Get footnote text */
122*25b329d5SDavid du Colombier 	fail(tFootnoteTextLength != 0);
123*25b329d5SDavid du Colombier 	tFootnoteTextLength = tFootnotes - 1;
124*25b329d5SDavid du Colombier 	fail(tFootnoteTextLength == 0);
125*25b329d5SDavid du Colombier 
126*25b329d5SDavid du Colombier 	fail(pFootnoteText != NULL);
127*25b329d5SDavid du Colombier 	pFootnoteText = xcalloc(tFootnoteTextLength,
128*25b329d5SDavid du Colombier 				sizeof(footnote_local_type));
129*25b329d5SDavid du Colombier 
130*25b329d5SDavid du Colombier 	for (tIndex = 0; tIndex < tFootnoteTextLength; tIndex++) {
131*25b329d5SDavid du Colombier 		pCurr = pFootnoteText + tIndex;
132*25b329d5SDavid du Colombier 		pCurr->tInfo.szText = NULL;
133*25b329d5SDavid du Colombier 		ulOffset = ulGetLong(tIndex * 8 + 4, aucBuffer);
134*25b329d5SDavid du Colombier 		DBG_HEX(ulOffset);
135*25b329d5SDavid du Colombier 		ulCharPos = ulBeginOfText + ulOffset;
136*25b329d5SDavid du Colombier 		DBG_HEX(ulCharPos);
137*25b329d5SDavid du Colombier 		DBG_HEX(ulCharPos2FileOffset(ulCharPos));
138*25b329d5SDavid du Colombier 		pCurr->ulCharPosStart = ulCharPos;
139*25b329d5SDavid du Colombier 		ulOffset = ulGetLong((tIndex + 1) * 8 + 4, aucBuffer);
140*25b329d5SDavid du Colombier 		DBG_HEX(ulOffset);
141*25b329d5SDavid du Colombier 		ulCharPos = ulBeginOfText + ulOffset;
142*25b329d5SDavid du Colombier 		DBG_HEX(ulCharPos);
143*25b329d5SDavid du Colombier 		DBG_HEX(ulCharPos2FileOffset(ulCharPos));
144*25b329d5SDavid du Colombier 		pCurr->ulCharPosNext = ulCharPos;
145*25b329d5SDavid du Colombier 		pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
146*25b329d5SDavid du Colombier 	}
147*25b329d5SDavid du Colombier 	aucBuffer = xfree(aucBuffer);
148*25b329d5SDavid du Colombier } /* end of vGet0FootnotesInfoAndText */
149*25b329d5SDavid du Colombier 
150*25b329d5SDavid du Colombier /*
151*25b329d5SDavid du Colombier  * Build the lists note information for Word for DOS files
152*25b329d5SDavid du Colombier  */
153*25b329d5SDavid du Colombier static void
vGet0NotesInfo(FILE * pFile,const UCHAR * aucHeader)154*25b329d5SDavid du Colombier vGet0NotesInfo(FILE *pFile, const UCHAR *aucHeader)
155*25b329d5SDavid du Colombier {
156*25b329d5SDavid du Colombier 	TRACE_MSG("vGet0NotesInfo");
157*25b329d5SDavid du Colombier 
158*25b329d5SDavid du Colombier 	vGet0FootnotesInfoAndText(pFile, aucHeader);
159*25b329d5SDavid du Colombier 	/* There are no endnotes in a Word for DOS file */
160*25b329d5SDavid du Colombier } /* end of vGet0NotesInfo */
161*25b329d5SDavid du Colombier 
162*25b329d5SDavid du Colombier /*
163*25b329d5SDavid du Colombier  * Build the list with footnote information for WinWord 1/2 files
164*25b329d5SDavid du Colombier  */
165*25b329d5SDavid du Colombier static void
vGet2FootnotesInfo(FILE * pFile,const UCHAR * aucHeader)166*25b329d5SDavid du Colombier vGet2FootnotesInfo(FILE *pFile, const UCHAR *aucHeader)
167*25b329d5SDavid du Colombier {
168*25b329d5SDavid du Colombier 	UCHAR	*aucBuffer;
169*25b329d5SDavid du Colombier 	ULONG	ulFileOffset, ulBeginOfText, ulOffset, ulBeginFootnoteInfo;
170*25b329d5SDavid du Colombier 	size_t	tFootnoteInfoLen;
171*25b329d5SDavid du Colombier 	size_t	tIndex;
172*25b329d5SDavid du Colombier 
173*25b329d5SDavid du Colombier 	TRACE_MSG("vGet2FootnotesInfo");
174*25b329d5SDavid du Colombier 
175*25b329d5SDavid du Colombier 	fail(pFile == NULL || aucHeader == NULL);
176*25b329d5SDavid du Colombier 
177*25b329d5SDavid du Colombier 	ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
178*25b329d5SDavid du Colombier 	NO_DBG_HEX(ulBeginOfText);
179*25b329d5SDavid du Colombier 	ulBeginFootnoteInfo = ulGetLong(0x64, aucHeader); /* fcPlcffndRef */
180*25b329d5SDavid du Colombier 	NO_DBG_HEX(ulBeginFootnoteInfo);
181*25b329d5SDavid du Colombier 	tFootnoteInfoLen = (size_t)usGetWord(0x68, aucHeader); /* cbPlcffndRef */
182*25b329d5SDavid du Colombier 	NO_DBG_DEC(tFootnoteInfoLen);
183*25b329d5SDavid du Colombier 
184*25b329d5SDavid du Colombier 	if (tFootnoteInfoLen < 10) {
185*25b329d5SDavid du Colombier 		DBG_MSG("No Footnotes in this document");
186*25b329d5SDavid du Colombier 		return;
187*25b329d5SDavid du Colombier 	}
188*25b329d5SDavid du Colombier 
189*25b329d5SDavid du Colombier 	aucBuffer = xmalloc(tFootnoteInfoLen);
190*25b329d5SDavid du Colombier 	if (!bReadBytes(aucBuffer,
191*25b329d5SDavid du Colombier 			tFootnoteInfoLen, ulBeginFootnoteInfo, pFile)) {
192*25b329d5SDavid du Colombier 		aucBuffer = xfree(aucBuffer);
193*25b329d5SDavid du Colombier 		return;
194*25b329d5SDavid du Colombier 	}
195*25b329d5SDavid du Colombier 	NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteInfoLen);
196*25b329d5SDavid du Colombier 
197*25b329d5SDavid du Colombier 	fail(tFootnoteListLength != 0);
198*25b329d5SDavid du Colombier 	tFootnoteListLength = (tFootnoteInfoLen - 4) / 6;
199*25b329d5SDavid du Colombier 	fail(tFootnoteListLength == 0);
200*25b329d5SDavid du Colombier 
201*25b329d5SDavid du Colombier 	fail(aulFootnoteList != NULL);
202*25b329d5SDavid du Colombier 	aulFootnoteList = xcalloc(tFootnoteListLength, sizeof(ULONG));
203*25b329d5SDavid du Colombier 
204*25b329d5SDavid du Colombier 	for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
205*25b329d5SDavid du Colombier 		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
206*25b329d5SDavid du Colombier 		NO_DBG_HEX(ulOffset);
207*25b329d5SDavid du Colombier 		ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
208*25b329d5SDavid du Colombier 		NO_DBG_HEX(ulFileOffset);
209*25b329d5SDavid du Colombier 		aulFootnoteList[tIndex] = ulFileOffset;
210*25b329d5SDavid du Colombier 	}
211*25b329d5SDavid du Colombier 	aucBuffer = xfree(aucBuffer);
212*25b329d5SDavid du Colombier } /* end of vGet2FootnotesInfo */
213*25b329d5SDavid du Colombier 
214*25b329d5SDavid du Colombier /*
215*25b329d5SDavid du Colombier  * Build the list with footnote text information for WinWord 1/2 files
216*25b329d5SDavid du Colombier  */
217*25b329d5SDavid du Colombier static void
vGet2FootnotesText(FILE * pFile,const UCHAR * aucHeader)218*25b329d5SDavid du Colombier vGet2FootnotesText(FILE *pFile, const UCHAR *aucHeader)
219*25b329d5SDavid du Colombier {
220*25b329d5SDavid du Colombier 	footnote_local_type	*pCurr;
221*25b329d5SDavid du Colombier 	UCHAR	*aucBuffer;
222*25b329d5SDavid du Colombier 	ULONG	ulCharPos, ulBeginOfFootnotes, ulOffset, ulBeginFootnoteText;
223*25b329d5SDavid du Colombier 	size_t	tFootnoteTextLen;
224*25b329d5SDavid du Colombier 	size_t	tIndex;
225*25b329d5SDavid du Colombier 
226*25b329d5SDavid du Colombier 	TRACE_MSG("vGet2FootnotesText");
227*25b329d5SDavid du Colombier 
228*25b329d5SDavid du Colombier 	fail(pFile == NULL || aucHeader == NULL);
229*25b329d5SDavid du Colombier 
230*25b329d5SDavid du Colombier 	ulBeginOfFootnotes = ulGetLong(0x18, aucHeader); /* fcMin */
231*25b329d5SDavid du Colombier 	ulBeginOfFootnotes += ulGetLong(0x34, aucHeader); /* ccpText */
232*25b329d5SDavid du Colombier 	NO_DBG_HEX(ulBeginOfFootnotes);
233*25b329d5SDavid du Colombier 
234*25b329d5SDavid du Colombier 	ulBeginFootnoteText = ulGetLong(0x6a, aucHeader); /* fcPlcffndTxt */
235*25b329d5SDavid du Colombier 	NO_DBG_HEX(ulBeginFootnoteText);
236*25b329d5SDavid du Colombier 	tFootnoteTextLen =
237*25b329d5SDavid du Colombier 		(size_t)usGetWord(0x6e, aucHeader); /* cbPlcffndTxt */
238*25b329d5SDavid du Colombier 	NO_DBG_DEC(tFootnoteTextLen);
239*25b329d5SDavid du Colombier 
240*25b329d5SDavid du Colombier 	if (tFootnoteTextLen < 12) {
241*25b329d5SDavid du Colombier 		DBG_MSG("No Footnote text in this document");
242*25b329d5SDavid du Colombier 		return;
243*25b329d5SDavid du Colombier 	}
244*25b329d5SDavid du Colombier 
245*25b329d5SDavid du Colombier 	aucBuffer = xmalloc(tFootnoteTextLen);
246*25b329d5SDavid du Colombier 	if (!bReadBytes(aucBuffer,
247*25b329d5SDavid du Colombier 			tFootnoteTextLen, ulBeginFootnoteText, pFile)) {
248*25b329d5SDavid du Colombier 		aucBuffer = xfree(aucBuffer);
249*25b329d5SDavid du Colombier 		return;
250*25b329d5SDavid du Colombier 	}
251*25b329d5SDavid du Colombier 	NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteTextLen);
252*25b329d5SDavid du Colombier 
253*25b329d5SDavid du Colombier 	fail(tFootnoteTextLength != 0);
254*25b329d5SDavid du Colombier 	tFootnoteTextLength = tFootnoteTextLen / 4 - 2;
255*25b329d5SDavid du Colombier 	fail(tFootnoteTextLength == 0);
256*25b329d5SDavid du Colombier 
257*25b329d5SDavid du Colombier 	fail(pFootnoteText != NULL);
258*25b329d5SDavid du Colombier 	pFootnoteText = xcalloc(tFootnoteTextLength,
259*25b329d5SDavid du Colombier 				sizeof(footnote_local_type));
260*25b329d5SDavid du Colombier 
261*25b329d5SDavid du Colombier 	for (tIndex = 0; tIndex < tFootnoteTextLength; tIndex++) {
262*25b329d5SDavid du Colombier 		pCurr = pFootnoteText + tIndex;
263*25b329d5SDavid du Colombier 		pCurr->tInfo.szText = NULL;
264*25b329d5SDavid du Colombier 		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
265*25b329d5SDavid du Colombier 		NO_DBG_HEX(ulOffset);
266*25b329d5SDavid du Colombier 		ulCharPos = ulBeginOfFootnotes + ulOffset;
267*25b329d5SDavid du Colombier 		NO_DBG_HEX(ulCharPos);
268*25b329d5SDavid du Colombier 		NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
269*25b329d5SDavid du Colombier 		pCurr->ulCharPosStart = ulCharPos;
270*25b329d5SDavid du Colombier 		ulOffset = ulGetLong(tIndex * 4 + 4, aucBuffer);
271*25b329d5SDavid du Colombier 		NO_DBG_HEX(ulOffset);
272*25b329d5SDavid du Colombier 		ulCharPos = ulBeginOfFootnotes + ulOffset;
273*25b329d5SDavid du Colombier 		NO_DBG_HEX(ulCharPos);
274*25b329d5SDavid du Colombier 		NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
275*25b329d5SDavid du Colombier 		pCurr->ulCharPosNext = ulCharPos;
276*25b329d5SDavid du Colombier 		pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
277*25b329d5SDavid du Colombier 	}
278*25b329d5SDavid du Colombier 	aucBuffer = xfree(aucBuffer);
279*25b329d5SDavid du Colombier } /* end of vGet2FootnotesText */
280*25b329d5SDavid du Colombier 
281*25b329d5SDavid du Colombier /*
282*25b329d5SDavid du Colombier  * Build the lists note information for WinWord 1/2 files
283*25b329d5SDavid du Colombier  */
284*25b329d5SDavid du Colombier static void
vGet2NotesInfo(FILE * pFile,const UCHAR * aucHeader)285*25b329d5SDavid du Colombier vGet2NotesInfo(FILE *pFile, const UCHAR *aucHeader)
286*25b329d5SDavid du Colombier {
287*25b329d5SDavid du Colombier 	TRACE_MSG("vGet2NotesInfo");
288*25b329d5SDavid du Colombier 
289*25b329d5SDavid du Colombier 	vGet2FootnotesInfo(pFile, aucHeader);
290*25b329d5SDavid du Colombier 	vGet2FootnotesText(pFile, aucHeader);
291*25b329d5SDavid du Colombier 	/* There are no endnotes in a WinWord 1/2 file */
292*25b329d5SDavid du Colombier } /* end of vGet2NotesInfo */
293*25b329d5SDavid du Colombier 
294*25b329d5SDavid du Colombier /*
295f5736e95SDavid du Colombier  * Build the list with footnote information for Word 6/7 files
296f5736e95SDavid du Colombier  */
297f5736e95SDavid du Colombier static void
vGet6FootnotesInfo(FILE * pFile,ULONG ulStartBlock,const ULONG * aulBBD,size_t tBBDLen,const UCHAR * aucHeader)298f5736e95SDavid du Colombier vGet6FootnotesInfo(FILE *pFile, ULONG ulStartBlock,
299f5736e95SDavid du Colombier 	const ULONG *aulBBD, size_t tBBDLen,
300f5736e95SDavid du Colombier 	const UCHAR *aucHeader)
301f5736e95SDavid du Colombier {
302f5736e95SDavid du Colombier 	UCHAR	*aucBuffer;
303f5736e95SDavid du Colombier 	ULONG	ulFileOffset, ulBeginOfText, ulOffset, ulBeginFootnoteInfo;
304f5736e95SDavid du Colombier 	size_t	tFootnoteInfoLen;
305*25b329d5SDavid du Colombier 	size_t	tIndex;
306*25b329d5SDavid du Colombier 
307*25b329d5SDavid du Colombier 	TRACE_MSG("vGet6FootnotesInfo");
308f5736e95SDavid du Colombier 
309f5736e95SDavid du Colombier 	fail(pFile == NULL || aucHeader == NULL);
310f5736e95SDavid du Colombier 	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
311f5736e95SDavid du Colombier 	fail(aulBBD == NULL);
312f5736e95SDavid du Colombier 
313*25b329d5SDavid du Colombier 	ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
314f5736e95SDavid du Colombier 	NO_DBG_HEX(ulBeginOfText);
315*25b329d5SDavid du Colombier 	ulBeginFootnoteInfo = ulGetLong(0x68, aucHeader); /* fcPlcffndRef */
316f5736e95SDavid du Colombier 	NO_DBG_HEX(ulBeginFootnoteInfo);
317*25b329d5SDavid du Colombier 	tFootnoteInfoLen =
318*25b329d5SDavid du Colombier 		(size_t)ulGetLong(0x6c, aucHeader); /* lcbPlcffndRef */
319f5736e95SDavid du Colombier 	NO_DBG_DEC(tFootnoteInfoLen);
320f5736e95SDavid du Colombier 
321f5736e95SDavid du Colombier 	if (tFootnoteInfoLen < 10) {
322f5736e95SDavid du Colombier 		DBG_MSG("No Footnotes in this document");
323f5736e95SDavid du Colombier 		return;
324f5736e95SDavid du Colombier 	}
325f5736e95SDavid du Colombier 
326f5736e95SDavid du Colombier 	aucBuffer = xmalloc(tFootnoteInfoLen);
327f5736e95SDavid du Colombier 	if (!bReadBuffer(pFile, ulStartBlock,
328f5736e95SDavid du Colombier 			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
329f5736e95SDavid du Colombier 			aucBuffer, ulBeginFootnoteInfo, tFootnoteInfoLen)) {
330f5736e95SDavid du Colombier 		aucBuffer = xfree(aucBuffer);
331f5736e95SDavid du Colombier 		return;
332f5736e95SDavid du Colombier 	}
333f5736e95SDavid du Colombier 	NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteInfoLen);
334f5736e95SDavid du Colombier 
335f5736e95SDavid du Colombier 	fail(tFootnoteListLength != 0);
336f5736e95SDavid du Colombier 	tFootnoteListLength = (tFootnoteInfoLen - 4) / 6;
337f5736e95SDavid du Colombier 	fail(tFootnoteListLength == 0);
338f5736e95SDavid du Colombier 
339f5736e95SDavid du Colombier 	fail(aulFootnoteList != NULL);
340f5736e95SDavid du Colombier 	aulFootnoteList = xcalloc(tFootnoteListLength, sizeof(ULONG));
341f5736e95SDavid du Colombier 
342*25b329d5SDavid du Colombier 	for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
343*25b329d5SDavid du Colombier 		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
344f5736e95SDavid du Colombier 		NO_DBG_HEX(ulOffset);
345f5736e95SDavid du Colombier 		ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
346f5736e95SDavid du Colombier 		NO_DBG_HEX(ulFileOffset);
347*25b329d5SDavid du Colombier 		aulFootnoteList[tIndex] = ulFileOffset;
348f5736e95SDavid du Colombier 	}
349f5736e95SDavid du Colombier 	aucBuffer = xfree(aucBuffer);
350f5736e95SDavid du Colombier } /* end of vGet6FootnotesInfo */
351f5736e95SDavid du Colombier 
352f5736e95SDavid du Colombier /*
353*25b329d5SDavid du Colombier  * Build the list with footnote text information for Word 6/7 files
354*25b329d5SDavid du Colombier  */
355*25b329d5SDavid du Colombier static void
vGet6FootnotesText(FILE * pFile,ULONG ulStartBlock,const ULONG * aulBBD,size_t tBBDLen,const UCHAR * aucHeader)356*25b329d5SDavid du Colombier vGet6FootnotesText(FILE *pFile, ULONG ulStartBlock,
357*25b329d5SDavid du Colombier 	const ULONG *aulBBD, size_t tBBDLen,
358*25b329d5SDavid du Colombier 	const UCHAR *aucHeader)
359*25b329d5SDavid du Colombier {
360*25b329d5SDavid du Colombier 	footnote_local_type	*pCurr;
361*25b329d5SDavid du Colombier 	UCHAR	*aucBuffer;
362*25b329d5SDavid du Colombier 	ULONG	ulCharPos, ulBeginOfFootnotes, ulOffset, ulBeginFootnoteText;
363*25b329d5SDavid du Colombier 	size_t	tFootnoteTextLen;
364*25b329d5SDavid du Colombier 	size_t	tIndex;
365*25b329d5SDavid du Colombier 
366*25b329d5SDavid du Colombier 	TRACE_MSG("vGet6FootnotesText");
367*25b329d5SDavid du Colombier 
368*25b329d5SDavid du Colombier 	fail(pFile == NULL || aucHeader == NULL);
369*25b329d5SDavid du Colombier 	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
370*25b329d5SDavid du Colombier 	fail(aulBBD == NULL);
371*25b329d5SDavid du Colombier 
372*25b329d5SDavid du Colombier 	ulBeginOfFootnotes = ulGetLong(0x18, aucHeader); /* fcMin */
373*25b329d5SDavid du Colombier 	ulBeginOfFootnotes += ulGetLong(0x34, aucHeader); /* ccpText */
374*25b329d5SDavid du Colombier 	NO_DBG_HEX(ulBeginOfFootnotes);
375*25b329d5SDavid du Colombier 
376*25b329d5SDavid du Colombier 	ulBeginFootnoteText = ulGetLong(0x70, aucHeader); /* fcPlcffndTxt */
377*25b329d5SDavid du Colombier 	NO_DBG_HEX(ulBeginFootnoteText);
378*25b329d5SDavid du Colombier 	tFootnoteTextLen =
379*25b329d5SDavid du Colombier 		(size_t)ulGetLong(0x74, aucHeader); /* lcbPlcffndTxt */
380*25b329d5SDavid du Colombier 	NO_DBG_DEC(tFootnoteTextLen);
381*25b329d5SDavid du Colombier 
382*25b329d5SDavid du Colombier 	if (tFootnoteTextLen < 12) {
383*25b329d5SDavid du Colombier 		DBG_MSG("No Footnote text in this document");
384*25b329d5SDavid du Colombier 		return;
385*25b329d5SDavid du Colombier 	}
386*25b329d5SDavid du Colombier 
387*25b329d5SDavid du Colombier 	aucBuffer = xmalloc(tFootnoteTextLen);
388*25b329d5SDavid du Colombier 	if (!bReadBuffer(pFile, ulStartBlock,
389*25b329d5SDavid du Colombier 			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
390*25b329d5SDavid du Colombier 			aucBuffer, ulBeginFootnoteText, tFootnoteTextLen)) {
391*25b329d5SDavid du Colombier 		aucBuffer = xfree(aucBuffer);
392*25b329d5SDavid du Colombier 		return;
393*25b329d5SDavid du Colombier 	}
394*25b329d5SDavid du Colombier 	NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteTextLen);
395*25b329d5SDavid du Colombier 
396*25b329d5SDavid du Colombier 	fail(tFootnoteTextLength != 0);
397*25b329d5SDavid du Colombier 	tFootnoteTextLength = tFootnoteTextLen / 4 - 2;
398*25b329d5SDavid du Colombier 	fail(tFootnoteTextLength == 0);
399*25b329d5SDavid du Colombier 
400*25b329d5SDavid du Colombier 	fail(pFootnoteText != NULL);
401*25b329d5SDavid du Colombier 	pFootnoteText = xcalloc(tFootnoteTextLength,
402*25b329d5SDavid du Colombier 				sizeof(footnote_local_type));
403*25b329d5SDavid du Colombier 
404*25b329d5SDavid du Colombier 	for (tIndex = 0; tIndex < tFootnoteTextLength; tIndex++) {
405*25b329d5SDavid du Colombier 		pCurr = pFootnoteText + tIndex;
406*25b329d5SDavid du Colombier 		pCurr->tInfo.szText = NULL;
407*25b329d5SDavid du Colombier 		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
408*25b329d5SDavid du Colombier 		NO_DBG_HEX(ulOffset);
409*25b329d5SDavid du Colombier 		ulCharPos = ulBeginOfFootnotes + ulOffset;
410*25b329d5SDavid du Colombier 		NO_DBG_HEX(ulCharPos);
411*25b329d5SDavid du Colombier 		NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
412*25b329d5SDavid du Colombier 		pCurr->ulCharPosStart = ulCharPos;
413*25b329d5SDavid du Colombier 		ulOffset = ulGetLong(tIndex * 4 + 4, aucBuffer);
414*25b329d5SDavid du Colombier 		NO_DBG_HEX(ulOffset);
415*25b329d5SDavid du Colombier 		ulCharPos = ulBeginOfFootnotes + ulOffset;
416*25b329d5SDavid du Colombier 		NO_DBG_HEX(ulCharPos);
417*25b329d5SDavid du Colombier 		NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
418*25b329d5SDavid du Colombier 		pCurr->ulCharPosNext = ulCharPos;
419*25b329d5SDavid du Colombier 		pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
420*25b329d5SDavid du Colombier 	}
421*25b329d5SDavid du Colombier 	aucBuffer = xfree(aucBuffer);
422*25b329d5SDavid du Colombier } /* end of vGet6FootnotesText */
423*25b329d5SDavid du Colombier 
424*25b329d5SDavid du Colombier /*
425f5736e95SDavid du Colombier  * Build the list with endnote information for Word 6/7 files
426f5736e95SDavid du Colombier  */
427f5736e95SDavid du Colombier static void
vGet6EndnotesInfo(FILE * pFile,ULONG ulStartBlock,const ULONG * aulBBD,size_t tBBDLen,const UCHAR * aucHeader)428f5736e95SDavid du Colombier vGet6EndnotesInfo(FILE *pFile, ULONG ulStartBlock,
429f5736e95SDavid du Colombier 	const ULONG *aulBBD, size_t tBBDLen,
430f5736e95SDavid du Colombier 	const UCHAR *aucHeader)
431f5736e95SDavid du Colombier {
432f5736e95SDavid du Colombier 	UCHAR	*aucBuffer;
433f5736e95SDavid du Colombier 	ULONG	ulFileOffset, ulBeginOfText, ulOffset, ulBeginEndnoteInfo;
434f5736e95SDavid du Colombier 	size_t	tEndnoteInfoLen;
435*25b329d5SDavid du Colombier 	size_t	tIndex;
436*25b329d5SDavid du Colombier 
437*25b329d5SDavid du Colombier 	TRACE_MSG("vGet6EndnotesInfo");
438f5736e95SDavid du Colombier 
439f5736e95SDavid du Colombier 	fail(pFile == NULL || aucHeader == NULL);
440f5736e95SDavid du Colombier 	fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
441f5736e95SDavid du Colombier 	fail(aulBBD == NULL);
442f5736e95SDavid du Colombier 
443*25b329d5SDavid du Colombier 	ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
444f5736e95SDavid du Colombier 	NO_DBG_HEX(ulBeginOfText);
445*25b329d5SDavid du Colombier 	ulBeginEndnoteInfo = ulGetLong(0x1d2, aucHeader); /* fcPlcfendRef */
446f5736e95SDavid du Colombier 	NO_DBG_HEX(ulBeginEndnoteInfo);
447*25b329d5SDavid du Colombier 	tEndnoteInfoLen =
448*25b329d5SDavid du Colombier 		(size_t)ulGetLong(0x1d6, aucHeader); /* lcbPlcfendRef */
449f5736e95SDavid du Colombier 	NO_DBG_DEC(tEndnoteInfoLen);
450f5736e95SDavid du Colombier 
451f5736e95SDavid du Colombier 	if (tEndnoteInfoLen < 10) {
452f5736e95SDavid du Colombier 		DBG_MSG("No Endnotes in this document");
453f5736e95SDavid du Colombier 		return;
454f5736e95SDavid du Colombier 	}
455f5736e95SDavid du Colombier 
456f5736e95SDavid du Colombier 	aucBuffer = xmalloc(tEndnoteInfoLen);
457f5736e95SDavid du Colombier 	if (!bReadBuffer(pFile, ulStartBlock,
458f5736e95SDavid du Colombier 			aulBBD, tBBDLen, BIG_BLOCK_SIZE,
459f5736e95SDavid du Colombier 			aucBuffer, ulBeginEndnoteInfo, tEndnoteInfoLen)) {
460f5736e95SDavid du Colombier 		aucBuffer = xfree(aucBuffer);
461f5736e95SDavid du Colombier 		return;
462f5736e95SDavid du Colombier 	}
463f5736e95SDavid du Colombier 	NO_DBG_PRINT_BLOCK(aucBuffer, tEndnoteInfoLen);
464f5736e95SDavid du Colombier 
465f5736e95SDavid du Colombier 	fail(tEndnoteListLength != 0);
466f5736e95SDavid du Colombier 	tEndnoteListLength = (tEndnoteInfoLen - 4) / 6;
467f5736e95SDavid du Colombier 	fail(tEndnoteListLength == 0);
468f5736e95SDavid du Colombier 
469f5736e95SDavid du Colombier 	fail(aulEndnoteList != NULL);
470f5736e95SDavid du Colombier 	aulEndnoteList = xcalloc(tEndnoteListLength, sizeof(ULONG));
471f5736e95SDavid du Colombier 
472*25b329d5SDavid du Colombier 	for (tIndex = 0; tIndex < tEndnoteListLength; tIndex++) {
473*25b329d5SDavid du Colombier 		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
474f5736e95SDavid du Colombier 		NO_DBG_HEX(ulOffset);
475f5736e95SDavid du Colombier 		ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
476f5736e95SDavid du Colombier 		NO_DBG_HEX(ulFileOffset);
477*25b329d5SDavid du Colombier 		aulEndnoteList[tIndex] = ulFileOffset;
478f5736e95SDavid du Colombier 	}
479f5736e95SDavid du Colombier 	aucBuffer = xfree(aucBuffer);
480f5736e95SDavid du Colombier } /* end of vGet6EndnotesInfo */
481f5736e95SDavid du Colombier 
482f5736e95SDavid du Colombier /*
483f5736e95SDavid du Colombier  * Build the lists note information for Word 6/7 files
484f5736e95SDavid du Colombier  */
485f5736e95SDavid du Colombier static void
vGet6NotesInfo(FILE * pFile,ULONG ulStartBlock,const ULONG * aulBBD,size_t tBBDLen,const UCHAR * aucHeader)486f5736e95SDavid du Colombier vGet6NotesInfo(FILE *pFile, ULONG ulStartBlock,
487f5736e95SDavid du Colombier 	const ULONG *aulBBD, size_t tBBDLen,
488f5736e95SDavid du Colombier 	const UCHAR *aucHeader)
489f5736e95SDavid du Colombier {
490*25b329d5SDavid du Colombier 	TRACE_MSG("vGet6NotesInfo");
491*25b329d5SDavid du Colombier 
492f5736e95SDavid du Colombier 	vGet6FootnotesInfo(pFile, ulStartBlock,
493f5736e95SDavid du Colombier 			aulBBD, tBBDLen, aucHeader);
494*25b329d5SDavid du Colombier 	vGet6FootnotesText(pFile, ulStartBlock,
495*25b329d5SDavid du Colombier 			aulBBD, tBBDLen, aucHeader);
496f5736e95SDavid du Colombier 	vGet6EndnotesInfo(pFile, ulStartBlock,
497f5736e95SDavid du Colombier 			aulBBD, tBBDLen, aucHeader);
498f5736e95SDavid du Colombier } /* end of vGet6NotesInfo */
499f5736e95SDavid du Colombier 
500f5736e95SDavid du Colombier /*
501f5736e95SDavid du Colombier  * Build the list with footnote information for Word 8/9/10 files
502f5736e95SDavid du Colombier  */
503f5736e95SDavid du Colombier static void
vGet8FootnotesInfo(FILE * pFile,const pps_info_type * pPPS,const ULONG * aulBBD,size_t tBBDLen,const ULONG * aulSBD,size_t tSBDLen,const UCHAR * aucHeader)504f5736e95SDavid du Colombier vGet8FootnotesInfo(FILE *pFile, const pps_info_type *pPPS,
505f5736e95SDavid du Colombier 	const ULONG *aulBBD, size_t tBBDLen,
506f5736e95SDavid du Colombier 	const ULONG *aulSBD, size_t tSBDLen,
507f5736e95SDavid du Colombier 	const UCHAR *aucHeader)
508f5736e95SDavid du Colombier {
509f5736e95SDavid du Colombier 	const ULONG	*aulBlockDepot;
510f5736e95SDavid du Colombier 	UCHAR	*aucBuffer;
511f5736e95SDavid du Colombier 	ULONG	ulFileOffset, ulBeginOfText, ulOffset, ulBeginFootnoteInfo;
512f5736e95SDavid du Colombier 	size_t	tFootnoteInfoLen, tBlockDepotLen, tBlockSize;
513*25b329d5SDavid du Colombier 	size_t	tIndex;
514f5736e95SDavid du Colombier 
515*25b329d5SDavid du Colombier 	TRACE_MSG("vGet8FootnotesInfo");
516*25b329d5SDavid du Colombier 
517*25b329d5SDavid du Colombier 	ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
518f5736e95SDavid du Colombier 	NO_DBG_HEX(ulBeginOfText);
519*25b329d5SDavid du Colombier 	ulBeginFootnoteInfo = ulGetLong(0xaa, aucHeader); /* fcPlcffndRef */
520f5736e95SDavid du Colombier 	NO_DBG_HEX(ulBeginFootnoteInfo);
521*25b329d5SDavid du Colombier 	tFootnoteInfoLen =
522*25b329d5SDavid du Colombier 		(size_t)ulGetLong(0xae, aucHeader); /* lcbPlcffndRef */
523f5736e95SDavid du Colombier 	NO_DBG_DEC(tFootnoteInfoLen);
524f5736e95SDavid du Colombier 
525f5736e95SDavid du Colombier 	if (tFootnoteInfoLen < 10) {
526f5736e95SDavid du Colombier 		DBG_MSG("No Footnotes in this document");
527f5736e95SDavid du Colombier 		return;
528f5736e95SDavid du Colombier 	}
529f5736e95SDavid du Colombier 
530*25b329d5SDavid du Colombier 	NO_DBG_DEC(pPPS->tTable.ulSB);
531*25b329d5SDavid du Colombier 	NO_DBG_HEX(pPPS->tTable.ulSize);
532*25b329d5SDavid du Colombier 	if (pPPS->tTable.ulSize == 0) {
533*25b329d5SDavid du Colombier 		DBG_MSG("No footnotes information");
534f5736e95SDavid du Colombier 		return;
535f5736e95SDavid du Colombier 	}
536*25b329d5SDavid du Colombier 
537*25b329d5SDavid du Colombier 	if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
538f5736e95SDavid du Colombier 	  	/* Use the Small Block Depot */
539f5736e95SDavid du Colombier 		aulBlockDepot = aulSBD;
540f5736e95SDavid du Colombier 		tBlockDepotLen = tSBDLen;
541f5736e95SDavid du Colombier 		tBlockSize = SMALL_BLOCK_SIZE;
542f5736e95SDavid du Colombier 	} else {
543f5736e95SDavid du Colombier 	  	/* Use the Big Block Depot */
544f5736e95SDavid du Colombier 		aulBlockDepot = aulBBD;
545f5736e95SDavid du Colombier 		tBlockDepotLen = tBBDLen;
546f5736e95SDavid du Colombier 		tBlockSize = BIG_BLOCK_SIZE;
547f5736e95SDavid du Colombier 	}
548f5736e95SDavid du Colombier 	aucBuffer = xmalloc(tFootnoteInfoLen);
549*25b329d5SDavid du Colombier 	if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
550f5736e95SDavid du Colombier 			aulBlockDepot, tBlockDepotLen, tBlockSize,
551f5736e95SDavid du Colombier 			aucBuffer, ulBeginFootnoteInfo, tFootnoteInfoLen)) {
552f5736e95SDavid du Colombier 		aucBuffer = xfree(aucBuffer);
553f5736e95SDavid du Colombier 		return;
554f5736e95SDavid du Colombier 	}
555f5736e95SDavid du Colombier 	NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteInfoLen);
556f5736e95SDavid du Colombier 
557f5736e95SDavid du Colombier 	fail(tFootnoteListLength != 0);
558f5736e95SDavid du Colombier 	tFootnoteListLength = (tFootnoteInfoLen - 4) / 6;
559f5736e95SDavid du Colombier 	fail(tFootnoteListLength == 0);
560f5736e95SDavid du Colombier 
561f5736e95SDavid du Colombier 	fail(aulFootnoteList != NULL);
562f5736e95SDavid du Colombier 	aulFootnoteList = xcalloc(tFootnoteListLength, sizeof(ULONG));
563f5736e95SDavid du Colombier 
564*25b329d5SDavid du Colombier 	for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
565*25b329d5SDavid du Colombier 		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
566f5736e95SDavid du Colombier 		NO_DBG_HEX(ulOffset);
567f5736e95SDavid du Colombier 		ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
568f5736e95SDavid du Colombier 		NO_DBG_HEX(ulFileOffset);
569*25b329d5SDavid du Colombier 		aulFootnoteList[tIndex] = ulFileOffset;
570f5736e95SDavid du Colombier 	}
571f5736e95SDavid du Colombier 	aucBuffer = xfree(aucBuffer);
572f5736e95SDavid du Colombier } /* end of vGet8FootnotesInfo */
573f5736e95SDavid du Colombier 
574f5736e95SDavid du Colombier /*
575*25b329d5SDavid du Colombier  * Build the list with footnote text information for Word 8/9/10 files
576*25b329d5SDavid du Colombier  */
577*25b329d5SDavid du Colombier static void
vGet8FootnotesText(FILE * pFile,const pps_info_type * pPPS,const ULONG * aulBBD,size_t tBBDLen,const ULONG * aulSBD,size_t tSBDLen,const UCHAR * aucHeader)578*25b329d5SDavid du Colombier vGet8FootnotesText(FILE *pFile, const pps_info_type *pPPS,
579*25b329d5SDavid du Colombier 	const ULONG *aulBBD, size_t tBBDLen,
580*25b329d5SDavid du Colombier 	const ULONG *aulSBD, size_t tSBDLen,
581*25b329d5SDavid du Colombier 	const UCHAR *aucHeader)
582*25b329d5SDavid du Colombier {
583*25b329d5SDavid du Colombier 	footnote_local_type	*pCurr;
584*25b329d5SDavid du Colombier 	const ULONG	*aulBlockDepot;
585*25b329d5SDavid du Colombier 	UCHAR	*aucBuffer;
586*25b329d5SDavid du Colombier 	ULONG	ulCharPos, ulBeginOfFootnotes, ulOffset, ulBeginFootnoteText;
587*25b329d5SDavid du Colombier 	size_t	tFootnoteTextLen, tBlockDepotLen, tBlockSize;
588*25b329d5SDavid du Colombier 	size_t	tIndex;
589*25b329d5SDavid du Colombier 
590*25b329d5SDavid du Colombier 	TRACE_MSG("vGet8FootnotesText");
591*25b329d5SDavid du Colombier 
592*25b329d5SDavid du Colombier 	ulBeginOfFootnotes = ulGetLong(0x18, aucHeader); /* fcMin */
593*25b329d5SDavid du Colombier 	ulBeginOfFootnotes += ulGetLong(0x4c, aucHeader); /* ccpText */
594*25b329d5SDavid du Colombier 	NO_DBG_HEX(ulBeginOfFootnotes);
595*25b329d5SDavid du Colombier 
596*25b329d5SDavid du Colombier 	ulBeginFootnoteText = ulGetLong(0xb2, aucHeader); /* fcPlcffndTxt */
597*25b329d5SDavid du Colombier 	NO_DBG_HEX(ulBeginFootnoteText);
598*25b329d5SDavid du Colombier 	tFootnoteTextLen =
599*25b329d5SDavid du Colombier 		(size_t)ulGetLong(0xb6, aucHeader); /* lcbPlcffndTxt */
600*25b329d5SDavid du Colombier 	NO_DBG_DEC(tFootnoteTextLen);
601*25b329d5SDavid du Colombier 
602*25b329d5SDavid du Colombier 	if (tFootnoteTextLen < 12) {
603*25b329d5SDavid du Colombier 		DBG_MSG("No Footnote text in this document");
604*25b329d5SDavid du Colombier 		return;
605*25b329d5SDavid du Colombier 	}
606*25b329d5SDavid du Colombier 
607*25b329d5SDavid du Colombier 	NO_DBG_DEC(pPPS->tTable.ulSB);
608*25b329d5SDavid du Colombier 	NO_DBG_HEX(pPPS->tTable.ulSize);
609*25b329d5SDavid du Colombier 	if (pPPS->tTable.ulSize == 0) {
610*25b329d5SDavid du Colombier 		DBG_MSG("No footnote text information");
611*25b329d5SDavid du Colombier 		return;
612*25b329d5SDavid du Colombier 	}
613*25b329d5SDavid du Colombier 
614*25b329d5SDavid du Colombier 	if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
615*25b329d5SDavid du Colombier 	  	/* Use the Small Block Depot */
616*25b329d5SDavid du Colombier 		aulBlockDepot = aulSBD;
617*25b329d5SDavid du Colombier 		tBlockDepotLen = tSBDLen;
618*25b329d5SDavid du Colombier 		tBlockSize = SMALL_BLOCK_SIZE;
619*25b329d5SDavid du Colombier 	} else {
620*25b329d5SDavid du Colombier 	  	/* Use the Big Block Depot */
621*25b329d5SDavid du Colombier 		aulBlockDepot = aulBBD;
622*25b329d5SDavid du Colombier 		tBlockDepotLen = tBBDLen;
623*25b329d5SDavid du Colombier 		tBlockSize = BIG_BLOCK_SIZE;
624*25b329d5SDavid du Colombier 	}
625*25b329d5SDavid du Colombier 	aucBuffer = xmalloc(tFootnoteTextLen);
626*25b329d5SDavid du Colombier 	if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
627*25b329d5SDavid du Colombier 			aulBlockDepot, tBlockDepotLen, tBlockSize,
628*25b329d5SDavid du Colombier 			aucBuffer, ulBeginFootnoteText, tFootnoteTextLen)) {
629*25b329d5SDavid du Colombier 		aucBuffer = xfree(aucBuffer);
630*25b329d5SDavid du Colombier 		return;
631*25b329d5SDavid du Colombier 	}
632*25b329d5SDavid du Colombier 	NO_DBG_PRINT_BLOCK(aucBuffer, tFootnoteTextLen);
633*25b329d5SDavid du Colombier 
634*25b329d5SDavid du Colombier 	fail(tFootnoteTextLength != 0);
635*25b329d5SDavid du Colombier 	tFootnoteTextLength = tFootnoteTextLen / 4 - 2;
636*25b329d5SDavid du Colombier 	fail(tFootnoteTextLength == 0);
637*25b329d5SDavid du Colombier 
638*25b329d5SDavid du Colombier 	fail(pFootnoteText != NULL);
639*25b329d5SDavid du Colombier 	pFootnoteText = xcalloc(tFootnoteTextLength,
640*25b329d5SDavid du Colombier 				sizeof(footnote_local_type));
641*25b329d5SDavid du Colombier 
642*25b329d5SDavid du Colombier 	for (tIndex = 0; tIndex < tFootnoteTextLength; tIndex++) {
643*25b329d5SDavid du Colombier 		pCurr = pFootnoteText + tIndex;
644*25b329d5SDavid du Colombier 		pCurr->tInfo.szText = NULL;
645*25b329d5SDavid du Colombier 		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
646*25b329d5SDavid du Colombier 		NO_DBG_HEX(ulOffset);
647*25b329d5SDavid du Colombier 		ulCharPos = ulBeginOfFootnotes + ulOffset;
648*25b329d5SDavid du Colombier 		NO_DBG_HEX(ulCharPos);
649*25b329d5SDavid du Colombier 		NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
650*25b329d5SDavid du Colombier 		pCurr->ulCharPosStart = ulCharPos;
651*25b329d5SDavid du Colombier 		ulOffset = ulGetLong(tIndex * 4 + 4, aucBuffer);
652*25b329d5SDavid du Colombier 		NO_DBG_HEX(ulOffset);
653*25b329d5SDavid du Colombier 		ulCharPos = ulBeginOfFootnotes + ulOffset;
654*25b329d5SDavid du Colombier 		NO_DBG_HEX(ulCharPos);
655*25b329d5SDavid du Colombier 		NO_DBG_HEX(ulCharPos2FileOffset(ulCharPos));
656*25b329d5SDavid du Colombier 		pCurr->ulCharPosNext = ulCharPos;
657*25b329d5SDavid du Colombier 		pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
658*25b329d5SDavid du Colombier 	}
659*25b329d5SDavid du Colombier 	aucBuffer = xfree(aucBuffer);
660*25b329d5SDavid du Colombier } /* end of vGet8FootnotesText */
661*25b329d5SDavid du Colombier 
662*25b329d5SDavid du Colombier /*
663f5736e95SDavid du Colombier  * Build the list with endnote information for Word 8/9/10 files
664f5736e95SDavid du Colombier  */
665f5736e95SDavid du Colombier static void
vGet8EndnotesInfo(FILE * pFile,const pps_info_type * pPPS,const ULONG * aulBBD,size_t tBBDLen,const ULONG * aulSBD,size_t tSBDLen,const UCHAR * aucHeader)666f5736e95SDavid du Colombier vGet8EndnotesInfo(FILE *pFile, const pps_info_type *pPPS,
667f5736e95SDavid du Colombier 	const ULONG *aulBBD, size_t tBBDLen,
668f5736e95SDavid du Colombier 	const ULONG *aulSBD, size_t tSBDLen,
669f5736e95SDavid du Colombier 	const UCHAR *aucHeader)
670f5736e95SDavid du Colombier {
671f5736e95SDavid du Colombier 	const ULONG	*aulBlockDepot;
672f5736e95SDavid du Colombier 	UCHAR	*aucBuffer;
673f5736e95SDavid du Colombier 	ULONG	ulFileOffset, ulBeginOfText, ulOffset, ulBeginEndnoteInfo;
674f5736e95SDavid du Colombier 	size_t	tEndnoteInfoLen, tBlockDepotLen, tBlockSize;
675*25b329d5SDavid du Colombier 	size_t	tIndex;
676f5736e95SDavid du Colombier 
677*25b329d5SDavid du Colombier 	TRACE_MSG("vGet8EndnotesInfo");
678*25b329d5SDavid du Colombier 
679*25b329d5SDavid du Colombier 	ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
680f5736e95SDavid du Colombier 	NO_DBG_HEX(ulBeginOfText);
681*25b329d5SDavid du Colombier 	ulBeginEndnoteInfo = ulGetLong(0x20a, aucHeader); /* fcPlcfendRef */
682f5736e95SDavid du Colombier 	NO_DBG_HEX(ulBeginEndnoteInfo);
683*25b329d5SDavid du Colombier 	tEndnoteInfoLen = (size_t)ulGetLong(0x20e, aucHeader); /* lcbPlcfendRef */
684f5736e95SDavid du Colombier 	NO_DBG_DEC(tEndnoteInfoLen);
685f5736e95SDavid du Colombier 
686f5736e95SDavid du Colombier 	if (tEndnoteInfoLen < 10) {
687*25b329d5SDavid du Colombier 		DBG_MSG("No endnotes in this document");
688f5736e95SDavid du Colombier 		return;
689f5736e95SDavid du Colombier 	}
690f5736e95SDavid du Colombier 
691*25b329d5SDavid du Colombier 	NO_DBG_DEC(pPPS->tTable.ulSB);
692*25b329d5SDavid du Colombier 	NO_DBG_HEX(pPPS->tTable.ulSize);
693*25b329d5SDavid du Colombier 	if (pPPS->tTable.ulSize == 0) {
694*25b329d5SDavid du Colombier 		DBG_MSG("No endnotes information");
695f5736e95SDavid du Colombier 		return;
696f5736e95SDavid du Colombier 	}
697*25b329d5SDavid du Colombier 
698*25b329d5SDavid du Colombier 	if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
699f5736e95SDavid du Colombier 	  	/* Use the Small Block Depot */
700f5736e95SDavid du Colombier 		aulBlockDepot = aulSBD;
701f5736e95SDavid du Colombier 		tBlockDepotLen = tSBDLen;
702f5736e95SDavid du Colombier 		tBlockSize = SMALL_BLOCK_SIZE;
703f5736e95SDavid du Colombier 	} else {
704f5736e95SDavid du Colombier 	  	/* Use the Big Block Depot */
705f5736e95SDavid du Colombier 		aulBlockDepot = aulBBD;
706f5736e95SDavid du Colombier 		tBlockDepotLen = tBBDLen;
707f5736e95SDavid du Colombier 		tBlockSize = BIG_BLOCK_SIZE;
708f5736e95SDavid du Colombier 	}
709f5736e95SDavid du Colombier 	aucBuffer = xmalloc(tEndnoteInfoLen);
710*25b329d5SDavid du Colombier 	if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
711f5736e95SDavid du Colombier 			aulBlockDepot, tBlockDepotLen, tBlockSize,
712f5736e95SDavid du Colombier 			aucBuffer, ulBeginEndnoteInfo, tEndnoteInfoLen)) {
713f5736e95SDavid du Colombier 		aucBuffer = xfree(aucBuffer);
714f5736e95SDavid du Colombier 		return;
715f5736e95SDavid du Colombier 	}
716f5736e95SDavid du Colombier 	NO_DBG_PRINT_BLOCK(aucBuffer, tEndnoteInfoLen);
717f5736e95SDavid du Colombier 
718f5736e95SDavid du Colombier 	fail(tEndnoteListLength != 0);
719f5736e95SDavid du Colombier 	tEndnoteListLength = (tEndnoteInfoLen - 4) / 6;
720f5736e95SDavid du Colombier 	fail(tEndnoteListLength == 0);
721f5736e95SDavid du Colombier 
722f5736e95SDavid du Colombier 	fail(aulEndnoteList != NULL);
723f5736e95SDavid du Colombier 	aulEndnoteList = xcalloc(tEndnoteListLength, sizeof(ULONG));
724f5736e95SDavid du Colombier 
725*25b329d5SDavid du Colombier 	for (tIndex = 0; tIndex < tEndnoteListLength; tIndex++) {
726*25b329d5SDavid du Colombier 		ulOffset = ulGetLong(tIndex * 4, aucBuffer);
727f5736e95SDavid du Colombier 		NO_DBG_HEX(ulOffset);
728f5736e95SDavid du Colombier 		ulFileOffset = ulCharPos2FileOffset(ulBeginOfText + ulOffset);
729f5736e95SDavid du Colombier 		NO_DBG_HEX(ulFileOffset);
730*25b329d5SDavid du Colombier 		aulEndnoteList[tIndex] = ulFileOffset;
731f5736e95SDavid du Colombier 	}
732f5736e95SDavid du Colombier 	aucBuffer = xfree(aucBuffer);
733f5736e95SDavid du Colombier } /* end of vGet8EndnotesInfo */
734f5736e95SDavid du Colombier 
735f5736e95SDavid du Colombier /*
736f5736e95SDavid du Colombier  * Build the lists with footnote and endnote information for Word 8/9/10 files
737f5736e95SDavid du Colombier  */
738f5736e95SDavid du Colombier static void
vGet8NotesInfo(FILE * pFile,const pps_info_type * pPPS,const ULONG * aulBBD,size_t tBBDLen,const ULONG * aulSBD,size_t tSBDLen,const UCHAR * aucHeader)739f5736e95SDavid du Colombier vGet8NotesInfo(FILE *pFile, const pps_info_type *pPPS,
740f5736e95SDavid du Colombier 	const ULONG *aulBBD, size_t tBBDLen,
741f5736e95SDavid du Colombier 	const ULONG *aulSBD, size_t tSBDLen,
742f5736e95SDavid du Colombier 	const UCHAR *aucHeader)
743f5736e95SDavid du Colombier {
744*25b329d5SDavid du Colombier 	TRACE_MSG("vGet8NotesInfo");
745*25b329d5SDavid du Colombier 
746f5736e95SDavid du Colombier 	vGet8FootnotesInfo(pFile, pPPS,
747f5736e95SDavid du Colombier 			aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
748*25b329d5SDavid du Colombier 	vGet8FootnotesText(pFile, pPPS,
749*25b329d5SDavid du Colombier 			aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
750f5736e95SDavid du Colombier 	vGet8EndnotesInfo(pFile, pPPS,
751f5736e95SDavid du Colombier 			aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
752f5736e95SDavid du Colombier } /* end of vGet8NotesInfo */
753f5736e95SDavid du Colombier 
754f5736e95SDavid du Colombier /*
755f5736e95SDavid du Colombier  * Build the lists with footnote and endnote information
756f5736e95SDavid du Colombier  */
757f5736e95SDavid du Colombier void
vGetNotesInfo(FILE * pFile,const pps_info_type * pPPS,const ULONG * aulBBD,size_t tBBDLen,const ULONG * aulSBD,size_t tSBDLen,const UCHAR * aucHeader,int iWordVersion)758f5736e95SDavid du Colombier vGetNotesInfo(FILE *pFile, const pps_info_type *pPPS,
759f5736e95SDavid du Colombier 	const ULONG *aulBBD, size_t tBBDLen,
760f5736e95SDavid du Colombier 	const ULONG *aulSBD, size_t tSBDLen,
761f5736e95SDavid du Colombier 	const UCHAR *aucHeader, int iWordVersion)
762f5736e95SDavid du Colombier {
763*25b329d5SDavid du Colombier 	TRACE_MSG("vGetNotesInfo");
764*25b329d5SDavid du Colombier 
765*25b329d5SDavid du Colombier 	fail(pFile == NULL);
766*25b329d5SDavid du Colombier 	fail(pPPS == NULL && iWordVersion >= 6);
767*25b329d5SDavid du Colombier 	fail(aulBBD == NULL && tBBDLen != 0);
768*25b329d5SDavid du Colombier 	fail(aulSBD == NULL && tSBDLen != 0);
769*25b329d5SDavid du Colombier 	fail(aucHeader == NULL);
770f5736e95SDavid du Colombier 
771f5736e95SDavid du Colombier 	switch (iWordVersion) {
772*25b329d5SDavid du Colombier 	case 0:
773*25b329d5SDavid du Colombier 		vGet0NotesInfo(pFile, aucHeader);
774*25b329d5SDavid du Colombier 		break;
775*25b329d5SDavid du Colombier 	case 1:
776*25b329d5SDavid du Colombier 	case 2:
777*25b329d5SDavid du Colombier 		vGet2NotesInfo(pFile, aucHeader);
778*25b329d5SDavid du Colombier 		break;
779*25b329d5SDavid du Colombier 	case 4:
780*25b329d5SDavid du Colombier 	case 5:
781*25b329d5SDavid du Colombier 		break;
782f5736e95SDavid du Colombier 	case 6:
783f5736e95SDavid du Colombier 	case 7:
784f5736e95SDavid du Colombier 		vGet6NotesInfo(pFile, pPPS->tWordDocument.ulSB,
785f5736e95SDavid du Colombier 			aulBBD, tBBDLen, aucHeader);
786f5736e95SDavid du Colombier 		break;
787f5736e95SDavid du Colombier 	case 8:
788f5736e95SDavid du Colombier 		vGet8NotesInfo(pFile, pPPS,
789f5736e95SDavid du Colombier 			aulBBD, tBBDLen, aulSBD, tSBDLen, aucHeader);
790f5736e95SDavid du Colombier 		break;
791f5736e95SDavid du Colombier 	default:
792f5736e95SDavid du Colombier 		werr(0, "Sorry, no notes information");
793f5736e95SDavid du Colombier 		break;
794f5736e95SDavid du Colombier 	}
795f5736e95SDavid du Colombier } /* end of vGetNotesInfo */
796f5736e95SDavid du Colombier 
797f5736e95SDavid du Colombier /*
798*25b329d5SDavid du Colombier  *  vPrepareFootnoteText - prepare the footnote text
799*25b329d5SDavid du Colombier  */
800*25b329d5SDavid du Colombier void
vPrepareFootnoteText(FILE * pFile)801*25b329d5SDavid du Colombier vPrepareFootnoteText(FILE *pFile)
802*25b329d5SDavid du Colombier {
803*25b329d5SDavid du Colombier 	footnote_local_type	*pCurr;
804*25b329d5SDavid du Colombier 	size_t		tFootnote;
805*25b329d5SDavid du Colombier 
806*25b329d5SDavid du Colombier 	fail(pFile == NULL);
807*25b329d5SDavid du Colombier 	fail(pFootnoteText == NULL && tFootnoteTextLength != 0);
808*25b329d5SDavid du Colombier 
809*25b329d5SDavid du Colombier 	if (pFootnoteText == NULL || tFootnoteTextLength == 0) {
810*25b329d5SDavid du Colombier 		/* No information */
811*25b329d5SDavid du Colombier 		return;
812*25b329d5SDavid du Colombier 	}
813*25b329d5SDavid du Colombier 
814*25b329d5SDavid du Colombier 	/* Fill text and useful-ness */
815*25b329d5SDavid du Colombier 	for (tFootnote = 0; tFootnote < tFootnoteTextLength; tFootnote++) {
816*25b329d5SDavid du Colombier 		pCurr = pFootnoteText + tFootnote;
817*25b329d5SDavid du Colombier 		pCurr->bUseful = pCurr->ulCharPosStart != pCurr->ulCharPosNext;
818*25b329d5SDavid du Colombier 		if (pCurr->bUseful) {
819*25b329d5SDavid du Colombier 			pCurr->tInfo.szText = szFootnoteDecryptor(pFile,
820*25b329d5SDavid du Colombier 							pCurr->ulCharPosStart,
821*25b329d5SDavid du Colombier 							pCurr->ulCharPosNext);
822*25b329d5SDavid du Colombier 		} else {
823*25b329d5SDavid du Colombier 			pCurr->tInfo.szText = NULL;
824*25b329d5SDavid du Colombier 		}
825*25b329d5SDavid du Colombier 	}
826*25b329d5SDavid du Colombier } /* end of vPrepareFootnoteText */
827*25b329d5SDavid du Colombier 
828*25b329d5SDavid du Colombier /*
829*25b329d5SDavid du Colombier  * szGetFootnootText - get the text of the spefified footnote
830*25b329d5SDavid du Colombier  */
831*25b329d5SDavid du Colombier const char *
szGetFootnootText(UINT uiFootnoteIndex)832*25b329d5SDavid du Colombier szGetFootnootText(UINT uiFootnoteIndex)
833*25b329d5SDavid du Colombier {
834*25b329d5SDavid du Colombier 	if ((size_t)uiFootnoteIndex >= tFootnoteTextLength) {
835*25b329d5SDavid du Colombier 		return NULL;
836*25b329d5SDavid du Colombier 	}
837*25b329d5SDavid du Colombier 	return pFootnoteText[uiFootnoteIndex].tInfo.szText;
838*25b329d5SDavid du Colombier } /* end of szGetFootnootText */
839*25b329d5SDavid du Colombier 
840*25b329d5SDavid du Colombier /*
841f5736e95SDavid du Colombier  * Get the notetype of the note at the given fileoffset
842f5736e95SDavid du Colombier  */
843f5736e95SDavid du Colombier notetype_enum
eGetNotetype(ULONG ulFileOffset)844f5736e95SDavid du Colombier eGetNotetype(ULONG ulFileOffset)
845f5736e95SDavid du Colombier {
846f5736e95SDavid du Colombier 	size_t	tIndex;
847f5736e95SDavid du Colombier 
848*25b329d5SDavid du Colombier 	TRACE_MSG("eGetNotetype");
849*25b329d5SDavid du Colombier 
850f5736e95SDavid du Colombier 	fail(aulFootnoteList == NULL && tFootnoteListLength != 0);
851f5736e95SDavid du Colombier 	fail(aulEndnoteList == NULL && tEndnoteListLength != 0);
852f5736e95SDavid du Colombier 
853f5736e95SDavid du Colombier 	/* Go for the easy answers first */
854f5736e95SDavid du Colombier 	if (tFootnoteListLength == 0 && tEndnoteListLength == 0) {
855f5736e95SDavid du Colombier 		return notetype_is_unknown;
856f5736e95SDavid du Colombier 	}
857f5736e95SDavid du Colombier 	if (tEndnoteListLength == 0) {
858f5736e95SDavid du Colombier 		return notetype_is_footnote;
859f5736e95SDavid du Colombier 	}
860f5736e95SDavid du Colombier 	if (tFootnoteListLength == 0) {
861f5736e95SDavid du Colombier 		return notetype_is_endnote;
862f5736e95SDavid du Colombier 	}
863f5736e95SDavid du Colombier 	/* No easy answer, so we search */
864f5736e95SDavid du Colombier 	for (tIndex = 0; tIndex < tFootnoteListLength; tIndex++) {
865f5736e95SDavid du Colombier 		if (aulFootnoteList[tIndex] == ulFileOffset) {
866f5736e95SDavid du Colombier 			return notetype_is_footnote;
867f5736e95SDavid du Colombier 		}
868f5736e95SDavid du Colombier 	}
869f5736e95SDavid du Colombier 	for (tIndex = 0; tIndex < tEndnoteListLength; tIndex++) {
870f5736e95SDavid du Colombier 		if (aulEndnoteList[tIndex] == ulFileOffset) {
871f5736e95SDavid du Colombier 			return notetype_is_endnote;
872f5736e95SDavid du Colombier 		}
873f5736e95SDavid du Colombier 	}
874f5736e95SDavid du Colombier 	/* Not found */
875f5736e95SDavid du Colombier 	return notetype_is_unknown;
876f5736e95SDavid du Colombier } /* end of eGetNotetype */
877