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
 * prop8.c
3
 * Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
4
 *
5
 * Description:
6
 * Read the property information from a MS Word 8, 9,10 or 11 file
7
 *
8
 * Word  8 is better known as Word 97 or as Word 98 for Mac
9
 * Word  9 is better known as Word 2000 or as Word 2001 for Mac
10
 * Word 10 is better known as Word 2002 or as Word XP
11
 * Word 11 is better known as Word 2003
12
 */
13
 
14
#include <stdlib.h>
15
#include <string.h>
16
#include "antiword.h"
17
 
18
#define DEFAULT_LISTCHAR	0x002e	/* A full stop */
19
 
20
 
21
/*
22
 * iGet8InfoLength - the length of the information for Word 8/9/10/11 files
23
 */
24
static int
25
iGet8InfoLength(int iByteNbr, const UCHAR *aucGrpprl)
26
{
27
	int	iTmp, iDel, iAdd;
28
	USHORT	usOpCode;
29
 
30
	usOpCode = usGetWord(iByteNbr, aucGrpprl);
31
 
32
	switch (usOpCode & 0xe000) {
33
	case 0x0000: case 0x2000:
34
		return 3;
35
	case 0x4000: case 0x8000: case 0xa000:
36
		return 4;
37
	case 0xe000:
38
		return 5;
39
	case 0x6000:
40
		return 6;
41
	case 0xc000:
42
		iTmp = (int)ucGetByte(iByteNbr + 2, aucGrpprl);
43
		if (usOpCode == 0xc615 && iTmp == 255) {
44
			iDel = (int)ucGetByte(iByteNbr + 3, aucGrpprl);
45
			iAdd = (int)ucGetByte(
46
					iByteNbr + 4 + iDel * 4, aucGrpprl);
47
			iTmp = 2 + iDel * 4 + iAdd * 3;
48
		}
49
		return 3 + iTmp;
50
	default:
51
		DBG_HEX(usOpCode);
52
		DBG_FIXME();
53
		return 1;
54
	}
55
} /* end of iGet8InfoLength */
56
 
57
/*
58
 * aucFillInfoBuffer - fill the information buffer
59
 *
60
 * Returns the information buffer when successful, otherwise NULL
61
 */
62
static UCHAR *
63
aucFillInfoBuffer(FILE *pFile, const pps_type *pTable,
64
	const ULONG *aulBBD, size_t tBBDLen,
65
	const ULONG *aulSBD, size_t tSBDLen,
66
	ULONG ulBeginInfo, size_t tInfoLen)
67
{
68
	const ULONG	*aulBlockDepot;
69
	UCHAR	*aucBuffer;
70
	size_t	tBlockDepotLen, tBlockSize;
71
 
72
	fail(pFile == NULL || pTable == NULL);
73
	fail(aulBBD == NULL || aulSBD == NULL);
74
	fail(tInfoLen == 0);
75
 
76
	NO_DBG_DEC(pTable->ulSB);
77
	NO_DBG_HEX(pTable->ulSize);
78
	if (pTable->ulSize == 0) {
79
		DBG_MSG("No information");
80
		return NULL;
81
	}
82
 
83
	if (pTable->ulSize < MIN_SIZE_FOR_BBD_USE) {
84
		/* Use the Small Block Depot */
85
		aulBlockDepot = aulSBD;
86
		tBlockDepotLen = tSBDLen;
87
		tBlockSize = SMALL_BLOCK_SIZE;
88
	} else {
89
		/* Use the Big Block Depot */
90
		aulBlockDepot = aulBBD;
91
		tBlockDepotLen = tBBDLen;
92
		tBlockSize = BIG_BLOCK_SIZE;
93
	}
94
	aucBuffer = xmalloc(tInfoLen);
95
	if (!bReadBuffer(pFile, pTable->ulSB,
96
			aulBlockDepot, tBlockDepotLen, tBlockSize,
97
			aucBuffer, ulBeginInfo, tInfoLen)) {
98
		aucBuffer = xfree(aucBuffer);
99
		return NULL;
100
	}
101
	return aucBuffer;
102
} /* end of aucFillInfoBuffer */
103
 
104
/*
105
 * Build the lists with Document Property Information for Word 8/9/10/11 files
106
 */
107
void
108
vGet8DopInfo(FILE *pFile, const pps_type *pTable,
109
	const ULONG *aulBBD, size_t tBBDLen,
110
	const ULONG *aulSBD, size_t tSBDLen,
111
	const UCHAR *aucHeader)
112
{
113
	document_block_type	tDocument;
114
	UCHAR	*aucBuffer;
115
	ULONG	ulBeginDocpInfo, ulTmp;
116
	size_t	tDocpInfoLen;
117
	USHORT	usTmp;
118
 
119
	fail(pFile == NULL || pTable == NULL || aucHeader == NULL);
120
	fail(aulBBD == NULL || aulSBD == NULL);
121
 
122
	ulBeginDocpInfo = ulGetLong(0x192, aucHeader); /* fcDop */
123
	NO_DBG_HEX(ulBeginSectInfo);
124
	tDocpInfoLen = (size_t)ulGetLong(0x196, aucHeader); /* lcbDop */
125
	NO_DBG_DEC(tSectInfoLen);
126
	if (tDocpInfoLen < 28) {
127
		DBG_MSG("No Document information");
128
		return;
129
	}
130
 
131
	aucBuffer = aucFillInfoBuffer(pFile, pTable,
132
			aulBBD, tBBDLen, aulSBD, tSBDLen,
133
			ulBeginDocpInfo, tDocpInfoLen);
134
	if (aucBuffer == NULL) {
135
		return;
136
	}
137
 
138
	usTmp = usGetWord(0x00, aucBuffer);
139
	tDocument.ucHdrFtrSpecification = (UCHAR)(usTmp >> 8); /* grpfIhdt */
140
	tDocument.usDefaultTabWidth = usGetWord(0x0a, aucBuffer); /* dxaTab */
141
	ulTmp = ulGetLong(0x14, aucBuffer); /* dttmCreated */
142
	tDocument.tCreateDate = tConvertDTTM(ulTmp);
143
	ulTmp = ulGetLong(0x18, aucBuffer); /* dttmRevised */
144
	tDocument.tRevisedDate = tConvertDTTM(ulTmp);
145
	vCreateDocumentInfoList(&tDocument);
146
 
147
	aucBuffer = xfree(aucBuffer);
148
} /* end of vGet8DopInfo */
149
 
150
/*
151
 * Fill the section information block with information
152
 * from a Word 8/9/10/11 file.
153
 */
154
static void
155
vGet8SectionInfo(const UCHAR *aucGrpprl, size_t tBytes,
156
		section_block_type *pSection)
157
{
158
	UINT	uiIndex;
159
	int	iFodoOff, iInfoLen, iSize, iTmp;
160
	USHORT	usCcol;
161
	UCHAR	ucTmp;
162
 
163
	fail(aucGrpprl == NULL || pSection == NULL);
164
 
165
	iFodoOff = 0;
166
	while (tBytes >= (size_t)iFodoOff + 2) {
167
		iInfoLen = 0;
168
		switch (usGetWord(iFodoOff, aucGrpprl)) {
169
		case 0x3009:	/* bkc */
170
			ucTmp = ucGetByte(iFodoOff + 2, aucGrpprl);
171
			DBG_DEC(ucTmp);
172
			pSection->bNewPage = ucTmp != 0 && ucTmp != 1;
173
			break;
174
		case 0x3014:	/* grpfIhdt */
175
			pSection->ucHdrFtrSpecification =
176
					ucGetByte(iFodoOff + 2, aucGrpprl);
177
			break;
178
		case 0x500b:	/* ccolM1 */
179
			usCcol = 1 + usGetWord(iFodoOff + 2, aucGrpprl);
180
			DBG_DEC(usCcol);
181
			break;
182
		case 0xd202:	/* olstAnm */
183
			iSize = (int)ucGetByte(iFodoOff + 2, aucGrpprl);
184
			DBG_DEC_C(iSize != 212, iSize);
185
			for (uiIndex = 0, iTmp = iFodoOff + 3;
186
			     uiIndex < 9 && iTmp < iFodoOff + 3 + iSize - 15;
187
			     uiIndex++, iTmp += 16) {
188
				pSection->aucNFC[uiIndex] =
189
						ucGetByte(iTmp, aucGrpprl);
190
				DBG_DEC(pSection->aucNFC[uiIndex]);
191
				ucTmp = ucGetByte(iTmp + 3, aucGrpprl);
192
				DBG_HEX(ucTmp);
193
				if ((ucTmp & BIT(2)) != 0) {
194
					pSection->usNeedPrevLvl |=
195
							(USHORT)BIT(uiIndex);
196
				}
197
				if ((ucTmp & BIT(3)) != 0) {
198
					pSection->usHangingIndent |=
199
							(USHORT)BIT(uiIndex);
200
				}
201
			}
202
			DBG_HEX(pSection->usNeedPrevLvl);
203
			DBG_HEX(pSection->usHangingIndent);
204
			break;
205
		default:
206
			break;
207
		}
208
		if (iInfoLen <= 0) {
209
			iInfoLen = iGet8InfoLength(iFodoOff, aucGrpprl);
210
			fail(iInfoLen <= 0);
211
		}
212
		iFodoOff += iInfoLen;
213
	}
214
} /* end of vGet8SectionInfo */
215
 
