Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * listlist.c
3
 * Copyright (C) 2002,2003 A.J. van Os; Released under GPL
4
 *
5
 * Description:
6
 * Build, read and destroy a list of Word list information
7
 *
8
 * Note:
9
 * This list only exists when the Word document is saved by Word 8 or later
10
 */
11
 
12
#include "antiword.h"
13
 
14
/*
15
 * Private structure to hide the way the information
16
 * is stored from the rest of the program
17
 */
18
typedef struct list_desc_tag {
19
	list_block_type		tInfo;
20
	ULONG			ulListID;
21
	USHORT			usIstd;
22
	UCHAR			ucListLevel;
23
	struct list_desc_tag	*pNext;
24
} list_desc_type;
25
 
26
typedef struct list_value_tag {
27
	USHORT			usValue;
28
	USHORT			usListIndex;
29
	UCHAR			ucListLevel;
30
	struct list_value_tag	*pNext;
31
} list_value_type;
32
 
33
/* Variables needed to describe the LFO list (pllfo) */
34
static ULONG		*aulLfoList = NULL;
35
static USHORT		usLfoLen = 0;
36
/* Variables needed to write the List Information List */
37
static list_desc_type	*pAnchor = NULL;
38
static list_desc_type	*pBlockLast = NULL;
39
/* Variable needed for numbering new lists */
40
static list_value_type	*pValues = NULL;
41
/* Variables needed for numbering old lists */
42
static int	iOldListSeqNumber = 0;
43
static USHORT	usOldListValue = 0;
44
 
45
 
46
/*
47
 * vDestroyListInfoList - destroy the List Information List
48
 */
49
void
50
vDestroyListInfoList(void)
51
{
52
	list_desc_type	*pCurr, *pNext;
53
	list_value_type	*pValueCurr, *pValueNext;
54
 
55
	DBG_MSG("vDestroyListInfoList");
56
 
57
	/* Free the LFO list */
58
	usLfoLen = 0;
59
	aulLfoList = xfree(aulLfoList);
60
 
61
	/* Free the List Information List */
62
	pCurr = pAnchor;
63
	while (pCurr != NULL) {
64
		pNext = pCurr->pNext;
65
		pCurr = xfree(pCurr);
66
		pCurr = pNext;
67
	}
68
	pAnchor = NULL;
69
	/* Reset all control variables */
70
	pBlockLast = NULL;
71
 
72
	/* Free the values list */
73
	pValueCurr = pValues;
74
	while (pValueCurr != NULL) {
75
		pValueNext = pValueCurr->pNext;
76
		pValueCurr = xfree(pValueCurr);
77
		pValueCurr = pValueNext;
78
	}
79
	pValues = NULL;
80
	/* Reset the values for the old lists */
81
	iOldListSeqNumber = 0;
82
	usOldListValue = 0;
83
} /* end of vDestroyListInfoList */
84
 
85
/*
86
 * vBuildLfoList - build the LFO list (pllfo)
87
 */
88
void
89
vBuildLfoList(const UCHAR *aucBuffer, size_t tBufLen)
90
{
91
	size_t	tRecords;
92
	int	iIndex;
93
 
94
	fail(aucBuffer == NULL);
95
 
96
	if (tBufLen < 4) {
97
		return;
98
	}
99
	tRecords = (size_t)ulGetLong(0, aucBuffer);
100
	NO_DBG_DEC(tRecords);
101
	if (4 + 16 * tRecords > tBufLen || tRecords >= 0x7fff) {
102
		/* Just a sanity check */
103
		DBG_DEC(tRecords);
104
		DBG_DEC(4 + 16 * tRecords);
105
		DBG_DEC(tBufLen);
106
		return;
107
	}
108
	aulLfoList = xcalloc(tRecords, sizeof(ULONG));
109
	for (iIndex = 0; iIndex < (int)tRecords; iIndex++) {
110
		aulLfoList[iIndex] = ulGetLong(4 + 16 * iIndex, aucBuffer);
111
		NO_DBG_HEX(aulLfoList[iIndex]);
112
	}
113
	usLfoLen = (USHORT)tRecords;
114
} /* end of vBuildLfoList */
115
 
