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
 * prop2.c
3
 * Copyright (C) 2002-2005 A.J. van Os; Released under GPL
4
 *
5
 * Description:
6
 * Read the property information from a WinWord 1 or 2 file
7
 */
8
 
9
#include <string.h>
10
#include "antiword.h"
11
 
12
 
13
#define MAX_FILESIZE		0x2000000UL	/* 32 Mb */
14
 
15
/*
16
 * iGet2InfoLength - the length of the information for WinWord 1/2 files
17
 */
18
static int
19
iGet2InfoLength(int iByteNbr, const UCHAR *aucGrpprl)
20
{
21
	int	iTmp, iDel, iAdd;
22
 
23
	switch (ucGetByte(iByteNbr, aucGrpprl)) {
24
	case   3: case  15: case  78: case 152: case 154: case 155:
25
		return 2 + (int)ucGetByte(iByteNbr + 1, aucGrpprl);
26
	case  16: case  17: case  18: case  19: case  21: case  22: case  26:
27
	case  27: case  28: case  30: case  31: case  32: case  33: case  34:
28
	case  35: case  36: case  38: case  39: case  40: case  41: case  42:
29
	case  43: case  45: case  46: case  47: case  48: case  49: case  68:
30
	case  71: case  72: case  82: case  83: case  96: case  97: case  98:
31
	case  99: case 115: case 116: case 119: case 120: case 123: case 124:
32
	case 129: case 130: case 131: case 132: case 135: case 136: case 139:
33
	case 140: case 141: case 142: case 143: case 144: case 145: case 146:
34
	case 147: case 148: case 153: case 159: case 161: case 162:
35
		return 1 + 2;
36
	case  23:
37
		iTmp = (int)ucGetByte(iByteNbr + 1, aucGrpprl);
38
		if (iTmp == 255) {
39
			iDel = (int)ucGetByte(iByteNbr + 2, aucGrpprl);
40
			iAdd = (int)ucGetByte(
41
					iByteNbr + 3 + iDel * 4, aucGrpprl);
42
			iTmp = 2 + iDel * 4 + iAdd * 3;
43
		}
44
		return 2 + iTmp;
45
	case  70:
46
		return 1 + 3;
47
	case  95:
48
		return 1 + 13;
49
	case 157: case 163:
50
		return 1 + 5;
51
	case 158: case 160: case 164:
52
		return 1 + 4;
53
	default:
54
		return 1 + 1;
55
	}
56
} /* end of iGet2InfoLength */
57
 
58
/*
59
 * Build the lists with Document Property Information for WinWord 1/2 files
60
 */
61
void
62
vGet2DopInfo(FILE *pFile, const UCHAR *aucHeader)
63
{
64
	document_block_type	tDocument;
65
	UCHAR	*aucBuffer;
66
	ULONG	ulBeginDocpInfo, ulTmp;
67
	size_t	tDocpInfoLen;
68
	USHORT	usTmp;
69
 
70
	ulBeginDocpInfo = ulGetLong(0x112, aucHeader); /* fcDop */
71
	DBG_HEX(ulBeginDocpInfo);
72
	tDocpInfoLen = (size_t)usGetWord(0x116, aucHeader); /* cbDop */
73
	DBG_DEC(tDocpInfoLen);
74
	if (tDocpInfoLen < 28) {
75
		DBG_MSG("No Document information");
76
		return;
77
	}
78
 
79
	aucBuffer = xmalloc(tDocpInfoLen);
80
	if (!bReadBytes(aucBuffer, tDocpInfoLen, ulBeginDocpInfo, pFile)) {
81
		aucBuffer = xfree(aucBuffer);
82
		return;
83
	}
84
 
85
	usTmp = usGetWord(0x00, aucBuffer);
86
	tDocument.ucHdrFtrSpecification = (UCHAR)(usTmp >> 8); /* grpfIhdt */
87
	tDocument.usDefaultTabWidth = usGetWord(0x0a, aucBuffer); /* dxaTab */
88
	ulTmp = ulGetLong(0x14, aucBuffer); /* dttmCreated */
89
	tDocument.tCreateDate = tConvertDTTM(ulTmp);
90
	ulTmp = ulGetLong(0x18, aucBuffer); /* dttmRevised */
91
	tDocument.tRevisedDate = tConvertDTTM(ulTmp);
92
	vCreateDocumentInfoList(&tDocument);
93
 
94
	aucBuffer = xfree(aucBuffer);
95
} /* end of vGet2DopInfo */
96
 
97
/*
98
 * Fill the section information block with information
99
 * from a WinWord 1/2 file.
100
 */
101
static void
102
vGet2SectionInfo(const UCHAR *aucGrpprl, size_t tBytes,
103
		section_block_type *pSection)
104
{
105
	int	iFodoOff, iInfoLen;
106
	USHORT	usCcol;
107
	UCHAR	ucTmp;
108
 
109
	fail(aucGrpprl == NULL || pSection == NULL);
110
 
111
	iFodoOff = 0;
112
	while (tBytes >= (size_t)iFodoOff + 1) {
113
		switch (ucGetByte(iFodoOff, aucGrpprl)) {
114
		case 117:	/* bkc */
115
			ucTmp = ucGetByte(iFodoOff + 1, aucGrpprl);
116
			DBG_DEC(ucTmp);
117
			pSection->bNewPage = ucTmp != 0 && ucTmp != 1;
118
			break;
119
		case 119:	/* ccolM1 */
120
			usCcol = 1 + usGetWord(iFodoOff + 1, aucGrpprl);
121
			DBG_DEC(usCcol);
122
			break;
123
		case 128:	/* grpfIhdt */
124
			pSection->ucHdrFtrSpecification =
125
					ucGetByte(iFodoOff + 1, aucGrpprl);
126
			break;
127
		default:
128
			break;
129
		}
130
		iInfoLen = iGet2InfoLength(iFodoOff, aucGrpprl);
131
		fail(iInfoLen <= 0);
132
		iFodoOff += iInfoLen;
133
	}
134
} /* end of vGet2SectionInfo */
135
 
