xref: /plan9/sys/src/cmd/aux/antiword/wordlib.c (revision 25b329d522281a8cdd35da0dcc08c3fc621059a9)
1f5736e95SDavid du Colombier /*
2f5736e95SDavid du Colombier  * wordlib.c
3*25b329d5SDavid du Colombier  * Copyright (C) 1998-2004 A.J. van Os; Released under GNU GPL
4f5736e95SDavid du Colombier  *
5f5736e95SDavid du Colombier  * Description:
6f5736e95SDavid du Colombier  * Deal with the internals of a MS Word file
7f5736e95SDavid du Colombier  */
8f5736e95SDavid du Colombier 
9f5736e95SDavid du Colombier #include "antiword.h"
10f5736e95SDavid du Colombier 
11f5736e95SDavid du Colombier static BOOL	bOldMacFile = FALSE;
12f5736e95SDavid du Colombier 
13f5736e95SDavid du Colombier 
14f5736e95SDavid du Colombier /*
15f5736e95SDavid du Colombier  * Common part of the file checking functions
16f5736e95SDavid du Colombier  */
17f5736e95SDavid du Colombier static BOOL
bCheckBytes(FILE * pFile,const UCHAR * aucBytes,size_t tBytes)18f5736e95SDavid du Colombier bCheckBytes(FILE *pFile, const UCHAR *aucBytes, size_t tBytes)
19f5736e95SDavid du Colombier {
20f5736e95SDavid du Colombier 	int	iIndex, iChar;
21f5736e95SDavid du Colombier 
22f5736e95SDavid du Colombier 	fail(pFile == NULL || aucBytes == NULL || tBytes == 0);
23f5736e95SDavid du Colombier 
24f5736e95SDavid du Colombier 	rewind(pFile);
25f5736e95SDavid du Colombier 
26f5736e95SDavid du Colombier 	for (iIndex = 0; iIndex < (int)tBytes; iIndex++) {
27f5736e95SDavid du Colombier 		iChar = getc(pFile);
28f5736e95SDavid du Colombier 		if (iChar == EOF || iChar != (int)aucBytes[iIndex]) {
29f5736e95SDavid du Colombier 			NO_DBG_HEX(iChar);
30f5736e95SDavid du Colombier 			NO_DBG_HEX(aucBytes[iIndex]);
31f5736e95SDavid du Colombier 			return FALSE;
32f5736e95SDavid du Colombier 		}
33f5736e95SDavid du Colombier 	}
34f5736e95SDavid du Colombier 	return TRUE;
35f5736e95SDavid du Colombier } /* end of bCheckBytes */
36f5736e95SDavid du Colombier 
37f5736e95SDavid du Colombier /*
38f5736e95SDavid du Colombier  * This function checks whether the given file is or is not a "Word for DOS"
39f5736e95SDavid du Colombier  * document
40f5736e95SDavid du Colombier  */
41f5736e95SDavid du Colombier BOOL
bIsWordForDosFile(FILE * pFile,long lFilesize)42f5736e95SDavid du Colombier bIsWordForDosFile(FILE *pFile, long lFilesize)
43f5736e95SDavid du Colombier {
44f5736e95SDavid du Colombier 	static UCHAR	aucBytes[] =
45f5736e95SDavid du Colombier 		{ 0x31, 0xbe, 0x00, 0x00, 0x00, 0xab };	/* Word for DOS */
46f5736e95SDavid du Colombier 
47f5736e95SDavid du Colombier 	DBG_MSG("bIsWordForDosFile");
48f5736e95SDavid du Colombier 
49f5736e95SDavid du Colombier 	if (pFile == NULL || lFilesize < 0) {
50f5736e95SDavid du Colombier 		DBG_MSG("No proper file given");
51f5736e95SDavid du Colombier 		return FALSE;
52f5736e95SDavid du Colombier 	}
53f5736e95SDavid du Colombier 	if (lFilesize < 128) {
54f5736e95SDavid du Colombier 		DBG_MSG("File too small to be a Word document");
55f5736e95SDavid du Colombier 		return FALSE;
56f5736e95SDavid du Colombier 	}
57f5736e95SDavid du Colombier 	return bCheckBytes(pFile, aucBytes, elementsof(aucBytes));
58f5736e95SDavid du Colombier } /* end of bIsWordForDosFile */
59f5736e95SDavid du Colombier 
60f5736e95SDavid du Colombier /*
61f5736e95SDavid du Colombier  * This function checks whether the given file is or is not a file with an
62f5736e95SDavid du Colombier  * OLE envelope (That is a document made by Word 6 or later)
63f5736e95SDavid du Colombier  */
64f5736e95SDavid du Colombier static BOOL
bIsWordFileWithOLE(FILE * pFile,long lFilesize)65f5736e95SDavid du Colombier bIsWordFileWithOLE(FILE *pFile, long lFilesize)
66f5736e95SDavid du Colombier {
67f5736e95SDavid du Colombier 	static UCHAR	aucBytes[] =
68f5736e95SDavid du Colombier 		{ 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 };
69f5736e95SDavid du Colombier 	int	iTailLen;
70f5736e95SDavid du Colombier 
71f5736e95SDavid du Colombier 	if (pFile == NULL || lFilesize < 0) {
72f5736e95SDavid du Colombier 		DBG_MSG("No proper file given");
73f5736e95SDavid du Colombier 		return FALSE;
74f5736e95SDavid du Colombier 	}
75f5736e95SDavid du Colombier 	if (lFilesize < (long)BIG_BLOCK_SIZE * 3) {
76f5736e95SDavid du Colombier 		DBG_MSG("This file is too small to be a Word document");
77f5736e95SDavid du Colombier 		return FALSE;
78f5736e95SDavid du Colombier 	}
79f5736e95SDavid du Colombier 
80f5736e95SDavid du Colombier 	iTailLen = (int)(lFilesize % BIG_BLOCK_SIZE);
81f5736e95SDavid du Colombier 	switch (iTailLen) {
82f5736e95SDavid du Colombier 	case 0:		/* No tail, as it should be */
83f5736e95SDavid du Colombier 		break;
84f5736e95SDavid du Colombier 	case 1:
85f5736e95SDavid du Colombier 	case 2:		/* Filesize mismatch or a buggy email program */
86f5736e95SDavid du Colombier 		if ((int)(lFilesize % 3) == iTailLen) {
87f5736e95SDavid du Colombier 			DBG_DEC(lFilesize);
88f5736e95SDavid du Colombier 			return FALSE;
89f5736e95SDavid du Colombier 		}
90f5736e95SDavid du Colombier 		/*
91f5736e95SDavid du Colombier 		 * Ignore extra bytes caused by buggy email programs.
92f5736e95SDavid du Colombier 		 * They have bugs in their base64 encoding or decoding.
93f5736e95SDavid du Colombier 		 * 3 bytes -> 4 ascii chars -> 3 bytes
94f5736e95SDavid du Colombier 		 */
95f5736e95SDavid du Colombier 		DBG_MSG("Document with extra bytes");
96f5736e95SDavid du Colombier 		break;
97f5736e95SDavid du Colombier 	default:	/* Wrong filesize for a Word document */
98f5736e95SDavid du Colombier 		DBG_DEC(lFilesize);
99f5736e95SDavid du Colombier 		DBG_DEC(iTailLen);
100f5736e95SDavid du Colombier 		return FALSE;
101f5736e95SDavid du Colombier 	}
102f5736e95SDavid du Colombier 	return bCheckBytes(pFile, aucBytes, elementsof(aucBytes));
103f5736e95SDavid du Colombier } /* end of bIsWordFileWithOLE */
104f5736e95SDavid du Colombier 
105f5736e95SDavid du Colombier /*
106f5736e95SDavid du Colombier  * This function checks whether the given file is or is not a RTF document
107f5736e95SDavid du Colombier  */
108f5736e95SDavid du Colombier BOOL
bIsRtfFile(FILE * pFile)109f5736e95SDavid du Colombier bIsRtfFile(FILE *pFile)
110f5736e95SDavid du Colombier {
111f5736e95SDavid du Colombier 	static UCHAR	aucBytes[] =
112f5736e95SDavid du Colombier 		{ '{', '\\', 'r', 't', 'f', '1' };
113f5736e95SDavid du Colombier 
114f5736e95SDavid du Colombier 	DBG_MSG("bIsRtfFile");
115f5736e95SDavid du Colombier 
116f5736e95SDavid du Colombier 	return bCheckBytes(pFile, aucBytes, elementsof(aucBytes));
117f5736e95SDavid du Colombier } /* end of bIsRtfFile */
118f5736e95SDavid du Colombier 
119f5736e95SDavid du Colombier /*
120f5736e95SDavid du Colombier  * This function checks whether the given file is or is not a WP document
121f5736e95SDavid du Colombier  */
122f5736e95SDavid du Colombier BOOL
bIsWordPerfectFile(FILE * pFile)123f5736e95SDavid du Colombier bIsWordPerfectFile(FILE *pFile)
124f5736e95SDavid du Colombier {
125f5736e95SDavid du Colombier 	static UCHAR	aucBytes[] =
126f5736e95SDavid du Colombier 		{ 0xff, 'W', 'P', 'C' };
127f5736e95SDavid du Colombier 
128f5736e95SDavid du Colombier 	DBG_MSG("bIsWordPerfectFile");
129f5736e95SDavid du Colombier 
130f5736e95SDavid du Colombier 	return bCheckBytes(pFile, aucBytes, elementsof(aucBytes));
131f5736e95SDavid du Colombier } /* end of bIsWordPerfectFile */
132f5736e95SDavid du Colombier 
133f5736e95SDavid du Colombier /*
134f5736e95SDavid du Colombier  * This function checks whether the given file is or is not a "Win Word 1 or 2"
135f5736e95SDavid du Colombier  * document
136f5736e95SDavid du Colombier  */
137f5736e95SDavid du Colombier BOOL
bIsWinWord12File(FILE * pFile,long lFilesize)138f5736e95SDavid du Colombier bIsWinWord12File(FILE *pFile, long lFilesize)
139f5736e95SDavid du Colombier {
140f5736e95SDavid du Colombier 	static UCHAR	aucBytes[2][4] = {
141f5736e95SDavid du Colombier 		{ 0x9b, 0xa5, 0x21, 0x00 },	/* Win Word 1.x */
142f5736e95SDavid du Colombier 		{ 0xdb, 0xa5, 0x2d, 0x00 },	/* Win Word 2.0 */
143f5736e95SDavid du Colombier 	};
144f5736e95SDavid du Colombier 	int	iIndex;
145f5736e95SDavid du Colombier 
146f5736e95SDavid du Colombier 	DBG_MSG("bIsWinWord12File");
147f5736e95SDavid du Colombier 
148f5736e95SDavid du Colombier 	if (pFile == NULL || lFilesize < 0) {
149f5736e95SDavid du Colombier 		DBG_MSG("No proper file given");
150f5736e95SDavid du Colombier 		return FALSE;
151f5736e95SDavid du Colombier 	}
152f5736e95SDavid du Colombier 	if (lFilesize < 384) {
153f5736e95SDavid du Colombier 		DBG_MSG("This file is too small to be a Word document");
154f5736e95SDavid du Colombier 		return FALSE;
155f5736e95SDavid du Colombier 	}
156f5736e95SDavid du Colombier 
157f5736e95SDavid du Colombier 	for (iIndex = 0; iIndex < (int)elementsof(aucBytes); iIndex++) {
158f5736e95SDavid du Colombier 		if (bCheckBytes(pFile,
159f5736e95SDavid du Colombier 				aucBytes[iIndex],
160f5736e95SDavid du Colombier 				elementsof(aucBytes[iIndex]))) {
161f5736e95SDavid du Colombier 			return TRUE;
162f5736e95SDavid du Colombier 		}
163f5736e95SDavid du Colombier 	}
164f5736e95SDavid du Colombier 	return FALSE;
165f5736e95SDavid du Colombier } /* end of bIsWinWord12File */
166f5736e95SDavid du Colombier 
167f5736e95SDavid du Colombier /*
168f5736e95SDavid du Colombier  * This function checks whether the given file is or is not a "Mac Word 4 or 5"
169f5736e95SDavid du Colombier  * document
170f5736e95SDavid du Colombier  */
171f5736e95SDavid du Colombier BOOL
bIsMacWord45File(FILE * pFile)172f5736e95SDavid du Colombier bIsMacWord45File(FILE *pFile)
173f5736e95SDavid du Colombier {
174f5736e95SDavid du Colombier 	static UCHAR	aucBytes[2][6] = {
175f5736e95SDavid du Colombier 		{ 0xfe, 0x37, 0x00, 0x1c, 0x00, 0x00 },	/* Mac Word 4 */
176f5736e95SDavid du Colombier 		{ 0xfe, 0x37, 0x00, 0x23, 0x00, 0x00 },	/* Mac Word 5 */
177f5736e95SDavid du Colombier 	};
178f5736e95SDavid du Colombier 	int	iIndex;
179f5736e95SDavid du Colombier 
180f5736e95SDavid du Colombier 	DBG_MSG("bIsMacWord45File");
181f5736e95SDavid du Colombier 
182f5736e95SDavid du Colombier 	for (iIndex = 0; iIndex < (int)elementsof(aucBytes); iIndex++) {
183f5736e95SDavid du Colombier 		if (bCheckBytes(pFile,
184f5736e95SDavid du Colombier 				aucBytes[iIndex],
185f5736e95SDavid du Colombier 				elementsof(aucBytes[iIndex]))) {
186f5736e95SDavid du Colombier 			return TRUE;
187f5736e95SDavid du Colombier 		}
188f5736e95SDavid du Colombier 	}
189f5736e95SDavid du Colombier 	return FALSE;
190f5736e95SDavid du Colombier } /* end of bIsMacWord45File */
191f5736e95SDavid du Colombier 
192f5736e95SDavid du Colombier /*
193f5736e95SDavid du Colombier  * iGuessVersionNumber - guess the Word version number from first few bytes
194f5736e95SDavid du Colombier  *
195f5736e95SDavid du Colombier  * Returns the guessed version number or -1 when no guess it possible
196f5736e95SDavid du Colombier  */
197f5736e95SDavid du Colombier int
iGuessVersionNumber(FILE * pFile,long lFilesize)198f5736e95SDavid du Colombier iGuessVersionNumber(FILE *pFile, long lFilesize)
199f5736e95SDavid du Colombier {
200f5736e95SDavid du Colombier 	if(bIsWordForDosFile(pFile, lFilesize)) {
201f5736e95SDavid du Colombier 		return 0;
202f5736e95SDavid du Colombier 	}
203f5736e95SDavid du Colombier 	if (bIsWinWord12File(pFile, lFilesize)) {
204f5736e95SDavid du Colombier 		return 2;
205f5736e95SDavid du Colombier 	}
206f5736e95SDavid du Colombier 	if (bIsMacWord45File(pFile)) {
207f5736e95SDavid du Colombier 		return 5;
208f5736e95SDavid du Colombier 	}
209f5736e95SDavid du Colombier 	if (bIsWordFileWithOLE(pFile, lFilesize)) {
210f5736e95SDavid du Colombier 		return 6;
211f5736e95SDavid du Colombier 	}
212f5736e95SDavid du Colombier 	return -1;
213f5736e95SDavid du Colombier } /* end of iGuessVersionNumber */
214f5736e95SDavid du Colombier 
215f5736e95SDavid du Colombier /*
216f5736e95SDavid du Colombier  * iGetVersionNumber - get the Word version number from the header
217f5736e95SDavid du Colombier  *
218f5736e95SDavid du Colombier  * Returns the version number or -1 when unknown
219f5736e95SDavid du Colombier  */
220f5736e95SDavid du Colombier int
iGetVersionNumber(const UCHAR * aucHeader)221f5736e95SDavid du Colombier iGetVersionNumber(const UCHAR *aucHeader)
222f5736e95SDavid du Colombier {
223f5736e95SDavid du Colombier 	USHORT	usFib, usChse;
224f5736e95SDavid du Colombier 
225f5736e95SDavid du Colombier 	usFib = usGetWord(0x02, aucHeader);
226f5736e95SDavid du Colombier 	if (usFib >= 0x1000) {
227f5736e95SDavid du Colombier 		/* To big: must be MacWord using Big Endian */
228f5736e95SDavid du Colombier 		DBG_HEX(usFib);
229f5736e95SDavid du Colombier 		usFib = usGetWordBE(0x02, aucHeader);
230f5736e95SDavid du Colombier 	}
231f5736e95SDavid du Colombier 	DBG_DEC(usFib);
232f5736e95SDavid du Colombier 	bOldMacFile = FALSE;
233f5736e95SDavid du Colombier 	switch (usFib) {
234f5736e95SDavid du Colombier 	case   0:
235f5736e95SDavid du Colombier 		DBG_MSG("Word for DOS");
236f5736e95SDavid du Colombier 		return 0;
237f5736e95SDavid du Colombier 	case  28:
238f5736e95SDavid du Colombier 		DBG_MSG("Word 4 for Macintosh");
239f5736e95SDavid du Colombier 		bOldMacFile = TRUE;
240f5736e95SDavid du Colombier 		return 4;
241f5736e95SDavid du Colombier 	case  33:
242f5736e95SDavid du Colombier 		DBG_MSG("Word 1.x for Windows");
243f5736e95SDavid du Colombier 		return 1;
244f5736e95SDavid du Colombier 	case  35:
245f5736e95SDavid du Colombier 		DBG_MSG("Word 5 for Macintosh");
246f5736e95SDavid du Colombier 		bOldMacFile = TRUE;
247f5736e95SDavid du Colombier 		return 5;
248f5736e95SDavid du Colombier 	case  45:
249f5736e95SDavid du Colombier 		DBG_MSG("Word 2 for Windows");
250f5736e95SDavid du Colombier 		return 2;
251f5736e95SDavid du Colombier 	case 101:
252f5736e95SDavid du Colombier 	case 102:
253f5736e95SDavid du Colombier 		DBG_MSG("Word 6 for Windows");
254f5736e95SDavid du Colombier 		return 6;
255f5736e95SDavid du Colombier 	case 103:
256f5736e95SDavid du Colombier 	case 104:
257f5736e95SDavid du Colombier 		usChse = usGetWord(0x14, aucHeader);
258f5736e95SDavid du Colombier 		DBG_DEC(usChse);
259f5736e95SDavid du Colombier 		switch (usChse) {
260f5736e95SDavid du Colombier 		case 0:
261f5736e95SDavid du Colombier 			DBG_MSG("Word 7 for Win95");
262f5736e95SDavid du Colombier 			return 7;
263f5736e95SDavid du Colombier 		case 256:
264f5736e95SDavid du Colombier 			DBG_MSG("Word 6 for Macintosh");
265f5736e95SDavid du Colombier 			bOldMacFile = TRUE;
266f5736e95SDavid du Colombier 			return 6;
267f5736e95SDavid du Colombier 		default:
268f5736e95SDavid du Colombier 			DBG_FIXME();
269f5736e95SDavid du Colombier 			if ((int)ucGetByte(0x05, aucHeader) == 0xe0) {
270f5736e95SDavid du Colombier 				DBG_MSG("Word 7 for Win95");
271f5736e95SDavid du Colombier 				return 7;
272f5736e95SDavid du Colombier 			}
273f5736e95SDavid du Colombier 			DBG_MSG("Word 6 for Macintosh");
274f5736e95SDavid du Colombier 			bOldMacFile = TRUE;
275f5736e95SDavid du Colombier 			return 6;
276f5736e95SDavid du Colombier 		}
277f5736e95SDavid du Colombier 	default:
278f5736e95SDavid du Colombier 		usChse = usGetWord(0x14, aucHeader);
279f5736e95SDavid du Colombier 		DBG_DEC(usChse);
280f5736e95SDavid du Colombier 		if (usFib < 192) {
281f5736e95SDavid du Colombier 			/* Unknown or unsupported version of Word */
282f5736e95SDavid du Colombier 			DBG_DEC(usFib);
283f5736e95SDavid du Colombier 			return -1;
284f5736e95SDavid du Colombier 		}
285f5736e95SDavid du Colombier 		DBG_MSG_C(usChse != 256, "Word97 for Win95/98/NT");
286f5736e95SDavid du Colombier 		DBG_MSG_C(usChse == 256, "Word98 for Macintosh");
287f5736e95SDavid du Colombier 		return 8;
288f5736e95SDavid du Colombier 	}
289f5736e95SDavid du Colombier } /* end of iGetVersionNumber */
290f5736e95SDavid du Colombier 
291f5736e95SDavid du Colombier /*
292f5736e95SDavid du Colombier  * TRUE if the current file was made by Word version 6 or older on an
293f5736e95SDavid du Colombier  * Apple Macintosh, otherwise FALSE.
294f5736e95SDavid du Colombier  * This function hides the methode of how to find out from the rest of the
295f5736e95SDavid du Colombier  * program.
296f5736e95SDavid du Colombier  */
297f5736e95SDavid du Colombier BOOL
bIsOldMacFile(void)298f5736e95SDavid du Colombier bIsOldMacFile(void)
299f5736e95SDavid du Colombier {
300f5736e95SDavid du Colombier 	return bOldMacFile;
301f5736e95SDavid du Colombier } /* end of bIsOldMacFile */
302f5736e95SDavid du Colombier 
303f5736e95SDavid du Colombier /*
304f5736e95SDavid du Colombier  * iInitDocument - initialize a document
305f5736e95SDavid du Colombier  *
306f5736e95SDavid du Colombier  * Returns the version of Word that made the document or -1
307f5736e95SDavid du Colombier  */
308f5736e95SDavid du Colombier int
iInitDocument(FILE * pFile,long lFilesize)309f5736e95SDavid du Colombier iInitDocument(FILE *pFile, long lFilesize)
310f5736e95SDavid du Colombier {
311f5736e95SDavid du Colombier 	int	iGuess, iWordVersion;
312f5736e95SDavid du Colombier 
313f5736e95SDavid du Colombier 	iGuess = iGuessVersionNumber(pFile, lFilesize);
314f5736e95SDavid du Colombier 	switch (iGuess) {
315f5736e95SDavid du Colombier 	case 0:
316f5736e95SDavid du Colombier 		iWordVersion = iInitDocumentDOS(pFile, lFilesize);
317f5736e95SDavid du Colombier 		break;
318f5736e95SDavid du Colombier 	case 2:
319f5736e95SDavid du Colombier 		iWordVersion = iInitDocumentWIN(pFile, lFilesize);
320f5736e95SDavid du Colombier 		break;
321f5736e95SDavid du Colombier 	case 5:
322f5736e95SDavid du Colombier 		iWordVersion = iInitDocumentMAC(pFile, lFilesize);
323f5736e95SDavid du Colombier 		break;
324f5736e95SDavid du Colombier 	case 6:
325f5736e95SDavid du Colombier 		iWordVersion = iInitDocumentOLE(pFile, lFilesize);
326f5736e95SDavid du Colombier 		break;
327f5736e95SDavid du Colombier 	default:
328f5736e95SDavid du Colombier 		DBG_DEC(iGuess);
329f5736e95SDavid du Colombier 		iWordVersion = -1;
330f5736e95SDavid du Colombier 		break;
331f5736e95SDavid du Colombier 	}
332f5736e95SDavid du Colombier 	return iWordVersion;
333f5736e95SDavid du Colombier } /* end of iInitDocument */
334f5736e95SDavid du Colombier 
335f5736e95SDavid du Colombier /*
336f5736e95SDavid du Colombier  * vFreeDocument - free a document by free-ing its parts
337f5736e95SDavid du Colombier  */
338f5736e95SDavid du Colombier void
vFreeDocument(void)339f5736e95SDavid du Colombier vFreeDocument(void)
340f5736e95SDavid du Colombier {
341f5736e95SDavid du Colombier 	DBG_MSG("vFreeDocument");
342f5736e95SDavid du Colombier 
343f5736e95SDavid du Colombier 	/* Free the memory */
344f5736e95SDavid du Colombier 	vDestroyTextBlockList();
345f5736e95SDavid du Colombier 	vDestroyDataBlockList();
346f5736e95SDavid du Colombier 	vDestroyListInfoList();
347f5736e95SDavid du Colombier 	vDestroyRowInfoList();
348f5736e95SDavid du Colombier 	vDestroyStyleInfoList();
349f5736e95SDavid du Colombier 	vDestroyFontInfoList();
350f5736e95SDavid du Colombier 	vDestroyStylesheetList();
351f5736e95SDavid du Colombier 	vDestroyPictInfoList();
352*25b329d5SDavid du Colombier 	vDestroyDocumentInfoList();
353f5736e95SDavid du Colombier 	vDestroySectionInfoList();
354*25b329d5SDavid du Colombier 	vDestroyHdrFtrInfoList();
355f5736e95SDavid du Colombier 	vDestroyPropModList();
356f5736e95SDavid du Colombier 	vDestroyNotesInfoLists();
357f5736e95SDavid du Colombier 	vDestroyFontTable();
358f5736e95SDavid du Colombier 	vDestroySummaryInfo();
359f5736e95SDavid du Colombier } /* end of vFreeDocument */
360