216
/*
217
 * Build the lists with Section Property Information for Word 8/9/10/11 files
218
 */
219
void
220
vGet8SepInfo(FILE *pFile, const pps_info_type *pPPS,
221
	const ULONG *aulBBD, size_t tBBDLen,
222
	const ULONG *aulSBD, size_t tSBDLen,
223
	const UCHAR *aucHeader)
224
{
225
	section_block_type	tSection;
226
	ULONG	*aulSectPage, *aulCharPos;
227
	UCHAR	*aucBuffer, *aucFpage;
228
	ULONG	ulBeginOfText, ulTextOffset, ulBeginSectInfo;
229
	size_t	tSectInfoLen, tIndex, tOffset, tLen, tBytes;
230
	UCHAR	aucTmp[2];
231
 
232
	fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
233
	fail(aulBBD == NULL || aulSBD == NULL);
234
 
235
	ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
236
	NO_DBG_HEX(ulBeginOfText);
237
	ulBeginSectInfo = ulGetLong(0xca, aucHeader); /* fcPlcfsed */
238
	NO_DBG_HEX(ulBeginSectInfo);
239
	tSectInfoLen = (size_t)ulGetLong(0xce, aucHeader); /* lcbPlcfsed */
240
	NO_DBG_DEC(tSectInfoLen);
241
	if (tSectInfoLen < 4) {
242
		DBG_DEC(tSectInfoLen);
243
		return;
244
	}
245
 
246
	aucBuffer = aucFillInfoBuffer(pFile, &pPPS->tTable,
247
			aulBBD, tBBDLen, aulSBD, tSBDLen,
248
			ulBeginSectInfo, tSectInfoLen);
249
	if (aucBuffer == NULL) {
250
		return;
251
	}
252
	NO_DBG_PRINT_BLOCK(aucBuffer, tSectInfoLen);
253
 
254
	/* Read the Section Descriptors */
255
	tLen = (tSectInfoLen - 4) / 16;
256
	/* Save the section offsets */
257
	aulCharPos = xcalloc(tLen, sizeof(ULONG));
258
	for (tIndex = 0, tOffset = 0;
259
	     tIndex < tLen;
260
	     tIndex++, tOffset += 4) {
261
		ulTextOffset = ulGetLong(tOffset, aucBuffer);
262
		NO_DBG_HEX(ulTextOffset);
263
		aulCharPos[tIndex] = ulBeginOfText + ulTextOffset;
264
		NO_DBG_HEX(aulCharPos[tIndex]);
265
	}
266
	/* Save the Sepx offsets */
267
	aulSectPage = xcalloc(tLen, sizeof(ULONG));
268
	for (tIndex = 0, tOffset = (tLen + 1) * 4;
269
	     tIndex < tLen;
270
	     tIndex++, tOffset += 12) {
271
		 aulSectPage[tIndex] = ulGetLong(tOffset + 2, aucBuffer);
272
		 NO_DBG_HEX(aulSectPage[tIndex]); /* fcSepx */
273
	}
274
	aucBuffer = xfree(aucBuffer);
275
 
276
	/* Read the Section Properties */
277
	for (tIndex = 0; tIndex < tLen; tIndex++) {
278
		if (aulSectPage[tIndex] == FC_INVALID) {
279
			vDefault2SectionInfoList(aulCharPos[tIndex]);
280
			continue;
281
		}
282
		/* Get the number of bytes to read */
283
		if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB,
284
				aulBBD, tBBDLen, BIG_BLOCK_SIZE,
285
				aucTmp, aulSectPage[tIndex], 2)) {
286
			continue;
287
		}
288
		tBytes = 2 + (size_t)usGetWord(0, aucTmp);
289
		NO_DBG_DEC(tBytes);
290
		/* Read the bytes */
291
		aucFpage = xmalloc(tBytes);
292
		if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB,
293
				aulBBD, tBBDLen, BIG_BLOCK_SIZE,
294
				aucFpage, aulSectPage[tIndex], tBytes)) {
295
			aucFpage = xfree(aucFpage);
296
			continue;
297
		}
298
		NO_DBG_PRINT_BLOCK(aucFpage, tBytes);
299
		/* Process the bytes */
300
		vGetDefaultSection(&tSection);
301
		vGet8SectionInfo(aucFpage + 2, tBytes - 2, &tSection);
302
		vAdd2SectionInfoList(&tSection, aulCharPos[tIndex]);
303
		aucFpage = xfree(aucFpage);
304
	}
305
	aulCharPos = xfree(aulCharPos);
306
	aulSectPage = xfree(aulSectPage);
307
} /* end of vGet8SepInfo */
308
 
309
/*
310
 * Build the list with Header/Footer Information for Word 8/9/10/11 files
311
 */
312
void
313
vGet8HdrFtrInfo(FILE *pFile, const pps_type *pTable,
314
	const ULONG *aulBBD, size_t tBBDLen,
315
	const ULONG *aulSBD, size_t tSBDLen,
316
	const UCHAR *aucHeader)
317
{
318
	ULONG	*aulCharPos;
319
	UCHAR	*aucBuffer;
320
	ULONG	ulHdrFtrOffset, ulBeginHdrFtrInfo;
321
	size_t	tHdrFtrInfoLen, tIndex, tOffset, tLen;
322
 
323
	fail(pFile == NULL || pTable == NULL || aucHeader == NULL);
324
	fail(aulBBD == NULL || aulSBD == NULL);
325
 
326
	ulBeginHdrFtrInfo = ulGetLong(0xf2, aucHeader); /* fcPlcfhdd */
327
	NO_DBG_HEX(ulBeginHdrFtrInfo);
328
	tHdrFtrInfoLen = (size_t)ulGetLong(0xf6, aucHeader); /* lcbPlcfhdd */
329
	NO_DBG_DEC(tHdrFtrInfoLen);
330
	if (tHdrFtrInfoLen < 8) {
331
		DBG_DEC_C(tHdrFtrInfoLen != 0, tHdrFtrInfoLen);
332
		return;
333
	}
334
 
335
	aucBuffer = aucFillInfoBuffer(pFile, pTable,
336
			aulBBD, tBBDLen, aulSBD, tSBDLen,
337
			ulBeginHdrFtrInfo, tHdrFtrInfoLen);
338
	if (aucBuffer == NULL) {
339
		return;
340
	}
341
	NO_DBG_PRINT_BLOCK(aucBuffer, tHdrFtrInfoLen);
342
 
343
	tLen = tHdrFtrInfoLen / 4 - 1;
344
	DBG_DEC_C(tLen % 12 != 1 && tLen % 12 != 7, tLen);
345
	/* Save the header/footer offsets */
346
	aulCharPos = xcalloc(tLen, sizeof(ULONG));
347
	for (tIndex = 0, tOffset = 0;
348
	     tIndex < tLen;
349
	     tIndex++, tOffset += 4) {
350
		ulHdrFtrOffset = ulGetLong(tOffset, aucBuffer);
351
		NO_DBG_HEX(ulHdrFtrOffset);
352
		aulCharPos[tIndex] = ulHdrFtrOffset2CharPos(ulHdrFtrOffset);
353
		NO_DBG_HEX(aulCharPos[tIndex]);
354
	}
355
	vCreat8HdrFtrInfoList(aulCharPos, tLen);
356
	/* Clean up and leave */
357
	aulCharPos = xfree(aulCharPos);
358
	aucBuffer = xfree(aucBuffer);
359
} /* end of vGet8HdrFtrInfo */
360
 
