3 * Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
6 * Read the property information from a MS Word 8, 9,10 or 11 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
11 * Word 11 is better known as Word 2003
18 #define DEFAULT_LISTCHAR 0x002e /* A full stop */
22 * iGet8InfoLength - the length of the information for Word 8/9/10/11 files
25 iGet8InfoLength(int iByteNbr
, const UCHAR
*aucGrpprl
)
30 usOpCode
= usGetWord(iByteNbr
, aucGrpprl
);
32 switch (usOpCode
& 0xe000) {
33 case 0x0000: case 0x2000:
35 case 0x4000: case 0x8000: case 0xa000:
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;
55 } /* end of iGet8InfoLength */
58 * aucFillInfoBuffer - fill the information buffer
60 * Returns the information buffer when successful, otherwise NULL
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
)
68 const ULONG
*aulBlockDepot
;
70 size_t tBlockDepotLen
, tBlockSize
;
72 fail(pFile
== NULL
|| pTable
== NULL
);
73 fail(aulBBD
== NULL
|| aulSBD
== NULL
);
76 NO_DBG_DEC(pTable
->ulSB
);
77 NO_DBG_HEX(pTable
->ulSize
);
78 if (pTable
->ulSize
== 0) {
79 DBG_MSG("No information");
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
;
89 /* Use the Big Block Depot */
90 aulBlockDepot
= aulBBD
;
91 tBlockDepotLen
= tBBDLen
;
92 tBlockSize
= BIG_BLOCK_SIZE
;
94 aucBuffer
= xmalloc(tInfoLen
);
95 if (!bReadBuffer(pFile
, pTable
->ulSB
,
96 aulBlockDepot
, tBlockDepotLen
, tBlockSize
,
97 aucBuffer
, ulBeginInfo
, tInfoLen
)) {
98 aucBuffer
= xfree(aucBuffer
);
102 } /* end of aucFillInfoBuffer */
105 * Build the lists with Document Property Information for Word 8/9/10/11 files
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
)
113 document_block_type tDocument
;
115 ULONG ulBeginDocpInfo
, ulTmp
;
119 fail(pFile
== NULL
|| pTable
== NULL
|| aucHeader
== NULL
);
120 fail(aulBBD
== NULL
|| aulSBD
== NULL
);
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");
131 aucBuffer
= aucFillInfoBuffer(pFile
, pTable
,
132 aulBBD
, tBBDLen
, aulSBD
, tSBDLen
,
133 ulBeginDocpInfo
, tDocpInfoLen
);
134 if (aucBuffer
== NULL
) {
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
);
147 aucBuffer
= xfree(aucBuffer
);
148 } /* end of vGet8DopInfo */
151 * Fill the section information block with information
152 * from a Word 8/9/10/11 file.
155 vGet8SectionInfo(const UCHAR
*aucGrpprl
, size_t tBytes
,
156 section_block_type
*pSection
)
159 int iFodoOff
, iInfoLen
, iSize
, iTmp
;
163 fail(aucGrpprl
== NULL
|| pSection
== NULL
);
166 while (tBytes
>= (size_t)iFodoOff
+ 2) {
168 switch (usGetWord(iFodoOff
, aucGrpprl
)) {
169 case 0x3009: /* bkc */
170 ucTmp
= ucGetByte(iFodoOff
+ 2, aucGrpprl
);
172 pSection
->bNewPage
= ucTmp
!= 0 && ucTmp
!= 1;
174 case 0x3014: /* grpfIhdt */
175 pSection
->ucHdrFtrSpecification
=
176 ucGetByte(iFodoOff
+ 2, aucGrpprl
);
178 case 0x500b: /* ccolM1 */
179 usCcol
= 1 + usGetWord(iFodoOff
+ 2, aucGrpprl
);
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
);
193 if ((ucTmp
& BIT(2)) != 0) {
194 pSection
->usNeedPrevLvl
|=
195 (USHORT
)BIT(uiIndex
);
197 if ((ucTmp
& BIT(3)) != 0) {
198 pSection
->usHangingIndent
|=
199 (USHORT
)BIT(uiIndex
);
202 DBG_HEX(pSection
->usNeedPrevLvl
);
203 DBG_HEX(pSection
->usHangingIndent
);
209 iInfoLen
= iGet8InfoLength(iFodoOff
, aucGrpprl
);
212 iFodoOff
+= iInfoLen
;
214 } /* end of vGet8SectionInfo */
217 * Build the lists with Section Property Information for Word 8/9/10/11 files
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
)
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
;
232 fail(pFile
== NULL
|| pPPS
== NULL
|| aucHeader
== NULL
);
233 fail(aulBBD
== NULL
|| aulSBD
== NULL
);
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
);
246 aucBuffer
= aucFillInfoBuffer(pFile
, &pPPS
->tTable
,
247 aulBBD
, tBBDLen
, aulSBD
, tSBDLen
,
248 ulBeginSectInfo
, tSectInfoLen
);
249 if (aucBuffer
== NULL
) {
252 NO_DBG_PRINT_BLOCK(aucBuffer
, tSectInfoLen
);
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;
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
]);
266 /* Save the Sepx offsets */
267 aulSectPage
= xcalloc(tLen
, sizeof(ULONG
));
268 for (tIndex
= 0, tOffset
= (tLen
+ 1) * 4;
270 tIndex
++, tOffset
+= 12) {
271 aulSectPage
[tIndex
] = ulGetLong(tOffset
+ 2, aucBuffer
);
272 NO_DBG_HEX(aulSectPage
[tIndex
]); /* fcSepx */
274 aucBuffer
= xfree(aucBuffer
);
276 /* Read the Section Properties */
277 for (tIndex
= 0; tIndex
< tLen
; tIndex
++) {
278 if (aulSectPage
[tIndex
] == FC_INVALID
) {
279 vDefault2SectionInfoList(aulCharPos
[tIndex
]);
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)) {
288 tBytes
= 2 + (size_t)usGetWord(0, aucTmp
);
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
);
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
);
305 aulCharPos
= xfree(aulCharPos
);
306 aulSectPage
= xfree(aulSectPage
);
307 } /* end of vGet8SepInfo */
310 * Build the list with Header/Footer Information for Word 8/9/10/11 files
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
)
320 ULONG ulHdrFtrOffset
, ulBeginHdrFtrInfo
;
321 size_t tHdrFtrInfoLen
, tIndex
, tOffset
, tLen
;
323 fail(pFile
== NULL
|| pTable
== NULL
|| aucHeader
== NULL
);
324 fail(aulBBD
== NULL
|| aulSBD
== NULL
);
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
);
335 aucBuffer
= aucFillInfoBuffer(pFile
, pTable
,
336 aulBBD
, tBBDLen
, aulSBD
, tSBDLen
,
337 ulBeginHdrFtrInfo
, tHdrFtrInfoLen
);
338 if (aucBuffer
== NULL
) {
341 NO_DBG_PRINT_BLOCK(aucBuffer
, tHdrFtrInfoLen
);
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;
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
]);
355 vCreat8HdrFtrInfoList(aulCharPos
, tLen
);
356 /* Clean up and leave */
357 aulCharPos
= xfree(aulCharPos
);
358 aucBuffer
= xfree(aucBuffer
);
359 } /* end of vGet8HdrFtrInfo */
362 * Translate the rowinfo to a member of the row_info enumeration
365 eGet8RowInfo(int iFodo
,
366 const UCHAR
*aucGrpprl
, int iBytes
, row_block_type
*pRow
)
368 int iFodoOff
, iInfoLen
;
369 int iIndex
, iSize
, iCol
;
370 int iPosCurr
, iPosPrev
;
372 BOOL bFound2416_0
, bFound2416_1
, bFound2417_0
, bFound2417_1
;
373 BOOL bFound244b_0
, bFound244b_1
, bFound244c_0
, bFound244c_1
;
376 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pRow
== NULL
);
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
;
388 while (iBytes
>= iFodoOff
+ 2) {
390 switch (usGetWord(iFodo
+ iFodoOff
, aucGrpprl
)) {
391 case 0x2416: /* fInTable */
392 if (odd(ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
))) {
398 case 0x2417: /* fTtp */
399 if (odd(ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
))) {
405 case 0x244b: /* sub-table fInTable */
406 if (odd(ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
))) {
412 case 0x244c: /* sub-table fTtp */
413 if (odd(ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
))) {
419 case 0x6424: /* brcTop */
420 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
422 NO_DBG_DEC(usTmp
>> 8);
424 pRow
->ucBorderInfo
&= ~TABLE_BORDER_TOP
;
426 pRow
->ucBorderInfo
|= TABLE_BORDER_TOP
;
429 case 0x6425: /* brcLeft */
430 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
432 NO_DBG_DEC(usTmp
>> 8);
434 pRow
->ucBorderInfo
&= ~TABLE_BORDER_LEFT
;
436 pRow
->ucBorderInfo
|= TABLE_BORDER_LEFT
;
439 case 0x6426: /* brcBottom */
440 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
442 NO_DBG_DEC(usTmp
>> 8);
444 pRow
->ucBorderInfo
&= ~TABLE_BORDER_BOTTOM
;
446 pRow
->ucBorderInfo
|= TABLE_BORDER_BOTTOM
;
449 case 0x6427: /* brcRight */
450 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
452 NO_DBG_DEC(usTmp
>> 8);
454 pRow
->ucBorderInfo
&= ~TABLE_BORDER_RIGHT
;
456 pRow
->ucBorderInfo
|= TABLE_BORDER_RIGHT
;
459 case 0xd606: /* cDefTable10 */
460 DBG_MSG("0xd606: sprmTDefTable10");
461 iSize
= (int)usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
464 case 0xd608: /* cDefTable */
465 iSize
= (int)usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
466 if (iSize
< 6 || iBytes
< iFodoOff
+ 8) {
472 iCol
= (int)ucGetByte(iFodo
+ iFodoOff
+ 4, aucGrpprl
);
474 iBytes
< iFodoOff
+ 4 + (iCol
+ 1) * 2) {
480 if (iCol
>= (int)elementsof(pRow
->asColumnWidth
)) {
482 werr(1, "The number of columns is corrupt");
484 pRow
->ucNumberOfColumns
= (UCHAR
)iCol
;
485 iPosPrev
= (int)(short)usGetWord(
486 iFodo
+ iFodoOff
+ 5,
488 for (iIndex
= 0; iIndex
< iCol
; iIndex
++) {
489 iPosCurr
= (int)(short)usGetWord(
490 iFodo
+ iFodoOff
+ 7 + iIndex
* 2,
492 pRow
->asColumnWidth
[iIndex
] =
493 (short)(iPosCurr
- iPosPrev
);
503 iGet8InfoLength(iFodo
+ iFodoOff
, aucGrpprl
);
506 iFodoOff
+= iInfoLen
;
509 if (bFound2417_1
&& bFoundd608
) {
510 return found_end_of_row
;
512 if (bFound2417_0
&& !bFoundd608
) {
513 return found_not_end_of_row
;
515 if (bFound2416_1
|| bFound244b_1
) {
518 if (bFound2416_0
|| bFound244b_0
) {
519 return found_not_a_cell
;
521 return found_nothing
;
522 } /* end of eGet8RowInfo */
525 * Fill the style information block with information
526 * from a Word 8/9/10/11 file.
529 vGet8StyleInfo(int iFodo
,
530 const UCHAR
*aucGrpprl
, int iBytes
, style_block_type
*pStyle
)
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
;
539 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pStyle
== NULL
);
541 NO_DBG_DEC_C(pStyle
->usListIndex
!= 0, pStyle
->usIstd
);
542 NO_DBG_DEC_C(pStyle
->usListIndex
!= 0, pStyle
->usListIndex
);
544 (void)memset(&tList6
, 0, sizeof(tList6
));
547 while (iBytes
>= iFodoOff
+ 2) {
549 usOpCode
= usGetWord(iFodo
+ iFodoOff
, aucGrpprl
);
551 case 0x2403: /* jc */
552 pStyle
->ucAlignment
= ucGetByte(
553 iFodo
+ iFodoOff
+ 2, aucGrpprl
);
555 case 0x260a: /* ilvl */
556 pStyle
->ucListLevel
=
557 ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
558 NO_DBG_DEC(pStyle
->ucListLevel
);
559 pStyle
->ucNumLevel
= pStyle
->ucListLevel
;
561 case 0x4600: /* istd */
562 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
565 case 0x460b: /* ilfo */
566 pStyle
->usListIndex
=
567 usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
568 NO_DBG_DEC(pStyle
->usListIndex
);
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;
578 DBG_DEC(pStyle
->sLeftIndent
);
580 case 0xc60d: /* ChgTabsPapx */
581 case 0xc615: /* ChgTabs */
582 iTmp
= (int)ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
588 iDel
= (int)ucGetByte(iFodo
+ iFodoOff
+ 3, aucGrpprl
);
589 if (iTmp
< 2 + 2 * iDel
) {
594 iAdd
= (int)ucGetByte(
595 iFodo
+ iFodoOff
+ 4 + 2 * iDel
, aucGrpprl
);
596 if (iTmp
< 2 + 2 * iDel
+ 2 * iAdd
) {
602 case 0x840e: /* dxaRight */
603 pStyle
->sRightIndent
= (short)usGetWord(
604 iFodo
+ iFodoOff
+ 2, aucGrpprl
);
605 NO_DBG_DEC(pStyle
->sRightIndent
);
607 case 0x840f: /* dxaLeft */
608 pStyle
->sLeftIndent
= (short)usGetWord(
609 iFodo
+ iFodoOff
+ 2, aucGrpprl
);
610 NO_DBG_DEC(pStyle
->sLeftIndent
);
612 case 0x8411: /* dxaLeft1 */
613 pStyle
->sLeftIndent1
= (short)usGetWord(
614 iFodo
+ iFodoOff
+ 2, aucGrpprl
);
615 NO_DBG_DEC(pStyle
->sLeftIndent1
);
617 case 0xa413: /* dyaBefore */
618 pStyle
->usBeforeIndent
= usGetWord(
619 iFodo
+ iFodoOff
+ 2, aucGrpprl
);
620 NO_DBG_DEC(pStyle
->usBeforeIndent
);
622 case 0xa414: /* dyaAfter */
623 pStyle
->usAfterIndent
= usGetWord(
624 iFodo
+ iFodoOff
+ 2, aucGrpprl
);
625 NO_DBG_DEC(pStyle
->usAfterIndent
);
627 case 0xc63e: /* anld */
628 iTmp
= (int)ucGetByte(
629 iFodo
+ iFodoOff
+ 2, aucGrpprl
);
630 DBG_DEC_C(iTmp
< 84, iTmp
);
632 tList6
.ucNFC
= ucGetByte(
633 iFodo
+ iFodoOff
+ 3, aucGrpprl
);
635 if (tList6
.ucNFC
!= LIST_BULLETS
&& iTmp
>= 2) {
636 iBefore
= (int)ucGetByte(
637 iFodo
+ iFodoOff
+ 4, aucGrpprl
);
642 tList6
.ulStartAt
= (ULONG
)usGetWord(
643 iFodo
+ iFodoOff
+ 13, aucGrpprl
);
645 if (iTmp
>= iBefore
+ 22) {
646 tList6
.usListChar
= usGetWord(
647 iFodo
+ iFodoOff
+ iBefore
+ 23,
649 DBG_HEX(tList6
.usListChar
);
653 NO_DBG_HEX(usOpCode
);
658 iGet8InfoLength(iFodo
+ iFodoOff
, aucGrpprl
);
661 iFodoOff
+= iInfoLen
;
664 if (pStyle
->usListIndex
== 2047) {
666 pStyle
->usStartAt
= (USHORT
)tList6
.ulStartAt
;
667 pStyle
->usListChar
= tList6
.usListChar
;
668 pStyle
->ucNFC
= tList6
.ucNFC
;
671 pList
= pGetListInfo(pStyle
->usListIndex
, pStyle
->ucListLevel
);
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
;
683 } /* end of vGet8StyleInfo */
686 * Get the left indentation value from the style information block
688 * Returns the value when found, otherwise 0
691 sGetLeftIndent(const UCHAR
*aucGrpprl
, size_t tBytes
)
693 int iOffset
, iInfoLen
;
694 USHORT usOpCode
, usTmp
;
696 fail(aucGrpprl
== NULL
);
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) {
708 iInfoLen
= iGet8InfoLength(iOffset
, aucGrpprl
);
713 } /* end of sGetLeftIndent */
716 * Build the list with List Information for Word 8/9/10/11 files
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
)
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
;
734 UCHAR ucTmp
, ucListLevel
, ucMaxLevel
, ucChpxLen
;
735 UCHAR aucLvlfInfo
[28], aucXst
[2];
737 fail(pFile
== NULL
|| pPPS
== NULL
|| aucHeader
== NULL
);
738 fail(aulBBD
== NULL
|| aulSBD
== NULL
);
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");
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
;
753 /* Use the Big Block Depot */
754 aulBlockDepot
= aulBBD
;
755 tBlockDepotLen
= tBBDLen
;
756 tBlockSize
= BIG_BLOCK_SIZE
;
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");
769 aucLfoInfo
= xmalloc(tLfoInfoLen
);
770 if (!bReadBuffer(pFile
, pPPS
->tTable
.ulSB
,
771 aulBlockDepot
, tBlockDepotLen
, tBlockSize
,
772 aucLfoInfo
, ulBeginLfoInfo
, tLfoInfoLen
)) {
773 aucLfoInfo
= xfree(aucLfoInfo
);
776 NO_DBG_PRINT_BLOCK(aucLfoInfo
, tLfoInfoLen
);
777 vBuildLfoList(aucLfoInfo
, tLfoInfoLen
);
778 aucLfoInfo
= xfree(aucLfoInfo
);
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");
790 aucLstfInfo
= xmalloc(tLstfInfoLen
);
791 if (!bReadBuffer(pFile
, pPPS
->tTable
.ulSB
,
792 aulBlockDepot
, tBlockDepotLen
, tBlockSize
,
793 aucLstfInfo
, ulBeginLstfInfo
, tLstfInfoLen
)) {
794 aucLstfInfo
= xfree(aucLstfInfo
);
797 NO_DBG_PRINT_BLOCK(aucLstfInfo
, tLstfInfoLen
);
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
);
807 /* LVLF (List leVeL on File) */
808 ulBeginLvlfInfo
= ulBeginLstfInfo
+ tLstfInfoLen
;
809 DBG_HEX(ulBeginLvlfInfo
);
812 ulStart
= ulBeginLvlfInfo
;
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
);
824 tStart
+ 8 + 2 * (size_t)ucListLevel
,
826 DBG_DEC_C(usIstd
!= STI_NIL
, usIstd
);
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
);
837 NO_DBG_PRINT_BLOCK(aucLvlfInfo
, sizeof(aucLvlfInfo
));
838 if (bAllZero(aucLvlfInfo
, sizeof(aucLvlfInfo
))) {
841 tList
.bNoRestart
= FALSE
;
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");
850 ulStart
+= sizeof(aucLvlfInfo
);
851 tPapxLen
= (size_t)ucGetByte(25, aucLvlfInfo
);
853 aucPapx
= xmalloc(tPapxLen
);
855 if (!bReadBuffer(pFile
, pPPS
->tTable
.ulSB
,
856 aulBlockDepot
, tBlockDepotLen
,
858 ulStart
, tPapxLen
)) {
859 aucPapx
= xfree(aucPapx
);
860 aucLstfInfo
= xfree(aucLstfInfo
);
863 NO_DBG_PRINT_BLOCK(aucPapx
, tPapxLen
);
865 sGetLeftIndent(aucPapx
, tPapxLen
);
866 aucPapx
= xfree(aucPapx
);
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
,
875 ulStart
, sizeof(aucXst
))) {
876 aucLstfInfo
= xfree(aucLstfInfo
);
879 NO_DBG_PRINT_BLOCK(aucXst
, sizeof(aucXst
));
880 tXstLen
= (size_t)usGetWord(0, aucXst
);
881 ulStart
+= sizeof(aucXst
);
883 tList
.usListChar
= DEFAULT_LISTCHAR
;
884 vAdd2ListInfoList(ulListID
,
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
,
897 aucXString
= xfree(aucXString
);
898 aucLstfInfo
= xfree(aucLstfInfo
);
901 NO_DBG_PRINT_BLOCK(aucXString
, tXstLen
);
903 for (iNums
= 6; iNums
< 15; iNums
++) {
904 ucTmp
= ucGetByte(iNums
, aucLvlfInfo
);
908 tOff
= (size_t)ucTmp
;
910 tOff
*= 2; /* Offset in chars to offset in bytes */
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
);
919 tList
.usListChar
= DEFAULT_LISTCHAR
;
921 vAdd2ListInfoList(ulListID
,
926 aucXString
= xfree(aucXString
);
929 aucLstfInfo
= xfree(aucLstfInfo
);
930 } /* end of vGet8LstInfo */
933 * Build the lists with Paragraph Information for Word 8/9/10/11 files
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
)
942 style_block_type tStyle
;
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
;
951 UCHAR aucFpage
[BIG_BLOCK_SIZE
];
953 fail(pFile
== NULL
|| pPPS
== NULL
|| aucHeader
== NULL
);
954 fail(aulBBD
== NULL
|| aulSBD
== NULL
);
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
);
965 aucBuffer
= aucFillInfoBuffer(pFile
, &pPPS
->tTable
,
966 aulBBD
, tBBDLen
, aulSBD
, tSBDLen
,
967 ulBeginParfInfo
, tParfInfoLen
);
968 if (aucBuffer
== NULL
) {
971 NO_DBG_PRINT_BLOCK(aucBuffer
, tParfInfoLen
);
973 tLen
= (tParfInfoLen
/ 4 - 1) / 2;
974 aulParfPage
= xcalloc(tLen
, sizeof(ULONG
));
975 for (iIndex
= 0, tOffset
= (tLen
+ 1) * 4;
977 iIndex
++, tOffset
+= 4) {
978 aulParfPage
[iIndex
] = ulGetLong(tOffset
, aucBuffer
);
979 NO_DBG_DEC(aulParfPage
[iIndex
]);
981 DBG_HEX(ulGetLong(0, aucBuffer
));
982 aucBuffer
= xfree(aucBuffer
);
983 NO_DBG_PRINT_BLOCK(aucHeader
, HEADER_SIZE
);
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
,
992 aulParfPage
[iIndex
] * BIG_BLOCK_SIZE
,
996 NO_DBG_PRINT_BLOCK(aucFpage
, BIG_BLOCK_SIZE
);
997 iRun
= (int)ucGetByte(0x1ff, aucFpage
);
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
);
1007 iLen
= 2 * (int)ucGetByte(iFodo
, aucFpage
);
1010 iLen
= 2 * (int)ucGetByte(iFodo
, aucFpage
);
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
);
1022 eRowInfo
= eGet8RowInfo(iFodo
,
1023 aucFpage
+ 3, iLen
- 3, &tRow
);
1026 if (ulCharPosFirst
!= CP_INVALID
) {
1029 ulCharPosFirst
= ulGetLong(
1030 iIndex2
* 4, aucFpage
);
1031 NO_DBG_HEX(ulCharPosFirst
);
1032 tRow
.ulCharPosStart
= ulCharPosFirst
;
1033 tRow
.ulFileOffsetStart
=
1034 ulCharPos2FileOffset(ulCharPosFirst
);
1036 tRow
.ulFileOffsetStart
== FC_INVALID
,
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
,
1048 vAdd2RowInfoList(&tRow
);
1049 (void)memset(&tRow
, 0, sizeof(tRow
));
1050 ulCharPosFirst
= CP_INVALID
;
1060 aulParfPage
= xfree(aulParfPage
);
1061 } /* end of vGet8PapInfo */
1064 * Fill the font information block with information
1065 * from a Word 8/9/10/11 file.
1068 vGet8FontInfo(int iFodo
, USHORT usIstd
,
1069 const UCHAR
*aucGrpprl
, int iBytes
, font_block_type
*pFont
)
1072 int iFodoOff
, iInfoLen
;
1073 USHORT usFtc0
, usFtc1
, usFtc2
, usTmp
;
1076 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pFont
== NULL
);
1083 while (iBytes
>= iFodoOff
+ 2) {
1084 switch (usGetWord(iFodo
+ iFodoOff
, aucGrpprl
)) {
1085 case 0x0800: /* fRMarkDel */
1086 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1088 pFont
->usFontStyle
&= ~FONT_MARKDEL
;
1090 pFont
->usFontStyle
|= FONT_MARKDEL
;
1093 case 0x0835: /* fBold */
1094 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1097 pFont
->usFontStyle
&= ~FONT_BOLD
;
1100 pFont
->usFontStyle
|= FONT_BOLD
;
1102 case 128: /* Unchanged */
1104 case 129: /* Negation */
1105 pFont
->usFontStyle
^= FONT_BOLD
;
1113 case 0x0836: /* fItalic */
1114 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1117 pFont
->usFontStyle
&= ~FONT_ITALIC
;
1120 pFont
->usFontStyle
|= FONT_ITALIC
;
1122 case 128: /* Unchanged */
1124 case 129: /* Negation */
1125 pFont
->usFontStyle
^= FONT_ITALIC
;
1133 case 0x0837: /* fStrike */
1134 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1137 pFont
->usFontStyle
&= ~FONT_STRIKE
;
1140 pFont
->usFontStyle
|= FONT_STRIKE
;
1142 case 128: /* Unchanged */
1144 case 129: /* Negation */
1145 pFont
->usFontStyle
^= FONT_STRIKE
;
1153 case 0x083a: /* fSmallCaps */
1154 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1157 pFont
->usFontStyle
&= ~FONT_SMALL_CAPITALS
;
1160 pFont
->usFontStyle
|= FONT_SMALL_CAPITALS
;
1162 case 128: /* Unchanged */
1164 case 129: /* Negation */
1165 pFont
->usFontStyle
^= FONT_SMALL_CAPITALS
;
1173 case 0x083b: /* fCaps */
1174 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1177 pFont
->usFontStyle
&= ~FONT_CAPITALS
;
1180 pFont
->usFontStyle
|= FONT_CAPITALS
;
1182 case 128: /* Unchanged */
1184 case 129: /* Negation */
1185 pFont
->usFontStyle
^= FONT_CAPITALS
;
1193 case 0x083c: /* fVanish */
1194 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1197 pFont
->usFontStyle
&= ~FONT_HIDDEN
;
1200 pFont
->usFontStyle
|= FONT_HIDDEN
;
1202 case 128: /* Unchanged */
1204 case 129: /* Negation */
1205 pFont
->usFontStyle
^= FONT_HIDDEN
;
1213 case 0x2a32: /* cDefault */
1214 pFont
->usFontStyle
&= FONT_HIDDEN
;
1215 pFont
->ucFontColor
= FONT_COLOR_DEFAULT
;
1217 case 0x2a33: /* cPlain */
1218 DBG_MSG("2a33: cPlain");
1219 vFillFontFromStylesheet(usIstd
, pFont
);
1221 case 0x2a3e: /* cKul */
1222 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1223 if (ucTmp
== 0 || ucTmp
== 5) {
1224 pFont
->usFontStyle
&= ~FONT_UNDERLINE
;
1226 NO_DBG_MSG("Underline text");
1227 pFont
->usFontStyle
|= FONT_UNDERLINE
;
1229 DBG_MSG("Bold text");
1230 pFont
->usFontStyle
|= FONT_BOLD
;
1234 case 0x2a42: /* cIco */
1235 pFont
->ucFontColor
=
1236 ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1237 NO_DBG_DEC(pFont
->ucFontColor
);
1239 case 0x2a44: /* cHpsInc */
1240 DBG_MSG("0x2a44: sprmCHpsInc");
1241 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1244 case 0x2a48: /* cIss */
1245 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
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");
1255 case 0x4a30: /* cIstd */
1256 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1259 case 0x4a43: /* cHps */
1261 usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1262 NO_DBG_DEC(pFont
->usFontSize
);
1264 case 0x4a4d: /* cHpsMul */
1265 DBG_MSG("0x4a4d: sprmCHpsMul");
1266 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1269 case 0x4a4f: /* cFtc0 */
1270 usFtc0
= usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1272 case 0x4a50: /* cFtc1 */
1273 usFtc1
= usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1275 case 0x4a51: /* cFtc2 */
1276 usFtc2
= usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1278 case 0xca47: /* cMajority */
1279 DBG_MSG("0xca47: sprmCMajority");
1281 case 0xca4a: /* cHpsInc1 */
1282 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1283 lTmp
= (long)pFont
->usFontSize
+ (long)usTmp
;
1285 pFont
->usFontSize
= 8;
1286 } else if (lTmp
> 32766) {
1287 pFont
->usFontSize
= 32766;
1289 pFont
->usFontSize
= (USHORT
)lTmp
;
1292 case 0xca4c: /* cMajority50 */
1293 DBG_MSG("0xca4c: sprmCMajority50");
1295 case 0xea3f: /* cHps, cHpsPos */
1296 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1299 pFont
->usFontSize
= (USHORT
)ucTmp
;
1301 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 3, aucGrpprl
);
1307 iInfoLen
= iGet8InfoLength(iFodo
+ iFodoOff
, aucGrpprl
);
1308 fail(iInfoLen
<= 0);
1309 iFodoOff
+= iInfoLen
;
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
;
1322 pFont
->ucFontNumber
= 0;
1324 } else if (usFtc2
<= 0x7fff) {
1325 if (usFtc2
<= (USHORT
)UCHAR_MAX
) {
1326 pFont
->ucFontNumber
= (UCHAR
)usFtc2
;
1330 pFont
->ucFontNumber
= 0;
1332 } else if (usFtc1
<= 0x7fff) {
1333 if (usFtc1
<= (USHORT
)UCHAR_MAX
) {
1334 pFont
->ucFontNumber
= (UCHAR
)usFtc1
;
1338 pFont
->ucFontNumber
= 0;
1341 } /* end of vGet8FontInfo */
1344 * Fill the picture information block with information
1345 * from a Word 8/9/10/11 file.
1346 * Returns TRUE when successful, otherwise FALSE
1349 bGet8PicInfo(int iFodo
,
1350 const UCHAR
*aucGrpprl
, int iBytes
, picture_block_type
*pPicture
)
1353 int iFodoOff
, iInfoLen
;
1357 fail(iFodo
<= 0 || aucGrpprl
== NULL
|| pPicture
== NULL
);
1361 while (iBytes
>= iFodoOff
+ 2) {
1362 switch (usGetWord(iFodo
+ iFodoOff
, aucGrpprl
)) {
1364 case 0x0806: /* fData */
1365 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1366 if (ucTmp
== 0x01) {
1367 /* Not a picture, but a form field */
1370 DBG_DEC_C(ucTmp
!= 0, ucTmp
);
1373 case 0x080a: /* fOle2 */
1374 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1375 if (ucTmp
== 0x01) {
1376 /* Not a picture, but an OLE object */
1379 DBG_DEC_C(ucTmp
!= 0, ucTmp
);
1381 case 0x680e: /* fcObj */
1382 ulTmp
= ulGetLong(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1385 case 0x6a03: /* fcPic */
1386 pPicture
->ulPictureOffset
= ulGetLong(
1387 iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1393 iInfoLen
= iGet8InfoLength(iFodo
+ iFodoOff
, aucGrpprl
);
1394 fail(iInfoLen
<= 0);
1395 iFodoOff
+= iInfoLen
;
1398 } /* end of bGet8PicInfo */
1401 * Build the lists with Character Information for Word 8/9/10/11 files
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
)
1409 font_block_type tFont
;
1410 picture_block_type tPicture
;
1413 ULONG ulFileOffset
, ulCharPos
, ulBeginCharInfo
;
1414 size_t tCharInfoLen
, tOffset
, tLen
;
1415 int iIndex
, iIndex2
, iRun
, iFodo
, iLen
;
1417 UCHAR aucFpage
[BIG_BLOCK_SIZE
];
1419 fail(pFile
== NULL
|| pPPS
== NULL
|| aucHeader
== NULL
);
1420 fail(aulBBD
== NULL
|| aulSBD
== NULL
);
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
);
1431 aucBuffer
= aucFillInfoBuffer(pFile
, &pPPS
->tTable
,
1432 aulBBD
, tBBDLen
, aulSBD
, tSBDLen
,
1433 ulBeginCharInfo
, tCharInfoLen
);
1434 if (aucBuffer
== NULL
) {
1437 NO_DBG_PRINT_BLOCK(aucBuffer
, tCharInfoLen
);
1439 tLen
= (tCharInfoLen
/ 4 - 1) / 2;
1440 aulCharPage
= xcalloc(tLen
, sizeof(ULONG
));
1441 for (iIndex
= 0, tOffset
= (tLen
+ 1) * 4;
1443 iIndex
++, tOffset
+= 4) {
1444 aulCharPage
[iIndex
] = ulGetLong(tOffset
, aucBuffer
);
1445 NO_DBG_DEC(aulCharPage
[iIndex
]);
1447 DBG_HEX(ulGetLong(0, aucBuffer
));
1448 aucBuffer
= xfree(aucBuffer
);
1449 NO_DBG_PRINT_BLOCK(aucHeader
, HEADER_SIZE
);
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
,
1456 aulCharPage
[iIndex
] * BIG_BLOCK_SIZE
,
1460 NO_DBG_PRINT_BLOCK(aucFpage
, BIG_BLOCK_SIZE
);
1461 iRun
= (int)ucGetByte(0x1ff, aucFpage
);
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
);
1469 iLen
= (int)ucGetByte(iFodo
, aucFpage
);
1471 usIstd
= usGetIstd(ulFileOffset
);
1472 vFillFontFromStylesheet(usIstd
, &tFont
);
1474 vGet8FontInfo(iFodo
, usIstd
,
1475 aucFpage
+ 1, iLen
- 1, &tFont
);
1477 tFont
.ulFileOffset
= ulFileOffset
;
1478 vAdd2FontInfoList(&tFont
);
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
);
1495 aulCharPage
= xfree(aulCharPage
);
1496 } /* end of vGet8ChrInfo */