136
/*
137
 * Build the lists with Section Property Information for WinWord 1/2 files
138
 */
139
void
140
vGet2SepInfo(FILE *pFile, const UCHAR *aucHeader)
141
{
142
	section_block_type	tSection;
143
	ULONG	*aulSectPage, *aulCharPos;
144
	UCHAR	*aucBuffer, *aucFpage;
145
	ULONG	ulBeginOfText, ulTextOffset, ulBeginSectInfo;
146
	size_t	tSectInfoLen, tIndex, tOffset, tLen, tBytes;
147
	UCHAR	aucTmp[1];
148
 
149
	fail(pFile == NULL || aucHeader == NULL);
150
 
151
	ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
152
	NO_DBG_HEX(ulBeginOfText);
153
	ulBeginSectInfo = ulGetLong(0x7c, aucHeader); /* fcPlcfsed */
154
	DBG_HEX(ulBeginSectInfo);
155
	tSectInfoLen = (size_t)usGetWord(0x80, aucHeader); /* cbPlcfsed */
156
	DBG_DEC(tSectInfoLen);
157
	if (tSectInfoLen < 4) {
158
		DBG_DEC(tSectInfoLen);
159
		return;
160
	}
161
 
162
	aucBuffer = xmalloc(tSectInfoLen);
163
	if (!bReadBytes(aucBuffer, tSectInfoLen, ulBeginSectInfo, pFile)) {
164
		aucBuffer = xfree(aucBuffer);
165
		return;
166
	}
167
	NO_DBG_PRINT_BLOCK(aucBuffer, tSectInfoLen);
168
 
169
	/* Read the Section Descriptors */
170
	tLen = (tSectInfoLen - 4) / 10;
171
	/* Save the section offsets */
172
	aulCharPos = xcalloc(tLen, sizeof(ULONG));
173
	for (tIndex = 0, tOffset = 0;
174
	     tIndex < tLen;
175
	     tIndex++, tOffset += 4) {
176
		ulTextOffset = ulGetLong(tOffset, aucBuffer);
177
		NO_DBG_HEX(ulTextOffset);
178
		aulCharPos[tIndex] = ulBeginOfText + ulTextOffset;
179
		NO_DBG_HEX(aulCharPos[tIndex]);
180
	}
181
	/* Save the Sepx offsets */
182
	aulSectPage = xcalloc(tLen, sizeof(ULONG));
183
	for (tIndex = 0, tOffset = (tLen + 1) * 4;
184
	     tIndex < tLen;
185
	     tIndex++, tOffset += 6) {
186
		aulSectPage[tIndex] = ulGetLong(tOffset + 2, aucBuffer);
187
		NO_DBG_HEX(aulSectPage[tIndex]); /* fcSepx */
188
	}
189
	aucBuffer = xfree(aucBuffer);
190
 
191
	/* Read the Section Properties */
192
	for (tIndex = 0; tIndex < tLen; tIndex++) {
193
		if (aulSectPage[tIndex] == FC_INVALID) {
194
			vDefault2SectionInfoList(aulCharPos[tIndex]);
195
			continue;
196
		}
197
		/* Get the number of bytes to read */
198
		if (!bReadBytes(aucTmp, 1, aulSectPage[tIndex], pFile)) {
199
			continue;
200
		}
201
		tBytes = 1 + (size_t)ucGetByte(0, aucTmp);
202
		NO_DBG_DEC(tBytes);
203
		/* Read the bytes */
204
		aucFpage = xmalloc(tBytes);
205
		if (!bReadBytes(aucFpage, tBytes, aulSectPage[tIndex], pFile)) {
206
			aucFpage = xfree(aucFpage);
207
			continue;
208
		}
209
		NO_DBG_PRINT_BLOCK(aucFpage, tBytes);
210
		/* Process the bytes */
211
		vGetDefaultSection(&tSection);
212
		vGet2SectionInfo(aucFpage + 1, tBytes - 1, &tSection);
213
		vAdd2SectionInfoList(&tSection, aulCharPos[tIndex]);
214
		aucFpage = xfree(aucFpage);
215
	}
216
	aulCharPos = xfree(aulCharPos);
217
	aulSectPage = xfree(aulSectPage);
218
} /* end of vGet2SepInfo */
219
 
220
/*
221
 * Build the list with Header/Footer Information for WinWord 1/2 files
222
 */
223
void
224
vGet2HdrFtrInfo(FILE *pFile, const UCHAR *aucHeader)
225
{
226
	ULONG	*aulCharPos;
227
	UCHAR	*aucBuffer;
228
	ULONG	ulHdrFtrOffset, ulBeginHdrFtrInfo;
229
	size_t	tHdrFtrInfoLen, tIndex, tOffset, tLen;
230
 
231
	fail(pFile == NULL || aucHeader == NULL);
232
 
233
	ulBeginHdrFtrInfo = ulGetLong(0x9a, aucHeader); /* fcPlcfhdd */
234
	NO_DBG_HEX(ulBeginHdrFtrInfo);
235
	tHdrFtrInfoLen = (size_t)usGetWord(0x9e, aucHeader); /* cbPlcfhdd */
236
	NO_DBG_DEC(tHdrFtrInfoLen);
237
	if (tHdrFtrInfoLen < 8) {
238
		DBG_DEC_C(tHdrFtrInfoLen != 0, tHdrFtrInfoLen);
239
		return;
240
	}
241
 
242
	aucBuffer = xmalloc(tHdrFtrInfoLen);
243
	if (!bReadBytes(aucBuffer, tHdrFtrInfoLen, ulBeginHdrFtrInfo, pFile)) {
244
		aucBuffer = xfree(aucBuffer);
245
		return;
246
	}
247
	NO_DBG_PRINT_BLOCK(aucBuffer, tHdrFtrInfoLen);
248
 
249
	tLen = tHdrFtrInfoLen / 4 - 1;
250
	/* Save the header/footer offsets */
251
	aulCharPos = xcalloc(tLen, sizeof(ULONG));
252
	for (tIndex = 0, tOffset = 0;
253
	     tIndex < tLen;
254
	     tIndex++, tOffset += 4) {
255
		ulHdrFtrOffset = ulGetLong(tOffset, aucBuffer);
256
		NO_DBG_HEX(ulHdrFtrOffset);
257
		aulCharPos[tIndex] = ulHdrFtrOffset2CharPos(ulHdrFtrOffset);
258
		NO_DBG_HEX(aulCharPos[tIndex]);
259
	}
260
	vCreat2HdrFtrInfoList(aulCharPos, tLen);
261
	aulCharPos = xfree(aulCharPos);
262
	aucBuffer = xfree(aucBuffer);
263
} /* end of vGet2HdrFtrInfo */
264
 
