#include "HWPDocInfo.h" #include "HWPElements/HWPRecordBinData.h" #include "HWPElements/HWPRecordDocumentProperties.h" #include "HWPElements/HWPRecordIDMaping.h" #include "HWPElements/HWPRecordFaceName.h" #include "HWPElements/HWPRecordBorderFill.h" #include "HWPElements/HWPRecordCharShape.h" #include "HWPElements/HWPRecordBullet.h" #include "HWPElements/HWPRecordNumbering.h" #include "HWPElements/HWPRecordParaShape.h" #include "HWPElements/HWPRecordStyle.h" #include "HWPElements/HwpRecordTabDef.h" #include "Common/NodeNames.h" namespace HWP { ECompatDoc GetCompatDoc(int nValue) { switch(static_cast(nValue)) { case ECompatDoc::HWP: return ECompatDoc::HWP; case ECompatDoc::OLD_HWP: return ECompatDoc::OLD_HWP; case ECompatDoc::MS_WORD: return ECompatDoc::MS_WORD; default: return ECompatDoc::UNKNOWN; } } CHWPDocInfo::CHWPDocInfo(EHanType eHanType) : m_eHanType(eHanType), m_eCompatibleDoc(ECompatDoc::HWP) {} CHWPDocInfo::CHWPDocInfo(CHWPXFile* pHWPXFile) : m_eHanType(EHanType::HWPX), m_pParentHWPX(pHWPXFile), m_eCompatibleDoc(ECompatDoc::UNKNOWN) {} CHWPDocInfo::CHWPDocInfo(CHWPFile* pHWPFile) : m_eHanType(EHanType::HWP), m_pParentHWP(pHWPFile), m_eCompatibleDoc(ECompatDoc::HWP) {} CHWPDocInfo::CHWPDocInfo(CHWPMLFile* pHWPMLFile) : m_eHanType(EHanType::HWPML), m_pParentHWPML(pHWPMLFile), m_eCompatibleDoc(ECompatDoc::UNKNOWN) {} CHWPDocInfo::~CHWPDocInfo() { #define REMOVE_LIST_DATA(array) \ for (CHWPRecord* pRecord : array) \ { \ if (nullptr != pRecord) \ delete pRecord; \ } \ array.clear() \ REMOVE_LIST_DATA(m_arRecords); REMOVE_LIST_DATA(m_arFaseNames); REMOVE_LIST_DATA(m_arBorderFills); REMOVE_LIST_DATA(m_arCharShapes); REMOVE_LIST_DATA(m_arNumberings); REMOVE_LIST_DATA(m_arBullets); REMOVE_LIST_DATA(m_arParaShapes); REMOVE_LIST_DATA(m_arStyles); REMOVE_LIST_DATA(m_arTabDefs); for (const std::pair& oBinData : m_mBinDatas) { if (nullptr != oBinData.second) delete oBinData.second; } m_mBinDatas.clear(); } bool CHWPDocInfo::Parse(CHWPStream& oBuffer, int nVersion) { int nHeader, nTagNum, nLevel, nSize; while (oBuffer.CanRead()) { oBuffer.ReadInt(nHeader); nTagNum = nHeader & 0x3FF; // 10 bits (0 - 9 bit) nLevel = (nHeader & 0xFFC00) >> 10; // 10 bits (10-19 bit) nSize = (nHeader & 0xFFF00000) >> 20; // 12 bits (20-31 bit) if (0xFFF == nSize) { //TODO:: buf[off+7]<<24&0xFF000000 | buf[off+6]<<16&0xFF0000 | buf[off+5]<<8&0xFF00 | buf[off+4]&0xFF; oBuffer.ReadInt(nSize); } CHWPRecord *pRecord = nullptr; EHWPTag eTag = GetTagFromNum(nTagNum); #define CREATE_AND_ADD_RECORD(type_record, array) \ pRecord = new type_record(*this, nTagNum, nLevel, nSize, oBuffer, 0, nVersion); \ if (nullptr != pRecord) \ array.push_back(pRecord) oBuffer.SavePosition(); switch (eTag) { case HWPTAG_DOCUMENT_PROPERTIES: { CREATE_AND_ADD_RECORD(CHWPRecordDocumentProperties, m_arRecords); break; } case HWPTAG_ID_MAPPINGS: { CREATE_AND_ADD_RECORD(CHWPRecordIDMaping, m_arRecords); break; } case HWPTAG_BIN_DATA: { CHWPRecordBinData *pBindData = new CHWPRecordBinData(*this, nTagNum, nLevel, nSize, oBuffer, 0, nVersion); if (nullptr != pBindData) m_mBinDatas.insert(std::make_pair(pBindData->GetItemID(), pBindData)); break; } case HWPTAG_FACE_NAME: { CREATE_AND_ADD_RECORD(CHWPRecordFaceName, m_arFaseNames); break; } case HWPTAG_BORDER_FILL: { CREATE_AND_ADD_RECORD(CHWPRecordBorderFill, m_arBorderFills); break; } case HWPTAG_HWP_CHAR_SHAPE: { CREATE_AND_ADD_RECORD(CHWPRecordCharShape, m_arCharShapes); break; } case HWPTAG_TAB_DEF: { CREATE_AND_ADD_RECORD(CHwpRecordTabDef, m_arTabDefs); break; } case HWPTAG_NUMBERING: { CREATE_AND_ADD_RECORD(CHWPRecordNumbering, m_arNumberings); break; } case HWPTAG_BULLET: { CREATE_AND_ADD_RECORD(CHWPRecordBullet, m_arBullets); break; } case HWPTAG_PARA_SHAPE: { CREATE_AND_ADD_RECORD(CHWPRecordParaShape, m_arParaShapes); break; } case HWPTAG_STYLE: { CREATE_AND_ADD_RECORD(CHWPRecordStyle, m_arStyles); break; } case HWPTAG_COMPATIBLE_DOCUMENT: { int nCompatDoc; oBuffer.ReadInt(nCompatDoc); m_eCompatibleDoc = GetCompatDoc(nCompatDoc); break; } case HWPTAG_LAYOUT_COMPATIBILITY: case HWPTAG_DOC_DATA: case HWPTAG_DISTRIBUTE_DOC_DATA: case HWPTAG_TRACKCHANGE: case HWPTAG_MEMO_SHAPE: case HWPTAG_FORBIDDEN_HWP_CHAR: case HWPTAG_TRACK_CHANGE: case HWPTAG_TRACK_CHANGE_AUTHOR: break; default: {} } oBuffer.Skip(nSize - oBuffer.GetDistanceToLastPos(true)); } return true; } bool CHWPDocInfo::ParseHWPX(CXMLReader& oReader) { WHILE_READ_NEXT_NODE_WITH_NAME(oReader) { if ("hh:beginNum" == sNodeName) m_arRecords.push_back(new CHWPRecordDocumentProperties(*this, oReader)); else if ("hh:refList" == sNodeName) ReadRefList(oReader); } END_WHILE return true; } bool CHWPDocInfo::ParseHWPML(CXMLReader &oReader) { WHILE_READ_NEXT_NODE_WITH_NAME(oReader) { if ("MAPPINGTABLE" == sNodeName) { WHILE_READ_NEXT_NODE_WITH_DEPTH_AND_NAME(oReader, Mapping) { if ("BINDATALIST" == sNodeMappingName) { CHWPRecordBinData *pRecordBinData = nullptr; WHILE_READ_NEXT_NODE_WITH_DEPTH_ONE_NAME(oReader, BinData, "BINITEM") pRecordBinData = new CHWPRecordBinData(oReader, EHanType::HWPML); m_mBinDatas.insert(std::make_pair(pRecordBinData->GetItemID(), (HWP::CHWPRecord*)pRecordBinData)); END_WHILE } else ReadRefListElement(oReader, EHanType::HWPML); } END_WHILE } } END_WHILE return true; } bool CHWPDocInfo::ReadRefList(CXMLReader& oReader) { WHILE_READ_NEXT_NODE(oReader) ReadRefListElement(oReader, EHanType::HWPX); END_WHILE return true; } bool CHWPDocInfo::ReadRefListElement(CXMLReader &oReader, HWP::EHanType eType) { const std::string sNodeName{oReader.GetName()}; if (GetNodeName(ENode::FaceNameList, eType) == sNodeName) { WHILE_READ_NEXT_NODE_WITH_DEPTH_ONE_NAME(oReader, FontFace, GetNodeName(ENode::FontFace, eType)) WHILE_READ_NEXT_NODE_WITH_DEPTH_ONE_NAME(oReader, Font, GetNodeName(ENode::Font, eType)) m_arFaseNames.push_back(new CHWPRecordFaceName(*this, oReader, eType)); END_WHILE END_WHILE } else if (GetNodeName(ENode::BorderFillList, eType) == sNodeName) { WHILE_READ_NEXT_NODE_WITH_DEPTH_ONE_NAME(oReader, BorderFill, GetNodeName(ENode::BorderFill, eType)) m_arBorderFills.push_back(new CHWPRecordBorderFill(*this, oReader, eType)); END_WHILE } else if (GetNodeName(ENode::CharShapeList, eType) == sNodeName) { WHILE_READ_NEXT_NODE_WITH_DEPTH_ONE_NAME(oReader, CharPr, GetNodeName(ENode::CharShape, eType)) m_arCharShapes.push_back(new CHWPRecordCharShape(*this, oReader, eType)); END_WHILE } else if (GetNodeName(ENode::TabDefList, eType) == sNodeName) { WHILE_READ_NEXT_NODE_WITH_DEPTH_ONE_NAME(oReader, TabPr, GetNodeName(ENode::TabDef, eType)) m_arTabDefs.push_back(new CHwpRecordTabDef(*this, oReader, eType)); END_WHILE } else if (GetNodeName(ENode::NumberingList, eType) == sNodeName) { WHILE_READ_NEXT_NODE_WITH_DEPTH_ONE_NAME(oReader, Numbering, GetNodeName(ENode::Numbering, eType)) m_arNumberings.push_back(new CHWPRecordNumbering(*this, oReader, eType)); END_WHILE } else if (GetNodeName(ENode::BulletList, eType) == sNodeName) { WHILE_READ_NEXT_NODE_WITH_DEPTH(oReader, Bullet) m_arBullets.push_back(new CHWPRecordBullet(*this, oReader, eType)); END_WHILE } else if (GetNodeName(ENode::ParaShapeList, eType) == sNodeName) { WHILE_READ_NEXT_NODE_WITH_DEPTH_ONE_NAME(oReader, ParaPr, GetNodeName(ENode::ParaShape, eType)) m_arParaShapes.push_back(new CHWPRecordParaShape(*this, oReader, eType)); END_WHILE } else if (GetNodeName(ENode::StyleList, eType) == sNodeName) { WHILE_READ_NEXT_NODE_WITH_DEPTH_ONE_NAME(oReader, Style, GetNodeName(ENode::Style, eType)) m_arStyles.push_back(new CHWPRecordStyle(*this, oReader, eType)); END_WHILE } return true; } bool CHWPDocInfo::ReadContentHpf(CXMLReader& oReader) { CHWPRecordBinData *pRecordBinData = nullptr; WHILE_READ_NEXT_NODE_WITH_ONE_NAME(oReader, "opf:manifest") { WHILE_READ_NEXT_NODE_WITH_DEPTH_ONE_NAME(oReader, Item, "opf:item") { pRecordBinData = new CHWPRecordBinData(oReader, EHanType::HWPX); m_mBinDatas.insert(std::make_pair(pRecordBinData->GetItemID(), (HWP::CHWPRecord*)pRecordBinData)); } END_WHILE } END_WHILE return true; } #define GET_RECORD(array_records, index) \ if (array_records.size() <= index || index < 0) \ return nullptr; \ return array_records[index] const CHWPRecord* CHWPDocInfo::GetRecord(int nIndex) const { GET_RECORD(m_arRecords, nIndex); } const CHWPRecord* CHWPDocInfo::GetFaceName(int nIndex) const { GET_RECORD(m_arFaseNames, nIndex); } const CHWPRecord* CHWPDocInfo::GetBorderFill(int nIndex) const { GET_RECORD(m_arBorderFills, nIndex - 1); } const CHWPRecord* CHWPDocInfo::GetCharShape(int nIndex) const { GET_RECORD(m_arCharShapes, nIndex); } const CHWPRecord* CHWPDocInfo::GetNumbering(int nIndex) const { GET_RECORD(m_arNumberings, nIndex); } const CHWPRecord* CHWPDocInfo::GetBullet(int nIndex) const { GET_RECORD(m_arBullets, nIndex - 1); } const CHWPRecord* CHWPDocInfo::GetParaShape(int nIndex) const { GET_RECORD(m_arParaShapes, nIndex); } const CHWPRecord* CHWPDocInfo::GetStyle(int nIndex) const { GET_RECORD(m_arStyles, nIndex); } const CHWPRecord* CHWPDocInfo::GetTabDef(int nIndex) const { GET_RECORD(m_arTabDefs, nIndex); } CHWPFile* CHWPDocInfo::GetParentHWP() { return m_pParentHWP; } const CHWPRecord* CHWPDocInfo::GetBinData(const HWP_STRING& sID) const { switch (m_eHanType) { case EHanType::HWP: case EHanType::HWPX: case EHanType::HWPML: { std::map::const_iterator itFound = m_mBinDatas.find(sID); if (m_mBinDatas.cend() != itFound) return itFound->second; } default: return nullptr; } } EHanType CHWPDocInfo::GetHanType() const { return m_eHanType; } ECompatDoc CHWPDocInfo::GetCompatibleDoc() const { return m_eCompatibleDoc; } }