/* -*- mode: C++; tab-width: 4; c-basic-offset: 4; -*- */ /* AbiSource * * Copyright (C) 2007 Philippe Milot * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. */ // Class definition include #include // Internal includes #include #include #include #include #include // AbiWord includes #include #include #include #include // External includes #include #include #include OXMLi_PackageManager* OXMLi_PackageManager::s_pInst = NULL; OXMLi_PackageManager* OXMLi_PackageManager::getNewInstance() { OXMLi_PackageManager::destroyInstance(); return OXMLi_PackageManager::getInstance(); } OXMLi_PackageManager* OXMLi_PackageManager::getInstance() { if (s_pInst == NULL) { try { s_pInst = new OXMLi_PackageManager(); } catch(...) { UT_DEBUGMSG(("Could not allocate memory!\n")); return NULL; } } return s_pInst; } void OXMLi_PackageManager::destroyInstance() { DELETEP(s_pInst); } OXMLi_PackageManager::OXMLi_PackageManager() : m_pPkg(NULL), m_pDocPart(NULL) { } OXMLi_PackageManager::~OXMLi_PackageManager() { if (m_pPkg) { g_object_unref (G_OBJECT(m_pPkg)); } if (m_pDocPart) { g_object_unref (G_OBJECT(m_pDocPart)); } m_parsedParts.clear(); } void OXMLi_PackageManager::setContainer(GsfInfile * pPkg) { if (m_pPkg) { g_object_unref (G_OBJECT(m_pPkg)); } if (m_pDocPart) { g_object_unref (G_OBJECT(m_pDocPart)); } m_pPkg = pPkg; } UT_Error OXMLi_PackageManager::parseDocumentStream() { OXMLi_StreamListener listener; listener.setupStates(DOCUMENT_PART); return _parseStream( _getDocumentStream(), &listener); } UT_Error OXMLi_PackageManager::parseDocumentHdrFtr( const char * id ) { GsfInput * doc = _getDocumentStream(); UT_return_val_if_fail(doc != NULL, UT_ERROR); OXMLi_StreamListener listener; listener.setupStates(HEADER_PART, id); //Doesn't matter whether it's header or footer return parseChildById(doc, id, &listener); } UT_Error OXMLi_PackageManager::parseDocumentStyles() { GsfInput * doc = _getDocumentStream(); UT_return_val_if_fail(doc != NULL, UT_ERROR); OXMLi_StreamListener listener; listener.setupStates(STYLES_PART); return parseChildByType(doc, STYLES_PART, &listener); } UT_Error OXMLi_PackageManager::parseDocumentTheme() { GsfInput * doc = _getDocumentStream(); UT_return_val_if_fail(doc != NULL, UT_ERROR); OXMLi_StreamListener listener; listener.setupStates(THEME_PART); UT_Error err = parseChildByType(doc, THEME_PART, &listener); //themes are optional in .docx files if(err != UT_OK){ UT_DEBUGMSG(("FRT: OpenXML Theme Part is not found\n")); } return UT_OK; } UT_Error OXMLi_PackageManager::parseDocumentSettings() { GsfInput * doc = _getDocumentStream(); UT_return_val_if_fail(doc != NULL, UT_ERROR); OXMLi_StreamListener listener; listener.setupStates(DOCSETTINGS_PART); return parseChildByType(doc, DOCSETTINGS_PART, &listener); } UT_Error OXMLi_PackageManager::parseDocumentNumbering() { GsfInput * doc = _getDocumentStream(); UT_return_val_if_fail(doc != NULL, UT_ERROR); OXMLi_StreamListener listener; listener.setupStates(NUMBERING_PART); return parseChildByType(doc, NUMBERING_PART, &listener); } UT_Error OXMLi_PackageManager::parseDocumentFootnotes() { GsfInput * doc = _getDocumentStream(); UT_return_val_if_fail(doc != NULL, UT_ERROR); OXMLi_StreamListener listener; listener.setupStates(FOOTNOTES_PART); return parseChildByType(doc, FOOTNOTES_PART, &listener); } UT_Error OXMLi_PackageManager::parseDocumentEndnotes() { GsfInput * doc = _getDocumentStream(); UT_return_val_if_fail(doc != NULL, UT_ERROR); OXMLi_StreamListener listener; listener.setupStates(ENDNOTES_PART); return parseChildByType(doc, ENDNOTES_PART, &listener); } GsfInput* OXMLi_PackageManager::getChildById( GsfInput * parent, const char * id ) { return gsf_open_pkg_get_rel_by_id(parent, id); } GsfInput* OXMLi_PackageManager::getChildByType( GsfInput * parent, OXML_PartType type ) { const char * fulltype; fulltype = _getFullType(type); UT_return_val_if_fail(fulltype != NULL, NULL); return gsf_open_pkg_get_rel_by_type(parent, fulltype); } UT_Error OXMLi_PackageManager::parseChildById( GsfInput * parent, const char * id, OXMLi_StreamListener * pListener) { GsfInput * pInput = getChildById(parent, id); UT_return_val_if_fail(pInput != NULL, UT_ERROR); return _parseStream( pInput, pListener); } UT_Error OXMLi_PackageManager::parseChildByType( GsfInput * parent, OXML_PartType type, OXMLi_StreamListener * pListener) { GsfInput * pInput = getChildByType(parent, type); if(!pInput) return UT_ERROR; return _parseStream( pInput, pListener); } const char * OXMLi_PackageManager::_getFullType( OXML_PartType type ) { //There's probably a better way to do this... const char * ret; switch (type) { case ALTERNATEFORMAT_PART: ret = ALTERNATEFORMAT_REL_TYPE; break; case COMMENTS_PART: ret = COMMENTS_REL_TYPE; break; case DOCSETTINGS_PART: ret = DOCSETTINGS_REL_TYPE; break; case DOCUMENT_PART: ret = DOCUMENT_REL_TYPE; break; case ENDNOTES_PART: ret = ENDNOTES_REL_TYPE; break; case FONTTABLE_PART: ret = FONTTABLE_REL_TYPE; break; case FOOTER_PART: ret = FOOTER_REL_TYPE; break; case FOOTNOTES_PART: ret = FOOTNOTES_REL_TYPE; break; case GLOSSARY_PART: ret = GLOSSARY_REL_TYPE; break; case HEADER_PART: ret = HEADER_REL_TYPE; break; case NUMBERING_PART: ret = NUMBERING_REL_TYPE; break; case STYLES_PART: ret = STYLES_REL_TYPE; break; case WEBSETTINGS_PART: ret = WEBSETTINGS_REL_TYPE; break; case IMAGE_PART: ret = IMAGE_REL_TYPE; break; case THEME_PART: ret = THEME_REL_TYPE; break; default: ret = NULL; } return ret; } GsfInput * OXMLi_PackageManager::_getDocumentStream() { UT_return_val_if_fail(m_pPkg != NULL, NULL); if (m_pDocPart == NULL) m_pDocPart = getChildByType ( GSF_INPUT (m_pPkg), DOCUMENT_PART ); return m_pDocPart; } UT_Error OXMLi_PackageManager::_parseStream( GsfInput * stream, OXMLi_StreamListener * pListener) { UT_return_val_if_fail(stream != NULL && pListener != NULL , UT_ERROR); //First, we check if this stream has already been parsed before std::string part_name = gsf_input_name(stream); //TODO: determine if part names are truly unique std::map::iterator it; it = m_parsedParts.find(part_name); if (it != m_parsedParts.end() && it->second) { //this stream has already been parsed successfully return UT_OK; } UT_Error ret = UT_OK; guint8 const *data = NULL; const char * cdata = NULL; size_t len = 0; UT_XML reader; reader.setListener(pListener); if (gsf_input_size (stream) > 0) { len = gsf_input_remaining (stream); if (len > 0) { data = gsf_input_read (stream, len, NULL); if (NULL == data) { g_object_unref (G_OBJECT (stream)); return UT_ERROR; } cdata = (const char *)data; ret = reader.parse (cdata, len); } } //There are two error codes to check here. if (ret == UT_OK && pListener->getStatus() == UT_OK) m_parsedParts[part_name] = true; //We prioritize the one from UT_XML when returning. return ret == UT_OK ? pListener->getStatus() : ret; } /** * Parses the image stream and returns the image data */ UT_ByteBuf* OXMLi_PackageManager::parseImageStream(const char * id) { GsfInput * parent = _getDocumentStream(); GsfInput * stream = getChildById(parent, id); //First, we check if this stream has already been parsed before std::string part_name = gsf_input_name(stream); //TODO: determine if part names are truly unique std::map::iterator it; it = m_parsedParts.find(part_name); if (it != m_parsedParts.end() && it->second) { //this stream has already been parsed successfully return NULL; } UT_ByteBuf* buffer = new UT_ByteBuf(); buffer->insertFromInput(0, stream); g_object_unref (G_OBJECT (stream)); m_parsedParts[part_name] = true; return buffer; } /** * This function is needed for external targets. Ex: hyperlinks, bookmarks. */ std::string OXMLi_PackageManager::getPartName(const char * id) { GsfInput * parent = _getDocumentStream(); const char* target = gsf_open_pkg_rel_get_target(gsf_open_pkg_lookup_rel_by_id(parent, id)); return std::string(target); }