265
/*
266
 * Translate the rowinfo to a member of the row_info enumeration
267
 */
268
row_info_enum
269
eGet2RowInfo(int iFodo,
270
	const UCHAR *aucGrpprl, int iBytes, row_block_type *pRow)
271
{
272
	int	iFodoOff, iInfoLen;
273
	int	iIndex, iSize, iCol;
274
	int	iPosCurr, iPosPrev;
275
	USHORT	usTmp;
276
	BOOL	bFound24_0, bFound24_1, bFound25_0, bFound25_1, bFound154;
277
 
278
	fail(iFodo < 0 || aucGrpprl == NULL || pRow == NULL);
279
 
280
	iFodoOff = 0;
281
	bFound24_0 = FALSE;
282
	bFound24_1 = FALSE;
283
	bFound25_0 = FALSE;
284
	bFound25_1 = FALSE;
285
	bFound154 = FALSE;
286
	while (iBytes >= iFodoOff + 1) {
287
		iInfoLen = 0;
288
		switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) {
289
		case  24:	/* fIntable */
290
			if (odd(ucGetByte(iFodo + iFodoOff + 1, aucGrpprl))) {
291
				bFound24_1 = TRUE;
292
			} else {
293
				bFound24_0 = TRUE;
294
			}
295
			break;
296
		case  25:	/* fTtp */
297
			if (odd(ucGetByte(iFodo + iFodoOff + 1, aucGrpprl))) {
298
				bFound25_1 = TRUE;
299
			} else {
300
				bFound25_0 = TRUE;
301
			}
302
			break;
303
		case 30:	/* brcTop10 */
304
			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
305
			usTmp &= 0x01ff;
306
			NO_DBG_DEC(usTmp >> 6);
307
			if (usTmp == 0) {
308
				pRow->ucBorderInfo &= ~TABLE_BORDER_TOP;
309
			} else {
310
				pRow->ucBorderInfo |= TABLE_BORDER_TOP;
311
			}
312
			break;
313
		case 31:	/* brcLeft10 */
314
			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
315
			usTmp &= 0x01ff;
316
			NO_DBG_DEC(usTmp >> 6);
317
			if (usTmp == 0) {
318
				pRow->ucBorderInfo &= ~TABLE_BORDER_LEFT;
319
			} else {
320
				pRow->ucBorderInfo |= TABLE_BORDER_LEFT;
321
			}
322
			break;
323
		case 32:	/* brcBottom10 */
324
			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
325
			usTmp &= 0x01ff;
326
			NO_DBG_DEC(usTmp >> 6);
327
			if (usTmp == 0) {
328
				pRow->ucBorderInfo &= ~TABLE_BORDER_BOTTOM;
329
			} else {
330
				pRow->ucBorderInfo |= TABLE_BORDER_BOTTOM;
331
			}
332
			break;
333
		case 33:	/* brcRight10 */
334
			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
335
			usTmp &= 0x01ff;
336
			NO_DBG_DEC(usTmp >> 6);
337
			if (usTmp == 0) {
338
				pRow->ucBorderInfo &= ~TABLE_BORDER_RIGHT;
339
			} else {
340
				pRow->ucBorderInfo |= TABLE_BORDER_RIGHT;
341
			}
342
			break;
343
		case 38:	/* brcTop */
344
			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
345
			usTmp &= 0x0018;
346
			NO_DBG_DEC(usTmp >> 3);
347
			if (usTmp == 0) {
348
				pRow->ucBorderInfo &= ~TABLE_BORDER_TOP;
349
			} else {
350
				pRow->ucBorderInfo |= TABLE_BORDER_TOP;
351
			}
352
			break;
353
		case 39:	/* brcLeft */
354
			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
355
			usTmp &= 0x0018;
356
			NO_DBG_DEC(usTmp >> 3);
357
			if (usTmp == 0) {
358
				pRow->ucBorderInfo &= ~TABLE_BORDER_LEFT;
359
			} else {
360
				pRow->ucBorderInfo |= TABLE_BORDER_LEFT;
361
			}
362
			break;
363
		case 40:	/* brcBottom */
364
			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
365
			usTmp &= 0x0018;
366
			NO_DBG_DEC(usTmp >> 3);
367
			if (usTmp == 0) {
368
				pRow->ucBorderInfo &= ~TABLE_BORDER_BOTTOM;
369
			} else {
370
				pRow->ucBorderInfo |= TABLE_BORDER_BOTTOM;
371
			}
372
			break;
373
		case 41:	/* brcRight */
374
			usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
375
			usTmp &= 0x0018;
376
			NO_DBG_DEC(usTmp >> 3);
377
			if (usTmp == 0) {
378
				pRow->ucBorderInfo &= ~TABLE_BORDER_RIGHT;
379
			} else {
380
				pRow->ucBorderInfo |= TABLE_BORDER_RIGHT;
381
			}
382
			break;
383
		case 152:	/* cDefTable10 */
384
		case 154:	/* cDefTable */
385
			iSize = (int)usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
386
			if (iSize < 6 || iBytes < iFodoOff + 7) {
387
				DBG_DEC(iSize);
388
				DBG_DEC(iBytes);
389
				DBG_DEC(iFodoOff);
390
				iInfoLen = 1;
391
				break;
392
			}
393
			iCol = (int)ucGetByte(iFodo + iFodoOff + 3, aucGrpprl);
394
			if (iCol < 1 ||
395
			    iBytes < iFodoOff + 3 + (iCol + 1) * 2) {
396
				DBG_DEC(iCol);
397
				DBG_DEC(iBytes);
398
				DBG_DEC(iFodoOff);
399
				DBG_DEC(ucGetByte(iFodo + iFodoOff, aucGrpprl));
400
				iInfoLen = 1;
401
				break;
402
			}
403
			if (iCol >= (int)elementsof(pRow->asColumnWidth)) {
404
				DBG_DEC(iCol);
405
				werr(1, "The number of columns is corrupt");
406
			}
407
			pRow->ucNumberOfColumns = (UCHAR)iCol;
408
			iPosPrev = (int)(short)usGetWord(
409
					iFodo + iFodoOff + 4,
410
					aucGrpprl);
411
			for (iIndex = 0; iIndex < iCol; iIndex++) {
412
				iPosCurr = (int)(short)usGetWord(
413
					iFodo + iFodoOff + 6 + iIndex * 2,
414
					aucGrpprl);
415
				pRow->asColumnWidth[iIndex] =
416
						(short)(iPosCurr - iPosPrev);
417
				iPosPrev = iPosCurr;
418
			}
419
			bFound154 = TRUE;
420
			break;
421
		default:
422
			break;
423
		}
424
		if (iInfoLen <= 0) {
425
			iInfoLen =
426
				iGet2InfoLength(iFodo + iFodoOff, aucGrpprl);
427
			fail(iInfoLen <= 0);
428
		}
429
		iFodoOff += iInfoLen;
430
	}