116
/*
117
 * vAdd2ListInfoList - add an element to the List Information list
118
 */
119
void
120
vAdd2ListInfoList(ULONG ulListID, USHORT usIstd, UCHAR ucListLevel,
121
	const list_block_type *pListBlock)
122
{
123
	list_desc_type	*pListMember;
124
 
125
	fail(pListBlock == NULL);
126
 
127
	NO_DBG_HEX(ulListID);
128
	NO_DBG_DEC(usIstd);
129
	NO_DBG_DEC(ucListLevel);
130
	NO_DBG_DEC(pListBlock->ulStartAt);
131
	NO_DBG_DEC(pListBlock->bNoRestart);
132
	NO_DBG_DEC(pListBlock->sLeftIndent);
133
	NO_DBG_HEX(pListBlock->ucNFC);
134
	NO_DBG_HEX(pListBlock->usListChar);
135
 
136
	/* Create list member */
137
	pListMember = xmalloc(sizeof(list_desc_type));
138
	/* Fill the list member */
139
	pListMember->tInfo = *pListBlock;
140
	pListMember->ulListID = ulListID;
141
	pListMember->usIstd = usIstd;
142
	pListMember->ucListLevel = ucListLevel;
143
	pListMember->pNext = NULL;
144
	/* Correct the values where needed */
145
	if (pListMember->tInfo.ulStartAt > 0xffff) {
146
		DBG_DEC(pListMember->tInfo.ulStartAt);
147
		pListMember->tInfo.ulStartAt = 1;
148
	}
149
	/* Add the new member to the list */
150
	if (pAnchor == NULL) {
151
		pAnchor = pListMember;
152
	} else {
153
		fail(pBlockLast == NULL);
154
		pBlockLast->pNext = pListMember;
155
	}
156
	pBlockLast = pListMember;
157
} /* end of vAdd2ListInfoList */
158
 
159
/*
160
 * Get a matching record from the List Information List
161
 *
162
 * Returns NULL if no matching records is found
163
 */
164
const list_block_type *
165
pGetListInfo(USHORT usListIndex, UCHAR ucListLevel)
166
{
167
	list_desc_type	*pCurr;
168
	list_block_type	*pNearMatch;
169
	ULONG	ulListID;
170
 
171
	if (usListIndex == 0) {
172
		return NULL;
173
	}
174
	if (usListIndex - 1 >= usLfoLen || ucListLevel > 8) {
175
		DBG_DEC(usListIndex);
176
		DBG_DEC(ucListLevel);
177
		return NULL;
178
	}
179
	fail(aulLfoList == NULL);
180
	ulListID = aulLfoList[usListIndex - 1];
181
	NO_DBG_HEX(ulListID);
182
 
183
	pNearMatch = NULL;
184
	for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
185
		if (pCurr->ulListID != ulListID) {
186
			/* No match */
187
			continue;
188
		}
189
		if (pCurr->ucListLevel == ucListLevel) {
190
			/* Exact match */
191
			return &pCurr->tInfo;
192
		}
193
		if (pCurr->ucListLevel == 0) {
194
			/* Near match */
195
			pNearMatch = &pCurr->tInfo;
196
		}
197
	}
198
	/* No exact match, use a near match if any */
199
	return pNearMatch;
200
} /* end of pGetListInfo */
201
 
202
/*
203
 * Get a matching record from the List Information List
204
 *
205
 * Returns NULL if no matching records is found
206
 */
207
const list_block_type *
208
pGetListInfoByIstd(USHORT usIstd)
209
{
210
	list_desc_type	*pCurr;
211
 
212
	if (usIstd == ISTD_INVALID || usIstd == STI_NIL || usIstd == STI_USER) {
213
		return NULL;
214
	}
215
 
216
	for (pCurr = pAnchor; pCurr != NULL; pCurr = pCurr->pNext) {
217
		if (pCurr->usIstd == usIstd) {
218
			return &pCurr->tInfo;
219
		}
220
	}
221
	return NULL;
222
} /* end of pGetListInfoByIstd */
223
 
