examples/PIPS/antiword/src/prop8.c

00001 /*
00002  * prop8.c
00003  * Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL
00004  *
00005  * Description:
00006  * Read the property information from a MS Word 8, 9,10 or 11 file
00007  *
00008  * Word  8 is better known as Word 97 or as Word 98 for Mac
00009  * Word  9 is better known as Word 2000 or as Word 2001 for Mac
00010  * Word 10 is better known as Word 2002 or as Word XP
00011  * Word 11 is better known as Word 2003
00012  */
00013 
00014 #include <stdlib.h>
00015 #include <string.h>
00016 #include "antiword.h"
00017 
00018 #define DEFAULT_LISTCHAR        0x002e  /* A full stop */
00019 
00020 
00021 /*
00022  * iGet8InfoLength - the length of the information for Word 8/9/10/11 files
00023  */
00024 static int
00025 iGet8InfoLength(int iByteNbr, const UCHAR *aucGrpprl)
00026 {
00027         int     iTmp, iDel, iAdd;
00028         USHORT  usOpCode;
00029 
00030         usOpCode = usGetWord(iByteNbr, aucGrpprl);
00031 
00032         switch (usOpCode & 0xe000) {
00033         case 0x0000: case 0x2000:
00034                 return 3;
00035         case 0x4000: case 0x8000: case 0xa000:
00036                 return 4;
00037         case 0xe000:
00038                 return 5;
00039         case 0x6000:
00040                 return 6;
00041         case 0xc000:
00042                 iTmp = (int)ucGetByte(iByteNbr + 2, aucGrpprl);
00043                 if (usOpCode == 0xc615 && iTmp == 255) {
00044                         iDel = (int)ucGetByte(iByteNbr + 3, aucGrpprl);
00045                         iAdd = (int)ucGetByte(
00046                                         iByteNbr + 4 + iDel * 4, aucGrpprl);
00047                         iTmp = 2 + iDel * 4 + iAdd * 3;
00048                 }
00049                 return 3 + iTmp;
00050         default:
00051                 DBG_HEX(usOpCode);
00052                 DBG_FIXME();
00053                 return 1;
00054         }
00055 } /* end of iGet8InfoLength */
00056 
00057 /*
00058  * aucFillInfoBuffer - fill the information buffer
00059  *
00060  * Returns the information buffer when successful, otherwise NULL
00061  */
00062 static UCHAR *
00063 aucFillInfoBuffer(FILE *pFile, const pps_type *pTable,
00064         const ULONG *aulBBD, size_t tBBDLen,
00065         const ULONG *aulSBD, size_t tSBDLen,
00066         ULONG ulBeginInfo, size_t tInfoLen)
00067 {
00068         const ULONG     *aulBlockDepot;
00069         UCHAR   *aucBuffer;
00070         size_t  tBlockDepotLen, tBlockSize;
00071 
00072         fail(pFile == NULL || pTable == NULL);
00073         fail(aulBBD == NULL || aulSBD == NULL);
00074         fail(tInfoLen == 0);
00075 
00076         NO_DBG_DEC(pTable->ulSB);
00077         NO_DBG_HEX(pTable->ulSize);
00078         if (pTable->ulSize == 0) {
00079                 DBG_MSG("No information");
00080                 return NULL;
00081         }
00082 
00083         if (pTable->ulSize < MIN_SIZE_FOR_BBD_USE) {
00084                 /* Use the Small Block Depot */
00085                 aulBlockDepot = aulSBD;
00086                 tBlockDepotLen = tSBDLen;
00087                 tBlockSize = SMALL_BLOCK_SIZE;
00088         } else {
00089                 /* Use the Big Block Depot */
00090                 aulBlockDepot = aulBBD;
00091                 tBlockDepotLen = tBBDLen;
00092                 tBlockSize = BIG_BLOCK_SIZE;
00093         }
00094         aucBuffer = xmalloc(tInfoLen);
00095         if (!bReadBuffer(pFile, pTable->ulSB,
00096                         aulBlockDepot, tBlockDepotLen, tBlockSize,
00097                         aucBuffer, ulBeginInfo, tInfoLen)) {
00098                 aucBuffer = xfree(aucBuffer);
00099                 return NULL;
00100         }
00101         return aucBuffer;
00102 } /* end of aucFillInfoBuffer */
00103 
00104 /*
00105  * Build the lists with Document Property Information for Word 8/9/10/11 files
00106  */
00107 void
00108 vGet8DopInfo(FILE *pFile, const pps_type *pTable,
00109         const ULONG *aulBBD, size_t tBBDLen,
00110         const ULONG *aulSBD, size_t tSBDLen,
00111         const UCHAR *aucHeader)
00112 {
00113         document_block_type     tDocument;
00114         UCHAR   *aucBuffer;
00115         ULONG   ulBeginDocpInfo, ulTmp;
00116         size_t  tDocpInfoLen;
00117         USHORT  usTmp;
00118 
00119         fail(pFile == NULL || pTable == NULL || aucHeader == NULL);
00120         fail(aulBBD == NULL || aulSBD == NULL);
00121 
00122         ulBeginDocpInfo = ulGetLong(0x192, aucHeader); /* fcDop */
00123         NO_DBG_HEX(ulBeginSectInfo);
00124         tDocpInfoLen = (size_t)ulGetLong(0x196, aucHeader); /* lcbDop */
00125         NO_DBG_DEC(tSectInfoLen);
00126         if (tDocpInfoLen < 28) {
00127                 DBG_MSG("No Document information");
00128                 return;
00129         }
00130 
00131         aucBuffer = aucFillInfoBuffer(pFile, pTable,
00132                         aulBBD, tBBDLen, aulSBD, tSBDLen,
00133                         ulBeginDocpInfo, tDocpInfoLen);
00134         if (aucBuffer == NULL) {
00135                 return;
00136         }
00137 
00138         usTmp = usGetWord(0x00, aucBuffer);
00139         tDocument.ucHdrFtrSpecification = (UCHAR)(usTmp >> 8); /* grpfIhdt */
00140         tDocument.usDefaultTabWidth = usGetWord(0x0a, aucBuffer); /* dxaTab */
00141         ulTmp = ulGetLong(0x14, aucBuffer); /* dttmCreated */
00142         tDocument.tCreateDate = tConvertDTTM(ulTmp);
00143         ulTmp = ulGetLong(0x18, aucBuffer); /* dttmRevised */
00144         tDocument.tRevisedDate = tConvertDTTM(ulTmp);
00145         vCreateDocumentInfoList(&tDocument);
00146 
00147         aucBuffer = xfree(aucBuffer);
00148 } /* end of vGet8DopInfo */
00149 
00150 /*
00151  * Fill the section information block with information
00152  * from a Word 8/9/10/11 file.
00153  */
00154 static void
00155 vGet8SectionInfo(const UCHAR *aucGrpprl, size_t tBytes,
00156                 section_block_type *pSection)
00157 {
00158         UINT    uiIndex;
00159         int     iFodoOff, iInfoLen, iSize, iTmp;
00160         USHORT  usCcol;
00161         UCHAR   ucTmp;
00162 
00163         fail(aucGrpprl == NULL || pSection == NULL);
00164 
00165         iFodoOff = 0;
00166         while (tBytes >= (size_t)iFodoOff + 2) {
00167                 iInfoLen = 0;
00168                 switch (usGetWord(iFodoOff, aucGrpprl)) {
00169                 case 0x3009:    /* bkc */
00170                         ucTmp = ucGetByte(iFodoOff + 2, aucGrpprl);
00171                         DBG_DEC(ucTmp);
00172                         pSection->bNewPage = ucTmp != 0 && ucTmp != 1;
00173                         break;
00174                 case 0x3014:    /* grpfIhdt */
00175                         pSection->ucHdrFtrSpecification =
00176                                         ucGetByte(iFodoOff + 2, aucGrpprl);
00177                         break;
00178                 case 0x500b:    /* ccolM1 */
00179                         usCcol = 1 + usGetWord(iFodoOff + 2, aucGrpprl);
00180                         DBG_DEC(usCcol);
00181                         break;
00182                 case 0xd202:    /* olstAnm */
00183                         iSize = (int)ucGetByte(iFodoOff + 2, aucGrpprl);
00184                         DBG_DEC_C(iSize != 212, iSize);
00185                         for (uiIndex = 0, iTmp = iFodoOff + 3;
00186                              uiIndex < 9 && iTmp < iFodoOff + 3 + iSize - 15;
00187                              uiIndex++, iTmp += 16) {
00188                                 pSection->aucNFC[uiIndex] =
00189                                                 ucGetByte(iTmp, aucGrpprl);
00190                                 DBG_DEC(pSection->aucNFC[uiIndex]);
00191                                 ucTmp = ucGetByte(iTmp + 3, aucGrpprl);
00192                                 DBG_HEX(ucTmp);
00193                                 if ((ucTmp & BIT(2)) != 0) {
00194                                         pSection->usNeedPrevLvl |=
00195                                                         (USHORT)BIT(uiIndex);
00196                                 }
00197                                 if ((ucTmp & BIT(3)) != 0) {
00198                                         pSection->usHangingIndent |=
00199                                                         (USHORT)BIT(uiIndex);
00200                                 }
00201                         }
00202                         DBG_HEX(pSection->usNeedPrevLvl);
00203                         DBG_HEX(pSection->usHangingIndent);
00204                         break;
00205                 default:
00206                         break;
00207                 }
00208                 if (iInfoLen <= 0) {
00209                         iInfoLen = iGet8InfoLength(iFodoOff, aucGrpprl);
00210                         fail(iInfoLen <= 0);
00211                 }
00212                 iFodoOff += iInfoLen;
00213         }
00214 } /* end of vGet8SectionInfo */
00215 
00216 /*
00217  * Build the lists with Section Property Information for Word 8/9/10/11 files
00218  */
00219 void
00220 vGet8SepInfo(FILE *pFile, const pps_info_type *pPPS,
00221         const ULONG *aulBBD, size_t tBBDLen,
00222         const ULONG *aulSBD, size_t tSBDLen,
00223         const UCHAR *aucHeader)
00224 {
00225         section_block_type      tSection;
00226         ULONG   *aulSectPage, *aulCharPos;
00227         UCHAR   *aucBuffer, *aucFpage;
00228         ULONG   ulBeginOfText, ulTextOffset, ulBeginSectInfo;
00229         size_t  tSectInfoLen, tIndex, tOffset, tLen, tBytes;
00230         UCHAR   aucTmp[2];
00231 
00232         fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
00233         fail(aulBBD == NULL || aulSBD == NULL);
00234 
00235         ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */
00236         NO_DBG_HEX(ulBeginOfText);
00237         ulBeginSectInfo = ulGetLong(0xca, aucHeader); /* fcPlcfsed */
00238         NO_DBG_HEX(ulBeginSectInfo);
00239         tSectInfoLen = (size_t)ulGetLong(0xce, aucHeader); /* lcbPlcfsed */
00240         NO_DBG_DEC(tSectInfoLen);
00241         if (tSectInfoLen < 4) {
00242                 DBG_DEC(tSectInfoLen);
00243                 return;
00244         }
00245 
00246         aucBuffer = aucFillInfoBuffer(pFile, &pPPS->tTable,
00247                         aulBBD, tBBDLen, aulSBD, tSBDLen,
00248                         ulBeginSectInfo, tSectInfoLen);
00249         if (aucBuffer == NULL) {
00250                 return;
00251         }
00252         NO_DBG_PRINT_BLOCK(aucBuffer, tSectInfoLen);
00253 
00254         /* Read the Section Descriptors */
00255         tLen = (tSectInfoLen - 4) / 16;
00256         /* Save the section offsets */
00257         aulCharPos = xcalloc(tLen, sizeof(ULONG));
00258         for (tIndex = 0, tOffset = 0;
00259              tIndex < tLen;
00260              tIndex++, tOffset += 4) {
00261                 ulTextOffset = ulGetLong(tOffset, aucBuffer);
00262                 NO_DBG_HEX(ulTextOffset);
00263                 aulCharPos[tIndex] = ulBeginOfText + ulTextOffset;
00264                 NO_DBG_HEX(aulCharPos[tIndex]);
00265         }
00266         /* Save the Sepx offsets */
00267         aulSectPage = xcalloc(tLen, sizeof(ULONG));
00268         for (tIndex = 0, tOffset = (tLen + 1) * 4;
00269              tIndex < tLen;
00270              tIndex++, tOffset += 12) {
00271                  aulSectPage[tIndex] = ulGetLong(tOffset + 2, aucBuffer);
00272                  NO_DBG_HEX(aulSectPage[tIndex]); /* fcSepx */
00273         }
00274         aucBuffer = xfree(aucBuffer);
00275 
00276         /* Read the Section Properties */
00277         for (tIndex = 0; tIndex < tLen; tIndex++) {
00278                 if (aulSectPage[tIndex] == FC_INVALID) {
00279                         vDefault2SectionInfoList(aulCharPos[tIndex]);
00280                         continue;
00281                 }
00282                 /* Get the number of bytes to read */
00283                 if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB,
00284                                 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
00285                                 aucTmp, aulSectPage[tIndex], 2)) {
00286                         continue;
00287                 }
00288                 tBytes = 2 + (size_t)usGetWord(0, aucTmp);
00289                 NO_DBG_DEC(tBytes);
00290                 /* Read the bytes */
00291                 aucFpage = xmalloc(tBytes);
00292                 if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB,
00293                                 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
00294                                 aucFpage, aulSectPage[tIndex], tBytes)) {
00295                         aucFpage = xfree(aucFpage);
00296                         continue;
00297                 }
00298                 NO_DBG_PRINT_BLOCK(aucFpage, tBytes);
00299                 /* Process the bytes */
00300                 vGetDefaultSection(&tSection);
00301                 vGet8SectionInfo(aucFpage + 2, tBytes - 2, &tSection);
00302                 vAdd2SectionInfoList(&tSection, aulCharPos[tIndex]);
00303                 aucFpage = xfree(aucFpage);
00304         }
00305         aulCharPos = xfree(aulCharPos);
00306         aulSectPage = xfree(aulSectPage);
00307 } /* end of vGet8SepInfo */
00308 
00309 /*
00310  * Build the list with Header/Footer Information for Word 8/9/10/11 files
00311  */
00312 void
00313 vGet8HdrFtrInfo(FILE *pFile, const pps_type *pTable,
00314         const ULONG *aulBBD, size_t tBBDLen,
00315         const ULONG *aulSBD, size_t tSBDLen,
00316         const UCHAR *aucHeader)
00317 {
00318         ULONG   *aulCharPos;
00319         UCHAR   *aucBuffer;
00320         ULONG   ulHdrFtrOffset, ulBeginHdrFtrInfo;
00321         size_t  tHdrFtrInfoLen, tIndex, tOffset, tLen;
00322 
00323         fail(pFile == NULL || pTable == NULL || aucHeader == NULL);
00324         fail(aulBBD == NULL || aulSBD == NULL);
00325 
00326         ulBeginHdrFtrInfo = ulGetLong(0xf2, aucHeader); /* fcPlcfhdd */
00327         NO_DBG_HEX(ulBeginHdrFtrInfo);
00328         tHdrFtrInfoLen = (size_t)ulGetLong(0xf6, aucHeader); /* lcbPlcfhdd */
00329         NO_DBG_DEC(tHdrFtrInfoLen);
00330         if (tHdrFtrInfoLen < 8) {
00331                 DBG_DEC_C(tHdrFtrInfoLen != 0, tHdrFtrInfoLen);
00332                 return;
00333         }
00334 
00335         aucBuffer = aucFillInfoBuffer(pFile, pTable,
00336                         aulBBD, tBBDLen, aulSBD, tSBDLen,
00337                         ulBeginHdrFtrInfo, tHdrFtrInfoLen);
00338         if (aucBuffer == NULL) {
00339                 return;
00340         }
00341         NO_DBG_PRINT_BLOCK(aucBuffer, tHdrFtrInfoLen);
00342 
00343         tLen = tHdrFtrInfoLen / 4 - 1;
00344         DBG_DEC_C(tLen % 12 != 1 && tLen % 12 != 7, tLen);
00345         /* Save the header/footer offsets */
00346         aulCharPos = xcalloc(tLen, sizeof(ULONG));
00347         for (tIndex = 0, tOffset = 0;
00348              tIndex < tLen;
00349              tIndex++, tOffset += 4) {
00350                 ulHdrFtrOffset = ulGetLong(tOffset, aucBuffer);
00351                 NO_DBG_HEX(ulHdrFtrOffset);
00352                 aulCharPos[tIndex] = ulHdrFtrOffset2CharPos(ulHdrFtrOffset);
00353                 NO_DBG_HEX(aulCharPos[tIndex]);
00354         }
00355         vCreat8HdrFtrInfoList(aulCharPos, tLen);
00356         /* Clean up and leave */
00357         aulCharPos = xfree(aulCharPos);
00358         aucBuffer = xfree(aucBuffer);
00359 } /* end of vGet8HdrFtrInfo */
00360 
00361 /*
00362  * Translate the rowinfo to a member of the row_info enumeration
00363  */
00364 row_info_enum
00365 eGet8RowInfo(int iFodo,
00366         const UCHAR *aucGrpprl, int iBytes, row_block_type *pRow)
00367 {
00368         int     iFodoOff, iInfoLen;
00369         int     iIndex, iSize, iCol;
00370         int     iPosCurr, iPosPrev;
00371         USHORT  usTmp;
00372         BOOL    bFound2416_0, bFound2416_1, bFound2417_0, bFound2417_1;
00373         BOOL    bFound244b_0, bFound244b_1, bFound244c_0, bFound244c_1;
00374         BOOL    bFoundd608;
00375 
00376         fail(iFodo < 0 || aucGrpprl == NULL || pRow == NULL);
00377 
00378         iFodoOff = 0;
00379         bFound2416_0 = FALSE;
00380         bFound2416_1 = FALSE;
00381         bFound2417_0 = FALSE;
00382         bFound2417_1 = FALSE;
00383         bFound244b_0 = FALSE;
00384         bFound244b_1 = FALSE;
00385         bFound244c_0 = FALSE;
00386         bFound244c_1 = FALSE;
00387         bFoundd608 = FALSE;
00388         while (iBytes >= iFodoOff + 2) {
00389                 iInfoLen = 0;
00390                 switch (usGetWord(iFodo + iFodoOff, aucGrpprl)) {
00391                 case 0x2416:    /* fInTable */
00392                         if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
00393                                 bFound2416_1 = TRUE;
00394                         } else {
00395                                 bFound2416_0 = TRUE;
00396                         }
00397                         break;
00398                 case 0x2417:    /* fTtp */
00399                         if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
00400                                 bFound2417_1 = TRUE;
00401                         } else {
00402                                 bFound2417_0 = TRUE;
00403                         }
00404                         break;
00405                 case 0x244b:    /* sub-table fInTable */
00406                         if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
00407                                 bFound244b_1 = TRUE;
00408                         } else {
00409                                 bFound244b_0 = TRUE;
00410                         }
00411                         break;
00412                 case 0x244c:    /* sub-table fTtp */
00413                         if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) {
00414                                 bFound244c_1 = TRUE;
00415                         } else {
00416                                 bFound244c_0 = TRUE;
00417                         }
00418                         break;
00419                 case 0x6424:    /* brcTop */
00420                         usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
00421                         usTmp &= 0xff00;
00422                         NO_DBG_DEC(usTmp >> 8);
00423                         if (usTmp == 0) {
00424                                 pRow->ucBorderInfo &= ~TABLE_BORDER_TOP;
00425                         } else {
00426                                 pRow->ucBorderInfo |= TABLE_BORDER_TOP;
00427                         }
00428                         break;
00429                 case 0x6425:    /* brcLeft */
00430                         usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
00431                         usTmp &= 0xff00;
00432                         NO_DBG_DEC(usTmp >> 8);
00433                         if (usTmp == 0) {
00434                                 pRow->ucBorderInfo &= ~TABLE_BORDER_LEFT;
00435                         } else {
00436                                 pRow->ucBorderInfo |= TABLE_BORDER_LEFT;
00437                         }
00438                         break;
00439                 case 0x6426:    /* brcBottom */
00440                         usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
00441                         usTmp &= 0xff00;
00442                         NO_DBG_DEC(usTmp >> 8);
00443                         if (usTmp == 0) {
00444                                 pRow->ucBorderInfo &= ~TABLE_BORDER_BOTTOM;
00445                         } else {
00446                                 pRow->ucBorderInfo |= TABLE_BORDER_BOTTOM;
00447                         }
00448                         break;
00449                 case 0x6427:    /* brcRight */
00450                         usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
00451                         usTmp &= 0xff00;
00452                         NO_DBG_DEC(usTmp >> 8);
00453                         if (usTmp == 0) {
00454                                 pRow->ucBorderInfo &= ~TABLE_BORDER_RIGHT;
00455                         } else {
00456                                 pRow->ucBorderInfo |= TABLE_BORDER_RIGHT;
00457                         }
00458                         break;
00459                 case 0xd606:    /* cDefTable10 */
00460                         DBG_MSG("0xd606: sprmTDefTable10");
00461                         iSize = (int)usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
00462                         DBG_DEC(iSize);
00463                         break;
00464                 case 0xd608:    /* cDefTable */
00465                         iSize = (int)usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
00466                         if (iSize < 6 || iBytes < iFodoOff + 8) {
00467                                 DBG_DEC(iSize);
00468                                 DBG_DEC(iFodoOff);
00469                                 iInfoLen = 2;
00470                                 break;
00471                         }
00472                         iCol = (int)ucGetByte(iFodo + iFodoOff + 4, aucGrpprl);
00473                         if (iCol < 1 ||
00474                             iBytes < iFodoOff + 4 + (iCol + 1) * 2) {
00475                                 DBG_DEC(iCol);
00476                                 DBG_DEC(iFodoOff);
00477                                 iInfoLen = 2;
00478                                 break;
00479                         }
00480                         if (iCol >= (int)elementsof(pRow->asColumnWidth)) {
00481                                 DBG_DEC(iCol);
00482                                 werr(1, "The number of columns is corrupt");
00483                         }
00484                         pRow->ucNumberOfColumns = (UCHAR)iCol;
00485                         iPosPrev = (int)(short)usGetWord(
00486                                         iFodo + iFodoOff + 5,
00487                                         aucGrpprl);
00488                         for (iIndex = 0; iIndex < iCol; iIndex++) {
00489                                 iPosCurr = (int)(short)usGetWord(
00490                                         iFodo + iFodoOff + 7 + iIndex * 2,
00491                                         aucGrpprl);
00492                                 pRow->asColumnWidth[iIndex] =
00493                                                 (short)(iPosCurr - iPosPrev);
00494                                 iPosPrev = iPosCurr;
00495                         }
00496                         bFoundd608 = TRUE;
00497                         break;
00498                 default:
00499                         break;
00500                 }
00501                 if (iInfoLen <= 0) {
00502                         iInfoLen =
00503                                 iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
00504                         fail(iInfoLen <= 0);
00505                 }
00506                 iFodoOff += iInfoLen;
00507         }
00508 
00509         if (bFound2417_1 && bFoundd608) {
00510                 return found_end_of_row;
00511         }
00512         if (bFound2417_0 && !bFoundd608) {
00513                 return found_not_end_of_row;
00514         }
00515         if (bFound2416_1 || bFound244b_1) {
00516                 return found_a_cell;
00517         }
00518         if (bFound2416_0 || bFound244b_0) {
00519                 return found_not_a_cell;
00520         }
00521         return found_nothing;
00522 } /* end of eGet8RowInfo */
00523 
00524 /*
00525  * Fill the style information block with information
00526  * from a Word 8/9/10/11 file.
00527  */
00528 void
00529 vGet8StyleInfo(int iFodo,
00530         const UCHAR *aucGrpprl, int iBytes, style_block_type *pStyle)
00531 {
00532         list_block_type tList6;
00533         const list_block_type   *pList;
00534         int     iFodoOff, iInfoLen;
00535         int     iTmp, iDel, iAdd, iBefore;
00536         USHORT  usOpCode, usTmp;
00537         short   sTmp;
00538 
00539         fail(iFodo < 0 || aucGrpprl == NULL || pStyle == NULL);
00540 
00541         NO_DBG_DEC_C(pStyle->usListIndex != 0, pStyle->usIstd);
00542         NO_DBG_DEC_C(pStyle->usListIndex != 0, pStyle->usListIndex);
00543 
00544         (void)memset(&tList6, 0, sizeof(tList6));
00545 
00546         iFodoOff = 0;
00547         while (iBytes >= iFodoOff + 2) {
00548                 iInfoLen = 0;
00549                 usOpCode = usGetWord(iFodo + iFodoOff, aucGrpprl);
00550                 switch (usOpCode) {
00551                 case 0x2403:    /* jc */
00552                         pStyle->ucAlignment = ucGetByte(
00553                                         iFodo + iFodoOff + 2, aucGrpprl);
00554                         break;
00555                 case 0x260a:    /* ilvl */
00556                         pStyle->ucListLevel =
00557                                 ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
00558                         NO_DBG_DEC(pStyle->ucListLevel);
00559                         pStyle->ucNumLevel = pStyle->ucListLevel;
00560                         break;
00561                 case 0x4600:    /* istd */
00562                         usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
00563                         NO_DBG_DEC(usTmp);
00564                         break;
00565                 case 0x460b:    /* ilfo */
00566                         pStyle->usListIndex =
00567                                 usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
00568                         NO_DBG_DEC(pStyle->usListIndex);
00569                         break;
00570                 case 0x4610: /* Nest dxaLeft */
00571                         sTmp = (short)usGetWord(
00572                                         iFodo + iFodoOff + 2, aucGrpprl);
00573                         pStyle->sLeftIndent += sTmp;
00574                         if (pStyle->sLeftIndent < 0) {
00575                                 pStyle->sLeftIndent = 0;
00576                         }
00577                         DBG_DEC(sTmp);
00578                         DBG_DEC(pStyle->sLeftIndent);
00579                         break;
00580                 case 0xc60d:    /* ChgTabsPapx */
00581                 case 0xc615:    /* ChgTabs */
00582                         iTmp = (int)ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
00583                         if (iTmp < 2) {
00584                                 iInfoLen = 1;
00585                                 break;
00586                         }
00587                         NO_DBG_DEC(iTmp);
00588                         iDel = (int)ucGetByte(iFodo + iFodoOff + 3, aucGrpprl);
00589                         if (iTmp < 2 + 2 * iDel) {
00590                                 iInfoLen = 1;
00591                                 break;
00592                         }
00593                         NO_DBG_DEC(iDel);
00594                         iAdd = (int)ucGetByte(
00595                                 iFodo + iFodoOff + 4 + 2 * iDel, aucGrpprl);
00596                         if (iTmp < 2 + 2 * iDel + 2 * iAdd) {
00597                                 iInfoLen = 1;
00598                                 break;
00599                         }
00600                         NO_DBG_DEC(iAdd);
00601                         break;
00602                 case 0x840e:    /* dxaRight */
00603                         pStyle->sRightIndent = (short)usGetWord(
00604                                         iFodo + iFodoOff + 2, aucGrpprl);
00605                         NO_DBG_DEC(pStyle->sRightIndent);
00606                         break;
00607                 case 0x840f:    /* dxaLeft */
00608                         pStyle->sLeftIndent = (short)usGetWord(
00609                                         iFodo + iFodoOff + 2, aucGrpprl);
00610                         NO_DBG_DEC(pStyle->sLeftIndent);
00611                         break;
00612                 case 0x8411:    /* dxaLeft1 */
00613                         pStyle->sLeftIndent1 = (short)usGetWord(
00614                                         iFodo + iFodoOff + 2, aucGrpprl);
00615                         NO_DBG_DEC(pStyle->sLeftIndent1);
00616                         break;
00617                 case 0xa413:    /* dyaBefore */
00618                         pStyle->usBeforeIndent = usGetWord(
00619                                         iFodo + iFodoOff + 2, aucGrpprl);
00620                         NO_DBG_DEC(pStyle->usBeforeIndent);
00621                         break;
00622                 case 0xa414:    /* dyaAfter */
00623                         pStyle->usAfterIndent = usGetWord(
00624                                         iFodo + iFodoOff + 2, aucGrpprl);
00625                         NO_DBG_DEC(pStyle->usAfterIndent);
00626                         break;
00627                 case 0xc63e:    /* anld */
00628                         iTmp = (int)ucGetByte(
00629                                         iFodo + iFodoOff + 2, aucGrpprl);
00630                         DBG_DEC_C(iTmp < 84, iTmp);
00631                         if (iTmp >= 1) {
00632                                 tList6.ucNFC = ucGetByte(
00633                                         iFodo + iFodoOff + 3, aucGrpprl);
00634                         }
00635                         if (tList6.ucNFC != LIST_BULLETS && iTmp >= 2) {
00636                                 iBefore = (int)ucGetByte(
00637                                         iFodo + iFodoOff + 4, aucGrpprl);
00638                         } else {
00639                                 iBefore = 0;
00640                         }
00641                         if (iTmp >= 12) {
00642                                 tList6.ulStartAt = (ULONG)usGetWord(
00643                                         iFodo + iFodoOff + 13, aucGrpprl);
00644                         }
00645                         if (iTmp >= iBefore + 22) {
00646                                 tList6.usListChar = usGetWord(
00647                                         iFodo + iFodoOff + iBefore + 23,
00648                                         aucGrpprl);
00649                                 DBG_HEX(tList6.usListChar);
00650                         }
00651                         break;
00652                 default:
00653                         NO_DBG_HEX(usOpCode);
00654                         break;
00655                 }
00656                 if (iInfoLen <= 0) {
00657                         iInfoLen =
00658                                 iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
00659                         fail(iInfoLen <= 0);
00660                 }
00661                 iFodoOff += iInfoLen;
00662         }
00663 
00664         if (pStyle->usListIndex == 2047) {
00665                 /* Old style list */
00666                 pStyle->usStartAt = (USHORT)tList6.ulStartAt;
00667                 pStyle->usListChar = tList6.usListChar;
00668                 pStyle->ucNFC = tList6.ucNFC;
00669         } else {
00670                 /* New style list */
00671                 pList = pGetListInfo(pStyle->usListIndex, pStyle->ucListLevel);
00672                 if (pList != NULL) {
00673                         pStyle->bNoRestart = pList->bNoRestart;
00674                         fail(pList->ulStartAt > (ULONG)USHRT_MAX);
00675                         pStyle->usStartAt = (USHORT)pList->ulStartAt;
00676                         pStyle->usListChar = pList->usListChar;
00677                         pStyle->ucNFC = pList->ucNFC;
00678                         if (pStyle->sLeftIndent <= 0) {
00679                                 pStyle->sLeftIndent = pList->sLeftIndent;
00680                         }
00681                 }
00682         }
00683 } /* end of vGet8StyleInfo */
00684 
00685 /*
00686  * Get the left indentation value from the style information block
00687  *
00688  * Returns the value when found, otherwise 0
00689  */
00690 static short
00691 sGetLeftIndent(const UCHAR *aucGrpprl, size_t tBytes)
00692 {
00693         int     iOffset, iInfoLen;
00694         USHORT  usOpCode, usTmp;
00695 
00696         fail(aucGrpprl == NULL);
00697 
00698         iOffset = 0;
00699         while (tBytes >= (size_t)iOffset + 4) {
00700                 usOpCode = usGetWord(iOffset, aucGrpprl);
00701                 if (usOpCode == 0x840f) {       /* dxaLeft */
00702                         usTmp = usGetWord(iOffset + 2, aucGrpprl);
00703                         if (usTmp <= 0x7fff) {
00704                                 NO_DBG_DEC(usTmp);
00705                                 return (short)usTmp;
00706                         }
00707                 }
00708                 iInfoLen = iGet8InfoLength(iOffset, aucGrpprl);
00709                 fail(iInfoLen <= 0);
00710                 iOffset += iInfoLen;
00711         }
00712         return 0;
00713 } /* end of sGetLeftIndent */
00714 
00715 /*
00716  * Build the list with List Information for Word 8/9/10/11 files
00717  */
00718 void
00719 vGet8LstInfo(FILE *pFile, const pps_info_type *pPPS,
00720         const ULONG *aulBBD, size_t tBBDLen,
00721         const ULONG *aulSBD, size_t tSBDLen,
00722         const UCHAR *aucHeader)
00723 {
00724         list_block_type tList;
00725         const ULONG     *aulBlockDepot;
00726         UCHAR   *aucLfoInfo, *aucLstfInfo, *aucPapx, *aucXString;
00727         ULONG   ulBeginLfoInfo, ulBeginLstfInfo, ulBeginLvlfInfo;
00728         ULONG   ulListID, ulStart;
00729         size_t  tBlockDepotLen, tBlockSize;
00730         size_t  tLfoInfoLen, tLstfInfoLen, tPapxLen, tXstLen, tOff;
00731         size_t  tLstfRecords, tStart, tIndex;
00732         int     iNums;
00733         USHORT  usIstd;
00734         UCHAR   ucTmp, ucListLevel, ucMaxLevel, ucChpxLen;
00735         UCHAR   aucLvlfInfo[28], aucXst[2];
00736 
00737         fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
00738         fail(aulBBD == NULL || aulSBD == NULL);
00739 
00740         NO_DBG_DEC(pPPS->tTable.ulSB);
00741         NO_DBG_HEX(pPPS->tTable.ulSize);
00742         if (pPPS->tTable.ulSize == 0) {
00743                 DBG_MSG("No list information");
00744                 return;
00745         }
00746 
00747         if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) {
00748                 /* Use the Small Block Depot */
00749                 aulBlockDepot = aulSBD;
00750                 tBlockDepotLen = tSBDLen;
00751                 tBlockSize = SMALL_BLOCK_SIZE;
00752         } else {
00753                 /* Use the Big Block Depot */
00754                 aulBlockDepot = aulBBD;
00755                 tBlockDepotLen = tBBDLen;
00756                 tBlockSize = BIG_BLOCK_SIZE;
00757         }
00758 
00759         /* LFO (List Format Override) */
00760         ulBeginLfoInfo = ulGetLong(0x2ea, aucHeader); /* fcPlfLfo */
00761         DBG_HEX(ulBeginLfoInfo);
00762         tLfoInfoLen = (size_t)ulGetLong(0x2ee, aucHeader); /* lcbPlfLfo */
00763         DBG_DEC(tLfoInfoLen);
00764         if (tLfoInfoLen == 0) {
00765                 DBG_MSG("No lists in this document");
00766                 return;
00767         }
00768 
00769         aucLfoInfo = xmalloc(tLfoInfoLen);
00770         if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
00771                         aulBlockDepot, tBlockDepotLen, tBlockSize,
00772                         aucLfoInfo, ulBeginLfoInfo, tLfoInfoLen)) {
00773                 aucLfoInfo = xfree(aucLfoInfo);
00774                 return;
00775         }
00776         NO_DBG_PRINT_BLOCK(aucLfoInfo, tLfoInfoLen);
00777         vBuildLfoList(aucLfoInfo, tLfoInfoLen);
00778         aucLfoInfo = xfree(aucLfoInfo);
00779 
00780         /* LSTF (LiST data on File) */
00781         ulBeginLstfInfo = ulGetLong(0x2e2, aucHeader); /* fcPlcfLst */
00782         DBG_HEX(ulBeginLstfInfo);
00783         tLstfInfoLen = (size_t)ulGetLong(0x2e6, aucHeader); /* lcbPlcfLst */
00784         DBG_DEC(tLstfInfoLen);
00785         if (tLstfInfoLen == 0) {
00786                 DBG_MSG("No list data on file");
00787                 return;
00788         }
00789 
00790         aucLstfInfo = xmalloc(tLstfInfoLen);
00791         if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
00792                         aulBlockDepot, tBlockDepotLen, tBlockSize,
00793                         aucLstfInfo, ulBeginLstfInfo, tLstfInfoLen)) {
00794                 aucLstfInfo = xfree(aucLstfInfo);
00795                 return;
00796         }
00797         NO_DBG_PRINT_BLOCK(aucLstfInfo, tLstfInfoLen);
00798 
00799         tLstfRecords = (size_t)usGetWord(0, aucLstfInfo);
00800         if (2 + tLstfRecords * 28 < tLstfInfoLen) {
00801                 DBG_DEC(2 + tLstfRecords * 28);
00802                 DBG_DEC(tLstfInfoLen);
00803                 aucLstfInfo = xfree(aucLstfInfo);
00804                 return;
00805         }
00806 
00807         /* LVLF (List leVeL on File) */
00808         ulBeginLvlfInfo = ulBeginLstfInfo + tLstfInfoLen;
00809         DBG_HEX(ulBeginLvlfInfo);
00810 
00811         aucXString = NULL;
00812         ulStart = ulBeginLvlfInfo;
00813 
00814         for (tIndex = 0, tStart = 2;
00815              tIndex < tLstfRecords;
00816              tIndex++, tStart += 28) {
00817                 ulListID = ulGetLong(tStart, aucLstfInfo);
00818                 NO_DBG_HEX(ulListID);
00819                 ucTmp = ucGetByte(tStart + 26, aucLstfInfo);
00820                 ucMaxLevel = odd(ucTmp) ? 1 : 9;
00821                 for (ucListLevel = 0; ucListLevel < ucMaxLevel; ucListLevel++) {
00822                         fail(aucXString != NULL);
00823                         usIstd = usGetWord(
00824                                         tStart + 8 + 2 * (size_t)ucListLevel,
00825                                         aucLstfInfo);
00826                         DBG_DEC_C(usIstd != STI_NIL, usIstd);
00827                         NO_DBG_HEX(ulStart);
00828                         (void)memset(&tList, 0, sizeof(tList));
00829                         /* Read the lvlf (List leVeL on File) */
00830                         if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
00831                                         aulBlockDepot, tBlockDepotLen,
00832                                         tBlockSize, aucLvlfInfo,
00833                                         ulStart, sizeof(aucLvlfInfo))) {
00834                                 aucLstfInfo = xfree(aucLstfInfo);
00835                                 return;
00836                         }
00837                         NO_DBG_PRINT_BLOCK(aucLvlfInfo, sizeof(aucLvlfInfo));
00838                         if (bAllZero(aucLvlfInfo, sizeof(aucLvlfInfo))) {
00839                                 tList.ulStartAt = 1;
00840                                 tList.ucNFC = 0x00;
00841                                 tList.bNoRestart = FALSE;
00842                         } else {
00843                                 tList.ulStartAt = ulGetLong(0, aucLvlfInfo);
00844                                 tList.ucNFC = ucGetByte(4, aucLvlfInfo);
00845                                 ucTmp = ucGetByte(5, aucLvlfInfo);
00846                                 tList.bNoRestart = (ucTmp & BIT(3)) != 0;
00847                                 DBG_MSG_C((ucTmp & BIT(4)) != 0 &&
00848                                         (ucTmp & BIT(6)) != 0, "Found one");
00849                         }
00850                         ulStart += sizeof(aucLvlfInfo);
00851                         tPapxLen = (size_t)ucGetByte(25, aucLvlfInfo);
00852                         if (tPapxLen != 0) {
00853                                 aucPapx = xmalloc(tPapxLen);
00854                                 /* Read the Papx */
00855                                 if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
00856                                                 aulBlockDepot, tBlockDepotLen,
00857                                                 tBlockSize, aucPapx,
00858                                                 ulStart, tPapxLen)) {
00859                                         aucPapx = xfree(aucPapx);
00860                                         aucLstfInfo = xfree(aucLstfInfo);
00861                                         return;
00862                                 }
00863                                 NO_DBG_PRINT_BLOCK(aucPapx, tPapxLen);
00864                                 tList.sLeftIndent =
00865                                         sGetLeftIndent(aucPapx, tPapxLen);
00866                                 aucPapx = xfree(aucPapx);
00867                         }
00868                         ulStart += tPapxLen;
00869                         ucChpxLen = ucGetByte(24, aucLvlfInfo);
00870                         ulStart += (ULONG)ucChpxLen;
00871                         /* Read the length of the XString */
00872                         if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
00873                                         aulBlockDepot, tBlockDepotLen,
00874                                         tBlockSize, aucXst,
00875                                         ulStart, sizeof(aucXst))) {
00876                                 aucLstfInfo = xfree(aucLstfInfo);
00877                                 return;
00878                         }
00879                         NO_DBG_PRINT_BLOCK(aucXst, sizeof(aucXst));
00880                         tXstLen = (size_t)usGetWord(0, aucXst);
00881                         ulStart += sizeof(aucXst);
00882                         if (tXstLen == 0) {
00883                                 tList.usListChar = DEFAULT_LISTCHAR;
00884                                 vAdd2ListInfoList(ulListID,
00885                                                 usIstd,
00886                                                 ucListLevel,
00887                                                 &tList);
00888                                 continue;
00889                         }
00890                         tXstLen *= 2;   /* Length in chars to length in bytes */
00891                         aucXString = xmalloc(tXstLen);
00892                         /* Read the XString */
00893                         if (!bReadBuffer(pFile, pPPS->tTable.ulSB,
00894                                         aulBlockDepot, tBlockDepotLen,
00895                                         tBlockSize, aucXString,
00896                                         ulStart, tXstLen)) {
00897                                 aucXString = xfree(aucXString);
00898                                 aucLstfInfo = xfree(aucLstfInfo);
00899                                 return;
00900                         }
00901                         NO_DBG_PRINT_BLOCK(aucXString, tXstLen);
00902                         tOff = 0;
00903                         for (iNums = 6; iNums < 15; iNums++) {
00904                                 ucTmp = ucGetByte(iNums, aucLvlfInfo);
00905                                 if (ucTmp == 0) {
00906                                         break;
00907                                 }
00908                                 tOff = (size_t)ucTmp;
00909                         }
00910                         tOff *= 2;      /* Offset in chars to offset in bytes */
00911                         NO_DBG_DEC(tOff);
00912                         if (tList.ucNFC == LIST_SPECIAL ||
00913                             tList.ucNFC == LIST_SPECIAL2 ||
00914                             tList.ucNFC == LIST_BULLETS) {
00915                                 tList.usListChar = usGetWord(0, aucXString);
00916                         } else if (tOff != 0 && tOff < tXstLen) {
00917                                 tList.usListChar = usGetWord(tOff, aucXString);
00918                         } else {
00919                                 tList.usListChar = DEFAULT_LISTCHAR;
00920                         }
00921                         vAdd2ListInfoList(ulListID,
00922                                         usIstd,
00923                                         ucListLevel,
00924                                         &tList);
00925                         ulStart += tXstLen;
00926                         aucXString = xfree(aucXString);
00927                 }
00928         }
00929         aucLstfInfo = xfree(aucLstfInfo);
00930 } /* end of vGet8LstInfo */
00931 
00932 /*
00933  * Build the lists with Paragraph Information for Word 8/9/10/11 files
00934  */
00935 void
00936 vGet8PapInfo(FILE *pFile, const pps_info_type *pPPS,
00937         const ULONG *aulBBD, size_t tBBDLen,
00938         const ULONG *aulSBD, size_t tSBDLen,
00939         const UCHAR *aucHeader)
00940 {
00941         row_block_type          tRow;
00942         style_block_type        tStyle;
00943         ULONG           *aulParfPage;
00944         UCHAR   *aucBuffer;
00945         ULONG   ulCharPos, ulCharPosFirst, ulCharPosLast;
00946         ULONG   ulBeginParfInfo;
00947         size_t  tParfInfoLen, tOffset, tLen;
00948         int     iIndex, iIndex2, iRun, iFodo, iLen;
00949         row_info_enum   eRowInfo;
00950         USHORT  usIstd;
00951         UCHAR   aucFpage[BIG_BLOCK_SIZE];
00952 
00953         fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
00954         fail(aulBBD == NULL || aulSBD == NULL);
00955 
00956         ulBeginParfInfo = ulGetLong(0x102, aucHeader); /* fcPlcfbtePapx */
00957         NO_DBG_HEX(ulBeginParfInfo);
00958         tParfInfoLen = (size_t)ulGetLong(0x106, aucHeader); /* lcbPlcfbtePapx */
00959         NO_DBG_DEC(tParfInfoLen);
00960         if (tParfInfoLen < 4) {
00961                 DBG_DEC(tParfInfoLen);
00962                 return;
00963         }
00964 
00965         aucBuffer = aucFillInfoBuffer(pFile, &pPPS->tTable,
00966                         aulBBD, tBBDLen, aulSBD, tSBDLen,
00967                         ulBeginParfInfo, tParfInfoLen);
00968         if (aucBuffer == NULL) {
00969                 return;
00970         }
00971         NO_DBG_PRINT_BLOCK(aucBuffer, tParfInfoLen);
00972 
00973         tLen = (tParfInfoLen / 4 - 1) / 2;
00974         aulParfPage = xcalloc(tLen, sizeof(ULONG));
00975         for (iIndex = 0, tOffset = (tLen + 1) * 4;
00976              iIndex < (int)tLen;
00977              iIndex++, tOffset += 4) {
00978                  aulParfPage[iIndex] = ulGetLong(tOffset, aucBuffer);
00979                  NO_DBG_DEC(aulParfPage[iIndex]);
00980         }
00981         DBG_HEX(ulGetLong(0, aucBuffer));
00982         aucBuffer = xfree(aucBuffer);
00983         NO_DBG_PRINT_BLOCK(aucHeader, HEADER_SIZE);
00984 
00985         (void)memset(&tRow, 0, sizeof(tRow));
00986         ulCharPosFirst = CP_INVALID;
00987         for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
00988                 fail(aulParfPage[iIndex] > ULONG_MAX / BIG_BLOCK_SIZE);
00989                 if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB,
00990                                 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
00991                                 aucFpage,
00992                                 aulParfPage[iIndex] * BIG_BLOCK_SIZE,
00993                                 BIG_BLOCK_SIZE)) {
00994                         break;
00995                 }
00996                 NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE);
00997                 iRun = (int)ucGetByte(0x1ff, aucFpage);
00998                 NO_DBG_DEC(iRun);
00999                 for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
01000                         NO_DBG_HEX(ulGetLong(iIndex2 * 4, aucFpage));
01001                         iFodo = 2 * (int)ucGetByte(
01002                                 (iRun + 1) * 4 + iIndex2 * 13, aucFpage);
01003                         if (iFodo <= 0) {
01004                                 continue;
01005                         }
01006 
01007                         iLen = 2 * (int)ucGetByte(iFodo, aucFpage);
01008                         if (iLen == 0) {
01009                                 iFodo++;
01010                                 iLen = 2 * (int)ucGetByte(iFodo, aucFpage);
01011                         }
01012 
01013                         usIstd = usGetWord(iFodo + 1, aucFpage);
01014                         vFillStyleFromStylesheet(usIstd, &tStyle);
01015                         vGet8StyleInfo(iFodo, aucFpage + 3, iLen - 3, &tStyle);
01016                         ulCharPos = ulGetLong(iIndex2 * 4, aucFpage);
01017                         NO_DBG_HEX(ulCharPos);
01018                         tStyle.ulFileOffset = ulCharPos2FileOffsetX(
01019                                                 ulCharPos, &tStyle.eListID);
01020                         vAdd2StyleInfoList(&tStyle);
01021 
01022                         eRowInfo = eGet8RowInfo(iFodo,
01023                                         aucFpage + 3, iLen - 3, &tRow);
01024                         switch (eRowInfo) {
01025                         case found_a_cell:
01026                                 if (ulCharPosFirst != CP_INVALID) {
01027                                         break;
01028                                 }
01029                                 ulCharPosFirst = ulGetLong(
01030                                                 iIndex2 * 4, aucFpage);
01031                                 NO_DBG_HEX(ulCharPosFirst);
01032                                 tRow.ulCharPosStart = ulCharPosFirst;
01033                                 tRow.ulFileOffsetStart =
01034                                         ulCharPos2FileOffset(ulCharPosFirst);
01035                                 NO_DBG_HEX_C(
01036                                         tRow.ulFileOffsetStart == FC_INVALID,
01037                                         ulCharPosFirst);
01038                                 break;
01039                         case found_end_of_row:
01040                                 ulCharPosLast = ulGetLong(
01041                                                 iIndex2 * 4, aucFpage);
01042                                 NO_DBG_HEX(ulCharPosLast);
01043                                 tRow.ulCharPosEnd = ulCharPosLast;
01044                                 tRow.ulFileOffsetEnd =
01045                                         ulCharPos2FileOffset(ulCharPosLast);
01046                                 NO_DBG_HEX_C(tRow.ulFileOffsetEnd == FC_INVALID,
01047                                                         ulCharPosLast);
01048                                 vAdd2RowInfoList(&tRow);
01049                                 (void)memset(&tRow, 0, sizeof(tRow));
01050                                 ulCharPosFirst = CP_INVALID;
01051                                 break;
01052                         case found_nothing:
01053                                 break;
01054                         default:
01055                                 DBG_DEC(eRowInfo);
01056                                 break;
01057                         }
01058                 }
01059         }
01060         aulParfPage = xfree(aulParfPage);
01061 } /* end of vGet8PapInfo */
01062 
01063 /*
01064  * Fill the font information block with information
01065  * from a Word 8/9/10/11 file.
01066  */
01067 void
01068 vGet8FontInfo(int iFodo, USHORT usIstd,
01069         const UCHAR *aucGrpprl, int iBytes, font_block_type *pFont)
01070 {
01071         long    lTmp;
01072         int     iFodoOff, iInfoLen;
01073         USHORT  usFtc0, usFtc1, usFtc2, usTmp;
01074         UCHAR   ucTmp;
01075 
01076         fail(iFodo < 0 || aucGrpprl == NULL || pFont == NULL);
01077 
01078         usFtc0 = USHRT_MAX;
01079         usFtc1 = USHRT_MAX;
01080         usFtc2 = USHRT_MAX;
01081 
01082         iFodoOff = 0;
01083         while (iBytes >= iFodoOff + 2) {
01084                 switch (usGetWord(iFodo + iFodoOff, aucGrpprl)) {
01085                 case 0x0800:    /* fRMarkDel */
01086                         ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
01087                         if (ucTmp == 0) {
01088                                 pFont->usFontStyle &= ~FONT_MARKDEL;
01089                         } else {
01090                                 pFont->usFontStyle |= FONT_MARKDEL;
01091                         }
01092                         break;
01093                 case 0x0835:    /* fBold */
01094                         ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
01095                         switch (ucTmp) {
01096                         case   0:       /* Unset */
01097                                 pFont->usFontStyle &= ~FONT_BOLD;
01098                                 break;
01099                         case   1:       /* Set */
01100                                 pFont->usFontStyle |= FONT_BOLD;
01101                                 break;
01102                         case 128:       /* Unchanged */
01103                                 break;
01104                         case 129:       /* Negation */
01105                                 pFont->usFontStyle ^= FONT_BOLD;
01106                                 break;
01107                         default:
01108                                 DBG_DEC(ucTmp);
01109                                 DBG_FIXME();
01110                                 break;
01111                         }
01112                         break;
01113                 case 0x0836:    /* fItalic */
01114                         ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
01115                         switch (ucTmp) {
01116                         case   0:       /* Unset */
01117                                 pFont->usFontStyle &= ~FONT_ITALIC;
01118                                 break;
01119                         case   1:       /* Set */
01120                                 pFont->usFontStyle |= FONT_ITALIC;
01121                                 break;
01122                         case 128:       /* Unchanged */
01123                                 break;
01124                         case 129:       /* Negation */
01125                                 pFont->usFontStyle ^= FONT_ITALIC;
01126                                 break;
01127                         default:
01128                                 DBG_DEC(ucTmp);
01129                                 DBG_FIXME();
01130                                 break;
01131                         }
01132                         break;
01133                 case 0x0837:    /* fStrike */
01134                         ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
01135                         switch (ucTmp) {
01136                         case   0:       /* Unset */
01137                                 pFont->usFontStyle &= ~FONT_STRIKE;
01138                                 break;
01139                         case   1:       /* Set */
01140                                 pFont->usFontStyle |= FONT_STRIKE;
01141                                 break;
01142                         case 128:       /* Unchanged */
01143                                 break;
01144                         case 129:       /* Negation */
01145                                 pFont->usFontStyle ^= FONT_STRIKE;
01146                                 break;
01147                         default:
01148                                 DBG_DEC(ucTmp);
01149                                 DBG_FIXME();
01150                                 break;
01151                         }
01152                         break;
01153                 case 0x083a:    /* fSmallCaps */
01154                         ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
01155                         switch (ucTmp) {
01156                         case   0:       /* Unset */
01157                                 pFont->usFontStyle &= ~FONT_SMALL_CAPITALS;
01158                                 break;
01159                         case   1:       /* Set */
01160                                 pFont->usFontStyle |= FONT_SMALL_CAPITALS;
01161                                 break;
01162                         case 128:       /* Unchanged */
01163                                 break;
01164                         case 129:       /* Negation */
01165                                 pFont->usFontStyle ^= FONT_SMALL_CAPITALS;
01166                                 break;
01167                         default:
01168                                 DBG_DEC(ucTmp);
01169                                 DBG_FIXME();
01170                                 break;
01171                         }
01172                         break;
01173                 case 0x083b:    /* fCaps */
01174                         ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
01175                         switch (ucTmp) {
01176                         case   0:       /* Unset */
01177                                 pFont->usFontStyle &= ~FONT_CAPITALS;
01178                                 break;
01179                         case   1:       /* Set */
01180                                 pFont->usFontStyle |= FONT_CAPITALS;
01181                                 break;
01182                         case 128:       /* Unchanged */
01183                                 break;
01184                         case 129:       /* Negation */
01185                                 pFont->usFontStyle ^= FONT_CAPITALS;
01186                                 break;
01187                         default:
01188                                 DBG_DEC(ucTmp);
01189                                 DBG_FIXME();
01190                                 break;
01191                         }
01192                         break;
01193                 case 0x083c:    /* fVanish */
01194                         ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
01195                         switch (ucTmp) {
01196                         case   0:       /* Unset */
01197                                 pFont->usFontStyle &= ~FONT_HIDDEN;
01198                                 break;
01199                         case   1:       /* Set */
01200                                 pFont->usFontStyle |= FONT_HIDDEN;
01201                                 break;
01202                         case 128:       /* Unchanged */
01203                                 break;
01204                         case 129:       /* Negation */
01205                                 pFont->usFontStyle ^= FONT_HIDDEN;
01206                                 break;
01207                         default:
01208                                 DBG_DEC(ucTmp);
01209                                 DBG_FIXME();
01210                                 break;
01211                         }
01212                         break;
01213                 case 0x2a32:    /* cDefault */
01214                         pFont->usFontStyle &= FONT_HIDDEN;
01215                         pFont->ucFontColor = FONT_COLOR_DEFAULT;
01216                         break;
01217                 case 0x2a33:    /* cPlain */
01218                         DBG_MSG("2a33: cPlain");
01219                         vFillFontFromStylesheet(usIstd, pFont);
01220                         break;
01221                 case 0x2a3e:    /* cKul */
01222                         ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
01223                         if (ucTmp == 0 || ucTmp == 5) {
01224                                 pFont->usFontStyle &= ~FONT_UNDERLINE;
01225                         } else {
01226                                 NO_DBG_MSG("Underline text");
01227                                 pFont->usFontStyle |= FONT_UNDERLINE;
01228                                 if (ucTmp == 6) {
01229                                         DBG_MSG("Bold text");
01230                                         pFont->usFontStyle |= FONT_BOLD;
01231                                 }
01232                         }
01233                         break;
01234                 case 0x2a42:    /* cIco */
01235                         pFont->ucFontColor =
01236                                 ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
01237                         NO_DBG_DEC(pFont->ucFontColor);
01238                         break;
01239                 case 0x2a44:    /* cHpsInc */
01240                         DBG_MSG("0x2a44: sprmCHpsInc");
01241                         ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
01242                         DBG_DEC(ucTmp);
01243                         break;
01244                 case 0x2a48:    /* cIss */
01245                         ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
01246                         ucTmp &= 0x07;
01247                         if (ucTmp == 1) {
01248                                 pFont->usFontStyle |= FONT_SUPERSCRIPT;
01249                                 NO_DBG_MSG("Superscript");
01250                         } else if (ucTmp == 2) {
01251                                 pFont->usFontStyle |= FONT_SUBSCRIPT;
01252                                 NO_DBG_MSG("Subscript");
01253                         }
01254                         break;
01255                 case 0x4a30:    /* cIstd */
01256                         usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
01257                         NO_DBG_DEC(usTmp);
01258                         break;
01259                 case 0x4a43:    /* cHps */
01260                         pFont->usFontSize =
01261                                 usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
01262                         NO_DBG_DEC(pFont->usFontSize);
01263                         break;
01264                 case 0x4a4d:    /* cHpsMul */
01265                         DBG_MSG("0x4a4d: sprmCHpsMul");
01266                         usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
01267                         DBG_DEC(usTmp);
01268                         break;
01269                 case 0x4a4f:    /* cFtc0 */
01270                         usFtc0 = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
01271                         break;
01272                 case 0x4a50:    /* cFtc1 */
01273                         usFtc1 = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
01274                         break;
01275                 case 0x4a51:    /* cFtc2 */
01276                         usFtc2 = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
01277                         break;
01278                 case 0xca47:    /* cMajority */
01279                         DBG_MSG("0xca47: sprmCMajority");
01280                         break;
01281                 case 0xca4a:    /* cHpsInc1 */
01282                         usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl);
01283                         lTmp = (long)pFont->usFontSize + (long)usTmp;
01284                         if (lTmp < 8) {
01285                                 pFont->usFontSize = 8;
01286                         } else if (lTmp > 32766) {
01287                                 pFont->usFontSize = 32766;
01288                         } else {
01289                                 pFont->usFontSize = (USHORT)lTmp;
01290                         }
01291                         break;
01292                 case 0xca4c:    /* cMajority50 */
01293                         DBG_MSG("0xca4c: sprmCMajority50");
01294                         break;
01295                 case 0xea3f:    /* cHps, cHpsPos */
01296                         ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
01297                         DBG_DEC(ucTmp);
01298                         if (ucTmp != 0) {
01299                                 pFont->usFontSize = (USHORT)ucTmp;
01300                         }
01301                         ucTmp = ucGetByte(iFodo + iFodoOff + 3, aucGrpprl);
01302                         DBG_DEC(ucTmp);
01303                         break;
01304                 default:
01305                         break;
01306                 }
01307                 iInfoLen = iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
01308                 fail(iInfoLen <= 0);
01309                 iFodoOff += iInfoLen;
01310         }
01311 
01312         /* Combine the Ftc's to a FontNumber */
01313         NO_DBG_DEC_C(usFtc0 != USHRT_MAX, usFtc0);
01314         NO_DBG_DEC_C(usFtc2 != USHRT_MAX, usFtc2);
01315         NO_DBG_DEC_C(usFtc1 != USHRT_MAX, usFtc1);
01316         if (usFtc0 <= 0x7fff) {
01317                 if (usFtc0 <= (USHORT)UCHAR_MAX) {
01318                         pFont->ucFontNumber = (UCHAR)usFtc0;
01319                 } else {
01320                         DBG_DEC(usFtc0);
01321                         DBG_FIXME();
01322                         pFont->ucFontNumber = 0;
01323                 }
01324         } else if (usFtc2 <= 0x7fff) {
01325                 if (usFtc2 <= (USHORT)UCHAR_MAX) {
01326                         pFont->ucFontNumber = (UCHAR)usFtc2;
01327                 } else {
01328                         DBG_DEC(usFtc2);
01329                         DBG_FIXME();
01330                         pFont->ucFontNumber = 0;
01331                 }
01332         } else if (usFtc1 <= 0x7fff) {
01333                 if (usFtc1 <= (USHORT)UCHAR_MAX) {
01334                         pFont->ucFontNumber = (UCHAR)usFtc1;
01335                 } else {
01336                         DBG_DEC(usFtc1);
01337                         DBG_FIXME();
01338                         pFont->ucFontNumber = 0;
01339                 }
01340         }
01341 } /* end of vGet8FontInfo */
01342 
01343 /*
01344  * Fill the picture information block with information
01345  * from a Word 8/9/10/11 file.
01346  * Returns TRUE when successful, otherwise FALSE
01347  */
01348 static BOOL
01349 bGet8PicInfo(int iFodo,
01350         const UCHAR *aucGrpprl, int iBytes, picture_block_type *pPicture)
01351 {
01352         ULONG   ulTmp;
01353         int     iFodoOff, iInfoLen;
01354         BOOL    bFound;
01355         UCHAR   ucTmp;
01356 
01357         fail(iFodo <= 0 || aucGrpprl == NULL || pPicture == NULL);
01358 
01359         iFodoOff = 0;
01360         bFound = FALSE;
01361         while (iBytes >= iFodoOff + 2) {
01362                 switch (usGetWord(iFodo + iFodoOff, aucGrpprl)) {
01363 #if 0
01364                 case 0x0806:    /* fData */
01365                         ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
01366                         if (ucTmp == 0x01) {
01367                                 /* Not a picture, but a form field */
01368                                 return FALSE;
01369                         }
01370                         DBG_DEC_C(ucTmp != 0, ucTmp);
01371                         break;
01372 #endif
01373                 case 0x080a:    /* fOle2 */
01374                         ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl);
01375                         if (ucTmp == 0x01) {
01376                                 /* Not a picture, but an OLE object */
01377                                 return FALSE;
01378                         }
01379                         DBG_DEC_C(ucTmp != 0, ucTmp);
01380                         break;
01381                 case 0x680e:    /* fcObj */
01382                         ulTmp = ulGetLong(iFodo + iFodoOff + 2, aucGrpprl);
01383                         DBG_HEX(ulTmp);
01384                         break;
01385                 case 0x6a03:    /* fcPic */
01386                         pPicture->ulPictureOffset = ulGetLong(
01387                                         iFodo + iFodoOff + 2, aucGrpprl);
01388                         bFound = TRUE;
01389                         break;
01390                 default:
01391                         break;
01392                 }
01393                 iInfoLen = iGet8InfoLength(iFodo + iFodoOff, aucGrpprl);
01394                 fail(iInfoLen <= 0);
01395                 iFodoOff += iInfoLen;
01396         }
01397         return bFound;
01398 } /* end of bGet8PicInfo */
01399 
01400 /*
01401  * Build the lists with Character Information for Word 8/9/10/11 files
01402  */
01403 void
01404 vGet8ChrInfo(FILE *pFile, const pps_info_type *pPPS,
01405         const ULONG *aulBBD, size_t tBBDLen,
01406         const ULONG *aulSBD, size_t tSBDLen,
01407         const UCHAR *aucHeader)
01408 {
01409         font_block_type         tFont;
01410         picture_block_type      tPicture;
01411         ULONG           *aulCharPage;
01412         UCHAR   *aucBuffer;
01413         ULONG   ulFileOffset, ulCharPos, ulBeginCharInfo;
01414         size_t  tCharInfoLen, tOffset, tLen;
01415         int     iIndex, iIndex2, iRun, iFodo, iLen;
01416         USHORT  usIstd;
01417         UCHAR   aucFpage[BIG_BLOCK_SIZE];
01418 
01419         fail(pFile == NULL || pPPS == NULL || aucHeader == NULL);
01420         fail(aulBBD == NULL || aulSBD == NULL);
01421 
01422         ulBeginCharInfo = ulGetLong(0xfa, aucHeader); /* fcPlcfbteChpx */
01423         NO_DBG_HEX(ulBeginCharInfo);
01424         tCharInfoLen = (size_t)ulGetLong(0xfe, aucHeader); /* lcbPlcfbteChpx */
01425         NO_DBG_DEC(tCharInfoLen);
01426         if (tCharInfoLen < 4) {
01427                 DBG_DEC(tCharInfoLen);
01428                 return;
01429         }
01430 
01431         aucBuffer = aucFillInfoBuffer(pFile, &pPPS->tTable,
01432                         aulBBD, tBBDLen, aulSBD, tSBDLen,
01433                         ulBeginCharInfo, tCharInfoLen);
01434         if (aucBuffer == NULL) {
01435                 return;
01436         }
01437         NO_DBG_PRINT_BLOCK(aucBuffer, tCharInfoLen);
01438 
01439         tLen = (tCharInfoLen / 4 - 1) / 2;
01440         aulCharPage = xcalloc(tLen, sizeof(ULONG));
01441         for (iIndex = 0, tOffset = (tLen + 1) * 4;
01442              iIndex < (int)tLen;
01443              iIndex++, tOffset += 4) {
01444                  aulCharPage[iIndex] = ulGetLong(tOffset, aucBuffer);
01445                  NO_DBG_DEC(aulCharPage[iIndex]);
01446         }
01447         DBG_HEX(ulGetLong(0, aucBuffer));
01448         aucBuffer = xfree(aucBuffer);
01449         NO_DBG_PRINT_BLOCK(aucHeader, HEADER_SIZE);
01450 
01451         for (iIndex = 0; iIndex < (int)tLen; iIndex++) {
01452                 fail(aulCharPage[iIndex] > ULONG_MAX / BIG_BLOCK_SIZE);
01453                 if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB,
01454                                 aulBBD, tBBDLen, BIG_BLOCK_SIZE,
01455                                 aucFpage,
01456                                 aulCharPage[iIndex] * BIG_BLOCK_SIZE,
01457                                 BIG_BLOCK_SIZE)) {
01458                         break;
01459                 }
01460                 NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE);
01461                 iRun = (int)ucGetByte(0x1ff, aucFpage);
01462                 NO_DBG_DEC(iRun);
01463                 for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) {
01464                         ulCharPos = ulGetLong(iIndex2 * 4, aucFpage);
01465                         ulFileOffset = ulCharPos2FileOffset(ulCharPos);
01466                         iFodo = 2 * (int)ucGetByte(
01467                                 (iRun + 1) * 4 + iIndex2, aucFpage);
01468 
01469                         iLen = (int)ucGetByte(iFodo, aucFpage);
01470 
01471                         usIstd = usGetIstd(ulFileOffset);
01472                         vFillFontFromStylesheet(usIstd, &tFont);
01473                         if (iFodo != 0) {
01474                                 vGet8FontInfo(iFodo, usIstd,
01475                                         aucFpage + 1, iLen - 1, &tFont);
01476                         }
01477                         tFont.ulFileOffset = ulFileOffset;
01478                         vAdd2FontInfoList(&tFont);
01479 
01480                         if (iFodo <= 0) {
01481                                 continue;
01482                         }
01483 
01484                         (void)memset(&tPicture, 0, sizeof(tPicture));
01485                         if (bGet8PicInfo(iFodo, aucFpage + 1,
01486                                                 iLen - 1, &tPicture)) {
01487                                 tPicture.ulFileOffset = ulFileOffset;
01488                                 tPicture.ulFileOffsetPicture =
01489                                         ulDataPos2FileOffset(
01490                                                 tPicture.ulPictureOffset);
01491                                 vAdd2PictInfoList(&tPicture);
01492                         }
01493                 }
01494         }
01495         aulCharPage = xfree(aulCharPage);
01496 } /* end of vGet8ChrInfo */

Generated by  doxygen 1.6.2