361
/*
362
 * Translate the rowinfo to a member of the row_info enumeration
363
 */
364
row_info_enum
365
eGet8RowInfo(int iFodo,
366
	const UCHAR *aucGrpprl, int iBytes, row_block_type *pRow)
367
{
368
	int	iFodoOff, iInfoLen;
369
	int	iIndex, iSize, iCol;
370
	int	iPosCurr, iPosPrev;
371
	USHORT	usTmp;
372
	BOOL	bFound2416_0, bFound2416_1, bFound2417_0, bFound2417_1;
373
	BOOL	bFound244b_0, bFound244b_1, bFound244c_0, bFound244c_1;
374
	BOOL	bFoundd608;
375
 
376
	fail(iFodo < 0 || aucGrpprl == NULL || pRow == NULL);
377
 
378
	iFodoOff = 0;
379
	bFound2416_0 = FALSE;
380
	bFound2416_1 = FALSE;
381
	bFound2417_0 = FALSE;
382
	bFound2417_1 = FALSE;
383
	bFound244b_0 = FALSE;
384
	bFound244b_1 = FALSE;
385
	bFound244c_0 = FALSE;
386
	bFound244c_1 = FALSE;
387
	bFoundd608 = FALSE;
388
	while (iBytes >= iFodoOff + 2) {
389
		iInfoLen = 0;
390
		switch (usGetWord(iFodo + iFodoOff, aucGrpprl)) {
391
		case 0x2416:	/* fInTable */
392
			if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
393
				bFound2416_1 = TRUE;
394
			} else {
395
				bFound2416_0 = TRUE;
396
			}
397
			break;
398
		case 0x2417:	/* fTtp */
399
			if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
400
				bFound2417_1 = TRUE;
401
			} else {
402
				bFound2417_0 = TRUE;
403
			}
404
			break;
405
		case 0x244b:	/* sub-table fInTable */
406
			if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
407
				bFound244b_1 = TRUE;
408
			} else {
409
				bFound244b_0 = TRUE;
410
			}
411
			break;
412
		case 0x244c:	/* sub-table fTtp */
413
			if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
414
				bFound244c_1 = TRUE;
415
			} else {
416
				bFound244c_0 = TRUE;
417
			}
418
			break;
419
		case 0x6424:	/* brcTop */
420
			usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
421
			usTmp &= 0xff00;
422
			NO_DBG_DEC(usTmp >> 8);
423
			if (usTmp == 0) {
424
				pRow->ucBorderInfo &= ~TABLE_BORDER_TOP;
425
			} else {
426
				pRow->ucBorderInfo |= TABLE_BORDER_TOP;
427
			}
428
			break;
429
		case 0x6425:	/* brcLeft */
430
			usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
431
			usTmp &= 0xff00;
432
			NO_DBG_DEC(usTmp >> 8);
433
			if (usTmp == 0) {
434
				pRow->ucBorderInfo &= ~TABLE_BORDER_LEFT;
435
			} else {
436
				pRow->ucBorderInfo |= TABLE_BORDER_LEFT;
437
			}
438
			break;
439
		case 0x6426:	/* brcBottom */
440
			usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
441
			usTmp &= 0xff00;
442
			NO_DBG_DEC(usTmp >> 8);
443
			if (usTmp == 0) {
444
				pRow->ucBorderInfo &= ~TABLE_BORDER_BOTTOM;
445
			} else {
446
				pRow->ucBorderInfo |= TABLE_BORDER_BOTTOM;
447
			}
448
			break;
449
		case 0x6427:	/* brcRight */
450
			usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
451
			usTmp &= 0xff00;
452
			NO_DBG_DEC(usTmp >> 8);
453
			if (usTmp == 0) {
454
				pRow->ucBorderInfo &= ~TABLE_BORDER_RIGHT;
455
			} else {
456
				pRow->ucBorderInfo |= TABLE_BORDER_RIGHT;
457
			}
458
			break;
459
		case 0xd606:	/* cDefTable10 */
460
			DBG_MSG("0xd606: sprmTDefTable10");
461
			iSize = (int)usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
462
			DBG_DEC(iSize);
463
			break;
464
		case 0xd608:	/* cDefTable */
465
			iSize = (int)usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
466
			if (iSize < 6 || iBytes < iFodoOff + 8) {
467
				DBG_DEC(iSize);
468
				DBG_DEC(iFodoOff);
469
				iInfoLen = 2;
470
				break;
471
			}
472
			iCol = (int)ucGetByte(iFodo + iFodoOff + 4, aucGrpprl);
473
			if (iCol < 1 ||
474
			    iBytes < iFodoOff + 4 + (iCol + 1) * 2) {
475
				DBG_DEC(iCol);
476
				DBG_DEC(iFodoOff);
477
				iInfoLen = 2;
478
				break;
479
			}
480
			if (iCol >= (int)elementsof(pRow->asColumnWidth)) {
481
				DBG_DEC(iCol);
482
				werr(1, "The number of columns is corrupt");
483
			}
484
			pRow->ucNumberOfColumns = (UCHAR)iCol;
485
			iPosPrev = (int)(short)usGetWord(
486
					iFodo + iFodoOff + 5,
487
					aucGrpprl);
488
			for (iIndex = 0; iIndex < iCol; iIndex++) {
489
				iPosCurr = (int)(short)usGetWord(
490
					iFodo + iFodoOff + 7 + iIndex * 2,
491
					aucGrpprl);
492
				pRow->asColumnWidth[iIndex] =
493
						(short)(iPosCurr - iPosPrev);
494
				iPosPrev = iPosCurr;
495
			}
496
			bFoundd608 = TRUE;
497
			break;
498
		default:
499
			break;
500
		}
501
		if (iInfoLen <= 0) {
502
			iInfoLen =
503
				iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
504
			fail(iInfoLen <= 0);
505
		}
506
		iFodoOff += iInfoLen;
507
	}
508
 
509
	if (bFound2417_1 && bFoundd608) {
510
		return found_end_of_row;
511
	}
512
	if (bFound2417_0 && !bFoundd608) {
513
		return found_not_end_of_row;
514
	}
515
	if (bFound2416_1 || bFound244b_1) {
516
		return found_a_cell;
517
	}
518
	if (bFound2416_0 || bFound244b_0) {
519
		return found_not_a_cell;
520
	}
521
	return found_nothing;
522
} /* end of eGet8RowInfo */
523
 
524
/*
525
 * Fill the style information block with information
526
 * from a Word 8/9/10/11 file.
527
 */
528
void
529
vGet8StyleInfo(int iFodo,
530
	const UCHAR *aucGrpprl, int iBytes, style_block_type *pStyle)
