/** * Destructor */ ODe_Style_MasterPage::~ODe_Style_MasterPage() { if (m_pHeaderContentTemp != NULL) { ODe_gsf_output_close(m_pHeaderContentTemp); } if (m_pHeaderEvenContentTemp != NULL) { ODe_gsf_output_close(m_pHeaderEvenContentTemp); } if (m_pFooterContentTemp != NULL) { ODe_gsf_output_close(m_pFooterContentTemp); } if (m_pFooterEvenContentTemp != NULL) { ODe_gsf_output_close(m_pFooterEvenContentTemp); } }
/** * Writes all pictures inside the Pictures subdirectory. */ bool ODe_PicturesWriter::writePictures(PD_Document* pDoc, GsfOutfile* pODT) { const char * szName; std::string mimeType; std::string extension; std::string fullName; const UT_ByteBuf * pByteBuf; GsfOutput* pImg; GsfOutput* pPicsDir = NULL; for (UT_uint32 k=0; (pDoc->enumDataItems(k, NULL, &szName, &pByteBuf, &mimeType)); k++) { // We must avoid saving RDF data as image if (!mimeType.empty() && (mimeType != "application/rdf+xml")) { if (pPicsDir == NULL) { // create Pictures directory pPicsDir = gsf_outfile_new_child(pODT, "Pictures", TRUE); } pDoc->getDataItemFileExtension(szName, extension, true); fullName = szName + extension; pImg = gsf_outfile_new_child(GSF_OUTFILE(pPicsDir), fullName.c_str(), FALSE); ODe_gsf_output_write(pImg, pByteBuf->getLength(), pByteBuf->getPointer(0)); ODe_gsf_output_close(pImg); } } if (pPicsDir != NULL) { ODe_gsf_output_close(pPicsDir); } return true; }
/** * Destructor */ ODe_DocumentData::~ODe_DocumentData() { UT_GenericVector<ODe_Style_MasterPage*>* pMasterPageVector; UT_uint32 count, i; pMasterPageVector = m_masterStyles.enumerate(); count = pMasterPageVector->getItemCount(); for (i=0; i<count; i++) { delete (*pMasterPageVector)[i]; } DELETEP(pMasterPageVector); if (m_pOfficeTextTemp != NULL) { ODe_gsf_output_close(m_pOfficeTextTemp); } }
/** * Convert the RDF contained in pDoc->getDocumenrRDF() to RDF/XML and * store that in manifest.rdf updating the pDoc so that a manifest * entry is created in META_INF by the manifest writing code. */ bool ODe_RDFWriter::writeRDF( PD_Document* pDoc, GsfOutfile* pODT, PD_RDFModelHandle additionalRDF ) { #ifndef WITH_REDLAND UT_UNUSED(pDoc); UT_UNUSED(pODT); UT_UNUSED(additionalRDF); return true; #else UT_DEBUGMSG(("writeRDF() \n")); GsfOutput* oss = gsf_outfile_new_child(GSF_OUTFILE(pODT), "manifest.rdf", FALSE); // // Convert the native RDF model into a redland one // PD_DocumentRDFHandle rdf = pDoc->getDocumentRDF(); std::list< PD_RDFModelHandle > ml; ml.push_back( rdf ); ml.push_back( additionalRDF ); std::string rdfxml = toRDFXML( ml ); ODe_gsf_output_write (oss, rdfxml.size(), (const guint8*)rdfxml.data() ); ODe_gsf_output_close(oss); // // add an entry that the manifest writing code will pick up // { UT_ByteBufPtr pByteBuf(new UT_ByteBuf); std::string mime_type = "application/rdf+xml"; PD_DataItemHandle* ppHandle = NULL; if(!pDoc->createDataItem("manifest.rdf", 0, pByteBuf, mime_type, ppHandle)) { UT_DEBUGMSG(("writeRDF() setting up manifest entry failed!\n")); } // This is to test to new dnode manifest code. // pDoc->createDataItem( "some/many/directories/foo.xml", 0, &pByteBuf, // mime_type, ppHandle ); } UT_DEBUGMSG(("writeRDF() complete\n")); return true; #endif }
bool ODe_SettingsWriter::writeSettings(PD_Document* /*pDoc*/, GsfOutfile* oo) { GsfOutput* pSettings = gsf_outfile_new_child (oo, "settings.xml", FALSE); static const char * const contents [] = { "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", "<office:document-settings" " xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\"" " xmlns:xlink=\"http://www.w3.org/1999/xlink\"" " xmlns:config=\"urn:oasis:names:tc:opendocument:xmlns:config:1.0\"" " xmlns:ooo=\"http://openoffice.org/2004/office\" office:version=\"1.1\">\n", "</office:document-settings>" }; ODe_writeToStream (pSettings, contents, G_N_ELEMENTS(contents)); ODe_gsf_output_close(pSettings); return true; }
ODe_AuxiliaryData::~ODe_AuxiliaryData() { if (m_pTOCContents) ODe_gsf_output_close(m_pTOCContents); }
/** * This writes out our AbiWord file as an OpenOffice * compound document */ UT_Error IE_Exp_OpenDocument::_writeDocument(void) { ODe_DocumentData docData(getDoc()); ODe_AuxiliaryData auxData; ODe_AbiDocListener* pAbiDocListener = NULL; ODe_AbiDocListenerImpl* pAbiDocListenerImpl = NULL; UT_return_val_if_fail (getFp(), UT_ERROR); PD_DocumentRDFHandle rdf = getDoc()->getDocumentRDF(); auxData.m_additionalRDF = rdf->createScratchModel(); const std::string & prop = getProperty ("uncompressed"); if (!prop.empty() && UT_parseBool (prop.c_str (), false)) { m_odt = GSF_OUTFILE(g_object_ref(G_OBJECT(getFp()))); } else { GError* error = NULL; m_odt = GSF_OUTFILE (gsf_outfile_zip_new (getFp(), &error)); if (error) { UT_DEBUGMSG(("Error writing odt file: %s\n", error->message)); UT_ASSERT_HARMLESS(UT_SHOULD_NOT_HAPPEN); } } UT_return_val_if_fail(m_odt, UT_ERROR); // Needed to ensure that all *printf writes numbers correctly, // like "45.56mm" instead of "45,56mm". UT_LocaleTransactor numericLocale (LC_NUMERIC, "C"); { GsfOutput * mimetype = gsf_outfile_new_child_full (m_odt, "mimetype", FALSE, "compression-level", 0, (void*)0); if (!mimetype) { ODe_gsf_output_close(GSF_OUTPUT(m_odt)); return UT_ERROR; } ODe_gsf_output_write(mimetype, 39 /*39 == strlen("application/vnd.oasis.opendocument.text")*/, (const guint8 *)"application/vnd.oasis.opendocument.text"); ODe_gsf_output_close(mimetype); } if (!ODe_MetaDataWriter::writeMetaData(getDoc(), m_odt)) { ODe_gsf_output_close(GSF_OUTPUT(m_odt)); return UT_ERROR; } if (!ODe_SettingsWriter::writeSettings(getDoc(), m_odt)) { ODe_gsf_output_close(GSF_OUTPUT(m_odt)); return UT_ERROR; } if (!ODe_PicturesWriter::writePictures(getDoc(), m_odt)) { ODe_gsf_output_close(GSF_OUTPUT(m_odt)); return UT_ERROR; } if (!ODe_ManifestWriter::writeManifest(getDoc(), m_odt)) { ODe_gsf_output_close(GSF_OUTPUT(m_odt)); return UT_ERROR; } // Gather all paragraph style names used by heading paragraphs // (ie. all paragraph styles that are used to build up TOCs). pAbiDocListenerImpl = new ODe_HeadingSearcher_Listener(docData.m_styles, auxData); pAbiDocListener = new ODe_AbiDocListener(getDoc(), pAbiDocListenerImpl, false); if (!getDoc()->tellListener(static_cast<PL_Listener *>(pAbiDocListener))) { ODe_gsf_output_close(GSF_OUTPUT(m_odt)); return UT_ERROR; } pAbiDocListener->finished(); DELETEP(pAbiDocListener); DELETEP(pAbiDocListenerImpl); // Now that we have all paragraph styles that build up the TOCs in the // document (if any), we can build up the TOC bodies. We do this because // OpenOffice.org requires the TOC bodies to be present and filled // when initially opening the document. Without it, it will show // an empty TOC until the user regenerates it, which is not that pretty. // Annoyingly we have to build up the TOC ourselves during export, as // it doesn't exist within AbiWord's PieceTable. Until that changes, this // is the best we can do. if (auxData.m_pTOCContents) { pAbiDocListenerImpl = new ODe_TOC_Listener(auxData); pAbiDocListener = new ODe_AbiDocListener(getDoc(), pAbiDocListenerImpl, false); if (!getDoc()->tellListener(static_cast<PL_Listener *>(pAbiDocListener))) { ODe_gsf_output_close(GSF_OUTPUT(m_odt)); return UT_ERROR; } pAbiDocListener->finished(); DELETEP(pAbiDocListener); DELETEP(pAbiDocListenerImpl); } // Gather document content and styles if (!docData.doPreListeningWork()) { ODe_gsf_output_close(GSF_OUTPUT(m_odt)); return UT_ERROR; } pAbiDocListenerImpl = new ODe_Main_Listener(docData, auxData); pAbiDocListener = new ODe_AbiDocListener(getDoc(), pAbiDocListenerImpl, false); if (!getDoc()->tellListener(static_cast<PL_Listener *>(pAbiDocListener))) { ODe_gsf_output_close(GSF_OUTPUT(m_odt)); return UT_ERROR; } pAbiDocListener->finished(); DELETEP(pAbiDocListener); DELETEP(pAbiDocListenerImpl); if (!docData.doPostListeningWork()) { ODe_gsf_output_close(GSF_OUTPUT(m_odt)); return UT_ERROR; } // Write RDF. if (!ODe_RDFWriter::writeRDF(getDoc(), m_odt, auxData.m_additionalRDF )) { ODe_gsf_output_close(GSF_OUTPUT(m_odt)); return UT_ERROR; } // Write content and styles if (!docData.writeStylesXML(m_odt)) { ODe_gsf_output_close(GSF_OUTPUT(m_odt)); return UT_ERROR; } if (!docData.writeContentXML(m_odt)) { ODe_gsf_output_close(GSF_OUTPUT(m_odt)); return UT_ERROR; } ODe_gsf_output_close(GSF_OUTPUT(m_odt)); return UT_OK; }
bool ODe_MetaDataWriter::writeMetaData(PD_Document* pDoc, GsfOutfile* oo) { GsfOutput* meta = gsf_outfile_new_child (oo, "meta.xml", FALSE); static const UT_UTF8String preamble = UT_UTF8String("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<office:document-meta" " xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\"" " xmlns:xlink=\"http://www.w3.org/1999/xlink\"" " xmlns:dc=\"http://purl.org/dc/elements/1.1/\"" " xmlns:meta=\"urn:oasis:names:tc:opendocument:xmlns:meta:1.0\"" " xmlns:ooo=\"http://openoffice.org/2004/office\"" " office:version=\"1.1\">\n" "<office:meta>\n" "<meta:generator>AbiWord/") + PACKAGE_VERSION + " (" + PLATFORM + ", " + TOOLKIT + ")</meta:generator>\n"; static const char * const postamble [] = { "</office:meta>\n", "</office:document-meta>\n" }; ODe_writeUTF8String(meta, preamble); UT_UTF8String meta_val, val; #define WRITE_METADATA_ELEMENT(abiwordKey, odElementName) if (pDoc->getMetaDataProp(abiwordKey, meta_val) && meta_val.size()) { \ meta_val.escapeXML(); \ val = UT_UTF8String_sprintf("<%s>%s</%s>\n", odElementName, meta_val.utf8_str(), odElementName); \ ODe_writeUTF8String (meta, val); \ } WRITE_METADATA_ELEMENT(PD_META_KEY_TITLE, "dc:title"); WRITE_METADATA_ELEMENT(PD_META_KEY_DESCRIPTION, "dc:description"); WRITE_METADATA_ELEMENT(PD_META_KEY_SUBJECT, "dc:subject"); //Each keyword needs to be exported individually: UT_UTF8String keywords; if (pDoc->getMetaDataProp (PD_META_KEY_KEYWORDS, keywords) && keywords.size()) { UT_UTF8String buf = ""; UT_UCS4String keyword = keywords.utf8_str(); for(UT_uint32 i = 0;i < keyword.length(); i++) { if(keyword[i] != ' ') { buf += keyword[i]; } else { if(buf.empty()) //only blank space encountered continue; buf.escapeXML(); val = UT_UTF8String_sprintf("<meta:keyword>%s</meta:keyword>\n", buf.utf8_str()); ODe_writeUTF8String(meta, val); buf.clear(); } } if(buf.length()) //there may only be one keyword (i.e. no spaces encountered) { buf.escapeXML(); val = UT_UTF8String_sprintf("<meta:keyword>%s</meta:keyword>\n", buf.utf8_str()); ODe_writeUTF8String(meta, val); } } // Should have a PD_META_KEY_INITIAL_CREATOR macro for this one, but only // if it gets implemented on the document properties dialog. WRITE_METADATA_ELEMENT("meta:initial-creator", "meta:initial-creator"); WRITE_METADATA_ELEMENT(PD_META_KEY_CREATOR, "dc:creator"); WRITE_METADATA_ELEMENT("meta:printed-by", "meta:printed-by"); // ATTENTION: I'm assuming that dc.date is used by AbiWord as // the document creation date & time. WRITE_METADATA_ELEMENT(PD_META_KEY_DATE, "meta:creation-date"); // Note that, for the OpenDocument standard, dc.date // is the last modification date & time. WRITE_METADATA_ELEMENT(PD_META_KEY_DATE_LAST_CHANGED, "dc:date"); WRITE_METADATA_ELEMENT("meta:print-date", "meta:print-date"); WRITE_METADATA_ELEMENT(PD_META_KEY_LANGUAGE, "dc:language"); #undef WRITE_METADATA_ELEMENT ODe_writeToStream(meta, postamble, G_N_ELEMENTS(postamble)); ODe_gsf_output_close(meta); return true; }
bool ODe_DocumentData::writeContentXML(GsfOutfile* pOdt) { GsfOutput* pContentStream; pContentStream = gsf_outfile_new_child (pOdt, "content.xml", FALSE); const char * const preamble [] = { "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", "\n", "<office:document-content" " xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\"" " xmlns:style=\"urn:oasis:names:tc:opendocument:xmlns:style:1.0\"" " xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\"" " xmlns:table=\"urn:oasis:names:tc:opendocument:xmlns:table:1.0\"" " xmlns:draw=\"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0\"" " xmlns:fo=\"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0\"" " xmlns:xlink=\"http://www.w3.org/1999/xlink\"" " xmlns:dc=\"http://purl.org/dc/elements/1.1/\"" " xmlns:meta=\"urn:oasis:names:tc:opendocument:xmlns:meta:1.0\"" " xmlns:number=\"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0\"" " xmlns:svg=\"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0\"" " xmlns:chart=\"urn:oasis:names:tc:opendocument:xmlns:chart:1.0\"" " xmlns:dr3d=\"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0\"" " xmlns:math=\"http://www.w3.org/1998/Math/MathML\"" " xmlns:form=\"urn:oasis:names:tc:opendocument:xmlns:form:1.0\"" " xmlns:script=\"urn:oasis:names:tc:opendocument:xmlns:script:1.0\"" " xmlns:ooo=\"http://openoffice.org/2004/office\"" " xmlns:ooow=\"http://openoffice.org/2004/writer\"" " xmlns:oooc=\"http://openoffice.org/2004/calc\"" " xmlns:dom=\"http://www.w3.org/2001/xml-events\"" " xmlns:xforms=\"http://www.w3.org/2002/xforms\"" " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" " xmlns:delta=\"http://www.deltaxml.com/ns/track-changes/delta-namespace\"" " xmlns:ac=\"http://www.deltaxml.com/ns/track-changes/attribute-change-namespace\"" " xmlns:split=\"http://www.deltaxml.com/ns/track-changes/split-namespace\"" " office:version=\"1.1\">\n"}; ODe_writeToStream(pContentStream, preamble, G_N_ELEMENTS(preamble)); m_contentXMLFontDecls.write( pContentStream ); m_contentAutoStyles.write( pContentStream ); m_contentRevisions.write( pContentStream, m_pAbiDoc ); ODe_writeUTF8String(pContentStream, " <office:body>\n" " <office:text>\n"); // FIXME: here OR the one above? // m_contentRevisions.write( pContentStream, m_pAbiDoc ); ODe_gsf_output_write(pContentStream, gsf_output_size (m_pOfficeTextTemp), gsf_output_memory_get_bytes (GSF_OUTPUT_MEMORY (m_pOfficeTextTemp))); ODe_gsf_output_close (m_pOfficeTextTemp); m_pOfficeTextTemp = NULL; ODe_writeUTF8String(pContentStream, " </office:text>\n" " </office:body>\n" "</office:document-content>"); ODe_gsf_output_close(pContentStream); return true; }
bool ODe_DocumentData::writeStylesXML(GsfOutfile* pOdt) const { GsfOutput* pStylesStream; UT_GenericVector<ODe_Style_MasterPage*>* pMasterPageVector; bool ok; UT_uint32 count, i; pStylesStream = gsf_outfile_new_child (pOdt, "styles.xml", FALSE); const char * const preamble [] = { "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", "\n", "<office:document-styles" " xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\"" " xmlns:style=\"urn:oasis:names:tc:opendocument:xmlns:style:1.0\"" " xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\"" " xmlns:table=\"urn:oasis:names:tc:opendocument:xmlns:table:1.0\"" " xmlns:draw=\"urn:oasis:names:tc:opendocument:xmlns:drawing:1.0\"" " xmlns:fo=\"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0\"" " xmlns:xlink=\"http://www.w3.org/1999/xlink\"" " xmlns:dc=\"http://purl.org/dc/elements/1.1/\"" " xmlns:meta=\"urn:oasis:names:tc:opendocument:xmlns:meta:1.0\"" " xmlns:number=\"urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0\"" " xmlns:svg=\"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0\"" " xmlns:chart=\"urn:oasis:names:tc:opendocument:xmlns:chart:1.0\"" " xmlns:dr3d=\"urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0\"" " xmlns:math=\"http://www.w3.org/1998/Math/MathML\"" " xmlns:form=\"urn:oasis:names:tc:opendocument:xmlns:form:1.0\"" " xmlns:script=\"urn:oasis:names:tc:opendocument:xmlns:script:1.0\"" " xmlns:ooo=\"http://openoffice.org/2004/office\"" " xmlns:ooow=\"http://openoffice.org/2004/writer\"" " xmlns:oooc=\"http://openoffice.org/2004/calc\"" " xmlns:dom=\"http://www.w3.org/2001/xml-events\"" " office:version=\"1.1\">\n"}; ODe_writeToStream(pStylesStream, preamble, G_N_ELEMENTS(preamble)); m_stylesXMLFontDecls.write(pStylesStream); m_styles.write(pStylesStream); m_stylesAutoStyles.write(pStylesStream); ODe_writeUTF8String(pStylesStream, " <office:master-styles>\n"); pMasterPageVector = m_masterStyles.enumerate(); count = pMasterPageVector->getItemCount(); for (i=0; i<count; i++) { ok = (*pMasterPageVector)[i]->write(pStylesStream); if (!ok) { return false; } } ODe_writeUTF8String(pStylesStream, " </office:master-styles>\n"); ODe_writeUTF8String(pStylesStream, "</office:document-styles>"); ODe_gsf_output_close(pStylesStream); return true; }
bool ODe_ManifestWriter::writeManifest(PD_Document* pDoc, GsfOutfile* pODT) { // Create META-INF directory GsfOutput* meta_inf = gsf_outfile_new_child(pODT, "META-INF", TRUE); GsfOutput* manifest = gsf_outfile_new_child( GSF_OUTFILE(meta_inf), "manifest.xml", FALSE); std::string name; static const char * const preamble [] = { "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", "<!DOCTYPE manifest:manifest PUBLIC \"-//OpenOffice.org//DTD Manifest 1.0//EN\" \"Manifest.dtd\">\n", "<manifest:manifest xmlns:manifest=\"urn:oasis:names:tc:opendocument:xmlns:manifest:1.0\">\n", " <manifest:file-entry manifest:media-type=\"application/vnd.oasis.opendocument.text\" manifest:full-path=\"/\"/>\n", " <manifest:file-entry manifest:media-type=\"text/xml\" manifest:full-path=\"content.xml\"/>\n", " <manifest:file-entry manifest:media-type=\"text/xml\" manifest:full-path=\"styles.xml\"/>\n", " <manifest:file-entry manifest:media-type=\"text/xml\" manifest:full-path=\"meta.xml\"/>\n", " <manifest:file-entry manifest:media-type=\"text/xml\" manifest:full-path=\"settings.xml\"/>\n" }; static const char * const postamble [] = { "</manifest:manifest>\n" }; typedef std::set< std::string > absolutePathMimeTypes_t; static absolutePathMimeTypes_t absolutePathMimeTypes; if( absolutePathMimeTypes.empty() ) { absolutePathMimeTypes.insert("application/rdf+xml"); } ODe_writeToStream (manifest, preamble, G_N_ELEMENTS(preamble)); const char* szName; std::string mimeType; const UT_ByteBuf* pByteBuf; std::set< std::string > pathsAlreadyWritten; for (UT_uint32 k = 0; (pDoc->enumDataItems(k, NULL, &szName, &pByteBuf, &mimeType)); k++) { if (!mimeType.empty()) { ensureDirectoryManifest( pDoc, manifest, szName, pathsAlreadyWritten ); std::string automaticPathPrefix = "Pictures/"; if( absolutePathMimeTypes.count(mimeType) ) automaticPathPrefix = ""; name = UT_std_string_sprintf( " <manifest:file-entry manifest:media-type=\"%s\" manifest:full-path=\"%s%s\"/>\n", mimeType.c_str(), automaticPathPrefix.c_str(), szName); ODe_gsf_output_write (manifest, name.size(), reinterpret_cast<const guint8 *>(name.c_str())); } } ODe_writeToStream (manifest, postamble, G_N_ELEMENTS(postamble)); ODe_gsf_output_close(manifest); ODe_gsf_output_close(meta_inf); return true; }