3 * Copyright (C) 1998-2003 A.J. van Os; Released under GPL
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
17 #define DEFAULT_LISTCHAR 0x002e /* A full stop */
21 * iGet8InfoLength - the length of the information for Word 8/9/10 files
24 iGet8InfoLength(int iByteNbr
, const UCHAR
*aucGrpprl
)
29 usOpCode
= usGetWord(iByteNbr
, aucGrpprl
);
31 switch (usOpCode
& 0xe000) {
32 case 0x0000: case 0x2000:
34 case 0x4000: case 0x8000: case 0xa000:
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;
54 } /* end of iGet8InfoLength */
57 * Fill the section information block with information
58 * from a Word 8/9/10 file.
61 vGet8SectionInfo(const UCHAR
*aucGrpprl
, size_t tBytes
,
62 section_block_type
*pSection
)
65 int iFodoOff
, iInfoLen
, iSize
, iTmp
;
69 fail(aucGrpprl
== NULL
|| pSection
== NULL
);
72 while (tBytes
>= (size_t)iFodoOff
+ 2) {
74 switch (usGetWord(iFodoOff
, aucGrpprl
)) {
75 case 0x3009: /* bkc */
76 ucTmp
= ucGetByte(iFodoOff
+ 2, aucGrpprl
);
78 pSection
->bNewPage
= ucTmp
!= 0 && ucTmp
!= 1;
80 case 0x500b: /* ccolM1 */
81 usCcol
= 1 + usGetWord(iFodoOff
+ 2, aucGrpprl
);
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
);
95 if ((ucTmp
& BIT(2)) != 0) {
96 pSection
->usNeedPrevLvl
|=
99 if ((ucTmp
& BIT(3)) != 0) {
100 pSection
->usHangingIndent
|=
101 (USHORT
)BIT(uiIndex
);
104 DBG_HEX(pSection
->usNeedPrevLvl
);
105 DBG_HEX(pSection
->usHangingIndent
);
111 iInfoLen
= iGet8InfoLength(iFodoOff
, aucGrpprl
);
114 iFodoOff
+= iInfoLen
;
116 } /* end of vGet8SectionInfo */
119 * Build the lists with Section Property Information for Word 8/9/10 files
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
;
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
);
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
;
157 ulTableStartBlock
= pPPS
->t0Table
.ulSB
;
158 ulTableSize
= pPPS
->t0Table
.ulSize
;
160 DBG_DEC(ulTableStartBlock
);
161 if (ulTableStartBlock
== 0) {
162 DBG_MSG("No section information");
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
;
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
);
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;
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;
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
]);
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)) {
217 tBytes
= 2 + (size_t)usGetWord(0, aucTmp
);
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
);
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
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
;
249 BOOL bFound2416_0
, bFound2416_1
, bFound2417_0
, bFound2417_1
;
252 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pRow
== NULL
);
255 bFound2416_0
= FALSE
;
256 bFound2416_1
= FALSE
;
257 bFound2417_0
= FALSE
;
258 bFound2417_1
= FALSE
;
260 while (iBytes
>= iFodoOff
+ 2) {
262 switch (usGetWord(iFodo
+ iFodoOff
, aucGrpprl
)) {
263 case 0x2416: /* fIntable */
264 if (odd(ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
))) {
270 case 0x2417: /* fTtp */
271 if (odd(ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
))) {
277 case 0x6424: /* brcTop */
278 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
280 NO_DBG_DEC(usTmp
>> 8);
282 pRow
->ucBorderInfo
&= ~TABLE_BORDER_TOP
;
284 pRow
->ucBorderInfo
|= TABLE_BORDER_TOP
;
287 case 0x6425: /* brcLeft */
288 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
290 NO_DBG_DEC(usTmp
>> 8);
292 pRow
->ucBorderInfo
&= ~TABLE_BORDER_LEFT
;
294 pRow
->ucBorderInfo
|= TABLE_BORDER_LEFT
;
297 case 0x6426: /* brcBottom */
298 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
300 NO_DBG_DEC(usTmp
>> 8);
302 pRow
->ucBorderInfo
&= ~TABLE_BORDER_BOTTOM
;
304 pRow
->ucBorderInfo
|= TABLE_BORDER_BOTTOM
;
307 case 0x6427: /* brcRight */
308 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
310 NO_DBG_DEC(usTmp
>> 8);
312 pRow
->ucBorderInfo
&= ~TABLE_BORDER_RIGHT
;
314 pRow
->ucBorderInfo
|= TABLE_BORDER_RIGHT
;
317 case 0xd608: /* cDefTable */
318 iSize
= (int)usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
319 if (iSize
< 6 || iBytes
< iFodoOff
+ 8) {
325 iCol
= (int)ucGetByte(iFodo
+ iFodoOff
+ 4, aucGrpprl
);
327 iBytes
< iFodoOff
+ 4 + (iCol
+ 1) * 2) {
333 if (iCol
>= (int)elementsof(pRow
->asColumnWidth
)) {
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,
342 for (iIndex
= 0; iIndex
< iCol
; iIndex
++) {
343 iPosCurr
= (int)(short)usGetWord(
344 iFodo
+ iFodoOff
+ 7 + iIndex
* 2,
346 pRow
->asColumnWidth
[iIndex
] =
347 (short)(iPosCurr
- iPosPrev
);
348 pRow
->iColumnWidthSum
+=
349 pRow
->asColumnWidth
[iIndex
];
359 iGet8InfoLength(iFodo
+ iFodoOff
, aucGrpprl
);
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
;
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.
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
;
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
));
402 while (iBytes
>= iFodoOff
+ 2) {
404 usOpCode
= usGetWord(iFodo
+ iFodoOff
, aucGrpprl
);
406 case 0x2403: /* jc */
407 pStyle
->ucAlignment
= ucGetByte(
408 iFodo
+ iFodoOff
+ 2, aucGrpprl
);
410 case 0x260a: /* ilvl */
411 pStyle
->ucListLevel
=
412 ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
413 NO_DBG_DEC(pStyle
->ucListLevel
);
414 pStyle
->ucNumLevel
= pStyle
->ucListLevel
;
416 case 0x4600: /* istd */
417 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
420 case 0x460b: /* ilfo */
421 pStyle
->usListIndex
=
422 usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
423 NO_DBG_DEC(pStyle
->usListIndex
);
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;
433 DBG_DEC(pStyle
->sLeftIndent
);
435 case 0x6c0d: /* ChgTabsPapx */
436 iTmp
= (int)ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
442 iDel
= (int)ucGetByte(iFodo
+ iFodoOff
+ 3, aucGrpprl
);
443 if (iTmp
< 2 + 2 * iDel
) {
448 iAdd
= (int)ucGetByte(
449 iFodo
+ iFodoOff
+ 4 + 2 * iDel
, aucGrpprl
);
450 if (iTmp
< 2 + 2 * iDel
+ 2 * iAdd
) {
456 case 0x840e: /* dxaRight */
457 pStyle
->sRightIndent
= (short)usGetWord(
458 iFodo
+ iFodoOff
+ 2, aucGrpprl
);
459 NO_DBG_DEC(pStyle
->sRightIndent
);
461 case 0x840f: /* dxaLeft */
462 pStyle
->sLeftIndent
= (short)usGetWord(
463 iFodo
+ iFodoOff
+ 2, aucGrpprl
);
464 NO_DBG_DEC(pStyle
->sLeftIndent
);
466 case 0x8411: /* dxaLeft1 */
467 pStyle
->sLeftIndent1
= (short)usGetWord(
468 iFodo
+ iFodoOff
+ 2, aucGrpprl
);
469 NO_DBG_DEC(pStyle
->sLeftIndent1
);
471 case 0xa413: /* dyaBefore */
472 pStyle
->usBeforeIndent
= usGetWord(
473 iFodo
+ iFodoOff
+ 2, aucGrpprl
);
474 NO_DBG_DEC(pStyle
->usBeforeIndent
);
476 case 0xa414: /* dyaAfter */
477 pStyle
->usAfterIndent
= usGetWord(
478 iFodo
+ iFodoOff
+ 2, aucGrpprl
);
479 NO_DBG_DEC(pStyle
->usAfterIndent
);
481 case 0xc63e: /* anld */
482 iTmp
= (int)ucGetByte(
483 iFodo
+ iFodoOff
+ 2, aucGrpprl
);
484 DBG_DEC_C(iTmp
< 84, iTmp
);
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
);
496 tList6
.ulStartAt
= (ULONG
)usGetWord(
497 iFodo
+ iFodoOff
+ 13, aucGrpprl
);
499 if (iTmp
>= iBefore
+ 22) {
500 tList6
.usListChar
= usGetWord(
501 iFodo
+ iFodoOff
+ iBefore
+ 23,
503 DBG_HEX(tList6
.usListChar
);
507 NO_DBG_HEX(usOpCode
);
512 iGet8InfoLength(iFodo
+ iFodoOff
, aucGrpprl
);
515 iFodoOff
+= iInfoLen
;
518 if (pStyle
->usListIndex
== 2047) {
520 pStyle
->usStartAt
= (USHORT
)tList6
.ulStartAt
;
521 pStyle
->usListChar
= tList6
.usListChar
;
522 pStyle
->ucNFC
= tList6
.ucNFC
;
525 pList
= pGetListInfo(pStyle
->usListIndex
, pStyle
->ucListLevel
);
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
545 sGetLeftIndent(const UCHAR
*aucGrpprl
, size_t tBytes
)
547 int iOffset
, iInfoLen
;
548 USHORT usOpCode
, usTmp
;
550 fail(aucGrpprl
== NULL
);
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) {
562 iInfoLen
= iGet8InfoLength(iOffset
, aucGrpprl
);
567 } /* end of sGetLeftIndent */
570 * Build the list with List Information for Word 8/9/10 files
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
;
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
;
601 ulTableStartBlock
= pPPS
->t0Table
.ulSB
;
602 ulTableSize
= pPPS
->t0Table
.ulSize
;
604 DBG_DEC(ulTableStartBlock
);
605 if (ulTableStartBlock
== 0) {
606 DBG_MSG("No list information");
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
;
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");
632 aucLfoInfo
= xmalloc(tLfoInfoLen
);
633 if (!bReadBuffer(pFile
, ulTableStartBlock
,
634 aulBlockDepot
, tBlockDepotLen
, tBlockSize
,
635 aucLfoInfo
, ulBeginLfoInfo
, tLfoInfoLen
)) {
636 aucLfoInfo
= xfree(aucLfoInfo
);
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");
653 aucLstfInfo
= xmalloc(tLstfInfoLen
);
654 if (!bReadBuffer(pFile
, ulTableStartBlock
,
655 aulBlockDepot
, tBlockDepotLen
, tBlockSize
,
656 aucLstfInfo
, ulBeginLstfInfo
, tLstfInfoLen
)) {
657 aucLstfInfo
= xfree(aucLstfInfo
);
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
);
670 /* LVLF (List leVeL on File) */
671 ulBeginLvlfInfo
= ulBeginLstfInfo
+ tLstfInfoLen
;
672 DBG_HEX(ulBeginLvlfInfo
);
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
);
687 tStart
+ 8 + 2 * (size_t)ucListLevel
,
689 DBG_DEC_C(usIstd
!= STI_NIL
, usIstd
);
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
);
700 NO_DBG_PRINT_BLOCK(aucLvlfInfo
, sizeof(aucLvlfInfo
));
701 if (bAllZero(aucLvlfInfo
, sizeof(aucLvlfInfo
))) {
704 tList
.bNoRestart
= FALSE
;
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
);
714 aucPapx
= xmalloc(tPapxLen
);
716 if (!bReadBuffer(pFile
, ulTableStartBlock
,
717 aulBlockDepot
, tBlockDepotLen
,
719 ulStart
, tPapxLen
)) {
720 aucPapx
= xfree(aucPapx
);
721 aucLstfInfo
= xfree(aucLstfInfo
);
724 NO_DBG_PRINT_BLOCK(aucPapx
, tPapxLen
);
726 sGetLeftIndent(aucPapx
, tPapxLen
);
727 aucPapx
= xfree(aucPapx
);
730 ucChpxLen
= ucGetByte(24, aucLvlfInfo
);
731 ulStart
+= (ULONG
)ucChpxLen
;
732 /* Read the length of the XString */
733 if (!bReadBuffer(pFile
, ulTableStartBlock
,
734 aulBlockDepot
, tBlockDepotLen
,
736 ulStart
, sizeof(aucXst
))) {
737 aucLstfInfo
= xfree(aucLstfInfo
);
740 NO_DBG_PRINT_BLOCK(aucXst
, sizeof(aucXst
));
741 tXstLen
= (size_t)usGetWord(0, aucXst
);
742 ulStart
+= sizeof(aucXst
);
744 tList
.usListChar
= DEFAULT_LISTCHAR
;
745 vAdd2ListInfoList(ulListID
,
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
,
758 aucXString
= xfree(aucXString
);
759 aucLstfInfo
= xfree(aucLstfInfo
);
762 NO_DBG_PRINT_BLOCK(aucXString
, tXstLen
);
764 for (iNums
= 6; iNums
< 15; iNums
++) {
765 ucTmp
= ucGetByte(iNums
, aucLvlfInfo
);
769 tOff
= (size_t)ucTmp
;
771 tOff
*= 2; /* Offset in chars to offset in bytes */
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
);
779 tList
.usListChar
= DEFAULT_LISTCHAR
;
781 vAdd2ListInfoList(ulListID
,
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
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
)
802 style_block_type tStyle
;
804 const ULONG
*aulBlockDepot
;
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
);
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
;
834 ulTableStartBlock
= pPPS
->t0Table
.ulSB
;
835 ulTableSize
= pPPS
->t0Table
.ulSize
;
837 DBG_DEC(ulTableStartBlock
);
838 if (ulTableStartBlock
== 0) {
839 DBG_MSG("No paragraph information");
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
;
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
);
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;
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
,
883 aulParfPage
[iIndex
] * BIG_BLOCK_SIZE
,
887 NO_DBG_PRINT_BLOCK(aucFpage
, BIG_BLOCK_SIZE
);
888 iRun
= (int)ucGetByte(0x1ff, aucFpage
);
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
);
898 iLen
= 2 * (int)ucGetByte(iFodo
, aucFpage
);
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
);
916 if (ulCharPosFirst
!= CP_INVALID
) {
919 ulCharPosFirst
= ulGetLong(
920 iIndex2
* 4, aucFpage
);
921 NO_DBG_HEX(ulCharPosFirst
);
922 tRow
.ulCharPosStart
= ulCharPosFirst
;
923 tRow
.ulFileOffsetStart
=
924 ulCharPos2FileOffset(ulCharPosFirst
);
926 tRow
.ulFileOffsetStart
== FC_INVALID
,
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
,
938 vAdd2RowInfoList(&tRow
);
939 (void)memset(&tRow
, 0, sizeof(tRow
));
940 ulCharPosFirst
= CP_INVALID
;
950 aulParfPage
= xfree(aulParfPage
);
951 } /* end of vGet8PapInfo */
954 * Fill the font information block with information
955 * from a Word 8/9/10 file.
958 vGet8FontInfo(int iFodo
, USHORT usIstd
,
959 const UCHAR
*aucGrpprl
, int iBytes
, font_block_type
*pFont
)
962 int iFodoOff
, iInfoLen
;
966 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pFont
== NULL
);
969 while (iBytes
>= iFodoOff
+ 2) {
970 switch (usGetWord(iFodo
+ iFodoOff
, aucGrpprl
)) {
971 case 0x0800: /* fRMarkDel */
972 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
974 pFont
->usFontStyle
&= ~FONT_MARKDEL
;
976 pFont
->usFontStyle
|= FONT_MARKDEL
;
979 case 0x0835: /* fBold */
980 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
983 pFont
->usFontStyle
&= ~FONT_BOLD
;
986 pFont
->usFontStyle
|= FONT_BOLD
;
988 case 128: /* Unchanged */
990 case 129: /* Negation */
991 pFont
->usFontStyle
^= FONT_BOLD
;
999 case 0x0836: /* fItalic */
1000 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1003 pFont
->usFontStyle
&= ~FONT_ITALIC
;
1006 pFont
->usFontStyle
|= FONT_ITALIC
;
1008 case 128: /* Unchanged */
1010 case 129: /* Negation */
1011 pFont
->usFontStyle
^= FONT_ITALIC
;
1019 case 0x0837: /* fStrike */
1020 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1023 pFont
->usFontStyle
&= ~FONT_STRIKE
;
1026 pFont
->usFontStyle
|= FONT_STRIKE
;
1028 case 128: /* Unchanged */
1030 case 129: /* Negation */
1031 pFont
->usFontStyle
^= FONT_STRIKE
;
1039 case 0x083a: /* fSmallCaps */
1040 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1043 pFont
->usFontStyle
&= ~FONT_SMALL_CAPITALS
;
1046 pFont
->usFontStyle
|= FONT_SMALL_CAPITALS
;
1048 case 128: /* Unchanged */
1050 case 129: /* Negation */
1051 pFont
->usFontStyle
^= FONT_SMALL_CAPITALS
;
1059 case 0x083b: /* fCaps */
1060 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1063 pFont
->usFontStyle
&= ~FONT_CAPITALS
;
1066 pFont
->usFontStyle
|= FONT_CAPITALS
;
1068 case 128: /* Unchanged */
1070 case 129: /* Negation */
1071 pFont
->usFontStyle
^= FONT_CAPITALS
;
1079 case 0x083c: /* fVanish */
1080 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1083 pFont
->usFontStyle
&= ~FONT_HIDDEN
;
1086 pFont
->usFontStyle
|= FONT_HIDDEN
;
1088 case 128: /* Unchanged */
1090 case 129: /* Negation */
1091 pFont
->usFontStyle
^= FONT_HIDDEN
;
1099 case 0x2a32: /* cDefault */
1100 pFont
->usFontStyle
&= FONT_HIDDEN
;
1101 pFont
->ucFontColor
= FONT_COLOR_DEFAULT
;
1103 case 0x2a33: /* cPlain */
1104 DBG_MSG("2a33: cPlain");
1105 vFillFontFromStylesheet(usIstd
, pFont
);
1107 case 0x2a3e: /* cKul */
1108 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1109 if (ucTmp
== 0 || ucTmp
== 5) {
1110 pFont
->usFontStyle
&= ~FONT_UNDERLINE
;
1112 NO_DBG_MSG("Underline text");
1113 pFont
->usFontStyle
|= FONT_UNDERLINE
;
1115 DBG_MSG("Bold text");
1116 pFont
->usFontStyle
|= FONT_BOLD
;
1120 case 0x2a42: /* cIco */
1121 pFont
->ucFontColor
=
1122 ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1123 NO_DBG_DEC(pFont
->ucFontColor
);
1125 case 0x2a48: /* cIss */
1126 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
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");
1136 case 0x4a30: /* cIstd */
1137 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1140 case 0x4a43: /* cHps */
1142 usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1143 NO_DBG_DEC(pFont
->usFontSize
);
1145 case 0x4a51: /* cFtc */
1146 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1147 if (usTmp
<= (USHORT
)UCHAR_MAX
) {
1148 pFont
->ucFontNumber
= (UCHAR
)usTmp
;
1150 pFont
->ucFontNumber
= 0;
1153 case 0xca4a: /* cHps */
1154 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1155 lTmp
= (long)pFont
->usFontSize
+ (long)usTmp
;
1157 pFont
->usFontSize
= 8;
1158 } else if (lTmp
> 32766) {
1159 pFont
->usFontSize
= 32766;
1161 pFont
->usFontSize
= (USHORT
)lTmp
;
1164 case 0xea3f: /* cHps, cHpsPos */
1165 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1167 pFont
->usFontSize
= (USHORT
)ucTmp
;
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
1186 bGet8PicInfo(int iFodo
,
1187 const UCHAR
*aucGrpprl
, int iBytes
, picture_block_type
*pPicture
)
1189 int iFodoOff
, iInfoLen
;
1193 fail(iFodo
<= 0 || aucGrpprl
== NULL
|| pPicture
== NULL
);
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 */
1205 DBG_DEC_C(ucTmp
!= 0, ucTmp
);
1207 case 0x080a: /* fOle2 */
1208 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1209 if (ucTmp
== 0x01) {
1210 /* Not a picture, but an OLE object */
1213 DBG_DEC_C(ucTmp
!= 0, ucTmp
);
1215 case 0x6a03: /* fcPic */
1216 pPicture
->ulPictureOffset
= ulGetLong(
1217 iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1223 iInfoLen
= iGet8InfoLength(iFodo
+ iFodoOff
, aucGrpprl
);
1224 fail(iInfoLen
<= 0);
1225 iFodoOff
+= iInfoLen
;
1228 } /* end of bGet8PicInfo */
1231 * Build the lists with Character Information for Word 8/9/10 files
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
;
1242 const ULONG
*aulBlockDepot
;
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
);
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
;
1270 ulTableStartBlock
= pPPS
->t0Table
.ulSB
;
1271 ulTableSize
= pPPS
->t0Table
.ulSize
;
1273 DBG_DEC(ulTableStartBlock
);
1274 if (ulTableStartBlock
== 0) {
1275 DBG_MSG("No character information");
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
;
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
);
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;
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
,
1316 aulCharPage
[iIndex
] * BIG_BLOCK_SIZE
,
1320 NO_DBG_PRINT_BLOCK(aucFpage
, BIG_BLOCK_SIZE
);
1321 iRun
= (int)ucGetByte(0x1ff, aucFpage
);
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
);
1334 vGet8FontInfo(iFodo
, usIstd
,
1335 aucFpage
+ 1, iLen
- 1, &tFont
);
1337 tFont
.ulFileOffset
= ulFileOffset
;
1338 vAdd2FontInfoList(&tFont
);
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 */