431
	if (bFound24_1 && bFound25_1 && bFound154) {
432
		return found_end_of_row;
433
	}
434
	if (bFound24_0 && bFound25_0 && !bFound154) {
435
		return found_not_end_of_row;
436
	}
437
	if (bFound24_1) {
438
		return found_a_cell;
439
	}
440
	if (bFound24_0) {
441
		return found_not_a_cell;
442
	}
443
	return found_nothing;
444
} /* end of eGet2RowInfo */
445
 
446
/*
447
 * Fill the style information block with information
448
 * from a WinWord 1/2 file.
449
 */
450
void
451
vGet2StyleInfo(int iFodo,
452
	const UCHAR *aucGrpprl, int iBytes, style_block_type *pStyle)
453
{
454
	int	iFodoOff, iInfoLen;
455
	int	iTmp, iDel, iAdd;
456
	short	sTmp;
457
	UCHAR	ucTmp;
458
 
459
	fail(iFodo < 0 || aucGrpprl == NULL || pStyle == NULL);
460
 
461
	NO_DBG_DEC(pStyle->usIstd);
462
 
463
	iFodoOff = 0;
464
	while (iBytes >= iFodoOff + 1) {
465
		iInfoLen = 0;
466
		switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) {
467
		case   2:	/* istd */
468
			sTmp = (short)ucGetByte(
469
					iFodo + iFodoOff + 1, aucGrpprl);
470
			NO_DBG_DEC(sTmp);
471
			break;
472
		case   5:	/* jc */
473
			pStyle->ucAlignment = ucGetByte(
474
					iFodo + iFodoOff + 1, aucGrpprl);
475
			break;
476
		case  12:	/* nfcSeqNumb */
477
			pStyle->ucNFC = ucGetByte(
478
					iFodo + iFodoOff + 1, aucGrpprl);
479
			break;
480
		case  13:	/* nLvlAnm */
481
			ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
482
			pStyle->ucNumLevel = ucTmp;
483
			pStyle->bNumPause =
484
				eGetNumType(ucTmp) == level_type_pause;
485
			break;
486
		case  15:	/* ChgTabsPapx */
487
		case  23:	/* ChgTabs */
488
			iTmp = (int)ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
489
			if (iTmp < 2) {
490
				iInfoLen = 1;
491
				break;
492
			}
493
			NO_DBG_DEC(iTmp);
494
			iDel = (int)ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
495
			if (iTmp < 2 + 2 * iDel) {
496
				iInfoLen = 1;
497
				break;
498
			}
499
			NO_DBG_DEC(iDel);
500
			iAdd = (int)ucGetByte(
501
				iFodo + iFodoOff + 3 + 2 * iDel, aucGrpprl);
502
			if (iTmp < 2 + 2 * iDel + 2 * iAdd) {
503
				iInfoLen = 1;
504
				break;
505
			}
506
			NO_DBG_DEC(iAdd);
507
			break;
508
		case  16:	/* dxaRight */
509
			pStyle->sRightIndent = (short)usGetWord(
510
					iFodo + iFodoOff + 1, aucGrpprl);
511
			NO_DBG_DEC(pStyle->sRightIndent);
512
			break;
513
		case  17:	/* dxaLeft */
514
			pStyle->sLeftIndent = (short)usGetWord(
515
					iFodo + iFodoOff + 1, aucGrpprl);
516
			NO_DBG_DEC(pStyle->sLeftIndent);
517
			break;
518
		case  18:	/* Nest dxaLeft */
519
			sTmp = (short)usGetWord(
520
					iFodo + iFodoOff + 1, aucGrpprl);
521
			pStyle->sLeftIndent += sTmp;
522
			if (pStyle->sLeftIndent < 0) {
523
				pStyle->sLeftIndent = 0;
524
			}
525
			NO_DBG_DEC(sTmp);
526
			NO_DBG_DEC(pStyle->sLeftIndent);
527
			break;
528
		case  19:	/* dxaLeft1 */
529
			pStyle->sLeftIndent1 = (short)usGetWord(
530
					iFodo + iFodoOff + 1, aucGrpprl);
531
			NO_DBG_DEC(pStyle->sLeftIndent1);
532
			break;
533
		case  21:	/* dyaBefore */
534
			pStyle->usBeforeIndent = usGetWord(
535
					iFodo + iFodoOff + 1, aucGrpprl);
536
			NO_DBG_DEC(pStyle->usBeforeIndent);
537
			break;
538
		case  22:	/* dyaAfter */
539
			pStyle->usAfterIndent = usGetWord(
540
					iFodo + iFodoOff + 1, aucGrpprl);
541
			NO_DBG_DEC(pStyle->usAfterIndent);
542
			break;
543
		default:
544
			break;
545
		}
546
		if (iInfoLen <= 0) {
547
			iInfoLen =
548
				iGet2InfoLength(iFodo + iFodoOff, aucGrpprl);
549
			fail(iInfoLen <= 0);
550
		}
551
		iFodoOff += iInfoLen;
552
	}
553
} /* end of vGet2StyleInfo */
554
 
555
/*
556
 * Build the lists with Paragraph Information for WinWord 1/2 files
557
 */
558
void
559
vGet2PapInfo(FILE *pFile, const UCHAR *aucHeader)
560
{
561
	row_block_type		tRow;
562
	style_block_type	tStyle;
563
	USHORT	*ausParfPage;
564
	UCHAR	*aucBuffer;
565
	ULONG	ulCharPos, ulCharPosFirst, ulCharPosLast;
566
	ULONG	ulBeginParfInfo;
567
	size_t	tParfInfoLen, tParfPageNum, tOffset, tSize, tLenOld, tLen;
568
	int	iIndex, iIndex2, iRun, iFodo, iLen;
569
	row_info_enum	eRowInfo;
570
	USHORT	usParfFirstPage, usCount, usIstd;
571
	UCHAR	ucStc;
572
	UCHAR	aucFpage[BIG_BLOCK_SIZE];
573
 
574
	fail(pFile == NULL || aucHeader == NULL);
575
 
576
	ulBeginParfInfo = ulGetLong(0xa6, aucHeader); /* fcPlcfbtePapx */
577
	NO_DBG_HEX(ulBeginParfInfo);
578
	tParfInfoLen = (size_t)usGetWord(0xaa, aucHeader); /* cbPlcfbtePapx */
579
	NO_DBG_DEC(tParfInfoLen);
580
	if (tParfInfoLen < 4) {
581
		DBG_DEC(tParfInfoLen);
582
		return;
583
	}
584
 
585
	aucBuffer = xmalloc(tParfInfoLen);
586
	if (!bReadBytes(aucBuffer, tParfInfoLen, ulBeginParfInfo, pFile)) {
587
		aucBuffer = xfree(aucBuffer);
588
		return;
589
	}
590
	NO_DBG_PRINT_BLOCK(aucBuffer, tParfInfoLen);
591
 
592
	tLen = (tParfInfoLen - 4) / 6;
593
	ausParfPage = xcalloc(tLen, sizeof(USHORT));
594
	for (iIndex = 0, tOffset = (tLen + 1) * 4;
595
	     iIndex < (int)tLen;
596
	     iIndex++, tOffset += 2) {
597
		ausParfPage[iIndex] = usGetWord(tOffset, aucBuffer);
598
		NO_DBG_DEC(ausParfPage[iIndex]);
599
	}
600
	DBG_HEX(ulGetLong(0, aucBuffer));
601
	aucBuffer = xfree(aucBuffer);
602
	tParfPageNum = (size_t)usGetWord(0x144, aucHeader); /* cpnBtePap */
603
	DBG_DEC(tParfPageNum);
604
	if (tLen < tParfPageNum) {
605
		/* Replace ParfPage by a longer version */
606
		tLenOld = tLen;
607
		usParfFirstPage = usGetWord(0x140, aucHeader); /* pnPapFirst */
608
		DBG_DEC(usParfFirstPage);
609
		tLen += tParfPageNum - 1;
610
		tSize = tLen * sizeof(USHORT);
611
		ausParfPage = xrealloc(ausParfPage, tSize);
612
		/* Add new values */
613
		usCount = usParfFirstPage + 1;
614
		for (iIndex = (int)tLenOld; iIndex < (int)tLen; iIndex++) {
615
			ausParfPage[iIndex] = usCount;
616
			NO_DBG_DEC(ausParfPage[iIndex]);
617
			usCount++;
618
		}
619
	}
620
 
621
	(void)memset(&tRow, 0, sizeof(tRow));
622
	ulCharPosFirst = CP_INVALID;
623
	for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
624
		if (!bReadBytes(aucFpage, BIG_BLOCK_SIZE,
625
				(ULONG)ausParfPage[iIndex] * BIG_BLOCK_SIZE,
626
				pFile)) {
627
			break;
628
		}
629
		NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE);
630
		iRun = (int)ucGetByte(0x1ff, aucFpage);
631
		NO_DBG_DEC(iRun);
632
		for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
633
			if ((iRun + 1) * 4 + iIndex2 * 1 >= BIG_BLOCK_SIZE) {
634
				break;
635
			}
636
			NO_DBG_HEX(ulGetLong(iIndex2 * 4, aucFpage));
637
			iFodo = 2 * (int)ucGetByte(
638
				(iRun + 1) * 4 + iIndex2 * 1, aucFpage);
639
			if (iFodo <= 0) {
640
				continue;
641
			}
642
 
643
			iLen = 2 * (int)ucGetByte(iFodo, aucFpage);
644
 
645
			ucStc = ucGetByte(iFodo + 1, aucFpage);
646
			usIstd = usStc2istd(ucStc);
647
 
648
			vFillStyleFromStylesheet(usIstd, &tStyle);
649
			vGet2StyleInfo(iFodo, aucFpage + 8, iLen - 8, &tStyle);
650
			ulCharPos = ulGetLong(iIndex2 * 4, aucFpage);
651
			NO_DBG_HEX(ulCharPos);
652
			tStyle.ulFileOffset = ulCharPos;
653
			vAdd2StyleInfoList(&tStyle);
654
 
655
			eRowInfo = eGet2RowInfo(iFodo,
656
					aucFpage + 8, iLen - 8, &tRow);
657
 
