]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/antiword/prop8.c
exec(2): fix prototypes
[plan9front.git] / sys / src / cmd / aux / antiword / prop8.c
1 /*
2  * prop8.c
3  * Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
4  *
5  * Description:
6  * Read the property information from a MS Word 8, 9,10 or 11 file
7  *
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
12  */
13
14 #include <stdlib.h>
15 #include <string.h>
16 #include "antiword.h"
17
18 #define DEFAULT_LISTCHAR        0x002e  /* A full stop */
19
20
21 /*
22  * iGet8InfoLength - the length of the information for Word 8/9/10/11 files
23  */
24 static int
25 iGet8InfoLength(int iByteNbr, const UCHAR *aucGrpprl)
26 {
27         int     iTmp, iDel, iAdd;
28         USHORT  usOpCode;
29
30         usOpCode = usGetWord(iByteNbr, aucGrpprl);
31
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;
48                 }
49                 return 3 + iTmp;
50         default:
51                 DBG_HEX(usOpCode);
52                 DBG_FIXME();
53                 return 1;
54         }
55 } /* end of iGet8InfoLength */
56
57 /*
58  * aucFillInfoBuffer - fill the information buffer
59  *
60  * Returns the information buffer when successful, otherwise NULL
61  */
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)
67 {
68         const ULONG     *aulBlockDepot;
69         UCHAR   *aucBuffer;
70         size_t  tBlockDepotLen, tBlockSize;
71
72         fail(pFile == NULL || pTable == NULL);
73         fail(aulBBD == NULL || aulSBD == NULL);
74         fail(tInfoLen == 0);
75
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;
81         }
82
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;
93         }
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;
100         }
101         return aucBuffer;
102 } /* end of aucFillInfoBuffer */
103
104 /*
105  * Build the lists with Document Property Information for Word 8/9/10/11 files
106  */
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)
112 {
113         document_block_type     tDocument;
114         UCHAR   *aucBuffer;
115         ULONG   ulBeginDocpInfo, ulTmp;
116         size_t  tDocpInfoLen;
117         USHORT  usTmp;
118
119         fail(pFile == NULL || pTable == NULL || aucHeader == NULL);
120         fail(aulBBD == NULL || aulSBD == NULL);
121
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;
129         }
130
131         aucBuffer = aucFillInfoBuffer(pFile, pTable,
132                         aulBBD, tBBDLen, aulSBD, tSBDLen,
133                         ulBeginDocpInfo, tDocpInfoLen);
134         if (aucBuffer == NULL) {
135                 return;
136         }
137
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);
146
147         aucBuffer = xfree(aucBuffer);
148 } /* end of vGet8DopInfo */
149
150 /*
151  * Fill the section information block with information
152  * from a Word 8/9/10/11 file.
153  */
154 static void
155 vGet8SectionInfo(const UCHAR *aucGrpprl, size_t tBytes,
156                 section_block_type *pSection)
157 {
158         UINT    uiIndex;
159         int     iFodoOff, iInfoLen, iSize, iTmp;
160         USHORT  usCcol;
161         UCHAR   ucTmp;
162
163         fail(aucGrpprl == NULL || pSection == NULL);
164
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);
196                                 }
197                                 if ((ucTmp & BIT(3)) != 0) {
198                                         pSection->usHangingIndent |=
199                                                         (USHORT)BIT(uiIndex);
200                                 }
201                         }
202                         DBG_HEX(pSection->usNeedPrevLvl);
203                         DBG_HEX(pSection->usHangingIndent);
204                         break;
205                 default:
206                         break;
207                 }
208                 if (iInfoLen <= 0) {
209                         iInfoLen = iGet8InfoLength(iFodoOff, aucGrpprl);
210                         fail(iInfoLen <= 0);
211                 }
212                 iFodoOff += iInfoLen;
213         }
214 } /* end of vGet8SectionInfo */
215
216 /*
217  * Build the lists with Section Property Information for Word 8/9/10/11 files
218  */
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)
224 {
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];
231
232         fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
233         fail(aulBBD == NULL || aulSBD == NULL);
234
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;
244         }
245
246         aucBuffer = aucFillInfoBuffer(pFile, &pPPS->tTable,
247                         aulBBD, tBBDLen, aulSBD, tSBDLen,
248                         ulBeginSectInfo, tSectInfoLen);
249         if (aucBuffer == NULL) {
250                 return;
251         }
252         NO_DBG_PRINT_BLOCK(aucBuffer, tSectInfoLen);
253
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]);
265         }
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 */
273         }
274         aucBuffer = xfree(aucBuffer);
275
276         /* Read the Section Properties */
277         for (tIndex = 0; tIndex < tLen; tIndex++) {
278                 if (aulSectPage[tIndex] == FC_INVALID) {
279                         vDefault2SectionInfoList(aulCharPos[tIndex]);
280                         continue;
281                 }
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;
287                 }
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;
297                 }
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);
304         }
305         aulCharPos = xfree(aulCharPos);
306         aulSectPage = xfree(aulSectPage);
307 } /* end of vGet8SepInfo */
308
309 /*
310  * Build the list with Header/Footer Information for Word 8/9/10/11 files
311  */
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)
317 {
318         ULONG   *aulCharPos;
319         UCHAR   *aucBuffer;
320         ULONG   ulHdrFtrOffset, ulBeginHdrFtrInfo;
321         size_t  tHdrFtrInfoLen, tIndex, tOffset, tLen;
322
323         fail(pFile == NULL || pTable == NULL || aucHeader == NULL);
324         fail(aulBBD == NULL || aulSBD == NULL);
325
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;
333         }
334
335         aucBuffer = aucFillInfoBuffer(pFile, pTable,
336                         aulBBD, tBBDLen, aulSBD, tSBDLen,
337                         ulBeginHdrFtrInfo, tHdrFtrInfoLen);
338         if (aucBuffer == NULL) {
339                 return;
340         }
341         NO_DBG_PRINT_BLOCK(aucBuffer, tHdrFtrInfoLen);
342
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]);
354         }
355         vCreat8HdrFtrInfoList(aulCharPos, tLen);
356         /* Clean up and leave */
357         aulCharPos = xfree(aulCharPos);
358         aucBuffer = xfree(aucBuffer);
359 } /* end of vGet8HdrFtrInfo */
360
361 /*
362  * Translate the rowinfo to a member of the row_info enumeration
363  */
364 row_info_enum
365 eGet8RowInfo(int iFodo,
366         const UCHAR *aucGrpprl, int iBytes, row_block_type *pRow)
367 {
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;
375
376         fail(iFodo < 0 || aucGrpprl == NULL || pRow == NULL);
377
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;
396                         }
397                         break;
398                 case 0x2417:    /* fTtp */
399                         if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
400                                 bFound2417_1 = TRUE;
401                         } else {
402                                 bFound2417_0 = TRUE;
403                         }
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;
410                         }
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;
417                         }
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;
427                         }
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;
437                         }
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;
447                         }
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;
457                         }
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;
471                         }
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;
479                         }
480                         if (iCol >= (int)elementsof(pRow->asColumnWidth)) {
481                                 DBG_DEC(iCol);
482                                 werr(1, "The number of columns is corrupt");
483                         }
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;
495                         }
496                         bFoundd608 = TRUE;
497                         break;
498                 default:
499                         break;
500                 }
501                 if (iInfoLen <= 0) {
502                         iInfoLen =
503                                 iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
504                         fail(iInfoLen <= 0);
505                 }
506                 iFodoOff += iInfoLen;
507         }
508
509         if (bFound2417_1 && bFoundd608) {
510                 return found_end_of_row;
511         }
512         if (bFound2417_0 && !bFoundd608) {
513                 return found_not_end_of_row;
514         }
515         if (bFound2416_1 || bFound244b_1) {
516                 return found_a_cell;
517         }
518         if (bFound2416_0 || bFound244b_0) {
519                 return found_not_a_cell;
520         }
521         return found_nothing;
522 } /* end of eGet8RowInfo */
523
524 /*
525  * Fill the style information block with information
526  * from a Word 8/9/10/11 file.
527  */
528 void
529 vGet8StyleInfo(int iFodo,
530         const UCHAR *aucGrpprl, int iBytes, style_block_type *pStyle)
531 {
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;
538
539         fail(iFodo < 0 || aucGrpprl == NULL || pStyle == NULL);
540
541         NO_DBG_DEC_C(pStyle->usListIndex != 0, pStyle->usIstd);
542         NO_DBG_DEC_C(pStyle->usListIndex != 0, pStyle->usListIndex);
543
544         (void)memset(&tList6, 0, sizeof(tList6));
545
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;
576                         }
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;
586                         }
587                         NO_DBG_DEC(iTmp);
588                         iDel = (int)ucGetByte(iFodo + iFodoOff + 3, aucGrpprl);
589                         if (iTmp < 2 + 2 * iDel) {
590                                 iInfoLen = 1;
591                                 break;
592                         }
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;
599                         }
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);
634                         }
635                         if (tList6.ucNFC != LIST_BULLETS && iTmp >= 2) {
636                                 iBefore = (int)ucGetByte(
637                                         iFodo + iFodoOff + 4, aucGrpprl);
638                         } else {
639                                 iBefore = 0;
640                         }
641                         if (iTmp >= 12) {
642                                 tList6.ulStartAt = (ULONG)usGetWord(
643                                         iFodo + iFodoOff + 13, aucGrpprl);
644                         }
645                         if (iTmp >= iBefore + 22) {
646                                 tList6.usListChar = usGetWord(
647                                         iFodo + iFodoOff + iBefore + 23,
648                                         aucGrpprl);
649                                 DBG_HEX(tList6.usListChar);
650                         }
651                         break;
652                 default:
653                         NO_DBG_HEX(usOpCode);
654                         break;
655                 }
656                 if (iInfoLen <= 0) {
657                         iInfoLen =
658                                 iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
659                         fail(iInfoLen <= 0);
660                 }
661                 iFodoOff += iInfoLen;
662         }
663
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;
680                         }
681                 }
682         }
683 } /* end of vGet8StyleInfo */
684
685 /*
686  * Get the left indentation value from the style information block
687  *
688  * Returns the value when found, otherwise 0
689  */
690 static short
691 sGetLeftIndent(const UCHAR *aucGrpprl, size_t tBytes)
692 {
693         int     iOffset, iInfoLen;
694         USHORT  usOpCode, usTmp;
695
696         fail(aucGrpprl == NULL);
697
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;
706                         }
707                 }
708                 iInfoLen = iGet8InfoLength(iOffset, aucGrpprl);
709                 fail(iInfoLen <= 0);
710                 iOffset += iInfoLen;
711         }
712         return 0;
713 } /* end of sGetLeftIndent */
714
715 /*
716  * Build the list with List Information for Word 8/9/10/11 files
717  */
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)
723 {
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];
736
737         fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
738         fail(aulBBD == NULL || aulSBD == NULL);
739
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;
745         }
746
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;
757         }
758
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;
767         }
768
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;
775         }
776         NO_DBG_PRINT_BLOCK(aucLfoInfo, tLfoInfoLen);
777         vBuildLfoList(aucLfoInfo, tLfoInfoLen);
778         aucLfoInfo = xfree(aucLfoInfo);
779
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;
788         }
789
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;
796         }
797         NO_DBG_PRINT_BLOCK(aucLstfInfo, tLstfInfoLen);
798
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;
805         }
806
807         /* LVLF (List leVeL on File) */
808         ulBeginLvlfInfo = ulBeginLstfInfo + tLstfInfoLen;
809         DBG_HEX(ulBeginLvlfInfo);
810
811         aucXString = NULL;
812         ulStart = ulBeginLvlfInfo;
813
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;
836                         }
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");
849                         }
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;
862                                 }
863                                 NO_DBG_PRINT_BLOCK(aucPapx, tPapxLen);
864                                 tList.sLeftIndent =
865                                         sGetLeftIndent(aucPapx, tPapxLen);
866                                 aucPapx = xfree(aucPapx);
867                         }
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;
878                         }
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;
889                         }
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;
900                         }
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;
907                                 }
908                                 tOff = (size_t)ucTmp;
909                         }
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;
920                         }
921                         vAdd2ListInfoList(ulListID,
922                                         usIstd,
923                                         ucListLevel,
924                                         &tList);
925                         ulStart += tXstLen;
926                         aucXString = xfree(aucXString);
927                 }
928         }
929         aucLstfInfo = xfree(aucLstfInfo);
930 } /* end of vGet8LstInfo */
931
932 /*
933  * Build the lists with Paragraph Information for Word 8/9/10/11 files
934  */
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)
940 {
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];
952
953         fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
954         fail(aulBBD == NULL || aulSBD == NULL);
955
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;
963         }
964
965         aucBuffer = aucFillInfoBuffer(pFile, &pPPS->tTable,
966                         aulBBD, tBBDLen, aulSBD, tSBDLen,
967                         ulBeginParfInfo, tParfInfoLen);
968         if (aucBuffer == NULL) {
969                 return;
970         }
971         NO_DBG_PRINT_BLOCK(aucBuffer, tParfInfoLen);
972
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]);
980         }
981         DBG_HEX(ulGetLong(0, aucBuffer));
982         aucBuffer = xfree(aucBuffer);
983         NO_DBG_PRINT_BLOCK(aucHeader, HEADER_SIZE);
984
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;
995                 }
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;
1005                         }
1006
1007                         iLen = 2 * (int)ucGetByte(iFodo, aucFpage);
1008                         if (iLen == 0) {
1009                                 iFodo++;
1010                                 iLen = 2 * (int)ucGetByte(iFodo, aucFpage);
1011                         }
1012
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);
1021
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;
1028                                 }
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;
1057                         }
1058                 }
1059         }
1060         aulParfPage = xfree(aulParfPage);
1061 } /* end of vGet8PapInfo */
1062
1063 /*
1064  * Fill the font information block with information
1065  * from a Word 8/9/10/11 file.
1066  */
1067 void
1068 vGet8FontInfo(int iFodo, USHORT usIstd,
1069         const UCHAR *aucGrpprl, int iBytes, font_block_type *pFont)
1070 {
1071         long    lTmp;
1072         int     iFodoOff, iInfoLen;
1073         USHORT  usFtc0, usFtc1, usFtc2, usTmp;
1074         UCHAR   ucTmp;
1075
1076         fail(iFodo < 0 || aucGrpprl == NULL || pFont == NULL);
1077
1078         usFtc0 = USHRT_MAX;
1079         usFtc1 = USHRT_MAX;
1080         usFtc2 = USHRT_MAX;
1081
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;
1091                         }
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;
1111                         }
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;
1131                         }
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;
1151                         }
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;
1171                         }
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;
1191                         }
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;
1211                         }
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;
1231                                 }
1232                         }
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");
1253                         }
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;
1290                         }
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;
1300                         }
1301                         ucTmp = ucGetByte(iFodo + iFodoOff + 3, aucGrpprl);
1302                         DBG_DEC(ucTmp);
1303                         break;
1304                 default:
1305                         break;
1306                 }
1307                 iInfoLen = iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
1308                 fail(iInfoLen <= 0);
1309                 iFodoOff += iInfoLen;
1310         }
1311
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;
1323                 }
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;
1331                 }
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;
1339                 }
1340         }
1341 } /* end of vGet8FontInfo */
1342
1343 /*
1344  * Fill the picture information block with information
1345  * from a Word 8/9/10/11 file.
1346  * Returns TRUE when successful, otherwise FALSE
1347  */
1348 static BOOL
1349 bGet8PicInfo(int iFodo,
1350         const UCHAR *aucGrpprl, int iBytes, picture_block_type *pPicture)
1351 {
1352         ULONG   ulTmp;
1353         int     iFodoOff, iInfoLen;
1354         BOOL    bFound;
1355         UCHAR   ucTmp;
1356
1357         fail(iFodo <= 0 || aucGrpprl == NULL || pPicture == NULL);
1358
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;
1369                         }
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;
1378                         }
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;
1392                 }
1393                 iInfoLen = iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
1394                 fail(iInfoLen <= 0);
1395                 iFodoOff += iInfoLen;
1396         }
1397         return bFound;
1398 } /* end of bGet8PicInfo */
1399
1400 /*
1401  * Build the lists with Character Information for Word 8/9/10/11 files
1402  */
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)
1408 {
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];
1418
1419         fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
1420         fail(aulBBD == NULL || aulSBD == NULL);
1421
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;
1429         }
1430
1431         aucBuffer = aucFillInfoBuffer(pFile, &pPPS->tTable,
1432                         aulBBD, tBBDLen, aulSBD, tSBDLen,
1433                         ulBeginCharInfo, tCharInfoLen);
1434         if (aucBuffer == NULL) {
1435                 return;
1436         }
1437         NO_DBG_PRINT_BLOCK(aucBuffer, tCharInfoLen);
1438
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]);
1446         }
1447         DBG_HEX(ulGetLong(0, aucBuffer));
1448         aucBuffer = xfree(aucBuffer);
1449         NO_DBG_PRINT_BLOCK(aucHeader, HEADER_SIZE);
1450
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;
1459                 }
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);
1468
1469                         iLen = (int)ucGetByte(iFodo, aucFpage);
1470
1471                         usIstd = usGetIstd(ulFileOffset);
1472                         vFillFontFromStylesheet(usIstd, &tFont);
1473                         if (iFodo != 0) {
1474                                 vGet8FontInfo(iFodo, usIstd,
1475                                         aucFpage + 1, iLen - 1, &tFont);
1476                         }
1477                         tFont.ulFileOffset = ulFileOffset;
1478                         vAdd2FontInfoList(&tFont);
1479
1480                         if (iFodo <= 0) {
1481                                 continue;
1482                         }
1483
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);
1492                         }
1493                 }
1494         }
1495         aulCharPage = xfree(aulCharPage);
1496 } /* end of vGet8ChrInfo */