📄 prop8.c
字号:
/* * prop8.c * Copyright (C) 1998-2005 A.J. van Os; Released under GNU GPL * * Description: * Read the property information from a MS Word 8, 9,10 or 11 file * * Word 8 is better known as Word 97 or as Word 98 for Mac * Word 9 is better known as Word 2000 or as Word 2001 for Mac * Word 10 is better known as Word 2002 or as Word XP * Word 11 is better known as Word 2003 */#include <stdlib.h>#include <string.h>#include "antiword.h"#define DEFAULT_LISTCHAR 0x002e /* A full stop *//* * iGet8InfoLength - the length of the information for Word 8/9/10/11 files */static intiGet8InfoLength(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 *//* * aucFillInfoBuffer - fill the information buffer * * Returns the information buffer when successful, otherwise NULL */static UCHAR *aucFillInfoBuffer(FILE *pFile, const pps_type *pTable, const ULONG *aulBBD, size_t tBBDLen, const ULONG *aulSBD, size_t tSBDLen, ULONG ulBeginInfo, size_t tInfoLen){ const ULONG *aulBlockDepot; UCHAR *aucBuffer; size_t tBlockDepotLen, tBlockSize; fail(pFile == NULL || pTable == NULL); fail(aulBBD == NULL || aulSBD == NULL); fail(tInfoLen == 0); NO_DBG_DEC(pTable->ulSB); NO_DBG_HEX(pTable->ulSize); if (pTable->ulSize == 0) { DBG_MSG("No information"); return NULL; } if (pTable->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; } aucBuffer = xmalloc(tInfoLen); if (!bReadBuffer(pFile, pTable->ulSB, aulBlockDepot, tBlockDepotLen, tBlockSize, aucBuffer, ulBeginInfo, tInfoLen)) { aucBuffer = xfree(aucBuffer); return NULL; } return aucBuffer;} /* end of aucFillInfoBuffer *//* * Build the lists with Document Property Information for Word 8/9/10/11 files */voidvGet8DopInfo(FILE *pFile, const pps_type *pTable, const ULONG *aulBBD, size_t tBBDLen, const ULONG *aulSBD, size_t tSBDLen, const UCHAR *aucHeader){ document_block_type tDocument; UCHAR *aucBuffer; ULONG ulBeginDocpInfo, ulTmp; size_t tDocpInfoLen; USHORT usTmp; fail(pFile == NULL || pTable == NULL || aucHeader == NULL); fail(aulBBD == NULL || aulSBD == NULL); ulBeginDocpInfo = ulGetLong(0x192, aucHeader); /* fcDop */ NO_DBG_HEX(ulBeginSectInfo); tDocpInfoLen = (size_t)ulGetLong(0x196, aucHeader); /* lcbDop */ NO_DBG_DEC(tSectInfoLen); if (tDocpInfoLen < 28) { DBG_MSG("No Document information"); return; } aucBuffer = aucFillInfoBuffer(pFile, pTable, aulBBD, tBBDLen, aulSBD, tSBDLen, ulBeginDocpInfo, tDocpInfoLen); if (aucBuffer == NULL) { return; } usTmp = usGetWord(0x00, aucBuffer); tDocument.ucHdrFtrSpecification = (UCHAR)(usTmp >> 8); /* grpfIhdt */ tDocument.usDefaultTabWidth = usGetWord(0x0a, aucBuffer); /* dxaTab */ ulTmp = ulGetLong(0x14, aucBuffer); /* dttmCreated */ tDocument.tCreateDate = tConvertDTTM(ulTmp); ulTmp = ulGetLong(0x18, aucBuffer); /* dttmRevised */ tDocument.tRevisedDate = tConvertDTTM(ulTmp); vCreateDocumentInfoList(&tDocument); aucBuffer = xfree(aucBuffer);} /* end of vGet8DopInfo *//* * Fill the section information block with information * from a Word 8/9/10/11 file. */static voidvGet8SectionInfo(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 Word 8/9/10/11 files */voidvGet8SepInfo(FILE *pFile, const pps_info_type *pPPS, const ULONG *aulBBD, size_t tBBDLen, const ULONG *aulSBD, size_t tSBDLen, 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[2]; fail(pFile == NULL || pPPS == NULL || aucHeader == NULL); fail(aulBBD == NULL || aulSBD == NULL); ulBeginOfText = ulGetLong(0x18, aucHeader); /* fcMin */ NO_DBG_HEX(ulBeginOfText); ulBeginSectInfo = ulGetLong(0xca, aucHeader); /* fcPlcfsed */ NO_DBG_HEX(ulBeginSectInfo); tSectInfoLen = (size_t)ulGetLong(0xce, aucHeader); /* lcbPlcfsed */ NO_DBG_DEC(tSectInfoLen); if (tSectInfoLen < 4) { DBG_DEC(tSectInfoLen); return; } aucBuffer = aucFillInfoBuffer(pFile, &pPPS->tTable, aulBBD, tBBDLen, aulSBD, tSBDLen, ulBeginSectInfo, tSectInfoLen); if (aucBuffer == NULL) { return; } NO_DBG_PRINT_BLOCK(aucBuffer, tSectInfoLen); /* Read the Section Descriptors */ tLen = (tSectInfoLen - 4) / 16; /* 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 += 12) { 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 (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB, aulBBD, tBBDLen, BIG_BLOCK_SIZE, aucTmp, aulSectPage[tIndex], 2)) { continue; } tBytes = 2 + (size_t)usGetWord(0, aucTmp); NO_DBG_DEC(tBytes); /* Read the bytes */ aucFpage = xmalloc(tBytes); if (!bReadBuffer(pFile, pPPS->tWordDocument.ulSB, aulBBD, tBBDLen, BIG_BLOCK_SIZE, aucFpage, aulSectPage[tIndex], tBytes)) { aucFpage = xfree(aucFpage); continue; } NO_DBG_PRINT_BLOCK(aucFpage, tBytes); /* Process the bytes */ vGetDefaultSection(&tSection); vGet8SectionInfo(aucFpage + 2, tBytes - 2, &tSection); vAdd2SectionInfoList(&tSection, aulCharPos[tIndex]); aucFpage = xfree(aucFpage); } aulCharPos = xfree(aulCharPos); aulSectPage = xfree(aulSectPage);} /* end of vGet8SepInfo *//* * Build the list with Header/Footer Information for Word 8/9/10/11 files */voidvGet8HdrFtrInfo(FILE *pFile, const pps_type *pTable, const ULONG *aulBBD, size_t tBBDLen, const ULONG *aulSBD, size_t tSBDLen, const UCHAR *aucHeader){ ULONG *aulCharPos; UCHAR *aucBuffer; ULONG ulHdrFtrOffset, ulBeginHdrFtrInfo; size_t tHdrFtrInfoLen, tIndex, tOffset, tLen; fail(pFile == NULL || pTable == NULL || aucHeader == NULL); fail(aulBBD == NULL || aulSBD == NULL); ulBeginHdrFtrInfo = ulGetLong(0xf2, aucHeader); /* fcPlcfhdd */ NO_DBG_HEX(ulBeginHdrFtrInfo); tHdrFtrInfoLen = (size_t)ulGetLong(0xf6, aucHeader); /* lcbPlcfhdd */ NO_DBG_DEC(tHdrFtrInfoLen); if (tHdrFtrInfoLen < 8) { DBG_DEC_C(tHdrFtrInfoLen != 0, tHdrFtrInfoLen); return; } aucBuffer = aucFillInfoBuffer(pFile, pTable, aulBBD, tBBDLen, aulSBD, tSBDLen, ulBeginHdrFtrInfo, tHdrFtrInfoLen); if (aucBuffer == NULL) { return; } NO_DBG_PRINT_BLOCK(aucBuffer, tHdrFtrInfoLen); tLen = tHdrFtrInfoLen / 4 - 1; DBG_DEC_C(tLen % 12 != 1 && tLen % 12 != 7, tLen); /* Save the header/footer offsets */ aulCharPos = xcalloc(tLen, sizeof(ULONG)); for (tIndex = 0, tOffset = 0; tIndex < tLen; tIndex++, tOffset += 4) { ulHdrFtrOffset = ulGetLong(tOffset, aucBuffer); NO_DBG_HEX(ulHdrFtrOffset); aulCharPos[tIndex] = ulHdrFtrOffset2CharPos(ulHdrFtrOffset); NO_DBG_HEX(aulCharPos[tIndex]); } vCreat8HdrFtrInfoList(aulCharPos, tLen); /* Clean up and leave */ aulCharPos = xfree(aulCharPos); aucBuffer = xfree(aucBuffer);} /* end of vGet8HdrFtrInfo *//* * Translate the rowinfo to a member of the row_info enumeration */row_info_enumeGet8RowInfo(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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -