xref: /plan9/sys/src/cmd/aux/antiword/prop8.c (revision 25b329d522281a8cdd35da0dcc08c3fc621059a9)
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
iGet8InfoLength(int iByteNbr,const UCHAR * aucGrpprl)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 *
aucFillInfoBuffer(FILE * pFile,const pps_type * pTable,const ULONG * aulBBD,size_t tBBDLen,const ULONG * aulSBD,size_t tSBDLen,ULONG ulBeginInfo,size_t tInfoLen)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
vGet8DopInfo(FILE * pFile,const pps_type * pTable,const ULONG * aulBBD,size_t tBBDLen,const ULONG * aulSBD,size_t tSBDLen,const UCHAR * aucHeader)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
vGet8SectionInfo(const UCHAR * aucGrpprl,size_t tBytes,section_block_type * pSection)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
vGet8SepInfo(FILE * pFile,const pps_info_type * pPPS,const ULONG * aulBBD,size_t tBBDLen,const ULONG * aulSBD,size_t tSBDLen,const UCHAR * aucHeader)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
vGet8HdrFtrInfo(FILE * pFile,const pps_type * pTable,const ULONG * aulBBD,size_t tBBDLen,const ULONG * aulSBD,size_t tSBDLen,const UCHAR * aucHeader)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
eGet8RowInfo(int iFodo,const UCHAR * aucGrpprl,int iBytes,row_block_type * pRow)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
vGet8StyleInfo(int iFodo,const UCHAR * aucGrpprl,int iBytes,style_block_type * pStyle)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
sGetLeftIndent(const UCHAR * aucGrpprl,size_t tBytes)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
vGet8LstInfo(FILE * pFile,const pps_info_type * pPPS,const ULONG * aulBBD,size_t tBBDLen,const ULONG * aulSBD,size_t tSBDLen,const UCHAR * aucHeader)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
vGet8PapInfo(FILE * pFile,const pps_info_type * pPPS,const ULONG * aulBBD,size_t tBBDLen,const ULONG * aulSBD,size_t tSBDLen,const UCHAR * aucHeader)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
vGet8FontInfo(int iFodo,USHORT usIstd,const UCHAR * aucGrpprl,int iBytes,font_block_type * pFont)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
bGet8PicInfo(int iFodo,const UCHAR * aucGrpprl,int iBytes,picture_block_type * pPicture)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
vGet8ChrInfo(FILE * pFile,const pps_info_type * pPPS,const ULONG * aulBBD,size_t tBBDLen,const ULONG * aulSBD,size_t tSBDLen,const UCHAR * aucHeader)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 */
1497