224
/*
225
 * vRestartListValues - reset the less significant list levels
226
 */
227
static void
228
vRestartListValues(USHORT usListIndex, UCHAR ucListLevel)
229
{
230
	list_value_type	*pPrev, *pCurr, *pNext;
231
	int		iCounter;
232
 
233
	iCounter = 0;
234
	pPrev = NULL;
235
	pCurr = pValues;
236
 
237
	while (pCurr != NULL) {
238
		if (pCurr->usListIndex != usListIndex ||
239
		    pCurr->ucListLevel <= ucListLevel) {
240
			pPrev = pCurr;
241
			pCurr = pCurr->pNext;
242
			continue;
243
		}
244
		/* Reset the level by deleting the record */
245
		pNext = pCurr->pNext;
246
		if (pPrev == NULL) {
247
			pValues = pNext;
248
		} else {
249
			pPrev->pNext = pNext;
250
		}
251
		DBG_DEC(pCurr->usListIndex);
252
		DBG_DEC(pCurr->ucListLevel);
253
		pCurr = xfree(pCurr);
254
		pCurr = pNext;
255
		iCounter++;
256
	}
257
	DBG_DEC_C(iCounter > 0, iCounter);
258
} /* end of vRestartListValues */
259
 
260
/*
261
 * usGetListValue - Get the current value of the given list
262
 *
263
 * Returns the value of the given list
264
 */
265
USHORT
266
usGetListValue(int iListSeqNumber, int iWordVersion,
267
	const style_block_type *pStyle)
268
{
269
	list_value_type	*pCurr;
270
	USHORT		usValue;
271
 
272
	fail(iListSeqNumber < 0);
273
	fail(iListSeqNumber < iOldListSeqNumber);
274
	fail(iWordVersion < 0);
275
	fail(pStyle == NULL);
276
 
277
	if (iListSeqNumber <= 0) {
278
		return 0;
279
	}
280
 
281
	if (iWordVersion < 8) {
282
		/* Old style list */
283
		if (iListSeqNumber == iOldListSeqNumber ||
284
		    (iListSeqNumber == iOldListSeqNumber + 1 &&
285
		     eGetNumType(pStyle->ucNumLevel) == level_type_sequence)) {
286
			if (!pStyle->bNumPause) {
287
				usOldListValue++;
288
			}
289
		} else {
290
			usOldListValue = pStyle->usStartAt;
291
		}
292
		iOldListSeqNumber = iListSeqNumber;
293
		return usOldListValue;
294
	}
295
 
296
	/* New style list */
297
	if (pStyle->usListIndex == 0 ||
298
	    pStyle->usListIndex - 1 >= usLfoLen ||
299
	    pStyle->ucListLevel > 8) {
300
		/* Out of range; no need to search */
301
		return 0;
302
	}
303
 
304
	for (pCurr = pValues; pCurr != NULL; pCurr = pCurr->pNext) {
305
		if (pCurr->usListIndex == pStyle->usListIndex &&
306
		    pCurr->ucListLevel == pStyle->ucListLevel) {
307
			/* Record found; increment and return the value */
308
			pCurr->usValue++;
309
			usValue = pCurr->usValue;
310
			if (!pStyle->bNoRestart) {
311
				vRestartListValues(pStyle->usListIndex,
312
						pStyle->ucListLevel);
313
			}
314
			return usValue;
315
		}
316
	}
317
 
318
	/* Record not found; create it and add it to the front of the list */
319
	pCurr = xmalloc(sizeof(list_value_type));
320
	pCurr->usValue = pStyle->usStartAt;
321
	pCurr->usListIndex = pStyle->usListIndex;
322
	pCurr->ucListLevel = pStyle->ucListLevel;
323
	pCurr->pNext = pValues;
324
	pValues = pCurr;
325
	usValue = pCurr->usValue;
326
	if (!pStyle->bNoRestart) {
327
		vRestartListValues(pStyle->usListIndex, pStyle->ucListLevel);
328
	}
329
	return usValue;
330
} /* end of usGetListValue */