531
{
532
	list_block_type	tList6;
533
	const list_block_type	*pList;
534
	int	iFodoOff, iInfoLen;
535
	int	iTmp, iDel, iAdd, iBefore;
536
	USHORT	usOpCode, usTmp;
537
	short	sTmp;
538
 
539
	fail(iFodo < 0 || aucGrpprl == NULL || pStyle == NULL);
540
 
541
	NO_DBG_DEC_C(pStyle->usListIndex != 0, pStyle->usIstd);
542
	NO_DBG_DEC_C(pStyle->usListIndex != 0, pStyle->usListIndex);
543
 
544
	(void)memset(&tList6, 0, sizeof(tList6));
545
 
546
	iFodoOff = 0;
547
	while (iBytes >= iFodoOff + 2) {
548
		iInfoLen = 0;
549
		usOpCode = usGetWord(iFodo + iFodoOff, aucGrpprl);
550
		switch (usOpCode) {
551
		case 0x2403:	/* jc */
552
			pStyle->ucAlignment = ucGetByte(
553
					iFodo + iFodoOff + 2, aucGrpprl);
554
			break;
555
		case 0x260a:	/* ilvl */
556
			pStyle->ucListLevel =
557
				ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
558
			NO_DBG_DEC(pStyle->ucListLevel);
559
			pStyle->ucNumLevel = pStyle->ucListLevel;
560
			break;
561
		case 0x4600:	/* istd */
562
			usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
563
			NO_DBG_DEC(usTmp);
564
			break;
565
		case 0x460b:	/* ilfo */
566
			pStyle->usListIndex =
567
				usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
568
			NO_DBG_DEC(pStyle->usListIndex);
569
			break;
570
		case 0x4610: /* Nest dxaLeft */
571
			sTmp = (short)usGetWord(
572
					iFodo + iFodoOff + 2, aucGrpprl);
573
			pStyle->sLeftIndent += sTmp;
574
			if (pStyle->sLeftIndent < 0) {
575
				pStyle->sLeftIndent = 0;
576
			}
577
			DBG_DEC(sTmp);
578
			DBG_DEC(pStyle->sLeftIndent);
579
			break;
580
		case 0xc60d:	/* ChgTabsPapx */
581
		case 0xc615:	/* ChgTabs */
582
			iTmp = (int)ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
583
			if (iTmp < 2) {
584
				iInfoLen = 1;
585
				break;
586
			}
587
			NO_DBG_DEC(iTmp);
588
			iDel = (int)ucGetByte(iFodo + iFodoOff + 3, aucGrpprl);
589
			if (iTmp < 2 + 2 * iDel) {
590
				iInfoLen = 1;
591
				break;
592
			}
593
			NO_DBG_DEC(iDel);
594
			iAdd = (int)ucGetByte(
595
				iFodo + iFodoOff + 4 + 2 * iDel, aucGrpprl);
596
			if (iTmp < 2 + 2 * iDel + 2 * iAdd) {
597
				iInfoLen = 1;
598
				break;
599
			}
600
			NO_DBG_DEC(iAdd);
601
			break;
602
		case 0x840e:	/* dxaRight */
603
			pStyle->sRightIndent = (short)usGetWord(
604
					iFodo + iFodoOff + 2, aucGrpprl);
605
			NO_DBG_DEC(pStyle->sRightIndent);
606
			break;
607
		case 0x840f:	/* dxaLeft */
608
			pStyle->sLeftIndent = (short)usGetWord(
609
					iFodo + iFodoOff + 2, aucGrpprl);
610
			NO_DBG_DEC(pStyle->sLeftIndent);
611
			break;
612
		case 0x8411:	/* dxaLeft1 */
613
			pStyle->sLeftIndent1 = (short)usGetWord(
614
					iFodo + iFodoOff + 2, aucGrpprl);
615
			NO_DBG_DEC(pStyle->sLeftIndent1);
616
			break;
617
		case 0xa413:	/* dyaBefore */
618
			pStyle->usBeforeIndent = usGetWord(
619
					iFodo + iFodoOff + 2, aucGrpprl);
620
			NO_DBG_DEC(pStyle->usBeforeIndent);
621
			break;
622
		case 0xa414:	/* dyaAfter */
623
			pStyle->usAfterIndent = usGetWord(
624
					iFodo + iFodoOff + 2, aucGrpprl);
625
			NO_DBG_DEC(pStyle->usAfterIndent);
626
			break;
627
		case 0xc63e:	/* anld */
628
			iTmp = (int)ucGetByte(
629
					iFodo + iFodoOff + 2, aucGrpprl);
630
			DBG_DEC_C(iTmp < 84, iTmp);
631
			if (iTmp >= 1) {
632
				tList6.ucNFC = ucGetByte(
633
					iFodo + iFodoOff + 3, aucGrpprl);
634
			}
635
			if (tList6.ucNFC != LIST_BULLETS && iTmp >= 2) {
636
				iBefore = (int)ucGetByte(
637
					iFodo + iFodoOff + 4, aucGrpprl);
638
			} else {
639
				iBefore = 0;
640
			}
641
			if (iTmp >= 12) {
642
				tList6.ulStartAt = (ULONG)usGetWord(
643
					iFodo + iFodoOff + 13, aucGrpprl);
644
			}
645
			if (iTmp >= iBefore + 22) {
646
				tList6.usListChar = usGetWord(
647
					iFodo + iFodoOff + iBefore + 23,
648
					aucGrpprl);
649
				DBG_HEX(tList6.usListChar);
650
			}
651
			break;
652
		default:
653
			NO_DBG_HEX(usOpCode);
654
			break;
655
		}
656
		if (iInfoLen <= 0) {
657
			iInfoLen =
658
				iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
659
			fail(iInfoLen <= 0);
660
		}
661
		iFodoOff += iInfoLen;
662
	}
663
 
664
	if (pStyle->usListIndex == 2047) {
665
		/* Old style list */
666
		pStyle->usStartAt = (USHORT)tList6.ulStartAt;
667
		pStyle->usListChar = tList6.usListChar;
668
		pStyle->ucNFC = tList6.ucNFC;
669
	} else {
670
		/* New style list */
671
		pList = pGetListInfo(pStyle->usListIndex, pStyle->ucListLevel);
672
		if (pList != NULL) {
673
			pStyle->bNoRestart = pList->bNoRestart;
674
			fail(pList->ulStartAt > (ULONG)USHRT_MAX);
675
			pStyle->usStartAt = (USHORT)pList->ulStartAt;
676
			pStyle->usListChar = pList->usListChar;
677
			pStyle->ucNFC = pList->ucNFC;
678
			if (pStyle->sLeftIndent <= 0) {
679
				pStyle->sLeftIndent = pList->sLeftIndent;
680
			}
681
		}
682
	}
683
} /* end of vGet8StyleInfo */
684
 
685
/*
686
 * Get the left indentation value from the style information block
687
 *
688
 * Returns the value when found, otherwise 0
689
 */
690
static short
691
sGetLeftIndent(const UCHAR *aucGrpprl, size_t tBytes)
692
{
693
	int	iOffset, iInfoLen;
694
	USHORT	usOpCode, usTmp;
695
 
696
	fail(aucGrpprl == NULL);
697
 
698
	iOffset = 0;
699
	while (tBytes >= (size_t)iOffset + 4) {
700
		usOpCode = usGetWord(iOffset, aucGrpprl);
701
		if (usOpCode == 0x840f) {	/* dxaLeft */
702
			usTmp = usGetWord(iOffset + 2, aucGrpprl);
703
			if (usTmp <= 0x7fff) {
704
				NO_DBG_DEC(usTmp);
705
				return (short)usTmp;
706
			}
707
		}
708
		iInfoLen = iGet8InfoLength(iOffset, aucGrpprl);
709
		fail(iInfoLen <= 0);
710
		iOffset += iInfoLen;
711
	}
712
	return 0;
713
} /* end of sGetLeftIndent */
714
 
715
/*
716
 * Build the list with List Information for Word 8/9/10/11 files
717
 */
718
void
719
vGet8LstInfo(FILE *pFile, const pps_info_type *pPPS,
720
	const ULONG *aulBBD, size_t tBBDLen,
721
	const ULONG *aulSBD, size_t tSBDLen,
722
	const UCHAR *aucHeader)
723
{
724
	list_block_type	tList;
725
	const ULONG	*aulBlockDepot;
726
	UCHAR	*aucLfoInfo, *aucLstfInfo, *aucPapx, *aucXString;
727
	ULONG	ulBeginLfoInfo, ulBeginLstfInfo, ulBeginLvlfInfo;
728
	ULONG	ulListID, ulStart;
729
	size_t	tBlockDepotLen, tBlockSize;
730
	size_t	tLfoInfoLen, tLstfInfoLen, tPapxLen, tXstLen, tOff;
731
	size_t	tLstfRecords, tStart, tIndex;
732
	int	iNums;
733
	USHORT	usIstd;
734
	UCHAR	ucTmp, ucListLevel, ucMaxLevel, ucChpxLen;
735
	UCHAR	aucLvlfInfo[28], aucXst[2];
736
 
737
	fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
738
	fail(aulBBD == NULL || aulSBD == NULL);
739
 
740
	NO_DBG_DEC(pPPS->tTable.ulSB);
741
	NO_DBG_HEX(pPPS->tTable.ulSize);
742
	if (pPPS->tTable.ulSize == 0) {
743
		DBG_MSG("No list information");
744
		return;
745
	}
746
 
747
	if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
748
		/* Use the Small Block Depot */
749
		aulBlockDepot = aulSBD;
750
		tBlockDepotLen = tSBDLen;
751
		tBlockSize = SMALL_BLOCK_SIZE;
752
	} else {
753
		/* Use the Big Block Depot */
754
		aulBlockDepot = aulBBD;
755
		tBlockDepotLen = tBBDLen;
756
		tBlockSize = BIG_BLOCK_SIZE;
757
	}
