/* * Fill the section information block with information * from a WinWord 1/2 file. */ static void vGet2SectionInfo(const UCHAR *aucGrpprl, size_t tBytes, section_block_type *pSection) { int iFodoOff, iInfoLen; USHORT usCcol; UCHAR ucTmp; fail(aucGrpprl == NULL || pSection == NULL); iFodoOff = 0; while (tBytes >= (size_t)iFodoOff + 1) { switch (ucGetByte(iFodoOff, aucGrpprl)) { case 117: /* bkc */ ucTmp = ucGetByte(iFodoOff + 1, aucGrpprl); DBG_DEC(ucTmp); pSection->bNewPage = ucTmp != 0 && ucTmp != 1; break; case 119: /* ccolM1 */ usCcol = 1 + usGetWord(iFodoOff + 1, aucGrpprl); DBG_DEC(usCcol); break; case 128: /* grpfIhdt */ pSection->ucHdrFtrSpecification = ucGetByte(iFodoOff + 1, aucGrpprl); break; default: break; } iInfoLen = iGet2InfoLength(iFodoOff, aucGrpprl); fail(iInfoLen <= 0); iFodoOff += iInfoLen; } } /* end of vGet2SectionInfo */
/* * iGet8InfoLength - the length of the information for Word 8/9/10/11 files */ static int iGet8InfoLength(int iByteNbr, const UCHAR *aucGrpprl) { int iTmp, iDel, iAdd; USHORT usOpCode; usOpCode = usGetWord(iByteNbr, aucGrpprl); switch (usOpCode & 0xe000) { case 0x0000: case 0x2000: return 3; case 0x4000: case 0x8000: case 0xa000: return 4; case 0xe000: return 5; case 0x6000: return 6; case 0xc000: iTmp = (int)ucGetByte(iByteNbr + 2, aucGrpprl); if (usOpCode == 0xc615 && iTmp == 255) { iDel = (int)ucGetByte(iByteNbr + 3, aucGrpprl); iAdd = (int)ucGetByte( iByteNbr + 4 + iDel * 4, aucGrpprl); iTmp = 2 + iDel * 4 + iAdd * 3; } return 3 + iTmp; default: DBG_HEX(usOpCode); DBG_FIXME(); return 1; } } /* end of iGet8InfoLength */
/* * Fill the picture information block with information * from a Word 8/9/10/11 file. * Returns TRUE when successful, otherwise FALSE */ static BOOL bGet8PicInfo(int iFodo, const UCHAR *aucGrpprl, int iBytes, picture_block_type *pPicture) { ULONG ulTmp; int iFodoOff, iInfoLen; BOOL bFound; UCHAR ucTmp; fail(iFodo <= 0 || aucGrpprl == NULL || pPicture == NULL); iFodoOff = 0; bFound = FALSE; while (iBytes >= iFodoOff + 2) { switch (usGetWord(iFodo + iFodoOff, aucGrpprl)) { #if 0 case 0x0806: /* fData */ ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl); if (ucTmp == 0x01) { /* Not a picture, but a form field */ return FALSE; } DBG_DEC_C(ucTmp != 0, ucTmp); break; #endif case 0x080a: /* fOle2 */ ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl); if (ucTmp == 0x01) { /* Not a picture, but an OLE object */ return FALSE; } DBG_DEC_C(ucTmp != 0, ucTmp); break; case 0x680e: /* fcObj */ ulTmp = ulGetLong(iFodo + iFodoOff + 2, aucGrpprl); DBG_HEX(ulTmp); break; case 0x6a03: /* fcPic */ pPicture->ulPictureOffset = ulGetLong( iFodo + iFodoOff + 2, aucGrpprl); bFound = TRUE; break; default: break; } iInfoLen = iGet8InfoLength(iFodo + iFodoOff, aucGrpprl); fail(iInfoLen <= 0); iFodoOff += iInfoLen; } return bFound; } /* end of bGet8PicInfo */
/* * Fill the picture information block with information * from a Word 6/7 file. * Returns TRUE when successful, otherwise FALSE */ static BOOL bGet6PicInfo(int iFodo, const UCHAR *aucGrpprl, int iBytes, picture_block_type *pPicture) { int iFodoOff, iInfoLen; BOOL bFound; UCHAR ucTmp; TRACE_MSG("vGet6PicInfo"); fail(iFodo < 0 || aucGrpprl == NULL || pPicture == NULL); iFodoOff = 0; bFound = FALSE; while (iBytes >= iFodoOff + 1) { switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) { case 68: /* fcPic */ pPicture->ulPictureOffset = ulGetLong( iFodo + iFodoOff + 2, aucGrpprl); bFound = TRUE; break; #if 0 case 71: /* fData */ ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl); if (ucTmp == 0x01) { /* Not a picture, but a form field */ return FALSE; } DBG_DEC_C(ucTmp != 0, ucTmp); break; #endif case 75: /* fOle2 */ ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl); if (ucTmp == 0x01) { /* Not a picture, but an OLE object */ return FALSE; } DBG_DEC_C(ucTmp != 0, ucTmp); break; default: break; } iInfoLen = iGet6InfoLength(iFodo + iFodoOff, aucGrpprl); fail(iInfoLen <= 0); iFodoOff += iInfoLen; } return bFound; } /* end of bGet6PicInfo */
/* * bGetDocumentText - make a list of the text blocks of a Word document * * Return TRUE when succesful, otherwise FALSE */ static BOOL bGetDocumentText(FILE *pFile, long lFilesize, const UCHAR *aucHeader) { text_block_type tTextBlock; ULONG ulTextLen; BOOL bFastSaved; UCHAR ucDocStatus, ucVersion; fail(pFile == NULL); fail(lFilesize < 128); fail(aucHeader == NULL); /* Get the status flags from the header */ ucDocStatus = ucGetByte(0x75, aucHeader); DBG_HEX(ucDocStatus); bFastSaved = (ucDocStatus & BIT(1)) != 0; DBG_MSG_C(bFastSaved, "This document is Fast Saved"); ucVersion = ucGetByte(0x74, aucHeader); DBG_DEC(ucVersion); DBG_MSG_C(ucVersion == 0, "Written by Word 4.0 or earlier"); DBG_MSG_C(ucVersion == 3, "Word 5.0 format, but not written by Word"); DBG_MSG_C(ucVersion == 4, "Written by Word 5.x"); if (bFastSaved) { werr(0, "Word for DOS: autosave documents are not supported"); return FALSE; } /* Get length information */ ulTextLen = ulGetLong(0x0e, aucHeader); DBG_HEX(ulTextLen); ulTextLen -= 128; DBG_DEC(ulTextLen); tTextBlock.ulFileOffset = 128; tTextBlock.ulCharPos = 128; tTextBlock.ulLength = ulTextLen; tTextBlock.bUsesUnicode = FALSE; tTextBlock.usPropMod = IGNORE_PROPMOD; if (!bAdd2TextBlockList(&tTextBlock)) { DBG_HEX(tTextBlock.ulFileOffset); DBG_HEX(tTextBlock.ulCharPos); DBG_DEC(tTextBlock.ulLength); DBG_DEC(tTextBlock.bUsesUnicode); DBG_DEC(tTextBlock.usPropMod); return FALSE; } return TRUE; } /* end of bGetDocumentText */
/* * iGet6InfoLength - the length of the information for Word 6/7 files */ static int iGet6InfoLength(int iByteNbr, const UCHAR *aucGrpprl) { int iTmp, iDel, iAdd; switch (ucGetByte(iByteNbr, aucGrpprl)) { case 2: case 16: case 17: case 18: case 19: case 21: case 22: case 26: case 27: case 28: case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 38: case 39: case 40: case 41: case 42: case 43: case 45: case 46: case 47: case 48: case 49: case 69: case 72: case 80: case 93: case 96: case 97: case 99: case 101: case 105: case 106: case 107: case 109: case 110: case 121: case 122: case 123: case 124: case 140: case 141: case 144: case 145: case 148: case 149: case 154: case 155: case 156: case 157: case 160: case 161: case 164: case 165: case 166: case 167: case 168: case 169: case 170: case 171: case 182: case 183: case 184: case 189: case 195: case 197: case 198: return 1 + 2; case 3: case 12: case 15: case 81: case 103: case 108: case 188: case 190: case 191: return 2 + (int)ucGetByte(iByteNbr + 1, aucGrpprl); case 20: case 70: case 74: case 192: case 194: case 196: case 200: return 1 + 4; case 23: iTmp = (int)ucGetByte(iByteNbr + 1, aucGrpprl); if (iTmp == 255) { iDel = (int)ucGetByte(iByteNbr + 2, aucGrpprl); iAdd = (int)ucGetByte( iByteNbr + 3 + iDel * 4, aucGrpprl); iTmp = 2 + iDel * 4 + iAdd * 3; } return 2 + iTmp; case 68: case 193: case 199: return 1 + 5; case 73: case 95: case 136: case 137: return 1 + 3; case 120: case 187: return 1 + 12; default: return 1 + 1; } } /* end of iGet6InfoLength */
/* * iGet2InfoLength - the length of the information for WinWord 1/2 files */ static int iGet2InfoLength(int iByteNbr, const UCHAR *aucGrpprl) { int iTmp, iDel, iAdd; switch (ucGetByte(iByteNbr, aucGrpprl)) { case 3: case 15: case 78: case 152: case 154: case 155: return 2 + (int)ucGetByte(iByteNbr + 1, aucGrpprl); case 16: case 17: case 18: case 19: case 21: case 22: case 26: case 27: case 28: case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 38: case 39: case 40: case 41: case 42: case 43: case 45: case 46: case 47: case 48: case 49: case 68: case 71: case 72: case 82: case 83: case 96: case 97: case 98: case 99: case 115: case 116: case 119: case 120: case 123: case 124: case 129: case 130: case 131: case 132: case 135: case 136: case 139: case 140: case 141: case 142: case 143: case 144: case 145: case 146: case 147: case 148: case 153: case 159: case 161: case 162: return 1 + 2; case 23: iTmp = (int)ucGetByte(iByteNbr + 1, aucGrpprl); if (iTmp == 255) { iDel = (int)ucGetByte(iByteNbr + 2, aucGrpprl); iAdd = (int)ucGetByte( iByteNbr + 3 + iDel * 4, aucGrpprl); iTmp = 2 + iDel * 4 + iAdd * 3; } return 2 + iTmp; case 70: return 1 + 3; case 95: return 1 + 13; case 157: case 163: return 1 + 5; case 158: case 160: case 164: return 1 + 4; default: return 1 + 1; } } /* end of iGet2InfoLength */
/* * bGetDocumentText - make a list of the text blocks of a Word document * * Return TRUE when succesful, otherwise FALSE */ static BOOL bGetDocumentText(FILE *pFile, const UCHAR *aucHeader) { text_block_type tTextBlock; ULONG ulBeginOfText, ulEndOfText; ULONG ulTextLen; UCHAR ucDocStatus; BOOL bFastSaved; fail(pFile == NULL); fail(aucHeader == NULL); DBG_MSG("bGetDocumentText"); NO_DBG_PRINT_BLOCK(aucHeader, 0x20); /* Get the status flags from the header */ ucDocStatus = ucGetByte(0x0a, aucHeader); DBG_HEX(ucDocStatus); bFastSaved = (ucDocStatus & BIT(5)) != 0; DBG_MSG_C(bFastSaved, "This document is Fast Saved"); if (bFastSaved) { werr(0, "MacWord: fast saved documents are not supported yet"); return FALSE; } /* Get length information */ ulBeginOfText = ulGetLongBE(0x14, aucHeader); DBG_HEX(ulBeginOfText); ulEndOfText = ulGetLongBE(0x18, aucHeader); DBG_HEX(ulEndOfText); ulTextLen = ulEndOfText - ulBeginOfText; DBG_DEC(ulTextLen); tTextBlock.ulFileOffset = ulBeginOfText; tTextBlock.ulCharPos = ulBeginOfText; tTextBlock.ulLength = ulTextLen; tTextBlock.bUsesUnicode = FALSE; tTextBlock.usPropMod = IGNORE_PROPMOD; if (!bAdd2TextBlockList(&tTextBlock)) { DBG_HEX(tTextBlock.ulFileOffset); DBG_HEX(tTextBlock.ulCharPos); DBG_DEC(tTextBlock.ulLength); DBG_DEC(tTextBlock.bUsesUnicode); DBG_DEC(tTextBlock.usPropMod); return FALSE; } return TRUE; } /* end of bGetDocumentText */
/* * Fill the section information block with information * from a Word 8/9/10/11 file. */ static void vGet8SectionInfo(const UCHAR *aucGrpprl, size_t tBytes, section_block_type *pSection) { UINT uiIndex; int iFodoOff, iInfoLen, iSize, iTmp; USHORT usCcol; UCHAR ucTmp; fail(aucGrpprl == NULL || pSection == NULL); iFodoOff = 0; while (tBytes >= (size_t)iFodoOff + 2) { iInfoLen = 0; switch (usGetWord(iFodoOff, aucGrpprl)) { case 0x3009: /* bkc */ ucTmp = ucGetByte(iFodoOff + 2, aucGrpprl); DBG_DEC(ucTmp); pSection->bNewPage = ucTmp != 0 && ucTmp != 1; break; case 0x3014: /* grpfIhdt */ pSection->ucHdrFtrSpecification = ucGetByte(iFodoOff + 2, aucGrpprl); break; case 0x500b: /* ccolM1 */ usCcol = 1 + usGetWord(iFodoOff + 2, aucGrpprl); DBG_DEC(usCcol); break; case 0xd202: /* olstAnm */ iSize = (int)ucGetByte(iFodoOff + 2, aucGrpprl); DBG_DEC_C(iSize != 212, iSize); for (uiIndex = 0, iTmp = iFodoOff + 3; uiIndex < 9 && iTmp < iFodoOff + 3 + iSize - 15; uiIndex++, iTmp += 16) { pSection->aucNFC[uiIndex] = ucGetByte(iTmp, aucGrpprl); DBG_DEC(pSection->aucNFC[uiIndex]); ucTmp = ucGetByte(iTmp + 3, aucGrpprl); DBG_HEX(ucTmp); if ((ucTmp & BIT(2)) != 0) { pSection->usNeedPrevLvl |= (USHORT)BIT(uiIndex); } if ((ucTmp & BIT(3)) != 0) { pSection->usHangingIndent |= (USHORT)BIT(uiIndex); } } DBG_HEX(pSection->usNeedPrevLvl); DBG_HEX(pSection->usHangingIndent); break; default: break; } if (iInfoLen <= 0) { iInfoLen = iGet8InfoLength(iFodoOff, aucGrpprl); fail(iInfoLen <= 0); } iFodoOff += iInfoLen; } } /* end of vGet8SectionInfo */
/* * Build the lists with Section Property Information for WinWord 1/2 files */ void vGet2SepInfo(FILE *pFile, const UCHAR *aucHeader) { section_block_type tSection; ULONG *aulSectPage, *aulCharPos; UCHAR *aucBuffer, *aucFpage; ULONG ulBeginOfText, ulTextOffset, ulBeginSectInfo; size_t tSectInfoLen, tIndex, tOffset, tLen, tBytes; UCHAR aucTmp[1]; fail(pFile == NULL || aucHeader == NULL); ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */ NO_DBG_HEX(ulBeginOfText); ulBeginSectInfo = ulGetLong(0x7c, aucHeader); /* fcPlcfsed */ DBG_HEX(ulBeginSectInfo); tSectInfoLen = (size_t)usGetWord(0x80, aucHeader); /* cbPlcfsed */ DBG_DEC(tSectInfoLen); if (tSectInfoLen < 4) { DBG_DEC(tSectInfoLen); return; } aucBuffer = xmalloc(tSectInfoLen); if (!bReadBytes(aucBuffer, tSectInfoLen, ulBeginSectInfo, pFile)) { aucBuffer = xfree(aucBuffer); return; } NO_DBG_PRINT_BLOCK(aucBuffer, tSectInfoLen); /* Read the Section Descriptors */ tLen = (tSectInfoLen - 4) / 10; /* Save the section offsets */ aulCharPos = xcalloc(tLen, sizeof(ULONG)); for (tIndex = 0, tOffset = 0; tIndex < tLen; tIndex++, tOffset += 4) { ulTextOffset = ulGetLong(tOffset, aucBuffer); NO_DBG_HEX(ulTextOffset); aulCharPos[tIndex] = ulBeginOfText + ulTextOffset; NO_DBG_HEX(aulCharPos[tIndex]); } /* Save the Sepx offsets */ aulSectPage = xcalloc(tLen, sizeof(ULONG)); for (tIndex = 0, tOffset = (tLen + 1) * 4; tIndex < tLen; tIndex++, tOffset += 6) { aulSectPage[tIndex] = ulGetLong(tOffset + 2, aucBuffer); NO_DBG_HEX(aulSectPage[tIndex]); /* fcSepx */ } aucBuffer = xfree(aucBuffer); /* Read the Section Properties */ for (tIndex = 0; tIndex < tLen; tIndex++) { if (aulSectPage[tIndex] == FC_INVALID) { vDefault2SectionInfoList(aulCharPos[tIndex]); continue; } /* Get the number of bytes to read */ if (!bReadBytes(aucTmp, 1, aulSectPage[tIndex], pFile)) { continue; } tBytes = 1 + (size_t)ucGetByte(0, aucTmp); NO_DBG_DEC(tBytes); /* Read the bytes */ aucFpage = xmalloc(tBytes); if (!bReadBytes(aucFpage, tBytes, aulSectPage[tIndex], pFile)) { aucFpage = xfree(aucFpage); continue; } NO_DBG_PRINT_BLOCK(aucFpage, tBytes); /* Process the bytes */ vGetDefaultSection(&tSection); vGet2SectionInfo(aucFpage + 1, tBytes - 1, &tSection); vAdd2SectionInfoList(&tSection, aulCharPos[tIndex]); aucFpage = xfree(aucFpage); } aulCharPos = xfree(aulCharPos); aulSectPage = xfree(aulSectPage); } /* end of vGet2SepInfo */
/* * Build the lists with Paragraph Information for Word 6/7 files */ void vGet6PapInfo(FILE *pFile, ULONG ulStartBlock, const ULONG *aulBBD, size_t tBBDLen, const UCHAR *aucHeader) { row_block_type tRow; style_block_type tStyle; USHORT *ausParfPage; UCHAR *aucBuffer; ULONG ulCharPos, ulCharPosFirst, ulCharPosLast; ULONG ulBeginParfInfo; size_t tParfInfoLen, tParfPageNum, tOffset, tSize, tLenOld, tLen; size_t tIndex, tIndex2, tRun; int iFodo, iLen; row_info_enum eRowInfo; USHORT usParfFirstPage, usCount, usIstd; UCHAR aucFpage[BIG_BLOCK_SIZE]; fail(pFile == NULL || aucHeader == NULL); fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN); fail(aulBBD == NULL); ulBeginParfInfo = ulGetLong(0xc0, aucHeader); /* fcPlcfbtePapx */ NO_DBG_HEX(ulBeginParfInfo); tParfInfoLen = (size_t)ulGetLong(0xc4, aucHeader); /* lcbPlcfbtePapx */ NO_DBG_DEC(tParfInfoLen); if (tParfInfoLen < 4) { DBG_DEC(tParfInfoLen); return; } aucBuffer = xmalloc(tParfInfoLen); if (!bReadBuffer(pFile, ulStartBlock, aulBBD, tBBDLen, BIG_BLOCK_SIZE, aucBuffer, ulBeginParfInfo, tParfInfoLen)) { aucBuffer = xfree(aucBuffer); return; } NO_DBG_PRINT_BLOCK(aucBuffer, tParfInfoLen); tLen = (tParfInfoLen - 4) / 6; ausParfPage = xcalloc(tLen, sizeof(USHORT)); for (tIndex = 0, tOffset = (tLen + 1) * 4; tIndex < tLen; tIndex++, tOffset += 2) { ausParfPage[tIndex] = usGetWord(tOffset, aucBuffer); NO_DBG_DEC(ausParfPage[tIndex]); } DBG_HEX(ulGetLong(0, aucBuffer)); aucBuffer = xfree(aucBuffer); tParfPageNum = (size_t)usGetWord(0x190, aucHeader); /* cpnBtePap */ DBG_DEC(tParfPageNum); if (tLen < tParfPageNum) { /* Replace ParfPage by a longer version */ tLenOld = tLen; usParfFirstPage = usGetWord(0x18c, aucHeader); /* pnPapFirst */ DBG_DEC(usParfFirstPage); tLen += tParfPageNum - 1; tSize = tLen * sizeof(USHORT); ausParfPage = xrealloc(ausParfPage, tSize); /* Add new values */ usCount = usParfFirstPage + 1; for (tIndex = tLenOld; tIndex < tLen; tIndex++) { ausParfPage[tIndex] = usCount; NO_DBG_DEC(ausParfPage[tIndex]); usCount++; } } (void)memset(&tRow, 0, sizeof(tRow)); ulCharPosFirst = CP_INVALID; for (tIndex = 0; tIndex < tLen; tIndex++) { if (!bReadBuffer(pFile, ulStartBlock, aulBBD, tBBDLen, BIG_BLOCK_SIZE, aucFpage, (ULONG)ausParfPage[tIndex] * BIG_BLOCK_SIZE, BIG_BLOCK_SIZE)) { break; } tRun = (size_t)ucGetByte(0x1ff, aucFpage); NO_DBG_DEC(tRun); for (tIndex2 = 0; tIndex2 < tRun; tIndex2++) { NO_DBG_HEX(ulGetLong(tIndex2 * 4, aucFpage)); iFodo = 2 * (int)ucGetByte( (tRun + 1) * 4 + tIndex2 * 7, aucFpage); if (iFodo <= 0) { continue; } iLen = 2 * (int)ucGetByte(iFodo, aucFpage); usIstd = (USHORT)ucGetByte(iFodo + 1, aucFpage); vFillStyleFromStylesheet(usIstd, &tStyle); vGet6StyleInfo(iFodo, aucFpage + 3, iLen - 3, &tStyle); ulCharPos = ulGetLong(tIndex2 * 4, aucFpage); NO_DBG_HEX(ulCharPos); tStyle.ulFileOffset = ulCharPos2FileOffsetX( ulCharPos, &tStyle.eListID); vAdd2StyleInfoList(&tStyle); eRowInfo = eGet6RowInfo(iFodo, aucFpage + 3, iLen - 3, &tRow); switch(eRowInfo) { case found_a_cell: if (ulCharPosFirst != CP_INVALID) { break; } ulCharPosFirst = ulGetLong( tIndex2 * 4, aucFpage); NO_DBG_HEX(ulCharPosFirst); tRow.ulCharPosStart = ulCharPosFirst; tRow.ulFileOffsetStart = ulCharPos2FileOffset(ulCharPosFirst); DBG_HEX_C(tRow.ulFileOffsetStart == FC_INVALID, ulCharPosFirst); break; case found_end_of_row: ulCharPosLast = ulGetLong( tIndex2 * 4, aucFpage); NO_DBG_HEX(ulCharPosLast); tRow.ulCharPosEnd = ulCharPosLast; tRow.ulFileOffsetEnd = ulCharPos2FileOffset(ulCharPosLast); DBG_HEX_C(tRow.ulFileOffsetEnd == FC_INVALID, ulCharPosLast); vAdd2RowInfoList(&tRow); (void)memset(&tRow, 0, sizeof(tRow)); ulCharPosFirst = CP_INVALID; break; case found_nothing: break; default: DBG_DEC(eRowInfo); break; } } } ausParfPage = xfree(ausParfPage); } /* end of vGet6PapInfo */
/* * Build the lists with Paragraph Information for Word 8/9/10/11 files */ void vGet8PapInfo(FILE *pFile, const pps_info_type *pPPS, const ULONG *aulBBD, size_t tBBDLen, const ULONG *aulSBD, size_t tSBDLen, const UCHAR *aucHeader) { row_block_type tRow; style_block_type tStyle; ULONG *aulParfPage; UCHAR *aucBuffer; ULONG ulCharPos, ulCharPosFirst, ulCharPosLast; ULONG ulBeginParfInfo; size_t tParfInfoLen, tOffset, tLen; int iIndex, iIndex2, iRun, iFodo, iLen; row_info_enum eRowInfo; USHORT usIstd; UCHAR aucFpage[BIG_BLOCK_SIZE]; fail(pFile == NULL || pPPS == NULL || aucHeader == NULL); fail(aulBBD == NULL || aulSBD == NULL); ulBeginParfInfo = ulGetLong(0x102, aucHeader); /* fcPlcfbtePapx */ NO_DBG_HEX(ulBeginParfInfo); tParfInfoLen = (size_t)ulGetLong(0x106, aucHeader); /* lcbPlcfbtePapx */ NO_DBG_DEC(tParfInfoLen); if (tParfInfoLen < 4) { DBG_DEC(tParfInfoLen); return; } aucBuffer = aucFillInfoBuffer(pFile, &pPPS->tTable, aulBBD, tBBDLen, aulSBD, tSBDLen, ulBeginParfInfo, tParfInfoLen); if (aucBuffer == NULL) { return; } NO_DBG_PRINT_BLOCK(aucBuffer, tParfInfoLen); tLen = (tParfInfoLen / 4 - 1) / 2; aulParfPage = xcalloc(tLen, sizeof(ULONG)); for (iIndex = 0, tOffset = (tLen + 1) * 4; iIndex < (int)tLen; iIndex++, tOffset += 4) { aulParfPage[iIndex] = ulGetLong(tOffset, aucBuffer); NO_DBG_DEC(aulParfPage[iIndex]); } DBG_HEX(ulGetLong(0, aucBuffer)); aucBuffer = xfree(aucBuffer); NO_DBG_PRINT_BLOCK(aucHeader, HEADER_SIZE); (void)memset(&tRow, 0, sizeof(tRow)); ulCharPosFirst = CP_INVALID; for (iIndex = 0; iIndex < (int)tLen; iIndex++) { fail(aulParfPage[iIndex] > ULONG_MAX / BIG_BLOCK_SIZE); if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB, aulBBD, tBBDLen, BIG_BLOCK_SIZE, aucFpage, aulParfPage[iIndex] * BIG_BLOCK_SIZE, BIG_BLOCK_SIZE)) { break; } NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE); iRun = (int)ucGetByte(0x1ff, aucFpage); NO_DBG_DEC(iRun); for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) { NO_DBG_HEX(ulGetLong(iIndex2 * 4, aucFpage)); iFodo = 2 * (int)ucGetByte( (iRun + 1) * 4 + iIndex2 * 13, aucFpage); if (iFodo <= 0) { continue; } iLen = 2 * (int)ucGetByte(iFodo, aucFpage); if (iLen == 0) { iFodo++; iLen = 2 * (int)ucGetByte(iFodo, aucFpage); } usIstd = usGetWord(iFodo + 1, aucFpage); vFillStyleFromStylesheet(usIstd, &tStyle); vGet8StyleInfo(iFodo, aucFpage + 3, iLen - 3, &tStyle); ulCharPos = ulGetLong(iIndex2 * 4, aucFpage); NO_DBG_HEX(ulCharPos); tStyle.ulFileOffset = ulCharPos2FileOffsetX( ulCharPos, &tStyle.eListID); vAdd2StyleInfoList(&tStyle); eRowInfo = eGet8RowInfo(iFodo, aucFpage + 3, iLen - 3, &tRow); switch (eRowInfo) { case found_a_cell: if (ulCharPosFirst != CP_INVALID) { break; } ulCharPosFirst = ulGetLong( iIndex2 * 4, aucFpage); NO_DBG_HEX(ulCharPosFirst); tRow.ulCharPosStart = ulCharPosFirst; tRow.ulFileOffsetStart = ulCharPos2FileOffset(ulCharPosFirst); NO_DBG_HEX_C( tRow.ulFileOffsetStart == FC_INVALID, ulCharPosFirst); break; case found_end_of_row: ulCharPosLast = ulGetLong( iIndex2 * 4, aucFpage); NO_DBG_HEX(ulCharPosLast); tRow.ulCharPosEnd = ulCharPosLast; tRow.ulFileOffsetEnd = ulCharPos2FileOffset(ulCharPosLast); NO_DBG_HEX_C(tRow.ulFileOffsetEnd == FC_INVALID, ulCharPosLast); vAdd2RowInfoList(&tRow); (void)memset(&tRow, 0, sizeof(tRow)); ulCharPosFirst = CP_INVALID; break; case found_nothing: break; default: DBG_DEC(eRowInfo); break; } } } aulParfPage = xfree(aulParfPage); } /* end of vGet8PapInfo */
/* * Build the list with List Information for Word 8/9/10/11 files */ void vGet8LstInfo(FILE *pFile, const pps_info_type *pPPS, const ULONG *aulBBD, size_t tBBDLen, const ULONG *aulSBD, size_t tSBDLen, const UCHAR *aucHeader) { list_block_type tList; const ULONG *aulBlockDepot; UCHAR *aucLfoInfo, *aucLstfInfo, *aucPapx, *aucXString; ULONG ulBeginLfoInfo, ulBeginLstfInfo, ulBeginLvlfInfo; ULONG ulListID, ulStart; size_t tBlockDepotLen, tBlockSize; size_t tLfoInfoLen, tLstfInfoLen, tPapxLen, tXstLen, tOff; size_t tLstfRecords, tStart, tIndex; int iNums; USHORT usIstd; UCHAR ucTmp, ucListLevel, ucMaxLevel, ucChpxLen; UCHAR aucLvlfInfo[28], aucXst[2]; fail(pFile == NULL || pPPS == NULL || aucHeader == NULL); fail(aulBBD == NULL || aulSBD == NULL); NO_DBG_DEC(pPPS->tTable.ulSB); NO_DBG_HEX(pPPS->tTable.ulSize); if (pPPS->tTable.ulSize == 0) { DBG_MSG("No list information"); return; } if (pPPS->tTable.ulSize < MIN_SIZE_FOR_BBD_USE) { /* Use the Small Block Depot */ aulBlockDepot = aulSBD; tBlockDepotLen = tSBDLen; tBlockSize = SMALL_BLOCK_SIZE; } else { /* Use the Big Block Depot */ aulBlockDepot = aulBBD; tBlockDepotLen = tBBDLen; tBlockSize = BIG_BLOCK_SIZE; } /* LFO (List Format Override) */ ulBeginLfoInfo = ulGetLong(0x2ea, aucHeader); /* fcPlfLfo */ DBG_HEX(ulBeginLfoInfo); tLfoInfoLen = (size_t)ulGetLong(0x2ee, aucHeader); /* lcbPlfLfo */ DBG_DEC(tLfoInfoLen); if (tLfoInfoLen == 0) { DBG_MSG("No lists in this document"); return; } aucLfoInfo = xmalloc(tLfoInfoLen); if (!bReadBuffer(pFile, pPPS->tTable.ulSB, aulBlockDepot, tBlockDepotLen, tBlockSize, aucLfoInfo, ulBeginLfoInfo, tLfoInfoLen)) { aucLfoInfo = xfree(aucLfoInfo); return; } NO_DBG_PRINT_BLOCK(aucLfoInfo, tLfoInfoLen); vBuildLfoList(aucLfoInfo, tLfoInfoLen); aucLfoInfo = xfree(aucLfoInfo); /* LSTF (LiST data on File) */ ulBeginLstfInfo = ulGetLong(0x2e2, aucHeader); /* fcPlcfLst */ DBG_HEX(ulBeginLstfInfo); tLstfInfoLen = (size_t)ulGetLong(0x2e6, aucHeader); /* lcbPlcfLst */ DBG_DEC(tLstfInfoLen); if (tLstfInfoLen == 0) { DBG_MSG("No list data on file"); return; } aucLstfInfo = xmalloc(tLstfInfoLen); if (!bReadBuffer(pFile, pPPS->tTable.ulSB, aulBlockDepot, tBlockDepotLen, tBlockSize, aucLstfInfo, ulBeginLstfInfo, tLstfInfoLen)) { aucLstfInfo = xfree(aucLstfInfo); return; } NO_DBG_PRINT_BLOCK(aucLstfInfo, tLstfInfoLen); tLstfRecords = (size_t)usGetWord(0, aucLstfInfo); if (2 + tLstfRecords * 28 < tLstfInfoLen) { DBG_DEC(2 + tLstfRecords * 28); DBG_DEC(tLstfInfoLen); aucLstfInfo = xfree(aucLstfInfo); return; } /* LVLF (List leVeL on File) */ ulBeginLvlfInfo = ulBeginLstfInfo + tLstfInfoLen; DBG_HEX(ulBeginLvlfInfo); aucXString = NULL; ulStart = ulBeginLvlfInfo; for (tIndex = 0, tStart = 2; tIndex < tLstfRecords; tIndex++, tStart += 28) { ulListID = ulGetLong(tStart, aucLstfInfo); NO_DBG_HEX(ulListID); ucTmp = ucGetByte(tStart + 26, aucLstfInfo); ucMaxLevel = odd(ucTmp) ? 1 : 9; for (ucListLevel = 0; ucListLevel < ucMaxLevel; ucListLevel++) { fail(aucXString != NULL); usIstd = usGetWord( tStart + 8 + 2 * (size_t)ucListLevel, aucLstfInfo); DBG_DEC_C(usIstd != STI_NIL, usIstd); NO_DBG_HEX(ulStart); (void)memset(&tList, 0, sizeof(tList)); /* Read the lvlf (List leVeL on File) */ if (!bReadBuffer(pFile, pPPS->tTable.ulSB, aulBlockDepot, tBlockDepotLen, tBlockSize, aucLvlfInfo, ulStart, sizeof(aucLvlfInfo))) { aucLstfInfo = xfree(aucLstfInfo); return; } NO_DBG_PRINT_BLOCK(aucLvlfInfo, sizeof(aucLvlfInfo)); if (bAllZero(aucLvlfInfo, sizeof(aucLvlfInfo))) { tList.ulStartAt = 1; tList.ucNFC = 0x00; tList.bNoRestart = FALSE; } else { tList.ulStartAt = ulGetLong(0, aucLvlfInfo); tList.ucNFC = ucGetByte(4, aucLvlfInfo); ucTmp = ucGetByte(5, aucLvlfInfo); tList.bNoRestart = (ucTmp & BIT(3)) != 0; DBG_MSG_C((ucTmp & BIT(4)) != 0 && (ucTmp & BIT(6)) != 0, "Found one"); } ulStart += sizeof(aucLvlfInfo); tPapxLen = (size_t)ucGetByte(25, aucLvlfInfo); if (tPapxLen != 0) { aucPapx = xmalloc(tPapxLen); /* Read the Papx */ if (!bReadBuffer(pFile, pPPS->tTable.ulSB, aulBlockDepot, tBlockDepotLen, tBlockSize, aucPapx, ulStart, tPapxLen)) { aucPapx = xfree(aucPapx); aucLstfInfo = xfree(aucLstfInfo); return; } NO_DBG_PRINT_BLOCK(aucPapx, tPapxLen); tList.sLeftIndent = sGetLeftIndent(aucPapx, tPapxLen); aucPapx = xfree(aucPapx); } ulStart += tPapxLen; ucChpxLen = ucGetByte(24, aucLvlfInfo); ulStart += (ULONG)ucChpxLen; /* Read the length of the XString */ if (!bReadBuffer(pFile, pPPS->tTable.ulSB, aulBlockDepot, tBlockDepotLen, tBlockSize, aucXst, ulStart, sizeof(aucXst))) { aucLstfInfo = xfree(aucLstfInfo); return; } NO_DBG_PRINT_BLOCK(aucXst, sizeof(aucXst)); tXstLen = (size_t)usGetWord(0, aucXst); ulStart += sizeof(aucXst); if (tXstLen == 0) { tList.usListChar = DEFAULT_LISTCHAR; vAdd2ListInfoList(ulListID, usIstd, ucListLevel, &tList); continue; } tXstLen *= 2; /* Length in chars to length in bytes */ aucXString = xmalloc(tXstLen); /* Read the XString */ if (!bReadBuffer(pFile, pPPS->tTable.ulSB, aulBlockDepot, tBlockDepotLen, tBlockSize, aucXString, ulStart, tXstLen)) { aucXString = xfree(aucXString); aucLstfInfo = xfree(aucLstfInfo); return; } NO_DBG_PRINT_BLOCK(aucXString, tXstLen); tOff = 0; for (iNums = 6; iNums < 15; iNums++) { ucTmp = ucGetByte(iNums, aucLvlfInfo); if (ucTmp == 0) { break; } tOff = (size_t)ucTmp; } tOff *= 2; /* Offset in chars to offset in bytes */ NO_DBG_DEC(tOff); if (tList.ucNFC == LIST_SPECIAL || tList.ucNFC == LIST_SPECIAL2 || tList.ucNFC == LIST_BULLETS) { tList.usListChar = usGetWord(0, aucXString); } else if (tOff != 0 && tOff < tXstLen) { tList.usListChar = usGetWord(tOff, aucXString); } else { tList.usListChar = DEFAULT_LISTCHAR; } vAdd2ListInfoList(ulListID, usIstd, ucListLevel, &tList); ulStart += tXstLen; aucXString = xfree(aucXString); } } aucLstfInfo = xfree(aucLstfInfo); } /* end of vGet8LstInfo */
/* * Fill the font information block with information * from a Word 6/7 file. * Returns TRUE when successful, otherwise FALSE */ void vGet6FontInfo(int iFodo, USHORT usIstd, const UCHAR *aucGrpprl, int iBytes, font_block_type *pFont) { long lTmp; int iFodoOff, iInfoLen; USHORT usTmp; UCHAR ucTmp; TRACE_MSG("vGet6FontInfo"); fail(iFodo < 0 || aucGrpprl == NULL || pFont == NULL); iFodoOff = 0; while (iBytes >= iFodoOff + 1) { switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) { case 65: /* fRMarkDel */ ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl); if (ucTmp == 0) { pFont->usFontStyle &= ~FONT_MARKDEL; } else { pFont->usFontStyle |= FONT_MARKDEL; } break; case 80: /* cIstd */ usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl); NO_DBG_DEC(usTmp); break; case 82: /* cDefault */ pFont->usFontStyle &= FONT_HIDDEN; pFont->ucFontColor = FONT_COLOR_DEFAULT; break; case 83: /* cPlain */ DBG_MSG("83: cPlain"); vFillFontFromStylesheet(usIstd, pFont); break; case 85: /* fBold */ ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl); switch (ucTmp) { case 0: /* Unset */ pFont->usFontStyle &= ~FONT_BOLD; break; case 1: /* Set */ pFont->usFontStyle |= FONT_BOLD; break; case 128: /* Unchanged */ break; case 129: /* Negation */ pFont->usFontStyle ^= FONT_BOLD; break; default: DBG_DEC(ucTmp); DBG_FIXME(); break; } break; case 86: /* fItalic */ ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl); switch (ucTmp) { case 0: /* Unset */ pFont->usFontStyle &= ~FONT_ITALIC; break; case 1: /* Set */ pFont->usFontStyle |= FONT_ITALIC; break; case 128: /* Unchanged */ break; case 129: /* Negation */ pFont->usFontStyle ^= FONT_ITALIC; break; default: DBG_DEC(ucTmp); DBG_FIXME(); break; } break; case 87: /* fStrike */ ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl); switch (ucTmp) { case 0: /* Unset */ pFont->usFontStyle &= ~FONT_STRIKE; break; case 1: /* Set */ pFont->usFontStyle |= FONT_STRIKE; break; case 128: /* Unchanged */ break; case 129: /* Negation */ pFont->usFontStyle ^= FONT_STRIKE; break; default: DBG_DEC(ucTmp); DBG_FIXME(); break; } break; case 90: /* fSmallCaps */ ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl); switch (ucTmp) { case 0: /* Unset */ pFont->usFontStyle &= ~FONT_SMALL_CAPITALS; break; case 1: /* Set */ pFont->usFontStyle |= FONT_SMALL_CAPITALS; break; case 128: /* Unchanged */ break; case 129: /* Negation */ pFont->usFontStyle ^= FONT_SMALL_CAPITALS; break; default: DBG_DEC(ucTmp); DBG_FIXME(); break; } break; case 91: /* fCaps */ ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl); switch (ucTmp) { case 0: /* Unset */ pFont->usFontStyle &= ~FONT_CAPITALS; break; case 1: /* Set */ pFont->usFontStyle |= FONT_CAPITALS; break; case 128: /* Unchanged */ break; case 129: /* Negation */ pFont->usFontStyle ^= FONT_CAPITALS; break; default: DBG_DEC(ucTmp); DBG_FIXME(); break; } break; case 92: /* fVanish */ ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl); switch (ucTmp) { case 0: /* Unset */ pFont->usFontStyle &= ~FONT_HIDDEN; break; case 1: /* Set */ pFont->usFontStyle |= FONT_HIDDEN; break; case 128: /* Unchanged */ break; case 129: /* Negation */ pFont->usFontStyle ^= FONT_HIDDEN; break; default: DBG_DEC(ucTmp); DBG_FIXME(); break; } break; case 93: /* cFtc */ usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl); if (usTmp <= (USHORT)UCHAR_MAX) { pFont->ucFontNumber = (UCHAR)usTmp; } else { DBG_DEC(usTmp); DBG_FIXME(); pFont->ucFontNumber = 0; } break; case 94: /* cKul */ ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl); if (ucTmp == 0 || ucTmp == 5) { pFont->usFontStyle &= ~FONT_UNDERLINE; } else { NO_DBG_MSG("Underline text"); pFont->usFontStyle |= FONT_UNDERLINE; if (ucTmp == 6) { DBG_MSG("Bold text"); pFont->usFontStyle |= FONT_BOLD; } } break; case 95: /* cHps, cHpsPos */ ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl); DBG_DEC(ucTmp); if (ucTmp != 0) { pFont->usFontSize = (USHORT)ucTmp; } ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl); DBG_DEC(ucTmp); break; case 98: /* cIco */ pFont->ucFontColor = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl); break; case 99: /* cHps */ pFont->usFontSize = usGetWord(iFodo + iFodoOff + 1, aucGrpprl); break; case 100: /* cHpsInc */ DBG_MSG("100: sprmCHpsInc"); ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl); DBG_DEC(ucTmp); break; case 103: /* cMajority */ DBG_MSG("103: sprmCMajority"); break; case 104: /* cIss */ ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl); ucTmp &= 0x07; if (ucTmp == 1) { pFont->usFontStyle |= FONT_SUPERSCRIPT; NO_DBG_MSG("Superscript"); } else if (ucTmp == 2) { pFont->usFontStyle |= FONT_SUBSCRIPT; NO_DBG_MSG("Subscript"); } break; case 106: /* cHpsInc1 */ usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl); lTmp = (long)pFont->usFontSize + (long)usTmp; if (lTmp < 8) { pFont->usFontSize = 8; } else if (lTmp > 32766) { pFont->usFontSize = 32766; } else { pFont->usFontSize = (USHORT)lTmp; } break; case 108: /* cMajority50 */ DBG_MSG("108: sprmCMajority50"); break; case 109: /* cHpsMul */ DBG_MSG("109: sprmCHpsMul"); usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl); DBG_DEC(usTmp); break; default: break; } iInfoLen = iGet6InfoLength(iFodo + iFodoOff, aucGrpprl); fail(iInfoLen <= 0); iFodoOff += iInfoLen; } } /* end of vGet6FontInfo */
/* * Build the lists with Paragraph Information for WinWord 1/2 files */ void vGet2PapInfo(FILE *pFile, const UCHAR *aucHeader) { row_block_type tRow; style_block_type tStyle; USHORT *ausParfPage; UCHAR *aucBuffer; ULONG ulCharPos, ulCharPosFirst, ulCharPosLast; ULONG ulBeginParfInfo; size_t tParfInfoLen, tParfPageNum, tOffset, tSize, tLenOld, tLen; int iIndex, iIndex2, iRun, iFodo, iLen; row_info_enum eRowInfo; USHORT usParfFirstPage, usCount, usIstd; UCHAR ucStc; UCHAR aucFpage[BIG_BLOCK_SIZE]; fail(pFile == NULL || aucHeader == NULL); ulBeginParfInfo = ulGetLong(0xa6, aucHeader); /* fcPlcfbtePapx */ NO_DBG_HEX(ulBeginParfInfo); tParfInfoLen = (size_t)usGetWord(0xaa, aucHeader); /* cbPlcfbtePapx */ NO_DBG_DEC(tParfInfoLen); if (tParfInfoLen < 4) { DBG_DEC(tParfInfoLen); return; } aucBuffer = xmalloc(tParfInfoLen); if (!bReadBytes(aucBuffer, tParfInfoLen, ulBeginParfInfo, pFile)) { aucBuffer = xfree(aucBuffer); return; } NO_DBG_PRINT_BLOCK(aucBuffer, tParfInfoLen); tLen = (tParfInfoLen - 4) / 6; ausParfPage = xcalloc(tLen, sizeof(USHORT)); for (iIndex = 0, tOffset = (tLen + 1) * 4; iIndex < (int)tLen; iIndex++, tOffset += 2) { ausParfPage[iIndex] = usGetWord(tOffset, aucBuffer); NO_DBG_DEC(ausParfPage[iIndex]); } DBG_HEX(ulGetLong(0, aucBuffer)); aucBuffer = xfree(aucBuffer); tParfPageNum = (size_t)usGetWord(0x144, aucHeader); /* cpnBtePap */ DBG_DEC(tParfPageNum); if (tLen < tParfPageNum) { /* Replace ParfPage by a longer version */ tLenOld = tLen; usParfFirstPage = usGetWord(0x140, aucHeader); /* pnPapFirst */ DBG_DEC(usParfFirstPage); tLen += tParfPageNum - 1; tSize = tLen * sizeof(USHORT); ausParfPage = xrealloc(ausParfPage, tSize); /* Add new values */ usCount = usParfFirstPage + 1; for (iIndex = (int)tLenOld; iIndex < (int)tLen; iIndex++) { ausParfPage[iIndex] = usCount; NO_DBG_DEC(ausParfPage[iIndex]); usCount++; } } (void)memset(&tRow, 0, sizeof(tRow)); ulCharPosFirst = CP_INVALID; for (iIndex = 0; iIndex < (int)tLen; iIndex++) { if (!bReadBytes(aucFpage, BIG_BLOCK_SIZE, (ULONG)ausParfPage[iIndex] * BIG_BLOCK_SIZE, pFile)) { break; } NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE); iRun = (int)ucGetByte(0x1ff, aucFpage); NO_DBG_DEC(iRun); for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) { if ((iRun + 1) * 4 + iIndex2 * 1 >= BIG_BLOCK_SIZE) { break; } NO_DBG_HEX(ulGetLong(iIndex2 * 4, aucFpage)); iFodo = 2 * (int)ucGetByte( (iRun + 1) * 4 + iIndex2 * 1, aucFpage); if (iFodo <= 0) { continue; } iLen = 2 * (int)ucGetByte(iFodo, aucFpage); ucStc = ucGetByte(iFodo + 1, aucFpage); usIstd = usStc2istd(ucStc); vFillStyleFromStylesheet(usIstd, &tStyle); vGet2StyleInfo(iFodo, aucFpage + 8, iLen - 8, &tStyle); ulCharPos = ulGetLong(iIndex2 * 4, aucFpage); NO_DBG_HEX(ulCharPos); tStyle.ulFileOffset = ulCharPos; vAdd2StyleInfoList(&tStyle); eRowInfo = eGet2RowInfo(iFodo, aucFpage + 8, iLen - 8, &tRow); switch(eRowInfo) { case found_a_cell: if (ulCharPosFirst != CP_INVALID) { break; } ulCharPosFirst = ulGetLong( iIndex2 * 4, aucFpage); NO_DBG_HEX(ulCharPosFirst); tRow.ulCharPosStart = ulCharPosFirst; tRow.ulFileOffsetStart = ulCharPosFirst; break; case found_end_of_row: ulCharPosLast = ulGetLong( iIndex2 * 4, aucFpage); NO_DBG_HEX(ulCharPosLast); tRow.ulCharPosEnd = ulCharPosLast; /* Add 1 for compatiblity with Word 6 and up */ tRow.ulFileOffsetEnd = ulCharPosLast + 1; vAdd2RowInfoList(&tRow); (void)memset(&tRow, 0, sizeof(tRow)); ulCharPosFirst = CP_INVALID; break; case found_nothing: break; default: DBG_DEC(eRowInfo); break; } } } ausParfPage = xfree(ausParfPage); } /* end of vGet2PapInfo */
/* * Translate the rowinfo to a member of the row_info enumeration */ row_info_enum eGet2RowInfo(int iFodo, const UCHAR *aucGrpprl, int iBytes, row_block_type *pRow) { int iFodoOff, iInfoLen; int iIndex, iSize, iCol; int iPosCurr, iPosPrev; USHORT usTmp; BOOL bFound24_0, bFound24_1, bFound25_0, bFound25_1, bFound154; fail(iFodo < 0 || aucGrpprl == NULL || pRow == NULL); iFodoOff = 0; bFound24_0 = FALSE; bFound24_1 = FALSE; bFound25_0 = FALSE; bFound25_1 = FALSE; bFound154 = FALSE; while (iBytes >= iFodoOff + 1) { iInfoLen = 0; switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) { case 24: /* fIntable */ if (odd(ucGetByte(iFodo + iFodoOff + 1, aucGrpprl))) { bFound24_1 = TRUE; } else { bFound24_0 = TRUE; } break; case 25: /* fTtp */ if (odd(ucGetByte(iFodo + iFodoOff + 1, aucGrpprl))) { bFound25_1 = TRUE; } else { bFound25_0 = TRUE; } break; case 30: /* brcTop10 */ usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl); usTmp &= 0x01ff; NO_DBG_DEC(usTmp >> 6); if (usTmp == 0) { pRow->ucBorderInfo &= ~TABLE_BORDER_TOP; } else { pRow->ucBorderInfo |= TABLE_BORDER_TOP; } break; case 31: /* brcLeft10 */ usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl); usTmp &= 0x01ff; NO_DBG_DEC(usTmp >> 6); if (usTmp == 0) { pRow->ucBorderInfo &= ~TABLE_BORDER_LEFT; } else { pRow->ucBorderInfo |= TABLE_BORDER_LEFT; } break; case 32: /* brcBottom10 */ usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl); usTmp &= 0x01ff; NO_DBG_DEC(usTmp >> 6); if (usTmp == 0) { pRow->ucBorderInfo &= ~TABLE_BORDER_BOTTOM; } else { pRow->ucBorderInfo |= TABLE_BORDER_BOTTOM; } break; case 33: /* brcRight10 */ usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl); usTmp &= 0x01ff; NO_DBG_DEC(usTmp >> 6); if (usTmp == 0) { pRow->ucBorderInfo &= ~TABLE_BORDER_RIGHT; } else { pRow->ucBorderInfo |= TABLE_BORDER_RIGHT; } break; case 38: /* brcTop */ usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl); usTmp &= 0x0018; NO_DBG_DEC(usTmp >> 3); if (usTmp == 0) { pRow->ucBorderInfo &= ~TABLE_BORDER_TOP; } else { pRow->ucBorderInfo |= TABLE_BORDER_TOP; } break; case 39: /* brcLeft */ usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl); usTmp &= 0x0018; NO_DBG_DEC(usTmp >> 3); if (usTmp == 0) { pRow->ucBorderInfo &= ~TABLE_BORDER_LEFT; } else { pRow->ucBorderInfo |= TABLE_BORDER_LEFT; } break; case 40: /* brcBottom */ usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl); usTmp &= 0x0018; NO_DBG_DEC(usTmp >> 3); if (usTmp == 0) { pRow->ucBorderInfo &= ~TABLE_BORDER_BOTTOM; } else { pRow->ucBorderInfo |= TABLE_BORDER_BOTTOM; } break; case 41: /* brcRight */ usTmp = usGetWord(iFodo + iFodoOff + 1, aucGrpprl); usTmp &= 0x0018; NO_DBG_DEC(usTmp >> 3); if (usTmp == 0) { pRow->ucBorderInfo &= ~TABLE_BORDER_RIGHT; } else { pRow->ucBorderInfo |= TABLE_BORDER_RIGHT; } break; case 152: /* cDefTable10 */ case 154: /* cDefTable */ iSize = (int)usGetWord(iFodo + iFodoOff + 1, aucGrpprl); if (iSize < 6 || iBytes < iFodoOff + 7) { DBG_DEC(iSize); DBG_DEC(iBytes); DBG_DEC(iFodoOff); iInfoLen = 1; break; } iCol = (int)ucGetByte(iFodo + iFodoOff + 3, aucGrpprl); if (iCol < 1 || iBytes < iFodoOff + 3 + (iCol + 1) * 2) { DBG_DEC(iCol); DBG_DEC(iBytes); DBG_DEC(iFodoOff); DBG_DEC(ucGetByte(iFodo + iFodoOff, aucGrpprl)); iInfoLen = 1; break; } if (iCol >= (int)elementsof(pRow->asColumnWidth)) { DBG_DEC(iCol); werr(1, "The number of columns is corrupt"); } pRow->ucNumberOfColumns = (UCHAR)iCol; iPosPrev = (int)(short)usGetWord( iFodo + iFodoOff + 4, aucGrpprl); for (iIndex = 0; iIndex < iCol; iIndex++) { iPosCurr = (int)(short)usGetWord( iFodo + iFodoOff + 6 + iIndex * 2, aucGrpprl); pRow->asColumnWidth[iIndex] = (short)(iPosCurr - iPosPrev); iPosPrev = iPosCurr; } bFound154 = TRUE; break; default: break; } if (iInfoLen <= 0) { iInfoLen = iGet2InfoLength(iFodo + iFodoOff, aucGrpprl); fail(iInfoLen <= 0); } iFodoOff += iInfoLen; } if (bFound24_1 && bFound25_1 && bFound154) { return found_end_of_row; } if (bFound24_0 && bFound25_0 && !bFound154) { return found_not_end_of_row; } if (bFound24_1) { return found_a_cell; } if (bFound24_0) { return found_not_a_cell; } return found_nothing; } /* end of eGet2RowInfo */
/* * Build the lists with Character Information for Word 8/9/10/11 files */ void vGet8ChrInfo(FILE *pFile, const pps_info_type *pPPS, const ULONG *aulBBD, size_t tBBDLen, const ULONG *aulSBD, size_t tSBDLen, const UCHAR *aucHeader) { font_block_type tFont; picture_block_type tPicture; ULONG *aulCharPage; UCHAR *aucBuffer; ULONG ulFileOffset, ulCharPos, ulBeginCharInfo; size_t tCharInfoLen, tOffset, tLen; int iIndex, iIndex2, iRun, iFodo, iLen; USHORT usIstd; UCHAR aucFpage[BIG_BLOCK_SIZE]; fail(pFile == NULL || pPPS == NULL || aucHeader == NULL); fail(aulBBD == NULL || aulSBD == NULL); ulBeginCharInfo = ulGetLong(0xfa, aucHeader); /* fcPlcfbteChpx */ NO_DBG_HEX(ulBeginCharInfo); tCharInfoLen = (size_t)ulGetLong(0xfe, aucHeader); /* lcbPlcfbteChpx */ NO_DBG_DEC(tCharInfoLen); if (tCharInfoLen < 4) { DBG_DEC(tCharInfoLen); return; } aucBuffer = aucFillInfoBuffer(pFile, &pPPS->tTable, aulBBD, tBBDLen, aulSBD, tSBDLen, ulBeginCharInfo, tCharInfoLen); if (aucBuffer == NULL) { return; } NO_DBG_PRINT_BLOCK(aucBuffer, tCharInfoLen); tLen = (tCharInfoLen / 4 - 1) / 2; aulCharPage = xcalloc(tLen, sizeof(ULONG)); for (iIndex = 0, tOffset = (tLen + 1) * 4; iIndex < (int)tLen; iIndex++, tOffset += 4) { aulCharPage[iIndex] = ulGetLong(tOffset, aucBuffer); NO_DBG_DEC(aulCharPage[iIndex]); } DBG_HEX(ulGetLong(0, aucBuffer)); aucBuffer = xfree(aucBuffer); NO_DBG_PRINT_BLOCK(aucHeader, HEADER_SIZE); for (iIndex = 0; iIndex < (int)tLen; iIndex++) { fail(aulCharPage[iIndex] > ULONG_MAX / BIG_BLOCK_SIZE); if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB, aulBBD, tBBDLen, BIG_BLOCK_SIZE, aucFpage, aulCharPage[iIndex] * BIG_BLOCK_SIZE, BIG_BLOCK_SIZE)) { break; } NO_DBG_PRINT_BLOCK(aucFpage, BIG_BLOCK_SIZE); iRun = (int)ucGetByte(0x1ff, aucFpage); NO_DBG_DEC(iRun); for (iIndex2 = 0; iIndex2 < iRun; iIndex2++) { ulCharPos = ulGetLong(iIndex2 * 4, aucFpage); ulFileOffset = ulCharPos2FileOffset(ulCharPos); iFodo = 2 * (int)ucGetByte( (iRun + 1) * 4 + iIndex2, aucFpage); iLen = (int)ucGetByte(iFodo, aucFpage); usIstd = usGetIstd(ulFileOffset); vFillFontFromStylesheet(usIstd, &tFont); if (iFodo != 0) { vGet8FontInfo(iFodo, usIstd, aucFpage + 1, iLen - 1, &tFont); } tFont.ulFileOffset = ulFileOffset; vAdd2FontInfoList(&tFont); if (iFodo <= 0) { continue; } (void)memset(&tPicture, 0, sizeof(tPicture)); if (bGet8PicInfo(iFodo, aucFpage + 1, iLen - 1, &tPicture)) { tPicture.ulFileOffset = ulFileOffset; tPicture.ulFileOffsetPicture =ulDataPos2FileOffset(tPicture.ulPictureOffset); vAdd2PictInfoList(&tPicture); } } } aulCharPage = xfree(aulCharPage); } /* end of vGet8ChrInfo */
/* * Fill the font information block with information * from a Word 8/9/10/11 file. */ void vGet8FontInfo(int iFodo, USHORT usIstd, const UCHAR *aucGrpprl, int iBytes, font_block_type *pFont) { long lTmp; int iFodoOff, iInfoLen; USHORT usFtc0, usFtc1, usFtc2, usTmp; UCHAR ucTmp; fail(iFodo < 0 || aucGrpprl == NULL || pFont == NULL); usFtc0 = USHRT_MAX; usFtc1 = USHRT_MAX; usFtc2 = USHRT_MAX; iFodoOff = 0; while (iBytes >= iFodoOff + 2) { switch (usGetWord(iFodo + iFodoOff, aucGrpprl)) { case 0x0800: /* fRMarkDel */ ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl); if (ucTmp == 0) { pFont->usFontStyle &= ~FONT_MARKDEL; } else { pFont->usFontStyle |= FONT_MARKDEL; } break; case 0x0835: /* fBold */ ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl); switch (ucTmp) { case 0: /* Unset */ pFont->usFontStyle &= ~FONT_BOLD; break; case 1: /* Set */ pFont->usFontStyle |= FONT_BOLD; break; case 128: /* Unchanged */ break; case 129: /* Negation */ pFont->usFontStyle ^= FONT_BOLD; break; default: DBG_DEC(ucTmp); DBG_FIXME(); break; } break; case 0x0836: /* fItalic */ ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl); switch (ucTmp) { case 0: /* Unset */ pFont->usFontStyle &= ~FONT_ITALIC; break; case 1: /* Set */ pFont->usFontStyle |= FONT_ITALIC; break; case 128: /* Unchanged */ break; case 129: /* Negation */ pFont->usFontStyle ^= FONT_ITALIC; break; default: DBG_DEC(ucTmp); DBG_FIXME(); break; } break; case 0x0837: /* fStrike */ ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl); switch (ucTmp) { case 0: /* Unset */ pFont->usFontStyle &= ~FONT_STRIKE; break; case 1: /* Set */ pFont->usFontStyle |= FONT_STRIKE; break; case 128: /* Unchanged */ break; case 129: /* Negation */ pFont->usFontStyle ^= FONT_STRIKE; break; default: DBG_DEC(ucTmp); DBG_FIXME(); break; } break; case 0x083a: /* fSmallCaps */ ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl); switch (ucTmp) { case 0: /* Unset */ pFont->usFontStyle &= ~FONT_SMALL_CAPITALS; break; case 1: /* Set */ pFont->usFontStyle |= FONT_SMALL_CAPITALS; break; case 128: /* Unchanged */ break; case 129: /* Negation */ pFont->usFontStyle ^= FONT_SMALL_CAPITALS; break; default: DBG_DEC(ucTmp); DBG_FIXME(); break; } break; case 0x083b: /* fCaps */ ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl); switch (ucTmp) { case 0: /* Unset */ pFont->usFontStyle &= ~FONT_CAPITALS; break; case 1: /* Set */ pFont->usFontStyle |= FONT_CAPITALS; break; case 128: /* Unchanged */ break; case 129: /* Negation */ pFont->usFontStyle ^= FONT_CAPITALS; break; default: DBG_DEC(ucTmp); DBG_FIXME(); break; } break; case 0x083c: /* fVanish */ ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl); switch (ucTmp) { case 0: /* Unset */ pFont->usFontStyle &= ~FONT_HIDDEN; break; case 1: /* Set */ pFont->usFontStyle |= FONT_HIDDEN; break; case 128: /* Unchanged */ break; case 129: /* Negation */ pFont->usFontStyle ^= FONT_HIDDEN; break; default: DBG_DEC(ucTmp); DBG_FIXME(); break; } break; case 0x2a32: /* cDefault */ pFont->usFontStyle &= FONT_HIDDEN; pFont->ucFontColor = FONT_COLOR_DEFAULT; break; case 0x2a33: /* cPlain */ DBG_MSG("2a33: cPlain"); vFillFontFromStylesheet(usIstd, pFont); break; case 0x2a3e: /* cKul */ ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl); if (ucTmp == 0 || ucTmp == 5) { pFont->usFontStyle &= ~FONT_UNDERLINE; } else { NO_DBG_MSG("Underline text"); pFont->usFontStyle |= FONT_UNDERLINE; if (ucTmp == 6) { DBG_MSG("Bold text"); pFont->usFontStyle |= FONT_BOLD; } } break; case 0x2a42: /* cIco */ pFont->ucFontColor = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl); NO_DBG_DEC(pFont->ucFontColor); break; case 0x2a44: /* cHpsInc */ DBG_MSG("0x2a44: sprmCHpsInc"); ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl); DBG_DEC(ucTmp); break; case 0x2a48: /* cIss */ ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl); ucTmp &= 0x07; if (ucTmp == 1) { pFont->usFontStyle |= FONT_SUPERSCRIPT; NO_DBG_MSG("Superscript"); } else if (ucTmp == 2) { pFont->usFontStyle |= FONT_SUBSCRIPT; NO_DBG_MSG("Subscript"); } break; case 0x4a30: /* cIstd */ usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl); NO_DBG_DEC(usTmp); break; case 0x4a43: /* cHps */ pFont->usFontSize = usGetWord(iFodo + iFodoOff + 2, aucGrpprl); NO_DBG_DEC(pFont->usFontSize); break; case 0x4a4d: /* cHpsMul */ DBG_MSG("0x4a4d: sprmCHpsMul"); usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl); DBG_DEC(usTmp); break; case 0x4a4f: /* cFtc0 */ usFtc0 = usGetWord(iFodo + iFodoOff + 2, aucGrpprl); break; case 0x4a50: /* cFtc1 */ usFtc1 = usGetWord(iFodo + iFodoOff + 2, aucGrpprl); break; case 0x4a51: /* cFtc2 */ usFtc2 = usGetWord(iFodo + iFodoOff + 2, aucGrpprl); break; case 0xca47: /* cMajority */ DBG_MSG("0xca47: sprmCMajority"); break; case 0xca4a: /* cHpsInc1 */ usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl); lTmp = (long)pFont->usFontSize + (long)usTmp; if (lTmp < 8) { pFont->usFontSize = 8; } else if (lTmp > 32766) { pFont->usFontSize = 32766; } else { pFont->usFontSize = (USHORT)lTmp; } break; case 0xca4c: /* cMajority50 */ DBG_MSG("0xca4c: sprmCMajority50"); break; case 0xea3f: /* cHps, cHpsPos */ ucTmp = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl); DBG_DEC(ucTmp); if (ucTmp != 0) { pFont->usFontSize = (USHORT)ucTmp; } ucTmp = ucGetByte(iFodo + iFodoOff + 3, aucGrpprl); DBG_DEC(ucTmp); break; default: break; } iInfoLen = iGet8InfoLength(iFodo + iFodoOff, aucGrpprl); fail(iInfoLen <= 0); iFodoOff += iInfoLen; } /* Combine the Ftc's to a FontNumber */ NO_DBG_DEC_C(usFtc0 != USHRT_MAX, usFtc0); NO_DBG_DEC_C(usFtc2 != USHRT_MAX, usFtc2); NO_DBG_DEC_C(usFtc1 != USHRT_MAX, usFtc1); if (usFtc0 <= 0x7fff) { if (usFtc0 <= (USHORT)UCHAR_MAX) { pFont->ucFontNumber = (UCHAR)usFtc0; } else { DBG_DEC(usFtc0); DBG_FIXME(); pFont->ucFontNumber = 0; } } else if (usFtc2 <= 0x7fff) { if (usFtc2 <= (USHORT)UCHAR_MAX) { pFont->ucFontNumber = (UCHAR)usFtc2; } else { DBG_DEC(usFtc2); DBG_FIXME(); pFont->ucFontNumber = 0; } } else if (usFtc1 <= 0x7fff) { if (usFtc1 <= (USHORT)UCHAR_MAX) { pFont->ucFontNumber = (UCHAR)usFtc1; } else { DBG_DEC(usFtc1); DBG_FIXME(); pFont->ucFontNumber = 0; } } } /* end of vGet8FontInfo */
/* * Fill the style information block with information * from a WinWord 1/2 file. */ void vGet2StyleInfo(int iFodo, const UCHAR *aucGrpprl, int iBytes, style_block_type *pStyle) { int iFodoOff, iInfoLen; int iTmp, iDel, iAdd; short sTmp; UCHAR ucTmp; fail(iFodo < 0 || aucGrpprl == NULL || pStyle == NULL); NO_DBG_DEC(pStyle->usIstd); iFodoOff = 0; while (iBytes >= iFodoOff + 1) { iInfoLen = 0; switch (ucGetByte(iFodo + iFodoOff, aucGrpprl)) { case 2: /* istd */ sTmp = (short)ucGetByte( iFodo + iFodoOff + 1, aucGrpprl); NO_DBG_DEC(sTmp); break; case 5: /* jc */ pStyle->ucAlignment = ucGetByte( iFodo + iFodoOff + 1, aucGrpprl); break; case 12: /* nfcSeqNumb */ pStyle->ucNFC = ucGetByte( iFodo + iFodoOff + 1, aucGrpprl); break; case 13: /* nLvlAnm */ ucTmp = ucGetByte(iFodo + iFodoOff + 1, aucGrpprl); pStyle->ucNumLevel = ucTmp; pStyle->bNumPause = eGetNumType(ucTmp) == level_type_pause; break; case 15: /* ChgTabsPapx */ case 23: /* ChgTabs */ iTmp = (int)ucGetByte(iFodo + iFodoOff + 1, aucGrpprl); if (iTmp < 2) { iInfoLen = 1; break; } NO_DBG_DEC(iTmp); iDel = (int)ucGetByte(iFodo + iFodoOff + 2, aucGrpprl); if (iTmp < 2 + 2 * iDel) { iInfoLen = 1; break; } NO_DBG_DEC(iDel); iAdd = (int)ucGetByte( iFodo + iFodoOff + 3 + 2 * iDel, aucGrpprl); if (iTmp < 2 + 2 * iDel + 2 * iAdd) { iInfoLen = 1; break; } NO_DBG_DEC(iAdd); break; case 16: /* dxaRight */ pStyle->sRightIndent = (short)usGetWord( iFodo + iFodoOff + 1, aucGrpprl); NO_DBG_DEC(pStyle->sRightIndent); break; case 17: /* dxaLeft */ pStyle->sLeftIndent = (short)usGetWord( iFodo + iFodoOff + 1, aucGrpprl); NO_DBG_DEC(pStyle->sLeftIndent); break; case 18: /* Nest dxaLeft */ sTmp = (short)usGetWord( iFodo + iFodoOff + 1, aucGrpprl); pStyle->sLeftIndent += sTmp; if (pStyle->sLeftIndent < 0) { pStyle->sLeftIndent = 0; } NO_DBG_DEC(sTmp); NO_DBG_DEC(pStyle->sLeftIndent); break; case 19: /* dxaLeft1 */ pStyle->sLeftIndent1 = (short)usGetWord( iFodo + iFodoOff + 1, aucGrpprl); NO_DBG_DEC(pStyle->sLeftIndent1); break; case 21: /* dyaBefore */ pStyle->usBeforeIndent = usGetWord( iFodo + iFodoOff + 1, aucGrpprl); NO_DBG_DEC(pStyle->usBeforeIndent); break; case 22: /* dyaAfter */ pStyle->usAfterIndent = usGetWord( iFodo + iFodoOff + 1, aucGrpprl); NO_DBG_DEC(pStyle->usAfterIndent); break; default: break; } if (iInfoLen <= 0) { iInfoLen = iGet2InfoLength(iFodo + iFodoOff, aucGrpprl); fail(iInfoLen <= 0); } iFodoOff += iInfoLen; } } /* end of vGet2StyleInfo */
/* * Translate the rowinfo to a member of the row_info enumeration */ row_info_enum eGet8RowInfo(int iFodo, const UCHAR *aucGrpprl, int iBytes, row_block_type *pRow) { int iFodoOff, iInfoLen; int iIndex, iSize, iCol; int iPosCurr, iPosPrev; USHORT usTmp; BOOL bFound2416_0, bFound2416_1, bFound2417_0, bFound2417_1; BOOL bFound244b_0, bFound244b_1, bFound244c_0, bFound244c_1; BOOL bFoundd608; fail(iFodo < 0 || aucGrpprl == NULL || pRow == NULL); iFodoOff = 0; bFound2416_0 = FALSE; bFound2416_1 = FALSE; bFound2417_0 = FALSE; bFound2417_1 = FALSE; bFound244b_0 = FALSE; bFound244b_1 = FALSE; bFound244c_0 = FALSE; bFound244c_1 = FALSE; bFoundd608 = FALSE; while (iBytes >= iFodoOff + 2) { iInfoLen = 0; switch (usGetWord(iFodo + iFodoOff, aucGrpprl)) { case 0x2416: /* fInTable */ if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) { bFound2416_1 = TRUE; } else { bFound2416_0 = TRUE; } break; case 0x2417: /* fTtp */ if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) { bFound2417_1 = TRUE; } else { bFound2417_0 = TRUE; } break; case 0x244b: /* sub-table fInTable */ if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) { bFound244b_1 = TRUE; } else { bFound244b_0 = TRUE; } break; case 0x244c: /* sub-table fTtp */ if (odd(ucGetByte(iFodo + iFodoOff + 2, aucGrpprl))) { bFound244c_1 = TRUE; } else { bFound244c_0 = TRUE; } break; case 0x6424: /* brcTop */ usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl); usTmp &= 0xff00; NO_DBG_DEC(usTmp >> 8); if (usTmp == 0) { pRow->ucBorderInfo &= ~TABLE_BORDER_TOP; } else { pRow->ucBorderInfo |= TABLE_BORDER_TOP; } break; case 0x6425: /* brcLeft */ usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl); usTmp &= 0xff00; NO_DBG_DEC(usTmp >> 8); if (usTmp == 0) { pRow->ucBorderInfo &= ~TABLE_BORDER_LEFT; } else { pRow->ucBorderInfo |= TABLE_BORDER_LEFT; } break; case 0x6426: /* brcBottom */ usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl); usTmp &= 0xff00; NO_DBG_DEC(usTmp >> 8); if (usTmp == 0) { pRow->ucBorderInfo &= ~TABLE_BORDER_BOTTOM; } else { pRow->ucBorderInfo |= TABLE_BORDER_BOTTOM; } break; case 0x6427: /* brcRight */ usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl); usTmp &= 0xff00; NO_DBG_DEC(usTmp >> 8); if (usTmp == 0) { pRow->ucBorderInfo &= ~TABLE_BORDER_RIGHT; } else { pRow->ucBorderInfo |= TABLE_BORDER_RIGHT; } break; case 0xd606: /* cDefTable10 */ DBG_MSG("0xd606: sprmTDefTable10"); iSize = (int)usGetWord(iFodo + iFodoOff + 2, aucGrpprl); DBG_DEC(iSize); break; case 0xd608: /* cDefTable */ iSize = (int)usGetWord(iFodo + iFodoOff + 2, aucGrpprl); if (iSize < 6 || iBytes < iFodoOff + 8) { DBG_DEC(iSize); DBG_DEC(iFodoOff); iInfoLen = 2; break; } iCol = (int)ucGetByte(iFodo + iFodoOff + 4, aucGrpprl); if (iCol < 1 || iBytes < iFodoOff + 4 + (iCol + 1) * 2) { DBG_DEC(iCol); DBG_DEC(iFodoOff); iInfoLen = 2; break; } if (iCol >= (int)elementsof(pRow->asColumnWidth)) { DBG_DEC(iCol); werr(1, "The number of columns is corrupt"); } pRow->ucNumberOfColumns = (UCHAR)iCol; iPosPrev = (int)(short)usGetWord( iFodo + iFodoOff + 5, aucGrpprl); for (iIndex = 0; iIndex < iCol; iIndex++) { iPosCurr = (int)(short)usGetWord( iFodo + iFodoOff + 7 + iIndex * 2, aucGrpprl); pRow->asColumnWidth[iIndex] = (short)(iPosCurr - iPosPrev); iPosPrev = iPosCurr; } bFoundd608 = TRUE; break; default: break; } if (iInfoLen <= 0) { iInfoLen = iGet8InfoLength(iFodo + iFodoOff, aucGrpprl); fail(iInfoLen <= 0); } iFodoOff += iInfoLen; } if (bFound2417_1 && bFoundd608) { return found_end_of_row; } if (bFound2417_0 && !bFoundd608) { return found_not_end_of_row; } if (bFound2416_1 || bFound244b_1) { return found_a_cell; } if (bFound2416_0 || bFound244b_0) { return found_not_a_cell; } return found_nothing; } /* end of eGet8RowInfo */
/* * Fill the font information block with information * from a WinWord 1 file. */ void vGet1FontInfo(int iFodo, const UCHAR *aucGrpprl, size_t tBytes, font_block_type *pFont) { BOOL bIcoChange, bFtcChange, bHpsChange, bKulChange; USHORT usTmp; UCHAR ucTmp; UCHAR aucChpx[12]; fail(iFodo < 0 || aucGrpprl == NULL || pFont == NULL); if (tBytes > sizeof(aucChpx)) { NO_DBG_PRINT_BLOCK(aucGrpprl + iFodo, tBytes); return; } /* Build the CHPX structure */ (void)memset(aucChpx, 0, sizeof(aucChpx)); (void)memcpy(aucChpx, aucGrpprl + iFodo, min(tBytes, sizeof(aucChpx))); usTmp = usGetWord(0, aucChpx); if ((usTmp & BIT(0)) != 0) { pFont->usFontStyle ^= FONT_BOLD; } if ((usTmp & BIT(1)) != 0) { pFont->usFontStyle ^= FONT_ITALIC; } if ((usTmp & BIT(2)) != 0) { pFont->usFontStyle ^= FONT_STRIKE; } if ((usTmp & BIT(5)) != 0) { pFont->usFontStyle ^= FONT_SMALL_CAPITALS; } if ((usTmp & BIT(6)) != 0) { pFont->usFontStyle ^= FONT_CAPITALS; } if ((usTmp & BIT(7)) != 0) { pFont->usFontStyle ^= FONT_HIDDEN; } ucTmp = ucGetByte(5, aucChpx); if (ucTmp != 0) { if (ucTmp < 128) { pFont->usFontStyle |= FONT_SUPERSCRIPT; DBG_MSG("Superscript"); } else { pFont->usFontStyle |= FONT_SUBSCRIPT; DBG_MSG("Subscript"); } } bIcoChange = (usTmp & BIT(10)) != 0; bFtcChange = (usTmp & BIT(11)) != 0; bHpsChange = (usTmp & BIT(12)) != 0; bKulChange = (usTmp & BIT(13)) != 0; if (bFtcChange) { usTmp = usGetWord(2, aucChpx); if (usTmp <= (USHORT)UCHAR_MAX) { pFont->ucFontNumber = (UCHAR)usTmp; } else { pFont->ucFontNumber = 0; } } if (bHpsChange) { pFont->usFontSize = (USHORT)ucGetByte(4, aucChpx); } if (bIcoChange || bKulChange) { usTmp = usGetWord(6, aucChpx); if (bIcoChange) { pFont->ucFontColor = (UCHAR)((usTmp & 0x0f00) >> 8); if (pFont->ucFontColor <= 7) { /* Add 1 for compatibility with Word 2 and up */ pFont->ucFontColor++; } else { DBG_DEC(pFont->ucFontColor); pFont->ucFontColor = 0; } } if (bKulChange) { usTmp = (usTmp & 0x7000) >> 12; DBG_DEC_C(usTmp > 4, usTmp); if (usTmp == 0) { pFont->usFontStyle &= ~FONT_UNDERLINE; } else { pFont->usFontStyle |= FONT_UNDERLINE; } } }
/* * Fill the style information block with information * from a Word 8/9/10/11 file. */ void vGet8StyleInfo(int iFodo, const UCHAR *aucGrpprl, int iBytes, style_block_type *pStyle) { list_block_type tList6; const list_block_type *pList; int iFodoOff, iInfoLen; int iTmp, iDel, iAdd, iBefore; USHORT usOpCode, usTmp; short sTmp; fail(iFodo < 0 || aucGrpprl == NULL || pStyle == NULL); NO_DBG_DEC_C(pStyle->usListIndex != 0, pStyle->usIstd); NO_DBG_DEC_C(pStyle->usListIndex != 0, pStyle->usListIndex); (void)memset(&tList6, 0, sizeof(tList6)); iFodoOff = 0; while (iBytes >= iFodoOff + 2) { iInfoLen = 0; usOpCode = usGetWord(iFodo + iFodoOff, aucGrpprl); switch (usOpCode) { case 0x2403: /* jc */ pStyle->ucAlignment = ucGetByte( iFodo + iFodoOff + 2, aucGrpprl); break; case 0x260a: /* ilvl */ pStyle->ucListLevel = ucGetByte(iFodo + iFodoOff + 2, aucGrpprl); NO_DBG_DEC(pStyle->ucListLevel); pStyle->ucNumLevel = pStyle->ucListLevel; break; case 0x4600: /* istd */ usTmp = usGetWord(iFodo + iFodoOff + 2, aucGrpprl); NO_DBG_DEC(usTmp); break; case 0x460b: /* ilfo */ pStyle->usListIndex = usGetWord(iFodo + iFodoOff + 2, aucGrpprl); NO_DBG_DEC(pStyle->usListIndex); break; case 0x4610: /* Nest dxaLeft */ sTmp = (short)usGetWord( iFodo + iFodoOff + 2, aucGrpprl); pStyle->sLeftIndent += sTmp; if (pStyle->sLeftIndent < 0) { pStyle->sLeftIndent = 0; } DBG_DEC(sTmp); DBG_DEC(pStyle->sLeftIndent); break; case 0xc60d: /* ChgTabsPapx */ case 0xc615: /* ChgTabs */ iTmp = (int)ucGetByte(iFodo + iFodoOff + 2, aucGrpprl); if (iTmp < 2) { iInfoLen = 1; break; } NO_DBG_DEC(iTmp); iDel = (int)ucGetByte(iFodo + iFodoOff + 3, aucGrpprl); if (iTmp < 2 + 2 * iDel) { iInfoLen = 1; break; } NO_DBG_DEC(iDel); iAdd = (int)ucGetByte( iFodo + iFodoOff + 4 + 2 * iDel, aucGrpprl); if (iTmp < 2 + 2 * iDel + 2 * iAdd) { iInfoLen = 1; break; } NO_DBG_DEC(iAdd); break; case 0x840e: /* dxaRight */ pStyle->sRightIndent = (short)usGetWord( iFodo + iFodoOff + 2, aucGrpprl); NO_DBG_DEC(pStyle->sRightIndent); break; case 0x840f: /* dxaLeft */ pStyle->sLeftIndent = (short)usGetWord( iFodo + iFodoOff + 2, aucGrpprl); NO_DBG_DEC(pStyle->sLeftIndent); break; case 0x8411: /* dxaLeft1 */ pStyle->sLeftIndent1 = (short)usGetWord( iFodo + iFodoOff + 2, aucGrpprl); NO_DBG_DEC(pStyle->sLeftIndent1); break; case 0xa413: /* dyaBefore */ pStyle->usBeforeIndent = usGetWord( iFodo + iFodoOff + 2, aucGrpprl); NO_DBG_DEC(pStyle->usBeforeIndent); break; case 0xa414: /* dyaAfter */ pStyle->usAfterIndent = usGetWord( iFodo + iFodoOff + 2, aucGrpprl); NO_DBG_DEC(pStyle->usAfterIndent); break; case 0xc63e: /* anld */ iTmp = (int)ucGetByte( iFodo + iFodoOff + 2, aucGrpprl); DBG_DEC_C(iTmp < 84, iTmp); if (iTmp >= 1) { tList6.ucNFC = ucGetByte( iFodo + iFodoOff + 3, aucGrpprl); } if (tList6.ucNFC != LIST_BULLETS && iTmp >= 2) { iBefore = (int)ucGetByte( iFodo + iFodoOff + 4, aucGrpprl); } else { iBefore = 0; } if (iTmp >= 12) { tList6.ulStartAt = (ULONG)usGetWord( iFodo + iFodoOff + 13, aucGrpprl); } if (iTmp >= iBefore + 22) { tList6.usListChar = usGetWord( iFodo + iFodoOff + iBefore + 23, aucGrpprl); DBG_HEX(tList6.usListChar); } break; default: NO_DBG_HEX(usOpCode); break; } if (iInfoLen <= 0) { iInfoLen = iGet8InfoLength(iFodo + iFodoOff, aucGrpprl); fail(iInfoLen <= 0); } iFodoOff += iInfoLen; } if (pStyle->usListIndex == 2047) { /* Old style list */ pStyle->usStartAt = (USHORT)tList6.ulStartAt; pStyle->usListChar = tList6.usListChar; pStyle->ucNFC = tList6.ucNFC; } else { /* New style list */ pList = pGetListInfo(pStyle->usListIndex, pStyle->ucListLevel); if (pList != NULL) { pStyle->bNoRestart = pList->bNoRestart; fail(pList->ulStartAt > (ULONG)USHRT_MAX); pStyle->usStartAt = (USHORT)pList->ulStartAt; pStyle->usListChar = pList->usListChar; pStyle->ucNFC = pList->ucNFC; if (pStyle->sLeftIndent <= 0) { pStyle->sLeftIndent = pList->sLeftIndent; } } } } /* end of vGet8StyleInfo */
/* * vSet2SummaryInfo - set summary information from a WinWord 1/2 file */ void vSet2SummaryInfo(FILE *pFile, int iWordVersion, const UCHAR *aucHeader) { UCHAR *aucBuffer; ULONG ulBeginSumdInfo, ulBeginDocpInfo, ulTmp; size_t tSumdInfoLen, tDocpInfoLen, tLen, tCounter, tStart; TRACE_MSG("vSet2SummaryInfo"); fail(pFile == NULL || aucHeader == NULL); fail(iWordVersion != 1 && iWordVersion != 2); /* First check the header */ usLid = usGetWord(0x06, aucHeader); /* Language IDentification */ DBG_HEX(usLid); if (usLid < 999 && iWordVersion == 1) { switch (usLid) { case 1: usLid = 0x0409; break; /* American English */ case 2: usLid = 0x0c0c; break; /* Canadian French */ case 31: usLid = 0x0413; break; /* Dutch */ case 33: usLid = 0x040c; break; /* French */ case 34: usLid = 0x040a; break; /* Spanish */ case 36: usLid = 0x040e; break; /* Hungarian */ case 39: usLid = 0x0410; break; /* Italian */ case 44: usLid = 0x0809; break; /* British English */ case 45: usLid = 0x0406; break; /* Danish */ case 46: usLid = 0x041f; break; /* Swedish */ case 47: usLid = 0x0414; break; /* Norwegian */ case 48: usLid = 0x0415; break; /* Polish */ case 49: usLid = 0x0407; break; /* German */ case 351: usLid = 0x0816; break; /* Portuguese */ case 358: usLid = 0x040b; break; /* Finnish */ default: DBG_DEC(usLid); DBG_FIXME(); usLid = 0x0409; /* American English */ break; } } if (iWordVersion != 2) { /* Unknown where to find the associated strings */ return; } /* Second check the associated strings */ ulBeginSumdInfo = ulGetLong(0x118, aucHeader); /* fcSttbfAssoc */ DBG_HEX(ulBeginSumdInfo); tSumdInfoLen = (size_t)usGetWord(0x11c, aucHeader); /* cbSttbfAssoc */ DBG_DEC(tSumdInfoLen); if (tSumdInfoLen == 0) { /* There is no summary information */ return; } aucBuffer = xmalloc(tSumdInfoLen); if (!bReadBytes(aucBuffer, tSumdInfoLen, ulBeginSumdInfo, pFile)) { aucBuffer = xfree(aucBuffer); return; } NO_DBG_PRINT_BLOCK(aucBuffer, tSumdInfoLen); tLen = (size_t)ucGetByte(0, aucBuffer); DBG_DEC_C(tSumdInfoLen != tLen, tSumdInfoLen); DBG_DEC_C(tSumdInfoLen != tLen, tLen); tStart = 1; for (tCounter = 0; tCounter < 17; tCounter++) { if (tStart >= tSumdInfoLen) { break; } tLen = (size_t)ucGetByte(tStart, aucBuffer); if (tLen != 0) { NO_DBG_DEC(tCounter); NO_DBG_STRN(aucBuffer + tStart + 1, tLen); switch (tCounter) { case 3: szTitle = xmalloc(tLen + 1); strncpy(szTitle, (char *)aucBuffer + tStart + 1, tLen); szTitle[tLen] = '\0'; break; case 4: szSubject = xmalloc(tLen + 1); strncpy(szSubject, (char *)aucBuffer + tStart + 1, tLen); szSubject[tLen] = '\0'; break; case 7: szAuthor = xmalloc(tLen + 1); strncpy(szAuthor, (char *)aucBuffer + tStart + 1, tLen); szAuthor[tLen] = '\0'; break; default: break; } } tStart += tLen + 1; } aucBuffer = xfree(aucBuffer); /* Third check the document properties */ ulBeginDocpInfo = ulGetLong(0x112, aucHeader); /* fcDop */ DBG_HEX(ulBeginDocpInfo); tDocpInfoLen = (size_t)usGetWord(0x116, aucHeader); /* cbDop */ DBG_DEC(tDocpInfoLen); if (tDocpInfoLen < 12) { return; } aucBuffer = xmalloc(tDocpInfoLen); if (!bReadBytes(aucBuffer, tDocpInfoLen, ulBeginDocpInfo, pFile)) { aucBuffer = xfree(aucBuffer); return; } ulTmp = ulGetLong(0x14, aucBuffer); /* dttmCreated */ tCreateDtm = tConvertDTTM(ulTmp); ulTmp = ulGetLong(0x18, aucBuffer); /* dttmRevised */ tLastSaveDtm = tConvertDTTM(ulTmp); aucBuffer = xfree(aucBuffer); } /* end of vSet2SummaryInfo */
/* * Build the lists with Character Information for Word 6/7 files */ void vGet6ChrInfo(FILE *pFile, ULONG ulStartBlock, const ULONG *aulBBD, size_t tBBDLen, const UCHAR *aucHeader) { font_block_type tFont; picture_block_type tPicture; USHORT *ausCharPage; UCHAR *aucBuffer; ULONG ulFileOffset, ulCharPos, ulBeginCharInfo; size_t tCharInfoLen, tOffset, tSize, tLenOld, tLen, tCharPageNum; size_t tIndex, tIndex2, tRun; int iFodo, iLen; USHORT usCharFirstPage, usCount, usIstd; UCHAR aucFpage[BIG_BLOCK_SIZE]; fail(pFile == NULL || aucHeader == NULL); fail(ulStartBlock > MAX_BLOCKNUMBER && ulStartBlock != END_OF_CHAIN); fail(aulBBD == NULL); ulBeginCharInfo = ulGetLong(0xb8, aucHeader); /* fcPlcfbteChpx */ NO_DBG_HEX(lBeginCharInfo); tCharInfoLen = (size_t)ulGetLong(0xbc, aucHeader); /* lcbPlcfbteChpx */ NO_DBG_DEC(tCharInfoLen); if (tCharInfoLen < 4) { DBG_DEC(tCharInfoLen); return; } aucBuffer = xmalloc(tCharInfoLen); if (!bReadBuffer(pFile, ulStartBlock, aulBBD, tBBDLen, BIG_BLOCK_SIZE, aucBuffer, ulBeginCharInfo, tCharInfoLen)) { aucBuffer = xfree(aucBuffer); return; } tLen = (tCharInfoLen - 4) / 6; ausCharPage = xcalloc(tLen, sizeof(USHORT)); for (tIndex = 0, tOffset = (tLen + 1) * 4; tIndex < tLen; tIndex++, tOffset += 2) { ausCharPage[tIndex] = usGetWord(tOffset, aucBuffer); NO_DBG_DEC(ausCharPage[tIndex]); } DBG_HEX(ulGetLong(0, aucBuffer)); aucBuffer = xfree(aucBuffer); tCharPageNum = (size_t)usGetWord(0x18e, aucHeader); /* cpnBteChp */ DBG_DEC(tCharPageNum); if (tLen < tCharPageNum) { /* Replace CharPage by a longer version */ tLenOld = tLen; usCharFirstPage = usGetWord(0x18a, aucHeader); /* pnChrFirst */ DBG_DEC(usCharFirstPage); tLen += tCharPageNum - 1; tSize = tLen * sizeof(USHORT); ausCharPage = xrealloc(ausCharPage, tSize); /* Add new values */ usCount = usCharFirstPage + 1; for (tIndex = tLenOld; tIndex < tLen; tIndex++) { ausCharPage[tIndex] = usCount; NO_DBG_DEC(ausCharPage[tIndex]); usCount++; } } for (tIndex = 0; tIndex < tLen; tIndex++) { if (!bReadBuffer(pFile, ulStartBlock, aulBBD, tBBDLen, BIG_BLOCK_SIZE, aucFpage, (ULONG)ausCharPage[tIndex] * BIG_BLOCK_SIZE, BIG_BLOCK_SIZE)) { break; } tRun = (size_t)ucGetByte(0x1ff, aucFpage); NO_DBG_DEC(tRun); for (tIndex2 = 0; tIndex2 < tRun; tIndex2++) { ulCharPos = ulGetLong(tIndex2 * 4, aucFpage); ulFileOffset = ulCharPos2FileOffset(ulCharPos); iFodo = 2 * (int)ucGetByte( (tRun + 1) * 4 + tIndex2, aucFpage); iLen = (int)ucGetByte(iFodo, aucFpage); /* usIstd = usGetIstd(ulFileOffset); vFillFontFromStylesheet(usIstd, &tFont); if (iFodo != 0) { vGet6FontInfo(iFodo, usIstd, aucFpage + 1, iLen - 1, &tFont); } tFont.ulFileOffset = ulFileOffset; vAdd2FontInfoList(&tFont); if (iFodo <= 0) { continue; } (void)memset(&tPicture, 0, sizeof(tPicture)); if (bGet6PicInfo(iFodo, aucFpage + 1, iLen - 1, &tPicture)) { tPicture.ulFileOffset = ulFileOffset; tPicture.ulFileOffsetPicture = ulDataPos2FileOffset( tPicture.ulPictureOffset); vAdd2PictInfoList(&tPicture); } */ } } ausCharPage = xfree(ausCharPage); } /* end of vGet6ChrInfo */