3 * Copyright (C) 2002-2005 A.J. van Os; Released under GPL
6 * Read the property information from a WinWord 1 or 2 file
13 #define MAX_FILESIZE 0x2000000UL /* 32 Mb */
16 * iGet2InfoLength - the length of the information for WinWord 1/2 files
19 iGet2InfoLength(int iByteNbr
, const UCHAR
*aucGrpprl
)
23 switch (ucGetByte(iByteNbr
, aucGrpprl
)) {
24 case 3: case 15: case 78: case 152: case 154: case 155:
25 return 2 + (int)ucGetByte(iByteNbr
+ 1, aucGrpprl
);
26 case 16: case 17: case 18: case 19: case 21: case 22: case 26:
27 case 27: case 28: case 30: case 31: case 32: case 33: case 34:
28 case 35: case 36: case 38: case 39: case 40: case 41: case 42:
29 case 43: case 45: case 46: case 47: case 48: case 49: case 68:
30 case 71: case 72: case 82: case 83: case 96: case 97: case 98:
31 case 99: case 115: case 116: case 119: case 120: case 123: case 124:
32 case 129: case 130: case 131: case 132: case 135: case 136: case 139:
33 case 140: case 141: case 142: case 143: case 144: case 145: case 146:
34 case 147: case 148: case 153: case 159: case 161: case 162:
37 iTmp
= (int)ucGetByte(iByteNbr
+ 1, aucGrpprl
);
39 iDel
= (int)ucGetByte(iByteNbr
+ 2, aucGrpprl
);
40 iAdd
= (int)ucGetByte(
41 iByteNbr
+ 3 + iDel
* 4, aucGrpprl
);
42 iTmp
= 2 + iDel
* 4 + iAdd
* 3;
51 case 158: case 160: case 164:
56 } /* end of iGet2InfoLength */
59 * Build the lists with Document Property Information for WinWord 1/2 files
62 vGet2DopInfo(FILE *pFile
, const UCHAR
*aucHeader
)
64 document_block_type tDocument
;
66 ULONG ulBeginDocpInfo
, ulTmp
;
70 ulBeginDocpInfo
= ulGetLong(0x112, aucHeader
); /* fcDop */
71 DBG_HEX(ulBeginDocpInfo
);
72 tDocpInfoLen
= (size_t)usGetWord(0x116, aucHeader
); /* cbDop */
73 DBG_DEC(tDocpInfoLen
);
74 if (tDocpInfoLen
< 28) {
75 DBG_MSG("No Document information");
79 aucBuffer
= xmalloc(tDocpInfoLen
);
80 if (!bReadBytes(aucBuffer
, tDocpInfoLen
, ulBeginDocpInfo
, pFile
)) {
81 aucBuffer
= xfree(aucBuffer
);
85 usTmp
= usGetWord(0x00, aucBuffer
);
86 tDocument
.ucHdrFtrSpecification
= (UCHAR
)(usTmp
>> 8); /* grpfIhdt */
87 tDocument
.usDefaultTabWidth
= usGetWord(0x0a, aucBuffer
); /* dxaTab */
88 ulTmp
= ulGetLong(0x14, aucBuffer
); /* dttmCreated */
89 tDocument
.tCreateDate
= tConvertDTTM(ulTmp
);
90 ulTmp
= ulGetLong(0x18, aucBuffer
); /* dttmRevised */
91 tDocument
.tRevisedDate
= tConvertDTTM(ulTmp
);
92 vCreateDocumentInfoList(&tDocument
);
94 aucBuffer
= xfree(aucBuffer
);
95 } /* end of vGet2DopInfo */
98 * Fill the section information block with information
99 * from a WinWord 1/2 file.
102 vGet2SectionInfo(const UCHAR
*aucGrpprl
, size_t tBytes
,
103 section_block_type
*pSection
)
105 int iFodoOff
, iInfoLen
;
109 fail(aucGrpprl
== NULL
|| pSection
== NULL
);
112 while (tBytes
>= (size_t)iFodoOff
+ 1) {
113 switch (ucGetByte(iFodoOff
, aucGrpprl
)) {
115 ucTmp
= ucGetByte(iFodoOff
+ 1, aucGrpprl
);
117 pSection
->bNewPage
= ucTmp
!= 0 && ucTmp
!= 1;
119 case 119: /* ccolM1 */
120 usCcol
= 1 + usGetWord(iFodoOff
+ 1, aucGrpprl
);
123 case 128: /* grpfIhdt */
124 pSection
->ucHdrFtrSpecification
=
125 ucGetByte(iFodoOff
+ 1, aucGrpprl
);
130 iInfoLen
= iGet2InfoLength(iFodoOff
, aucGrpprl
);
132 iFodoOff
+= iInfoLen
;
134 } /* end of vGet2SectionInfo */
137 * Build the lists with Section Property Information for WinWord 1/2 files
140 vGet2SepInfo(FILE *pFile
, const UCHAR
*aucHeader
)
142 section_block_type tSection
;
143 ULONG
*aulSectPage
, *aulCharPos
;
144 UCHAR
*aucBuffer
, *aucFpage
;
145 ULONG ulBeginOfText
, ulTextOffset
, ulBeginSectInfo
;
146 size_t tSectInfoLen
, tIndex
, tOffset
, tLen
, tBytes
;
149 fail(pFile
== NULL
|| aucHeader
== NULL
);
151 ulBeginOfText
= ulGetLong(0x18, aucHeader
); /* fcMin */
152 NO_DBG_HEX(ulBeginOfText
);
153 ulBeginSectInfo
= ulGetLong(0x7c, aucHeader
); /* fcPlcfsed */
154 DBG_HEX(ulBeginSectInfo
);
155 tSectInfoLen
= (size_t)usGetWord(0x80, aucHeader
); /* cbPlcfsed */
156 DBG_DEC(tSectInfoLen
);
157 if (tSectInfoLen
< 4) {
158 DBG_DEC(tSectInfoLen
);
162 aucBuffer
= xmalloc(tSectInfoLen
);
163 if (!bReadBytes(aucBuffer
, tSectInfoLen
, ulBeginSectInfo
, pFile
)) {
164 aucBuffer
= xfree(aucBuffer
);
167 NO_DBG_PRINT_BLOCK(aucBuffer
, tSectInfoLen
);
169 /* Read the Section Descriptors */
170 tLen
= (tSectInfoLen
- 4) / 10;
171 /* Save the section offsets */
172 aulCharPos
= xcalloc(tLen
, sizeof(ULONG
));
173 for (tIndex
= 0, tOffset
= 0;
175 tIndex
++, tOffset
+= 4) {
176 ulTextOffset
= ulGetLong(tOffset
, aucBuffer
);
177 NO_DBG_HEX(ulTextOffset
);
178 aulCharPos
[tIndex
] = ulBeginOfText
+ ulTextOffset
;
179 NO_DBG_HEX(aulCharPos
[tIndex
]);
181 /* Save the Sepx offsets */
182 aulSectPage
= xcalloc(tLen
, sizeof(ULONG
));
183 for (tIndex
= 0, tOffset
= (tLen
+ 1) * 4;
185 tIndex
++, tOffset
+= 6) {
186 aulSectPage
[tIndex
] = ulGetLong(tOffset
+ 2, aucBuffer
);
187 NO_DBG_HEX(aulSectPage
[tIndex
]); /* fcSepx */
189 aucBuffer
= xfree(aucBuffer
);
191 /* Read the Section Properties */
192 for (tIndex
= 0; tIndex
< tLen
; tIndex
++) {
193 if (aulSectPage
[tIndex
] == FC_INVALID
) {
194 vDefault2SectionInfoList(aulCharPos
[tIndex
]);
197 /* Get the number of bytes to read */
198 if (!bReadBytes(aucTmp
, 1, aulSectPage
[tIndex
], pFile
)) {
201 tBytes
= 1 + (size_t)ucGetByte(0, aucTmp
);
204 aucFpage
= xmalloc(tBytes
);
205 if (!bReadBytes(aucFpage
, tBytes
, aulSectPage
[tIndex
], pFile
)) {
206 aucFpage
= xfree(aucFpage
);
209 NO_DBG_PRINT_BLOCK(aucFpage
, tBytes
);
210 /* Process the bytes */
211 vGetDefaultSection(&tSection
);
212 vGet2SectionInfo(aucFpage
+ 1, tBytes
- 1, &tSection
);
213 vAdd2SectionInfoList(&tSection
, aulCharPos
[tIndex
]);
214 aucFpage
= xfree(aucFpage
);
216 aulCharPos
= xfree(aulCharPos
);
217 aulSectPage
= xfree(aulSectPage
);
218 } /* end of vGet2SepInfo */
221 * Build the list with Header/Footer Information for WinWord 1/2 files
224 vGet2HdrFtrInfo(FILE *pFile
, const UCHAR
*aucHeader
)
228 ULONG ulHdrFtrOffset
, ulBeginHdrFtrInfo
;
229 size_t tHdrFtrInfoLen
, tIndex
, tOffset
, tLen
;
231 fail(pFile
== NULL
|| aucHeader
== NULL
);
233 ulBeginHdrFtrInfo
= ulGetLong(0x9a, aucHeader
); /* fcPlcfhdd */
234 NO_DBG_HEX(ulBeginHdrFtrInfo
);
235 tHdrFtrInfoLen
= (size_t)usGetWord(0x9e, aucHeader
); /* cbPlcfhdd */
236 NO_DBG_DEC(tHdrFtrInfoLen
);
237 if (tHdrFtrInfoLen
< 8) {
238 DBG_DEC_C(tHdrFtrInfoLen
!= 0, tHdrFtrInfoLen
);
242 aucBuffer
= xmalloc(tHdrFtrInfoLen
);
243 if (!bReadBytes(aucBuffer
, tHdrFtrInfoLen
, ulBeginHdrFtrInfo
, pFile
)) {
244 aucBuffer
= xfree(aucBuffer
);
247 NO_DBG_PRINT_BLOCK(aucBuffer
, tHdrFtrInfoLen
);
249 tLen
= tHdrFtrInfoLen
/ 4 - 1;
250 /* Save the header/footer offsets */
251 aulCharPos
= xcalloc(tLen
, sizeof(ULONG
));
252 for (tIndex
= 0, tOffset
= 0;
254 tIndex
++, tOffset
+= 4) {
255 ulHdrFtrOffset
= ulGetLong(tOffset
, aucBuffer
);
256 NO_DBG_HEX(ulHdrFtrOffset
);
257 aulCharPos
[tIndex
] = ulHdrFtrOffset2CharPos(ulHdrFtrOffset
);
258 NO_DBG_HEX(aulCharPos
[tIndex
]);
260 vCreat2HdrFtrInfoList(aulCharPos
, tLen
);
261 aulCharPos
= xfree(aulCharPos
);
262 aucBuffer
= xfree(aucBuffer
);
263 } /* end of vGet2HdrFtrInfo */
266 * Translate the rowinfo to a member of the row_info enumeration
269 eGet2RowInfo(int iFodo
,
270 const UCHAR
*aucGrpprl
, int iBytes
, row_block_type
*pRow
)
272 int iFodoOff
, iInfoLen
;
273 int iIndex
, iSize
, iCol
;
274 int iPosCurr
, iPosPrev
;
276 BOOL bFound24_0
, bFound24_1
, bFound25_0
, bFound25_1
, bFound154
;
278 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pRow
== NULL
);
286 while (iBytes
>= iFodoOff
+ 1) {
288 switch (ucGetByte(iFodo
+ iFodoOff
, aucGrpprl
)) {
289 case 24: /* fIntable */
290 if (odd(ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
))) {
297 if (odd(ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
))) {
303 case 30: /* brcTop10 */
304 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
306 NO_DBG_DEC(usTmp
>> 6);
308 pRow
->ucBorderInfo
&= ~TABLE_BORDER_TOP
;
310 pRow
->ucBorderInfo
|= TABLE_BORDER_TOP
;
313 case 31: /* brcLeft10 */
314 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
316 NO_DBG_DEC(usTmp
>> 6);
318 pRow
->ucBorderInfo
&= ~TABLE_BORDER_LEFT
;
320 pRow
->ucBorderInfo
|= TABLE_BORDER_LEFT
;
323 case 32: /* brcBottom10 */
324 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
326 NO_DBG_DEC(usTmp
>> 6);
328 pRow
->ucBorderInfo
&= ~TABLE_BORDER_BOTTOM
;
330 pRow
->ucBorderInfo
|= TABLE_BORDER_BOTTOM
;
333 case 33: /* brcRight10 */
334 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
336 NO_DBG_DEC(usTmp
>> 6);
338 pRow
->ucBorderInfo
&= ~TABLE_BORDER_RIGHT
;
340 pRow
->ucBorderInfo
|= TABLE_BORDER_RIGHT
;
343 case 38: /* brcTop */
344 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
346 NO_DBG_DEC(usTmp
>> 3);
348 pRow
->ucBorderInfo
&= ~TABLE_BORDER_TOP
;
350 pRow
->ucBorderInfo
|= TABLE_BORDER_TOP
;
353 case 39: /* brcLeft */
354 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
356 NO_DBG_DEC(usTmp
>> 3);
358 pRow
->ucBorderInfo
&= ~TABLE_BORDER_LEFT
;
360 pRow
->ucBorderInfo
|= TABLE_BORDER_LEFT
;
363 case 40: /* brcBottom */
364 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
366 NO_DBG_DEC(usTmp
>> 3);
368 pRow
->ucBorderInfo
&= ~TABLE_BORDER_BOTTOM
;
370 pRow
->ucBorderInfo
|= TABLE_BORDER_BOTTOM
;
373 case 41: /* brcRight */
374 usTmp
= usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
376 NO_DBG_DEC(usTmp
>> 3);
378 pRow
->ucBorderInfo
&= ~TABLE_BORDER_RIGHT
;
380 pRow
->ucBorderInfo
|= TABLE_BORDER_RIGHT
;
383 case 152: /* cDefTable10 */
384 case 154: /* cDefTable */
385 iSize
= (int)usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
386 if (iSize
< 6 || iBytes
< iFodoOff
+ 7) {
393 iCol
= (int)ucGetByte(iFodo
+ iFodoOff
+ 3, aucGrpprl
);
395 iBytes
< iFodoOff
+ 3 + (iCol
+ 1) * 2) {
399 DBG_DEC(ucGetByte(iFodo
+ iFodoOff
, aucGrpprl
));
403 if (iCol
>= (int)elementsof(pRow
->asColumnWidth
)) {
405 werr(1, "The number of columns is corrupt");
407 pRow
->ucNumberOfColumns
= (UCHAR
)iCol
;
408 iPosPrev
= (int)(short)usGetWord(
409 iFodo
+ iFodoOff
+ 4,
411 for (iIndex
= 0; iIndex
< iCol
; iIndex
++) {
412 iPosCurr
= (int)(short)usGetWord(
413 iFodo
+ iFodoOff
+ 6 + iIndex
* 2,
415 pRow
->asColumnWidth
[iIndex
] =
416 (short)(iPosCurr
- iPosPrev
);
426 iGet2InfoLength(iFodo
+ iFodoOff
, aucGrpprl
);
429 iFodoOff
+= iInfoLen
;
431 if (bFound24_1
&& bFound25_1
&& bFound154
) {
432 return found_end_of_row
;
434 if (bFound24_0
&& bFound25_0
&& !bFound154
) {
435 return found_not_end_of_row
;
441 return found_not_a_cell
;
443 return found_nothing
;
444 } /* end of eGet2RowInfo */
447 * Fill the style information block with information
448 * from a WinWord 1/2 file.
451 vGet2StyleInfo(int iFodo
,
452 const UCHAR
*aucGrpprl
, int iBytes
, style_block_type
*pStyle
)
454 int iFodoOff
, iInfoLen
;
455 int iTmp
, iDel
, iAdd
;
459 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pStyle
== NULL
);
461 NO_DBG_DEC(pStyle
->usIstd
);
464 while (iBytes
>= iFodoOff
+ 1) {
466 switch (ucGetByte(iFodo
+ iFodoOff
, aucGrpprl
)) {
468 sTmp
= (short)ucGetByte(
469 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
473 pStyle
->ucAlignment
= ucGetByte(
474 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
476 case 12: /* nfcSeqNumb */
477 pStyle
->ucNFC
= ucGetByte(
478 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
480 case 13: /* nLvlAnm */
481 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
482 pStyle
->ucNumLevel
= ucTmp
;
484 eGetNumType(ucTmp
) == level_type_pause
;
486 case 15: /* ChgTabsPapx */
487 case 23: /* ChgTabs */
488 iTmp
= (int)ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
494 iDel
= (int)ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
495 if (iTmp
< 2 + 2 * iDel
) {
500 iAdd
= (int)ucGetByte(
501 iFodo
+ iFodoOff
+ 3 + 2 * iDel
, aucGrpprl
);
502 if (iTmp
< 2 + 2 * iDel
+ 2 * iAdd
) {
508 case 16: /* dxaRight */
509 pStyle
->sRightIndent
= (short)usGetWord(
510 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
511 NO_DBG_DEC(pStyle
->sRightIndent
);
513 case 17: /* dxaLeft */
514 pStyle
->sLeftIndent
= (short)usGetWord(
515 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
516 NO_DBG_DEC(pStyle
->sLeftIndent
);
518 case 18: /* Nest dxaLeft */
519 sTmp
= (short)usGetWord(
520 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
521 pStyle
->sLeftIndent
+= sTmp
;
522 if (pStyle
->sLeftIndent
< 0) {
523 pStyle
->sLeftIndent
= 0;
526 NO_DBG_DEC(pStyle
->sLeftIndent
);
528 case 19: /* dxaLeft1 */
529 pStyle
->sLeftIndent1
= (short)usGetWord(
530 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
531 NO_DBG_DEC(pStyle
->sLeftIndent1
);
533 case 21: /* dyaBefore */
534 pStyle
->usBeforeIndent
= usGetWord(
535 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
536 NO_DBG_DEC(pStyle
->usBeforeIndent
);
538 case 22: /* dyaAfter */
539 pStyle
->usAfterIndent
= usGetWord(
540 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
541 NO_DBG_DEC(pStyle
->usAfterIndent
);
548 iGet2InfoLength(iFodo
+ iFodoOff
, aucGrpprl
);
551 iFodoOff
+= iInfoLen
;
553 } /* end of vGet2StyleInfo */
556 * Build the lists with Paragraph Information for WinWord 1/2 files
559 vGet2PapInfo(FILE *pFile
, const UCHAR
*aucHeader
)
562 style_block_type tStyle
;
565 ULONG ulCharPos
, ulCharPosFirst
, ulCharPosLast
;
566 ULONG ulBeginParfInfo
;
567 size_t tParfInfoLen
, tParfPageNum
, tOffset
, tSize
, tLenOld
, tLen
;
568 int iIndex
, iIndex2
, iRun
, iFodo
, iLen
;
569 row_info_enum eRowInfo
;
570 USHORT usParfFirstPage
, usCount
, usIstd
;
572 UCHAR aucFpage
[BIG_BLOCK_SIZE
];
574 fail(pFile
== NULL
|| aucHeader
== NULL
);
576 ulBeginParfInfo
= ulGetLong(0xa6, aucHeader
); /* fcPlcfbtePapx */
577 NO_DBG_HEX(ulBeginParfInfo
);
578 tParfInfoLen
= (size_t)usGetWord(0xaa, aucHeader
); /* cbPlcfbtePapx */
579 NO_DBG_DEC(tParfInfoLen
);
580 if (tParfInfoLen
< 4) {
581 DBG_DEC(tParfInfoLen
);
585 aucBuffer
= xmalloc(tParfInfoLen
);
586 if (!bReadBytes(aucBuffer
, tParfInfoLen
, ulBeginParfInfo
, pFile
)) {
587 aucBuffer
= xfree(aucBuffer
);
590 NO_DBG_PRINT_BLOCK(aucBuffer
, tParfInfoLen
);
592 tLen
= (tParfInfoLen
- 4) / 6;
593 ausParfPage
= xcalloc(tLen
, sizeof(USHORT
));
594 for (iIndex
= 0, tOffset
= (tLen
+ 1) * 4;
596 iIndex
++, tOffset
+= 2) {
597 ausParfPage
[iIndex
] = usGetWord(tOffset
, aucBuffer
);
598 NO_DBG_DEC(ausParfPage
[iIndex
]);
600 DBG_HEX(ulGetLong(0, aucBuffer
));
601 aucBuffer
= xfree(aucBuffer
);
602 tParfPageNum
= (size_t)usGetWord(0x144, aucHeader
); /* cpnBtePap */
603 DBG_DEC(tParfPageNum
);
604 if (tLen
< tParfPageNum
) {
605 /* Replace ParfPage by a longer version */
607 usParfFirstPage
= usGetWord(0x140, aucHeader
); /* pnPapFirst */
608 DBG_DEC(usParfFirstPage
);
609 tLen
+= tParfPageNum
- 1;
610 tSize
= tLen
* sizeof(USHORT
);
611 ausParfPage
= xrealloc(ausParfPage
, tSize
);
613 usCount
= usParfFirstPage
+ 1;
614 for (iIndex
= (int)tLenOld
; iIndex
< (int)tLen
; iIndex
++) {
615 ausParfPage
[iIndex
] = usCount
;
616 NO_DBG_DEC(ausParfPage
[iIndex
]);
621 (void)memset(&tRow
, 0, sizeof(tRow
));
622 ulCharPosFirst
= CP_INVALID
;
623 for (iIndex
= 0; iIndex
< (int)tLen
; iIndex
++) {
624 if (!bReadBytes(aucFpage
, BIG_BLOCK_SIZE
,
625 (ULONG
)ausParfPage
[iIndex
] * BIG_BLOCK_SIZE
,
629 NO_DBG_PRINT_BLOCK(aucFpage
, BIG_BLOCK_SIZE
);
630 iRun
= (int)ucGetByte(0x1ff, aucFpage
);
632 for (iIndex2
= 0; iIndex2
< iRun
; iIndex2
++) {
633 if ((iRun
+ 1) * 4 + iIndex2
* 1 >= BIG_BLOCK_SIZE
) {
636 NO_DBG_HEX(ulGetLong(iIndex2
* 4, aucFpage
));
637 iFodo
= 2 * (int)ucGetByte(
638 (iRun
+ 1) * 4 + iIndex2
* 1, aucFpage
);
643 iLen
= 2 * (int)ucGetByte(iFodo
, aucFpage
);
645 ucStc
= ucGetByte(iFodo
+ 1, aucFpage
);
646 usIstd
= usStc2istd(ucStc
);
648 vFillStyleFromStylesheet(usIstd
, &tStyle
);
649 vGet2StyleInfo(iFodo
, aucFpage
+ 8, iLen
- 8, &tStyle
);
650 ulCharPos
= ulGetLong(iIndex2
* 4, aucFpage
);
651 NO_DBG_HEX(ulCharPos
);
652 tStyle
.ulFileOffset
= ulCharPos
;
653 vAdd2StyleInfoList(&tStyle
);
655 eRowInfo
= eGet2RowInfo(iFodo
,
656 aucFpage
+ 8, iLen
- 8, &tRow
);
660 if (ulCharPosFirst
!= CP_INVALID
) {
663 ulCharPosFirst
= ulGetLong(
664 iIndex2
* 4, aucFpage
);
665 NO_DBG_HEX(ulCharPosFirst
);
666 tRow
.ulCharPosStart
= ulCharPosFirst
;
667 tRow
.ulFileOffsetStart
= ulCharPosFirst
;
669 case found_end_of_row
:
670 ulCharPosLast
= ulGetLong(
671 iIndex2
* 4, aucFpage
);
672 NO_DBG_HEX(ulCharPosLast
);
673 tRow
.ulCharPosEnd
= ulCharPosLast
;
674 /* Add 1 for compatiblity with Word 6 and up */
675 tRow
.ulFileOffsetEnd
= ulCharPosLast
+ 1;
676 vAdd2RowInfoList(&tRow
);
677 (void)memset(&tRow
, 0, sizeof(tRow
));
678 ulCharPosFirst
= CP_INVALID
;
688 ausParfPage
= xfree(ausParfPage
);
689 } /* end of vGet2PapInfo */
692 * Fill the font information block with information
693 * from a WinWord 1 file.
696 vGet1FontInfo(int iFodo
,
697 const UCHAR
*aucGrpprl
, size_t tBytes
, font_block_type
*pFont
)
699 BOOL bIcoChange
, bFtcChange
, bHpsChange
, bKulChange
;
704 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pFont
== NULL
);
706 if (tBytes
> sizeof(aucChpx
)) {
707 NO_DBG_PRINT_BLOCK(aucGrpprl
+ iFodo
, tBytes
);
711 /* Build the CHPX structure */
712 (void)memset(aucChpx
, 0, sizeof(aucChpx
));
713 (void)memcpy(aucChpx
, aucGrpprl
+ iFodo
, min(tBytes
, sizeof(aucChpx
)));
715 usTmp
= usGetWord(0, aucChpx
);
716 if ((usTmp
& BIT(0)) != 0) {
717 pFont
->usFontStyle
^= FONT_BOLD
;
719 if ((usTmp
& BIT(1)) != 0) {
720 pFont
->usFontStyle
^= FONT_ITALIC
;
722 if ((usTmp
& BIT(2)) != 0) {
723 pFont
->usFontStyle
^= FONT_STRIKE
;
725 if ((usTmp
& BIT(5)) != 0) {
726 pFont
->usFontStyle
^= FONT_SMALL_CAPITALS
;
728 if ((usTmp
& BIT(6)) != 0) {
729 pFont
->usFontStyle
^= FONT_CAPITALS
;
731 if ((usTmp
& BIT(7)) != 0) {
732 pFont
->usFontStyle
^= FONT_HIDDEN
;
735 ucTmp
= ucGetByte(5, aucChpx
);
738 pFont
->usFontStyle
|= FONT_SUPERSCRIPT
;
739 DBG_MSG("Superscript");
741 pFont
->usFontStyle
|= FONT_SUBSCRIPT
;
742 DBG_MSG("Subscript");
746 bIcoChange
= (usTmp
& BIT(10)) != 0;
747 bFtcChange
= (usTmp
& BIT(11)) != 0;
748 bHpsChange
= (usTmp
& BIT(12)) != 0;
749 bKulChange
= (usTmp
& BIT(13)) != 0;
752 usTmp
= usGetWord(2, aucChpx
);
753 if (usTmp
<= (USHORT
)UCHAR_MAX
) {
754 pFont
->ucFontNumber
= (UCHAR
)usTmp
;
756 pFont
->ucFontNumber
= 0;
761 pFont
->usFontSize
= (USHORT
)ucGetByte(4, aucChpx
);
764 if (bIcoChange
|| bKulChange
) {
765 usTmp
= usGetWord(6, aucChpx
);
767 pFont
->ucFontColor
= (UCHAR
)((usTmp
& 0x0f00) >> 8);
768 if (pFont
->ucFontColor
<= 7) {
769 /* Add 1 for compatibility with Word 2 and up */
770 pFont
->ucFontColor
++;
772 DBG_DEC(pFont
->ucFontColor
);
773 pFont
->ucFontColor
= 0;
777 usTmp
= (usTmp
& 0x7000) >> 12;
778 DBG_DEC_C(usTmp
> 4, usTmp
);
780 pFont
->usFontStyle
&= ~FONT_UNDERLINE
;
782 pFont
->usFontStyle
|= FONT_UNDERLINE
;
786 } /* end of vGet1FontInfo */
789 * Fill the font information block with information
790 * from a WinWord 1/2 file.
793 vGet2FontInfo(int iFodo
,
794 const UCHAR
*aucGrpprl
, size_t tBytes
, font_block_type
*pFont
)
796 BOOL bIcoChange
, bFtcChange
, bHpsChange
, bKulChange
;
801 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pFont
== NULL
);
803 if (tBytes
> sizeof(aucChpx
)) {
804 NO_DBG_PRINT_BLOCK(aucGrpprl
+ iFodo
, tBytes
);
808 /* Build the CHPX structure */
809 (void)memset(aucChpx
, 0, sizeof(aucChpx
));
810 (void)memcpy(aucChpx
, aucGrpprl
+ iFodo
, min(tBytes
, sizeof(aucChpx
)));
812 usTmp
= usGetWord(0, aucChpx
);
813 if ((usTmp
& BIT(0)) != 0) {
814 pFont
->usFontStyle
^= FONT_BOLD
;
816 if ((usTmp
& BIT(1)) != 0) {
817 pFont
->usFontStyle
^= FONT_ITALIC
;
819 if (usTmp
& BIT(3)) {
820 pFont
->usFontStyle
^= FONT_MARKDEL
;
822 if ((usTmp
& BIT(5)) != 0) {
823 pFont
->usFontStyle
^= FONT_SMALL_CAPITALS
;
825 if ((usTmp
& BIT(6)) != 0) {
826 pFont
->usFontStyle
^= FONT_CAPITALS
;
828 if ((usTmp
& BIT(7)) != 0) {
829 pFont
->usFontStyle
^= FONT_HIDDEN
;
831 if (usTmp
& BIT(10)) {
832 pFont
->usFontStyle
^= FONT_STRIKE
;
835 ucTmp
= ucGetByte(10, aucChpx
);
836 DBG_MSG_C(ucTmp
!= 0 && ucTmp
< 128, "Superscript");
837 DBG_MSG_C(ucTmp
>= 128, "Subscript");
839 usTmp
= usGetWord(2, aucChpx
);
841 /* No changes, nothing to do */
845 bIcoChange
= (usTmp
& BIT(0)) != 0;
846 bFtcChange
= (usTmp
& BIT(1)) != 0;
847 bHpsChange
= (usTmp
& BIT(2)) != 0;
848 bKulChange
= (usTmp
& BIT(3)) != 0;
851 usTmp
= usGetWord(4, aucChpx
);
852 if (usTmp
<= (USHORT
)UCHAR_MAX
) {
853 pFont
->ucFontNumber
= (UCHAR
)usTmp
;
855 pFont
->ucFontNumber
= 0;
860 pFont
->usFontSize
= usGetWord(6, aucChpx
);
863 if (bIcoChange
|| bKulChange
) {
864 ucTmp
= ucGetByte(9, aucChpx
);
866 pFont
->ucFontColor
= ucTmp
& 0x1f;
867 if (pFont
->ucFontColor
> 16) {
868 DBG_DEC(pFont
->ucFontColor
);
869 pFont
->ucFontColor
= 0;
873 ucTmp
= (ucTmp
& 0xe0) >> 5;
874 DBG_DEC_C(ucTmp
> 4, ucTmp
);
876 pFont
->usFontStyle
&= ~FONT_UNDERLINE
;
878 pFont
->usFontStyle
|= FONT_UNDERLINE
;
882 } /* end of vGet2FontInfo */
885 * Fill the picture information block with information from a WinWord 1 file.
886 * Returns TRUE when successful, otherwise FALSE
889 bGet1PicInfo(int iFodo
,
890 const UCHAR
*aucGrpprl
, size_t tBytes
, picture_block_type
*pPicture
)
895 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pPicture
== NULL
);
897 if (tBytes
> sizeof(aucChpx
)) {
898 NO_DBG_PRINT_BLOCK(aucGrpprl
+ iFodo
, tBytes
);
899 tBytes
= sizeof(aucChpx
);
902 /* Build the CHPX structure */
903 (void)memset(aucChpx
, 0, sizeof(aucChpx
));
904 (void)memcpy(aucChpx
, aucGrpprl
+ iFodo
, min(tBytes
, sizeof(aucChpx
)));
906 ulTmp
= ulGetLong(8, aucChpx
);
907 if (ulTmp
!= 0 && ulTmp
< MAX_FILESIZE
) {
908 pPicture
->ulPictureOffset
= ulTmp
;
909 DBG_HEX(pPicture
->ulPictureOffset
);
913 } /* end of bGet1PicInfo */
916 * Fill the picture information block with information from a WinWord 2 file.
917 * Returns TRUE when successful, otherwise FALSE
920 bGet2PicInfo(int iFodo
,
921 const UCHAR
*aucGrpprl
, size_t tBytes
, picture_block_type
*pPicture
)
926 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pPicture
== NULL
);
928 if (tBytes
> sizeof(aucChpx
)) {
929 NO_DBG_PRINT_BLOCK(aucGrpprl
+ iFodo
, tBytes
);
930 tBytes
= sizeof(aucChpx
);
933 /* Build the CHPX structure */
934 (void)memset(aucChpx
, 0, sizeof(aucChpx
));
935 (void)memcpy(aucChpx
, aucGrpprl
+ iFodo
, min(tBytes
, sizeof(aucChpx
)));
937 ulTmp
= ulGetLong(14, aucChpx
);
938 if (ulTmp
!= 0 && ulTmp
< MAX_FILESIZE
) {
939 pPicture
->ulPictureOffset
= ulTmp
;
940 DBG_HEX(pPicture
->ulPictureOffset
);
945 } /* end of bGet2PicInfo */
948 * Build the lists with Character Information for WinWord 1/2 files
951 vGet2ChrInfo(FILE *pFile
, int iWordVersion
, const UCHAR
*aucHeader
)
953 font_block_type tFont
;
954 picture_block_type tPicture
;
957 ULONG ulFileOffset
, ulCharPos
, ulBeginCharInfo
;
958 size_t tCharInfoLen
, tOffset
, tSize
, tChrLen
, tCharPageNum
;
959 size_t tLenOld
, tLen
;
960 int iIndex
, iIndex2
, iRun
, iFodo
;
961 BOOL bSuccess1
, bSuccess2
;
962 USHORT usCharFirstPage
, usCount
, usIstd
;
963 UCHAR aucFpage
[BIG_BLOCK_SIZE
];
965 fail(pFile
== NULL
|| aucHeader
== NULL
);
966 fail(iWordVersion
!= 1 && iWordVersion
!= 2);
968 ulBeginCharInfo
= ulGetLong(0xa0, aucHeader
); /* fcPlcfbteChpx */
969 DBG_HEX(ulBeginCharInfo
);
970 tCharInfoLen
= (size_t)usGetWord(0xa4, aucHeader
); /* cbPlcfbteChpx */
971 DBG_DEC(tCharInfoLen
);
972 if (tCharInfoLen
< 4) {
973 DBG_DEC(tCharInfoLen
);
977 aucBuffer
= xmalloc(tCharInfoLen
);
978 if (!bReadBytes(aucBuffer
, tCharInfoLen
, ulBeginCharInfo
, pFile
)) {
979 aucBuffer
= xfree(aucBuffer
);
982 NO_DBG_PRINT_BLOCK(aucBuffer
, tCharInfoLen
);
984 tLen
= (tCharInfoLen
- 4) / 6;
985 ausCharPage
= xcalloc(tLen
, sizeof(USHORT
));
986 for (iIndex
= 0, tOffset
= (tLen
+ 1) * 4;
988 iIndex
++, tOffset
+= 2) {
989 ausCharPage
[iIndex
] = usGetWord(tOffset
, aucBuffer
);
990 NO_DBG_DEC(ausCharPage
[iIndex
]);
992 DBG_HEX(ulGetLong(0, aucBuffer
));
993 aucBuffer
= xfree(aucBuffer
);
994 tCharPageNum
= (size_t)usGetWord(0x142, aucHeader
); /* cpnBteChp */
995 DBG_DEC(tCharPageNum
);
996 if (tLen
< tCharPageNum
) {
997 /* Replace CharPage by a longer version */
999 usCharFirstPage
= usGetWord(0x13e, aucHeader
); /* pnChrFirst */
1000 NO_DBG_DEC(usCharFirstPage
);
1001 tLen
+= tCharPageNum
- 1;
1002 tSize
= tLen
* sizeof(USHORT
);
1003 ausCharPage
= xrealloc(ausCharPage
, tSize
);
1004 /* Add new values */
1005 usCount
= usCharFirstPage
+ 1;
1006 for (iIndex
= (int)tLenOld
; iIndex
< (int)tLen
; iIndex
++) {
1007 ausCharPage
[iIndex
] = usCount
;
1008 NO_DBG_DEC(ausCharPage
[iIndex
]);
1013 for (iIndex
= 0; iIndex
< (int)tLen
; iIndex
++) {
1014 if (!bReadBytes(aucFpage
, BIG_BLOCK_SIZE
,
1015 (ULONG
)ausCharPage
[iIndex
] * BIG_BLOCK_SIZE
,
1019 NO_DBG_PRINT_BLOCK(aucFpage
, BIG_BLOCK_SIZE
);
1020 iRun
= (int)ucGetByte(0x1ff, aucFpage
);
1022 for (iIndex2
= 0; iIndex2
< iRun
; iIndex2
++) {
1023 if ((iRun
+ 1) * 4 + iIndex2
>= BIG_BLOCK_SIZE
) {
1026 ulCharPos
= ulGetLong(iIndex2
* 4, aucFpage
);
1027 ulFileOffset
= ulCharPos
;
1028 iFodo
= 2 * (int)ucGetByte(
1029 (iRun
+ 1) * 4 + iIndex2
, aucFpage
);
1031 tChrLen
= (size_t)ucGetByte(iFodo
, aucFpage
);
1033 usIstd
= usGetIstd(ulFileOffset
);
1034 vFillFontFromStylesheet(usIstd
, &tFont
);
1036 if (iWordVersion
== 1) {
1037 vGet1FontInfo(iFodo
,
1038 aucFpage
+ 1, tChrLen
, &tFont
);
1039 } else if (iWordVersion
== 2) {
1040 vGet2FontInfo(iFodo
,
1041 aucFpage
+ 1, tChrLen
, &tFont
);
1044 tFont
.ulFileOffset
= ulFileOffset
;
1045 vAdd2FontInfoList(&tFont
);
1051 (void)memset(&tPicture
, 0, sizeof(tPicture
));
1052 bSuccess1
= iWordVersion
== 1 &&
1053 bGet1PicInfo(iFodo
, aucFpage
+ 1,
1054 tChrLen
, &tPicture
);
1055 bSuccess2
= iWordVersion
== 2 &&
1056 bGet2PicInfo(iFodo
, aucFpage
+ 1,
1057 tChrLen
, &tPicture
);
1058 if (bSuccess1
|| bSuccess2
) {
1059 tPicture
.ulFileOffset
= ulFileOffset
;
1060 tPicture
.ulFileOffsetPicture
=
1061 tPicture
.ulPictureOffset
;
1062 vAdd2PictInfoList(&tPicture
);
1066 ausCharPage
= xfree(ausCharPage
);
1067 } /* end of vGet2ChrInfo */