758
 
759
	/* LFO (List Format Override) */
760
	ulBeginLfoInfo = ulGetLong(0x2ea, aucHeader); /* fcPlfLfo */
761
	DBG_HEX(ulBeginLfoInfo);
762
	tLfoInfoLen = (size_t)ulGetLong(0x2ee, aucHeader); /* lcbPlfLfo */
763
	DBG_DEC(tLfoInfoLen);
764
	if (tLfoInfoLen == 0) {
765
		DBG_MSG("No lists in this document");
766
		return;
767
	}
768
 
769
	aucLfoInfo = xmalloc(tLfoInfoLen);
770
	if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
771
			aulBlockDepot, tBlockDepotLen, tBlockSize,
772
			aucLfoInfo, ulBeginLfoInfo, tLfoInfoLen)) {
773
		aucLfoInfo = xfree(aucLfoInfo);
774
		return;
775
	}
776
	NO_DBG_PRINT_BLOCK(aucLfoInfo, tLfoInfoLen);
777
	vBuildLfoList(aucLfoInfo, tLfoInfoLen);
778
	aucLfoInfo = xfree(aucLfoInfo);
779
 
780
	/* LSTF (LiST data on File) */
781
	ulBeginLstfInfo = ulGetLong(0x2e2, aucHeader); /* fcPlcfLst */
782
	DBG_HEX(ulBeginLstfInfo);
783
	tLstfInfoLen = (size_t)ulGetLong(0x2e6, aucHeader); /* lcbPlcfLst */
784
	DBG_DEC(tLstfInfoLen);
785
	if (tLstfInfoLen == 0) {
786
		DBG_MSG("No list data on file");
787
		return;
788
	}
789
 
790
	aucLstfInfo = xmalloc(tLstfInfoLen);
791
	if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
792
			aulBlockDepot, tBlockDepotLen, tBlockSize,
793
			aucLstfInfo, ulBeginLstfInfo, tLstfInfoLen)) {
794
		aucLstfInfo = xfree(aucLstfInfo);
795
		return;
796
	}
797
	NO_DBG_PRINT_BLOCK(aucLstfInfo, tLstfInfoLen);
798
 
799
	tLstfRecords = (size_t)usGetWord(0, aucLstfInfo);
800
	if (2 + tLstfRecords * 28 < tLstfInfoLen) {
801
		DBG_DEC(2 + tLstfRecords * 28);
802
		DBG_DEC(tLstfInfoLen);
803
		aucLstfInfo = xfree(aucLstfInfo);
804
		return;
805
	}
806
 
807
	/* LVLF (List leVeL on File) */
808
	ulBeginLvlfInfo = ulBeginLstfInfo + tLstfInfoLen;
809
	DBG_HEX(ulBeginLvlfInfo);
810
 
811
	aucXString = NULL;
812
	ulStart = ulBeginLvlfInfo;
813
 
814
	for (tIndex = 0, tStart = 2;
815
	     tIndex < tLstfRecords;
816
	     tIndex++, tStart += 28) {
817
		ulListID = ulGetLong(tStart, aucLstfInfo);
818
		NO_DBG_HEX(ulListID);
819
		ucTmp = ucGetByte(tStart + 26, aucLstfInfo);
820
		ucMaxLevel = odd(ucTmp) ? 1 : 9;
821
		for (ucListLevel = 0; ucListLevel < ucMaxLevel; ucListLevel++) {
822
			fail(aucXString != NULL);
823
			usIstd = usGetWord(
824
					tStart + 8 + 2 * (size_t)ucListLevel,
825
					aucLstfInfo);
826
			DBG_DEC_C(usIstd != STI_NIL, usIstd);
827
			NO_DBG_HEX(ulStart);
828
			(void)memset(&tList, 0, sizeof(tList));
829
			/* Read the lvlf (List leVeL on File) */
830
			if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
831
					aulBlockDepot, tBlockDepotLen,
832
					tBlockSize, aucLvlfInfo,
833
					ulStart, sizeof(aucLvlfInfo))) {
834
				aucLstfInfo = xfree(aucLstfInfo);
835
				return;
836
			}
837
			NO_DBG_PRINT_BLOCK(aucLvlfInfo, sizeof(aucLvlfInfo));
838
			if (bAllZero(aucLvlfInfo, sizeof(aucLvlfInfo))) {
839
				tList.ulStartAt = 1;
840
				tList.ucNFC = 0x00;
841
				tList.bNoRestart = FALSE;
842
			} else {
843
				tList.ulStartAt = ulGetLong(0, aucLvlfInfo);
844
				tList.ucNFC = ucGetByte(4, aucLvlfInfo);
845
				ucTmp = ucGetByte(5, aucLvlfInfo);
846
				tList.bNoRestart = (ucTmp & BIT(3)) != 0;
847
				DBG_MSG_C((ucTmp & BIT(4)) != 0 &&
848
					(ucTmp & BIT(6)) != 0, "Found one");
849
			}
850
			ulStart += sizeof(aucLvlfInfo);
851
			tPapxLen = (size_t)ucGetByte(25, aucLvlfInfo);
852
			if (tPapxLen != 0) {
853
				aucPapx = xmalloc(tPapxLen);
854
				/* Read the Papx */
855
				if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
856
						aulBlockDepot, tBlockDepotLen,
857
						tBlockSize, aucPapx,
858
						ulStart, tPapxLen)) {
859
					aucPapx = xfree(aucPapx);
860
					aucLstfInfo = xfree(aucLstfInfo);
861
					return;
862
				}
863
				NO_DBG_PRINT_BLOCK(aucPapx, tPapxLen);
864
				tList.sLeftIndent =
865
					sGetLeftIndent(aucPapx, tPapxLen);
866
				aucPapx = xfree(aucPapx);
867
			}
868
			ulStart += tPapxLen;
869
			ucChpxLen = ucGetByte(24, aucLvlfInfo);
870
			ulStart += (ULONG)ucChpxLen;
871
			/* Read the length of the XString */
872
			if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
873
					aulBlockDepot, tBlockDepotLen,
874
					tBlockSize, aucXst,
875
					ulStart, sizeof(aucXst))) {
876
				aucLstfInfo = xfree(aucLstfInfo);
877
				return;
878
			}
879
			NO_DBG_PRINT_BLOCK(aucXst, sizeof(aucXst));
880
			tXstLen = (size_t)usGetWord(0, aucXst);
881
			ulStart += sizeof(aucXst);
882
			if (tXstLen == 0) {
883
				tList.usListChar = DEFAULT_LISTCHAR;
884
				vAdd2ListInfoList(ulListID,
885
						usIstd,
886
						ucListLevel,
887
						&tList);
888
				continue;
889
			}
890
			tXstLen *= 2;	/* Length in chars to length in bytes */
891
			aucXString = xmalloc(tXstLen);
892
			/* Read the XString */
893
			if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
894
					aulBlockDepot, tBlockDepotLen,
895
					tBlockSize, aucXString,
896
					ulStart, tXstLen)) {
897
				aucXString = xfree(aucXString);
898
				aucLstfInfo = xfree(aucLstfInfo);
899
				return;
900
			}
901
			NO_DBG_PRINT_BLOCK(aucXString, tXstLen);
902
			tOff = 0;
903
			for (iNums = 6; iNums < 15; iNums++) {
904
				ucTmp = ucGetByte(iNums, aucLvlfInfo);
905
				if (ucTmp == 0) {
906
					break;
907
				}
908
				tOff = (size_t)ucTmp;
909
			}
910
			tOff *= 2;	/* Offset in chars to offset in bytes */
911
			NO_DBG_DEC(tOff);
912
			if (tList.ucNFC == LIST_SPECIAL ||
913
			    tList.ucNFC == LIST_SPECIAL2 ||
914
			    tList.ucNFC == LIST_BULLETS) {
915
				tList.usListChar = usGetWord(0, aucXString);
916
			} else if (tOff != 0 && tOff < tXstLen) {
917
				tList.usListChar = usGetWord(tOff, aucXString);
918
			} else {
919
				tList.usListChar = DEFAULT_LISTCHAR;
920
			}
