3 * Copyright (C) 1998-2005 A.J. van Os; Released under GPL
6 * Read the property information from a MS Word 6 or 7 file
15 * iGet6InfoLength - the length of the information for Word 6/7 files
18 iGet6InfoLength(int iByteNbr
, const UCHAR
*aucGrpprl
)
22 switch (ucGetByte(iByteNbr
, aucGrpprl
)) {
23 case 2: case 16: case 17: case 18: case 19: case 21: case 22:
24 case 26: case 27: case 28: case 30: case 31: case 32: case 33:
25 case 34: case 35: case 36: case 38: case 39: case 40: case 41:
26 case 42: case 43: case 45: case 46: case 47: case 48: case 49:
27 case 69: case 72: case 80: case 93: case 96: case 97: case 99:
28 case 101: case 105: case 106: case 107: case 109: case 110: case 121:
29 case 122: case 123: case 124: case 140: case 141: case 144: case 145:
30 case 148: case 149: case 154: case 155: case 156: case 157: case 160:
31 case 161: case 164: case 165: case 166: case 167: case 168: case 169:
32 case 170: case 171: case 182: case 183: case 184: case 189: case 195:
35 case 3: case 12: case 15: case 81: case 103: case 108: case 188:
37 return 2 + (int)ucGetByte(iByteNbr
+ 1, aucGrpprl
);
38 case 20: case 70: case 74: case 192: case 194: case 196: case 200:
41 iTmp
= (int)ucGetByte(iByteNbr
+ 1, aucGrpprl
);
43 iDel
= (int)ucGetByte(iByteNbr
+ 2, aucGrpprl
);
44 iAdd
= (int)ucGetByte(
45 iByteNbr
+ 3 + iDel
* 4, aucGrpprl
);
46 iTmp
= 2 + iDel
* 4 + iAdd
* 3;
49 case 68: case 193: case 199:
51 case 73: case 95: case 136: case 137:
58 } /* end of iGet6InfoLength */
61 * Build the lists with Document Property Information for Word 6/7 files
64 vGet6DopInfo(FILE *pFile
, ULONG ulStartBlock
,
65 const ULONG
*aulBBD
, size_t tBBDLen
,
66 const UCHAR
*aucHeader
)
68 document_block_type tDocument
;
70 ULONG ulBeginDocpInfo
, ulTmp
;
74 ulBeginDocpInfo
= ulGetLong(0x150, aucHeader
); /* fcDop */
75 DBG_HEX(ulBeginDocpInfo
);
76 tDocpInfoLen
= (size_t)ulGetLong(0x154, aucHeader
); /* lcbDop */
77 DBG_DEC(tDocpInfoLen
);
78 if (tDocpInfoLen
< 28) {
79 DBG_MSG("No Document information");
83 aucBuffer
= xmalloc(tDocpInfoLen
);
84 if (!bReadBuffer(pFile
, ulStartBlock
,
85 aulBBD
, tBBDLen
, BIG_BLOCK_SIZE
,
86 aucBuffer
, ulBeginDocpInfo
, tDocpInfoLen
)) {
87 aucBuffer
= xfree(aucBuffer
);
91 usTmp
= usGetWord(0x00, aucBuffer
);
92 tDocument
.ucHdrFtrSpecification
= (UCHAR
)(usTmp
>> 8); /* grpfIhdt */
93 tDocument
.usDefaultTabWidth
= usGetWord(0x0a, aucBuffer
); /* dxaTab */
94 ulTmp
= ulGetLong(0x14, aucBuffer
); /* dttmCreated */
95 tDocument
.tCreateDate
= tConvertDTTM(ulTmp
);
96 ulTmp
= ulGetLong(0x18, aucBuffer
); /* dttmRevised */
97 tDocument
.tRevisedDate
= tConvertDTTM(ulTmp
);
98 vCreateDocumentInfoList(&tDocument
);
100 aucBuffer
= xfree(aucBuffer
);
101 } /* end of vGet6DopInfo */
104 * Fill the section information block with information
105 * from a Word 6/7 file.
108 vGet6SectionInfo(const UCHAR
*aucGrpprl
, size_t tBytes
,
109 section_block_type
*pSection
)
112 int iFodoOff
, iInfoLen
, iSize
, iTmp
;
116 fail(aucGrpprl
== NULL
|| pSection
== NULL
);
119 while (tBytes
>= (size_t)iFodoOff
+ 1) {
121 switch (ucGetByte(iFodoOff
, aucGrpprl
)) {
122 case 133: /* olstAnm */
123 iSize
= (int)ucGetByte(iFodoOff
+ 1, aucGrpprl
);
124 DBG_DEC_C(iSize
!= 212, iSize
);
125 for (uiIndex
= 0, iTmp
= iFodoOff
+ 2;
126 uiIndex
< 9 && iTmp
< iFodoOff
+ 2 + iSize
- 15;
127 uiIndex
++, iTmp
+= 16) {
128 pSection
->aucNFC
[uiIndex
] =
129 ucGetByte(iTmp
, aucGrpprl
);
130 NO_DBG_DEC(pSection
->aucNFC
[uiIndex
]);
131 ucTmp
= ucGetByte(iTmp
+ 3, aucGrpprl
);
133 if ((ucTmp
& BIT(2)) != 0) {
134 pSection
->usNeedPrevLvl
|=
135 (USHORT
)BIT(uiIndex
);
137 if ((ucTmp
& BIT(3)) != 0) {
138 pSection
->usHangingIndent
|=
139 (USHORT
)BIT(uiIndex
);
142 DBG_HEX(pSection
->usNeedPrevLvl
);
143 DBG_HEX(pSection
->usHangingIndent
);
146 ucTmp
= ucGetByte(iFodoOff
+ 1, aucGrpprl
);
148 pSection
->bNewPage
= ucTmp
!= 0 && ucTmp
!= 1;
150 case 144: /* ccolM1 */
151 usCcol
= 1 + usGetWord(iFodoOff
+ 1, aucGrpprl
);
154 case 153: /* grpfIhdt */
155 pSection
->ucHdrFtrSpecification
=
156 ucGetByte(iFodoOff
+ 1, aucGrpprl
);
162 iInfoLen
= iGet6InfoLength(iFodoOff
, aucGrpprl
);
165 iFodoOff
+= iInfoLen
;
167 } /* end of vGet6SectionInfo */
170 * Build the lists with Section Property Information for Word 6/7 files
173 vGet6SepInfo(FILE *pFile
, ULONG ulStartBlock
,
174 const ULONG
*aulBBD
, size_t tBBDLen
,
175 const UCHAR
*aucHeader
)
177 section_block_type tSection
;
178 ULONG
*aulSectPage
, *aulCharPos
;
179 UCHAR
*aucBuffer
, *aucFpage
;
180 ULONG ulBeginOfText
, ulTextOffset
, ulBeginSectInfo
;
181 size_t tSectInfoLen
, tIndex
, tOffset
, tLen
, tBytes
;
184 fail(pFile
== NULL
|| aucHeader
== NULL
);
185 fail(ulStartBlock
> MAX_BLOCKNUMBER
&& ulStartBlock
!= END_OF_CHAIN
);
186 fail(aulBBD
== NULL
);
188 ulBeginOfText
= ulGetLong(0x18, aucHeader
); /* fcMin */
189 NO_DBG_HEX(ulBeginOfText
);
190 ulBeginSectInfo
= ulGetLong(0x88, aucHeader
); /* fcPlcfsed */
191 DBG_HEX(ulBeginSectInfo
);
192 tSectInfoLen
= (size_t)ulGetLong(0x8c, aucHeader
); /* lcbPlcfsed */
193 DBG_DEC(tSectInfoLen
);
194 if (tSectInfoLen
< 4) {
195 DBG_DEC(tSectInfoLen
);
199 aucBuffer
= xmalloc(tSectInfoLen
);
200 if (!bReadBuffer(pFile
, ulStartBlock
,
201 aulBBD
, tBBDLen
, BIG_BLOCK_SIZE
,
202 aucBuffer
, ulBeginSectInfo
, tSectInfoLen
)) {
203 aucBuffer
= xfree(aucBuffer
);
206 NO_DBG_PRINT_BLOCK(aucBuffer
, tSectInfoLen
);
208 /* Read the Section Descriptors */
209 tLen
= (tSectInfoLen
- 4) / 16;
210 /* Save the section offsets */
211 aulCharPos
= xcalloc(tLen
, sizeof(ULONG
));
212 for (tIndex
= 0, tOffset
= 0; tIndex
< tLen
; tIndex
++, tOffset
+= 4) {
213 ulTextOffset
= ulGetLong(tOffset
, aucBuffer
);
214 NO_DBG_HEX(ulTextOffset
);
215 aulCharPos
[tIndex
] = ulBeginOfText
+ ulTextOffset
;
216 NO_DBG_HEX(aulCharPos
[tIndex
]);
218 /* Save the Sepx offsets */
219 aulSectPage
= xcalloc(tLen
, sizeof(ULONG
));
220 for (tIndex
= 0, tOffset
= (tLen
+ 1) * 4;
222 tIndex
++, tOffset
+= 12) {
223 aulSectPage
[tIndex
] = ulGetLong(tOffset
+ 2, aucBuffer
);
224 NO_DBG_HEX(aulSectPage
[tIndex
]); /* fcSepx */
226 aucBuffer
= xfree(aucBuffer
);
228 /* Read the Section Properties */
229 for (tIndex
= 0; tIndex
< tLen
; tIndex
++) {
230 if (aulSectPage
[tIndex
] == FC_INVALID
) {
231 vDefault2SectionInfoList(aulCharPos
[tIndex
]);
234 /* Get the number of bytes to read */
235 if (!bReadBuffer(pFile
, ulStartBlock
,
236 aulBBD
, tBBDLen
, BIG_BLOCK_SIZE
,
237 aucTmp
, aulSectPage
[tIndex
], 2)) {
240 tBytes
= 2 + (size_t)usGetWord(0, aucTmp
);
243 aucFpage
= xmalloc(tBytes
);
244 if (!bReadBuffer(pFile
, ulStartBlock
,
245 aulBBD
, tBBDLen
, BIG_BLOCK_SIZE
,
246 aucFpage
, aulSectPage
[tIndex
], tBytes
)) {
247 aucFpage
= xfree(aucFpage
);
250 NO_DBG_PRINT_BLOCK(aucFpage
, tBytes
);
251 /* Process the bytes */
252 vGetDefaultSection(&tSection
);
253 vGet6SectionInfo(aucFpage
+ 2, tBytes
- 2, &tSection
);
254 vAdd2SectionInfoList(&tSection
, aulCharPos
[tIndex
]);
255 aucFpage
= xfree(aucFpage
);
257 aulCharPos
= xfree(aulCharPos
);
258 aulSectPage
= xfree(aulSectPage
);
259 } /* end of vGet6SepInfo */
262 * Build the list with Header/Footer Information for Word 6/7 files
265 vGet6HdrFtrInfo(FILE *pFile
, ULONG ulStartBlock
,
266 const ULONG
*aulBBD
, size_t tBBDLen
,
267 const UCHAR
*aucHeader
)
271 ULONG ulHdrFtrOffset
, ulBeginHdrFtrInfo
;
272 size_t tHdrFtrInfoLen
, tIndex
, tOffset
, tLen
;
274 fail(pFile
== NULL
|| aucHeader
== NULL
);
275 fail(ulStartBlock
> MAX_BLOCKNUMBER
&& ulStartBlock
!= END_OF_CHAIN
);
276 fail(aulBBD
== NULL
);
278 ulBeginHdrFtrInfo
= ulGetLong(0xb0, aucHeader
); /* fcPlcfhdd */
279 NO_DBG_HEX(ulBeginHdrFtrInfo
);
280 tHdrFtrInfoLen
= (size_t)ulGetLong(0xb4, aucHeader
); /* lcbPlcfhdd */
281 NO_DBG_DEC(tHdrFtrInfoLen
);
282 if (tHdrFtrInfoLen
< 8) {
283 DBG_DEC_C(tHdrFtrInfoLen
!= 0, tHdrFtrInfoLen
);
287 aucBuffer
= xmalloc(tHdrFtrInfoLen
);
288 if (!bReadBuffer(pFile
, ulStartBlock
,
289 aulBBD
, tBBDLen
, BIG_BLOCK_SIZE
,
290 aucBuffer
, ulBeginHdrFtrInfo
, tHdrFtrInfoLen
)) {
291 aucBuffer
= xfree(aucBuffer
);
294 NO_DBG_PRINT_BLOCK(aucBuffer
, tHdrFtrInfoLen
);
296 tLen
= tHdrFtrInfoLen
/ 4 - 1;
297 /* Save the header/footer offsets */
298 aulCharPos
= xcalloc(tLen
, sizeof(ULONG
));
299 for (tIndex
= 0, tOffset
= 0;
301 tIndex
++, tOffset
+= 4) {
302 ulHdrFtrOffset
= ulGetLong(tOffset
, aucBuffer
);
303 NO_DBG_HEX(ulHdrFtrOffset
);
304 aulCharPos
[tIndex
] = ulHdrFtrOffset2CharPos(ulHdrFtrOffset
);
305 NO_DBG_HEX(aulCharPos
[tIndex
]);
307 vCreat6HdrFtrInfoList(aulCharPos
, tLen
);
308 aulCharPos
= xfree(aulCharPos
);
309 aucBuffer
= xfree(aucBuffer
);
310 } /* end of vGet6HdrFtrInfo */
313 * Translate the rowinfo to a member of the row_info enumeration
316 eGet6RowInfo(int iFodo
,
317 const UCHAR
*aucGrpprl
, int iBytes
, row_block_type
*pRow
)
319 int iFodoOff
, iInfoLen
;
320 int iIndex
, iSize
, iCol
;
321 int iPosCurr
, iPosPrev
;
323 BOOL bFound24_0
, bFound24_1
, bFound25_0
, bFound25_1
, bFound190
;
325 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pRow
== NULL
);
333 while (iBytes
>= iFodoOff
+ 1) {
335 switch (ucGetByte(iFodo
+ iFodoOff
, aucGrpprl
)) {
336 case 24: /* fInTable */
337 if (odd(ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
))) {
344 if (odd(ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
))) {
350 case 38: /* brcTop */
351 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
353 NO_DBG_DEC(usTmp
>> 3);
355 pRow
->ucBorderInfo
&= ~TABLE_BORDER_TOP
;
357 pRow
->ucBorderInfo
|= TABLE_BORDER_TOP
;
360 case 39: /* brcLeft */
361 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
363 NO_DBG_DEC(usTmp
>> 3);
365 pRow
->ucBorderInfo
&= ~TABLE_BORDER_LEFT
;
367 pRow
->ucBorderInfo
|= TABLE_BORDER_LEFT
;
370 case 40: /* brcBottom */
371 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
373 NO_DBG_DEC(usTmp
>> 3);
375 pRow
->ucBorderInfo
&= ~TABLE_BORDER_BOTTOM
;
377 pRow
->ucBorderInfo
|= TABLE_BORDER_BOTTOM
;
380 case 41: /* brcRight */
381 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
383 NO_DBG_DEC(usTmp
>> 3);
385 pRow
->ucBorderInfo
&= ~TABLE_BORDER_RIGHT
;
387 pRow
->ucBorderInfo
|= TABLE_BORDER_RIGHT
;
390 case 188: /* cDefTable10 */
391 DBG_MSG("188: sprmTDefTable10");
392 iSize
= (int)usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
395 case 190: /* cDefTable */
396 iSize
= (int)usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
397 if (iSize
< 6 || iBytes
< iFodoOff
+ 7) {
403 iCol
= (int)ucGetByte(iFodo
+ iFodoOff
+ 3, aucGrpprl
);
405 iBytes
< iFodoOff
+ 3 + (iCol
+ 1) * 2) {
411 if (iCol
>= (int)elementsof(pRow
->asColumnWidth
)) {
413 werr(1, "The number of columns is corrupt");
415 pRow
->ucNumberOfColumns
= (UCHAR
)iCol
;
416 iPosPrev
= (int)(short)usGetWord(
417 iFodo
+ iFodoOff
+ 4,
419 for (iIndex
= 0; iIndex
< iCol
; iIndex
++) {
420 iPosCurr
= (int)(short)usGetWord(
421 iFodo
+ iFodoOff
+ 6 + iIndex
* 2,
423 pRow
->asColumnWidth
[iIndex
] =
424 (short)(iPosCurr
- iPosPrev
);
434 iGet6InfoLength(iFodo
+ iFodoOff
, aucGrpprl
);
437 iFodoOff
+= iInfoLen
;
440 if (bFound25_1
&& bFound190
) {
441 return found_end_of_row
;
443 if (bFound25_0
&& !bFound190
) {
444 return found_not_end_of_row
;
450 return found_not_a_cell
;
452 return found_nothing
;
453 } /* end of eGet6RowInfo */
456 * Fill the style information block with information
457 * from a Word 6/7 file.
460 vGet6StyleInfo(int iFodo
,
461 const UCHAR
*aucGrpprl
, int iBytes
, style_block_type
*pStyle
)
463 int iFodoOff
, iInfoLen
;
464 int iTmp
, iDel
, iAdd
, iBefore
;
468 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pStyle
== NULL
);
470 NO_DBG_DEC(pStyle
->usIstd
);
473 while (iBytes
>= iFodoOff
+ 1) {
475 switch (ucGetByte(iFodo
+ iFodoOff
, aucGrpprl
)) {
477 sTmp
= (short)ucGetByte(
478 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
482 pStyle
->ucAlignment
= ucGetByte(
483 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
486 iTmp
= (int)ucGetByte(
487 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
488 DBG_DEC_C(iTmp
< 52, iTmp
);
490 pStyle
->ucNFC
= ucGetByte(
491 iFodo
+ iFodoOff
+ 2, aucGrpprl
);
493 if (pStyle
->ucNFC
!= LIST_BULLETS
&& iTmp
>= 2) {
494 iBefore
= (int)ucGetByte(
495 iFodo
+ iFodoOff
+ 3, aucGrpprl
);
500 pStyle
->usStartAt
= usGetWord(
501 iFodo
+ iFodoOff
+ 12, aucGrpprl
);
503 if (iTmp
>= iBefore
+ 21) {
504 pStyle
->usListChar
= (USHORT
)ucGetByte(
505 iFodo
+ iFodoOff
+ iBefore
+ 22,
507 NO_DBG_HEX(pStyle
->usListChar
);
510 case 13: /* nLvlAnm */
511 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
512 pStyle
->ucNumLevel
= ucTmp
;
514 eGetNumType(ucTmp
) == level_type_pause
;
516 case 15: /* ChgTabsPapx */
517 case 23: /* ChgTabs */
518 iTmp
= (int)ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
524 iDel
= (int)ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
525 if (iTmp
< 2 + 2 * iDel
) {
530 iAdd
= (int)ucGetByte(
531 iFodo
+ iFodoOff
+ 3 + 2 * iDel
, aucGrpprl
);
532 if (iTmp
< 2 + 2 * iDel
+ 2 * iAdd
) {
538 case 16: /* dxaRight */
539 pStyle
->sRightIndent
= (short)usGetWord(
540 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
541 NO_DBG_DEC(pStyle
->sRightIndent
);
543 case 17: /* dxaLeft */
544 pStyle
->sLeftIndent
= (short)usGetWord(
545 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
546 NO_DBG_DEC(pStyle
->sLeftIndent
);
548 case 18: /* Nest dxaLeft */
549 sTmp
= (short)usGetWord(
550 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
551 pStyle
->sLeftIndent
+= sTmp
;
552 if (pStyle
->sLeftIndent
< 0) {
553 pStyle
->sLeftIndent
= 0;
556 NO_DBG_DEC(pStyle
->sLeftIndent
);
558 case 19: /* dxaLeft1 */
559 pStyle
->sLeftIndent1
= (short)usGetWord(
560 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
561 NO_DBG_DEC(pStyle
->sLeftIndent1
);
563 case 21: /* dyaBefore */
564 pStyle
->usBeforeIndent
= usGetWord(
565 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
566 NO_DBG_DEC(pStyle
->usBeforeIndent
);
568 case 22: /* dyaAfter */
569 pStyle
->usAfterIndent
= usGetWord(
570 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
571 NO_DBG_DEC(pStyle
->usAfterIndent
);
578 iGet6InfoLength(iFodo
+ iFodoOff
, aucGrpprl
);
581 iFodoOff
+= iInfoLen
;
583 } /* end of vGet6StyleInfo */
586 * Build the lists with Paragraph Information for Word 6/7 files
589 vGet6PapInfo(FILE *pFile
, ULONG ulStartBlock
,
590 const ULONG
*aulBBD
, size_t tBBDLen
,
591 const UCHAR
*aucHeader
)
594 style_block_type tStyle
;
597 ULONG ulCharPos
, ulCharPosFirst
, ulCharPosLast
;
598 ULONG ulBeginParfInfo
;
599 size_t tParfInfoLen
, tParfPageNum
, tOffset
, tSize
, tLenOld
, tLen
;
600 size_t tIndex
, tIndex2
, tRun
;
602 row_info_enum eRowInfo
;
603 USHORT usParfFirstPage
, usCount
, usIstd
;
604 UCHAR aucFpage
[BIG_BLOCK_SIZE
];
606 fail(pFile
== NULL
|| aucHeader
== NULL
);
607 fail(ulStartBlock
> MAX_BLOCKNUMBER
&& ulStartBlock
!= END_OF_CHAIN
);
608 fail(aulBBD
== NULL
);
610 ulBeginParfInfo
= ulGetLong(0xc0, aucHeader
); /* fcPlcfbtePapx */
611 NO_DBG_HEX(ulBeginParfInfo
);
612 tParfInfoLen
= (size_t)ulGetLong(0xc4, aucHeader
); /* lcbPlcfbtePapx */
613 NO_DBG_DEC(tParfInfoLen
);
614 if (tParfInfoLen
< 4) {
615 DBG_DEC(tParfInfoLen
);
619 aucBuffer
= xmalloc(tParfInfoLen
);
620 if (!bReadBuffer(pFile
, ulStartBlock
,
621 aulBBD
, tBBDLen
, BIG_BLOCK_SIZE
,
622 aucBuffer
, ulBeginParfInfo
, tParfInfoLen
)) {
623 aucBuffer
= xfree(aucBuffer
);
626 NO_DBG_PRINT_BLOCK(aucBuffer
, tParfInfoLen
);
628 tLen
= (tParfInfoLen
- 4) / 6;
629 ausParfPage
= xcalloc(tLen
, sizeof(USHORT
));
630 for (tIndex
= 0, tOffset
= (tLen
+ 1) * 4;
632 tIndex
++, tOffset
+= 2) {
633 ausParfPage
[tIndex
] = usGetWord(tOffset
, aucBuffer
);
634 NO_DBG_DEC(ausParfPage
[tIndex
]);
636 DBG_HEX(ulGetLong(0, aucBuffer
));
637 aucBuffer
= xfree(aucBuffer
);
638 tParfPageNum
= (size_t)usGetWord(0x190, aucHeader
); /* cpnBtePap */
639 DBG_DEC(tParfPageNum
);
640 if (tLen
< tParfPageNum
) {
641 /* Replace ParfPage by a longer version */
643 usParfFirstPage
= usGetWord(0x18c, aucHeader
); /* pnPapFirst */
644 DBG_DEC(usParfFirstPage
);
645 tLen
+= tParfPageNum
- 1;
646 tSize
= tLen
* sizeof(USHORT
);
647 ausParfPage
= xrealloc(ausParfPage
, tSize
);
649 usCount
= usParfFirstPage
+ 1;
650 for (tIndex
= tLenOld
; tIndex
< tLen
; tIndex
++) {
651 ausParfPage
[tIndex
] = usCount
;
652 NO_DBG_DEC(ausParfPage
[tIndex
]);
657 (void)memset(&tRow
, 0, sizeof(tRow
));
658 ulCharPosFirst
= CP_INVALID
;
659 for (tIndex
= 0; tIndex
< tLen
; tIndex
++) {
660 if (!bReadBuffer(pFile
, ulStartBlock
,
661 aulBBD
, tBBDLen
, BIG_BLOCK_SIZE
,
663 (ULONG
)ausParfPage
[tIndex
] * BIG_BLOCK_SIZE
,
667 tRun
= (size_t)ucGetByte(0x1ff, aucFpage
);
669 for (tIndex2
= 0; tIndex2
< tRun
; tIndex2
++) {
670 NO_DBG_HEX(ulGetLong(tIndex2
* 4, aucFpage
));
671 iFodo
= 2 * (int)ucGetByte(
672 (tRun
+ 1) * 4 + tIndex2
* 7, aucFpage
);
677 iLen
= 2 * (int)ucGetByte(iFodo
, aucFpage
);
679 usIstd
= (USHORT
)ucGetByte(iFodo
+ 1, aucFpage
);
680 vFillStyleFromStylesheet(usIstd
, &tStyle
);
681 vGet6StyleInfo(iFodo
, aucFpage
+ 3, iLen
- 3, &tStyle
);
682 ulCharPos
= ulGetLong(tIndex2
* 4, aucFpage
);
683 NO_DBG_HEX(ulCharPos
);
684 tStyle
.ulFileOffset
= ulCharPos2FileOffsetX(
685 ulCharPos
, &tStyle
.eListID
);
686 vAdd2StyleInfoList(&tStyle
);
688 eRowInfo
= eGet6RowInfo(iFodo
,
689 aucFpage
+ 3, iLen
- 3, &tRow
);
692 if (ulCharPosFirst
!= CP_INVALID
) {
695 ulCharPosFirst
= ulGetLong(
696 tIndex2
* 4, aucFpage
);
697 NO_DBG_HEX(ulCharPosFirst
);
698 tRow
.ulCharPosStart
= ulCharPosFirst
;
699 tRow
.ulFileOffsetStart
=
700 ulCharPos2FileOffset(ulCharPosFirst
);
701 DBG_HEX_C(tRow
.ulFileOffsetStart
== FC_INVALID
,
704 case found_end_of_row
:
705 ulCharPosLast
= ulGetLong(
706 tIndex2
* 4, aucFpage
);
707 NO_DBG_HEX(ulCharPosLast
);
708 tRow
.ulCharPosEnd
= ulCharPosLast
;
709 tRow
.ulFileOffsetEnd
=
710 ulCharPos2FileOffset(ulCharPosLast
);
711 DBG_HEX_C(tRow
.ulFileOffsetEnd
== FC_INVALID
,
713 vAdd2RowInfoList(&tRow
);
714 (void)memset(&tRow
, 0, sizeof(tRow
));
715 ulCharPosFirst
= CP_INVALID
;
725 ausParfPage
= xfree(ausParfPage
);
726 } /* end of vGet6PapInfo */
729 * Fill the font information block with information
730 * from a Word 6/7 file.
731 * Returns TRUE when successful, otherwise FALSE
734 vGet6FontInfo(int iFodo
, USHORT usIstd
,
735 const UCHAR
*aucGrpprl
, int iBytes
, font_block_type
*pFont
)
738 int iFodoOff
, iInfoLen
;
742 TRACE_MSG("vGet6FontInfo");
744 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pFont
== NULL
);
747 while (iBytes
>= iFodoOff
+ 1) {
748 switch (ucGetByte(iFodo
+ iFodoOff
, aucGrpprl
)) {
749 case 65: /* fRMarkDel */
750 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
752 pFont
->usFontStyle
&= ~FONT_MARKDEL
;
754 pFont
->usFontStyle
|= FONT_MARKDEL
;
758 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
761 case 82: /* cDefault */
762 pFont
->usFontStyle
&= FONT_HIDDEN
;
763 pFont
->ucFontColor
= FONT_COLOR_DEFAULT
;
765 case 83: /* cPlain */
766 DBG_MSG("83: cPlain");
767 vFillFontFromStylesheet(usIstd
, pFont
);
770 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
773 pFont
->usFontStyle
&= ~FONT_BOLD
;
776 pFont
->usFontStyle
|= FONT_BOLD
;
778 case 128: /* Unchanged */
780 case 129: /* Negation */
781 pFont
->usFontStyle
^= FONT_BOLD
;
789 case 86: /* fItalic */
790 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
793 pFont
->usFontStyle
&= ~FONT_ITALIC
;
796 pFont
->usFontStyle
|= FONT_ITALIC
;
798 case 128: /* Unchanged */
800 case 129: /* Negation */
801 pFont
->usFontStyle
^= FONT_ITALIC
;
809 case 87: /* fStrike */
810 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
813 pFont
->usFontStyle
&= ~FONT_STRIKE
;
816 pFont
->usFontStyle
|= FONT_STRIKE
;
818 case 128: /* Unchanged */
820 case 129: /* Negation */
821 pFont
->usFontStyle
^= FONT_STRIKE
;
829 case 90: /* fSmallCaps */
830 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
833 pFont
->usFontStyle
&= ~FONT_SMALL_CAPITALS
;
836 pFont
->usFontStyle
|= FONT_SMALL_CAPITALS
;
838 case 128: /* Unchanged */
840 case 129: /* Negation */
841 pFont
->usFontStyle
^= FONT_SMALL_CAPITALS
;
850 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
853 pFont
->usFontStyle
&= ~FONT_CAPITALS
;
856 pFont
->usFontStyle
|= FONT_CAPITALS
;
858 case 128: /* Unchanged */
860 case 129: /* Negation */
861 pFont
->usFontStyle
^= FONT_CAPITALS
;
869 case 92: /* fVanish */
870 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
873 pFont
->usFontStyle
&= ~FONT_HIDDEN
;
876 pFont
->usFontStyle
|= FONT_HIDDEN
;
878 case 128: /* Unchanged */
880 case 129: /* Negation */
881 pFont
->usFontStyle
^= FONT_HIDDEN
;
890 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
891 if (usTmp
<= (USHORT
)UCHAR_MAX
) {
892 pFont
->ucFontNumber
= (UCHAR
)usTmp
;
896 pFont
->ucFontNumber
= 0;
900 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
901 if (ucTmp
== 0 || ucTmp
== 5) {
902 pFont
->usFontStyle
&= ~FONT_UNDERLINE
;
904 NO_DBG_MSG("Underline text");
905 pFont
->usFontStyle
|= FONT_UNDERLINE
;
907 DBG_MSG("Bold text");
908 pFont
->usFontStyle
|= FONT_BOLD
;
912 case 95: /* cHps, cHpsPos */
913 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
916 pFont
->usFontSize
= (USHORT
)ucTmp
;
918 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
923 ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
927 usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
929 case 100: /* cHpsInc */
930 DBG_MSG("100: sprmCHpsInc");
931 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
934 case 103: /* cMajority */
935 DBG_MSG("103: sprmCMajority");
938 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
941 pFont
->usFontStyle
|= FONT_SUPERSCRIPT
;
942 NO_DBG_MSG("Superscript");
943 } else if (ucTmp
== 2) {
944 pFont
->usFontStyle
|= FONT_SUBSCRIPT
;
945 NO_DBG_MSG("Subscript");
948 case 106: /* cHpsInc1 */
949 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
950 lTmp
= (long)pFont
->usFontSize
+ (long)usTmp
;
952 pFont
->usFontSize
= 8;
953 } else if (lTmp
> 32766) {
954 pFont
->usFontSize
= 32766;
956 pFont
->usFontSize
= (USHORT
)lTmp
;
959 case 108: /* cMajority50 */
960 DBG_MSG("108: sprmCMajority50");
962 case 109: /* cHpsMul */
963 DBG_MSG("109: sprmCHpsMul");
964 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
970 iInfoLen
= iGet6InfoLength(iFodo
+ iFodoOff
, aucGrpprl
);
972 iFodoOff
+= iInfoLen
;
974 } /* end of vGet6FontInfo */
977 * Fill the picture information block with information
978 * from a Word 6/7 file.
979 * Returns TRUE when successful, otherwise FALSE
982 bGet6PicInfo(int iFodo
,
983 const UCHAR
*aucGrpprl
, int iBytes
, picture_block_type
*pPicture
)
985 int iFodoOff
, iInfoLen
;
989 TRACE_MSG("vGet6PicInfo");
991 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pPicture
== NULL
);
995 while (iBytes
>= iFodoOff
+ 1) {
996 switch (ucGetByte(iFodo
+ iFodoOff
, aucGrpprl
)) {
998 pPicture
->ulPictureOffset
= ulGetLong(
999 iFodo
+ iFodoOff
+ 2, aucGrpprl
);
1003 case 71: /* fData */
1004 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
1005 if (ucTmp
== 0x01) {
1006 /* Not a picture, but a form field */
1009 DBG_DEC_C(ucTmp
!= 0, ucTmp
);
1012 case 75: /* fOle2 */
1013 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
1014 if (ucTmp
== 0x01) {
1015 /* Not a picture, but an OLE object */
1018 DBG_DEC_C(ucTmp
!= 0, ucTmp
);
1023 iInfoLen
= iGet6InfoLength(iFodo
+ iFodoOff
, aucGrpprl
);
1024 fail(iInfoLen
<= 0);
1025 iFodoOff
+= iInfoLen
;
1028 } /* end of bGet6PicInfo */
1031 * Build the lists with Character Information for Word 6/7 files
1034 vGet6ChrInfo(FILE *pFile
, ULONG ulStartBlock
,
1035 const ULONG
*aulBBD
, size_t tBBDLen
, const UCHAR
*aucHeader
)
1037 font_block_type tFont
;
1038 picture_block_type tPicture
;
1039 USHORT
*ausCharPage
;
1041 ULONG ulFileOffset
, ulCharPos
, ulBeginCharInfo
;
1042 size_t tCharInfoLen
, tOffset
, tSize
, tLenOld
, tLen
, tCharPageNum
;
1043 size_t tIndex
, tIndex2
, tRun
;
1045 USHORT usCharFirstPage
, usCount
, usIstd
;
1046 UCHAR aucFpage
[BIG_BLOCK_SIZE
];
1048 fail(pFile
== NULL
|| aucHeader
== NULL
);
1049 fail(ulStartBlock
> MAX_BLOCKNUMBER
&& ulStartBlock
!= END_OF_CHAIN
);
1050 fail(aulBBD
== NULL
);
1052 ulBeginCharInfo
= ulGetLong(0xb8, aucHeader
); /* fcPlcfbteChpx */
1053 NO_DBG_HEX(lBeginCharInfo
);
1054 tCharInfoLen
= (size_t)ulGetLong(0xbc, aucHeader
); /* lcbPlcfbteChpx */
1055 NO_DBG_DEC(tCharInfoLen
);
1056 if (tCharInfoLen
< 4) {
1057 DBG_DEC(tCharInfoLen
);
1061 aucBuffer
= xmalloc(tCharInfoLen
);
1062 if (!bReadBuffer(pFile
, ulStartBlock
,
1063 aulBBD
, tBBDLen
, BIG_BLOCK_SIZE
,
1064 aucBuffer
, ulBeginCharInfo
, tCharInfoLen
)) {
1065 aucBuffer
= xfree(aucBuffer
);
1069 tLen
= (tCharInfoLen
- 4) / 6;
1070 ausCharPage
= xcalloc(tLen
, sizeof(USHORT
));
1071 for (tIndex
= 0, tOffset
= (tLen
+ 1) * 4;
1073 tIndex
++, tOffset
+= 2) {
1074 ausCharPage
[tIndex
] = usGetWord(tOffset
, aucBuffer
);
1075 NO_DBG_DEC(ausCharPage
[tIndex
]);
1077 DBG_HEX(ulGetLong(0, aucBuffer
));
1078 aucBuffer
= xfree(aucBuffer
);
1079 tCharPageNum
= (size_t)usGetWord(0x18e, aucHeader
); /* cpnBteChp */
1080 DBG_DEC(tCharPageNum
);
1081 if (tLen
< tCharPageNum
) {
1082 /* Replace CharPage by a longer version */
1084 usCharFirstPage
= usGetWord(0x18a, aucHeader
); /* pnChrFirst */
1085 DBG_DEC(usCharFirstPage
);
1086 tLen
+= tCharPageNum
- 1;
1087 tSize
= tLen
* sizeof(USHORT
);
1088 ausCharPage
= xrealloc(ausCharPage
, tSize
);
1089 /* Add new values */
1090 usCount
= usCharFirstPage
+ 1;
1091 for (tIndex
= tLenOld
; tIndex
< tLen
; tIndex
++) {
1092 ausCharPage
[tIndex
] = usCount
;
1093 NO_DBG_DEC(ausCharPage
[tIndex
]);
1098 for (tIndex
= 0; tIndex
< tLen
; tIndex
++) {
1099 if (!bReadBuffer(pFile
, ulStartBlock
,
1100 aulBBD
, tBBDLen
, BIG_BLOCK_SIZE
,
1102 (ULONG
)ausCharPage
[tIndex
] * BIG_BLOCK_SIZE
,
1106 tRun
= (size_t)ucGetByte(0x1ff, aucFpage
);
1108 for (tIndex2
= 0; tIndex2
< tRun
; tIndex2
++) {
1109 ulCharPos
= ulGetLong(tIndex2
* 4, aucFpage
);
1110 ulFileOffset
= ulCharPos2FileOffset(ulCharPos
);
1111 iFodo
= 2 * (int)ucGetByte(
1112 (tRun
+ 1) * 4 + tIndex2
, aucFpage
);
1114 iLen
= (int)ucGetByte(iFodo
, aucFpage
);
1116 usIstd
= usGetIstd(ulFileOffset
);
1117 vFillFontFromStylesheet(usIstd
, &tFont
);
1119 vGet6FontInfo(iFodo
, usIstd
,
1120 aucFpage
+ 1, iLen
- 1, &tFont
);
1122 tFont
.ulFileOffset
= ulFileOffset
;
1123 vAdd2FontInfoList(&tFont
);
1129 (void)memset(&tPicture
, 0, sizeof(tPicture
));
1130 if (bGet6PicInfo(iFodo
, aucFpage
+ 1,
1131 iLen
- 1, &tPicture
)) {
1132 tPicture
.ulFileOffset
= ulFileOffset
;
1133 tPicture
.ulFileOffsetPicture
=
1134 ulDataPos2FileOffset(
1135 tPicture
.ulPictureOffset
);
1136 vAdd2PictInfoList(&tPicture
);
1140 ausCharPage
= xfree(ausCharPage
);
1141 } /* end of vGet6ChrInfo */