658
			switch(eRowInfo) {
659
			case found_a_cell:
660
				if (ulCharPosFirst != CP_INVALID) {
661
					break;
662
				}
663
				ulCharPosFirst = ulGetLong(
664
						iIndex2 * 4, aucFpage);
665
				NO_DBG_HEX(ulCharPosFirst);
666
				tRow.ulCharPosStart = ulCharPosFirst;
667
				tRow.ulFileOffsetStart = ulCharPosFirst;
668
				break;
669
			case found_end_of_row:
670
				ulCharPosLast = ulGetLong(
671
						iIndex2 * 4, aucFpage);
672
				NO_DBG_HEX(ulCharPosLast);
673
				tRow.ulCharPosEnd = ulCharPosLast;
674
				/* Add 1 for compatiblity with Word 6 and up */
675
				tRow.ulFileOffsetEnd = ulCharPosLast + 1;
676
				vAdd2RowInfoList(&tRow);
677
				(void)memset(&tRow, 0, sizeof(tRow));
678
				ulCharPosFirst = CP_INVALID;
679
				break;
680
			case found_nothing:
681
				break;
682
			default:
683
				DBG_DEC(eRowInfo);
684
				break;
685
			}
686
		}
687
	}
688
	ausParfPage = xfree(ausParfPage);
689
} /* end of vGet2PapInfo */
690
 
691
/*
692
 * Fill the font information block with information
693
 * from a WinWord 1 file.
694
 */
695
void
696
vGet1FontInfo(int iFodo,
697
	const UCHAR *aucGrpprl, size_t tBytes, font_block_type *pFont)
698
{
699
	BOOL	bIcoChange, bFtcChange, bHpsChange, bKulChange;
700
	USHORT	usTmp;
701
	UCHAR	ucTmp;
702
	UCHAR	aucChpx[12];
703
 
704
	fail(iFodo < 0 || aucGrpprl == NULL || pFont == NULL);
705
 
706
	if (tBytes > sizeof(aucChpx)) {
707
		NO_DBG_PRINT_BLOCK(aucGrpprl + iFodo, tBytes);
708
		return;
709
	}
710
 
711
	/* Build the CHPX structure */
712
	(void)memset(aucChpx, 0, sizeof(aucChpx));
713
	(void)memcpy(aucChpx, aucGrpprl + iFodo, min(tBytes, sizeof(aucChpx)));
714
 
715
	usTmp = usGetWord(0, aucChpx);
716
	if ((usTmp & BIT(0)) != 0) {
717
		pFont->usFontStyle ^= FONT_BOLD;
718
	}
719
	if ((usTmp & BIT(1)) != 0) {
720
		pFont->usFontStyle ^= FONT_ITALIC;
721
	}
722
	if ((usTmp & BIT(2)) != 0) {
723
		pFont->usFontStyle ^= FONT_STRIKE;
724
	}
725
	if ((usTmp & BIT(5)) != 0) {
726
		pFont->usFontStyle ^= FONT_SMALL_CAPITALS;
727
	}
728
	if ((usTmp & BIT(6)) != 0) {
729
		pFont->usFontStyle ^= FONT_CAPITALS;
730
	}
731
	if ((usTmp & BIT(7)) != 0) {
732
		pFont->usFontStyle ^= FONT_HIDDEN;
733
	}
734
 
735
	ucTmp = ucGetByte(5, aucChpx);
736
	if (ucTmp != 0) {
737
		if (ucTmp < 128) {
738
			pFont->usFontStyle |= FONT_SUPERSCRIPT;
739
			DBG_MSG("Superscript");
740
		} else {
741
			pFont->usFontStyle |= FONT_SUBSCRIPT;
742
			DBG_MSG("Subscript");
743
		}
744
	}
745
 
746
	bIcoChange = (usTmp & BIT(10)) != 0;
747
	bFtcChange = (usTmp & BIT(11)) != 0;
748
	bHpsChange = (usTmp & BIT(12)) != 0;
749
	bKulChange = (usTmp & BIT(13)) != 0;
750
 
751
	if (bFtcChange) {
752
		usTmp = usGetWord(2, aucChpx);
753
		if (usTmp <= (USHORT)UCHAR_MAX) {
754
			pFont->ucFontNumber = (UCHAR)usTmp;
755
		} else {
756
			pFont->ucFontNumber = 0;
757
		}
758
	}
759
 
760
	if (bHpsChange) {
761
		pFont->usFontSize = (USHORT)ucGetByte(4, aucChpx);
762
	}
763
 
764
	if (bIcoChange || bKulChange) {
765
		usTmp = usGetWord(6, aucChpx);
766
		if (bIcoChange) {
767
			pFont->ucFontColor = (UCHAR)((usTmp & 0x0f00) >> 8);
768
			if (pFont->ucFontColor <= 7) {
769
				/* Add 1 for compatibility with Word 2 and up */
770
				pFont->ucFontColor++;
771
			} else {
772
				DBG_DEC(pFont->ucFontColor);
773
				pFont->ucFontColor = 0;
774
			}
775
		}
776
		if (bKulChange) {
777
			usTmp = (usTmp & 0x7000) >> 12;
778
			DBG_DEC_C(usTmp > 4, usTmp);
779
			if (usTmp == 0) {
780
				pFont->usFontStyle &= ~FONT_UNDERLINE;
781
			} else {
782
				pFont->usFontStyle |= FONT_UNDERLINE;
783
			}
784
		}
785
	}
786
} /* end of vGet1FontInfo */
787
 
788
/*
789
 * Fill the font information block with information
790
 * from a WinWord 1/2 file.
791
 */
792
void
793
vGet2FontInfo(int iFodo,
794
	const UCHAR *aucGrpprl, size_t tBytes, font_block_type *pFont)