921
			vAdd2ListInfoList(ulListID,
922
					usIstd,
923
					ucListLevel,
924
					&tList);
925
			ulStart += tXstLen;
926
			aucXString = xfree(aucXString);
927
		}
928
	}
929
	aucLstfInfo = xfree(aucLstfInfo);
930
} /* end of vGet8LstInfo */
931
 
932
/*
933
 * Build the lists with Paragraph Information for Word 8/9/10/11 files
934
 */
935
void
936
vGet8PapInfo(FILE *pFile, const pps_info_type *pPPS,
937
	const ULONG *aulBBD, size_t tBBDLen,
938
	const ULONG *aulSBD, size_t tSBDLen,
939
	const UCHAR *aucHeader)
940
{
941
	row_block_type		tRow;
942
	style_block_type	tStyle;
943
	ULONG		*aulParfPage;
944
	UCHAR	*aucBuffer;
945
	ULONG	ulCharPos, ulCharPosFirst, ulCharPosLast;
946
	ULONG	ulBeginParfInfo;
947
	size_t	tParfInfoLen, tOffset, tLen;
948
	int	iIndex, iIndex2, iRun, iFodo, iLen;
949
	row_info_enum	eRowInfo;
950
	USHORT	usIstd;
951
	UCHAR	aucFpage[BIG_BLOCK_SIZE];
952
 
953
	fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
954
	fail(aulBBD == NULL || aulSBD == NULL);
955
 
956
	ulBeginParfInfo = ulGetLong(0x102, aucHeader); /* fcPlcfbtePapx */
957
	NO_DBG_HEX(ulBeginParfInfo);
958
	tParfInfoLen = (size_t)ulGetLong(0x106, aucHeader); /* lcbPlcfbtePapx */
959
	NO_DBG_DEC(tParfInfoLen);
960
	if (tParfInfoLen < 4) {
961
		DBG_DEC(tParfInfoLen);
962
		return;
963
	}
964
 
965
	aucBuffer = aucFillInfoBuffer(pFile, &pPPS->tTable,
966
			aulBBD, tBBDLen, aulSBD, tSBDLen,
967
			ulBeginParfInfo, tParfInfoLen);
968
	if (aucBuffer == NULL) {
969
		return;
970
	}
971
	NO_DBG_PRINT_BLOCK(aucBuffer, tParfInfoLen);
972
 
973
	tLen = (tParfInfoLen / 4 - 1) / 2;
974
	aulParfPage = xcalloc(tLen, sizeof(ULONG));
975
	for (iIndex = 0, tOffset = (tLen + 1) * 4;
976
	     iIndex < (int)tLen;
977
	     iIndex++, tOffset += 4) {
978
		 aulParfPage[iIndex] = ulGetLong(tOffset, aucBuffer);
979
		 NO_DBG_DEC(aulParfPage[iIndex]);
980
	}
981
	DBG_HEX(ulGetLong(0, aucBuffer));
982
	aucBuffer = xfree(aucBuffer);
983
	NO_DBG_PRINT_BLOCK(aucHeader, HEADER_SIZE);
984
 
985
	(void)memset(&tRow, 0, sizeof(tRow));
986
	ulCharPosFirst = CP_INVALID;
987
	for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
988
		fail(aulParfPage[iIndex] > ULONG_MAX / BIG_BLOCK_SIZE);
989
		if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB,
990
				aulBBD, tBBDLen, BIG_BLOCK_SIZE,
991
				aucFpage,
992
				aulParfPage[iIndex] * BIG_BLOCK_SIZE,
993
				BIG_BLOCK_SIZE)) {
994
			break;
995
		}
996
		NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE);
997
		iRun = (int)ucGetByte(0x1ff, aucFpage);
998
		NO_DBG_DEC(iRun);
999
		for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
1000
			NO_DBG_HEX(ulGetLong(iIndex2 * 4, aucFpage));
1001
			iFodo = 2 * (int)ucGetByte(
1002
				(iRun + 1) * 4 + iIndex2 * 13, aucFpage);
1003
			if (iFodo <= 0) {
1004
				continue;
1005
			}
1006
 
1007
			iLen = 2 * (int)ucGetByte(iFodo, aucFpage);
1008
			if (iLen == 0) {
1009
				iFodo++;
1010
				iLen = 2 * (int)ucGetByte(iFodo, aucFpage);
1011
			}
1012
 
1013
			usIstd = usGetWord(iFodo + 1, aucFpage);
1014
			vFillStyleFromStylesheet(usIstd, &tStyle);
1015
			vGet8StyleInfo(iFodo, aucFpage + 3, iLen - 3, &tStyle);
1016
			ulCharPos = ulGetLong(iIndex2 * 4, aucFpage);
1017
			NO_DBG_HEX(ulCharPos);
1018
			tStyle.ulFileOffset = ulCharPos2FileOffsetX(
1019
						ulCharPos, &tStyle.eListID);
1020
			vAdd2StyleInfoList(&tStyle);
1021
 
1022
			eRowInfo = eGet8RowInfo(iFodo,
1023
					aucFpage + 3, iLen - 3, &tRow);
1024
			switch (eRowInfo) {
1025
			case found_a_cell:
1026
				if (ulCharPosFirst != CP_INVALID) {
1027
					break;
1028
				}
1029
				ulCharPosFirst = ulGetLong(
1030
						iIndex2 * 4, aucFpage);
1031
				NO_DBG_HEX(ulCharPosFirst);
1032
				tRow.ulCharPosStart = ulCharPosFirst;
1033
				tRow.ulFileOffsetStart =
1034
					ulCharPos2FileOffset(ulCharPosFirst);
1035
				NO_DBG_HEX_C(
1036
					tRow.ulFileOffsetStart == FC_INVALID,
1037
					ulCharPosFirst);
1038
				break;
1039
			case found_end_of_row:
1040
				ulCharPosLast = ulGetLong(
1041
						iIndex2 * 4, aucFpage);
1042
				NO_DBG_HEX(ulCharPosLast);
1043
				tRow.ulCharPosEnd = ulCharPosLast;
1044
				tRow.ulFileOffsetEnd =
1045
					ulCharPos2FileOffset(ulCharPosLast);
1046
				NO_DBG_HEX_C(tRow.ulFileOffsetEnd == FC_INVALID,
1047
							ulCharPosLast);
1048
				vAdd2RowInfoList(&tRow);
1049
				(void)memset(&tRow, 0, sizeof(tRow));
1050
				ulCharPosFirst = CP_INVALID;
1051
				break;
1052
			case found_nothing:
1053
				break;
1054
			default:
1055
				DBG_DEC(eRowInfo);
1056
				break;
1057
			}
1058
		}
1059
	}
1060
	aulParfPage = xfree(aulParfPage);
1061
} /* end of vGet8PapInfo */
1062
 
1063
/*
1064
 * Fill the font information block with information
1065
 * from a Word 8/9/10/11 file.
1066
 */
1067
void
1068
vGet8FontInfo(int iFodo, USHORT usIstd,
1069
	const UCHAR *aucGrpprl, int iBytes, font_block_type *pFont)
