Imported from antiword-0.34.tar.gz.
[antiword.git] / prop8.c
blob49993fba69a8495d9dbe93a70c97db854359f848
1 /*
2 * prop8.c
3 * Copyright (C) 1998-2003 A.J. van Os; Released under GPL
5 * Description:
6 * Read the property information from a MS Word 8, 9 or 10 file
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
13 #include <stdlib.h>
14 #include <string.h>
15 #include "antiword.h"
17 #define DEFAULT_LISTCHAR 0x002e /* A full stop */
21 * iGet8InfoLength - the length of the information for Word 8/9/10 files
23 static int
24 iGet8InfoLength(int iByteNbr, const UCHAR *aucGrpprl)
26 int iTmp, iDel, iAdd;
27 USHORT usOpCode;
29 usOpCode = usGetWord(iByteNbr, aucGrpprl);
31 switch (usOpCode & 0xe000) {
32 case 0x0000: case 0x2000:
33 return 3;
34 case 0x4000: case 0x8000: case 0xa000:
35 return 4;
36 case 0xe000:
37 return 5;
38 case 0x6000:
39 return 6;
40 case 0xc000:
41 iTmp = (int)ucGetByte(iByteNbr + 2, aucGrpprl);
42 if (usOpCode == 0xc615 && iTmp == 255) {
43 iDel = (int)ucGetByte(iByteNbr + 3, aucGrpprl);
44 iAdd = (int)ucGetByte(
45 iByteNbr + 4 + iDel * 4, aucGrpprl);
46 iTmp = 2 + iDel * 4 + iAdd * 3;
48 return 3 + iTmp;
49 default:
50 DBG_HEX(usOpCode);
51 DBG_FIXME();
52 return 1;
54 } /* end of iGet8InfoLength */
57 * Fill the section information block with information
58 * from a Word 8/9/10 file.
60 static void
61 vGet8SectionInfo(const UCHAR *aucGrpprl, size_t tBytes,
62 section_block_type *pSection)
64 UINT uiIndex;
65 int iFodoOff, iInfoLen, iSize, iTmp;
66 USHORT usCcol;
67 UCHAR ucTmp;
69 fail(aucGrpprl == NULL || pSection == NULL);
71 iFodoOff = 0;
72 while (tBytes >= (size_t)iFodoOff + 2) {
73 iInfoLen = 0;
74 switch (usGetWord(iFodoOff, aucGrpprl)) {
75 case 0x3009: /* bkc */
76 ucTmp = ucGetByte(iFodoOff + 2, aucGrpprl);
77 DBG_DEC(ucTmp);
78 pSection->bNewPage = ucTmp != 0 && ucTmp != 1;
79 break;
80 case 0x500b: /* ccolM1 */
81 usCcol = 1 + usGetWord(iFodoOff + 2, aucGrpprl);
82 DBG_DEC(usCcol);
83 break;
84 case 0xd202: /* olstAnm */
85 iSize = (int)ucGetByte(iFodoOff + 2, aucGrpprl);
86 DBG_DEC_C(iSize != 212, iSize);
87 for (uiIndex = 0, iTmp = iFodoOff + 3;
88 uiIndex < 9 && iTmp < iFodoOff + 3 + iSize - 15;
89 uiIndex++, iTmp += 16) {
90 pSection->aucNFC[uiIndex] =
91 ucGetByte(iTmp, aucGrpprl);
92 DBG_DEC(pSection->aucNFC[uiIndex]);
93 ucTmp = ucGetByte(iTmp + 3, aucGrpprl);
94 DBG_HEX(ucTmp);
95 if ((ucTmp & BIT(2)) != 0) {
96 pSection->usNeedPrevLvl |=
97 (USHORT)BIT(uiIndex);
99 if ((ucTmp & BIT(3)) != 0) {
100 pSection->usHangingIndent |=
101 (USHORT)BIT(uiIndex);
104 DBG_HEX(pSection->usNeedPrevLvl);
105 DBG_HEX(pSection->usHangingIndent);
106 break;
107 default:
108 break;
110 if (iInfoLen <= 0) {
111 iInfoLen = iGet8InfoLength(iFodoOff, aucGrpprl);
112 fail(iInfoLen <= 0);
114 iFodoOff += iInfoLen;
116 } /* end of vGet8SectionInfo */
119 * Build the lists with Section Property Information for Word 8/9/10 files
121 void
122 vGet8SepInfo(FILE *pFile, const pps_info_type *pPPS,
123 const ULONG *aulBBD, size_t tBBDLen,
124 const ULONG *aulSBD, size_t tSBDLen,
125 const UCHAR *aucHeader)
127 section_block_type tSection;
128 ULONG *aulSectPage, *aulTextOffset;
129 const ULONG *aulBlockDepot;
130 UCHAR *aucBuffer, *aucFpage;
131 ULONG ulBeginSectInfo;
132 ULONG ulTableSize, ulTableStartBlock;
133 size_t tSectInfoLen, tBlockDepotLen;
134 size_t tBlockSize, tOffset, tLen, tBytes;
135 int iIndex;
136 USHORT usDocStatus;
137 UCHAR aucTmp[2];
139 fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
140 fail(aulBBD == NULL || aulSBD == NULL);
142 ulBeginSectInfo = ulGetLong(0xca, aucHeader); /* fcPlcfsed */
143 NO_DBG_HEX(ulBeginSectInfo);
144 tSectInfoLen = (size_t)ulGetLong(0xce, aucHeader); /* lcbPlcfsed */
145 NO_DBG_DEC(tSectInfoLen);
146 if (tSectInfoLen < 4) {
147 DBG_DEC(tSectInfoLen);
148 return;
151 /* Use 0Table or 1Table? */
152 usDocStatus = usGetWord(0x0a, aucHeader);
153 if (usDocStatus & BIT(9)) {
154 ulTableStartBlock = pPPS->t1Table.ulSB;
155 ulTableSize = pPPS->t1Table.ulSize;
156 } else {
157 ulTableStartBlock = pPPS->t0Table.ulSB;
158 ulTableSize = pPPS->t0Table.ulSize;
160 DBG_DEC(ulTableStartBlock);
161 if (ulTableStartBlock == 0) {
162 DBG_MSG("No section information");
163 return;
165 DBG_HEX(ulTableSize);
166 if (ulTableSize < MIN_SIZE_FOR_BBD_USE) {
167 /* Use the Small Block Depot */
168 aulBlockDepot = aulSBD;
169 tBlockDepotLen = tSBDLen;
170 tBlockSize = SMALL_BLOCK_SIZE;
171 } else {
172 /* Use the Big Block Depot */
173 aulBlockDepot = aulBBD;
174 tBlockDepotLen = tBBDLen;
175 tBlockSize = BIG_BLOCK_SIZE;
177 aucBuffer = xmalloc(tSectInfoLen);
178 if (!bReadBuffer(pFile, ulTableStartBlock,
179 aulBlockDepot, tBlockDepotLen, tBlockSize,
180 aucBuffer, ulBeginSectInfo, tSectInfoLen)) {
181 aucBuffer = xfree(aucBuffer);
182 return;
184 NO_DBG_PRINT_BLOCK(aucBuffer, tSectInfoLen);
186 /* Read the Section Descriptors */
187 tLen = (tSectInfoLen - 4) / 16;
188 /* Save the section offsets */
189 aulTextOffset = xcalloc(tLen, sizeof(ULONG));
190 for (iIndex = 0, tOffset = 0;
191 iIndex < (int)tLen;
192 iIndex++, tOffset += 4) {
193 aulTextOffset[iIndex] = ulGetLong(tOffset, aucBuffer);
195 /* Save the Sepx offsets */
196 aulSectPage = xcalloc(tLen, sizeof(ULONG));
197 for (iIndex = 0, tOffset = (tLen + 1) * 4;
198 iIndex < (int)tLen;
199 iIndex++, tOffset += 12) {
200 aulSectPage[iIndex] = ulGetLong(tOffset + 2, aucBuffer);
201 NO_DBG_HEX(aulSectPage[iIndex]); /* fcSepx */
203 aucBuffer = xfree(aucBuffer);
205 /* Read the Section Properties */
206 for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
207 if (aulSectPage[iIndex] == FC_INVALID) {
208 vDefault2SectionInfoList(aulTextOffset[iIndex]);
209 continue;
211 /* Get the number of bytes to read */
212 if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB,
213 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
214 aucTmp, aulSectPage[iIndex], 2)) {
215 continue;
217 tBytes = 2 + (size_t)usGetWord(0, aucTmp);
218 NO_DBG_DEC(tBytes);
219 /* Read the bytes */
220 aucFpage = xmalloc(tBytes);
221 if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB,
222 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
223 aucFpage, aulSectPage[iIndex], tBytes)) {
224 aucFpage = xfree(aucFpage);
225 continue;
227 NO_DBG_PRINT_BLOCK(aucFpage, tBytes);
228 /* Process the bytes */
229 vGetDefaultSection(&tSection);
230 vGet8SectionInfo(aucFpage + 2, tBytes - 2, &tSection);
231 vAdd2SectionInfoList(&tSection, aulTextOffset[iIndex]);
232 aucFpage = xfree(aucFpage);
234 aulTextOffset = xfree(aulTextOffset);
235 aulSectPage = xfree(aulSectPage);
236 } /* end of vGet8SepInfo */
239 * Translate the rowinfo to a member of the row_info enumeration
241 row_info_enum
242 eGet8RowInfo(int iFodo,
243 const UCHAR *aucGrpprl, int iBytes, row_block_type *pRow)
245 int iFodoOff, iInfoLen;
246 int iIndex, iSize, iCol;
247 int iPosCurr, iPosPrev;
248 USHORT usTmp;
249 BOOL bFound2416_0, bFound2416_1, bFound2417_0, bFound2417_1;
250 BOOL bFoundd608;
252 fail(iFodo < 0 || aucGrpprl == NULL || pRow == NULL);
254 iFodoOff = 0;
255 bFound2416_0 = FALSE;
256 bFound2416_1 = FALSE;
257 bFound2417_0 = FALSE;
258 bFound2417_1 = FALSE;
259 bFoundd608 = FALSE;
260 while (iBytes >= iFodoOff + 2) {
261 iInfoLen = 0;
262 switch (usGetWord(iFodo + iFodoOff, aucGrpprl)) {
263 case 0x2416: /* fIntable */
264 if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
265 bFound2416_1 = TRUE;
266 } else {
267 bFound2416_0 = TRUE;
269 break;
270 case 0x2417: /* fTtp */
271 if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
272 bFound2417_1 = TRUE;
273 } else {
274 bFound2417_0 = TRUE;
276 break;
277 case 0x6424: /* brcTop */
278 usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
279 usTmp &= 0xff00;
280 NO_DBG_DEC(usTmp >> 8);
281 if (usTmp == 0) {
282 pRow->ucBorderInfo &= ~TABLE_BORDER_TOP;
283 } else {
284 pRow->ucBorderInfo |= TABLE_BORDER_TOP;
286 break;
287 case 0x6425: /* brcLeft */
288 usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
289 usTmp &= 0xff00;
290 NO_DBG_DEC(usTmp >> 8);
291 if (usTmp == 0) {
292 pRow->ucBorderInfo &= ~TABLE_BORDER_LEFT;
293 } else {
294 pRow->ucBorderInfo |= TABLE_BORDER_LEFT;
296 break;
297 case 0x6426: /* brcBottom */
298 usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
299 usTmp &= 0xff00;
300 NO_DBG_DEC(usTmp >> 8);
301 if (usTmp == 0) {
302 pRow->ucBorderInfo &= ~TABLE_BORDER_BOTTOM;
303 } else {
304 pRow->ucBorderInfo |= TABLE_BORDER_BOTTOM;
306 break;
307 case 0x6427: /* brcRight */
308 usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
309 usTmp &= 0xff00;
310 NO_DBG_DEC(usTmp >> 8);
311 if (usTmp == 0) {
312 pRow->ucBorderInfo &= ~TABLE_BORDER_RIGHT;
313 } else {
314 pRow->ucBorderInfo |= TABLE_BORDER_RIGHT;
316 break;
317 case 0xd608: /* cDefTable */
318 iSize = (int)usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
319 if (iSize < 6 || iBytes < iFodoOff + 8) {
320 DBG_DEC(iSize);
321 DBG_DEC(iFodoOff);
322 iInfoLen = 2;
323 break;
325 iCol = (int)ucGetByte(iFodo + iFodoOff + 4, aucGrpprl);
326 if (iCol < 1 ||
327 iBytes < iFodoOff + 4 + (iCol + 1) * 2) {
328 DBG_DEC(iCol);
329 DBG_DEC(iFodoOff);
330 iInfoLen = 2;
331 break;
333 if (iCol >= (int)elementsof(pRow->asColumnWidth)) {
334 DBG_DEC(iCol);
335 werr(1, "The number of columns is corrupt");
337 pRow->ucNumberOfColumns = (UCHAR)iCol;
338 pRow->iColumnWidthSum = 0;
339 iPosPrev = (int)(short)usGetWord(
340 iFodo + iFodoOff + 5,
341 aucGrpprl);
342 for (iIndex = 0; iIndex < iCol; iIndex++) {
343 iPosCurr = (int)(short)usGetWord(
344 iFodo + iFodoOff + 7 + iIndex * 2,
345 aucGrpprl);
346 pRow->asColumnWidth[iIndex] =
347 (short)(iPosCurr - iPosPrev);
348 pRow->iColumnWidthSum +=
349 pRow->asColumnWidth[iIndex];
350 iPosPrev = iPosCurr;
352 bFoundd608 = TRUE;
353 break;
354 default:
355 break;
357 if (iInfoLen <= 0) {
358 iInfoLen =
359 iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
360 fail(iInfoLen <= 0);
362 iFodoOff += iInfoLen;
364 if (bFound2416_1 && bFound2417_1 && bFoundd608) {
365 return found_end_of_row;
367 if (bFound2416_0 && bFound2417_0 && !bFoundd608) {
368 return found_not_end_of_row;
370 if (bFound2416_1) {
371 return found_a_cell;
373 if (bFound2416_0) {
374 return found_not_a_cell;
376 return found_nothing;
377 } /* end of eGet8RowInfo */
380 * Fill the style information block with information
381 * from a Word 8/9/10 file.
383 void
384 vGet8StyleInfo(int iFodo,
385 const UCHAR *aucGrpprl, int iBytes, style_block_type *pStyle)
387 list_block_type tList6;
388 const list_block_type *pList;
389 int iFodoOff, iInfoLen;
390 int iTmp, iDel, iAdd, iBefore;
391 USHORT usOpCode, usTmp;
392 short sTmp;
394 fail(iFodo < 0 || aucGrpprl == NULL || pStyle == NULL);
396 NO_DBG_DEC_C(pStyle->usListIndex != 0, pStyle->usIstd);
397 NO_DBG_DEC_C(pStyle->usListIndex != 0, pStyle->usListIndex);
399 (void)memset(&tList6, 0, sizeof(tList6));
401 iFodoOff = 0;
402 while (iBytes >= iFodoOff + 2) {
403 iInfoLen = 0;
404 usOpCode = usGetWord(iFodo + iFodoOff, aucGrpprl);
405 switch (usOpCode) {
406 case 0x2403: /* jc */
407 pStyle->ucAlignment = ucGetByte(
408 iFodo + iFodoOff + 2, aucGrpprl);
409 break;
410 case 0x260a: /* ilvl */
411 pStyle->ucListLevel =
412 ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
413 NO_DBG_DEC(pStyle->ucListLevel);
414 pStyle->ucNumLevel = pStyle->ucListLevel;
415 break;
416 case 0x4600: /* istd */
417 usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
418 NO_DBG_DEC(usTmp);
419 break;
420 case 0x460b: /* ilfo */
421 pStyle->usListIndex =
422 usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
423 NO_DBG_DEC(pStyle->usListIndex);
424 break;
425 case 0x4610: /* Nest dxaLeft */
426 sTmp = (short)usGetWord(
427 iFodo + iFodoOff + 2, aucGrpprl);
428 pStyle->sLeftIndent += sTmp;
429 if (pStyle->sLeftIndent < 0) {
430 pStyle->sLeftIndent = 0;
432 DBG_DEC(sTmp);
433 DBG_DEC(pStyle->sLeftIndent);
434 break;
435 case 0x6c0d: /* ChgTabsPapx */
436 iTmp = (int)ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
437 if (iTmp < 2) {
438 iInfoLen = 1;
439 break;
441 DBG_DEC(iTmp);
442 iDel = (int)ucGetByte(iFodo + iFodoOff + 3, aucGrpprl);
443 if (iTmp < 2 + 2 * iDel) {
444 iInfoLen = 1;
445 break;
447 DBG_DEC(iDel);
448 iAdd = (int)ucGetByte(
449 iFodo + iFodoOff + 4 + 2 * iDel, aucGrpprl);
450 if (iTmp < 2 + 2 * iDel + 2 * iAdd) {
451 iInfoLen = 1;
452 break;
454 DBG_DEC(iAdd);
455 break;
456 case 0x840e: /* dxaRight */
457 pStyle->sRightIndent = (short)usGetWord(
458 iFodo + iFodoOff + 2, aucGrpprl);
459 NO_DBG_DEC(pStyle->sRightIndent);
460 break;
461 case 0x840f: /* dxaLeft */
462 pStyle->sLeftIndent = (short)usGetWord(
463 iFodo + iFodoOff + 2, aucGrpprl);
464 NO_DBG_DEC(pStyle->sLeftIndent);
465 break;
466 case 0x8411: /* dxaLeft1 */
467 pStyle->sLeftIndent1 = (short)usGetWord(
468 iFodo + iFodoOff + 2, aucGrpprl);
469 NO_DBG_DEC(pStyle->sLeftIndent1);
470 break;
471 case 0xa413: /* dyaBefore */
472 pStyle->usBeforeIndent = usGetWord(
473 iFodo + iFodoOff + 2, aucGrpprl);
474 NO_DBG_DEC(pStyle->usBeforeIndent);
475 break;
476 case 0xa414: /* dyaAfter */
477 pStyle->usAfterIndent = usGetWord(
478 iFodo + iFodoOff + 2, aucGrpprl);
479 NO_DBG_DEC(pStyle->usAfterIndent);
480 break;
481 case 0xc63e: /* anld */
482 iTmp = (int)ucGetByte(
483 iFodo + iFodoOff + 2, aucGrpprl);
484 DBG_DEC_C(iTmp < 84, iTmp);
485 if (iTmp >= 1) {
486 tList6.ucNFC = ucGetByte(
487 iFodo + iFodoOff + 3, aucGrpprl);
489 if (tList6.ucNFC != LIST_BULLETS && iTmp >= 2) {
490 iBefore = (int)ucGetByte(
491 iFodo + iFodoOff + 4, aucGrpprl);
492 } else {
493 iBefore = 0;
495 if (iTmp >= 12) {
496 tList6.ulStartAt = (ULONG)usGetWord(
497 iFodo + iFodoOff + 13, aucGrpprl);
499 if (iTmp >= iBefore + 22) {
500 tList6.usListChar = usGetWord(
501 iFodo + iFodoOff + iBefore + 23,
502 aucGrpprl);
503 DBG_HEX(tList6.usListChar);
505 break;
506 default:
507 NO_DBG_HEX(usOpCode);
508 break;
510 if (iInfoLen <= 0) {
511 iInfoLen =
512 iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
513 fail(iInfoLen <= 0);
515 iFodoOff += iInfoLen;
518 if (pStyle->usListIndex == 2047) {
519 /* Old style list */
520 pStyle->usStartAt = (USHORT)tList6.ulStartAt;
521 pStyle->usListChar = tList6.usListChar;
522 pStyle->ucNFC = tList6.ucNFC;
523 } else {
524 /* New style list */
525 pList = pGetListInfo(pStyle->usListIndex, pStyle->ucListLevel);
526 if (pList != NULL) {
527 pStyle->bNoRestart = pList->bNoRestart;
528 fail(pList->ulStartAt > (ULONG)USHRT_MAX);
529 pStyle->usStartAt = (USHORT)pList->ulStartAt;
530 pStyle->usListChar = pList->usListChar;
531 pStyle->ucNFC = pList->ucNFC;
532 if (pStyle->sLeftIndent <= 0) {
533 pStyle->sLeftIndent = pList->sLeftIndent;
537 } /* end of vGet8StyleInfo */
540 * Get the left indentation value from the style information block
542 * Returns the value when found, otherwise 0
544 static short
545 sGetLeftIndent(const UCHAR *aucGrpprl, size_t tBytes)
547 int iOffset, iInfoLen;
548 USHORT usOpCode, usTmp;
550 fail(aucGrpprl == NULL);
552 iOffset = 0;
553 while (tBytes >= (size_t)iOffset + 4) {
554 usOpCode = usGetWord(iOffset, aucGrpprl);
555 if (usOpCode == 0x840f) { /* dxaLeft */
556 usTmp = usGetWord(iOffset + 2, aucGrpprl);
557 if (usTmp <= 0x7fff) {
558 NO_DBG_DEC(usTmp);
559 return (short)usTmp;
562 iInfoLen = iGet8InfoLength(iOffset, aucGrpprl);
563 fail(iInfoLen <= 0);
564 iOffset += iInfoLen;
566 return 0;
567 } /* end of sGetLeftIndent */
570 * Build the list with List Information for Word 8/9/10 files
572 void
573 vGet8LstInfo(FILE *pFile, const pps_info_type *pPPS,
574 const ULONG *aulBBD, size_t tBBDLen,
575 const ULONG *aulSBD, size_t tSBDLen,
576 const UCHAR *aucHeader)
578 list_block_type tList;
579 const ULONG *aulBlockDepot;
580 UCHAR *aucLfoInfo, *aucLstfInfo, *aucPapx, *aucXString;
581 ULONG ulTableStartBlock, ulTableSize;
582 ULONG ulBeginLfoInfo, ulBeginLstfInfo, ulBeginLvlfInfo;
583 ULONG ulListID, ulStart;
584 size_t tBlockDepotLen, tBlockSize;
585 size_t tLfoInfoLen, tLstfInfoLen, tPapxLen, tXstLen, tOff;
586 size_t tLstfRecords, tStart, tIndex;
587 int iNums;
588 USHORT usDocStatus, usIstd;
589 UCHAR ucTmp, ucListLevel, ucMaxLevel, ucChpxLen;
590 UCHAR aucLvlfInfo[28], aucXst[2];
592 fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
593 fail(aulBBD == NULL || aulSBD == NULL);
595 /* Use 0Table or 1Table? */
596 usDocStatus = usGetWord(0x0a, aucHeader);
597 if (usDocStatus & BIT(9)) {
598 ulTableStartBlock = pPPS->t1Table.ulSB;
599 ulTableSize = pPPS->t1Table.ulSize;
600 } else {
601 ulTableStartBlock = pPPS->t0Table.ulSB;
602 ulTableSize = pPPS->t0Table.ulSize;
604 DBG_DEC(ulTableStartBlock);
605 if (ulTableStartBlock == 0) {
606 DBG_MSG("No list information");
607 return;
609 DBG_HEX(ulTableSize);
610 if (ulTableSize < MIN_SIZE_FOR_BBD_USE) {
611 /* Use the Small Block Depot */
612 aulBlockDepot = aulSBD;
613 tBlockDepotLen = tSBDLen;
614 tBlockSize = SMALL_BLOCK_SIZE;
615 } else {
616 /* Use the Big Block Depot */
617 aulBlockDepot = aulBBD;
618 tBlockDepotLen = tBBDLen;
619 tBlockSize = BIG_BLOCK_SIZE;
622 /* LFO (List Format Override) */
623 ulBeginLfoInfo = ulGetLong(0x2ea, aucHeader); /* fcPlfLfo */
624 DBG_HEX(ulBeginLfoInfo);
625 tLfoInfoLen = (size_t)ulGetLong(0x2ee, aucHeader); /* lcbPlfLfo */
626 DBG_DEC(tLfoInfoLen);
627 if (tLfoInfoLen == 0) {
628 DBG_MSG("No lists in this document");
629 return;
632 aucLfoInfo = xmalloc(tLfoInfoLen);
633 if (!bReadBuffer(pFile, ulTableStartBlock,
634 aulBlockDepot, tBlockDepotLen, tBlockSize,
635 aucLfoInfo, ulBeginLfoInfo, tLfoInfoLen)) {
636 aucLfoInfo = xfree(aucLfoInfo);
637 return;
639 NO_DBG_PRINT_BLOCK(aucLfoInfo, tLfoInfoLen);
640 vBuildLfoList(aucLfoInfo, tLfoInfoLen);
641 aucLfoInfo = xfree(aucLfoInfo);
643 /* LSTF (LiST data on File) */
644 ulBeginLstfInfo = ulGetLong(0x2e2, aucHeader); /* fcPlcfLst */
645 DBG_HEX(ulBeginLstfInfo);
646 tLstfInfoLen = (size_t)ulGetLong(0x2e6, aucHeader); /* lcbPlcfLst */
647 DBG_DEC(tLstfInfoLen);
648 if (tLstfInfoLen == 0) {
649 DBG_MSG("No list data on file");
650 return;
653 aucLstfInfo = xmalloc(tLstfInfoLen);
654 if (!bReadBuffer(pFile, ulTableStartBlock,
655 aulBlockDepot, tBlockDepotLen, tBlockSize,
656 aucLstfInfo, ulBeginLstfInfo, tLstfInfoLen)) {
657 aucLstfInfo = xfree(aucLstfInfo);
658 return;
660 NO_DBG_PRINT_BLOCK(aucLstfInfo, tLstfInfoLen);
662 tLstfRecords = (size_t)usGetWord(0, aucLstfInfo);
663 if (2 + tLstfRecords * 28 < tLstfInfoLen) {
664 DBG_DEC(2 + tLstfRecords * 28);
665 DBG_DEC(tLstfInfoLen);
666 aucLstfInfo = xfree(aucLstfInfo);
667 return;
670 /* LVLF (List leVeL on File) */
671 ulBeginLvlfInfo = ulBeginLstfInfo + tLstfInfoLen;
672 DBG_HEX(ulBeginLvlfInfo);
674 aucXString = NULL;
675 ulStart = ulBeginLvlfInfo;
677 for (tIndex = 0, tStart = 2;
678 tIndex < tLstfRecords;
679 tIndex++, tStart += 28) {
680 ulListID = ulGetLong(tStart, aucLstfInfo);
681 NO_DBG_HEX(ulListID);
682 ucTmp = ucGetByte(tStart + 26, aucLstfInfo);
683 ucMaxLevel = odd(ucTmp) ? 1 : 9;
684 for (ucListLevel = 0; ucListLevel < ucMaxLevel; ucListLevel++) {
685 fail(aucXString != NULL);
686 usIstd = usGetWord(
687 tStart + 8 + 2 * (size_t)ucListLevel,
688 aucLstfInfo);
689 DBG_DEC_C(usIstd != STI_NIL, usIstd);
690 NO_DBG_HEX(ulStart);
691 (void)memset(&tList, 0, sizeof(tList));
692 /* Read the lvlf (List leVeL on File) */
693 if (!bReadBuffer(pFile, ulTableStartBlock,
694 aulBlockDepot, tBlockDepotLen,
695 tBlockSize, aucLvlfInfo,
696 ulStart, sizeof(aucLvlfInfo))) {
697 aucLstfInfo = xfree(aucLstfInfo);
698 return;
700 NO_DBG_PRINT_BLOCK(aucLvlfInfo, sizeof(aucLvlfInfo));
701 if (bAllZero(aucLvlfInfo, sizeof(aucLvlfInfo))) {
702 tList.ulStartAt = 1;
703 tList.ucNFC = 0x00;
704 tList.bNoRestart = FALSE;
705 } else {
706 tList.ulStartAt = ulGetLong(0, aucLvlfInfo);
707 tList.ucNFC = ucGetByte(4, aucLvlfInfo);
708 ucTmp = ucGetByte(5, aucLvlfInfo);
709 tList.bNoRestart = (ucTmp & BIT(3)) != 0;
711 ulStart += sizeof(aucLvlfInfo);
712 tPapxLen = (size_t)ucGetByte(25, aucLvlfInfo);
713 if (tPapxLen != 0) {
714 aucPapx = xmalloc(tPapxLen);
715 /* Read the Papx */
716 if (!bReadBuffer(pFile, ulTableStartBlock,
717 aulBlockDepot, tBlockDepotLen,
718 tBlockSize, aucPapx,
719 ulStart, tPapxLen)) {
720 aucPapx = xfree(aucPapx);
721 aucLstfInfo = xfree(aucLstfInfo);
722 return;
724 NO_DBG_PRINT_BLOCK(aucPapx, tPapxLen);
725 tList.sLeftIndent =
726 sGetLeftIndent(aucPapx, tPapxLen);
727 aucPapx = xfree(aucPapx);
729 ulStart += tPapxLen;
730 ucChpxLen = ucGetByte(24, aucLvlfInfo);
731 ulStart += (ULONG)ucChpxLen;
732 /* Read the length of the XString */
733 if (!bReadBuffer(pFile, ulTableStartBlock,
734 aulBlockDepot, tBlockDepotLen,
735 tBlockSize, aucXst,
736 ulStart, sizeof(aucXst))) {
737 aucLstfInfo = xfree(aucLstfInfo);
738 return;
740 NO_DBG_PRINT_BLOCK(aucXst, sizeof(aucXst));
741 tXstLen = (size_t)usGetWord(0, aucXst);
742 ulStart += sizeof(aucXst);
743 if (tXstLen == 0) {
744 tList.usListChar = DEFAULT_LISTCHAR;
745 vAdd2ListInfoList(ulListID,
746 usIstd,
747 ucListLevel,
748 &tList);
749 continue;
751 tXstLen *= 2; /* Length in chars to length in bytes */
752 aucXString = xmalloc(tXstLen);
753 /* Read the XString */
754 if (!bReadBuffer(pFile, ulTableStartBlock,
755 aulBlockDepot, tBlockDepotLen,
756 tBlockSize, aucXString,
757 ulStart, tXstLen)) {
758 aucXString = xfree(aucXString);
759 aucLstfInfo = xfree(aucLstfInfo);
760 return;
762 NO_DBG_PRINT_BLOCK(aucXString, tXstLen);
763 tOff = 0;
764 for (iNums = 6; iNums < 15; iNums++) {
765 ucTmp = ucGetByte(iNums, aucLvlfInfo);
766 if (ucTmp == 0) {
767 break;
769 tOff = (size_t)ucTmp;
771 tOff *= 2; /* Offset in chars to offset in bytes */
772 NO_DBG_DEC(tOff);
773 if (tList.ucNFC == LIST_SPECIAL ||
774 tList.ucNFC == LIST_BULLETS) {
775 tList.usListChar = usGetWord(0, aucXString);
776 } else if (tOff != 0 && tOff < tXstLen) {
777 tList.usListChar = usGetWord(tOff, aucXString);
778 } else {
779 tList.usListChar = DEFAULT_LISTCHAR;
781 vAdd2ListInfoList(ulListID,
782 usIstd,
783 ucListLevel,
784 &tList);
785 ulStart += tXstLen;
786 aucXString = xfree(aucXString);
789 aucLstfInfo = xfree(aucLstfInfo);
790 } /* end of vGet8LstInfo */
793 * Build the lists with Paragraph Information for Word 8/9/10 files
795 void
796 vGet8PapInfo(FILE *pFile, const pps_info_type *pPPS,
797 const ULONG *aulBBD, size_t tBBDLen,
798 const ULONG *aulSBD, size_t tSBDLen,
799 const UCHAR *aucHeader)
801 row_block_type tRow;
802 style_block_type tStyle;
803 ULONG *aulParfPage;
804 const ULONG *aulBlockDepot;
805 UCHAR *aucBuffer;
806 ULONG ulCharPos, ulCharPosFirst, ulCharPosLast;
807 ULONG ulBeginParfInfo;
808 ULONG ulTableSize, ulTableStartBlock;
809 size_t tParfInfoLen, tBlockDepotLen;
810 size_t tBlockSize, tOffset, tLen;
811 int iIndex, iIndex2, iRun, iFodo, iLen;
812 row_info_enum eRowInfo;
813 USHORT usDocStatus, usIstd;
814 UCHAR aucFpage[BIG_BLOCK_SIZE];
816 fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
817 fail(aulBBD == NULL || aulSBD == NULL);
819 ulBeginParfInfo = ulGetLong(0x102, aucHeader); /* fcPlcfbtePapx */
820 NO_DBG_HEX(ulBeginParfInfo);
821 tParfInfoLen = (size_t)ulGetLong(0x106, aucHeader); /* lcbPlcfbtePapx */
822 NO_DBG_DEC(tParfInfoLen);
823 if (tParfInfoLen < 4) {
824 DBG_DEC(tParfInfoLen);
825 return;
828 /* Use 0Table or 1Table? */
829 usDocStatus = usGetWord(0x0a, aucHeader);
830 if (usDocStatus & BIT(9)) {
831 ulTableStartBlock = pPPS->t1Table.ulSB;
832 ulTableSize = pPPS->t1Table.ulSize;
833 } else {
834 ulTableStartBlock = pPPS->t0Table.ulSB;
835 ulTableSize = pPPS->t0Table.ulSize;
837 DBG_DEC(ulTableStartBlock);
838 if (ulTableStartBlock == 0) {
839 DBG_MSG("No paragraph information");
840 return;
842 DBG_HEX(ulTableSize);
843 if (ulTableSize < MIN_SIZE_FOR_BBD_USE) {
844 /* Use the Small Block Depot */
845 aulBlockDepot = aulSBD;
846 tBlockDepotLen = tSBDLen;
847 tBlockSize = SMALL_BLOCK_SIZE;
848 } else {
849 /* Use the Big Block Depot */
850 aulBlockDepot = aulBBD;
851 tBlockDepotLen = tBBDLen;
852 tBlockSize = BIG_BLOCK_SIZE;
855 aucBuffer = xmalloc(tParfInfoLen);
856 if (!bReadBuffer(pFile, ulTableStartBlock,
857 aulBlockDepot, tBlockDepotLen, tBlockSize,
858 aucBuffer, ulBeginParfInfo, tParfInfoLen)) {
859 aucBuffer = xfree(aucBuffer);
860 return;
862 NO_DBG_PRINT_BLOCK(aucBuffer, tParfInfoLen);
864 tLen = (tParfInfoLen / 4 - 1) / 2;
865 aulParfPage = xcalloc(tLen, sizeof(ULONG));
866 for (iIndex = 0, tOffset = (tLen + 1) * 4;
867 iIndex < (int)tLen;
868 iIndex++, tOffset += 4) {
869 aulParfPage[iIndex] = ulGetLong(tOffset, aucBuffer);
870 NO_DBG_DEC(aulParfPage[iIndex]);
872 DBG_HEX(ulGetLong(0, aucBuffer));
873 aucBuffer = xfree(aucBuffer);
874 NO_DBG_PRINT_BLOCK(aucHeader, HEADER_SIZE);
876 (void)memset(&tRow, 0, sizeof(tRow));
877 ulCharPosFirst = CP_INVALID;
878 for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
879 fail(aulParfPage[iIndex] > ULONG_MAX / BIG_BLOCK_SIZE);
880 if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB,
881 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
882 aucFpage,
883 aulParfPage[iIndex] * BIG_BLOCK_SIZE,
884 BIG_BLOCK_SIZE)) {
885 break;
887 NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE);
888 iRun = (int)ucGetByte(0x1ff, aucFpage);
889 NO_DBG_DEC(iRun);
890 for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
891 NO_DBG_HEX(ulGetLong(iIndex2 * 4, aucFpage));
892 iFodo = 2 * (int)ucGetByte(
893 (iRun + 1) * 4 + iIndex2 * 13, aucFpage);
894 if (iFodo <= 0) {
895 continue;
898 iLen = 2 * (int)ucGetByte(iFodo, aucFpage);
899 if (iLen == 0) {
900 iFodo++;
901 iLen = 2 * (int)ucGetByte(iFodo, aucFpage);
904 usIstd = usGetWord(iFodo + 1, aucFpage);
905 vFillStyleFromStylesheet(usIstd, &tStyle);
906 vGet8StyleInfo(iFodo, aucFpage + 3, iLen - 3, &tStyle);
907 ulCharPos = ulGetLong(iIndex2 * 4, aucFpage);
908 NO_DBG_HEX(ulCharPos);
909 tStyle.ulFileOffset = ulCharPos2FileOffset(ulCharPos);
910 vAdd2StyleInfoList(&tStyle);
912 eRowInfo = eGet8RowInfo(iFodo,
913 aucFpage + 3, iLen - 3, &tRow);
914 switch (eRowInfo) {
915 case found_a_cell:
916 if (ulCharPosFirst != CP_INVALID) {
917 break;
919 ulCharPosFirst = ulGetLong(
920 iIndex2 * 4, aucFpage);
921 NO_DBG_HEX(ulCharPosFirst);
922 tRow.ulCharPosStart = ulCharPosFirst;
923 tRow.ulFileOffsetStart =
924 ulCharPos2FileOffset(ulCharPosFirst);
925 NO_DBG_HEX_C(
926 tRow.ulFileOffsetStart == FC_INVALID,
927 ulCharPosFirst);
928 break;
929 case found_end_of_row:
930 ulCharPosLast = ulGetLong(
931 iIndex2 * 4, aucFpage);
932 NO_DBG_HEX(ulCharPosLast);
933 tRow.ulCharPosEnd = ulCharPosLast;
934 tRow.ulFileOffsetEnd =
935 ulCharPos2FileOffset(ulCharPosLast);
936 NO_DBG_HEX_C(tRow.ulFileOffsetEnd == FC_INVALID,
937 ulCharPosLast);
938 vAdd2RowInfoList(&tRow);
939 (void)memset(&tRow, 0, sizeof(tRow));
940 ulCharPosFirst = CP_INVALID;
941 break;
942 case found_nothing:
943 break;
944 default:
945 DBG_DEC(eRowInfo);
946 break;
950 aulParfPage = xfree(aulParfPage);
951 } /* end of vGet8PapInfo */
954 * Fill the font information block with information
955 * from a Word 8/9/10 file.
957 void
958 vGet8FontInfo(int iFodo, USHORT usIstd,
959 const UCHAR *aucGrpprl, int iBytes, font_block_type *pFont)
961 long lTmp;
962 int iFodoOff, iInfoLen;
963 USHORT usTmp;
964 UCHAR ucTmp;
966 fail(iFodo < 0 || aucGrpprl == NULL || pFont == NULL);
968 iFodoOff = 0;
969 while (iBytes >= iFodoOff + 2) {
970 switch (usGetWord(iFodo + iFodoOff, aucGrpprl)) {
971 case 0x0800: /* fRMarkDel */
972 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
973 if (ucTmp == 0) {
974 pFont->usFontStyle &= ~FONT_MARKDEL;
975 } else {
976 pFont->usFontStyle |= FONT_MARKDEL;
978 break;
979 case 0x0835: /* fBold */
980 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
981 switch (ucTmp) {
982 case 0: /* Unset */
983 pFont->usFontStyle &= ~FONT_BOLD;
984 break;
985 case 1: /* Set */
986 pFont->usFontStyle |= FONT_BOLD;
987 break;
988 case 128: /* Unchanged */
989 break;
990 case 129: /* Negation */
991 pFont->usFontStyle ^= FONT_BOLD;
992 break;
993 default:
994 DBG_DEC(ucTmp);
995 DBG_FIXME();
996 break;
998 break;
999 case 0x0836: /* fItalic */
1000 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1001 switch (ucTmp) {
1002 case 0: /* Unset */
1003 pFont->usFontStyle &= ~FONT_ITALIC;
1004 break;
1005 case 1: /* Set */
1006 pFont->usFontStyle |= FONT_ITALIC;
1007 break;
1008 case 128: /* Unchanged */
1009 break;
1010 case 129: /* Negation */
1011 pFont->usFontStyle ^= FONT_ITALIC;
1012 break;
1013 default:
1014 DBG_DEC(ucTmp);
1015 DBG_FIXME();
1016 break;
1018 break;
1019 case 0x0837: /* fStrike */
1020 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1021 switch (ucTmp) {
1022 case 0: /* Unset */
1023 pFont->usFontStyle &= ~FONT_STRIKE;
1024 break;
1025 case 1: /* Set */
1026 pFont->usFontStyle |= FONT_STRIKE;
1027 break;
1028 case 128: /* Unchanged */
1029 break;
1030 case 129: /* Negation */
1031 pFont->usFontStyle ^= FONT_STRIKE;
1032 break;
1033 default:
1034 DBG_DEC(ucTmp);
1035 DBG_FIXME();
1036 break;
1038 break;
1039 case 0x083a: /* fSmallCaps */
1040 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1041 switch (ucTmp) {
1042 case 0: /* Unset */
1043 pFont->usFontStyle &= ~FONT_SMALL_CAPITALS;
1044 break;
1045 case 1: /* Set */
1046 pFont->usFontStyle |= FONT_SMALL_CAPITALS;
1047 break;
1048 case 128: /* Unchanged */
1049 break;
1050 case 129: /* Negation */
1051 pFont->usFontStyle ^= FONT_SMALL_CAPITALS;
1052 break;
1053 default:
1054 DBG_DEC(ucTmp);
1055 DBG_FIXME();
1056 break;
1058 break;
1059 case 0x083b: /* fCaps */
1060 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1061 switch (ucTmp) {
1062 case 0: /* Unset */
1063 pFont->usFontStyle &= ~FONT_CAPITALS;
1064 break;
1065 case 1: /* Set */
1066 pFont->usFontStyle |= FONT_CAPITALS;
1067 break;
1068 case 128: /* Unchanged */
1069 break;
1070 case 129: /* Negation */
1071 pFont->usFontStyle ^= FONT_CAPITALS;
1072 break;
1073 default:
1074 DBG_DEC(ucTmp);
1075 DBG_FIXME();
1076 break;
1078 break;
1079 case 0x083c: /* fVanish */
1080 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1081 switch (ucTmp) {
1082 case 0: /* Unset */
1083 pFont->usFontStyle &= ~FONT_HIDDEN;
1084 break;
1085 case 1: /* Set */
1086 pFont->usFontStyle |= FONT_HIDDEN;
1087 break;
1088 case 128: /* Unchanged */
1089 break;
1090 case 129: /* Negation */
1091 pFont->usFontStyle ^= FONT_HIDDEN;
1092 break;
1093 default:
1094 DBG_DEC(ucTmp);
1095 DBG_FIXME();
1096 break;
1098 break;
1099 case 0x2a32: /* cDefault */
1100 pFont->usFontStyle &= FONT_HIDDEN;
1101 pFont->ucFontColor = FONT_COLOR_DEFAULT;
1102 break;
1103 case 0x2a33: /* cPlain */
1104 DBG_MSG("2a33: cPlain");
1105 vFillFontFromStylesheet(usIstd, pFont);
1106 break;
1107 case 0x2a3e: /* cKul */
1108 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1109 if (ucTmp == 0 || ucTmp == 5) {
1110 pFont->usFontStyle &= ~FONT_UNDERLINE;
1111 } else {
1112 NO_DBG_MSG("Underline text");
1113 pFont->usFontStyle |= FONT_UNDERLINE;
1114 if (ucTmp == 6) {
1115 DBG_MSG("Bold text");
1116 pFont->usFontStyle |= FONT_BOLD;
1119 break;
1120 case 0x2a42: /* cIco */
1121 pFont->ucFontColor =
1122 ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1123 NO_DBG_DEC(pFont->ucFontColor);
1124 break;
1125 case 0x2a48: /* cIss */
1126 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1127 ucTmp &= 0x07;
1128 if (ucTmp == 1) {
1129 pFont->usFontStyle |= FONT_SUPERSCRIPT;
1130 NO_DBG_MSG("Superscript");
1131 } else if (ucTmp == 2) {
1132 pFont->usFontStyle |= FONT_SUBSCRIPT;
1133 NO_DBG_MSG("Subscript");
1135 break;
1136 case 0x4a30: /* cIstd */
1137 usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
1138 NO_DBG_DEC(usTmp);
1139 break;
1140 case 0x4a43: /* cHps */
1141 pFont->usFontSize =
1142 usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
1143 NO_DBG_DEC(pFont->usFontSize);
1144 break;
1145 case 0x4a51: /* cFtc */
1146 usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
1147 if (usTmp <= (USHORT)UCHAR_MAX) {
1148 pFont->ucFontNumber = (UCHAR)usTmp;
1149 } else {
1150 pFont->ucFontNumber = 0;
1152 break;
1153 case 0xca4a: /* cHps */
1154 usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
1155 lTmp = (long)pFont->usFontSize + (long)usTmp;
1156 if (lTmp < 8) {
1157 pFont->usFontSize = 8;
1158 } else if (lTmp > 32766) {
1159 pFont->usFontSize = 32766;
1160 } else {
1161 pFont->usFontSize = (USHORT)lTmp;
1163 break;
1164 case 0xea3f: /* cHps, cHpsPos */
1165 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1166 if (ucTmp != 0) {
1167 pFont->usFontSize = (USHORT)ucTmp;
1169 DBG_DEC(ucTmp);
1170 break;
1171 default:
1172 break;
1174 iInfoLen = iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
1175 fail(iInfoLen <= 0);
1176 iFodoOff += iInfoLen;
1178 } /* end of vGet8FontInfo */
1181 * Fill the picture information block with information
1182 * from a Word 8/9/10 file.
1183 * Returns TRUE when successful, otherwise FALSE
1185 static BOOL
1186 bGet8PicInfo(int iFodo,
1187 const UCHAR *aucGrpprl, int iBytes, picture_block_type *pPicture)
1189 int iFodoOff, iInfoLen;
1190 BOOL bFound;
1191 UCHAR ucTmp;
1193 fail(iFodo <= 0 || aucGrpprl == NULL || pPicture == NULL);
1195 iFodoOff = 0;
1196 bFound = FALSE;
1197 while (iBytes >= iFodoOff + 2) {
1198 switch (usGetWord(iFodo + iFodoOff, aucGrpprl)) {
1199 case 0x0806: /* fData */
1200 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1201 if (ucTmp == 0x01) {
1202 /* Not a picture, but a form field */
1203 return FALSE;
1205 DBG_DEC_C(ucTmp != 0, ucTmp);
1206 break;
1207 case 0x080a: /* fOle2 */
1208 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1209 if (ucTmp == 0x01) {
1210 /* Not a picture, but an OLE object */
1211 return FALSE;
1213 DBG_DEC_C(ucTmp != 0, ucTmp);
1214 break;
1215 case 0x6a03: /* fcPic */
1216 pPicture->ulPictureOffset = ulGetLong(
1217 iFodo + iFodoOff + 2, aucGrpprl);
1218 bFound = TRUE;
1219 break;
1220 default:
1221 break;
1223 iInfoLen = iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
1224 fail(iInfoLen <= 0);
1225 iFodoOff += iInfoLen;
1227 return bFound;
1228 } /* end of bGet8PicInfo */
1231 * Build the lists with Character Information for Word 8/9/10 files
1233 void
1234 vGet8ChrInfo(FILE *pFile, const pps_info_type *pPPS,
1235 const ULONG *aulBBD, size_t tBBDLen,
1236 const ULONG *aulSBD, size_t tSBDLen,
1237 const UCHAR *aucHeader)
1239 font_block_type tFont;
1240 picture_block_type tPicture;
1241 ULONG *aulCharPage;
1242 const ULONG *aulBlockDepot;
1243 UCHAR *aucBuffer;
1244 ULONG ulFileOffset, ulCharPos, ulBeginCharInfo;
1245 ULONG ulTableSize, ulTableStartBlock;
1246 size_t tCharInfoLen, tBlockDepotLen;
1247 size_t tOffset, tBlockSize, tLen;
1248 int iIndex, iIndex2, iRun, iFodo, iLen;
1249 USHORT usDocStatus, usIstd;
1250 UCHAR aucFpage[BIG_BLOCK_SIZE];
1252 fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
1253 fail(aulBBD == NULL || aulSBD == NULL);
1255 ulBeginCharInfo = ulGetLong(0xfa, aucHeader); /* fcPlcfbteChpx */
1256 NO_DBG_HEX(ulBeginCharInfo);
1257 tCharInfoLen = (size_t)ulGetLong(0xfe, aucHeader); /* lcbPlcfbteChpx */
1258 NO_DBG_DEC(tCharInfoLen);
1259 if (tCharInfoLen < 4) {
1260 DBG_DEC(tCharInfoLen);
1261 return;
1264 /* Use 0Table or 1Table? */
1265 usDocStatus = usGetWord(0x0a, aucHeader);
1266 if (usDocStatus & BIT(9)) {
1267 ulTableStartBlock = pPPS->t1Table.ulSB;
1268 ulTableSize = pPPS->t1Table.ulSize;
1269 } else {
1270 ulTableStartBlock = pPPS->t0Table.ulSB;
1271 ulTableSize = pPPS->t0Table.ulSize;
1273 DBG_DEC(ulTableStartBlock);
1274 if (ulTableStartBlock == 0) {
1275 DBG_MSG("No character information");
1276 return;
1278 DBG_HEX(ulTableSize);
1279 if (ulTableSize < MIN_SIZE_FOR_BBD_USE) {
1280 /* Use the Small Block Depot */
1281 aulBlockDepot = aulSBD;
1282 tBlockDepotLen = tSBDLen;
1283 tBlockSize = SMALL_BLOCK_SIZE;
1284 } else {
1285 /* Use the Big Block Depot */
1286 aulBlockDepot = aulBBD;
1287 tBlockDepotLen = tBBDLen;
1288 tBlockSize = BIG_BLOCK_SIZE;
1290 aucBuffer = xmalloc(tCharInfoLen);
1291 if (!bReadBuffer(pFile, ulTableStartBlock,
1292 aulBlockDepot, tBlockDepotLen, tBlockSize,
1293 aucBuffer, ulBeginCharInfo, tCharInfoLen)) {
1294 aucBuffer = xfree(aucBuffer);
1295 return;
1297 NO_DBG_PRINT_BLOCK(aucBuffer, tCharInfoLen);
1299 tLen = (tCharInfoLen / 4 - 1) / 2;
1300 aulCharPage = xcalloc(tLen, sizeof(ULONG));
1301 for (iIndex = 0, tOffset = (tLen + 1) * 4;
1302 iIndex < (int)tLen;
1303 iIndex++, tOffset += 4) {
1304 aulCharPage[iIndex] = ulGetLong(tOffset, aucBuffer);
1305 NO_DBG_DEC(aulCharPage[iIndex]);
1307 DBG_HEX(ulGetLong(0, aucBuffer));
1308 aucBuffer = xfree(aucBuffer);
1309 NO_DBG_PRINT_BLOCK(aucHeader, HEADER_SIZE);
1311 for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
1312 fail(aulCharPage[iIndex] > ULONG_MAX / BIG_BLOCK_SIZE);
1313 if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB,
1314 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
1315 aucFpage,
1316 aulCharPage[iIndex] * BIG_BLOCK_SIZE,
1317 BIG_BLOCK_SIZE)) {
1318 break;
1320 NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE);
1321 iRun = (int)ucGetByte(0x1ff, aucFpage);
1322 NO_DBG_DEC(iRun);
1323 for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
1324 ulCharPos = ulGetLong(iIndex2 * 4, aucFpage);
1325 ulFileOffset = ulCharPos2FileOffset(ulCharPos);
1326 iFodo = 2 * (int)ucGetByte(
1327 (iRun + 1) * 4 + iIndex2, aucFpage);
1329 iLen = (int)ucGetByte(iFodo, aucFpage);
1331 usIstd = usGetIstd(ulFileOffset);
1332 vFillFontFromStylesheet(usIstd, &tFont);
1333 if (iFodo != 0) {
1334 vGet8FontInfo(iFodo, usIstd,
1335 aucFpage + 1, iLen - 1, &tFont);
1337 tFont.ulFileOffset = ulFileOffset;
1338 vAdd2FontInfoList(&tFont);
1340 if (iFodo <= 0) {
1341 continue;
1344 (void)memset(&tPicture, 0, sizeof(tPicture));
1345 if (bGet8PicInfo(iFodo, aucFpage + 1,
1346 iLen - 1, &tPicture)) {
1347 tPicture.ulFileOffset = ulFileOffset;
1348 tPicture.ulFileOffsetPicture =
1349 ulDataPos2FileOffset(
1350 tPicture.ulPictureOffset);
1351 vAdd2PictInfoList(&tPicture);
1355 aulCharPage = xfree(aulCharPage);
1356 } /* end of vGet8ChrInfo */