Imported from antiword-0.37.tar.gz.
[antiword.git] / prop8.c
blobc31204e08fa0602b0a73854ea601df08a0d5a691
1 /*
2 * prop8.c
3 * Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
5 * Description:
6 * Read the property information from a MS Word 8, 9,10 or 11 file
8 * Word 8 is better known as Word 97 or as Word 98 for Mac
9 * Word 9 is better known as Word 2000 or as Word 2001 for Mac
10 * Word 10 is better known as Word 2002 or as Word XP
11 * Word 11 is better known as Word 2003
14 #include <stdlib.h>
15 #include <string.h>
16 #include "antiword.h"
18 #define DEFAULT_LISTCHAR 0x002e /* A full stop */
22 * iGet8InfoLength - the length of the information for Word 8/9/10/11 files
24 static int
25 iGet8InfoLength(int iByteNbr, const UCHAR *aucGrpprl)
27 int iTmp, iDel, iAdd;
28 USHORT usOpCode;
30 usOpCode = usGetWord(iByteNbr, aucGrpprl);
32 switch (usOpCode & 0xe000) {
33 case 0x0000: case 0x2000:
34 return 3;
35 case 0x4000: case 0x8000: case 0xa000:
36 return 4;
37 case 0xe000:
38 return 5;
39 case 0x6000:
40 return 6;
41 case 0xc000:
42 iTmp = (int)ucGetByte(iByteNbr + 2, aucGrpprl);
43 if (usOpCode == 0xc615 && iTmp == 255) {
44 iDel = (int)ucGetByte(iByteNbr + 3, aucGrpprl);
45 iAdd = (int)ucGetByte(
46 iByteNbr + 4 + iDel * 4, aucGrpprl);
47 iTmp = 2 + iDel * 4 + iAdd * 3;
49 return 3 + iTmp;
50 default:
51 DBG_HEX(usOpCode);
52 DBG_FIXME();
53 return 1;
55 } /* end of iGet8InfoLength */
58 * aucFillInfoBuffer - fill the information buffer
60 * Returns the information buffer when successful, otherwise NULL
62 static UCHAR *
63 aucFillInfoBuffer(FILE *pFile, const pps_type *pTable,
64 const ULONG *aulBBD, size_t tBBDLen,
65 const ULONG *aulSBD, size_t tSBDLen,
66 ULONG ulBeginInfo, size_t tInfoLen)
68 const ULONG *aulBlockDepot;
69 UCHAR *aucBuffer;
70 size_t tBlockDepotLen, tBlockSize;
72 fail(pFile == NULL || pTable == NULL);
73 fail(aulBBD == NULL || aulSBD == NULL);
74 fail(tInfoLen == 0);
76 NO_DBG_DEC(pTable->ulSB);
77 NO_DBG_HEX(pTable->ulSize);
78 if (pTable->ulSize == 0) {
79 DBG_MSG("No information");
80 return NULL;
83 if (pTable->ulSize < MIN_SIZE_FOR_BBD_USE) {
84 /* Use the Small Block Depot */
85 aulBlockDepot = aulSBD;
86 tBlockDepotLen = tSBDLen;
87 tBlockSize = SMALL_BLOCK_SIZE;
88 } else {
89 /* Use the Big Block Depot */
90 aulBlockDepot = aulBBD;
91 tBlockDepotLen = tBBDLen;
92 tBlockSize = BIG_BLOCK_SIZE;
94 aucBuffer = xmalloc(tInfoLen);
95 if (!bReadBuffer(pFile, pTable->ulSB,
96 aulBlockDepot, tBlockDepotLen, tBlockSize,
97 aucBuffer, ulBeginInfo, tInfoLen)) {
98 aucBuffer = xfree(aucBuffer);
99 return NULL;
101 return aucBuffer;
102 } /* end of aucFillInfoBuffer */
105 * Build the lists with Document Property Information for Word 8/9/10/11 files
107 void
108 vGet8DopInfo(FILE *pFile, const pps_type *pTable,
109 const ULONG *aulBBD, size_t tBBDLen,
110 const ULONG *aulSBD, size_t tSBDLen,
111 const UCHAR *aucHeader)
113 document_block_type tDocument;
114 UCHAR *aucBuffer;
115 ULONG ulBeginDocpInfo, ulTmp;
116 size_t tDocpInfoLen;
117 USHORT usTmp;
119 fail(pFile == NULL || pTable == NULL || aucHeader == NULL);
120 fail(aulBBD == NULL || aulSBD == NULL);
122 ulBeginDocpInfo = ulGetLong(0x192, aucHeader); /* fcDop */
123 NO_DBG_HEX(ulBeginSectInfo);
124 tDocpInfoLen = (size_t)ulGetLong(0x196, aucHeader); /* lcbDop */
125 NO_DBG_DEC(tSectInfoLen);
126 if (tDocpInfoLen < 28) {
127 DBG_MSG("No Document information");
128 return;
131 aucBuffer = aucFillInfoBuffer(pFile, pTable,
132 aulBBD, tBBDLen, aulSBD, tSBDLen,
133 ulBeginDocpInfo, tDocpInfoLen);
134 if (aucBuffer == NULL) {
135 return;
138 usTmp = usGetWord(0x00, aucBuffer);
139 tDocument.ucHdrFtrSpecification = (UCHAR)(usTmp >> 8); /* grpfIhdt */
140 tDocument.usDefaultTabWidth = usGetWord(0x0a, aucBuffer); /* dxaTab */
141 ulTmp = ulGetLong(0x14, aucBuffer); /* dttmCreated */
142 tDocument.tCreateDate = tConvertDTTM(ulTmp);
143 ulTmp = ulGetLong(0x18, aucBuffer); /* dttmRevised */
144 tDocument.tRevisedDate = tConvertDTTM(ulTmp);
145 vCreateDocumentInfoList(&tDocument);
147 aucBuffer = xfree(aucBuffer);
148 } /* end of vGet8DopInfo */
151 * Fill the section information block with information
152 * from a Word 8/9/10/11 file.
154 static void
155 vGet8SectionInfo(const UCHAR *aucGrpprl, size_t tBytes,
156 section_block_type *pSection)
158 UINT uiIndex;
159 int iFodoOff, iInfoLen, iSize, iTmp;
160 USHORT usCcol;
161 UCHAR ucTmp;
163 fail(aucGrpprl == NULL || pSection == NULL);
165 iFodoOff = 0;
166 while (tBytes >= (size_t)iFodoOff + 2) {
167 iInfoLen = 0;
168 switch (usGetWord(iFodoOff, aucGrpprl)) {
169 case 0x3009: /* bkc */
170 ucTmp = ucGetByte(iFodoOff + 2, aucGrpprl);
171 DBG_DEC(ucTmp);
172 pSection->bNewPage = ucTmp != 0 && ucTmp != 1;
173 break;
174 case 0x3014: /* grpfIhdt */
175 pSection->ucHdrFtrSpecification =
176 ucGetByte(iFodoOff + 2, aucGrpprl);
177 break;
178 case 0x500b: /* ccolM1 */
179 usCcol = 1 + usGetWord(iFodoOff + 2, aucGrpprl);
180 DBG_DEC(usCcol);
181 break;
182 case 0xd202: /* olstAnm */
183 iSize = (int)ucGetByte(iFodoOff + 2, aucGrpprl);
184 DBG_DEC_C(iSize != 212, iSize);
185 for (uiIndex = 0, iTmp = iFodoOff + 3;
186 uiIndex < 9 && iTmp < iFodoOff + 3 + iSize - 15;
187 uiIndex++, iTmp += 16) {
188 pSection->aucNFC[uiIndex] =
189 ucGetByte(iTmp, aucGrpprl);
190 DBG_DEC(pSection->aucNFC[uiIndex]);
191 ucTmp = ucGetByte(iTmp + 3, aucGrpprl);
192 DBG_HEX(ucTmp);
193 if ((ucTmp & BIT(2)) != 0) {
194 pSection->usNeedPrevLvl |=
195 (USHORT)BIT(uiIndex);
197 if ((ucTmp & BIT(3)) != 0) {
198 pSection->usHangingIndent |=
199 (USHORT)BIT(uiIndex);
202 DBG_HEX(pSection->usNeedPrevLvl);
203 DBG_HEX(pSection->usHangingIndent);
204 break;
205 default:
206 break;
208 if (iInfoLen <= 0) {
209 iInfoLen = iGet8InfoLength(iFodoOff, aucGrpprl);
210 fail(iInfoLen <= 0);
212 iFodoOff += iInfoLen;
214 } /* end of vGet8SectionInfo */
217 * Build the lists with Section Property Information for Word 8/9/10/11 files
219 void
220 vGet8SepInfo(FILE *pFile, const pps_info_type *pPPS,
221 const ULONG *aulBBD, size_t tBBDLen,
222 const ULONG *aulSBD, size_t tSBDLen,
223 const UCHAR *aucHeader)
225 section_block_type tSection;
226 ULONG *aulSectPage, *aulCharPos;
227 UCHAR *aucBuffer, *aucFpage;
228 ULONG ulBeginOfText, ulTextOffset, ulBeginSectInfo;
229 size_t tSectInfoLen, tIndex, tOffset, tLen, tBytes;
230 UCHAR aucTmp[2];
232 fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
233 fail(aulBBD == NULL || aulSBD == NULL);
235 ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
236 NO_DBG_HEX(ulBeginOfText);
237 ulBeginSectInfo = ulGetLong(0xca, aucHeader); /* fcPlcfsed */
238 NO_DBG_HEX(ulBeginSectInfo);
239 tSectInfoLen = (size_t)ulGetLong(0xce, aucHeader); /* lcbPlcfsed */
240 NO_DBG_DEC(tSectInfoLen);
241 if (tSectInfoLen < 4) {
242 DBG_DEC(tSectInfoLen);
243 return;
246 aucBuffer = aucFillInfoBuffer(pFile, &pPPS->tTable,
247 aulBBD, tBBDLen, aulSBD, tSBDLen,
248 ulBeginSectInfo, tSectInfoLen);
249 if (aucBuffer == NULL) {
250 return;
252 NO_DBG_PRINT_BLOCK(aucBuffer, tSectInfoLen);
254 /* Read the Section Descriptors */
255 tLen = (tSectInfoLen - 4) / 16;
256 /* Save the section offsets */
257 aulCharPos = xcalloc(tLen, sizeof(ULONG));
258 for (tIndex = 0, tOffset = 0;
259 tIndex < tLen;
260 tIndex++, tOffset += 4) {
261 ulTextOffset = ulGetLong(tOffset, aucBuffer);
262 NO_DBG_HEX(ulTextOffset);
263 aulCharPos[tIndex] = ulBeginOfText + ulTextOffset;
264 NO_DBG_HEX(aulCharPos[tIndex]);
266 /* Save the Sepx offsets */
267 aulSectPage = xcalloc(tLen, sizeof(ULONG));
268 for (tIndex = 0, tOffset = (tLen + 1) * 4;
269 tIndex < tLen;
270 tIndex++, tOffset += 12) {
271 aulSectPage[tIndex] = ulGetLong(tOffset + 2, aucBuffer);
272 NO_DBG_HEX(aulSectPage[tIndex]); /* fcSepx */
274 aucBuffer = xfree(aucBuffer);
276 /* Read the Section Properties */
277 for (tIndex = 0; tIndex < tLen; tIndex++) {
278 if (aulSectPage[tIndex] == FC_INVALID) {
279 vDefault2SectionInfoList(aulCharPos[tIndex]);
280 continue;
282 /* Get the number of bytes to read */
283 if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB,
284 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
285 aucTmp, aulSectPage[tIndex], 2)) {
286 continue;
288 tBytes = 2 + (size_t)usGetWord(0, aucTmp);
289 NO_DBG_DEC(tBytes);
290 /* Read the bytes */
291 aucFpage = xmalloc(tBytes);
292 if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB,
293 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
294 aucFpage, aulSectPage[tIndex], tBytes)) {
295 aucFpage = xfree(aucFpage);
296 continue;
298 NO_DBG_PRINT_BLOCK(aucFpage, tBytes);
299 /* Process the bytes */
300 vGetDefaultSection(&tSection);
301 vGet8SectionInfo(aucFpage + 2, tBytes - 2, &tSection);
302 vAdd2SectionInfoList(&tSection, aulCharPos[tIndex]);
303 aucFpage = xfree(aucFpage);
305 aulCharPos = xfree(aulCharPos);
306 aulSectPage = xfree(aulSectPage);
307 } /* end of vGet8SepInfo */
310 * Build the list with Header/Footer Information for Word 8/9/10/11 files
312 void
313 vGet8HdrFtrInfo(FILE *pFile, const pps_type *pTable,
314 const ULONG *aulBBD, size_t tBBDLen,
315 const ULONG *aulSBD, size_t tSBDLen,
316 const UCHAR *aucHeader)
318 ULONG *aulCharPos;
319 UCHAR *aucBuffer;
320 ULONG ulHdrFtrOffset, ulBeginHdrFtrInfo;
321 size_t tHdrFtrInfoLen, tIndex, tOffset, tLen;
323 fail(pFile == NULL || pTable == NULL || aucHeader == NULL);
324 fail(aulBBD == NULL || aulSBD == NULL);
326 ulBeginHdrFtrInfo = ulGetLong(0xf2, aucHeader); /* fcPlcfhdd */
327 NO_DBG_HEX(ulBeginHdrFtrInfo);
328 tHdrFtrInfoLen = (size_t)ulGetLong(0xf6, aucHeader); /* lcbPlcfhdd */
329 NO_DBG_DEC(tHdrFtrInfoLen);
330 if (tHdrFtrInfoLen < 8) {
331 DBG_DEC_C(tHdrFtrInfoLen != 0, tHdrFtrInfoLen);
332 return;
335 aucBuffer = aucFillInfoBuffer(pFile, pTable,
336 aulBBD, tBBDLen, aulSBD, tSBDLen,
337 ulBeginHdrFtrInfo, tHdrFtrInfoLen);
338 if (aucBuffer == NULL) {
339 return;
341 NO_DBG_PRINT_BLOCK(aucBuffer, tHdrFtrInfoLen);
343 tLen = tHdrFtrInfoLen / 4 - 1;
344 DBG_DEC_C(tLen % 12 != 1 && tLen % 12 != 7, tLen);
345 /* Save the header/footer offsets */
346 aulCharPos = xcalloc(tLen, sizeof(ULONG));
347 for (tIndex = 0, tOffset = 0;
348 tIndex < tLen;
349 tIndex++, tOffset += 4) {
350 ulHdrFtrOffset = ulGetLong(tOffset, aucBuffer);
351 NO_DBG_HEX(ulHdrFtrOffset);
352 aulCharPos[tIndex] = ulHdrFtrOffset2CharPos(ulHdrFtrOffset);
353 NO_DBG_HEX(aulCharPos[tIndex]);
355 vCreat8HdrFtrInfoList(aulCharPos, tLen);
356 /* Clean up and leave */
357 aulCharPos = xfree(aulCharPos);
358 aucBuffer = xfree(aucBuffer);
359 } /* end of vGet8HdrFtrInfo */
362 * Translate the rowinfo to a member of the row_info enumeration
364 row_info_enum
365 eGet8RowInfo(int iFodo,
366 const UCHAR *aucGrpprl, int iBytes, row_block_type *pRow)
368 int iFodoOff, iInfoLen;
369 int iIndex, iSize, iCol;
370 int iPosCurr, iPosPrev;
371 USHORT usTmp;
372 BOOL bFound2416_0, bFound2416_1, bFound2417_0, bFound2417_1;
373 BOOL bFound244b_0, bFound244b_1, bFound244c_0, bFound244c_1;
374 BOOL bFoundd608;
376 fail(iFodo < 0 || aucGrpprl == NULL || pRow == NULL);
378 iFodoOff = 0;
379 bFound2416_0 = FALSE;
380 bFound2416_1 = FALSE;
381 bFound2417_0 = FALSE;
382 bFound2417_1 = FALSE;
383 bFound244b_0 = FALSE;
384 bFound244b_1 = FALSE;
385 bFound244c_0 = FALSE;
386 bFound244c_1 = FALSE;
387 bFoundd608 = FALSE;
388 while (iBytes >= iFodoOff + 2) {
389 iInfoLen = 0;
390 switch (usGetWord(iFodo + iFodoOff, aucGrpprl)) {
391 case 0x2416: /* fInTable */
392 if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
393 bFound2416_1 = TRUE;
394 } else {
395 bFound2416_0 = TRUE;
397 break;
398 case 0x2417: /* fTtp */
399 if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
400 bFound2417_1 = TRUE;
401 } else {
402 bFound2417_0 = TRUE;
404 break;
405 case 0x244b: /* sub-table fInTable */
406 if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
407 bFound244b_1 = TRUE;
408 } else {
409 bFound244b_0 = TRUE;
411 break;
412 case 0x244c: /* sub-table fTtp */
413 if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
414 bFound244c_1 = TRUE;
415 } else {
416 bFound244c_0 = TRUE;
418 break;
419 case 0x6424: /* brcTop */
420 usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
421 usTmp &= 0xff00;
422 NO_DBG_DEC(usTmp >> 8);
423 if (usTmp == 0) {
424 pRow->ucBorderInfo &= ~TABLE_BORDER_TOP;
425 } else {
426 pRow->ucBorderInfo |= TABLE_BORDER_TOP;
428 break;
429 case 0x6425: /* brcLeft */
430 usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
431 usTmp &= 0xff00;
432 NO_DBG_DEC(usTmp >> 8);
433 if (usTmp == 0) {
434 pRow->ucBorderInfo &= ~TABLE_BORDER_LEFT;
435 } else {
436 pRow->ucBorderInfo |= TABLE_BORDER_LEFT;
438 break;
439 case 0x6426: /* brcBottom */
440 usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
441 usTmp &= 0xff00;
442 NO_DBG_DEC(usTmp >> 8);
443 if (usTmp == 0) {
444 pRow->ucBorderInfo &= ~TABLE_BORDER_BOTTOM;
445 } else {
446 pRow->ucBorderInfo |= TABLE_BORDER_BOTTOM;
448 break;
449 case 0x6427: /* brcRight */
450 usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
451 usTmp &= 0xff00;
452 NO_DBG_DEC(usTmp >> 8);
453 if (usTmp == 0) {
454 pRow->ucBorderInfo &= ~TABLE_BORDER_RIGHT;
455 } else {
456 pRow->ucBorderInfo |= TABLE_BORDER_RIGHT;
458 break;
459 case 0xd606: /* cDefTable10 */
460 DBG_MSG("0xd606: sprmTDefTable10");
461 iSize = (int)usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
462 DBG_DEC(iSize);
463 break;
464 case 0xd608: /* cDefTable */
465 iSize = (int)usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
466 if (iSize < 6 || iBytes < iFodoOff + 8) {
467 DBG_DEC(iSize);
468 DBG_DEC(iFodoOff);
469 iInfoLen = 2;
470 break;
472 iCol = (int)ucGetByte(iFodo + iFodoOff + 4, aucGrpprl);
473 if (iCol < 1 ||
474 iBytes < iFodoOff + 4 + (iCol + 1) * 2) {
475 DBG_DEC(iCol);
476 DBG_DEC(iFodoOff);
477 iInfoLen = 2;
478 break;
480 if (iCol >= (int)elementsof(pRow->asColumnWidth)) {
481 DBG_DEC(iCol);
482 werr(1, "The number of columns is corrupt");
484 pRow->ucNumberOfColumns = (UCHAR)iCol;
485 iPosPrev = (int)(short)usGetWord(
486 iFodo + iFodoOff + 5,
487 aucGrpprl);
488 for (iIndex = 0; iIndex < iCol; iIndex++) {
489 iPosCurr = (int)(short)usGetWord(
490 iFodo + iFodoOff + 7 + iIndex * 2,
491 aucGrpprl);
492 pRow->asColumnWidth[iIndex] =
493 (short)(iPosCurr - iPosPrev);
494 iPosPrev = iPosCurr;
496 bFoundd608 = TRUE;
497 break;
498 default:
499 break;
501 if (iInfoLen <= 0) {
502 iInfoLen =
503 iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
504 fail(iInfoLen <= 0);
506 iFodoOff += iInfoLen;
509 if (bFound2417_1 && bFoundd608) {
510 return found_end_of_row;
512 if (bFound2417_0 && !bFoundd608) {
513 return found_not_end_of_row;
515 if (bFound2416_1 || bFound244b_1) {
516 return found_a_cell;
518 if (bFound2416_0 || bFound244b_0) {
519 return found_not_a_cell;
521 return found_nothing;
522 } /* end of eGet8RowInfo */
525 * Fill the style information block with information
526 * from a Word 8/9/10/11 file.
528 void
529 vGet8StyleInfo(int iFodo,
530 const UCHAR *aucGrpprl, int iBytes, style_block_type *pStyle)
532 list_block_type tList6;
533 const list_block_type *pList;
534 int iFodoOff, iInfoLen;
535 int iTmp, iDel, iAdd, iBefore;
536 USHORT usOpCode, usTmp;
537 short sTmp;
539 fail(iFodo < 0 || aucGrpprl == NULL || pStyle == NULL);
541 NO_DBG_DEC_C(pStyle->usListIndex != 0, pStyle->usIstd);
542 NO_DBG_DEC_C(pStyle->usListIndex != 0, pStyle->usListIndex);
544 (void)memset(&tList6, 0, sizeof(tList6));
546 iFodoOff = 0;
547 while (iBytes >= iFodoOff + 2) {
548 iInfoLen = 0;
549 usOpCode = usGetWord(iFodo + iFodoOff, aucGrpprl);
550 switch (usOpCode) {
551 case 0x2403: /* jc */
552 pStyle->ucAlignment = ucGetByte(
553 iFodo + iFodoOff + 2, aucGrpprl);
554 break;
555 case 0x260a: /* ilvl */
556 pStyle->ucListLevel =
557 ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
558 NO_DBG_DEC(pStyle->ucListLevel);
559 pStyle->ucNumLevel = pStyle->ucListLevel;
560 break;
561 case 0x4600: /* istd */
562 usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
563 NO_DBG_DEC(usTmp);
564 break;
565 case 0x460b: /* ilfo */
566 pStyle->usListIndex =
567 usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
568 NO_DBG_DEC(pStyle->usListIndex);
569 break;
570 case 0x4610: /* Nest dxaLeft */
571 sTmp = (short)usGetWord(
572 iFodo + iFodoOff + 2, aucGrpprl);
573 pStyle->sLeftIndent += sTmp;
574 if (pStyle->sLeftIndent < 0) {
575 pStyle->sLeftIndent = 0;
577 DBG_DEC(sTmp);
578 DBG_DEC(pStyle->sLeftIndent);
579 break;
580 case 0xc60d: /* ChgTabsPapx */
581 case 0xc615: /* ChgTabs */
582 iTmp = (int)ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
583 if (iTmp < 2) {
584 iInfoLen = 1;
585 break;
587 NO_DBG_DEC(iTmp);
588 iDel = (int)ucGetByte(iFodo + iFodoOff + 3, aucGrpprl);
589 if (iTmp < 2 + 2 * iDel) {
590 iInfoLen = 1;
591 break;
593 NO_DBG_DEC(iDel);
594 iAdd = (int)ucGetByte(
595 iFodo + iFodoOff + 4 + 2 * iDel, aucGrpprl);
596 if (iTmp < 2 + 2 * iDel + 2 * iAdd) {
597 iInfoLen = 1;
598 break;
600 NO_DBG_DEC(iAdd);
601 break;
602 case 0x840e: /* dxaRight */
603 pStyle->sRightIndent = (short)usGetWord(
604 iFodo + iFodoOff + 2, aucGrpprl);
605 NO_DBG_DEC(pStyle->sRightIndent);
606 break;
607 case 0x840f: /* dxaLeft */
608 pStyle->sLeftIndent = (short)usGetWord(
609 iFodo + iFodoOff + 2, aucGrpprl);
610 NO_DBG_DEC(pStyle->sLeftIndent);
611 break;
612 case 0x8411: /* dxaLeft1 */
613 pStyle->sLeftIndent1 = (short)usGetWord(
614 iFodo + iFodoOff + 2, aucGrpprl);
615 NO_DBG_DEC(pStyle->sLeftIndent1);
616 break;
617 case 0xa413: /* dyaBefore */
618 pStyle->usBeforeIndent = usGetWord(
619 iFodo + iFodoOff + 2, aucGrpprl);
620 NO_DBG_DEC(pStyle->usBeforeIndent);
621 break;
622 case 0xa414: /* dyaAfter */
623 pStyle->usAfterIndent = usGetWord(
624 iFodo + iFodoOff + 2, aucGrpprl);
625 NO_DBG_DEC(pStyle->usAfterIndent);
626 break;
627 case 0xc63e: /* anld */
628 iTmp = (int)ucGetByte(
629 iFodo + iFodoOff + 2, aucGrpprl);
630 DBG_DEC_C(iTmp < 84, iTmp);
631 if (iTmp >= 1) {
632 tList6.ucNFC = ucGetByte(
633 iFodo + iFodoOff + 3, aucGrpprl);
635 if (tList6.ucNFC != LIST_BULLETS && iTmp >= 2) {
636 iBefore = (int)ucGetByte(
637 iFodo + iFodoOff + 4, aucGrpprl);
638 } else {
639 iBefore = 0;
641 if (iTmp >= 12) {
642 tList6.ulStartAt = (ULONG)usGetWord(
643 iFodo + iFodoOff + 13, aucGrpprl);
645 if (iTmp >= iBefore + 22) {
646 tList6.usListChar = usGetWord(
647 iFodo + iFodoOff + iBefore + 23,
648 aucGrpprl);
649 DBG_HEX(tList6.usListChar);
651 break;
652 default:
653 NO_DBG_HEX(usOpCode);
654 break;
656 if (iInfoLen <= 0) {
657 iInfoLen =
658 iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
659 fail(iInfoLen <= 0);
661 iFodoOff += iInfoLen;
664 if (pStyle->usListIndex == 2047) {
665 /* Old style list */
666 pStyle->usStartAt = (USHORT)tList6.ulStartAt;
667 pStyle->usListChar = tList6.usListChar;
668 pStyle->ucNFC = tList6.ucNFC;
669 } else {
670 /* New style list */
671 pList = pGetListInfo(pStyle->usListIndex, pStyle->ucListLevel);
672 if (pList != NULL) {
673 pStyle->bNoRestart = pList->bNoRestart;
674 fail(pList->ulStartAt > (ULONG)USHRT_MAX);
675 pStyle->usStartAt = (USHORT)pList->ulStartAt;
676 pStyle->usListChar = pList->usListChar;
677 pStyle->ucNFC = pList->ucNFC;
678 if (pStyle->sLeftIndent <= 0) {
679 pStyle->sLeftIndent = pList->sLeftIndent;
683 } /* end of vGet8StyleInfo */
686 * Get the left indentation value from the style information block
688 * Returns the value when found, otherwise 0
690 static short
691 sGetLeftIndent(const UCHAR *aucGrpprl, size_t tBytes)
693 int iOffset, iInfoLen;
694 USHORT usOpCode, usTmp;
696 fail(aucGrpprl == NULL);
698 iOffset = 0;
699 while (tBytes >= (size_t)iOffset + 4) {
700 usOpCode = usGetWord(iOffset, aucGrpprl);
701 if (usOpCode == 0x840f) { /* dxaLeft */
702 usTmp = usGetWord(iOffset + 2, aucGrpprl);
703 if (usTmp <= 0x7fff) {
704 NO_DBG_DEC(usTmp);
705 return (short)usTmp;
708 iInfoLen = iGet8InfoLength(iOffset, aucGrpprl);
709 fail(iInfoLen <= 0);
710 iOffset += iInfoLen;
712 return 0;
713 } /* end of sGetLeftIndent */
716 * Build the list with List Information for Word 8/9/10/11 files
718 void
719 vGet8LstInfo(FILE *pFile, const pps_info_type *pPPS,
720 const ULONG *aulBBD, size_t tBBDLen,
721 const ULONG *aulSBD, size_t tSBDLen,
722 const UCHAR *aucHeader)
724 list_block_type tList;
725 const ULONG *aulBlockDepot;
726 UCHAR *aucLfoInfo, *aucLstfInfo, *aucPapx, *aucXString;
727 ULONG ulBeginLfoInfo, ulBeginLstfInfo, ulBeginLvlfInfo;
728 ULONG ulListID, ulStart;
729 size_t tBlockDepotLen, tBlockSize;
730 size_t tLfoInfoLen, tLstfInfoLen, tPapxLen, tXstLen, tOff;
731 size_t tLstfRecords, tStart, tIndex;
732 int iNums;
733 USHORT usIstd;
734 UCHAR ucTmp, ucListLevel, ucMaxLevel, ucChpxLen;
735 UCHAR aucLvlfInfo[28], aucXst[2];
737 fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
738 fail(aulBBD == NULL || aulSBD == NULL);
740 NO_DBG_DEC(pPPS->tTable.ulSB);
741 NO_DBG_HEX(pPPS->tTable.ulSize);
742 if (pPPS->tTable.ulSize == 0) {
743 DBG_MSG("No list information");
744 return;
747 if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
748 /* Use the Small Block Depot */
749 aulBlockDepot = aulSBD;
750 tBlockDepotLen = tSBDLen;
751 tBlockSize = SMALL_BLOCK_SIZE;
752 } else {
753 /* Use the Big Block Depot */
754 aulBlockDepot = aulBBD;
755 tBlockDepotLen = tBBDLen;
756 tBlockSize = BIG_BLOCK_SIZE;
759 /* LFO (List Format Override) */
760 ulBeginLfoInfo = ulGetLong(0x2ea, aucHeader); /* fcPlfLfo */
761 DBG_HEX(ulBeginLfoInfo);
762 tLfoInfoLen = (size_t)ulGetLong(0x2ee, aucHeader); /* lcbPlfLfo */
763 DBG_DEC(tLfoInfoLen);
764 if (tLfoInfoLen == 0) {
765 DBG_MSG("No lists in this document");
766 return;
769 aucLfoInfo = xmalloc(tLfoInfoLen);
770 if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
771 aulBlockDepot, tBlockDepotLen, tBlockSize,
772 aucLfoInfo, ulBeginLfoInfo, tLfoInfoLen)) {
773 aucLfoInfo = xfree(aucLfoInfo);
774 return;
776 NO_DBG_PRINT_BLOCK(aucLfoInfo, tLfoInfoLen);
777 vBuildLfoList(aucLfoInfo, tLfoInfoLen);
778 aucLfoInfo = xfree(aucLfoInfo);
780 /* LSTF (LiST data on File) */
781 ulBeginLstfInfo = ulGetLong(0x2e2, aucHeader); /* fcPlcfLst */
782 DBG_HEX(ulBeginLstfInfo);
783 tLstfInfoLen = (size_t)ulGetLong(0x2e6, aucHeader); /* lcbPlcfLst */
784 DBG_DEC(tLstfInfoLen);
785 if (tLstfInfoLen == 0) {
786 DBG_MSG("No list data on file");
787 return;
790 aucLstfInfo = xmalloc(tLstfInfoLen);
791 if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
792 aulBlockDepot, tBlockDepotLen, tBlockSize,
793 aucLstfInfo, ulBeginLstfInfo, tLstfInfoLen)) {
794 aucLstfInfo = xfree(aucLstfInfo);
795 return;
797 NO_DBG_PRINT_BLOCK(aucLstfInfo, tLstfInfoLen);
799 tLstfRecords = (size_t)usGetWord(0, aucLstfInfo);
800 if (2 + tLstfRecords * 28 < tLstfInfoLen) {
801 DBG_DEC(2 + tLstfRecords * 28);
802 DBG_DEC(tLstfInfoLen);
803 aucLstfInfo = xfree(aucLstfInfo);
804 return;
807 /* LVLF (List leVeL on File) */
808 ulBeginLvlfInfo = ulBeginLstfInfo + tLstfInfoLen;
809 DBG_HEX(ulBeginLvlfInfo);
811 aucXString = NULL;
812 ulStart = ulBeginLvlfInfo;
814 for (tIndex = 0, tStart = 2;
815 tIndex < tLstfRecords;
816 tIndex++, tStart += 28) {
817 ulListID = ulGetLong(tStart, aucLstfInfo);
818 NO_DBG_HEX(ulListID);
819 ucTmp = ucGetByte(tStart + 26, aucLstfInfo);
820 ucMaxLevel = odd(ucTmp) ? 1 : 9;
821 for (ucListLevel = 0; ucListLevel < ucMaxLevel; ucListLevel++) {
822 fail(aucXString != NULL);
823 usIstd = usGetWord(
824 tStart + 8 + 2 * (size_t)ucListLevel,
825 aucLstfInfo);
826 DBG_DEC_C(usIstd != STI_NIL, usIstd);
827 NO_DBG_HEX(ulStart);
828 (void)memset(&tList, 0, sizeof(tList));
829 /* Read the lvlf (List leVeL on File) */
830 if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
831 aulBlockDepot, tBlockDepotLen,
832 tBlockSize, aucLvlfInfo,
833 ulStart, sizeof(aucLvlfInfo))) {
834 aucLstfInfo = xfree(aucLstfInfo);
835 return;
837 NO_DBG_PRINT_BLOCK(aucLvlfInfo, sizeof(aucLvlfInfo));
838 if (bAllZero(aucLvlfInfo, sizeof(aucLvlfInfo))) {
839 tList.ulStartAt = 1;
840 tList.ucNFC = 0x00;
841 tList.bNoRestart = FALSE;
842 } else {
843 tList.ulStartAt = ulGetLong(0, aucLvlfInfo);
844 tList.ucNFC = ucGetByte(4, aucLvlfInfo);
845 ucTmp = ucGetByte(5, aucLvlfInfo);
846 tList.bNoRestart = (ucTmp & BIT(3)) != 0;
847 DBG_MSG_C((ucTmp & BIT(4)) != 0 &&
848 (ucTmp & BIT(6)) != 0, "Found one");
850 ulStart += sizeof(aucLvlfInfo);
851 tPapxLen = (size_t)ucGetByte(25, aucLvlfInfo);
852 if (tPapxLen != 0) {
853 aucPapx = xmalloc(tPapxLen);
854 /* Read the Papx */
855 if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
856 aulBlockDepot, tBlockDepotLen,
857 tBlockSize, aucPapx,
858 ulStart, tPapxLen)) {
859 aucPapx = xfree(aucPapx);
860 aucLstfInfo = xfree(aucLstfInfo);
861 return;
863 NO_DBG_PRINT_BLOCK(aucPapx, tPapxLen);
864 tList.sLeftIndent =
865 sGetLeftIndent(aucPapx, tPapxLen);
866 aucPapx = xfree(aucPapx);
868 ulStart += tPapxLen;
869 ucChpxLen = ucGetByte(24, aucLvlfInfo);
870 ulStart += (ULONG)ucChpxLen;
871 /* Read the length of the XString */
872 if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
873 aulBlockDepot, tBlockDepotLen,
874 tBlockSize, aucXst,
875 ulStart, sizeof(aucXst))) {
876 aucLstfInfo = xfree(aucLstfInfo);
877 return;
879 NO_DBG_PRINT_BLOCK(aucXst, sizeof(aucXst));
880 tXstLen = (size_t)usGetWord(0, aucXst);
881 ulStart += sizeof(aucXst);
882 if (tXstLen == 0) {
883 tList.usListChar = DEFAULT_LISTCHAR;
884 vAdd2ListInfoList(ulListID,
885 usIstd,
886 ucListLevel,
887 &tList);
888 continue;
890 tXstLen *= 2; /* Length in chars to length in bytes */
891 aucXString = xmalloc(tXstLen);
892 /* Read the XString */
893 if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
894 aulBlockDepot, tBlockDepotLen,
895 tBlockSize, aucXString,
896 ulStart, tXstLen)) {
897 aucXString = xfree(aucXString);
898 aucLstfInfo = xfree(aucLstfInfo);
899 return;
901 NO_DBG_PRINT_BLOCK(aucXString, tXstLen);
902 tOff = 0;
903 for (iNums = 6; iNums < 15; iNums++) {
904 ucTmp = ucGetByte(iNums, aucLvlfInfo);
905 if (ucTmp == 0) {
906 break;
908 tOff = (size_t)ucTmp;
910 tOff *= 2; /* Offset in chars to offset in bytes */
911 NO_DBG_DEC(tOff);
912 if (tList.ucNFC == LIST_SPECIAL ||
913 tList.ucNFC == LIST_SPECIAL2 ||
914 tList.ucNFC == LIST_BULLETS) {
915 tList.usListChar = usGetWord(0, aucXString);
916 } else if (tOff != 0 && tOff < tXstLen) {
917 tList.usListChar = usGetWord(tOff, aucXString);
918 } else {
919 tList.usListChar = DEFAULT_LISTCHAR;
921 vAdd2ListInfoList(ulListID,
922 usIstd,
923 ucListLevel,
924 &tList);
925 ulStart += tXstLen;
926 aucXString = xfree(aucXString);
929 aucLstfInfo = xfree(aucLstfInfo);
930 } /* end of vGet8LstInfo */
933 * Build the lists with Paragraph Information for Word 8/9/10/11 files
935 void
936 vGet8PapInfo(FILE *pFile, const pps_info_type *pPPS,
937 const ULONG *aulBBD, size_t tBBDLen,
938 const ULONG *aulSBD, size_t tSBDLen,
939 const UCHAR *aucHeader)
941 row_block_type tRow;
942 style_block_type tStyle;
943 ULONG *aulParfPage;
944 UCHAR *aucBuffer;
945 ULONG ulCharPos, ulCharPosFirst, ulCharPosLast;
946 ULONG ulBeginParfInfo;
947 size_t tParfInfoLen, tOffset, tLen;
948 int iIndex, iIndex2, iRun, iFodo, iLen;
949 row_info_enum eRowInfo;
950 USHORT usIstd;
951 UCHAR aucFpage[BIG_BLOCK_SIZE];
953 fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
954 fail(aulBBD == NULL || aulSBD == NULL);
956 ulBeginParfInfo = ulGetLong(0x102, aucHeader); /* fcPlcfbtePapx */
957 NO_DBG_HEX(ulBeginParfInfo);
958 tParfInfoLen = (size_t)ulGetLong(0x106, aucHeader); /* lcbPlcfbtePapx */
959 NO_DBG_DEC(tParfInfoLen);
960 if (tParfInfoLen < 4) {
961 DBG_DEC(tParfInfoLen);
962 return;
965 aucBuffer = aucFillInfoBuffer(pFile, &pPPS->tTable,
966 aulBBD, tBBDLen, aulSBD, tSBDLen,
967 ulBeginParfInfo, tParfInfoLen);
968 if (aucBuffer == NULL) {
969 return;
971 NO_DBG_PRINT_BLOCK(aucBuffer, tParfInfoLen);
973 tLen = (tParfInfoLen / 4 - 1) / 2;
974 aulParfPage = xcalloc(tLen, sizeof(ULONG));
975 for (iIndex = 0, tOffset = (tLen + 1) * 4;
976 iIndex < (int)tLen;
977 iIndex++, tOffset += 4) {
978 aulParfPage[iIndex] = ulGetLong(tOffset, aucBuffer);
979 NO_DBG_DEC(aulParfPage[iIndex]);
981 DBG_HEX(ulGetLong(0, aucBuffer));
982 aucBuffer = xfree(aucBuffer);
983 NO_DBG_PRINT_BLOCK(aucHeader, HEADER_SIZE);
985 (void)memset(&tRow, 0, sizeof(tRow));
986 ulCharPosFirst = CP_INVALID;
987 for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
988 fail(aulParfPage[iIndex] > ULONG_MAX / BIG_BLOCK_SIZE);
989 if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB,
990 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
991 aucFpage,
992 aulParfPage[iIndex] * BIG_BLOCK_SIZE,
993 BIG_BLOCK_SIZE)) {
994 break;
996 NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE);
997 iRun = (int)ucGetByte(0x1ff, aucFpage);
998 NO_DBG_DEC(iRun);
999 for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
1000 NO_DBG_HEX(ulGetLong(iIndex2 * 4, aucFpage));
1001 iFodo = 2 * (int)ucGetByte(
1002 (iRun + 1) * 4 + iIndex2 * 13, aucFpage);
1003 if (iFodo <= 0) {
1004 continue;
1007 iLen = 2 * (int)ucGetByte(iFodo, aucFpage);
1008 if (iLen == 0) {
1009 iFodo++;
1010 iLen = 2 * (int)ucGetByte(iFodo, aucFpage);
1013 usIstd = usGetWord(iFodo + 1, aucFpage);
1014 vFillStyleFromStylesheet(usIstd, &tStyle);
1015 vGet8StyleInfo(iFodo, aucFpage + 3, iLen - 3, &tStyle);
1016 ulCharPos = ulGetLong(iIndex2 * 4, aucFpage);
1017 NO_DBG_HEX(ulCharPos);
1018 tStyle.ulFileOffset = ulCharPos2FileOffsetX(
1019 ulCharPos, &tStyle.eListID);
1020 vAdd2StyleInfoList(&tStyle);
1022 eRowInfo = eGet8RowInfo(iFodo,
1023 aucFpage + 3, iLen - 3, &tRow);
1024 switch (eRowInfo) {
1025 case found_a_cell:
1026 if (ulCharPosFirst != CP_INVALID) {
1027 break;
1029 ulCharPosFirst = ulGetLong(
1030 iIndex2 * 4, aucFpage);
1031 NO_DBG_HEX(ulCharPosFirst);
1032 tRow.ulCharPosStart = ulCharPosFirst;
1033 tRow.ulFileOffsetStart =
1034 ulCharPos2FileOffset(ulCharPosFirst);
1035 NO_DBG_HEX_C(
1036 tRow.ulFileOffsetStart == FC_INVALID,
1037 ulCharPosFirst);
1038 break;
1039 case found_end_of_row:
1040 ulCharPosLast = ulGetLong(
1041 iIndex2 * 4, aucFpage);
1042 NO_DBG_HEX(ulCharPosLast);
1043 tRow.ulCharPosEnd = ulCharPosLast;
1044 tRow.ulFileOffsetEnd =
1045 ulCharPos2FileOffset(ulCharPosLast);
1046 NO_DBG_HEX_C(tRow.ulFileOffsetEnd == FC_INVALID,
1047 ulCharPosLast);
1048 vAdd2RowInfoList(&tRow);
1049 (void)memset(&tRow, 0, sizeof(tRow));
1050 ulCharPosFirst = CP_INVALID;
1051 break;
1052 case found_nothing:
1053 break;
1054 default:
1055 DBG_DEC(eRowInfo);
1056 break;
1060 aulParfPage = xfree(aulParfPage);
1061 } /* end of vGet8PapInfo */
1064 * Fill the font information block with information
1065 * from a Word 8/9/10/11 file.
1067 void
1068 vGet8FontInfo(int iFodo, USHORT usIstd,
1069 const UCHAR *aucGrpprl, int iBytes, font_block_type *pFont)
1071 long lTmp;
1072 int iFodoOff, iInfoLen;
1073 USHORT usFtc0, usFtc1, usFtc2, usTmp;
1074 UCHAR ucTmp;
1076 fail(iFodo < 0 || aucGrpprl == NULL || pFont == NULL);
1078 usFtc0 = USHRT_MAX;
1079 usFtc1 = USHRT_MAX;
1080 usFtc2 = USHRT_MAX;
1082 iFodoOff = 0;
1083 while (iBytes >= iFodoOff + 2) {
1084 switch (usGetWord(iFodo + iFodoOff, aucGrpprl)) {
1085 case 0x0800: /* fRMarkDel */
1086 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1087 if (ucTmp == 0) {
1088 pFont->usFontStyle &= ~FONT_MARKDEL;
1089 } else {
1090 pFont->usFontStyle |= FONT_MARKDEL;
1092 break;
1093 case 0x0835: /* fBold */
1094 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1095 switch (ucTmp) {
1096 case 0: /* Unset */
1097 pFont->usFontStyle &= ~FONT_BOLD;
1098 break;
1099 case 1: /* Set */
1100 pFont->usFontStyle |= FONT_BOLD;
1101 break;
1102 case 128: /* Unchanged */
1103 break;
1104 case 129: /* Negation */
1105 pFont->usFontStyle ^= FONT_BOLD;
1106 break;
1107 default:
1108 DBG_DEC(ucTmp);
1109 DBG_FIXME();
1110 break;
1112 break;
1113 case 0x0836: /* fItalic */
1114 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1115 switch (ucTmp) {
1116 case 0: /* Unset */
1117 pFont->usFontStyle &= ~FONT_ITALIC;
1118 break;
1119 case 1: /* Set */
1120 pFont->usFontStyle |= FONT_ITALIC;
1121 break;
1122 case 128: /* Unchanged */
1123 break;
1124 case 129: /* Negation */
1125 pFont->usFontStyle ^= FONT_ITALIC;
1126 break;
1127 default:
1128 DBG_DEC(ucTmp);
1129 DBG_FIXME();
1130 break;
1132 break;
1133 case 0x0837: /* fStrike */
1134 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1135 switch (ucTmp) {
1136 case 0: /* Unset */
1137 pFont->usFontStyle &= ~FONT_STRIKE;
1138 break;
1139 case 1: /* Set */
1140 pFont->usFontStyle |= FONT_STRIKE;
1141 break;
1142 case 128: /* Unchanged */
1143 break;
1144 case 129: /* Negation */
1145 pFont->usFontStyle ^= FONT_STRIKE;
1146 break;
1147 default:
1148 DBG_DEC(ucTmp);
1149 DBG_FIXME();
1150 break;
1152 break;
1153 case 0x083a: /* fSmallCaps */
1154 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1155 switch (ucTmp) {
1156 case 0: /* Unset */
1157 pFont->usFontStyle &= ~FONT_SMALL_CAPITALS;
1158 break;
1159 case 1: /* Set */
1160 pFont->usFontStyle |= FONT_SMALL_CAPITALS;
1161 break;
1162 case 128: /* Unchanged */
1163 break;
1164 case 129: /* Negation */
1165 pFont->usFontStyle ^= FONT_SMALL_CAPITALS;
1166 break;
1167 default:
1168 DBG_DEC(ucTmp);
1169 DBG_FIXME();
1170 break;
1172 break;
1173 case 0x083b: /* fCaps */
1174 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1175 switch (ucTmp) {
1176 case 0: /* Unset */
1177 pFont->usFontStyle &= ~FONT_CAPITALS;
1178 break;
1179 case 1: /* Set */
1180 pFont->usFontStyle |= FONT_CAPITALS;
1181 break;
1182 case 128: /* Unchanged */
1183 break;
1184 case 129: /* Negation */
1185 pFont->usFontStyle ^= FONT_CAPITALS;
1186 break;
1187 default:
1188 DBG_DEC(ucTmp);
1189 DBG_FIXME();
1190 break;
1192 break;
1193 case 0x083c: /* fVanish */
1194 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1195 switch (ucTmp) {
1196 case 0: /* Unset */
1197 pFont->usFontStyle &= ~FONT_HIDDEN;
1198 break;
1199 case 1: /* Set */
1200 pFont->usFontStyle |= FONT_HIDDEN;
1201 break;
1202 case 128: /* Unchanged */
1203 break;
1204 case 129: /* Negation */
1205 pFont->usFontStyle ^= FONT_HIDDEN;
1206 break;
1207 default:
1208 DBG_DEC(ucTmp);
1209 DBG_FIXME();
1210 break;
1212 break;
1213 case 0x2a32: /* cDefault */
1214 pFont->usFontStyle &= FONT_HIDDEN;
1215 pFont->ucFontColor = FONT_COLOR_DEFAULT;
1216 break;
1217 case 0x2a33: /* cPlain */
1218 DBG_MSG("2a33: cPlain");
1219 vFillFontFromStylesheet(usIstd, pFont);
1220 break;
1221 case 0x2a3e: /* cKul */
1222 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1223 if (ucTmp == 0 || ucTmp == 5) {
1224 pFont->usFontStyle &= ~FONT_UNDERLINE;
1225 } else {
1226 NO_DBG_MSG("Underline text");
1227 pFont->usFontStyle |= FONT_UNDERLINE;
1228 if (ucTmp == 6) {
1229 DBG_MSG("Bold text");
1230 pFont->usFontStyle |= FONT_BOLD;
1233 break;
1234 case 0x2a42: /* cIco */
1235 pFont->ucFontColor =
1236 ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1237 NO_DBG_DEC(pFont->ucFontColor);
1238 break;
1239 case 0x2a44: /* cHpsInc */
1240 DBG_MSG("0x2a44: sprmCHpsInc");
1241 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1242 DBG_DEC(ucTmp);
1243 break;
1244 case 0x2a48: /* cIss */
1245 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1246 ucTmp &= 0x07;
1247 if (ucTmp == 1) {
1248 pFont->usFontStyle |= FONT_SUPERSCRIPT;
1249 NO_DBG_MSG("Superscript");
1250 } else if (ucTmp == 2) {
1251 pFont->usFontStyle |= FONT_SUBSCRIPT;
1252 NO_DBG_MSG("Subscript");
1254 break;
1255 case 0x4a30: /* cIstd */
1256 usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
1257 NO_DBG_DEC(usTmp);
1258 break;
1259 case 0x4a43: /* cHps */
1260 pFont->usFontSize =
1261 usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
1262 NO_DBG_DEC(pFont->usFontSize);
1263 break;
1264 case 0x4a4d: /* cHpsMul */
1265 DBG_MSG("0x4a4d: sprmCHpsMul");
1266 usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
1267 DBG_DEC(usTmp);
1268 break;
1269 case 0x4a4f: /* cFtc0 */
1270 usFtc0 = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
1271 break;
1272 case 0x4a50: /* cFtc1 */
1273 usFtc1 = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
1274 break;
1275 case 0x4a51: /* cFtc2 */
1276 usFtc2 = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
1277 break;
1278 case 0xca47: /* cMajority */
1279 DBG_MSG("0xca47: sprmCMajority");
1280 break;
1281 case 0xca4a: /* cHpsInc1 */
1282 usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
1283 lTmp = (long)pFont->usFontSize + (long)usTmp;
1284 if (lTmp < 8) {
1285 pFont->usFontSize = 8;
1286 } else if (lTmp > 32766) {
1287 pFont->usFontSize = 32766;
1288 } else {
1289 pFont->usFontSize = (USHORT)lTmp;
1291 break;
1292 case 0xca4c: /* cMajority50 */
1293 DBG_MSG("0xca4c: sprmCMajority50");
1294 break;
1295 case 0xea3f: /* cHps, cHpsPos */
1296 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1297 DBG_DEC(ucTmp);
1298 if (ucTmp != 0) {
1299 pFont->usFontSize = (USHORT)ucTmp;
1301 ucTmp = ucGetByte(iFodo + iFodoOff + 3, aucGrpprl);
1302 DBG_DEC(ucTmp);
1303 break;
1304 default:
1305 break;
1307 iInfoLen = iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
1308 fail(iInfoLen <= 0);
1309 iFodoOff += iInfoLen;
1312 /* Combine the Ftc's to a FontNumber */
1313 NO_DBG_DEC_C(usFtc0 != USHRT_MAX, usFtc0);
1314 NO_DBG_DEC_C(usFtc2 != USHRT_MAX, usFtc2);
1315 NO_DBG_DEC_C(usFtc1 != USHRT_MAX, usFtc1);
1316 if (usFtc0 <= 0x7fff) {
1317 if (usFtc0 <= (USHORT)UCHAR_MAX) {
1318 pFont->ucFontNumber = (UCHAR)usFtc0;
1319 } else {
1320 DBG_DEC(usFtc0);
1321 DBG_FIXME();
1322 pFont->ucFontNumber = 0;
1324 } else if (usFtc2 <= 0x7fff) {
1325 if (usFtc2 <= (USHORT)UCHAR_MAX) {
1326 pFont->ucFontNumber = (UCHAR)usFtc2;
1327 } else {
1328 DBG_DEC(usFtc2);
1329 DBG_FIXME();
1330 pFont->ucFontNumber = 0;
1332 } else if (usFtc1 <= 0x7fff) {
1333 if (usFtc1 <= (USHORT)UCHAR_MAX) {
1334 pFont->ucFontNumber = (UCHAR)usFtc1;
1335 } else {
1336 DBG_DEC(usFtc1);
1337 DBG_FIXME();
1338 pFont->ucFontNumber = 0;
1341 } /* end of vGet8FontInfo */
1344 * Fill the picture information block with information
1345 * from a Word 8/9/10/11 file.
1346 * Returns TRUE when successful, otherwise FALSE
1348 static BOOL
1349 bGet8PicInfo(int iFodo,
1350 const UCHAR *aucGrpprl, int iBytes, picture_block_type *pPicture)
1352 ULONG ulTmp;
1353 int iFodoOff, iInfoLen;
1354 BOOL bFound;
1355 UCHAR ucTmp;
1357 fail(iFodo <= 0 || aucGrpprl == NULL || pPicture == NULL);
1359 iFodoOff = 0;
1360 bFound = FALSE;
1361 while (iBytes >= iFodoOff + 2) {
1362 switch (usGetWord(iFodo + iFodoOff, aucGrpprl)) {
1363 #if 0
1364 case 0x0806: /* fData */
1365 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1366 if (ucTmp == 0x01) {
1367 /* Not a picture, but a form field */
1368 return FALSE;
1370 DBG_DEC_C(ucTmp != 0, ucTmp);
1371 break;
1372 #endif
1373 case 0x080a: /* fOle2 */
1374 ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
1375 if (ucTmp == 0x01) {
1376 /* Not a picture, but an OLE object */
1377 return FALSE;
1379 DBG_DEC_C(ucTmp != 0, ucTmp);
1380 break;
1381 case 0x680e: /* fcObj */
1382 ulTmp = ulGetLong(iFodo + iFodoOff + 2, aucGrpprl);
1383 DBG_HEX(ulTmp);
1384 break;
1385 case 0x6a03: /* fcPic */
1386 pPicture->ulPictureOffset = ulGetLong(
1387 iFodo + iFodoOff + 2, aucGrpprl);
1388 bFound = TRUE;
1389 break;
1390 default:
1391 break;
1393 iInfoLen = iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
1394 fail(iInfoLen <= 0);
1395 iFodoOff += iInfoLen;
1397 return bFound;
1398 } /* end of bGet8PicInfo */
1401 * Build the lists with Character Information for Word 8/9/10/11 files
1403 void
1404 vGet8ChrInfo(FILE *pFile, const pps_info_type *pPPS,
1405 const ULONG *aulBBD, size_t tBBDLen,
1406 const ULONG *aulSBD, size_t tSBDLen,
1407 const UCHAR *aucHeader)
1409 font_block_type tFont;
1410 picture_block_type tPicture;
1411 ULONG *aulCharPage;
1412 UCHAR *aucBuffer;
1413 ULONG ulFileOffset, ulCharPos, ulBeginCharInfo;
1414 size_t tCharInfoLen, tOffset, tLen;
1415 int iIndex, iIndex2, iRun, iFodo, iLen;
1416 USHORT usIstd;
1417 UCHAR aucFpage[BIG_BLOCK_SIZE];
1419 fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
1420 fail(aulBBD == NULL || aulSBD == NULL);
1422 ulBeginCharInfo = ulGetLong(0xfa, aucHeader); /* fcPlcfbteChpx */
1423 NO_DBG_HEX(ulBeginCharInfo);
1424 tCharInfoLen = (size_t)ulGetLong(0xfe, aucHeader); /* lcbPlcfbteChpx */
1425 NO_DBG_DEC(tCharInfoLen);
1426 if (tCharInfoLen < 4) {
1427 DBG_DEC(tCharInfoLen);
1428 return;
1431 aucBuffer = aucFillInfoBuffer(pFile, &pPPS->tTable,
1432 aulBBD, tBBDLen, aulSBD, tSBDLen,
1433 ulBeginCharInfo, tCharInfoLen);
1434 if (aucBuffer == NULL) {
1435 return;
1437 NO_DBG_PRINT_BLOCK(aucBuffer, tCharInfoLen);
1439 tLen = (tCharInfoLen / 4 - 1) / 2;
1440 aulCharPage = xcalloc(tLen, sizeof(ULONG));
1441 for (iIndex = 0, tOffset = (tLen + 1) * 4;
1442 iIndex < (int)tLen;
1443 iIndex++, tOffset += 4) {
1444 aulCharPage[iIndex] = ulGetLong(tOffset, aucBuffer);
1445 NO_DBG_DEC(aulCharPage[iIndex]);
1447 DBG_HEX(ulGetLong(0, aucBuffer));
1448 aucBuffer = xfree(aucBuffer);
1449 NO_DBG_PRINT_BLOCK(aucHeader, HEADER_SIZE);
1451 for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
1452 fail(aulCharPage[iIndex] > ULONG_MAX / BIG_BLOCK_SIZE);
1453 if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB,
1454 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
1455 aucFpage,
1456 aulCharPage[iIndex] * BIG_BLOCK_SIZE,
1457 BIG_BLOCK_SIZE)) {
1458 break;
1460 NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE);
1461 iRun = (int)ucGetByte(0x1ff, aucFpage);
1462 NO_DBG_DEC(iRun);
1463 for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
1464 ulCharPos = ulGetLong(iIndex2 * 4, aucFpage);
1465 ulFileOffset = ulCharPos2FileOffset(ulCharPos);
1466 iFodo = 2 * (int)ucGetByte(
1467 (iRun + 1) * 4 + iIndex2, aucFpage);
1469 iLen = (int)ucGetByte(iFodo, aucFpage);
1471 usIstd = usGetIstd(ulFileOffset);
1472 vFillFontFromStylesheet(usIstd, &tFont);
1473 if (iFodo != 0) {
1474 vGet8FontInfo(iFodo, usIstd,
1475 aucFpage + 1, iLen - 1, &tFont);
1477 tFont.ulFileOffset = ulFileOffset;
1478 vAdd2FontInfoList(&tFont);
1480 if (iFodo <= 0) {
1481 continue;
1484 (void)memset(&tPicture, 0, sizeof(tPicture));
1485 if (bGet8PicInfo(iFodo, aucFpage + 1,
1486 iLen - 1, &tPicture)) {
1487 tPicture.ulFileOffset = ulFileOffset;
1488 tPicture.ulFileOffsetPicture =
1489 ulDataPos2FileOffset(
1490 tPicture.ulPictureOffset);
1491 vAdd2PictInfoList(&tPicture);
1495 aulCharPage = xfree(aulCharPage);
1496 } /* end of vGet8ChrInfo */