1070
{
1071
	long	lTmp;
1072
	int	iFodoOff, iInfoLen;
1073
	USHORT	usFtc0, usFtc1, usFtc2, usTmp;
1074
	UCHAR	ucTmp;
1075
 
1076
	fail(iFodo < 0 || aucGrpprl == NULL || pFont == NULL);
1077
 
1078
	usFtc0 = USHRT_MAX;
1079
	usFtc1 = USHRT_MAX;
1080
	usFtc2 = USHRT_MAX;
1081
 
1082
	iFodoOff = 0;
1083
	while (iBytes >= iFodoOff + 2) {
1084
		switch (usGetWord(iFodo + iFodoOff, aucGrpprl)) {
1085
		case 0x0800:	/* fRMarkDel */
1086
			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1087
			if (ucTmp == 0) {
1088
				pFont->usFontStyle &= ~FONT_MARKDEL;
1089
			} else {
1090
				pFont->usFontStyle |= FONT_MARKDEL;
1091
			}
1092
			break;
1093
		case 0x0835:	/* fBold */
1094
			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1095
			switch (ucTmp) {
1096
			case   0:	/* Unset */
1097
				pFont->usFontStyle &= ~FONT_BOLD;
1098
				break;
1099
			case   1:	/* Set */
1100
				pFont->usFontStyle |= FONT_BOLD;
1101
				break;
1102
			case 128:	/* Unchanged */
1103
				break;
1104
			case 129:	/* Negation */
1105
				pFont->usFontStyle ^= FONT_BOLD;
1106
				break;
1107
			default:
1108
				DBG_DEC(ucTmp);
1109
				DBG_FIXME();
1110
				break;
1111
			}
1112
			break;
1113
		case 0x0836:	/* fItalic */
1114
			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1115
			switch (ucTmp) {
1116
			case   0:	/* Unset */
1117
				pFont->usFontStyle &= ~FONT_ITALIC;
1118
				break;
1119
			case   1:	/* Set */
1120
				pFont->usFontStyle |= FONT_ITALIC;
1121
				break;
1122
			case 128:	/* Unchanged */
1123
				break;
1124
			case 129:	/* Negation */
1125
				pFont->usFontStyle ^= FONT_ITALIC;
1126
				break;
1127
			default:
1128
				DBG_DEC(ucTmp);
1129
				DBG_FIXME();
1130
				break;
1131
			}
1132
			break;
1133
		case 0x0837:	/* fStrike */
1134
			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1135
			switch (ucTmp) {
1136
			case   0:	/* Unset */
1137
				pFont->usFontStyle &= ~FONT_STRIKE;
1138
				break;
1139
			case   1:	/* Set */
1140
				pFont->usFontStyle |= FONT_STRIKE;
1141
				break;
1142
			case 128:	/* Unchanged */
1143
				break;
1144
			case 129:	/* Negation */
1145
				pFont->usFontStyle ^= FONT_STRIKE;
1146
				break;
1147
			default:
1148
				DBG_DEC(ucTmp);
1149
				DBG_FIXME();
1150
				break;
1151
			}
1152
			break;
1153
		case 0x083a:	/* fSmallCaps */
1154
			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1155
			switch (ucTmp) {
1156
			case   0:	/* Unset */
1157
				pFont->usFontStyle &= ~FONT_SMALL_CAPITALS;
1158
				break;
1159
			case   1:	/* Set */
1160
				pFont->usFontStyle |= FONT_SMALL_CAPITALS;
1161
				break;
1162
			case 128:	/* Unchanged */
1163
				break;
1164
			case 129:	/* Negation */
1165
				pFont->usFontStyle ^= FONT_SMALL_CAPITALS;
1166
				break;
1167
			default:
1168
				DBG_DEC(ucTmp);
1169
				DBG_FIXME();
1170
				break;
1171
			}
1172
			break;
1173
		case 0x083b:	/* fCaps */
1174
			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1175
			switch (ucTmp) {
1176
			case   0:	/* Unset */
1177
				pFont->usFontStyle &= ~FONT_CAPITALS;
1178
				break;
1179
			case   1:	/* Set */
1180
				pFont->usFontStyle |= FONT_CAPITALS;
1181
				break;
1182
			case 128:	/* Unchanged */
1183
				break;
1184
			case 129:	/* Negation */
1185
				pFont->usFontStyle ^= FONT_CAPITALS;
1186
				break;
1187
			default:
1188
				DBG_DEC(ucTmp);
1189
				DBG_FIXME();
1190
				break;
1191
			}
1192
			break;
1193
		case 0x083c:	/* fVanish */
1194
			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1195
			switch (ucTmp) {
1196
			case   0:	/* Unset */
1197
				pFont->usFontStyle &= ~FONT_HIDDEN;
1198
				break;
1199
			case   1:	/* Set */
1200
				pFont->usFontStyle |= FONT_HIDDEN;
1201
				break;
1202
			case 128:	/* Unchanged */
1203
				break;
1204
			case 129:	/* Negation */
1205
				pFont->usFontStyle ^= FONT_HIDDEN;
1206
				break;
1207
			default:
1208
				DBG_DEC(ucTmp);
1209
				DBG_FIXME();
1210
				break;
1211
			}
1212
			break;
1213
		case 0x2a32:	/* cDefault */
1214
			pFont->usFontStyle &= FONT_HIDDEN;
1215
			pFont->ucFontColor = FONT_COLOR_DEFAULT;
1216
			break;
1217
		case 0x2a33:	/* cPlain */
1218
			DBG_MSG("2a33: cPlain");
1219
			vFillFontFromStylesheet(usIstd, pFont);
1220
			break;
1221
		case 0x2a3e:	/* cKul */
1222
			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1223
			if (ucTmp == 0 || ucTmp == 5) {
1224
				pFont->usFontStyle &= ~FONT_UNDERLINE;
1225
			} else {
1226
				NO_DBG_MSG("Underline text");
1227
				pFont->usFontStyle |= FONT_UNDERLINE;
1228
				if (ucTmp == 6) {
1229
					DBG_MSG("Bold text");
1230
					pFont->usFontStyle |= FONT_BOLD;
1231
				}
1232
			}
1233
			break;
1234
		case 0x2a42:	/* cIco */
1235
			pFont->ucFontColor =
1236
				ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1237
			NO_DBG_DEC(pFont->ucFontColor);
1238
			break;
1239
		case 0x2a44:	/* cHpsInc */
1240
			DBG_MSG("0x2a44: sprmCHpsInc");
1241
			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1242
			DBG_DEC(ucTmp);
1243
			break;
1244
		case 0x2a48:	/* cIss */
1245
			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1246
			ucTmp &= 0x07;
1247
			if (ucTmp == 1) {
1248
				pFont->usFontStyle |= FONT_SUPERSCRIPT;
1249
				NO_DBG_MSG("Superscript");
1250
			} else if (ucTmp == 2) {
1251
				pFont->usFontStyle |= FONT_SUBSCRIPT;
1252
				NO_DBG_MSG("Subscript");
1253
			}
1254
			break;
1255
		case 0x4a30:	/* cIstd */
1256
			usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
1257
			NO_DBG_DEC(usTmp);
1258
			break;
1259
		case 0x4a43:	/* cHps */
1260
			pFont->usFontSize =
1261
				usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
1262
			NO_DBG_DEC(pFont->usFontSize);
1263
			break;
1264
		case 0x4a4d:	/* cHpsMul */
1265
			DBG_MSG("0x4a4d: sprmCHpsMul");
1266
			usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
1267
			DBG_DEC(usTmp);
1268
			break;
1269
		case 0x4a4f:	/* cFtc0 */
1270
			usFtc0 = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
1271
			break;
1272
		case 0x4a50:	/* cFtc1 */
1273
			usFtc1 = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
1274
			break;
1275
		case 0x4a51:	/* cFtc2 */
1276
			usFtc2 = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
1277
			break;
1278
		case 0xca47:	/* cMajority */
1279
			DBG_MSG("0xca47: sprmCMajority");
1280
			break;
1281
		case 0xca4a:	/* cHpsInc1 */
1282
			usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
1283
			lTmp = (long)pFont->usFontSize + (long)usTmp;
1284
			if (lTmp < 8) {
1285
				pFont->usFontSize = 8;
1286
			} else if (lTmp > 32766) {
1287
				pFont->usFontSize = 32766;
1288
			} else {
1289
				pFont->usFontSize = (USHORT)lTmp;
1290
			}
1291
			break;
1292
		case 0xca4c:	/* cMajority50 */
1293
			DBG_MSG("0xca4c: sprmCMajority50");
1294
			break;
1295
		case 0xea3f:	/* cHps, cHpsPos */
1296
			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1297
			DBG_DEC(ucTmp);
1298
			if (ucTmp != 0) {
1299
				pFont->usFontSize = (USHORT)ucTmp;
1300
			}
1301
			ucTmp = ucGetByte(iFodo + iFodoOff + 3, aucGrpprl);
1302
			DBG_DEC(ucTmp);
1303
			break;
1304
		default:
1305
			break;
1306
		}
1307
		iInfoLen = iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
1308
		fail(iInfoLen <= 0);
1309
		iFodoOff += iInfoLen;
1310
	}
1311
 
1312
	/* Combine the Ftc's to a FontNumber */
1313
	NO_DBG_DEC_C(usFtc0 != USHRT_MAX, usFtc0);
1314
	NO_DBG_DEC_C(usFtc2 != USHRT_MAX, usFtc2);
1315
	NO_DBG_DEC_C(usFtc1 != USHRT_MAX, usFtc1);
1316
	if (usFtc0 <= 0x7fff) {
1317
		if (usFtc0 <= (USHORT)UCHAR_MAX) {
1318
			pFont->ucFontNumber = (UCHAR)usFtc0;
1319
		} else {
1320
			DBG_DEC(usFtc0);
1321
			DBG_FIXME();
1322
			pFont->ucFontNumber = 0;
1323
		}
1324
	} else if (usFtc2 <= 0x7fff) {
1325
		if (usFtc2 <= (USHORT)UCHAR_MAX) {
1326
			pFont->ucFontNumber = (UCHAR)usFtc2;
1327
		} else {
1328
			DBG_DEC(usFtc2);
1329
			DBG_FIXME();
1330
			pFont->ucFontNumber = 0;
1331
		}
1332
	} else if (usFtc1 <= 0x7fff) {
1333
		if (usFtc1 <= (USHORT)UCHAR_MAX) {
1334
			pFont->ucFontNumber = (UCHAR)usFtc1;
1335
		} else {
1336
			DBG_DEC(usFtc1);
1337
			DBG_FIXME();
1338
			pFont->ucFontNumber = 0;
1339
		}
1340
	}
1341
} /* end of vGet8FontInfo */
1342
 
