3 * Copyright (C) 2002 A.J. van Os; Released under GPL
6 * Read the property information from a WinWord 1 or 2 file
14 * iGet2InfoLength - the length of the information for WinWord 1/2 files
17 iGet2InfoLength(int iByteNbr
, const UCHAR
*aucGrpprl
)
21 switch (ucGetByte(iByteNbr
, aucGrpprl
)) {
22 case 3: case 15: case 78: case 152: case 154: case 155:
23 return 2 + (int)ucGetByte(iByteNbr
+ 1, aucGrpprl
);
24 case 16: case 17: case 18: case 19: case 21: case 22: case 26:
25 case 27: case 28: case 30: case 31: case 32: case 33: case 34:
26 case 35: case 36: case 38: case 39: case 40: case 41: case 42:
27 case 43: case 45: case 46: case 47: case 48: case 49: case 68:
28 case 71: case 72: case 82: case 83: case 96: case 97: case 98:
29 case 99: case 115: case 116: case 119: case 120: case 123: case 124:
30 case 129: case 130: case 131: case 132: case 135: case 136: case 139:
31 case 140: case 141: case 142: case 143: case 144: case 145: case 146:
32 case 147: case 148: case 153: case 159: case 161: case 162:
35 iTmp
= (int)ucGetByte(iByteNbr
+ 1, aucGrpprl
);
37 iDel
= (int)ucGetByte(iByteNbr
+ 2, aucGrpprl
);
38 iAdd
= (int)ucGetByte(
39 iByteNbr
+ 3 + iDel
* 4, aucGrpprl
);
40 iTmp
= 2 + iDel
* 4 + iAdd
* 3;
49 case 158: case 160: case 164:
54 } /* end of iGet2InfoLength */
57 * Fill the section information block with information
58 * from a WinWord 1/2 file.
61 vGet2SectionInfo(const UCHAR
*aucGrpprl
, size_t tBytes
,
62 section_block_type
*pSection
)
64 int iFodoOff
, iInfoLen
;
68 fail(aucGrpprl
== NULL
|| pSection
== NULL
);
71 while (tBytes
>= (size_t)iFodoOff
+ 1) {
73 switch (ucGetByte(iFodoOff
, aucGrpprl
)) {
75 ucTmp
= ucGetByte(iFodoOff
+ 1, aucGrpprl
);
77 pSection
->bNewPage
= ucTmp
!= 0 && ucTmp
!= 1;
79 case 119: /* ccolM1 */
80 usCcol
= 1 + usGetWord(iFodoOff
+ 1, aucGrpprl
);
87 iInfoLen
= iGet2InfoLength(iFodoOff
, aucGrpprl
);
92 } /* end of vGet2SectionInfo */
95 * Build the lists with Section Property Information for WinWord 1/2 files
98 vGet2SepInfo(FILE *pFile
, const UCHAR
*aucHeader
)
100 section_block_type tSection
;
101 ULONG
*aulSectPage
, *aulTextOffset
;
102 UCHAR
*aucBuffer
, *aucFpage
;
103 ULONG ulBeginSectInfo
;
104 size_t tSectInfoLen
, tOffset
, tSize
, tLen
, tBytes
;
108 fail(pFile
== NULL
|| aucHeader
== NULL
);
110 ulBeginSectInfo
= ulGetLong(0x7c, aucHeader
); /* fcPlcfsed */
111 DBG_HEX(ulBeginSectInfo
);
112 tSectInfoLen
= (size_t)usGetWord(0x80, aucHeader
); /* cbPlcfsed */
113 DBG_DEC(tSectInfoLen
);
114 if (tSectInfoLen
< 4) {
115 DBG_DEC(tSectInfoLen
);
119 aucBuffer
= xmalloc(tSectInfoLen
);
120 if (!bReadBytes(aucBuffer
, tSectInfoLen
, ulBeginSectInfo
, pFile
)) {
121 aucBuffer
= xfree(aucBuffer
);
124 NO_DBG_PRINT_BLOCK(aucBuffer
, tSectInfoLen
);
126 /* Read the Section Descriptors */
127 tLen
= (tSectInfoLen
- 4) / 10;
128 tSize
= tLen
* sizeof(ULONG
);
129 /* Save the section offsets */
130 aulTextOffset
= xmalloc(tSize
);
131 for (iIndex
= 0, tOffset
= 0;
133 iIndex
++, tOffset
+= 4) {
134 aulTextOffset
[iIndex
] = ulGetLong(tOffset
, aucBuffer
);
136 /* Save the Sepx offsets */
137 aulSectPage
= xmalloc(tSize
);
138 for (iIndex
= 0, tOffset
= (tLen
+ 1) * 4;
140 iIndex
++, tOffset
+= 6) {
141 aulSectPage
[iIndex
] = ulGetLong(tOffset
+ 2, aucBuffer
);
142 NO_DBG_HEX(aulSectPage
[iIndex
]); /* fcSepx */
144 aucBuffer
= xfree(aucBuffer
);
146 /* Read the Section Properties */
147 for (iIndex
= 0; iIndex
< (int)tLen
; iIndex
++) {
148 if (aulSectPage
[iIndex
] == FC_INVALID
) {
149 vDefault2SectionInfoList(aulTextOffset
[iIndex
]);
152 /* Get the number of bytes to read */
153 if (!bReadBytes(aucTmp
, 1, aulSectPage
[iIndex
], pFile
)) {
156 tBytes
= 1 + (size_t)ucGetByte(0, aucTmp
);
159 aucFpage
= xmalloc(tBytes
);
160 if (!bReadBytes(aucFpage
, tBytes
, aulSectPage
[iIndex
], pFile
)) {
161 aucFpage
= xfree(aucFpage
);
164 NO_DBG_PRINT_BLOCK(aucFpage
, tBytes
);
165 /* Process the bytes */
166 vGetDefaultSection(&tSection
);
167 vGet2SectionInfo(aucFpage
+ 1, tBytes
- 1, &tSection
);
168 vAdd2SectionInfoList(&tSection
, aulTextOffset
[iIndex
]);
169 aucFpage
= xfree(aucFpage
);
171 aulTextOffset
= xfree(aulTextOffset
);
172 aulSectPage
= xfree(aulSectPage
);
173 } /* end of vGet2SepInfo */
176 * Translate the rowinfo to a member of the row_info enumeration
179 eGet2RowInfo(int iFodo
,
180 const UCHAR
*aucGrpprl
, int iBytes
, row_block_type
*pRow
)
182 int iFodoOff
, iInfoLen
;
183 int iIndex
, iSize
, iCol
;
184 int iPosCurr
, iPosPrev
;
185 BOOL bFound24_0
, bFound24_1
, bFound25_0
, bFound25_1
, bFound154
;
187 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pRow
== NULL
);
195 while (iBytes
>= iFodoOff
+ 1) {
197 switch (ucGetByte(iFodo
+ iFodoOff
, aucGrpprl
)) {
198 case 24: /* fIntable */
199 if (odd(ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
))) {
206 if (odd(ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
))) {
212 case 152: /* cDefTable10 */
213 case 154: /* cDefTable */
214 iSize
= (int)usGetWord(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
215 if (iSize
< 6 || iBytes
< iFodoOff
+ 7) {
222 iCol
= (int)ucGetByte(iFodo
+ iFodoOff
+ 3, aucGrpprl
);
224 iBytes
< iFodoOff
+ 3 + (iCol
+ 1) * 2) {
231 if (iCol
>= (int)elementsof(pRow
->asColumnWidth
)) {
233 werr(1, "The number of columns is corrupt");
235 pRow
->ucNumberOfColumns
= (UCHAR
)iCol
;
236 pRow
->iColumnWidthSum
= 0;
237 iPosPrev
= (int)(short)usGetWord(
238 iFodo
+ iFodoOff
+ 4,
240 for (iIndex
= 0; iIndex
< iCol
; iIndex
++) {
241 iPosCurr
= (int)(short)usGetWord(
242 iFodo
+ iFodoOff
+ 6 + iIndex
* 2,
244 pRow
->asColumnWidth
[iIndex
] =
245 (short)(iPosCurr
- iPosPrev
);
246 pRow
->iColumnWidthSum
+=
247 pRow
->asColumnWidth
[iIndex
];
257 iGet2InfoLength(iFodo
+ iFodoOff
, aucGrpprl
);
260 iFodoOff
+= iInfoLen
;
262 if (bFound24_1
&& bFound25_1
&& bFound154
) {
263 return found_end_of_row
;
265 if (bFound24_0
&& bFound25_0
&& !bFound154
) {
266 return found_not_end_of_row
;
272 return found_not_a_cell
;
274 return found_nothing
;
275 } /* end of eGet2RowInfo */
278 * Fill the style information block with information
279 * from a WinWord 1/2 file.
282 vGet2StyleInfo(int iFodo
,
283 const UCHAR
*aucGrpprl
, int iBytes
, style_block_type
*pStyle
)
285 int iFodoOff
, iInfoLen
;
286 int iTmp
, iDel
, iAdd
;
290 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pStyle
== NULL
);
292 NO_DBG_DEC(pStyle
->usIstd
);
295 while (iBytes
>= iFodoOff
+ 1) {
297 switch (ucGetByte(iFodo
+ iFodoOff
, aucGrpprl
)) {
299 sTmp
= (short)ucGetByte(
300 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
304 pStyle
->ucAlignment
= ucGetByte(
305 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
307 case 12: /* nfcSeqNumb */
308 pStyle
->ucNFC
= ucGetByte(
309 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
311 case 13: /* nLvlAnm */
312 ucTmp
= ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
313 pStyle
->ucListLevel
= ucTmp
;
316 pStyle
->bNoNumbering
= TRUE
;
319 pStyle
->bNumPause
= TRUE
;
322 if ((int)ucTmp
== 0 || (int)ucTmp
>= 12) {
323 pStyle
->bNumPause
= TRUE
;
327 case 15: /* ChgTabsPapx */
328 iTmp
= (int)ucGetByte(iFodo
+ iFodoOff
+ 1, aucGrpprl
);
334 iDel
= (int)ucGetByte(iFodo
+ iFodoOff
+ 2, aucGrpprl
);
335 if (iTmp
< 2 + 2 * iDel
) {
340 iAdd
= (int)ucGetByte(
341 iFodo
+ iFodoOff
+ 3 + 2 * iDel
, aucGrpprl
);
342 if (iTmp
< 2 + 2 * iDel
+ 2 * iAdd
) {
348 case 16: /* dxaRight */
349 pStyle
->sRightIndent
= (short)usGetWord(
350 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
351 NO_DBG_DEC(pStyle
->sRightIndent
);
353 case 17: /* dxaLeft */
354 pStyle
->sLeftIndent
= (short)usGetWord(
355 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
356 NO_DBG_DEC(pStyle
->sLeftIndent
);
358 case 18: /* Nest dxaLeft */
359 sTmp
= (short)usGetWord(
360 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
361 pStyle
->sLeftIndent
+= sTmp
;
362 if (pStyle
->sLeftIndent
< 0) {
363 pStyle
->sLeftIndent
= 0;
366 NO_DBG_DEC(pStyle
->sLeftIndent
);
368 case 21: /* dyaBefore */
369 pStyle
->usBeforeIndent
= usGetWord(
370 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
371 NO_DBG_DEC(pStyle
->usBeforeIndent
);
373 case 22: /* dyaAfter */
374 pStyle
->usAfterIndent
= usGetWord(
375 iFodo
+ iFodoOff
+ 1, aucGrpprl
);
376 NO_DBG_DEC(pStyle
->usAfterIndent
);
383 iGet2InfoLength(iFodo
+ iFodoOff
, aucGrpprl
);
386 iFodoOff
+= iInfoLen
;
388 } /* end of vGet2StyleInfo */
391 * Build the lists with Paragraph Information for WinWord 1/2 files
394 vGet2PapInfo(FILE *pFile
, const UCHAR
*aucHeader
)
397 style_block_type tStyle
;
400 ULONG ulCharPos
, ulCharPosFirst
, ulCharPosLast
;
401 ULONG ulBeginParfInfo
;
402 size_t tParfInfoLen
, tParfPageNum
, tOffset
, tSize
, tLenOld
, tLen
;
403 int iIndex
, iIndex2
, iRun
, iFodo
, iLen
;
404 row_info_enum eRowInfo
;
405 USHORT usParfFirstPage
, usCount
, usIstd
;
407 UCHAR aucFpage
[BIG_BLOCK_SIZE
];
409 fail(pFile
== NULL
|| aucHeader
== NULL
);
411 ulBeginParfInfo
= ulGetLong(0xa6, aucHeader
); /* fcPlcfbtePapx */
412 NO_DBG_HEX(ulBeginParfInfo
);
413 tParfInfoLen
= (size_t)usGetWord(0xaa, aucHeader
); /* cbPlcfbtePapx */
414 NO_DBG_DEC(tParfInfoLen
);
415 if (tParfInfoLen
< 4) {
416 DBG_DEC(tParfInfoLen
);
420 aucBuffer
= xmalloc(tParfInfoLen
);
421 if (!bReadBytes(aucBuffer
, tParfInfoLen
, ulBeginParfInfo
, pFile
)) {
422 aucBuffer
= xfree(aucBuffer
);
425 NO_DBG_PRINT_BLOCK(aucBuffer
, tParfInfoLen
);
427 tLen
= (tParfInfoLen
- 4) / 6;
428 tSize
= tLen
* sizeof(USHORT
);
429 ausParfPage
= xmalloc(tSize
);
430 for (iIndex
= 0, tOffset
= (tLen
+ 1) * 4;
432 iIndex
++, tOffset
+= 2) {
433 ausParfPage
[iIndex
] = usGetWord(tOffset
, aucBuffer
);
434 NO_DBG_DEC(ausParfPage
[iIndex
]);
436 DBG_HEX(ulGetLong(0, aucBuffer
));
437 aucBuffer
= xfree(aucBuffer
);
438 tParfPageNum
= (size_t)usGetWord(0x144, aucHeader
); /* cpnBtePap */
439 DBG_DEC(tParfPageNum
);
440 if (tLen
< tParfPageNum
) {
441 /* Replace ParfPage by a longer version */
443 usParfFirstPage
= usGetWord(0x140, aucHeader
); /* pnPapFirst */
444 DBG_DEC(usParfFirstPage
);
445 tLen
+= tParfPageNum
- 1;
446 tSize
= tLen
* sizeof(USHORT
);
447 ausParfPage
= xrealloc(ausParfPage
, tSize
);
449 usCount
= usParfFirstPage
+ 1;
450 for (iIndex
= (int)tLenOld
; iIndex
< (int)tLen
; iIndex
++) {
451 ausParfPage
[iIndex
] = usCount
;
452 NO_DBG_DEC(ausParfPage
[iIndex
]);
457 (void)memset(&tRow
, 0, sizeof(tRow
));
458 ulCharPosFirst
= CP_INVALID
;
459 for (iIndex
= 0; iIndex
< (int)tLen
; iIndex
++) {
460 if (!bReadBytes(aucFpage
, BIG_BLOCK_SIZE
,
461 (ULONG
)ausParfPage
[iIndex
] * BIG_BLOCK_SIZE
,
465 NO_DBG_PRINT_BLOCK(aucFpage
, BIG_BLOCK_SIZE
);
466 iRun
= (int)ucGetByte(0x1ff, aucFpage
);
468 for (iIndex2
= 0; iIndex2
< iRun
; iIndex2
++) {
469 NO_DBG_HEX(ulGetLong(iIndex2
* 4, aucFpage
));
470 iFodo
= 2 * (int)ucGetByte(
471 (iRun
+ 1) * 4 + iIndex2
* 1, aucFpage
);
476 iLen
= 2 * (int)ucGetByte(iFodo
, aucFpage
);
478 ucStc
= ucGetByte(iFodo
+ 1, aucFpage
);
479 usIstd
= usStc2istd(ucStc
);
481 vFillStyleFromStylesheet(usIstd
, &tStyle
);
482 vGet2StyleInfo(iFodo
, aucFpage
+ 8, iLen
- 8, &tStyle
);
483 ulCharPos
= ulGetLong(iIndex2
* 4, aucFpage
);
484 NO_DBG_HEX(ulCharPos
);
485 tStyle
.ulFileOffset
= ulCharPos
;
486 vAdd2StyleInfoList(&tStyle
);
488 eRowInfo
= eGet2RowInfo(iFodo
,
489 aucFpage
+ 8, iLen
- 8, &tRow
);
493 if (ulCharPosFirst
!= CP_INVALID
) {
496 ulCharPosFirst
= ulGetLong(
497 iIndex2
* 4, aucFpage
);
498 DBG_HEX(ulCharPosFirst
);
499 tRow
.ulCharPosStart
= ulCharPosFirst
;
500 tRow
.ulFileOffsetStart
= ulCharPosFirst
;
502 case found_end_of_row
:
503 ulCharPosLast
= ulGetLong(
504 iIndex2
* 4, aucFpage
);
505 DBG_HEX(ulCharPosLast
);
506 tRow
.ulCharPosEnd
= ulCharPosLast
;
507 /* Add 1 for compatiblity with Word 6 and up */
508 tRow
.ulFileOffsetEnd
= ulCharPosLast
+ 1;
509 vAdd2RowInfoList(&tRow
);
510 (void)memset(&tRow
, 0, sizeof(tRow
));
511 ulCharPosFirst
= CP_INVALID
;
521 ausParfPage
= xfree(ausParfPage
);
522 } /* end of vGet2PapInfo */
525 * Fill the font information block with information
526 * from a WinWord 1 file.
527 * Returns TRUE when successful, otherwise FALSE
530 vGet1FontInfo(int iFodo
,
531 const UCHAR
*aucGrpprl
, size_t tBytes
, font_block_type
*pFont
)
533 BOOL bIcoChange
, bFtcChange
, bHpsChange
, bKulChange
;
538 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pFont
== NULL
);
539 fail(tBytes
> sizeof(aucChpx
));
541 NO_DBG_PRINT_BLOCK(aucGrpprl
+ iFodo
, iBytes
);
543 /* Build the CHPX structure */
544 (void)memset(aucChpx
, 0, sizeof(aucChpx
));
545 (void)memcpy(aucChpx
, aucGrpprl
+ iFodo
, min(tBytes
, sizeof(aucChpx
)));
547 usTmp
= usGetWord(0, aucChpx
);
548 if ((usTmp
& BIT(0)) != 0) {
549 pFont
->ucFontstyle
^= FONT_BOLD
;
551 if ((usTmp
& BIT(1)) != 0) {
552 pFont
->ucFontstyle
^= FONT_ITALIC
;
554 if ((usTmp
& BIT(2)) != 0) {
555 pFont
->ucFontstyle
^= FONT_STRIKE
;
557 if ((usTmp
& BIT(5)) != 0) {
558 pFont
->ucFontstyle
^= FONT_SMALL_CAPITALS
;
560 if ((usTmp
& BIT(6)) != 0) {
561 pFont
->ucFontstyle
^= FONT_CAPITALS
;
563 if ((usTmp
& BIT(7)) != 0) {
564 pFont
->ucFontstyle
^= FONT_HIDDEN
;
567 ucTmp
= ucGetByte(5, aucChpx
);
568 DBG_MSG_C(ucTmp
!= 0 && ucTmp
< 128, "Superscript");
569 DBG_MSG_C(ucTmp
>= 128, "Subscript");
571 bIcoChange
= (usTmp
& BIT(10)) != 0;
572 bFtcChange
= (usTmp
& BIT(11)) != 0;
573 bHpsChange
= (usTmp
& BIT(12)) != 0;
574 bKulChange
= (usTmp
& BIT(13)) != 0;
577 usTmp
= usGetWord(2, aucChpx
);
578 if (usTmp
<= (USHORT
)UCHAR_MAX
) {
579 pFont
->ucFontnumber
= (UCHAR
)usTmp
;
581 pFont
->ucFontnumber
= 0;
586 pFont
->sFontsize
= (short)ucGetByte(4, aucChpx
);
589 if (bIcoChange
|| bKulChange
) {
590 usTmp
= usGetWord(6, aucChpx
);
592 pFont
->ucFontcolor
= (UCHAR
)((usTmp
& 0x0f00) >> 8);
593 if (pFont
->ucFontcolor
<= 7) {
594 /* Add 1 for compatibility with Word 2 and up */
595 pFont
->ucFontcolor
++;
597 DBG_DEC(pFont
->ucFontcolor
);
598 pFont
->ucFontcolor
= 0;
602 usTmp
= (usTmp
& 0x7000) >> 12;
603 DBG_DEC_C(usTmp
> 4, usTmp
);
605 pFont
->ucFontstyle
&= ~FONT_UNDERLINE
;
607 pFont
->ucFontstyle
|= FONT_UNDERLINE
;
611 } /* end of vGet1FontInfo */
614 * Fill the font information block with information
615 * from a WinWord 1/2 file.
616 * Returns TRUE when successful, otherwise FALSE
619 vGet2FontInfo(int iFodo
,
620 const UCHAR
*aucGrpprl
, size_t tBytes
, font_block_type
*pFont
)
622 BOOL bIcoChange
, bFtcChange
, bHpsChange
, bKulChange
;
627 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pFont
== NULL
);
628 fail(tBytes
> sizeof(aucChpx
));
630 NO_DBG_PRINT_BLOCK(aucGrpprl
+ iFodo
, tBytes
);
632 /* Build the CHPX structure */
633 (void)memset(aucChpx
, 0, sizeof(aucChpx
));
634 (void)memcpy(aucChpx
, aucGrpprl
+ iFodo
, min(tBytes
, sizeof(aucChpx
)));
636 usTmp
= usGetWord(0, aucChpx
);
637 if ((usTmp
& BIT(0)) != 0) {
638 pFont
->ucFontstyle
^= FONT_BOLD
;
640 if ((usTmp
& BIT(1)) != 0) {
641 pFont
->ucFontstyle
^= FONT_ITALIC
;
643 if (usTmp
& BIT(3)) {
644 pFont
->ucFontstyle
^= FONT_MARKDEL
;
646 if ((usTmp
& BIT(5)) != 0) {
647 pFont
->ucFontstyle
^= FONT_SMALL_CAPITALS
;
649 if ((usTmp
& BIT(6)) != 0) {
650 pFont
->ucFontstyle
^= FONT_CAPITALS
;
652 if ((usTmp
& BIT(7)) != 0) {
653 pFont
->ucFontstyle
^= FONT_HIDDEN
;
655 if (usTmp
& BIT(10)) {
656 pFont
->ucFontstyle
^= FONT_STRIKE
;
659 ucTmp
= ucGetByte(10, aucChpx
);
660 DBG_MSG_C(ucTmp
!= 0 && ucTmp
< 128, "Superscript");
661 DBG_MSG_C(ucTmp
>= 128, "Subscript");
663 usTmp
= usGetWord(2, aucChpx
);
665 /* No changes, nothing to do */
669 bIcoChange
= (usTmp
& BIT(0)) != 0;
670 bFtcChange
= (usTmp
& BIT(1)) != 0;
671 bHpsChange
= (usTmp
& BIT(2)) != 0;
672 bKulChange
= (usTmp
& BIT(3)) != 0;
675 usTmp
= usGetWord(4, aucChpx
);
676 if (usTmp
<= (USHORT
)UCHAR_MAX
) {
677 pFont
->ucFontnumber
= (UCHAR
)usTmp
;
679 pFont
->ucFontnumber
= 0;
684 usTmp
= usGetWord(6, aucChpx
);
685 if (usTmp
> (USHORT
)SHRT_MAX
) {
686 pFont
->sFontsize
= SHRT_MAX
;
688 pFont
->sFontsize
= (short)usTmp
;
692 if (bIcoChange
|| bKulChange
) {
693 ucTmp
= ucGetByte(9, aucChpx
);
695 pFont
->ucFontcolor
= ucTmp
& 0x1f;
696 if (pFont
->ucFontcolor
> 16) {
697 DBG_DEC(pFont
->ucFontcolor
);
698 pFont
->ucFontcolor
= 0;
702 ucTmp
= (ucTmp
& 0xe0) >> 5;
703 DBG_DEC_C(ucTmp
> 4, ucTmp
);
705 pFont
->ucFontstyle
&= ~FONT_UNDERLINE
;
707 pFont
->ucFontstyle
|= FONT_UNDERLINE
;
711 } /* end of vGet2FontInfo */
714 * Fill the picture information block with information from a WinWord 1 file.
715 * Returns TRUE when successful, otherwise FALSE
718 bGet1PicInfo(int iFodo
,
719 const UCHAR
*aucGrpprl
, size_t tBytes
, picture_block_type
*pPicture
)
724 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pPicture
== NULL
);
725 fail(tBytes
> sizeof(aucChpx
));
727 DBG_PRINT_BLOCK(aucGrpprl
+ iFodo
, tBytes
);
729 /* Build the CHPX structure */
730 (void)memset(aucChpx
, 0, sizeof(aucChpx
));
731 (void)memcpy(aucChpx
, aucGrpprl
+ iFodo
, min(tBytes
, sizeof(aucChpx
)));
733 ulTmp
= ulGetLong(8, aucChpx
);
735 pPicture
->ulPictureOffset
= ulTmp
;
736 DBG_HEX(pPicture
->ulPictureOffset
);
740 } /* end of bGet1PicInfo */
743 * Fill the picture information block with information from a WinWord 2 file.
744 * Returns TRUE when successful, otherwise FALSE
747 bGet2PicInfo(int iFodo
,
748 const UCHAR
*aucGrpprl
, size_t tBytes
, picture_block_type
*pPicture
)
753 fail(iFodo
< 0 || aucGrpprl
== NULL
|| pPicture
== NULL
);
754 fail(tBytes
> sizeof(aucChpx
));
756 DBG_PRINT_BLOCK(aucGrpprl
+ iFodo
, tBytes
);
758 /* Build the CHPX structure */
759 (void)memset(aucChpx
, 0, sizeof(aucChpx
));
760 (void)memcpy(aucChpx
, aucGrpprl
+ iFodo
, min(tBytes
, sizeof(aucChpx
)));
762 ulTmp
= ulGetLong(14, aucChpx
);
764 pPicture
->ulPictureOffset
= ulTmp
;
765 DBG_HEX(pPicture
->ulPictureOffset
);
770 } /* end of bGet2PicInfo */
773 * Build the lists with Character Information for WinWord 1/2 files
776 vGet2ChrInfo(FILE *pFile
, int iWordVersion
, const UCHAR
*aucHeader
)
778 font_block_type tFont
;
779 picture_block_type tPicture
;
782 ULONG ulFileOffset
, ulCharPos
, ulBeginCharInfo
;
783 size_t tCharInfoLen
, tOffset
, tSize
, tChrLen
, tCharPageNum
;
784 size_t tLenOld
, tLen
;
785 int iIndex
, iIndex2
, iRun
, iFodo
;
786 BOOL bSuccess1
, bSuccess2
;
787 USHORT usCharFirstPage
, usCount
, usIstd
;
788 UCHAR aucFpage
[BIG_BLOCK_SIZE
];
790 fail(pFile
== NULL
|| aucHeader
== NULL
);
791 fail(iWordVersion
!= 1 && iWordVersion
!= 2);
793 ulBeginCharInfo
= ulGetLong(0xa0, aucHeader
); /* fcPlcfbteChpx */
794 DBG_HEX(ulBeginCharInfo
);
795 tCharInfoLen
= (size_t)usGetWord(0xa4, aucHeader
); /* cbPlcfbteChpx */
796 DBG_DEC(tCharInfoLen
);
797 if (tCharInfoLen
< 4) {
798 DBG_DEC(tCharInfoLen
);
801 aucBuffer
= xmalloc(tCharInfoLen
);
802 if (!bReadBytes(aucBuffer
, tCharInfoLen
, ulBeginCharInfo
, pFile
)) {
803 aucBuffer
= xfree(aucBuffer
);
806 NO_DBG_PRINT_BLOCK(aucBuffer
, tCharInfoLen
);
808 tLen
= (tCharInfoLen
- 4) / 6;
809 tSize
= tLen
* sizeof(USHORT
);
810 ausCharPage
= xmalloc(tSize
);
811 for (iIndex
= 0, tOffset
= (tLen
+ 1) * 4;
813 iIndex
++, tOffset
+= 2) {
814 ausCharPage
[iIndex
] = usGetWord(tOffset
, aucBuffer
);
815 NO_DBG_DEC(ausCharPage
[iIndex
]);
817 DBG_HEX(ulGetLong(0, aucBuffer
));
818 aucBuffer
= xfree(aucBuffer
);
819 tCharPageNum
= (size_t)usGetWord(0x142, aucHeader
); /* cpnBteChp */
820 DBG_DEC(tCharPageNum
);
821 if (tLen
< tCharPageNum
) {
822 /* Replace CharPage by a longer version */
824 usCharFirstPage
= usGetWord(0x13e, aucHeader
); /* pnChrFirst */
825 NO_DBG_DEC(usCharFirstPage
);
826 tLen
+= tCharPageNum
- 1;
827 tSize
= tLen
* sizeof(USHORT
);
828 ausCharPage
= xrealloc(ausCharPage
, tSize
);
830 usCount
= usCharFirstPage
+ 1;
831 for (iIndex
= (int)tLenOld
; iIndex
< (int)tLen
; iIndex
++) {
832 ausCharPage
[iIndex
] = usCount
;
833 NO_DBG_DEC(ausCharPage
[iIndex
]);
838 for (iIndex
= 0; iIndex
< (int)tLen
; iIndex
++) {
839 if (!bReadBytes(aucFpage
, BIG_BLOCK_SIZE
,
840 (ULONG
)ausCharPage
[iIndex
] * BIG_BLOCK_SIZE
,
844 NO_DBG_PRINT_BLOCK(aucFpage
, BIG_BLOCK_SIZE
);
845 iRun
= (int)ucGetByte(0x1ff, aucFpage
);
847 for (iIndex2
= 0; iIndex2
< iRun
; iIndex2
++) {
848 ulCharPos
= ulGetLong(iIndex2
* 4, aucFpage
);
849 ulFileOffset
= ulCharPos
;
850 iFodo
= 2 * (int)ucGetByte(
851 (iRun
+ 1) * 4 + iIndex2
, aucFpage
);
853 tChrLen
= (size_t)ucGetByte(iFodo
, aucFpage
);
855 usIstd
= usGetIstd(ulFileOffset
);
856 vFillFontFromStylesheet(usIstd
, &tFont
);
858 if (iWordVersion
== 1) {
860 aucFpage
+ 1, tChrLen
, &tFont
);
861 } else if (iWordVersion
== 2) {
863 aucFpage
+ 1, tChrLen
, &tFont
);
866 tFont
.ulFileOffset
= ulFileOffset
;
867 vAdd2FontInfoList(&tFont
);
873 (void)memset(&tPicture
, 0, sizeof(tPicture
));
874 bSuccess1
= iWordVersion
== 1 &&
875 bGet1PicInfo(iFodo
, aucFpage
+ 1,
877 bSuccess2
= iWordVersion
== 2 &&
878 bGet2PicInfo(iFodo
, aucFpage
+ 1,
880 if (bSuccess1
|| bSuccess2
) {
881 tPicture
.ulFileOffset
= ulFileOffset
;
882 tPicture
.ulFileOffsetPicture
=
883 tPicture
.ulPictureOffset
;
884 vAdd2PictInfoList(&tPicture
);
888 ausCharPage
= xfree(ausCharPage
);
889 } /* end of vGet2ChrInfo */