795
{
796
	BOOL	bIcoChange, bFtcChange, bHpsChange, bKulChange;
797
	USHORT	usTmp;
798
	UCHAR	ucTmp;
799
	UCHAR	aucChpx[18];
800
 
801
	fail(iFodo < 0 || aucGrpprl == NULL || pFont == NULL);
802
 
803
	if (tBytes > sizeof(aucChpx)) {
804
		NO_DBG_PRINT_BLOCK(aucGrpprl + iFodo, tBytes);
805
		return;
806
	}
807
 
808
	/* Build the CHPX structure */
809
	(void)memset(aucChpx, 0, sizeof(aucChpx));
810
	(void)memcpy(aucChpx, aucGrpprl + iFodo, min(tBytes, sizeof(aucChpx)));
811
 
812
	usTmp = usGetWord(0, aucChpx);
813
	if ((usTmp & BIT(0)) != 0) {
814
		pFont->usFontStyle ^= FONT_BOLD;
815
	}
816
	if ((usTmp & BIT(1)) != 0) {
817
		pFont->usFontStyle ^= FONT_ITALIC;
818
	}
819
	if (usTmp & BIT(3)) {
820
		pFont->usFontStyle ^= FONT_MARKDEL;
821
	}
822
	if ((usTmp & BIT(5)) != 0) {
823
		pFont->usFontStyle ^= FONT_SMALL_CAPITALS;
824
	}
825
	if ((usTmp & BIT(6)) != 0) {
826
		pFont->usFontStyle ^= FONT_CAPITALS;
827
	}
828
	if ((usTmp & BIT(7)) != 0) {
829
		pFont->usFontStyle ^= FONT_HIDDEN;
830
	}
831
	if (usTmp & BIT(10)) {
832
		pFont->usFontStyle ^= FONT_STRIKE;
833
	}
834
 
835
	ucTmp = ucGetByte(10, aucChpx);
836
	DBG_MSG_C(ucTmp != 0 && ucTmp < 128, "Superscript");
837
	DBG_MSG_C(ucTmp >= 128, "Subscript");
838
 
839
	usTmp = usGetWord(2, aucChpx);
840
	if (usTmp == 0) {
841
		/* No changes, nothing to do */
842
		return;
843
	}
844
 
845
	bIcoChange = (usTmp & BIT(0)) != 0;
846
	bFtcChange = (usTmp & BIT(1)) != 0;
847
	bHpsChange = (usTmp & BIT(2)) != 0;
848
	bKulChange = (usTmp & BIT(3)) != 0;
849
 
850
	if (bFtcChange) {
851
		usTmp = usGetWord(4, aucChpx);
852
		if (usTmp <= (USHORT)UCHAR_MAX) {
853
			pFont->ucFontNumber = (UCHAR)usTmp;
854
		} else {
855
			pFont->ucFontNumber = 0;
856
		}
857
	}
858
 
859
	if (bHpsChange) {
860
		pFont->usFontSize = usGetWord(6, aucChpx);
861
	}
862
 
863
	if (bIcoChange || bKulChange) {
864
		ucTmp = ucGetByte(9, aucChpx);
865
		if (bIcoChange) {
866
			pFont->ucFontColor = ucTmp & 0x1f;
867
			if (pFont->ucFontColor > 16) {
868
				DBG_DEC(pFont->ucFontColor);
869
				pFont->ucFontColor = 0;
870
			}
871
		}
872
		if (bKulChange) {
873
			ucTmp = (ucTmp & 0xe0) >> 5;
874
			DBG_DEC_C(ucTmp > 4, ucTmp);
875
			if (ucTmp == 0) {
876
				pFont->usFontStyle &= ~FONT_UNDERLINE;
877
			} else {
878
				pFont->usFontStyle |= FONT_UNDERLINE;
879
			}
880
		}
881
	}
882
} /* end of vGet2FontInfo */
883
 
884
/*
885
 * Fill the picture information block with information from a WinWord 1 file.
886
 * Returns TRUE when successful, otherwise FALSE
887
 */
888
static BOOL
889
bGet1PicInfo(int iFodo,
890
	const UCHAR *aucGrpprl, size_t tBytes, picture_block_type *pPicture)
891
{
892
	ULONG	ulTmp;
893
	UCHAR	aucChpx[12];
894
 
895
	fail(iFodo < 0 || aucGrpprl == NULL || pPicture == NULL);
896
 
897
	if (tBytes > sizeof(aucChpx)) {
898
		NO_DBG_PRINT_BLOCK(aucGrpprl + iFodo, tBytes);
899
		tBytes = sizeof(aucChpx);
900
	}
901
 
902
	/* Build the CHPX structure */
903
	(void)memset(aucChpx, 0, sizeof(aucChpx));
904
	(void)memcpy(aucChpx, aucGrpprl + iFodo, min(tBytes, sizeof(aucChpx)));
905
 
906
	ulTmp = ulGetLong(8, aucChpx);
907
	if (ulTmp != 0 && ulTmp < MAX_FILESIZE) {
908
		pPicture->ulPictureOffset = ulTmp;
909
		DBG_HEX(pPicture->ulPictureOffset);
910
		return TRUE;
911
	}
912
	return FALSE;
913
} /* end of bGet1PicInfo */
914
 
915
/*
916
 * Fill the picture information block with information from a WinWord 2 file.
917
 * Returns TRUE when successful, otherwise FALSE
918
 */
919
static BOOL
920
bGet2PicInfo(int iFodo,
921
	const UCHAR *aucGrpprl, size_t tBytes, picture_block_type *pPicture)
922
{
923
	ULONG	ulTmp;
924
	UCHAR	aucChpx[18];
925
 
926
	fail(iFodo < 0 || aucGrpprl == NULL || pPicture == NULL);
927
 
928
	if (tBytes > sizeof(aucChpx)) {
929
		NO_DBG_PRINT_BLOCK(aucGrpprl + iFodo, tBytes);
930
		tBytes = sizeof(aucChpx);
931
	}
932
 
933
	/* Build the CHPX structure */
934
	(void)memset(aucChpx, 0, sizeof(aucChpx));
935
	(void)memcpy(aucChpx, aucGrpprl + iFodo, min(tBytes, sizeof(aucChpx)));
936
 
937
	ulTmp = ulGetLong(14, aucChpx);
938
	if (ulTmp != 0 && ulTmp < MAX_FILESIZE) {
939
		pPicture->ulPictureOffset = ulTmp;
940
		DBG_HEX(pPicture->ulPictureOffset);
941
		DBG_DEC(tBytes);
942
		return TRUE;
943
	}
944
	return FALSE;
945
} /* end of bGet2PicInfo */
946
 