1343
/*
1344
 * Fill the picture information block with information
1345
 * from a Word 8/9/10/11 file.
1346
 * Returns TRUE when successful, otherwise FALSE
1347
 */
1348
static BOOL
1349
bGet8PicInfo(int iFodo,
1350
	const UCHAR *aucGrpprl, int iBytes, picture_block_type *pPicture)
1351
{
1352
	ULONG	ulTmp;
1353
	int	iFodoOff, iInfoLen;
1354
	BOOL	bFound;
1355
	UCHAR	ucTmp;
1356
 
1357
	fail(iFodo <= 0 || aucGrpprl == NULL || pPicture == NULL);
1358
 
1359
	iFodoOff = 0;
1360
	bFound = FALSE;
1361
	while (iBytes >= iFodoOff + 2) {
1362
		switch (usGetWord(iFodo + iFodoOff, aucGrpprl)) {
1363
#if 0
1364
		case 0x0806:	/* fData */
1365
			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1366
			if (ucTmp == 0x01) {
1367
				/* Not a picture, but a form field */
1368
				return FALSE;
1369
			}
1370
			DBG_DEC_C(ucTmp != 0, ucTmp);
1371
			break;
1372
#endif
1373
		case 0x080a:	/* fOle2 */
1374
			ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1375
			if (ucTmp == 0x01) {
1376
				/* Not a picture, but an OLE object */
1377
				return FALSE;
1378
			}
1379
			DBG_DEC_C(ucTmp != 0, ucTmp);
1380
			break;
1381
		case 0x680e:	/* fcObj */
1382
			ulTmp = ulGetLong(iFodo + iFodoOff + 2, aucGrpprl);
1383
			DBG_HEX(ulTmp);
1384
			break;
1385
		case 0x6a03:	/* fcPic */
1386
			pPicture->ulPictureOffset = ulGetLong(
1387
					iFodo + iFodoOff + 2, aucGrpprl);
1388
			bFound = TRUE;
1389
			break;
1390
		default:
1391
			break;
1392
		}
1393
		iInfoLen = iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
1394
		fail(iInfoLen <= 0);
1395
		iFodoOff += iInfoLen;
1396
	}
1397
	return bFound;
1398
} /* end of bGet8PicInfo */
1399
 
1400
/*
1401
 * Build the lists with Character Information for Word 8/9/10/11 files
1402
 */
1403
void
1404
vGet8ChrInfo(FILE *pFile, const pps_info_type *pPPS,
1405
	const ULONG *aulBBD, size_t tBBDLen,
1406
	const ULONG *aulSBD, size_t tSBDLen,
1407
	const UCHAR *aucHeader)
1408
{
1409
	font_block_type		tFont;
1410
	picture_block_type	tPicture;
1411
	ULONG		*aulCharPage;
1412
	UCHAR	*aucBuffer;
1413
	ULONG	ulFileOffset, ulCharPos, ulBeginCharInfo;
1414
	size_t	tCharInfoLen, tOffset, tLen;
1415
	int	iIndex, iIndex2, iRun, iFodo, iLen;
1416
	USHORT	usIstd;
1417
	UCHAR	aucFpage[BIG_BLOCK_SIZE];
1418
 
1419
	fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
1420
	fail(aulBBD == NULL || aulSBD == NULL);
1421
 
1422
	ulBeginCharInfo = ulGetLong(0xfa, aucHeader); /* fcPlcfbteChpx */
1423
	NO_DBG_HEX(ulBeginCharInfo);
1424
	tCharInfoLen = (size_t)ulGetLong(0xfe, aucHeader); /* lcbPlcfbteChpx */
1425
	NO_DBG_DEC(tCharInfoLen);
1426
	if (tCharInfoLen < 4) {
1427
		DBG_DEC(tCharInfoLen);
1428
		return;
1429
	}
1430
 
1431
	aucBuffer = aucFillInfoBuffer(pFile, &pPPS->tTable,
1432
			aulBBD, tBBDLen, aulSBD, tSBDLen,
1433
			ulBeginCharInfo, tCharInfoLen);
1434
	if (aucBuffer == NULL) {
1435
		return;
1436
	}
1437
	NO_DBG_PRINT_BLOCK(aucBuffer, tCharInfoLen);
1438
 
1439
	tLen = (tCharInfoLen / 4 - 1) / 2;
1440
	aulCharPage = xcalloc(tLen, sizeof(ULONG));
1441
	for (iIndex = 0, tOffset = (tLen + 1) * 4;
1442
	     iIndex < (int)tLen;
1443
	     iIndex++, tOffset += 4) {
1444
		 aulCharPage[iIndex] = ulGetLong(tOffset, aucBuffer);
1445
		 NO_DBG_DEC(aulCharPage[iIndex]);
1446
	}
1447
	DBG_HEX(ulGetLong(0, aucBuffer));
1448
	aucBuffer = xfree(aucBuffer);
1449
	NO_DBG_PRINT_BLOCK(aucHeader, HEADER_SIZE);
1450
 
1451
	for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
1452
		fail(aulCharPage[iIndex] > ULONG_MAX / BIG_BLOCK_SIZE);
1453
		if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB,
1454
				aulBBD, tBBDLen, BIG_BLOCK_SIZE,
1455
				aucFpage,
1456
				aulCharPage[iIndex] * BIG_BLOCK_SIZE,
1457
				BIG_BLOCK_SIZE)) {
1458
			break;
1459
		}
1460
		NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE);
1461
		iRun = (int)ucGetByte(0x1ff, aucFpage);
1462
		NO_DBG_DEC(iRun);
1463
		for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
1464
			ulCharPos = ulGetLong(iIndex2 * 4, aucFpage);
1465
			ulFileOffset = ulCharPos2FileOffset(ulCharPos);
1466
			iFodo = 2 * (int)ucGetByte(
1467
				(iRun + 1) * 4 + iIndex2, aucFpage);
1468
 
1469
			iLen = (int)ucGetByte(iFodo, aucFpage);
1470
 
1471
			usIstd = usGetIstd(ulFileOffset);
1472
			vFillFontFromStylesheet(usIstd, &tFont);
1473
			if (iFodo != 0) {
1474
				vGet8FontInfo(iFodo, usIstd,
1475
					aucFpage + 1, iLen - 1, &tFont);
1476
			}
1477
			tFont.ulFileOffset = ulFileOffset;
1478
			vAdd2FontInfoList(&tFont);
1479
 
1480
			if (iFodo <= 0) {
1481
				continue;
1482
			}
1483
 
1484
			(void)memset(&tPicture, 0, sizeof(tPicture));
1485
			if (bGet8PicInfo(iFodo, aucFpage + 1,
1486
						iLen - 1, &tPicture)) {
1487
				tPicture.ulFileOffset = ulFileOffset;
1488
				tPicture.ulFileOffsetPicture =
1489
					ulDataPos2FileOffset(
1490
						tPicture.ulPictureOffset);
1491
				vAdd2PictInfoList(&tPicture);
1492
			}
1493
		}
1494
	}
1495
	aulCharPage = xfree(aulCharPage);
1496
} /* end of vGet8ChrInfo */