Imported from antiword-0.34.tar.gz.
[antiword.git] / prop6.c
blobe96ed271f33e7da849d4c742ab786ff0908e40bc
1 /*
2 * prop6.c
3 * Copyright (C) 1998-2003 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 UINT uiIndex;
71 int iFodoOff, iInfoLen, iSize, iTmp;
72 USHORT usCcol;
73 UCHAR ucTmp;
75 fail(aucGrpprl == NULL || pSection == NULL);
77 iFodoOff = 0;
78 while (tBytes >= (size_t)iFodoOff + 1) {
79 iInfoLen = 0;
80 switch (ucGetByte(iFodoOff, aucGrpprl)) {
81 case 133: /* olstAnm */
82 iSize = (int)ucGetByte(iFodoOff + 1, aucGrpprl);
83 DBG_DEC_C(iSize != 212, iSize);
84 for (uiIndex = 0, iTmp = iFodoOff + 2;
85 uiIndex < 9 && iTmp < iFodoOff + 2 + iSize - 15;
86 uiIndex++, iTmp += 16) {
87 pSection->aucNFC[uiIndex] =
88 ucGetByte(iTmp, aucGrpprl);
89 NO_DBG_DEC(pSection->aucNFC[uiIndex]);
90 ucTmp = ucGetByte(iTmp + 3, aucGrpprl);
91 NO_DBG_HEX(ucTmp);
92 if ((ucTmp & BIT(2)) != 0) {
93 pSection->usNeedPrevLvl |=
94 (USHORT)BIT(uiIndex);
96 if ((ucTmp & BIT(3)) != 0) {
97 pSection->usHangingIndent |=
98 (USHORT)BIT(uiIndex);
101 DBG_HEX(pSection->usNeedPrevLvl);
102 DBG_HEX(pSection->usHangingIndent);
103 break;
104 case 142: /* bkc */
105 ucTmp = ucGetByte(iFodoOff + 1, aucGrpprl);
106 DBG_DEC(ucTmp);
107 pSection->bNewPage = ucTmp != 0 && ucTmp != 1;
108 break;
109 case 144: /* ccolM1 */
110 usCcol = 1 + usGetWord(iFodoOff + 1, aucGrpprl);
111 DBG_DEC(usCcol);
112 break;
113 default:
114 break;
116 if (iInfoLen <= 0) {
117 iInfoLen = iGet6InfoLength(iFodoOff, aucGrpprl);
118 fail(iInfoLen <= 0);
120 iFodoOff += iInfoLen;
122 } /* end of vGet6SectionInfo */
125 * Build the lists with Section Property Information for Word 6/7 files
127 void
128 vGet6SepInfo(FILE *pFile, ULONG ulStartBlock,
129 const ULONG *aulBBD, size_t tBBDLen,
130 const UCHAR *aucHeader)
132 section_block_type tSection;
133 ULONG *aulSectPage, *aulTextOffset;
134 UCHAR *aucBuffer, *aucFpage;
135 ULONG ulBeginSectInfo;
136 size_t tSectInfoLen, tOffset, tLen, tBytes;
137 int iIndex;
138 UCHAR aucTmp[2];
140 fail(pFile == NULL || aucHeader == NULL);
141 fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
142 fail(aulBBD == NULL);
144 ulBeginSectInfo = ulGetLong(0x88, aucHeader); /* fcPlcfsed */
145 DBG_HEX(ulBeginSectInfo);
146 tSectInfoLen = (size_t)ulGetLong(0x8c, aucHeader); /* lcbPlcfsed */
147 DBG_DEC(tSectInfoLen);
148 if (tSectInfoLen < 4) {
149 DBG_DEC(tSectInfoLen);
150 return;
153 aucBuffer = xmalloc(tSectInfoLen);
154 if (!bReadBuffer(pFile, ulStartBlock,
155 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
156 aucBuffer, ulBeginSectInfo, tSectInfoLen)) {
157 aucBuffer = xfree(aucBuffer);
158 return;
160 NO_DBG_PRINT_BLOCK(aucBuffer, tSectInfoLen);
162 /* Read the Section Descriptors */
163 tLen = (tSectInfoLen - 4) / 16;
164 /* Save the section offsets */
165 aulTextOffset = xcalloc(tLen, sizeof(ULONG));
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 = xcalloc(tLen, sizeof(ULONG));
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 USHORT usTmp;
225 BOOL bFound24_0, bFound24_1, bFound25_0, bFound25_1, bFound190;
227 fail(iFodo < 0 || aucGrpprl == NULL || pRow == NULL);
229 iFodoOff = 0;
230 bFound24_0 = FALSE;
231 bFound24_1 = FALSE;
232 bFound25_0 = FALSE;
233 bFound25_1 = FALSE;
234 bFound190 = FALSE;
235 while (iBytes >= iFodoOff + 1) {
236 iInfoLen = 0;
237 switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) {
238 case 24: /* fIntable */
239 if (odd(ucGetByte(iFodo + iFodoOff + 1, aucGrpprl))) {
240 bFound24_1 = TRUE;
241 } else {
242 bFound24_0 = TRUE;
244 break;
245 case 25: /* fTtp */
246 if (odd(ucGetByte(iFodo + iFodoOff + 1, aucGrpprl))) {
247 bFound25_1 = TRUE;
248 } else {
249 bFound25_0 = TRUE;
251 break;
252 case 38: /* brcTop */
253 usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
254 usTmp &= 0x0018;
255 NO_DBG_DEC(usTmp >> 3);
256 if (usTmp == 0) {
257 pRow->ucBorderInfo &= ~TABLE_BORDER_TOP;
258 } else {
259 pRow->ucBorderInfo |= TABLE_BORDER_TOP;
261 break;
262 case 39: /* brcLeft */
263 usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
264 usTmp &= 0x0018;
265 NO_DBG_DEC(usTmp >> 3);
266 if (usTmp == 0) {
267 pRow->ucBorderInfo &= ~TABLE_BORDER_LEFT;
268 } else {
269 pRow->ucBorderInfo |= TABLE_BORDER_LEFT;
271 break;
272 case 40: /* brcBottom */
273 usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
274 usTmp &= 0x0018;
275 NO_DBG_DEC(usTmp >> 3);
276 if (usTmp == 0) {
277 pRow->ucBorderInfo &= ~TABLE_BORDER_BOTTOM;
278 } else {
279 pRow->ucBorderInfo |= TABLE_BORDER_BOTTOM;
281 break;
282 case 41: /* brcRight */
283 usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
284 usTmp &= 0x0018;
285 NO_DBG_DEC(usTmp >> 3);
286 if (usTmp == 0) {
287 pRow->ucBorderInfo &= ~TABLE_BORDER_RIGHT;
288 } else {
289 pRow->ucBorderInfo |= TABLE_BORDER_RIGHT;
291 break;
292 case 190: /* cDefTable */
293 iSize = (int)usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
294 if (iSize < 6 || iBytes < iFodoOff + 7) {
295 DBG_DEC(iSize);
296 DBG_DEC(iFodoOff);
297 iInfoLen = 1;
298 break;
300 iCol = (int)ucGetByte(iFodo + iFodoOff + 3, aucGrpprl);
301 if (iCol < 1 ||
302 iBytes < iFodoOff + 3 + (iCol + 1) * 2) {
303 DBG_DEC(iCol);
304 DBG_DEC(iFodoOff);
305 iInfoLen = 1;
306 break;
308 if (iCol >= (int)elementsof(pRow->asColumnWidth)) {
309 DBG_DEC(iCol);
310 werr(1, "The number of columns is corrupt");
312 pRow->ucNumberOfColumns = (UCHAR)iCol;
313 pRow->iColumnWidthSum = 0;
314 iPosPrev = (int)(short)usGetWord(
315 iFodo + iFodoOff + 4,
316 aucGrpprl);
317 for (iIndex = 0; iIndex < iCol; iIndex++) {
318 iPosCurr = (int)(short)usGetWord(
319 iFodo + iFodoOff + 6 + iIndex * 2,
320 aucGrpprl);
321 pRow->asColumnWidth[iIndex] =
322 (short)(iPosCurr - iPosPrev);
323 pRow->iColumnWidthSum +=
324 pRow->asColumnWidth[iIndex];
325 iPosPrev = iPosCurr;
327 bFound190 = TRUE;
328 break;
329 default:
330 break;
332 if (iInfoLen <= 0) {
333 iInfoLen =
334 iGet6InfoLength(iFodo + iFodoOff, aucGrpprl);
335 fail(iInfoLen <= 0);
337 iFodoOff += iInfoLen;
339 if (bFound24_1 && bFound25_1 && bFound190) {
340 return found_end_of_row;
342 if (bFound24_0 && bFound25_0 && !bFound190) {
343 return found_not_end_of_row;
345 if (bFound24_1) {
346 return found_a_cell;
348 if (bFound24_0) {
349 return found_not_a_cell;
351 return found_nothing;
352 } /* end of eGet6RowInfo */
355 * Fill the style information block with information
356 * from a Word 6/7 file.
358 void
359 vGet6StyleInfo(int iFodo,
360 const UCHAR *aucGrpprl, int iBytes, style_block_type *pStyle)
362 int iFodoOff, iInfoLen;
363 int iTmp, iDel, iAdd, iBefore;
364 short sTmp;
365 UCHAR ucTmp;
367 fail(iFodo < 0 || aucGrpprl == NULL || pStyle == NULL);
369 NO_DBG_DEC(pStyle->usIstd);
371 iFodoOff = 0;
372 while (iBytes >= iFodoOff + 1) {
373 iInfoLen = 0;
374 switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) {
375 case 2: /* istd */
376 sTmp = (short)ucGetByte(
377 iFodo + iFodoOff + 1, aucGrpprl);
378 NO_DBG_DEC(sTmp);
379 break;
380 case 5: /* jc */
381 pStyle->ucAlignment = ucGetByte(
382 iFodo + iFodoOff + 1, aucGrpprl);
383 break;
384 case 12: /* anld */
385 iTmp = (int)ucGetByte(
386 iFodo + iFodoOff + 1, aucGrpprl);
387 DBG_DEC_C(iTmp < 52, iTmp);
388 if (iTmp >= 1) {
389 pStyle->ucNFC = ucGetByte(
390 iFodo + iFodoOff + 2, aucGrpprl);
392 if (pStyle->ucNFC != LIST_BULLETS && iTmp >= 2) {
393 iBefore = (int)ucGetByte(
394 iFodo + iFodoOff + 3, aucGrpprl);
395 } else {
396 iBefore = 0;
398 if (iTmp >= 12) {
399 pStyle->usStartAt = usGetWord(
400 iFodo + iFodoOff + 12, aucGrpprl);
402 if (iTmp >= iBefore + 21) {
403 pStyle->usListChar = (USHORT)ucGetByte(
404 iFodo + iFodoOff + iBefore + 22,
405 aucGrpprl);
406 NO_DBG_HEX(pStyle->usListChar);
408 break;
409 case 13: /* nLvlAnm */
410 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
411 pStyle->ucNumLevel = ucTmp;
412 pStyle->bNumPause =
413 eGetNumType(ucTmp) == level_type_pause;
414 break;
415 case 15: /* ChgTabsPapx */
416 iTmp = (int)ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
417 if (iTmp < 2) {
418 iInfoLen = 1;
419 break;
421 NO_DBG_DEC(iTmp);
422 iDel = (int)ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
423 if (iTmp < 2 + 2 * iDel) {
424 iInfoLen = 1;
425 break;
427 NO_DBG_DEC(iDel);
428 iAdd = (int)ucGetByte(
429 iFodo + iFodoOff + 3 + 2 * iDel, aucGrpprl);
430 if (iTmp < 2 + 2 * iDel + 2 * iAdd) {
431 iInfoLen = 1;
432 break;
434 NO_DBG_DEC(iAdd);
435 break;
436 case 16: /* dxaRight */
437 pStyle->sRightIndent = (short)usGetWord(
438 iFodo + iFodoOff + 1, aucGrpprl);
439 NO_DBG_DEC(pStyle->sRightIndent);
440 break;
441 case 17: /* dxaLeft */
442 pStyle->sLeftIndent = (short)usGetWord(
443 iFodo + iFodoOff + 1, aucGrpprl);
444 NO_DBG_DEC(pStyle->sLeftIndent);
445 break;
446 case 18: /* Nest dxaLeft */
447 sTmp = (short)usGetWord(
448 iFodo + iFodoOff + 1, aucGrpprl);
449 pStyle->sLeftIndent += sTmp;
450 if (pStyle->sLeftIndent < 0) {
451 pStyle->sLeftIndent = 0;
453 NO_DBG_DEC(sTmp);
454 NO_DBG_DEC(pStyle->sLeftIndent);
455 break;
456 case 19: /* dxaLeft1 */
457 pStyle->sLeftIndent1 = (short)usGetWord(
458 iFodo + iFodoOff + 1, aucGrpprl);
459 NO_DBG_DEC(pStyle->sLeftIndent1);
460 break;
461 case 21: /* dyaBefore */
462 pStyle->usBeforeIndent = usGetWord(
463 iFodo + iFodoOff + 1, aucGrpprl);
464 NO_DBG_DEC(pStyle->usBeforeIndent);
465 break;
466 case 22: /* dyaAfter */
467 pStyle->usAfterIndent = usGetWord(
468 iFodo + iFodoOff + 1, aucGrpprl);
469 NO_DBG_DEC(pStyle->usAfterIndent);
470 break;
471 default:
472 break;
474 if (iInfoLen <= 0) {
475 iInfoLen =
476 iGet6InfoLength(iFodo + iFodoOff, aucGrpprl);
477 fail(iInfoLen <= 0);
479 iFodoOff += iInfoLen;
481 } /* end of vGet6StyleInfo */
484 * Build the lists with Paragraph Information for Word 6/7 files
486 void
487 vGet6PapInfo(FILE *pFile, ULONG ulStartBlock,
488 const ULONG *aulBBD, size_t tBBDLen,
489 const UCHAR *aucHeader)
491 row_block_type tRow;
492 style_block_type tStyle;
493 USHORT *ausParfPage;
494 UCHAR *aucBuffer;
495 ULONG ulCharPos, ulCharPosFirst, ulCharPosLast;
496 ULONG ulBeginParfInfo;
497 size_t tParfInfoLen, tParfPageNum, tOffset, tSize, tLenOld, tLen;
498 int iIndex, iIndex2, iRun, iFodo, iLen;
499 row_info_enum eRowInfo;
500 USHORT usParfFirstPage, usCount, usIstd;
501 UCHAR aucFpage[BIG_BLOCK_SIZE];
503 fail(pFile == NULL || aucHeader == NULL);
504 fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
505 fail(aulBBD == NULL);
507 ulBeginParfInfo = ulGetLong(0xc0, aucHeader); /* fcPlcfbtePapx */
508 NO_DBG_HEX(ulBeginParfInfo);
509 tParfInfoLen = (size_t)ulGetLong(0xc4, aucHeader); /* lcbPlcfbtePapx */
510 NO_DBG_DEC(tParfInfoLen);
511 if (tParfInfoLen < 4) {
512 DBG_DEC(tParfInfoLen);
513 return;
516 aucBuffer = xmalloc(tParfInfoLen);
517 if (!bReadBuffer(pFile, ulStartBlock,
518 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
519 aucBuffer, ulBeginParfInfo, tParfInfoLen)) {
520 aucBuffer = xfree(aucBuffer);
521 return;
523 NO_DBG_PRINT_BLOCK(aucBuffer, tParfInfoLen);
525 tLen = (tParfInfoLen - 4) / 6;
526 ausParfPage = xcalloc(tLen, sizeof(USHORT));
527 for (iIndex = 0, tOffset = (tLen + 1) * 4;
528 iIndex < (int)tLen;
529 iIndex++, tOffset += 2) {
530 ausParfPage[iIndex] = usGetWord(tOffset, aucBuffer);
531 NO_DBG_DEC(ausParfPage[iIndex]);
533 DBG_HEX(ulGetLong(0, aucBuffer));
534 aucBuffer = xfree(aucBuffer);
535 tParfPageNum = (size_t)usGetWord(0x190, aucHeader); /* cpnBtePap */
536 DBG_DEC(tParfPageNum);
537 if (tLen < tParfPageNum) {
538 /* Replace ParfPage by a longer version */
539 tLenOld = tLen;
540 usParfFirstPage = usGetWord(0x18c, aucHeader); /* pnPapFirst */
541 DBG_DEC(usParfFirstPage);
542 tLen += tParfPageNum - 1;
543 tSize = tLen * sizeof(USHORT);
544 ausParfPage = xrealloc(ausParfPage, tSize);
545 /* Add new values */
546 usCount = usParfFirstPage + 1;
547 for (iIndex = (int)tLenOld; iIndex < (int)tLen; iIndex++) {
548 ausParfPage[iIndex] = usCount;
549 NO_DBG_DEC(ausParfPage[iIndex]);
550 usCount++;
554 (void)memset(&tRow, 0, sizeof(tRow));
555 ulCharPosFirst = CP_INVALID;
556 for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
557 if (!bReadBuffer(pFile, ulStartBlock,
558 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
559 aucFpage,
560 (ULONG)ausParfPage[iIndex] * BIG_BLOCK_SIZE,
561 BIG_BLOCK_SIZE)) {
562 break;
564 iRun = (int)ucGetByte(0x1ff, aucFpage);
565 NO_DBG_DEC(iRun);
566 for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
567 NO_DBG_HEX(ulGetLong(iIndex2 * 4, aucFpage));
568 iFodo = 2 * (int)ucGetByte(
569 (iRun + 1) * 4 + iIndex2 * 7, aucFpage);
570 if (iFodo <= 0) {
571 continue;
574 iLen = 2 * (int)ucGetByte(iFodo, aucFpage);
576 usIstd = (USHORT)ucGetByte(iFodo + 1, aucFpage);
577 vFillStyleFromStylesheet(usIstd, &tStyle);
578 vGet6StyleInfo(iFodo, aucFpage + 3, iLen - 3, &tStyle);
579 ulCharPos = ulGetLong(iIndex2 * 4, aucFpage);
580 NO_DBG_HEX(ulCharPos);
581 tStyle.ulFileOffset = ulCharPos2FileOffset(ulCharPos);
582 vAdd2StyleInfoList(&tStyle);
584 eRowInfo = eGet6RowInfo(iFodo,
585 aucFpage + 3, iLen - 3, &tRow);
586 switch(eRowInfo) {
587 case found_a_cell:
588 if (ulCharPosFirst != CP_INVALID) {
589 break;
591 ulCharPosFirst = ulGetLong(
592 iIndex2 * 4, aucFpage);
593 NO_DBG_HEX(ulCharPosFirst);
594 tRow.ulCharPosStart = ulCharPosFirst;
595 tRow.ulFileOffsetStart =
596 ulCharPos2FileOffset(ulCharPosFirst);
597 DBG_HEX_C(tRow.ulFileOffsetStart == FC_INVALID,
598 ulCharPosFirst);
599 break;
600 case found_end_of_row:
601 ulCharPosLast = ulGetLong(
602 iIndex2 * 4, aucFpage);
603 NO_DBG_HEX(ulCharPosLast);
604 tRow.ulCharPosEnd = ulCharPosLast;
605 tRow.ulFileOffsetEnd = ulCharPos2FileOffset(
606 ulCharPosLast);
607 DBG_HEX_C(tRow.ulFileOffsetEnd == FC_INVALID,
608 ulCharPosLast);
609 vAdd2RowInfoList(&tRow);
610 (void)memset(&tRow, 0, sizeof(tRow));
611 ulCharPosFirst = CP_INVALID;
612 break;
613 case found_nothing:
614 break;
615 default:
616 DBG_DEC(eRowInfo);
617 break;
621 ausParfPage = xfree(ausParfPage);
622 } /* end of vGet6PapInfo */
625 * Fill the font information block with information
626 * from a Word 6/7 file.
627 * Returns TRUE when successful, otherwise FALSE
629 void
630 vGet6FontInfo(int iFodo, USHORT usIstd,
631 const UCHAR *aucGrpprl, int iBytes, font_block_type *pFont)
633 long lTmp;
634 int iFodoOff, iInfoLen;
635 USHORT usTmp;
636 UCHAR ucTmp;
638 fail(iFodo < 0 || aucGrpprl == NULL || pFont == NULL);
640 iFodoOff = 0;
641 while (iBytes >= iFodoOff + 1) {
642 switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) {
643 case 65: /* fRMarkDel */
644 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
645 if (ucTmp == 0) {
646 pFont->usFontStyle &= ~FONT_MARKDEL;
647 } else {
648 pFont->usFontStyle |= FONT_MARKDEL;
650 break;
651 case 80: /* cIstd */
652 usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
653 NO_DBG_DEC(usTmp);
654 break;
655 case 82: /* cDefault */
656 pFont->usFontStyle &= FONT_HIDDEN;
657 pFont->ucFontColor = FONT_COLOR_DEFAULT;
658 break;
659 case 83: /* cPlain */
660 DBG_MSG("83: cPlain");
661 vFillFontFromStylesheet(usIstd, pFont);
662 break;
663 case 85: /* fBold */
664 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
665 switch (ucTmp) {
666 case 0: /* Unset */
667 pFont->usFontStyle &= ~FONT_BOLD;
668 break;
669 case 1: /* Set */
670 pFont->usFontStyle |= FONT_BOLD;
671 break;
672 case 128: /* Unchanged */
673 break;
674 case 129: /* Negation */
675 pFont->usFontStyle ^= FONT_BOLD;
676 break;
677 default:
678 DBG_DEC(ucTmp);
679 DBG_FIXME();
680 break;
682 break;
683 case 86: /* fItalic */
684 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
685 switch (ucTmp) {
686 case 0: /* Unset */
687 pFont->usFontStyle &= ~FONT_ITALIC;
688 break;
689 case 1: /* Set */
690 pFont->usFontStyle |= FONT_ITALIC;
691 break;
692 case 128: /* Unchanged */
693 break;
694 case 129: /* Negation */
695 pFont->usFontStyle ^= FONT_ITALIC;
696 break;
697 default:
698 DBG_DEC(ucTmp);
699 DBG_FIXME();
700 break;
702 break;
703 case 87: /* fStrike */
704 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
705 switch (ucTmp) {
706 case 0: /* Unset */
707 pFont->usFontStyle &= ~FONT_STRIKE;
708 break;
709 case 1: /* Set */
710 pFont->usFontStyle |= FONT_STRIKE;
711 break;
712 case 128: /* Unchanged */
713 break;
714 case 129: /* Negation */
715 pFont->usFontStyle ^= FONT_STRIKE;
716 break;
717 default:
718 DBG_DEC(ucTmp);
719 DBG_FIXME();
720 break;
722 break;
723 case 90: /* fSmallCaps */
724 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
725 switch (ucTmp) {
726 case 0: /* Unset */
727 pFont->usFontStyle &= ~FONT_SMALL_CAPITALS;
728 break;
729 case 1: /* Set */
730 pFont->usFontStyle |= FONT_SMALL_CAPITALS;
731 break;
732 case 128: /* Unchanged */
733 break;
734 case 129: /* Negation */
735 pFont->usFontStyle ^= FONT_SMALL_CAPITALS;
736 break;
737 default:
738 DBG_DEC(ucTmp);
739 DBG_FIXME();
740 break;
742 break;
743 case 91: /* fCaps */
744 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
745 switch (ucTmp) {
746 case 0: /* Unset */
747 pFont->usFontStyle &= ~FONT_CAPITALS;
748 break;
749 case 1: /* Set */
750 pFont->usFontStyle |= FONT_CAPITALS;
751 break;
752 case 128: /* Unchanged */
753 break;
754 case 129: /* Negation */
755 pFont->usFontStyle ^= FONT_CAPITALS;
756 break;
757 default:
758 DBG_DEC(ucTmp);
759 DBG_FIXME();
760 break;
762 break;
763 case 92: /* fVanish */
764 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
765 switch (ucTmp) {
766 case 0: /* Unset */
767 pFont->usFontStyle &= ~FONT_HIDDEN;
768 break;
769 case 1: /* Set */
770 pFont->usFontStyle |= FONT_HIDDEN;
771 break;
772 case 128: /* Unchanged */
773 break;
774 case 129: /* Negation */
775 pFont->usFontStyle ^= FONT_HIDDEN;
776 break;
777 default:
778 DBG_DEC(ucTmp);
779 DBG_FIXME();
780 break;
782 break;
783 case 93: /* cFtc */
784 usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
785 if (usTmp <= (USHORT)UCHAR_MAX) {
786 pFont->ucFontNumber = (UCHAR)usTmp;
787 } else {
788 pFont->ucFontNumber = 0;
790 break;
791 case 94: /* cKul */
792 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
793 if (ucTmp == 0 || ucTmp == 5) {
794 pFont->usFontStyle &= ~FONT_UNDERLINE;
795 } else {
796 NO_DBG_MSG("Underline text");
797 pFont->usFontStyle |= FONT_UNDERLINE;
798 if (ucTmp == 6) {
799 DBG_MSG("Bold text");
800 pFont->usFontStyle |= FONT_BOLD;
803 break;
804 case 95: /* cHps, cHpsPos */
805 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
806 if (ucTmp != 0) {
807 pFont->usFontSize = (USHORT)ucTmp;
809 DBG_DEC(ucTmp);
810 break;
811 case 98: /* cIco */
812 pFont->ucFontColor =
813 ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
814 break;
815 case 99: /* cHps */
816 pFont->usFontSize =
817 usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
818 break;
819 case 104: /* cIss */
820 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
821 ucTmp &= 0x07;
822 if (ucTmp == 1) {
823 pFont->usFontStyle |= FONT_SUPERSCRIPT;
824 NO_DBG_MSG("Superscript");
825 } else if (ucTmp == 2) {
826 pFont->usFontStyle |= FONT_SUBSCRIPT;
827 NO_DBG_MSG("Subscript");
829 break;
830 case 106: /* cHps */
831 usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl);
832 lTmp = (long)pFont->usFontSize + (long)usTmp;
833 if (lTmp < 8) {
834 pFont->usFontSize = 8;
835 } else if (lTmp > 32766) {
836 pFont->usFontSize = 32766;
837 } else {
838 pFont->usFontSize = (USHORT)lTmp;
840 break;
841 default:
842 break;
844 iInfoLen = iGet6InfoLength(iFodo + iFodoOff, aucGrpprl);
845 fail(iInfoLen <= 0);
846 iFodoOff += iInfoLen;
848 } /* end of vGet6FontInfo */
851 * Fill the picture information block with information
852 * from a Word 6/7 file.
853 * Returns TRUE when successful, otherwise FALSE
855 static BOOL
856 bGet6PicInfo(int iFodo,
857 const UCHAR *aucGrpprl, int iBytes, picture_block_type *pPicture)
859 int iFodoOff, iInfoLen;
860 BOOL bFound;
861 UCHAR ucTmp;
863 fail(iFodo < 0 || aucGrpprl == NULL || pPicture == NULL);
865 iFodoOff = 0;
866 bFound = FALSE;
867 while (iBytes >= iFodoOff + 1) {
868 switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) {
869 case 68: /* fcPic */
870 pPicture->ulPictureOffset = ulGetLong(
871 iFodo + iFodoOff + 2, aucGrpprl);
872 bFound = TRUE;
873 break;
874 case 71: /* dttm */
875 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
876 if (ucTmp == 0x01) {
877 /* Not a picture, but a form field */
878 return FALSE;
880 DBG_DEC_C(ucTmp != 0, ucTmp);
881 break;
882 case 75: /* fOle2 */
883 ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl);
884 if (ucTmp == 0x01) {
885 /* Not a picture, but an OLE object */
886 return FALSE;
888 DBG_DEC_C(ucTmp != 0, ucTmp);
889 break;
890 default:
891 break;
893 iInfoLen = iGet6InfoLength(iFodo + iFodoOff, aucGrpprl);
894 fail(iInfoLen <= 0);
895 iFodoOff += iInfoLen;
897 return bFound;
898 } /* end of bGet6PicInfo */
901 * Build the lists with Character Information for Word 6/7 files
903 void
904 vGet6ChrInfo(FILE *pFile, ULONG ulStartBlock,
905 const ULONG *aulBBD, size_t tBBDLen, const UCHAR *aucHeader)
907 font_block_type tFont;
908 picture_block_type tPicture;
909 USHORT *ausCharPage;
910 UCHAR *aucBuffer;
911 ULONG ulFileOffset, ulCharPos, ulBeginCharInfo;
912 size_t tCharInfoLen, tOffset, tSize, tLenOld, tLen, tCharPageNum;
913 int iIndex, iIndex2, iRun, iFodo, iLen;
914 USHORT usCharFirstPage, usCount, usIstd;
915 UCHAR aucFpage[BIG_BLOCK_SIZE];
917 fail(pFile == NULL || aucHeader == NULL);
918 fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN);
919 fail(aulBBD == NULL);
921 ulBeginCharInfo = ulGetLong(0xb8, aucHeader); /* fcPlcfbteChpx */
922 NO_DBG_HEX(lBeginCharInfo);
923 tCharInfoLen = (size_t)ulGetLong(0xbc, aucHeader); /* lcbPlcfbteChpx */
924 NO_DBG_DEC(tCharInfoLen);
925 if (tCharInfoLen < 4) {
926 DBG_DEC(tCharInfoLen);
927 return;
930 aucBuffer = xmalloc(tCharInfoLen);
931 if (!bReadBuffer(pFile, ulStartBlock,
932 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
933 aucBuffer, ulBeginCharInfo, tCharInfoLen)) {
934 aucBuffer = xfree(aucBuffer);
935 return;
938 tLen = (tCharInfoLen - 4) / 6;
939 ausCharPage = xcalloc(tLen, sizeof(USHORT));
940 for (iIndex = 0, tOffset = (tLen + 1) * 4;
941 iIndex < (int)tLen;
942 iIndex++, tOffset += 2) {
943 ausCharPage[iIndex] = usGetWord(tOffset, aucBuffer);
944 NO_DBG_DEC(ausCharPage[iIndex]);
946 DBG_HEX(ulGetLong(0, aucBuffer));
947 aucBuffer = xfree(aucBuffer);
948 tCharPageNum = (size_t)usGetWord(0x18e, aucHeader); /* cpnBteChp */
949 DBG_DEC(tCharPageNum);
950 if (tLen < tCharPageNum) {
951 /* Replace CharPage by a longer version */
952 tLenOld = tLen;
953 usCharFirstPage = usGetWord(0x18a, aucHeader); /* pnChrFirst */
954 DBG_DEC(usCharFirstPage);
955 tLen += tCharPageNum - 1;
956 tSize = tLen * sizeof(USHORT);
957 ausCharPage = xrealloc(ausCharPage, tSize);
958 /* Add new values */
959 usCount = usCharFirstPage + 1;
960 for (iIndex = (int)tLenOld; iIndex < (int)tLen; iIndex++) {
961 ausCharPage[iIndex] = usCount;
962 NO_DBG_DEC(ausCharPage[iIndex]);
963 usCount++;
967 for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
968 if (!bReadBuffer(pFile, ulStartBlock,
969 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
970 aucFpage,
971 (ULONG)ausCharPage[iIndex] * BIG_BLOCK_SIZE,
972 BIG_BLOCK_SIZE)) {
973 break;
975 iRun = (int)ucGetByte(0x1ff, aucFpage);
976 NO_DBG_DEC(iRun);
977 for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
978 ulCharPos = ulGetLong(iIndex2 * 4, aucFpage);
979 ulFileOffset = ulCharPos2FileOffset(ulCharPos);
980 iFodo = 2 * (int)ucGetByte(
981 (iRun + 1) * 4 + iIndex2, aucFpage);
983 iLen = (int)ucGetByte(iFodo, aucFpage);
985 usIstd = usGetIstd(ulFileOffset);
986 vFillFontFromStylesheet(usIstd, &tFont);
987 if (iFodo != 0) {
988 vGet6FontInfo(iFodo, usIstd,
989 aucFpage + 1, iLen - 1, &tFont);
991 tFont.ulFileOffset = ulFileOffset;
992 vAdd2FontInfoList(&tFont);
994 if (iFodo <= 0) {
995 continue;
998 (void)memset(&tPicture, 0, sizeof(tPicture));
999 if (bGet6PicInfo(iFodo, aucFpage + 1,
1000 iLen - 1, &tPicture)) {
1001 tPicture.ulFileOffset = ulFileOffset;
1002 tPicture.ulFileOffsetPicture =
1003 ulDataPos2FileOffset(
1004 tPicture.ulPictureOffset);
1005 vAdd2PictInfoList(&tPicture);
1009 ausCharPage = xfree(ausCharPage);
1010 } /* end of vGet6ChrInfo */