Imported from antiword-0.33.tar.gz.
[antiword.git] / prop6.c
blobcdcd4bffeff1ff939fddf804478104bd9fb30fb3
1 /*
2 * prop6.c
3 * Copyright (C) 1998-2002 A.J. van Os; Released under GPL
5 * Description:
6 * Read the property information from a MS Word 6 or 7 file
7 */
9 #include <stdlib.h>
10 #include <string.h>
11 #include "antiword.h"
15 * iGet6InfoLength - the length of the information for Word 6/7 files
17 static int
18 iGet6InfoLength(int iByteNbr, const UCHAR *aucGrpprl)
20 int iTmp, iDel, iAdd;
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:
33 case 197: case 198:
34 return 1 + 2;
35 case 3: case 12: case 15: case 81: case 103: case 108: case 188:
36 case 190: case 191:
37 return 2 + (int)ucGetByte(iByteNbr + 1, aucGrpprl);
38 case 20: case 70: case 74: case 192: case 194: case 196: case 200:
39 return 1 + 4;
40 case 23:
41 iTmp = (int)ucGetByte(iByteNbr + 1, aucGrpprl);
42 if (iTmp == 255) {
43 iDel = (int)ucGetByte(iByteNbr + 2, aucGrpprl);
44 iAdd = (int)ucGetByte(
45 iByteNbr + 3 + iDel * 4, aucGrpprl);
46 iTmp = 2 + iDel * 4 + iAdd * 3;
48 return 2 + iTmp;
49 case 68: case 193: case 199:
50 return 1 + 5;
51 case 73: case 95: case 136: case 137:
52 return 1 + 3;
53 case 120:
54 return 1 + 13;
55 case 187:
56 return 1 + 12;
57 default:
58 return 1 + 1;
60 } /* end of iGet6InfoLength */
63 * Fill the section information block with information
64 * from a Word 6/7 file.
66 static void
67 vGet6SectionInfo(const UCHAR *aucGrpprl, size_t tBytes,
68 section_block_type *pSection)
70 int iFodoOff, iInfoLen, iSize, iIndex, iTmp;
71 USHORT usCcol;
72 UCHAR ucTmp;
74 fail(aucGrpprl == NULL || pSection == NULL);
76 iFodoOff = 0;
77 while (tBytes >= (size_t)iFodoOff + 1) {
78 iInfoLen = 0;
79 switch (ucGetByte(iFodoOff, aucGrpprl)) {
80 case 133: /* olstAnm */
81 iSize = (int)ucGetByte(iFodoOff + 1, aucGrpprl);
82 DBG_DEC_C(iSize != 212, iSize);
83 for (iIndex = 0, iTmp = iFodoOff + 2;
84 iIndex < 9 && iTmp < iFodoOff + 2 + iSize - 15;
85 iIndex++, iTmp += 16) {
86 pSection->aucNFC[iIndex] =
87 ucGetByte(iTmp, aucGrpprl);
88 DBG_DEC(pSection->aucNFC[iIndex]);
89 ucTmp = ucGetByte(iTmp + 3, aucGrpprl);
90 DBG_HEX(ucTmp);
91 if ((ucTmp & BIT(2)) != 0) {
92 pSection->usNeedPrevLvl |=
93 (USHORT)BIT(iIndex);
95 if ((ucTmp & BIT(3)) != 0) {
96 pSection->usHangingIndent |=
97 (USHORT)BIT(iIndex);
100 DBG_HEX(pSection->usNeedPrevLvl);
101 DBG_HEX(pSection->usHangingIndent);
102 break;
103 case 142: /* bkc */
104 ucTmp = ucGetByte(iFodoOff + 1, aucGrpprl);
105 DBG_DEC(ucTmp);
106 pSection->bNewPage = ucTmp != 0 && ucTmp != 1;
107 break;
108 case 144: /* ccolM1 */
109 usCcol = 1 + usGetWord(iFodoOff + 1, aucGrpprl);
110 DBG_DEC(usCcol);
111 break;
112 default:
113 break;
115 if (iInfoLen <= 0) {
116 iInfoLen = iGet6InfoLength(iFodoOff, aucGrpprl);
117 fail(iInfoLen <= 0);
119 iFodoOff += iInfoLen;
121 } /* end of vGet6SectionInfo */
124 * Build the lists with Section Property Information for Word 6/7 files
126 void
127 vGet6SepInfo(FILE *pFile, ULONG ulStartBlock,
128 const ULONG *aulBBD, size_t tBBDLen,
129 const UCHAR *aucHeader)
131 section_block_type tSection;
132 ULONG *aulSectPage, *aulTextOffset;
133 UCHAR *aucBuffer, *aucFpage;
134 ULONG ulBeginSectInfo;
135 size_t tSectInfoLen, tOffset, tSize, tLen, tBytes;
136 int iIndex;
137 UCHAR aucTmp[2];
139 fail(pFile == NULL || aucHeader == NULL);
140 fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
141 fail(aulBBD == NULL);
143 ulBeginSectInfo = ulGetLong(0x88, aucHeader); /* fcPlcfsed */
144 DBG_HEX(ulBeginSectInfo);
145 tSectInfoLen = (size_t)ulGetLong(0x8c, aucHeader); /* lcbPlcfsed */
146 DBG_DEC(tSectInfoLen);
147 if (tSectInfoLen < 4) {
148 DBG_DEC(tSectInfoLen);
149 return;
152 aucBuffer = xmalloc(tSectInfoLen);
153 if (!bReadBuffer(pFile, ulStartBlock,
154 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
155 aucBuffer, ulBeginSectInfo, tSectInfoLen)) {
156 aucBuffer = xfree(aucBuffer);
157 return;
159 NO_DBG_PRINT_BLOCK(aucBuffer, tSectInfoLen);
161 /* Read the Section Descriptors */
162 tLen = (tSectInfoLen - 4) / 16;
163 tSize = tLen * sizeof(ULONG);
164 /* Save the section offsets */
165 aulTextOffset = xmalloc(tSize);
166 for (iIndex = 0, tOffset = 0;
167 iIndex < (int)tLen;
168 iIndex++, tOffset += 4) {
169 aulTextOffset[iIndex] = ulGetLong(tOffset, aucBuffer);
171 /* Save the Sepx offsets */
172 aulSectPage = xmalloc(tSize);
173 for (iIndex = 0, tOffset = (tLen + 1) * 4;
174 iIndex < (int)tLen;
175 iIndex++, tOffset += 12) {
176 aulSectPage[iIndex] = ulGetLong(tOffset + 2, aucBuffer);
177 NO_DBG_HEX(aulSectPage[iIndex]); /* fcSepx */
179 aucBuffer = xfree(aucBuffer);
181 /* Read the Section Properties */
182 for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
183 if (aulSectPage[iIndex] == FC_INVALID) {
184 vDefault2SectionInfoList(aulTextOffset[iIndex]);
185 continue;
187 /* Get the number of bytes to read */
188 if (!bReadBuffer(pFile, ulStartBlock,
189 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
190 aucTmp, aulSectPage[iIndex], 2)) {
191 continue;
193 tBytes = 2 + (size_t)usGetWord(0, aucTmp);
194 NO_DBG_DEC(tBytes);
195 /* Read the bytes */
196 aucFpage = xmalloc(tBytes);
197 if (!bReadBuffer(pFile, ulStartBlock,
198 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
199 aucFpage, aulSectPage[iIndex], tBytes)) {
200 aucFpage = xfree(aucFpage);
201 continue;
203 NO_DBG_PRINT_BLOCK(aucFpage, tBytes);
204 /* Process the bytes */
205 vGetDefaultSection(&tSection);
206 vGet6SectionInfo(aucFpage + 2, tBytes - 2, &tSection);
207 vAdd2SectionInfoList(&tSection, aulTextOffset[iIndex]);
208 aucFpage = xfree(aucFpage);
210 aulTextOffset = xfree(aulTextOffset);
211 aulSectPage = xfree(aulSectPage);
212 } /* end of vGet6SepInfo */
215 * Translate the rowinfo to a member of the row_info enumeration
217 row_info_enum
218 eGet6RowInfo(int iFodo,
219 const UCHAR *aucGrpprl, int iBytes, row_block_type *pRow)
221 int iFodoOff, iInfoLen;
222 int iIndex, iSize, iCol;
223 int iPosCurr, iPosPrev;
224 BOOL bFound24_0, bFound24_1, bFound25_0, bFound25_1, bFound190;
226 fail(iFodo < 0 || aucGrpprl == NULL || pRow == NULL);
228 iFodoOff = 0;
229 bFound24_0 = FALSE;
230 bFound24_1 = FALSE;
231 bFound25_0 = FALSE;
232 bFound25_1 = FALSE;
233 bFound190 = FALSE;
234 while (iBytes >= iFodoOff + 1) {
235 iInfoLen = 0;
236 switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) {
237 case 24: /* fIntable */
238 if (odd(ucGetByte(iFodo + iFodoOff + 1, aucGrpprl))) {
239 bFound24_1 = TRUE;
240 } else {
241 bFound24_0 = TRUE;
243 break;
244 case 25: /* fTtp */
245 if (odd(ucGetByte(iFodo + iFodoOff + 1, aucGrpprl))) {
246 bFound25_1 = TRUE;
247 } else {
248 bFound25_0 = TRUE;
250 break;
251 case 190: /* cDefTable */
252 iSize = (int)usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
253 if (iSize < 6 || iBytes < iFodoOff + 7) {
254 DBG_DEC(iSize);
255 DBG_DEC(iFodoOff);
256 iInfoLen = 1;
257 break;
259 iCol = (int)ucGetByte(iFodo + iFodoOff + 3, aucGrpprl);
260 if (iCol < 1 ||
261 iBytes < iFodoOff + 3 + (iCol + 1) * 2) {
262 DBG_DEC(iCol);
263 DBG_DEC(iFodoOff);
264 iInfoLen = 1;
265 break;
267 if (iCol >= (int)elementsof(pRow->asColumnWidth)) {
268 DBG_DEC(iCol);
269 werr(1, "The number of columns is corrupt");
271 pRow->ucNumberOfColumns = (UCHAR)iCol;
272 pRow->iColumnWidthSum = 0;
273 iPosPrev = (int)(short)usGetWord(
274 iFodo + iFodoOff + 4,
275 aucGrpprl);
276 for (iIndex = 0; iIndex < iCol; iIndex++) {
277 iPosCurr = (int)(short)usGetWord(
278 iFodo + iFodoOff + 6 + iIndex * 2,
279 aucGrpprl);
280 pRow->asColumnWidth[iIndex] =
281 (short)(iPosCurr - iPosPrev);
282 pRow->iColumnWidthSum +=
283 pRow->asColumnWidth[iIndex];
284 iPosPrev = iPosCurr;
286 bFound190 = TRUE;
287 break;
288 default:
289 break;
291 if (iInfoLen <= 0) {
292 iInfoLen =
293 iGet6InfoLength(iFodo + iFodoOff, aucGrpprl);
294 fail(iInfoLen <= 0);
296 iFodoOff += iInfoLen;
298 if (bFound24_1 && bFound25_1 && bFound190) {
299 return found_end_of_row;
301 if (bFound24_0 && bFound25_0 && !bFound190) {
302 return found_not_end_of_row;
304 if (bFound24_1) {
305 return found_a_cell;
307 if (bFound24_0) {
308 return found_not_a_cell;
310 return found_nothing;
311 } /* end of eGet6RowInfo */
314 * Fill the style information block with information
315 * from a Word 6/7 file.
317 void
318 vGet6StyleInfo(int iFodo,
319 const UCHAR *aucGrpprl, int iBytes, style_block_type *pStyle)
321 int iFodoOff, iInfoLen;
322 int iTmp, iDel, iAdd, iBefore;
323 short sTmp;
324 UCHAR ucTmp;
326 fail(iFodo < 0 || aucGrpprl == NULL || pStyle == NULL);
328 NO_DBG_DEC(pStyle->usIstd);
330 iFodoOff = 0;
331 while (iBytes >= iFodoOff + 1) {
332 iInfoLen = 0;
333 switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) {
334 case 2: /* istd */
335 sTmp = (short)ucGetByte(
336 iFodo + iFodoOff + 1, aucGrpprl);
337 NO_DBG_DEC(sTmp);
338 break;
339 case 5: /* jc */
340 pStyle->ucAlignment = ucGetByte(
341 iFodo + iFodoOff + 1, aucGrpprl);
342 break;
343 case 12: /* anld */
344 iTmp = (int)ucGetByte(
345 iFodo + iFodoOff + 1, aucGrpprl);
346 DBG_DEC_C(iTmp < 52, iTmp);
347 pStyle->bInList = TRUE;
348 if (iTmp >= 1) {
349 pStyle->ucNFC = ucGetByte(
350 iFodo + iFodoOff + 2, aucGrpprl);
352 if (pStyle->ucNFC != LIST_BULLETS && iTmp >= 2) {
353 iBefore = (int)ucGetByte(
354 iFodo + iFodoOff + 3, aucGrpprl);
355 } else {
356 iBefore = 0;
358 if (iTmp >= 12) {
359 pStyle->usStartAt = usGetWord(
360 iFodo + iFodoOff + 12, aucGrpprl);
362 if (iTmp >= iBefore + 21) {
363 pStyle->ucListCharacter = ucGetByte(
364 iFodo + iFodoOff + iBefore + 22,
365 aucGrpprl);
366 NO_DBG_CHR(pStyle->ucListCharacter);
368 break;
369 case 13: /* nLvlAnm */
370 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
371 pStyle->ucListLevel = ucTmp;
372 #if 0
373 if (iTmp == 0) {
374 pStyle->bNoNumbering = TRUE;
376 if (iTmp >= 12) {
377 pStyle->bNumPause = TRUE;
379 #else
380 if ((int)ucTmp == 0 || (int)ucTmp >= 12) {
381 pStyle->bNumPause = TRUE;
383 #endif
384 break;
385 case 15: /* ChgTabsPapx */
386 iTmp = (int)ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
387 if (iTmp < 2) {
388 iInfoLen = 1;
389 break;
391 NO_DBG_DEC(iTmp);
392 iDel = (int)ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
393 if (iTmp < 2 + 2 * iDel) {
394 iInfoLen = 1;
395 break;
397 NO_DBG_DEC(iDel);
398 iAdd = (int)ucGetByte(
399 iFodo + iFodoOff + 3 + 2 * iDel, aucGrpprl);
400 if (iTmp < 2 + 2 * iDel + 2 * iAdd) {
401 iInfoLen = 1;
402 break;
404 NO_DBG_DEC(iAdd);
405 break;
406 case 16: /* dxaRight */
407 pStyle->sRightIndent = (short)usGetWord(
408 iFodo + iFodoOff + 1, aucGrpprl);
409 NO_DBG_DEC(pStyle->sRightIndent);
410 break;
411 case 17: /* dxaLeft */
412 pStyle->sLeftIndent = (short)usGetWord(
413 iFodo + iFodoOff + 1, aucGrpprl);
414 NO_DBG_DEC(pStyle->sLeftIndent);
415 break;
416 case 18: /* Nest dxaLeft */
417 sTmp = (short)usGetWord(
418 iFodo + iFodoOff + 1, aucGrpprl);
419 pStyle->sLeftIndent += sTmp;
420 if (pStyle->sLeftIndent < 0) {
421 pStyle->sLeftIndent = 0;
423 NO_DBG_DEC(sTmp);
424 NO_DBG_DEC(pStyle->sLeftIndent);
425 break;
426 case 21: /* dyaBefore */
427 pStyle->usBeforeIndent = usGetWord(
428 iFodo + iFodoOff + 1, aucGrpprl);
429 NO_DBG_DEC(pStyle->usBeforeIndent);
430 break;
431 case 22: /* dyaAfter */
432 pStyle->usAfterIndent = usGetWord(
433 iFodo + iFodoOff + 1, aucGrpprl);
434 NO_DBG_DEC(pStyle->usAfterIndent);
435 break;
436 default:
437 break;
439 if (iInfoLen <= 0) {
440 iInfoLen =
441 iGet6InfoLength(iFodo + iFodoOff, aucGrpprl);
442 fail(iInfoLen <= 0);
444 iFodoOff += iInfoLen;
446 } /* end of vGet6StyleInfo */
449 * Build the lists with Paragraph Information for Word 6/7 files
451 void
452 vGet6PapInfo(FILE *pFile, ULONG ulStartBlock,
453 const ULONG *aulBBD, size_t tBBDLen,
454 const UCHAR *aucHeader)
456 row_block_type tRow;
457 style_block_type tStyle;
458 USHORT *ausParfPage;
459 UCHAR *aucBuffer;
460 ULONG ulCharPos, ulCharPosFirst, ulCharPosLast;
461 ULONG ulBeginParfInfo;
462 size_t tParfInfoLen, tParfPageNum, tOffset, tSize, tLenOld, tLen;
463 int iIndex, iIndex2, iRun, iFodo, iLen;
464 row_info_enum eRowInfo;
465 USHORT usParfFirstPage, usCount, usIstd;
466 UCHAR aucFpage[BIG_BLOCK_SIZE];
468 fail(pFile == NULL || aucHeader == NULL);
469 fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
470 fail(aulBBD == NULL);
472 ulBeginParfInfo = ulGetLong(0xc0, aucHeader); /* fcPlcfbtePapx */
473 NO_DBG_HEX(ulBeginParfInfo);
474 tParfInfoLen = (size_t)ulGetLong(0xc4, aucHeader); /* lcbPlcfbtePapx */
475 NO_DBG_DEC(tParfInfoLen);
476 if (tParfInfoLen < 4) {
477 DBG_DEC(tParfInfoLen);
478 return;
481 aucBuffer = xmalloc(tParfInfoLen);
482 if (!bReadBuffer(pFile, ulStartBlock,
483 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
484 aucBuffer, ulBeginParfInfo, tParfInfoLen)) {
485 aucBuffer = xfree(aucBuffer);
486 return;
488 NO_DBG_PRINT_BLOCK(aucBuffer, tParfInfoLen);
490 tLen = (tParfInfoLen - 4) / 6;
491 tSize = tLen * sizeof(USHORT);
492 ausParfPage = xmalloc(tSize);
493 for (iIndex = 0, tOffset = (tLen + 1) * 4;
494 iIndex < (int)tLen;
495 iIndex++, tOffset += 2) {
496 ausParfPage[iIndex] = usGetWord(tOffset, aucBuffer);
497 NO_DBG_DEC(ausParfPage[iIndex]);
499 DBG_HEX(ulGetLong(0, aucBuffer));
500 aucBuffer = xfree(aucBuffer);
501 tParfPageNum = (size_t)usGetWord(0x190, aucHeader); /* cpnBtePap */
502 DBG_DEC(tParfPageNum);
503 if (tLen < tParfPageNum) {
504 /* Replace ParfPage by a longer version */
505 tLenOld = tLen;
506 usParfFirstPage = usGetWord(0x18c, aucHeader); /* pnPapFirst */
507 DBG_DEC(usParfFirstPage);
508 tLen += tParfPageNum - 1;
509 tSize = tLen * sizeof(USHORT);
510 ausParfPage = xrealloc(ausParfPage, tSize);
511 /* Add new values */
512 usCount = usParfFirstPage + 1;
513 for (iIndex = (int)tLenOld; iIndex < (int)tLen; iIndex++) {
514 ausParfPage[iIndex] = usCount;
515 NO_DBG_DEC(ausParfPage[iIndex]);
516 usCount++;
520 (void)memset(&tRow, 0, sizeof(tRow));
521 ulCharPosFirst = CP_INVALID;
522 for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
523 if (!bReadBuffer(pFile, ulStartBlock,
524 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
525 aucFpage,
526 (ULONG)ausParfPage[iIndex] * BIG_BLOCK_SIZE,
527 BIG_BLOCK_SIZE)) {
528 break;
530 iRun = (int)ucGetByte(0x1ff, aucFpage);
531 NO_DBG_DEC(iRun);
532 for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
533 NO_DBG_HEX(ulGetLong(iIndex2 * 4, aucFpage));
534 iFodo = 2 * (int)ucGetByte(
535 (iRun + 1) * 4 + iIndex2 * 7, aucFpage);
536 if (iFodo <= 0) {
537 continue;
540 iLen = 2 * (int)ucGetByte(iFodo, aucFpage);
542 usIstd = (USHORT)ucGetByte(iFodo + 1, aucFpage);
543 vFillStyleFromStylesheet(usIstd, &tStyle);
544 vGet6StyleInfo(iFodo, aucFpage + 3, iLen - 3, &tStyle);
545 ulCharPos = ulGetLong(iIndex2 * 4, aucFpage);
546 NO_DBG_HEX(ulCharPos);
547 tStyle.ulFileOffset = ulCharPos2FileOffset(ulCharPos);
548 vAdd2StyleInfoList(&tStyle);
550 eRowInfo = eGet6RowInfo(iFodo,
551 aucFpage + 3, iLen - 3, &tRow);
552 switch(eRowInfo) {
553 case found_a_cell:
554 if (ulCharPosFirst != CP_INVALID) {
555 break;
557 ulCharPosFirst = ulGetLong(
558 iIndex2 * 4, aucFpage);
559 NO_DBG_HEX(ulCharPosFirst);
560 tRow.ulCharPosStart = ulCharPosFirst;
561 tRow.ulFileOffsetStart =
562 ulCharPos2FileOffset(ulCharPosFirst);
563 DBG_HEX_C(tRow.ulFileOffsetStart == FC_INVALID,
564 ulCharPosFirst);
565 break;
566 case found_end_of_row:
567 ulCharPosLast = ulGetLong(
568 iIndex2 * 4, aucFpage);
569 NO_DBG_HEX(ulCharPosLast);
570 tRow.ulCharPosEnd = ulCharPosLast;
571 tRow.ulFileOffsetEnd = ulCharPos2FileOffset(
572 ulCharPosLast);
573 DBG_HEX_C(tRow.ulFileOffsetEnd == FC_INVALID,
574 ulCharPosLast);
575 vAdd2RowInfoList(&tRow);
576 (void)memset(&tRow, 0, sizeof(tRow));
577 ulCharPosFirst = CP_INVALID;
578 break;
579 case found_nothing:
580 break;
581 default:
582 DBG_DEC(eRowInfo);
583 break;
587 ausParfPage = xfree(ausParfPage);
588 } /* end of vGet6PapInfo */
591 * Fill the font information block with information
592 * from a Word 6/7 file.
593 * Returns TRUE when successful, otherwise FALSE
595 void
596 vGet6FontInfo(int iFodo, USHORT usIstd,
597 const UCHAR *aucGrpprl, int iBytes, font_block_type *pFont)
599 long lTmp;
600 int iFodoOff, iInfoLen;
601 USHORT usTmp;
602 short sTmp;
603 UCHAR ucTmp;
605 fail(iFodo < 0 || aucGrpprl == NULL || pFont == NULL);
607 iFodoOff = 0;
608 while (iBytes >= iFodoOff + 1) {
609 switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) {
610 case 65: /* fRMarkDel */
611 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
612 if (ucTmp == 0) {
613 pFont->ucFontstyle &= ~FONT_MARKDEL;
614 } else {
615 pFont->ucFontstyle |= FONT_MARKDEL;
617 break;
618 case 80: /* cIstd */
619 usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
620 NO_DBG_DEC(usTmp);
621 break;
622 case 82: /* cDefault */
623 pFont->ucFontstyle &= FONT_HIDDEN;
624 pFont->ucFontcolor = FONT_COLOR_DEFAULT;
625 break;
626 case 83: /* cPlain */
627 DBG_MSG("83: cPlain");
628 vFillFontFromStylesheet(usIstd, pFont);
629 break;
630 case 85: /* fBold */
631 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
632 switch (ucTmp) {
633 case 0: /* Unset */
634 pFont->ucFontstyle &= ~FONT_BOLD;
635 break;
636 case 1: /* Set */
637 pFont->ucFontstyle |= FONT_BOLD;
638 break;
639 case 128: /* Unchanged */
640 break;
641 case 129: /* Negation */
642 pFont->ucFontstyle ^= FONT_BOLD;
643 break;
644 default:
645 DBG_DEC(ucTmp);
646 DBG_FIXME();
647 break;
649 break;
650 case 86: /* fItalic */
651 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
652 switch (ucTmp) {
653 case 0: /* Unset */
654 pFont->ucFontstyle &= ~FONT_ITALIC;
655 break;
656 case 1: /* Set */
657 pFont->ucFontstyle |= FONT_ITALIC;
658 break;
659 case 128: /* Unchanged */
660 break;
661 case 129: /* Negation */
662 pFont->ucFontstyle ^= FONT_ITALIC;
663 break;
664 default:
665 DBG_DEC(ucTmp);
666 DBG_FIXME();
667 break;
669 break;
670 case 87: /* fStrike */
671 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
672 switch (ucTmp) {
673 case 0: /* Unset */
674 pFont->ucFontstyle &= ~FONT_STRIKE;
675 break;
676 case 1: /* Set */
677 pFont->ucFontstyle |= FONT_STRIKE;
678 break;
679 case 128: /* Unchanged */
680 break;
681 case 129: /* Negation */
682 pFont->ucFontstyle ^= FONT_STRIKE;
683 break;
684 default:
685 DBG_DEC(ucTmp);
686 DBG_FIXME();
687 break;
689 break;
690 case 90: /* fSmallCaps */
691 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
692 switch (ucTmp) {
693 case 0: /* Unset */
694 pFont->ucFontstyle &= ~FONT_SMALL_CAPITALS;
695 break;
696 case 1: /* Set */
697 pFont->ucFontstyle |= FONT_SMALL_CAPITALS;
698 break;
699 case 128: /* Unchanged */
700 break;
701 case 129: /* Negation */
702 pFont->ucFontstyle ^= FONT_SMALL_CAPITALS;
703 break;
704 default:
705 DBG_DEC(ucTmp);
706 DBG_FIXME();
707 break;
709 break;
710 case 91: /* fCaps */
711 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
712 switch (ucTmp) {
713 case 0: /* Unset */
714 pFont->ucFontstyle &= ~FONT_CAPITALS;
715 break;
716 case 1: /* Set */
717 pFont->ucFontstyle |= FONT_CAPITALS;
718 break;
719 case 128: /* Unchanged */
720 break;
721 case 129: /* Negation */
722 pFont->ucFontstyle ^= FONT_CAPITALS;
723 break;
724 default:
725 DBG_DEC(ucTmp);
726 DBG_FIXME();
727 break;
729 break;
730 case 92: /* fVanish */
731 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
732 switch (ucTmp) {
733 case 0: /* Unset */
734 pFont->ucFontstyle &= ~FONT_HIDDEN;
735 break;
736 case 1: /* Set */
737 pFont->ucFontstyle |= FONT_HIDDEN;
738 break;
739 case 128: /* Unchanged */
740 break;
741 case 129: /* Negation */
742 pFont->ucFontstyle ^= FONT_HIDDEN;
743 break;
744 default:
745 DBG_DEC(ucTmp);
746 DBG_FIXME();
747 break;
749 break;
750 case 93: /* cFtc */
751 usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
752 if (usTmp <= (USHORT)UCHAR_MAX) {
753 pFont->ucFontnumber = (UCHAR)usTmp;
754 } else {
755 pFont->ucFontnumber = 0;
757 break;
758 case 94: /* cKul */
759 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
760 if (ucTmp == 0 || ucTmp == 5) {
761 pFont->ucFontstyle &= ~FONT_UNDERLINE;
762 } else {
763 NO_DBG_MSG("Underline text");
764 pFont->ucFontstyle |= FONT_UNDERLINE;
765 if (ucTmp == 6) {
766 DBG_MSG("Bold text");
767 pFont->ucFontstyle |= FONT_BOLD;
770 break;
771 case 95: /* cHps, cHpsPos */
772 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
773 if (ucTmp != 0) {
774 pFont->sFontsize = (short)ucTmp;
776 DBG_DEC(ucTmp);
777 break;
778 case 98: /* cIco */
779 pFont->ucFontcolor =
780 ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
781 break;
782 case 99: /* cHps */
783 usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
784 if (usTmp > (USHORT)SHRT_MAX) {
785 pFont->sFontsize = SHRT_MAX;
786 } else {
787 pFont->sFontsize = (short)usTmp;
789 break;
790 case 104: /* cIss */
791 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
792 ucTmp &= 0x07;
793 DBG_MSG_C(ucTmp == 1, "Superscript");
794 DBG_MSG_C(ucTmp == 2, "Subscript");
795 break;
796 case 106: /* cHps */
797 sTmp = (short)usGetWord(
798 iFodo + iFodoOff + 1, aucGrpprl);
799 lTmp = (long)pFont->sFontsize + (long)sTmp;
800 if (lTmp < 8) {
801 pFont->sFontsize = 8;
802 } else if (lTmp > 32766) {
803 pFont->sFontsize = 32766;
804 } else {
805 pFont->sFontsize = (short)lTmp;
807 break;
808 default:
809 break;
811 iInfoLen = iGet6InfoLength(iFodo + iFodoOff, aucGrpprl);
812 fail(iInfoLen <= 0);
813 iFodoOff += iInfoLen;
815 } /* end of vGet6FontInfo */
818 * Fill the picture information block with information
819 * from a Word 6/7 file.
820 * Returns TRUE when successful, otherwise FALSE
822 static BOOL
823 bGet6PicInfo(int iFodo,
824 const UCHAR *aucGrpprl, int iBytes, picture_block_type *pPicture)
826 int iFodoOff, iInfoLen;
827 BOOL bFound;
828 UCHAR ucTmp;
830 fail(iFodo < 0 || aucGrpprl == NULL || pPicture == NULL);
832 iFodoOff = 0;
833 bFound = FALSE;
834 while (iBytes >= iFodoOff + 1) {
835 switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) {
836 case 68: /* fcPic */
837 pPicture->ulPictureOffset = ulGetLong(
838 iFodo + iFodoOff + 2, aucGrpprl);
839 bFound = TRUE;
840 break;
841 case 71: /* dttm */
842 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
843 if (ucTmp == 0x01) {
844 /* Not a picture, but a form field */
845 return FALSE;
847 DBG_DEC_C(ucTmp != 0, ucTmp);
848 break;
849 case 75: /* fOle2 */
850 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
851 if (ucTmp == 0x01) {
852 /* Not a picture, but an OLE object */
853 return FALSE;
855 DBG_DEC_C(ucTmp != 0, ucTmp);
856 break;
857 default:
858 break;
860 iInfoLen = iGet6InfoLength(iFodo + iFodoOff, aucGrpprl);
861 fail(iInfoLen <= 0);
862 iFodoOff += iInfoLen;
864 return bFound;
865 } /* end of bGet6PicInfo */
868 * Build the lists with Character Information for Word 6/7 files
870 void
871 vGet6ChrInfo(FILE *pFile, ULONG ulStartBlock,
872 const ULONG *aulBBD, size_t tBBDLen, const UCHAR *aucHeader)
874 font_block_type tFont;
875 picture_block_type tPicture;
876 USHORT *ausCharPage;
877 UCHAR *aucBuffer;
878 ULONG ulFileOffset, ulCharPos, ulBeginCharInfo;
879 size_t tCharInfoLen, tOffset, tSize, tLenOld, tLen, tCharPageNum;
880 int iIndex, iIndex2, iRun, iFodo, iLen;
881 USHORT usCharFirstPage, usCount, usIstd;
882 UCHAR aucFpage[BIG_BLOCK_SIZE];
884 fail(pFile == NULL || aucHeader == NULL);
885 fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
886 fail(aulBBD == NULL);
888 ulBeginCharInfo = ulGetLong(0xb8, aucHeader); /* fcPlcfbteChpx */
889 NO_DBG_HEX(lBeginCharInfo);
890 tCharInfoLen = (size_t)ulGetLong(0xbc, aucHeader); /* lcbPlcfbteChpx */
891 NO_DBG_DEC(tCharInfoLen);
892 if (tCharInfoLen < 4) {
893 DBG_DEC(tCharInfoLen);
894 return;
897 aucBuffer = xmalloc(tCharInfoLen);
898 if (!bReadBuffer(pFile, ulStartBlock,
899 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
900 aucBuffer, ulBeginCharInfo, tCharInfoLen)) {
901 aucBuffer = xfree(aucBuffer);
902 return;
905 tLen = (tCharInfoLen - 4) / 6;
906 tSize = tLen * sizeof(USHORT);
907 ausCharPage = xmalloc(tSize);
908 for (iIndex = 0, tOffset = (tLen + 1) * 4;
909 iIndex < (int)tLen;
910 iIndex++, tOffset += 2) {
911 ausCharPage[iIndex] = usGetWord(tOffset, aucBuffer);
912 NO_DBG_DEC(ausCharPage[iIndex]);
914 DBG_HEX(ulGetLong(0, aucBuffer));
915 aucBuffer = xfree(aucBuffer);
916 tCharPageNum = (size_t)usGetWord(0x18e, aucHeader); /* cpnBteChp */
917 DBG_DEC(tCharPageNum);
918 if (tLen < tCharPageNum) {
919 /* Replace CharPage by a longer version */
920 tLenOld = tLen;
921 usCharFirstPage = usGetWord(0x18a, aucHeader); /* pnChrFirst */
922 DBG_DEC(usCharFirstPage);
923 tLen += tCharPageNum - 1;
924 tSize = tLen * sizeof(USHORT);
925 ausCharPage = xrealloc(ausCharPage, tSize);
926 /* Add new values */
927 usCount = usCharFirstPage + 1;
928 for (iIndex = (int)tLenOld; iIndex < (int)tLen; iIndex++) {
929 ausCharPage[iIndex] = usCount;
930 NO_DBG_DEC(ausCharPage[iIndex]);
931 usCount++;
935 for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
936 if (!bReadBuffer(pFile, ulStartBlock,
937 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
938 aucFpage,
939 (ULONG)ausCharPage[iIndex] * BIG_BLOCK_SIZE,
940 BIG_BLOCK_SIZE)) {
941 break;
943 iRun = (int)ucGetByte(0x1ff, aucFpage);
944 NO_DBG_DEC(iRun);
945 for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
946 ulCharPos = ulGetLong(iIndex2 * 4, aucFpage);
947 ulFileOffset = ulCharPos2FileOffset(ulCharPos);
948 iFodo = 2 * (int)ucGetByte(
949 (iRun + 1) * 4 + iIndex2, aucFpage);
951 iLen = (int)ucGetByte(iFodo, aucFpage);
953 usIstd = usGetIstd(ulFileOffset);
954 vFillFontFromStylesheet(usIstd, &tFont);
955 if (iFodo != 0) {
956 vGet6FontInfo(iFodo, usIstd,
957 aucFpage + 1, iLen - 1, &tFont);
959 tFont.ulFileOffset = ulFileOffset;
960 vAdd2FontInfoList(&tFont);
962 if (iFodo <= 0) {
963 continue;
966 (void)memset(&tPicture, 0, sizeof(tPicture));
967 if (bGet6PicInfo(iFodo, aucFpage + 1,
968 iLen - 1, &tPicture)) {
969 tPicture.ulFileOffset = ulFileOffset;
970 tPicture.ulFileOffsetPicture =
971 ulDataPos2FileOffset(
972 tPicture.ulPictureOffset);
973 vAdd2PictInfoList(&tPicture);
977 ausCharPage = xfree(ausCharPage);
978 } /* end of vGet6ChrInfo */