947
/*
948
 * Build the lists with Character Information for WinWord 1/2 files
949
 */
950
void
951
vGet2ChrInfo(FILE *pFile, int iWordVersion, const UCHAR *aucHeader)
952
{
953
	font_block_type		tFont;
954
	picture_block_type	tPicture;
955
	USHORT	*ausCharPage;
956
	UCHAR	*aucBuffer;
957
	ULONG	ulFileOffset, ulCharPos, ulBeginCharInfo;
958
	size_t	tCharInfoLen, tOffset, tSize, tChrLen, tCharPageNum;
959
	size_t	tLenOld, tLen;
960
	int	iIndex, iIndex2, iRun, iFodo;
961
	BOOL	bSuccess1, bSuccess2;
962
	USHORT	usCharFirstPage, usCount, usIstd;
963
	UCHAR	aucFpage[BIG_BLOCK_SIZE];
964
 
965
	fail(pFile == NULL || aucHeader == NULL);
966
	fail(iWordVersion != 1 && iWordVersion != 2);
967
 
968
	ulBeginCharInfo = ulGetLong(0xa0, aucHeader); /* fcPlcfbteChpx */
969
	DBG_HEX(ulBeginCharInfo);
970
	tCharInfoLen = (size_t)usGetWord(0xa4, aucHeader); /* cbPlcfbteChpx */
971
	DBG_DEC(tCharInfoLen);
972
	if (tCharInfoLen < 4) {
973
		DBG_DEC(tCharInfoLen);
974
		return;
975
	}
976
 
977
	aucBuffer = xmalloc(tCharInfoLen);
978
	if (!bReadBytes(aucBuffer, tCharInfoLen, ulBeginCharInfo, pFile)) {
979
		aucBuffer = xfree(aucBuffer);
980
		return;
981
	}
982
	NO_DBG_PRINT_BLOCK(aucBuffer, tCharInfoLen);
983
 
984
	tLen = (tCharInfoLen - 4) / 6;
985
	ausCharPage = xcalloc(tLen, sizeof(USHORT));
986
	for (iIndex = 0, tOffset = (tLen + 1) * 4;
987
	     iIndex < (int)tLen;
988
	     iIndex++, tOffset += 2) {
989
		ausCharPage[iIndex] = usGetWord(tOffset, aucBuffer);
990
		NO_DBG_DEC(ausCharPage[iIndex]);
991
	}
992
	DBG_HEX(ulGetLong(0, aucBuffer));
993
	aucBuffer = xfree(aucBuffer);
994
	tCharPageNum = (size_t)usGetWord(0x142, aucHeader); /* cpnBteChp */
995
	DBG_DEC(tCharPageNum);
996
	if (tLen < tCharPageNum) {
997
		/* Replace CharPage by a longer version */
998
		tLenOld = tLen;
999
		usCharFirstPage = usGetWord(0x13e, aucHeader); /* pnChrFirst */
1000
		NO_DBG_DEC(usCharFirstPage);
1001
		tLen += tCharPageNum - 1;
1002
		tSize = tLen * sizeof(USHORT);
1003
		ausCharPage = xrealloc(ausCharPage, tSize);
1004
		/* Add new values */
1005
		usCount = usCharFirstPage + 1;
1006
		for (iIndex = (int)tLenOld; iIndex < (int)tLen; iIndex++) {
1007
			ausCharPage[iIndex] = usCount;
1008
			NO_DBG_DEC(ausCharPage[iIndex]);
1009
			usCount++;
1010
		}
1011
	}
1012
 
1013
	for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
1014
		if (!bReadBytes(aucFpage, BIG_BLOCK_SIZE,
1015
				(ULONG)ausCharPage[iIndex] * BIG_BLOCK_SIZE,
1016
				pFile)) {
1017
			break;
1018
		}
1019
		NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE);
1020
		iRun = (int)ucGetByte(0x1ff, aucFpage);
1021
		NO_DBG_DEC(iRun);
1022
		for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
1023
			if ((iRun + 1) * 4 + iIndex2 >= BIG_BLOCK_SIZE) {
1024
				break;
1025
			}
1026
			ulCharPos = ulGetLong(iIndex2 * 4, aucFpage);
1027
			ulFileOffset = ulCharPos;
1028
			iFodo = 2 * (int)ucGetByte(
1029
				(iRun + 1) * 4 + iIndex2, aucFpage);
1030
 
1031
			tChrLen = (size_t)ucGetByte(iFodo, aucFpage);
1032
 
1033
			usIstd = usGetIstd(ulFileOffset);
1034
			vFillFontFromStylesheet(usIstd, &tFont);
1035
			if (iFodo != 0) {
1036
				if (iWordVersion == 1) {
1037
					vGet1FontInfo(iFodo,
1038
						aucFpage + 1, tChrLen, &tFont);
1039
				} else if (iWordVersion == 2) {
1040
					vGet2FontInfo(iFodo,
1041
						aucFpage + 1, tChrLen, &tFont);
1042
				}
1043
			}
1044
			tFont.ulFileOffset = ulFileOffset;
1045
			vAdd2FontInfoList(&tFont);
1046
 
1047
			if (iFodo <= 0) {
1048
				continue;
1049
			}
1050
 
1051
			(void)memset(&tPicture, 0, sizeof(tPicture));
1052
			bSuccess1 = iWordVersion == 1 &&
1053
					bGet1PicInfo(iFodo, aucFpage + 1,
1054
						tChrLen, &tPicture);
1055
			bSuccess2 = iWordVersion == 2 &&
1056
					bGet2PicInfo(iFodo, aucFpage + 1,
1057
						tChrLen, &tPicture);
1058
			if (bSuccess1 || bSuccess2) {
1059
				tPicture.ulFileOffset = ulFileOffset;
1060
				tPicture.ulFileOffsetPicture =
1061
						tPicture.ulPictureOffset;
1062
				vAdd2PictInfoList(&tPicture);
1063
			}
1064
		}
1065
	}
1066
	ausCharPage = xfree(ausCharPage);
1067
} /* end of vGet2ChrInfo */