diff options
Diffstat (limited to 'writerperfect/source')
48 files changed, 6680 insertions, 0 deletions
diff --git a/writerperfect/source/filter/DocumentCollector.cxx b/writerperfect/source/filter/DocumentCollector.cxx new file mode 100644 index 000000000000..22605664cc65 --- /dev/null +++ b/writerperfect/source/filter/DocumentCollector.cxx @@ -0,0 +1,1312 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* DocumentCollector: Collects sections and runs of text from a + * file (and styles to go along with them) and writes them + * to a Writer target document + * + * Copyright (C) 2002-2004 William Lachance (william.lachance@sympatico.ca) + * Copyright (C) 2003-2004 Net Integration Technologies (http://www.net-itech.com) + * Copyright (C) 2004 Fridrich Strba (fridrich.strba@bluewin.ch) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#if defined _MSC_VER +#pragma warning( push, 1 ) +#endif +#include <libwpd/libwpd.h> +#if defined _MSC_VER +#pragma warning( pop ) +#endif +#include <string.h> // for strcmp + +#include "DocumentCollector.hxx" +#include "DocumentElement.hxx" +#include "DocumentHandler.hxx" +#include "InternalHandler.hxx" +#include "TextRunStyle.hxx" +#include "FontStyle.hxx" +#include "ListStyle.hxx" +#include "PageSpan.hxx" +#include "SectionStyle.hxx" +#include "TableStyle.hxx" +#include "FilterInternal.hxx" +#include "WriterProperties.hxx" +#include "OdgExporter.hxx" + +_WriterDocumentState::_WriterDocumentState() : + mbFirstElement(true), + mbFirstParagraphInPageSpan(true), + mbInFakeSection(false), + mbListElementOpenedAtCurrentLevel(false), + mbTableCellOpened(false), + mbHeaderRow(false), + mbInNote(false), + mbInTextBox(false), + mbInFrame(false) +{ +} + +_WriterListState::_WriterListState() : + mpCurrentListStyle(NULL), + miCurrentListLevel(0), + miLastListLevel(0), + miLastListNumber(0), + mbListContinueNumbering(false), + mbListElementParagraphOpened(false), + mbListElementOpened() +{ +} + +DocumentCollector::DocumentCollector(WPXInputStream *pInput, DocumentHandlerInterface *pHandler) : + mpInput(pInput), + mpHandler(pHandler), + mbUsed(false), + mWriterDocumentStates(), + mWriterListStates(), + mfSectionSpaceAfter(0.0f), + miNumListStyles(0), + mpCurrentContentElements(&mBodyElements), + mpCurrentPageSpan(NULL), + miNumPageStyles(0), + miObjectNumber(0), + mbIsFlatXML(true), + mpPassword(NULL) +{ + mWriterDocumentStates.push(WriterDocumentState()); + mWriterListStates.push(WriterListState()); +} + +DocumentCollector::~DocumentCollector() +{ +} + +bool DocumentCollector::filter() +{ + // The contract for DocumentCollector is that it will only be used once after it is + // instantiated + if (mbUsed) + return false; + + mbUsed = true; + + // parse & write + // WLACH_REFACTORING: Remove these args.. + if (!parseSourceDocument(*mpInput)) + return false; + if (!_writeTargetDocument(mpHandler)) + return false; + + // clean up the mess we made + WRITER_DEBUG_MSG(("WriterWordPerfect: Cleaning up our mess..\n")); + + WRITER_DEBUG_MSG(("Destroying the body elements\n")); + for (std::vector<DocumentElement *>::iterator iterBody = mBodyElements.begin(); iterBody != mBodyElements.end(); ++iterBody) { + delete (*iterBody); + (*iterBody) = NULL; + } + + WRITER_DEBUG_MSG(("Destroying the styles elements\n")); + for (std::vector<DocumentElement *>::iterator iterStyles = mStylesElements.begin(); iterStyles != mStylesElements.end(); ++iterStyles) { + delete (*iterStyles); + (*iterStyles) = NULL; // we may pass over the same element again (in the case of headers/footers spanning multiple pages) + // so make sure we don't do a double del + } + + WRITER_DEBUG_MSG(("Destroying the rest of the styles elements\n")); + for (std::map<WPXString, ParagraphStyle *, ltstr>::iterator iterTextStyle = mTextStyleHash.begin(); iterTextStyle != mTextStyleHash.end(); ++iterTextStyle) { + delete (iterTextStyle->second); + } + for (std::map<WPXString, SpanStyle *, ltstr>::iterator iterSpanStyle = mSpanStyleHash.begin(); iterSpanStyle != mSpanStyleHash.end(); ++iterSpanStyle) { + delete(iterSpanStyle->second); + } + + for (std::map<WPXString, FontStyle *, ltstr>::iterator iterFont = mFontHash.begin(); iterFont != mFontHash.end(); ++iterFont) { + delete(iterFont->second); + } + + for (std::vector<ListStyle *>::iterator iterListStyles = mListStyles.begin(); iterListStyles != mListStyles.end(); ++iterListStyles) { + delete (*iterListStyles); + } + for (std::vector<SectionStyle *>::iterator iterSectionStyles = mSectionStyles.begin(); iterSectionStyles != mSectionStyles.end(); ++iterSectionStyles) { + delete (*iterSectionStyles); + } + for (std::vector<TableStyle *>::iterator iterTableStyles = mTableStyles.begin(); iterTableStyles != mTableStyles.end(); ++iterTableStyles) { + delete((*iterTableStyles)); + } + + for (std::vector<PageSpan *>::iterator iterPageSpans = mPageSpans.begin(); iterPageSpans != mPageSpans.end(); ++iterPageSpans) { + delete (*iterPageSpans); + } + for (std::vector<DocumentElement *>::iterator iterFrameStyles = mFrameStyles.begin(); iterFrameStyles != mFrameStyles.end(); ++iterFrameStyles) { + delete(*iterFrameStyles); + } + for (std::vector<DocumentElement *>::iterator iterFrameAutomaticStyles = mFrameAutomaticStyles.begin(); + iterFrameAutomaticStyles != mFrameAutomaticStyles.end(); ++iterFrameAutomaticStyles) { + delete(*iterFrameAutomaticStyles); + } + for (std::vector<DocumentElement *>::iterator iterMetaData = mMetaData.begin(); iterMetaData != mMetaData.end(); ++iterMetaData) { + delete(*iterMetaData); + } + + return true; +} + +void DocumentCollector::_writeDefaultStyles(DocumentHandlerInterface *pHandler) +{ + TagOpenElement("office:styles").write(pHandler); + + TagOpenElement defaultParagraphStyleOpenElement("style:default-style"); + defaultParagraphStyleOpenElement.addAttribute("style:family", "paragraph"); + defaultParagraphStyleOpenElement.write(pHandler); + + TagOpenElement defaultParagraphStylePropertiesOpenElement("style:paragraph-properties"); + defaultParagraphStylePropertiesOpenElement.addAttribute("style:tab-stop-distance", "0.5in"); + defaultParagraphStylePropertiesOpenElement.write(pHandler); + TagCloseElement defaultParagraphStylePropertiesCloseElement("style:paragraph-properties"); + defaultParagraphStylePropertiesCloseElement.write(pHandler); + + pHandler->endElement("style:default-style"); + + TagOpenElement defaultTableRowStyleOpenElement("style:default-style"); + defaultTableRowStyleOpenElement.addAttribute("style:family", "table-row"); + defaultTableRowStyleOpenElement.write(pHandler); + + TagOpenElement defaultTableRowPropertiesOpenElement("style:table-row-properties"); + defaultTableRowPropertiesOpenElement.addAttribute("fo:keep-together", "auto"); + defaultTableRowPropertiesOpenElement.write(pHandler); + + pHandler->endElement("style:table-row-properties"); + pHandler->endElement("style:default-style"); + + TagOpenElement standardStyleOpenElement("style:style"); + standardStyleOpenElement.addAttribute("style:name", "Standard"); + standardStyleOpenElement.addAttribute("style:family", "paragraph"); + standardStyleOpenElement.addAttribute("style:class", "text"); + standardStyleOpenElement.write(pHandler); + + pHandler->endElement("style:style"); + + TagOpenElement textBodyStyleOpenElement("style:style"); + textBodyStyleOpenElement.addAttribute("style:name", "Text_Body"); + textBodyStyleOpenElement.addAttribute("style:display-name", "Text Body"); + textBodyStyleOpenElement.addAttribute("style:family", "paragraph"); + textBodyStyleOpenElement.addAttribute("style:parent-style-name", "Standard"); + textBodyStyleOpenElement.addAttribute("style:class", "text"); + textBodyStyleOpenElement.write(pHandler); + + pHandler->endElement("style:style"); + + TagOpenElement tableContentsStyleOpenElement("style:style"); + tableContentsStyleOpenElement.addAttribute("style:name", "Table_Contents"); + tableContentsStyleOpenElement.addAttribute("style:display-name", "Table Contents"); + tableContentsStyleOpenElement.addAttribute("style:family", "paragraph"); + tableContentsStyleOpenElement.addAttribute("style:parent-style-name", "Text_Body"); + tableContentsStyleOpenElement.addAttribute("style:class", "extra"); + tableContentsStyleOpenElement.write(pHandler); + + pHandler->endElement("style:style"); + + TagOpenElement tableHeadingStyleOpenElement("style:style"); + tableHeadingStyleOpenElement.addAttribute("style:name", "Table_Heading"); + tableHeadingStyleOpenElement.addAttribute("style:display-name", "Table Heading"); + tableHeadingStyleOpenElement.addAttribute("style:family", "paragraph"); + tableHeadingStyleOpenElement.addAttribute("style:parent-style-name", "Table_Contents"); + tableHeadingStyleOpenElement.addAttribute("style:class", "extra"); + tableHeadingStyleOpenElement.write(pHandler); + + pHandler->endElement("style:style"); + + for (std::vector<DocumentElement *>::const_iterator iter = mFrameStyles.begin(); + iter != mFrameStyles.end(); ++iter) + (*iter)->write(pHandler); + + pHandler->endElement("office:styles"); +} + +void DocumentCollector::_writeMasterPages(DocumentHandlerInterface *pHandler) +{ + TagOpenElement("office:master-styles").write(mpHandler); + int pageNumber = 1; + for (unsigned int i=0; i<mPageSpans.size(); i++) + { + bool bLastPage; + (i == (mPageSpans.size() - 1)) ? bLastPage = true : bLastPage = false; + mPageSpans[i]->writeMasterPages(pageNumber, i, bLastPage, pHandler); + pageNumber += mPageSpans[i]->getSpan(); + } + pHandler->endElement("office:master-styles"); +} + +void DocumentCollector::_writePageLayouts(DocumentHandlerInterface *pHandler) +{ + for (unsigned int i=0; i<mPageSpans.size(); i++) + { + mPageSpans[i]->writePageLayout(i, pHandler); + } +} + +bool DocumentCollector::_writeTargetDocument(DocumentHandlerInterface *pHandler) +{ + WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: Printing out the header stuff..\n")); + + WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: Start Document\n")); + mpHandler->startDocument(); + + WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: preamble\n")); + WPXPropertyList docContentPropList; + docContentPropList.insert("xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0"); + docContentPropList.insert("xmlns:meta", "urn:oasis:names:tc:opendocument:xmlns:meta:1.0"); + docContentPropList.insert("xmlns:dc", "http://purl.org/dc/elements/1.1/"); + docContentPropList.insert("xmlns:config", "urn:oasis:names:tc:opendocument:xmlns:config:1.0"); + docContentPropList.insert("xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0"); + docContentPropList.insert("xmlns:table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0"); + docContentPropList.insert("xmlns:draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"); + docContentPropList.insert("xmlns:fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"); + docContentPropList.insert("xmlns:xlink", "http://www.w3.org/1999/xlink"); + docContentPropList.insert("xmlns:number", "http://openoffice.org/2000/datastyle"); + docContentPropList.insert("xmlns:svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"); + docContentPropList.insert("xmlns:chart", "urn:oasis:names:tc:opendocument:xmlns:chart:1.0"); + docContentPropList.insert("xmlns:dr3d", "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"); + docContentPropList.insert("xmlns:math", "http://www.w3.org/1998/Math/MathML"); + docContentPropList.insert("xmlns:form", "urn:oasis:names:tc:opendocument:xmlns:form:1.0"); + docContentPropList.insert("xmlns:script", "urn:oasis:names:tc:opendocument:xmlns:script:1.0"); + docContentPropList.insert("xmlns:style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0"); + docContentPropList.insert("office:version", "1.0"); + docContentPropList.insert("office:mimetype", "application/vnd.oasis.opendocument.text"); + mpHandler->startElement("office:document", docContentPropList); + + // write out the metadata + TagOpenElement("office:meta").write(mpHandler); + for (std::vector<DocumentElement *>::const_iterator iterMetaData = mMetaData.begin(); iterMetaData != mMetaData.end(); ++iterMetaData) { + (*iterMetaData)->write(mpHandler); + } + mpHandler->endElement("office:meta"); + + // write out the font styles + TagOpenElement("office:font-face-decls").write(mpHandler); + for (std::map<WPXString, FontStyle *, ltstr>::iterator iterFont = mFontHash.begin(); iterFont != mFontHash.end(); ++iterFont) { + iterFont->second->write(mpHandler); + } + TagOpenElement symbolFontOpen("style:font-face"); + symbolFontOpen.addAttribute("style:name", "StarSymbol"); + symbolFontOpen.addAttribute("svg:font-family", "StarSymbol"); + symbolFontOpen.addAttribute("style:font-charset", "x-symbol"); + symbolFontOpen.write(mpHandler); + mpHandler->endElement("style:font-face"); + + mpHandler->endElement("office:font-face-decls"); + + WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: Writing out the styles..\n")); + + // write default styles + _writeDefaultStyles(mpHandler); + + TagOpenElement("office:automatic-styles").write(mpHandler); + + for (std::vector<DocumentElement *>::const_iterator iterFrameAutomaticStyles = mFrameAutomaticStyles.begin(); + iterFrameAutomaticStyles != mFrameAutomaticStyles.end(); ++iterFrameAutomaticStyles) + { + (*iterFrameAutomaticStyles)->write(pHandler); + } + + for (std::map<WPXString, ParagraphStyle *, ltstr>::const_iterator iterTextStyle = mTextStyleHash.begin(); + iterTextStyle != mTextStyleHash.end(); ++iterTextStyle) + { + // writing out the paragraph styles + if (strcmp((iterTextStyle->second)->getName().cstr(), "Standard")) + { + // don't write standard paragraph "no styles" style + (iterTextStyle->second)->write(pHandler); + } + } + + // span styles.. + for (std::map<WPXString, SpanStyle *, ltstr>::const_iterator iterSpanStyle = mSpanStyleHash.begin(); + iterSpanStyle != mSpanStyleHash.end(); ++iterSpanStyle) + { + (iterSpanStyle->second)->write(pHandler); + } + + // writing out the sections styles + for (std::vector<SectionStyle *>::const_iterator iterSectionStyles = mSectionStyles.begin(); iterSectionStyles != mSectionStyles.end(); ++iterSectionStyles) { + (*iterSectionStyles)->write(pHandler); + } + + // writing out the lists styles + for (std::vector<ListStyle *>::const_iterator iterListStyles = mListStyles.begin(); iterListStyles != mListStyles.end(); ++iterListStyles) { + (*iterListStyles)->write(pHandler); + } + + // writing out the table styles + for (std::vector<TableStyle *>::const_iterator iterTableStyles = mTableStyles.begin(); iterTableStyles != mTableStyles.end(); ++iterTableStyles) { + (*iterTableStyles)->write(pHandler); + } + + // writing out the page masters + _writePageLayouts(pHandler); + + + pHandler->endElement("office:automatic-styles"); + + _writeMasterPages(pHandler); + + WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: Writing out the document..\n")); + // writing out the document + TagOpenElement("office:body").write(mpHandler); + TagOpenElement("office:text").write(mpHandler); + + for (std::vector<DocumentElement *>::const_iterator iterBodyElements = mBodyElements.begin(); iterBodyElements != mBodyElements.end(); ++iterBodyElements) { + (*iterBodyElements)->write(pHandler); + } + WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: Finished writing all doc els..\n")); + + pHandler->endElement("office:text"); + pHandler->endElement("office:body"); + pHandler->endElement("office:document"); + + pHandler->endDocument(); + + return true; +} + + +WPXString propListToStyleKey(const WPXPropertyList & xPropList) +{ + WPXString sKey; + WPXPropertyList::Iter i(xPropList); + for (i.rewind(); i.next(); ) + { + WPXString sProp; + sProp.sprintf("[%s:%s]", i.key(), i()->getStr().cstr()); + sKey.append(sProp); + } + + return sKey; +} + +WPXString getParagraphStyleKey(const WPXPropertyList & xPropList, const WPXPropertyListVector & xTabStops) +{ + WPXString sKey = propListToStyleKey(xPropList); + + WPXString sTabStops; + sTabStops.sprintf("[num-tab-stops:%i]", xTabStops.count()); + WPXPropertyListVector::Iter i(xTabStops); + for (i.rewind(); i.next();) + { + sTabStops.append(propListToStyleKey(i())); + } + sKey.append(sTabStops); + + return sKey; +} + +// _allocateFontName: add a (potentially mapped) font style to the hash if it's not already there, do nothing otherwise +void DocumentCollector::_allocateFontName(const WPXString & sFontName) +{ + if (mFontHash.find(sFontName) == mFontHash.end()) + { + FontStyle *pFontStyle = new FontStyle(sFontName.cstr(), sFontName.cstr()); + mFontHash[sFontName] = pFontStyle; + } +} + +void DocumentCollector::setDocumentMetaData(const WPXPropertyList &propList) +{ + WPXPropertyList::Iter i(propList); + for (i.rewind(); i.next(); ) + { + // filter out libwpd elements + if (strncmp(i.key(), "libwpd", 6) != 0 && strncmp(i.key(), "dcterms", 7) != 0) + { + mMetaData.push_back(new TagOpenElement(i.key())); + WPXString sStringValue(i()->getStr(), true); + mMetaData.push_back(new CharDataElement(sStringValue.cstr())); + mMetaData.push_back(new TagCloseElement(i.key())); + } + } + +} + +void DocumentCollector::openPageSpan(const WPXPropertyList &propList) +{ + PageSpan *pPageSpan = new PageSpan(propList); + mPageSpans.push_back(pPageSpan); + mpCurrentPageSpan = pPageSpan; + miNumPageStyles++; + + mWriterDocumentStates.top().mbFirstParagraphInPageSpan = true; +} + +void DocumentCollector::openHeader(const WPXPropertyList &propList) +{ + std::vector<DocumentElement *> * pHeaderFooterContentElements = new std::vector<DocumentElement *>; + + if (propList["libwpd:occurence"]->getStr() == "even") + mpCurrentPageSpan->setHeaderLeftContent(pHeaderFooterContentElements); + else + mpCurrentPageSpan->setHeaderContent(pHeaderFooterContentElements); + + mpCurrentContentElements = pHeaderFooterContentElements; +} + +void DocumentCollector::closeHeader() +{ + mpCurrentContentElements = &mBodyElements; +} + +void DocumentCollector::openFooter(const WPXPropertyList &propList) +{ + std::vector<DocumentElement *> * pHeaderFooterContentElements = new std::vector<DocumentElement *>; + + if (propList["libwpd:occurence"]->getStr() == "even") + mpCurrentPageSpan->setFooterLeftContent(pHeaderFooterContentElements); + else + mpCurrentPageSpan->setFooterContent(pHeaderFooterContentElements); + + mpCurrentContentElements = pHeaderFooterContentElements; +} + +void DocumentCollector::closeFooter() +{ + mpCurrentContentElements = &mBodyElements; +} + +void DocumentCollector::openSection(const WPXPropertyList &propList, const WPXPropertyListVector &columns) +{ + int iNumColumns = columns.count(); + double fSectionMarginLeft = 0.0; + double fSectionMarginRight = 0.0; + if (propList["fo:margin-left"]) + fSectionMarginLeft = propList["fo:margin-left"]->getDouble(); + if (propList["fo:margin-right"]) + fSectionMarginRight = propList["fo:margin-right"]->getDouble(); + + if (iNumColumns > 1 || fSectionMarginLeft != 0 || fSectionMarginRight != 0) + { + if (propList["fo:margin-bottom"]) + mfSectionSpaceAfter = propList["fo:margin-bottom"]->getDouble(); + else if (propList["libwpd:margin-bottom"]) + mfSectionSpaceAfter = propList["libwpd:margin-bottom"]->getDouble(); + + WPXString sSectionName; + sSectionName.sprintf("Section%i", mSectionStyles.size()); + + SectionStyle *pSectionStyle = new SectionStyle(propList, columns, sSectionName.cstr()); + mSectionStyles.push_back(pSectionStyle); + + TagOpenElement *pSectionOpenElement = new TagOpenElement("text:section"); + pSectionOpenElement->addAttribute("text:style-name", pSectionStyle->getName()); + pSectionOpenElement->addAttribute("text:name", pSectionStyle->getName()); + mpCurrentContentElements->push_back(pSectionOpenElement); + } + else + mWriterDocumentStates.top().mbInFakeSection = true; +} + +void DocumentCollector::closeSection() +{ + if (!mWriterDocumentStates.top().mbInFakeSection) + mpCurrentContentElements->push_back(new TagCloseElement("text:section")); + else + mWriterDocumentStates.top().mbInFakeSection = false; + + mfSectionSpaceAfter = 0.0; +} + +void DocumentCollector::openParagraph(const WPXPropertyList &propList, const WPXPropertyListVector &tabStops) +{ + // FIXMENOW: What happens if we open a footnote inside a table? do we then inherit the footnote's style + // from "Table Contents" + + WPXPropertyList *pPersistPropList = new WPXPropertyList(propList); + ParagraphStyle *pStyle = NULL; + + if (mWriterDocumentStates.top().mbFirstElement && mpCurrentContentElements == &mBodyElements) + { + // we don't have to go through the fuss of determining if the paragraph style is + // unique in this case, because if we are the first document element, then we + // are singular. Neither do we have to determine what our parent style is-- we can't + // be inside a table in this case (the table would be the first document element + //in that case) + pPersistPropList->insert("style:parent-style-name", "Standard"); + WPXString sName; + sName.sprintf("FS"); + + WPXString sParagraphHashKey("P|FS"); + pPersistPropList->insert("style:master-page-name", "Page_Style_1"); + pStyle = new ParagraphStyle(pPersistPropList, tabStops, sName); + mTextStyleHash[sParagraphHashKey] = pStyle; + mWriterDocumentStates.top().mbFirstElement = false; + mWriterDocumentStates.top().mbFirstParagraphInPageSpan = false; + } + else + { + if (mWriterDocumentStates.top().mbFirstParagraphInPageSpan && mpCurrentContentElements == &mBodyElements) + { + WPXString sPageStyleName; + sPageStyleName.sprintf("Page_Style_%i", miNumPageStyles); + pPersistPropList->insert("style:master-page-name", sPageStyleName); + mWriterDocumentStates.top().mbFirstParagraphInPageSpan = false; + } + + if (mWriterDocumentStates.top().mbTableCellOpened) + { + if (mWriterDocumentStates.top().mbHeaderRow) + pPersistPropList->insert("style:parent-style-name", "Table_Heading"); + else + pPersistPropList->insert("style:parent-style-name", "Table_Contents"); + } + else + pPersistPropList->insert("style:parent-style-name", "Standard"); + + WPXString sKey = getParagraphStyleKey(*pPersistPropList, tabStops); + + if (mTextStyleHash.find(sKey) == mTextStyleHash.end()) + { + WPXString sName; + sName.sprintf("S%i", mTextStyleHash.size()); + + pStyle = new ParagraphStyle(pPersistPropList, tabStops, sName); + + mTextStyleHash[sKey] = pStyle; + } + else + { + pStyle = mTextStyleHash[sKey]; + delete pPersistPropList; + } + } + // create a document element corresponding to the paragraph, and append it to our list of document elements + TagOpenElement *pParagraphOpenElement = new TagOpenElement("text:p"); + pParagraphOpenElement->addAttribute("text:style-name", pStyle->getName()); + mpCurrentContentElements->push_back(pParagraphOpenElement); +} + +void DocumentCollector::closeParagraph() +{ + mpCurrentContentElements->push_back(new TagCloseElement("text:p")); +} + +void DocumentCollector::openSpan(const WPXPropertyList &propList) +{ + if (propList["style:font-name"]) + _allocateFontName(propList["style:font-name"]->getStr()); + WPXString sSpanHashKey = propListToStyleKey(propList); + WRITER_DEBUG_MSG(("WriterWordPerfect: Span Hash Key: %s\n", sSpanHashKey.cstr())); + + // Get the style + WPXString sName; + if (mSpanStyleHash.find(sSpanHashKey) == mSpanStyleHash.end()) + { + // allocate a new paragraph style + sName.sprintf("Span%i", mSpanStyleHash.size()); + SpanStyle *pStyle = new SpanStyle(sName.cstr(), propList); + + mSpanStyleHash[sSpanHashKey] = pStyle; + } + else + { + sName.sprintf("%s", mSpanStyleHash.find(sSpanHashKey)->second->getName().cstr()); + } + + // create a document element corresponding to the paragraph, and append it to our list of document elements + TagOpenElement *pSpanOpenElement = new TagOpenElement("text:span"); + pSpanOpenElement->addAttribute("text:style-name", sName.cstr()); + mpCurrentContentElements->push_back(pSpanOpenElement); +} + +void DocumentCollector::closeSpan() +{ + mpCurrentContentElements->push_back(new TagCloseElement("text:span")); +} + +void DocumentCollector::defineOrderedListLevel(const WPXPropertyList &propList) +{ + int id = 0; + if (propList["libwpd:id"]) + id = propList["libwpd:id"]->getInt(); + + OrderedListStyle *pOrderedListStyle = NULL; + if (mWriterListStates.top().mpCurrentListStyle && mWriterListStates.top().mpCurrentListStyle->getListID() == id) + pOrderedListStyle = static_cast<OrderedListStyle *>(mWriterListStates.top().mpCurrentListStyle); // FIXME: using a dynamic cast here causes oo to crash?! + + // this rather appalling conditional makes sure we only start a new list (rather than continue an old + // one) if: (1) we have no prior list OR (2) the prior list is actually definitively different + // from the list that is just being defined (listIDs differ) OR (3) we can tell that the user actually + // is starting a new list at level 1 (and only level 1) + if (pOrderedListStyle == NULL || pOrderedListStyle->getListID() != id || + (propList["libwpd:level"] && propList["libwpd:level"]->getInt()==1 && + (propList["text:start-value"] && propList["text:start-value"]->getInt() != (mWriterListStates.top().miLastListNumber+1)))) + { + WRITER_DEBUG_MSG(("Attempting to create a new ordered list style (listid: %i)\n", id)); + WPXString sName; + sName.sprintf("OL%i", miNumListStyles); + miNumListStyles++; + pOrderedListStyle = new OrderedListStyle(sName.cstr(), id); + mListStyles.push_back(pOrderedListStyle); + mWriterListStates.top().mpCurrentListStyle = pOrderedListStyle; + mWriterListStates.top().mbListContinueNumbering = false; + mWriterListStates.top().miLastListNumber = 0; + } + else + mWriterListStates.top().mbListContinueNumbering = true; + + // Iterate through ALL list styles with the same WordPerfect list id and define a level if it is not already defined + // This solves certain problems with lists that start and finish without reaching certain levels and then begin again + // and reach those levels. See gradguide0405_PC.wpd in the regression suite + for (std::vector<ListStyle *>::iterator iterOrderedListStyles = mListStyles.begin(); iterOrderedListStyles != mListStyles.end(); ++iterOrderedListStyles) + { + if ((* iterOrderedListStyles)->getListID() == id) + (* iterOrderedListStyles)->updateListLevel((propList["libwpd:level"]->getInt() - 1), propList); + } +} + +void DocumentCollector::defineUnorderedListLevel(const WPXPropertyList &propList) +{ + int id = 0; + if (propList["libwpd:id"]) + id = propList["libwpd:id"]->getInt(); + + UnorderedListStyle *pUnorderedListStyle = NULL; + if (mWriterListStates.top().mpCurrentListStyle && mWriterListStates.top().mpCurrentListStyle->getListID() == id) + pUnorderedListStyle = static_cast<UnorderedListStyle *>(mWriterListStates.top().mpCurrentListStyle); // FIXME: using a dynamic cast here causes oo to crash?! + + if (pUnorderedListStyle == NULL) { + WRITER_DEBUG_MSG(("Attempting to create a new unordered list style (listid: %i)\n", id)); + WPXString sName; + sName.sprintf("UL%i", miNumListStyles); + miNumListStyles++; + pUnorderedListStyle = new UnorderedListStyle(sName.cstr(), id); + mListStyles.push_back(pUnorderedListStyle); + mWriterListStates.top().mpCurrentListStyle = pUnorderedListStyle; + } + + // See comment in DocumentCollector::defineOrderedListLevel + for (std::vector<ListStyle *>::iterator iterUnorderedListStyles = mListStyles.begin(); iterUnorderedListStyles != mListStyles.end(); ++iterUnorderedListStyles) + { + if ((* iterUnorderedListStyles)->getListID() == id) + (* iterUnorderedListStyles)->updateListLevel((propList["libwpd:level"]->getInt() - 1), propList); + } +} + +void DocumentCollector::openOrderedListLevel(const WPXPropertyList & /* propList */) +{ + if (mWriterListStates.top().mbListElementParagraphOpened) + { + mpCurrentContentElements->push_back(new TagCloseElement("text:p")); + mWriterListStates.top().mbListElementParagraphOpened = false; + } + TagOpenElement *pListLevelOpenElement = new TagOpenElement("text:list"); + _openListLevel(pListLevelOpenElement); + + if (mWriterListStates.top().mbListContinueNumbering) { + pListLevelOpenElement->addAttribute("text:continue-numbering", "true"); + } + + mpCurrentContentElements->push_back(pListLevelOpenElement); +} + +void DocumentCollector::openUnorderedListLevel(const WPXPropertyList & /* propList */) +{ + if (mWriterListStates.top().mbListElementParagraphOpened) + { + mpCurrentContentElements->push_back(new TagCloseElement("text:p")); + mWriterListStates.top().mbListElementParagraphOpened = false; + } + TagOpenElement *pListLevelOpenElement = new TagOpenElement("text:list"); + _openListLevel(pListLevelOpenElement); + + mpCurrentContentElements->push_back(pListLevelOpenElement); +} + +void DocumentCollector::_openListLevel(TagOpenElement *pListLevelOpenElement) +{ + if (!mWriterListStates.top().mbListElementOpened.empty() && + !mWriterListStates.top().mbListElementOpened.top()) + { + mpCurrentContentElements->push_back(new TagOpenElement("text:list-item")); + mWriterListStates.top().mbListElementOpened.top() = true; + } + + mWriterListStates.top().mbListElementOpened.push(false); + if (mWriterListStates.top().mbListElementOpened.size() == 1) { + pListLevelOpenElement->addAttribute("text:style-name", mWriterListStates.top().mpCurrentListStyle->getName()); + } +} + +void DocumentCollector::closeOrderedListLevel() +{ + _closeListLevel(); +} + +void DocumentCollector::closeUnorderedListLevel() +{ + _closeListLevel(); +} + +void DocumentCollector::_closeListLevel() +{ + if (mWriterListStates.top().mbListElementOpened.top()) + { + mpCurrentContentElements->push_back(new TagCloseElement("text:list-item")); + mWriterListStates.top().mbListElementOpened.top() = false; + } + + mpCurrentContentElements->push_back(new TagCloseElement("text:list")); + + if (!mWriterListStates.top().mbListElementOpened.empty()) + { + mWriterListStates.top().mbListElementOpened.pop(); + } +} + +void DocumentCollector::openListElement(const WPXPropertyList &propList, const WPXPropertyListVector &tabStops) +{ + mWriterListStates.top().miLastListLevel = mWriterListStates.top().miCurrentListLevel; + if (mWriterListStates.top().miCurrentListLevel == 1) + mWriterListStates.top().miLastListNumber++; + + if (mWriterListStates.top().mbListElementOpened.top()) + { + mpCurrentContentElements->push_back(new TagCloseElement("text:list-item")); + mWriterListStates.top().mbListElementOpened.top() = false; + } + + ParagraphStyle *pStyle = NULL; + + WPXPropertyList *pPersistPropList = new WPXPropertyList(propList); + pPersistPropList->insert("style:list-style-name", mWriterListStates.top().mpCurrentListStyle->getName()); + pPersistPropList->insert("style:parent-style-name", "Standard"); + + WPXString sKey = getParagraphStyleKey(*pPersistPropList, tabStops); + + if (mTextStyleHash.find(sKey) == mTextStyleHash.end()) + { + WPXString sName; + sName.sprintf("S%i", mTextStyleHash.size()); + + pStyle = new ParagraphStyle(pPersistPropList, tabStops, sName); + + mTextStyleHash[sKey] = pStyle; + } + else + { + pStyle = mTextStyleHash[sKey]; + delete pPersistPropList; + } + + mpCurrentContentElements->push_back(new TagOpenElement("text:list-item")); + + TagOpenElement *pOpenListElementParagraph = new TagOpenElement("text:p"); + pOpenListElementParagraph->addAttribute("text:style-name", pStyle->getName()); + mpCurrentContentElements->push_back(pOpenListElementParagraph); + + if (mpCurrentContentElements == &mBodyElements) + mWriterDocumentStates.top().mbFirstParagraphInPageSpan = false; + + mWriterListStates.top().mbListElementOpened.top() = true; + mWriterListStates.top().mbListElementParagraphOpened = true; + mWriterListStates.top().mbListContinueNumbering = false; +} + +void DocumentCollector::closeListElement() +{ + // this code is kind of tricky, because we don't actually close the list element (because this list element + // could contain another list level in OOo's implementation of lists). that is done in the closeListLevel + // code (or when we open another list element) + + if (mWriterListStates.top().mbListElementParagraphOpened) + { + mpCurrentContentElements->push_back(new TagCloseElement("text:p")); + mWriterListStates.top().mbListElementParagraphOpened = false; + } +} + +void DocumentCollector::openFootnote(const WPXPropertyList &propList) +{ + mWriterListStates.push(WriterListState()); + TagOpenElement *pOpenFootNote = new TagOpenElement("text:note"); + pOpenFootNote->addAttribute("text:note-class", "footnote"); + if (propList["libwpd:number"]) + { + WPXString tmpString("ftn"); + tmpString.append(propList["libwpd:number"]->getStr()); + pOpenFootNote->addAttribute("text:id", tmpString); + } + mpCurrentContentElements->push_back(pOpenFootNote); + + mpCurrentContentElements->push_back(new TagOpenElement("text:note-citation")); + if (propList["libwpd:number"]) + mpCurrentContentElements->push_back(new CharDataElement(propList["libwpd:number"]->getStr().cstr())); + mpCurrentContentElements->push_back(new TagCloseElement("text:note-citation")); + + mpCurrentContentElements->push_back(new TagOpenElement("text:note-body")); + + mWriterDocumentStates.top().mbInNote = true; +} + +void DocumentCollector::closeFootnote() +{ + mWriterDocumentStates.top().mbInNote = false; + if (mWriterListStates.size() > 1) + mWriterListStates.pop(); + + mpCurrentContentElements->push_back(new TagCloseElement("text:note-body")); + mpCurrentContentElements->push_back(new TagCloseElement("text:note")); +} + +void DocumentCollector::openEndnote(const WPXPropertyList &propList) +{ + mWriterListStates.push(WriterListState()); + TagOpenElement *pOpenEndNote = new TagOpenElement("text:note"); + pOpenEndNote->addAttribute("text:note-class", "endnote"); + if (propList["libwpd:number"]) + { + WPXString tmpString("edn"); + tmpString.append(propList["libwpd:number"]->getStr()); + pOpenEndNote->addAttribute("text:id", tmpString); + } + mpCurrentContentElements->push_back(pOpenEndNote); + + mpCurrentContentElements->push_back(new TagOpenElement("text:note-citation")); + if (propList["libwpd:number"]) + mpCurrentContentElements->push_back(new CharDataElement(propList["libwpd:number"]->getStr().cstr())); + mpCurrentContentElements->push_back(new TagCloseElement("text:note-citation")); + + mpCurrentContentElements->push_back(new TagOpenElement("text:note-body")); + + mWriterDocumentStates.top().mbInNote = true; +} + +void DocumentCollector::closeEndnote() +{ + mWriterDocumentStates.top().mbInNote = false; + if (mWriterListStates.size() > 1) + mWriterListStates.pop(); + + mpCurrentContentElements->push_back(new TagCloseElement("text:note-body")); + mpCurrentContentElements->push_back(new TagCloseElement("text:note")); +} + +void DocumentCollector::openComment(const WPXPropertyList & /*propList*/) +{ + mWriterListStates.push(WriterListState()); + mpCurrentContentElements->push_back(new TagOpenElement("office:annotation")); + + mWriterDocumentStates.top().mbInNote = true; +} + +void DocumentCollector::closeComment() +{ + mWriterDocumentStates.top().mbInNote = false; + if (mWriterListStates.size() > 1) + mWriterListStates.pop(); + + mpCurrentContentElements->push_back(new TagCloseElement("office:annotation")); +} + +void DocumentCollector::openTable(const WPXPropertyList &propList, const WPXPropertyListVector &columns) +{ + if (!mWriterDocumentStates.top().mbInNote) + { + WPXString sTableName; + sTableName.sprintf("Table%i", mTableStyles.size()); + + // FIXME: we base the table style off of the page's margin left, ignoring (potential) wordperfect margin + // state which is transmitted inside the page. could this lead to unacceptable behaviour? + // WLACH_REFACTORING: characterize this behaviour, probably should nip it at the bud within libwpd + TableStyle *pTableStyle = new TableStyle(propList, columns, sTableName.cstr()); + + if (mWriterDocumentStates.top().mbFirstElement && mpCurrentContentElements == &mBodyElements) + { + WPXString sMasterPageName("Page_Style_1"); + pTableStyle->setMasterPageName(sMasterPageName); + mWriterDocumentStates.top().mbFirstElement = false; + } + + mTableStyles.push_back(pTableStyle); + + mpCurrentTableStyle = pTableStyle; + + TagOpenElement *pTableOpenElement = new TagOpenElement("table:table"); + + pTableOpenElement->addAttribute("table:name", sTableName.cstr()); + pTableOpenElement->addAttribute("table:style-name", sTableName.cstr()); + mpCurrentContentElements->push_back(pTableOpenElement); + + for (int i=0; i<pTableStyle->getNumColumns(); i++) + { + TagOpenElement *pTableColumnOpenElement = new TagOpenElement("table:table-column"); + WPXString sColumnStyleName; + sColumnStyleName.sprintf("%s.Column%i", sTableName.cstr(), (i+1)); + pTableColumnOpenElement->addAttribute("table:style-name", sColumnStyleName.cstr()); + mpCurrentContentElements->push_back(pTableColumnOpenElement); + + TagCloseElement *pTableColumnCloseElement = new TagCloseElement("table:table-column"); + mpCurrentContentElements->push_back(pTableColumnCloseElement); + } +} +} + +void DocumentCollector::openTableRow(const WPXPropertyList &propList) +{ + if (!mWriterDocumentStates.top().mbInNote) + { + if (propList["libwpd:is-header-row"] && (propList["libwpd:is-header-row"]->getInt())) + { + mpCurrentContentElements->push_back(new TagOpenElement("table:table-header-rows")); + mWriterDocumentStates.top().mbHeaderRow = true; + } + + WPXString sTableRowStyleName; + sTableRowStyleName.sprintf("%s.Row%i", mpCurrentTableStyle->getName().cstr(), mpCurrentTableStyle->getNumTableRowStyles()); + TableRowStyle *pTableRowStyle = new TableRowStyle(propList, sTableRowStyleName.cstr()); + mpCurrentTableStyle->addTableRowStyle(pTableRowStyle); + + TagOpenElement *pTableRowOpenElement = new TagOpenElement("table:table-row"); + pTableRowOpenElement->addAttribute("table:style-name", sTableRowStyleName); + mpCurrentContentElements->push_back(pTableRowOpenElement); + } +} + +void DocumentCollector::closeTableRow() +{ + if (!mWriterDocumentStates.top().mbInNote) + { + mpCurrentContentElements->push_back(new TagCloseElement("table:table-row")); + if (mWriterDocumentStates.top().mbHeaderRow) + { + mpCurrentContentElements->push_back(new TagCloseElement("table:table-header-rows")); + mWriterDocumentStates.top().mbHeaderRow = false; + } + } +} + +void DocumentCollector::openTableCell(const WPXPropertyList &propList) +{ + if (!mWriterDocumentStates.top().mbInNote) + { + WPXString sTableCellStyleName; + sTableCellStyleName.sprintf( "%s.Cell%i", mpCurrentTableStyle->getName().cstr(), mpCurrentTableStyle->getNumTableCellStyles()); + TableCellStyle *pTableCellStyle = new TableCellStyle(propList, sTableCellStyleName.cstr()); + mpCurrentTableStyle->addTableCellStyle(pTableCellStyle); + + TagOpenElement *pTableCellOpenElement = new TagOpenElement("table:table-cell"); + pTableCellOpenElement->addAttribute("table:style-name", sTableCellStyleName); + if (propList["table:number-columns-spanned"]) + pTableCellOpenElement->addAttribute("table:number-columns-spanned", + propList["table:number-columns-spanned"]->getStr().cstr()); + if (propList["table:number-rows-spanned"]) + pTableCellOpenElement->addAttribute("table:number-rows-spanned", + propList["table:number-rows-spanned"]->getStr().cstr()); + // pTableCellOpenElement->addAttribute("table:value-type", "string"); + mpCurrentContentElements->push_back(pTableCellOpenElement); + + mWriterDocumentStates.top().mbTableCellOpened = true; + } +} + +void DocumentCollector::closeTableCell() +{ + if (!mWriterDocumentStates.top().mbInNote) + { + mpCurrentContentElements->push_back(new TagCloseElement("table:table-cell")); + mWriterDocumentStates.top().mbTableCellOpened = false; + } +} + +void DocumentCollector::insertCoveredTableCell(const WPXPropertyList & /* propList */) +{ + if (!mWriterDocumentStates.top().mbInNote) + { + mpCurrentContentElements->push_back(new TagOpenElement("table:covered-table-cell")); + mpCurrentContentElements->push_back(new TagCloseElement("table:covered-table-cell")); + } +} + +void DocumentCollector::closeTable() +{ + if (!mWriterDocumentStates.top().mbInNote) + { + mpCurrentContentElements->push_back(new TagCloseElement("table:table")); + } +} + + +void DocumentCollector::insertTab() +{ + mpCurrentContentElements->push_back(new TagOpenElement("text:tab")); + mpCurrentContentElements->push_back(new TagCloseElement("text:tab")); +} + +void DocumentCollector::insertSpace() +{ + mpCurrentContentElements->push_back(new TagOpenElement("text:s")); + mpCurrentContentElements->push_back(new TagCloseElement("text:s")); +} + +void DocumentCollector::insertLineBreak() +{ + mpCurrentContentElements->push_back(new TagOpenElement("text:line-break")); + mpCurrentContentElements->push_back(new TagCloseElement("text:line-break")); +} + +void DocumentCollector::insertField(const WPXString &type, const WPXPropertyList &propList) +{ + if (!type.len()) + return; + + TagOpenElement *openElement = new TagOpenElement(type.cstr()); + if (type == "text:page-number") + openElement->addAttribute("text:select-page", "current"); + + if (propList["style:num-format"]) + openElement->addAttribute("style:num-format", propList["style:num-format"]->getStr()); + + mpCurrentContentElements->push_back(openElement); + mpCurrentContentElements->push_back(new TagCloseElement(type.cstr())); +} + +void DocumentCollector::insertText(const WPXString &text) +{ + DocumentElement *pText = new TextElement(text); + mpCurrentContentElements->push_back(pText); +} + +void DocumentCollector::openFrame(const WPXPropertyList &propList) +{ + mWriterListStates.push(WriterListState()); + + // First, let's create a Frame Style for this box + TagOpenElement *frameStyleOpenElement = new TagOpenElement("style:style"); + WPXString frameStyleName; + frameStyleName.sprintf("GraphicFrame_%i", miObjectNumber); + frameStyleOpenElement->addAttribute("style:name", frameStyleName); + frameStyleOpenElement->addAttribute("style:family", "graphic"); + + mFrameStyles.push_back(frameStyleOpenElement); + + TagOpenElement *frameStylePropertiesOpenElement = new TagOpenElement("style:graphic-properties"); + + if (propList["text:anchor-type"]) + frameStylePropertiesOpenElement->addAttribute("text:anchor-type", propList["text:anchor-type"]->getStr()); + else + frameStylePropertiesOpenElement->addAttribute("text:anchor-type","paragraph"); + + if (propList["text:anchor-page-number"]) + frameStylePropertiesOpenElement->addAttribute("text:anchor-page-number", propList["text:anchor-page-number"]->getStr()); + + if (propList["svg:x"]) + frameStylePropertiesOpenElement->addAttribute("svg:x", propList["svg:x"]->getStr()); + + if (propList["svg:y"]) + frameStylePropertiesOpenElement->addAttribute("svg:y", propList["svg:y"]->getStr()); + + if (propList["svg:width"]) + frameStylePropertiesOpenElement->addAttribute("svg:width", propList["svg:width"]->getStr()); + + if (propList["svg:height"]) + frameStylePropertiesOpenElement->addAttribute("svg:height", propList["svg:height"]->getStr()); + + if (propList["style:rel-width"]) + frameStylePropertiesOpenElement->addAttribute("style:rel-width", propList["style:rel-width"]->getStr()); + + if (propList["style:rel-height"]) + frameStylePropertiesOpenElement->addAttribute("style:rel-height", propList["style:rel-height"]->getStr()); + + if (propList["fo:max-width"]) + frameStylePropertiesOpenElement->addAttribute("fo:max-width", propList["fo:max-width"]->getStr()); + + if (propList["fo:max-height"]) + frameStylePropertiesOpenElement->addAttribute("fo:max-height", propList["fo:max-height"]->getStr()); + + if (propList["style:wrap"]) + frameStylePropertiesOpenElement->addAttribute("style:wrap", propList["style:wrap"]->getStr()); + + mFrameStyles.push_back(frameStylePropertiesOpenElement); + + mFrameStyles.push_back(new TagCloseElement("style:graphic-properties")); + + mFrameStyles.push_back(new TagCloseElement("style:style")); + + // Now, let's create an automatic style for this frame + TagOpenElement *frameAutomaticStyleElement = new TagOpenElement("style:style"); + WPXString frameAutomaticStyleName; + frameAutomaticStyleName.sprintf("fr%i", miObjectNumber); + frameAutomaticStyleElement->addAttribute("style:name", frameAutomaticStyleName); + frameAutomaticStyleElement->addAttribute("style:family", "graphic"); + frameAutomaticStyleElement->addAttribute("style:parent-style-name", frameStyleName); + + mFrameAutomaticStyles.push_back(frameAutomaticStyleElement); + + TagOpenElement *frameAutomaticStylePropertiesElement = new TagOpenElement("style:graphic-properties"); + if (propList["style:horizontal-pos"]) + frameAutomaticStylePropertiesElement->addAttribute("style:horizontal-pos", propList["style:horizontal-pos"]->getStr()); + else + frameAutomaticStylePropertiesElement->addAttribute("style:horizontal-pos", "left"); + + if (propList["style:horizontal-rel"]) + frameAutomaticStylePropertiesElement->addAttribute("style:horizontal-rel", propList["style:horizontal-rel"]->getStr()); + else + frameAutomaticStylePropertiesElement->addAttribute("style:horizontal-rel", "paragraph"); + + if (propList["style:vertical-pos"]) + frameAutomaticStylePropertiesElement->addAttribute("style:vertical-pos", propList["style:vertical-pos"]->getStr()); + else + frameAutomaticStylePropertiesElement->addAttribute("style:vertical-pos", "top"); + + if (propList["style:vertical-rel"]) + frameAutomaticStylePropertiesElement->addAttribute("style:vertical-rel", propList["style:vertical-rel"]->getStr()); + else + frameAutomaticStylePropertiesElement->addAttribute("style:vertical-rel", "page-content"); + + if (propList["fo:max-width"]) + frameAutomaticStylePropertiesElement->addAttribute("fo:max-width", propList["fo:max-width"]->getStr()); + + if (propList["fo:max-height"]) + frameAutomaticStylePropertiesElement->addAttribute("fo:max-height", propList["fo:max-height"]->getStr()); + + frameAutomaticStylePropertiesElement->addAttribute("draw:ole-draw-aspect", "1"); + + mFrameAutomaticStyles.push_back(frameAutomaticStylePropertiesElement); + + mFrameAutomaticStyles.push_back(new TagCloseElement("style:graphic-properties")); + + mFrameAutomaticStyles.push_back(new TagCloseElement("style:style")); + + // And write the frame itself + TagOpenElement *drawFrameOpenElement = new TagOpenElement("draw:frame"); + + drawFrameOpenElement->addAttribute("draw:style-name", frameAutomaticStyleName); + WPXString objectName; + objectName.sprintf("Object%i", miObjectNumber++); + drawFrameOpenElement->addAttribute("draw:name", objectName); + if (propList["text:anchor-type"]) + drawFrameOpenElement->addAttribute("text:anchor-type", propList["text:anchor-type"]->getStr()); + else + drawFrameOpenElement->addAttribute("text:anchor-type","paragraph"); + + if (propList["text:anchor-page-number"]) + drawFrameOpenElement->addAttribute("text:anchor-page-number", propList["text:anchor-page-number"]->getStr()); + + if (propList["svg:x"]) + drawFrameOpenElement->addAttribute("svg:x", propList["svg:x"]->getStr()); + + if (propList["svg:y"]) + drawFrameOpenElement->addAttribute("svg:y", propList["svg:y"]->getStr()); + + if (propList["svg:width"]) + drawFrameOpenElement->addAttribute("svg:width", propList["svg:width"]->getStr()); + + if (propList["svg:height"]) + drawFrameOpenElement->addAttribute("svg:height", propList["svg:height"]->getStr()); + + if (propList["style:rel-width"]) + drawFrameOpenElement->addAttribute("style:rel-width", propList["style:rel-width"]->getStr()); + + if (propList["style:rel-height"]) + drawFrameOpenElement->addAttribute("style:rel-height", propList["style:rel-height"]->getStr()); + + mpCurrentContentElements->push_back(drawFrameOpenElement); + + mWriterDocumentStates.top().mbInFrame = true; +} + +void DocumentCollector::closeFrame() +{ + if (mWriterListStates.size() > 1) + mWriterListStates.pop(); + + mpCurrentContentElements->push_back(new TagCloseElement("draw:frame")); + + mWriterDocumentStates.top().mbInFrame = false; +} + +void DocumentCollector::insertBinaryObject(const WPXPropertyList &propList, const WPXBinaryData &data) +{ + if (!data.size()) + return; + if (!mWriterDocumentStates.top().mbInFrame) // Embedded objects without a frame simply don't make sense for us + return; + if (!propList["libwpd:mimetype"]) + return; + + if (propList["libwpd:mimetype"]->getStr() == "image/x-wpg") + { + std::vector<DocumentElement *> tmpContentElements; + InternalHandler tmpHandler(&tmpContentElements); + OdgExporter exporter(&tmpHandler); + + libwpg::WPGFileFormat fileFormat = libwpg::WPG_AUTODETECT; + + if (!libwpg::WPGraphics::isSupported(const_cast<WPXInputStream *>(data.getDataStream()))) + fileFormat = libwpg::WPG_WPG1; + + if (libwpg::WPGraphics::parse(const_cast<WPXInputStream *>(data.getDataStream()), &exporter, fileFormat) && !tmpContentElements.empty()) + { + mpCurrentContentElements->push_back(new TagOpenElement("draw:object")); + for (std::vector<DocumentElement *>::const_iterator iter = tmpContentElements.begin(); iter != tmpContentElements.end(); ++iter) + mpCurrentContentElements->push_back(*iter); + mpCurrentContentElements->push_back(new TagCloseElement("draw:object")); + } + } + else + { + mpCurrentContentElements->push_back(new TagOpenElement("draw:image")); + + mpCurrentContentElements->push_back(new TagOpenElement("office:binary-data")); + + WPXString binaryBase64Data = data.getBase64Data(); + + mpCurrentContentElements->push_back(new CharDataElement(binaryBase64Data.cstr())); + + mpCurrentContentElements->push_back(new TagCloseElement("office:binary-data")); + + mpCurrentContentElements->push_back(new TagCloseElement("draw:image")); + } +} + +void DocumentCollector::openTextBox(const WPXPropertyList & /*propList*/) +{ + if (!mWriterDocumentStates.top().mbInFrame) // Text box without a frame simply doesn't make sense for us + return; + mWriterListStates.push(WriterListState()); + mWriterDocumentStates.push(WriterDocumentState()); + mpCurrentContentElements->push_back(new TagOpenElement("draw:text-box")); + mWriterDocumentStates.top().mbInTextBox = true; + mWriterDocumentStates.top().mbFirstElement = false; +} + +void DocumentCollector::closeTextBox() +{ + if (!mWriterDocumentStates.top().mbInTextBox) + return; + if (mWriterListStates.size() > 1) + mWriterListStates.pop(); + if (mWriterDocumentStates.size() > 1) + mWriterDocumentStates.pop(); + + mpCurrentContentElements->push_back(new TagCloseElement("draw:text-box")); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/DocumentCollector.hxx b/writerperfect/source/filter/DocumentCollector.hxx new file mode 100644 index 000000000000..619bc1de603d --- /dev/null +++ b/writerperfect/source/filter/DocumentCollector.hxx @@ -0,0 +1,251 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* DocumentCollector: Collects sections and runs of text from a + * file (and styles to go along with them) and writes them + * to a target file + * + * Copyright (C) 2002-2004 William Lachance (william.lachance@sympatico.ca) + * Copyright (C) 2003-2004 Net Integration Technologies (http://www.net-itech.com) + * Copyright (C) 2004 Fridrich Strba (fridrich.strba@bluewin.ch) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#ifndef _DOCUMENTCOLLECTOR_HXX +#define _DOCUMENTCOLLECTOR_HXX +#include "SectionStyle.hxx" + +#if defined _MSC_VER +#pragma warning( push, 1 ) +#endif +#include <libwps/libwps.h> +#include <libwpd/libwpd.h> +#if defined _MSC_VER +#pragma warning( pop ) +#endif +#include <vector> +#include <map> +#include <stack> +#include <string.h> + +#include "DocumentHandlerInterface.hxx" + +class DocumentElement; +class TagOpenElement; +class FontStyle; +class ListStyle; + +class ParagraphStyle; +class SpanStyle; +class TableStyle; +class PageSpan; + +// the state we use for writing the final document +typedef struct _WriterDocumentState WriterDocumentState; +struct _WriterDocumentState +{ + _WriterDocumentState(); + + bool mbFirstElement; + bool mbFirstParagraphInPageSpan; + bool mbInFakeSection; + bool mbListElementOpenedAtCurrentLevel; + bool mbTableCellOpened; + bool mbHeaderRow; + bool mbInNote; + bool mbInTextBox; + bool mbInFrame; +}; + +// list state +typedef struct _WriterListState WriterListState; +struct _WriterListState +{ + _WriterListState(); + + ListStyle *mpCurrentListStyle; + unsigned int miCurrentListLevel; + unsigned int miLastListLevel; + unsigned int miLastListNumber; + bool mbListContinueNumbering; + bool mbListElementParagraphOpened; + std::stack<bool> mbListElementOpened; +}; + +enum WriterListType { unordered, ordered }; + +struct ltstr +{ + bool operator()(const WPXString & s1, const WPXString & s2) const + { + return strcmp(s1.cstr(), s2.cstr()) < 0; + } +}; + +class DocumentCollector : public WPXDocumentInterface +{ +public: + DocumentCollector(WPXInputStream *pInput, DocumentHandlerInterface *pHandler); + virtual ~DocumentCollector(); + bool filter(); + + // WPXDocumentInterface's callbacks + virtual void setDocumentMetaData(const WPXPropertyList &propList); + virtual void startDocument() {} + virtual void endDocument() {} + + virtual void definePageStyle(const WPXPropertyList&) {} + virtual void openPageSpan(const WPXPropertyList &propList); + virtual void closePageSpan() {} + + virtual void defineSectionStyle(const WPXPropertyList&, const WPXPropertyListVector&) {} + virtual void openSection(const WPXPropertyList &propList, const WPXPropertyListVector &columns); + virtual void closeSection(); + + virtual void openHeader(const WPXPropertyList &propList); + virtual void closeHeader(); + virtual void openFooter(const WPXPropertyList &propList); + virtual void closeFooter(); + + virtual void defineParagraphStyle(const WPXPropertyList&, const WPXPropertyListVector&) {} + virtual void openParagraph(const WPXPropertyList &propList, const WPXPropertyListVector &tabStops); + virtual void closeParagraph(); + + virtual void defineCharacterStyle(const WPXPropertyList&) {} + virtual void openSpan(const WPXPropertyList &propList); + virtual void closeSpan(); + + virtual void insertTab(); + virtual void insertSpace(); + virtual void insertText(const WPXString &text); + virtual void insertLineBreak(); + virtual void insertField(const WPXString &type, const WPXPropertyList &propList); + + virtual void defineOrderedListLevel(const WPXPropertyList &propList); + virtual void defineUnorderedListLevel(const WPXPropertyList &propList); + virtual void openOrderedListLevel(const WPXPropertyList &propList); + virtual void openUnorderedListLevel(const WPXPropertyList &propList); + virtual void closeOrderedListLevel(); + virtual void closeUnorderedListLevel(); + virtual void openListElement(const WPXPropertyList &propList, const WPXPropertyListVector &tabStops); + virtual void closeListElement(); + + virtual void openFootnote(const WPXPropertyList &propList); + virtual void closeFootnote(); + virtual void openEndnote(const WPXPropertyList &propList); + virtual void closeEndnote(); + virtual void openComment(const WPXPropertyList &propList); + virtual void closeComment(); + virtual void openTextBox(const WPXPropertyList &propList); + virtual void closeTextBox(); + + virtual void openTable(const WPXPropertyList &propList, const WPXPropertyListVector &columns); + virtual void openTableRow(const WPXPropertyList &propList); + virtual void closeTableRow(); + virtual void openTableCell(const WPXPropertyList &propList); + virtual void closeTableCell(); + virtual void insertCoveredTableCell(const WPXPropertyList &propList); + virtual void closeTable(); + + virtual void openFrame(const WPXPropertyList & propList); + virtual void closeFrame(); + + virtual void insertBinaryObject(const WPXPropertyList &propList, const WPXBinaryData &data); + virtual void insertEquation(const WPXPropertyList & /* propList */, const WPXString & /* data */) {} + + virtual bool parseSourceDocument(WPXInputStream &input) = 0; + +protected: + void _resetDocumentState(); + bool _writeTargetDocument(DocumentHandlerInterface *pHandler); + void _writeDefaultStyles(DocumentHandlerInterface *pHandler); + void _writeMasterPages(DocumentHandlerInterface *pHandler); + void _writePageLayouts(DocumentHandlerInterface *pHandler); + void _allocateFontName(const WPXString &); + +private: + void _openListLevel(TagOpenElement *pListLevelOpenElement); + void _closeListLevel(); + + WPXInputStream *mpInput; + DocumentHandlerInterface *mpHandler; + bool mbUsed; // whether or not it has been before (you can only use me once!) + + std::stack<WriterDocumentState> mWriterDocumentStates; + + std::stack<WriterListState> mWriterListStates; + + // paragraph styles + std::map<WPXString, ParagraphStyle *, ltstr> mTextStyleHash; + + // span styles + std::map<WPXString, SpanStyle *, ltstr> mSpanStyleHash; + + // font styles + std::map<WPXString, FontStyle *, ltstr> mFontHash; + + // section styles + std::vector<SectionStyle *> mSectionStyles; + float mfSectionSpaceAfter; + + // table styles + std::vector<TableStyle *> mTableStyles; + + // frame styles + std::vector<DocumentElement *> mFrameStyles; + + std::vector<DocumentElement *> mFrameAutomaticStyles; + + // metadata + std::vector<DocumentElement *> mMetaData; + + // list styles + unsigned int miNumListStyles; + + // style elements + std::vector<DocumentElement *> mStylesElements; + // content elements + std::vector<DocumentElement *> mBodyElements; + // the current set of elements that we're writing to + std::vector<DocumentElement *> * mpCurrentContentElements; + + // page state + std::vector<PageSpan *> mPageSpans; + PageSpan *mpCurrentPageSpan; + int miNumPageStyles; + + // list styles + std::vector<ListStyle *> mListStyles; + + // object state + unsigned miObjectNumber; + + // table state + TableStyle *mpCurrentTableStyle; + + const bool mbIsFlatXML; + + const char * mpPassword; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/DocumentElement.cxx b/writerperfect/source/filter/DocumentElement.cxx new file mode 100644 index 000000000000..f330ab0ace47 --- /dev/null +++ b/writerperfect/source/filter/DocumentElement.cxx @@ -0,0 +1,108 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* DocumentElement: The items we are collecting to be put into the Writer + * document: paragraph and spans of text, as well as section breaks. + * + * Copyright (C) 2002-2003 William Lachance (william.lachance@sympatico.ca) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#include "DocumentElement.hxx" +#include "DocumentHandler.hxx" +#include "FilterInternal.hxx" +#include <string.h> + +#define ASCII_SPACE 0x0020 + +void TagElement::print() const +{ + WRITER_DEBUG_MSG(("%s\n", msTagName.cstr())); +} + +void TagOpenElement::write(DocumentHandlerInterface *pHandler) const +{ + pHandler->startElement(getTagName().cstr(), maAttrList); +} + +void TagOpenElement::print() const +{ + TagElement::print(); +} + +void TagOpenElement::addAttribute(const char *szAttributeName, const WPXString &sAttributeValue) +{ + maAttrList.insert(szAttributeName, sAttributeValue); +} + +void TagCloseElement::write(DocumentHandlerInterface *pHandler) const +{ + WRITER_DEBUG_MSG(("TagCloseElement: write (%s)\n", getTagName().cstr())); + + pHandler->endElement(getTagName().cstr()); +} + +void CharDataElement::write(DocumentHandlerInterface *pHandler) const +{ + WRITER_DEBUG_MSG(("TextElement: write\n")); + pHandler->characters(msData); +} + +TextElement::TextElement(const WPXString & sTextBuf) : + msTextBuf(sTextBuf, false) +{ +} + +// write: writes a text run, appropriately converting spaces to <text:s> +// elements +void TextElement::write(DocumentHandlerInterface *pHandler) const +{ + if (msTextBuf.len() <= 0) + return; + WPXPropertyList xBlankAttrList; + + WPXString sTemp; + + int iNumConsecutiveSpaces = 0; + WPXString::Iter i(msTextBuf); + for (i.rewind(); i.next();) + { + if (*(i()) == ASCII_SPACE) + iNumConsecutiveSpaces++; + else + iNumConsecutiveSpaces = 0; + + if (iNumConsecutiveSpaces > 1) { + if (sTemp.len() > 0) { + pHandler->characters(sTemp); + sTemp.clear(); + } + pHandler->startElement("text:s", xBlankAttrList); + pHandler->endElement("text:s"); + } + else { + sTemp.append(i()); + } + } + pHandler->characters(sTemp); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/DocumentElement.hxx b/writerperfect/source/filter/DocumentElement.hxx new file mode 100644 index 000000000000..cb84777a278a --- /dev/null +++ b/writerperfect/source/filter/DocumentElement.hxx @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* DocumentElement: The items we are collecting to be put into the Writer + * document: paragraph and spans of text, as well as section breaks. + * + * Copyright (C) 2002-2003 William Lachance (william.lachance@sympatico.ca) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#ifndef _DOCUMENTELEMENT_H +#define _DOCUMENTELEMENT_H +#include <libwpd/libwpd.h> +#include <libwpd/WPXProperty.h> +#include <libwpd/WPXString.h> +#include <vector> + +#include "DocumentHandlerInterface.hxx" + +class DocumentElement +{ +public: + virtual ~DocumentElement() {} + virtual void write(DocumentHandlerInterface *pHandler) const = 0; + virtual void print() const {} +}; + +class TagElement : public DocumentElement +{ +public: + virtual ~TagElement() {} + TagElement(const char *szTagName) : msTagName(szTagName) {} + const WPXString & getTagName() const { return msTagName; } + virtual void print() const; +private: + WPXString msTagName; +}; + +class TagOpenElement : public TagElement +{ +public: + TagOpenElement(const char *szTagName) : TagElement(szTagName) {} + virtual ~TagOpenElement() {} + void addAttribute(const char *szAttributeName, const WPXString &sAttributeValue); + virtual void write(DocumentHandlerInterface *pHandler) const; + virtual void print () const; +private: + WPXPropertyList maAttrList; +}; + +class TagCloseElement : public TagElement +{ +public: + TagCloseElement(const char *szTagName) : TagElement(szTagName) {} + virtual ~TagCloseElement() {} + virtual void write(DocumentHandlerInterface *pHandler) const; +}; + +class CharDataElement : public DocumentElement +{ +public: + CharDataElement(const char *sData) : DocumentElement(), msData(sData) {} + virtual ~CharDataElement() {} + virtual void write(DocumentHandlerInterface *pHandler) const; +private: + WPXString msData; +}; + +class TextElement : public DocumentElement +{ +public: + TextElement(const WPXString & sTextBuf); + virtual ~TextElement() {} + virtual void write(DocumentHandlerInterface *pHandler) const; + +private: + WPXString msTextBuf; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/DocumentHandler.cxx b/writerperfect/source/filter/DocumentHandler.cxx new file mode 100644 index 000000000000..c61ffc0c19c5 --- /dev/null +++ b/writerperfect/source/filter/DocumentHandler.cxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2004 William Lachance (william.lachance@sympatico.ca) + * Copyright (C) 2004 Net Integration Technologies (http://www.net-itech.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ +#include "DocumentHandler.hxx" +#include "FilterInternal.hxx" + +#include <string.h> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XAttributeList.hpp> + +#include <xmloff/attrlist.hxx> + +// #define DEBUG_XML 1 + +using namespace ::rtl; +using rtl::OUString; + +using com::sun::star::xml::sax::XAttributeList; + +DocumentHandler::DocumentHandler(Reference < XDocumentHandler > &xHandler) : + mxHandler(xHandler) +{ +} + +void DocumentHandler::startDocument() +{ + mxHandler->startDocument(); +} + +void DocumentHandler::endDocument() +{ + mxHandler->endDocument(); +} + +void DocumentHandler::startElement(const char *psName, const WPXPropertyList &xPropList) +{ +#ifdef DEBUG_XML + printf("<%s", psName); +#endif + SvXMLAttributeList *pAttrList = new SvXMLAttributeList(); + Reference < XAttributeList > xAttrList(pAttrList); + WPXPropertyList::Iter i(xPropList); + for (i.rewind(); i.next(); ) + { + // filter out libwpd elements + if (strncmp(i.key(), "libwpd", 6) != 0) + { + pAttrList->AddAttribute(OUString::createFromAscii(i.key()), + OUString::createFromAscii(i()->getStr().cstr())); +#ifdef DEBUG_XML + printf(" %s=\"%s\"", i.key(), i()->getStr().cstr()); +#endif + } + } +#ifdef DEBUG_XML + printf(">"); +#endif + + mxHandler->startElement(OUString::createFromAscii(psName), xAttrList); +} + +void DocumentHandler::endElement(const char *psName) +{ +#ifdef DEBUG_XML + printf("</%s>", psName); +#endif + mxHandler->endElement(OUString::createFromAscii(psName)); +} + +void DocumentHandler::characters(const WPXString &sCharacters) +{ + OUString sCharU16(sCharacters.cstr(), strlen(sCharacters.cstr()), RTL_TEXTENCODING_UTF8); +#ifdef DEBUG_XML + WPXString sEscapedCharacters(sCharacters, true); + printf("%s", sEscapedCharacters.cstr()); +#endif + mxHandler->characters(sCharU16); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/DocumentHandler.hxx b/writerperfect/source/filter/DocumentHandler.hxx new file mode 100644 index 000000000000..249f64ff4e7b --- /dev/null +++ b/writerperfect/source/filter/DocumentHandler.hxx @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#ifndef _OODOCUMENTHANDLER_HXX_ +#define _OODOCUMENTHANDLER_HXX_ + +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> + +#if defined _MSC_VER +#pragma warning( push, 1 ) +#endif +#include <libwpd/libwpd.h> +#if defined _MSC_VER +#pragma warning( pop ) +#endif + +#include "DocumentHandlerInterface.hxx" + +using com::sun::star::uno::Reference; +using com::sun::star::xml::sax::XDocumentHandler; + +class DocumentHandler: public DocumentHandlerInterface +{ +public: + DocumentHandler(Reference < XDocumentHandler > &xHandler); + void startDocument(); + void endDocument(); + void startElement(const char *psName, const WPXPropertyList &xPropList); + void endElement(const char *psName); + void characters(const WPXString &sCharacters); + +private: + Reference < XDocumentHandler > mxHandler; +}; + +#endif // _OODOCUMENTHANDLER_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/DocumentHandlerInterface.hxx b/writerperfect/source/filter/DocumentHandlerInterface.hxx new file mode 100644 index 000000000000..73ced7d39650 --- /dev/null +++ b/writerperfect/source/filter/DocumentHandlerInterface.hxx @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2004 William Lachance (wlach@interlog.com) + * Copyright (C) 2004 Net Integration Technologies (http://www.net-itech.com) + * + * 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. + * + * Contributor(s): Martin Gallwey (gallwey@sun.com) + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef _DOCUMENTHANDLERINTERFACE_H +#define _DOCUMENTHANDLERINTERFACE_H +#include <libwpd/libwpd.h> +#include <libwpd/WPXProperty.h> +#include <libwpd/WPXString.h> + +class DocumentHandlerInterface +{ +public: + DocumentHandlerInterface() {}; + virtual ~DocumentHandlerInterface() {}; + + virtual void startDocument() = 0; + virtual void endDocument() = 0; + virtual void startElement(const char *psName, const WPXPropertyList &xPropList) = 0; + virtual void endElement(const char *psName) = 0; + virtual void characters(const WPXString &sCharacters) = 0; +}; +#endif diff --git a/writerperfect/source/filter/FilterInternal.hxx b/writerperfect/source/filter/FilterInternal.hxx new file mode 100644 index 000000000000..c53e83ec5d35 --- /dev/null +++ b/writerperfect/source/filter/FilterInternal.hxx @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* FilterInternal: Debugging information + * + * Copyright (C) 2002-2003 William Lachance (william.lachance@sympatico.ca) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +#ifndef _FILTERINTERNAL_HXX +#define _FILTERINTERNAL_HXX + +#include <stdio.h> +#ifdef DEBUG +#define WRITER_DEBUG_MSG(M) printf M +#else +#define WRITER_DEBUG_MSG(M) +#endif + +const float fDefaultSideMargin = 1.0f; // inches +const float fDefaultPageWidth = 8.5f; // inches (OOo required default: we will handle this later) +const float fDefaultPageHeight = 11.0f; // inches + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/FontStyle.cxx b/writerperfect/source/filter/FontStyle.cxx new file mode 100644 index 000000000000..e15c6651edd9 --- /dev/null +++ b/writerperfect/source/filter/FontStyle.cxx @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* FontStyle: Stores (and writes) font-based information that is needed at + * the head of an OO document. + * + * Copyright (C) 2002-2003 William Lachance (william.lachance@sympatico.ca) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#include "FontStyle.hxx" +#include "WriterProperties.hxx" +#include "DocumentElement.hxx" + +FontStyle::FontStyle(const char *psName, const char *psFontFamily) : Style(psName), + msFontFamily(psFontFamily, true), + msFontPitch(IMP_DEFAULT_FONT_PITCH) +{ +} + +FontStyle::~FontStyle() +{ +} + +void FontStyle::write(DocumentHandlerInterface *pHandler) const +{ + TagOpenElement styleOpen("style:font-face"); + styleOpen.addAttribute("style:name", getName()); + styleOpen.addAttribute("svg:font-family", msFontFamily); +// styleOpen.addAttribute("style:font-pitch", msFontPitch); + styleOpen.write(pHandler); + TagCloseElement styleClose("style:font-face"); + styleClose.write(pHandler); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/FontStyle.hxx b/writerperfect/source/filter/FontStyle.hxx new file mode 100644 index 000000000000..aec430dbd43e --- /dev/null +++ b/writerperfect/source/filter/FontStyle.hxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* FontStyle: Stores (and writes) font-based information that is needed at + * the head of an OO document. + * + * Copyright (C) 2002-2003 William Lachance (william.lachance@sympatico.ca) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef _FONTSTYLE_H +#define _FONTSTYLE_H +#include <libwpd/libwpd.h> + +#include "Style.hxx" +#include "WriterProperties.hxx" +#include "DocumentHandlerInterface.hxx" + +class FontStyle : public Style +{ +public: + FontStyle(const char *psName, const char *psFontFamily); + ~FontStyle(); + virtual void write(DocumentHandlerInterface *pHandler) const; + const WPXString &getFontFamily() const { return msFontFamily; } + +private: + WPXString msFontFamily; + WPXString msFontPitch; +}; +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/GraphicsStyle.cxx b/writerperfect/source/filter/GraphicsStyle.cxx new file mode 100644 index 000000000000..4067f55baf46 --- /dev/null +++ b/writerperfect/source/filter/GraphicsStyle.cxx @@ -0,0 +1,40 @@ +/* GraphicsStyle: + * + * Copyright (C) 2007 Fridrich Strba .strba@bluewin.ch) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#include "GraphicsStyle.hxx" +#include "WriterProperties.hxx" +#include "DocumentElement.hxx" + +GraphicsStyle::GraphicsStyle(const char *psName) : Style(psName) +{ +} + +GraphicsStyle::~GraphicsStyle() +{ +} + +void GraphicsStyle::write(DocumentHandlerInterface * /* pHandler */) const +{ +} diff --git a/writerperfect/source/filter/GraphicsStyle.hxx b/writerperfect/source/filter/GraphicsStyle.hxx new file mode 100644 index 000000000000..b6ee0c66da88 --- /dev/null +++ b/writerperfect/source/filter/GraphicsStyle.hxx @@ -0,0 +1,40 @@ +/* GraphicsStyle: + * + * Copyright (C) 2007 Fridrich Strba .strba@bluewin.ch) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef _GRAPHICSSTYLE_H +#define _GRAPHICSSTYLE_H + +#include "Style.hxx" +#include "WriterProperties.hxx" +#include "DocumentHandlerInterface.hxx" + +class GraphicsStyle : public Style +{ +public: + GraphicsStyle(const char *psName); + ~GraphicsStyle(); + virtual void write(DocumentHandlerInterface *pHandler) const; +}; +#endif diff --git a/writerperfect/source/filter/InternalHandler.cxx b/writerperfect/source/filter/InternalHandler.cxx new file mode 100644 index 000000000000..82479bd2221a --- /dev/null +++ b/writerperfect/source/filter/InternalHandler.cxx @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2007 Fridrich Strba .strba@bluewin.ch) + * + * 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. + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#include "InternalHandler.hxx" + +#include <string.h> + +InternalHandler::InternalHandler(std::vector<DocumentElement *> *elements): + mpElements(elements) +{ +} + +void InternalHandler::startElement(const char *psName, const WPXPropertyList &xPropList) +{ + TagOpenElement *element = new TagOpenElement(psName); + WPXPropertyList::Iter i(xPropList); + for (i.rewind(); i.next(); ) + { + // filter out libwpd elements + if (strncmp(i.key(), "libwpd", 6) != 0) + element->addAttribute(i.key(), i()->getStr()); + } + mpElements->push_back(element); +} + +void InternalHandler::endElement(const char *psName) +{ + mpElements->push_back(new TagCloseElement(psName)); +} + +void InternalHandler::characters(const WPXString &sCharacters) +{ + mpElements->push_back(new CharDataElement(sCharacters.cstr())); +} diff --git a/writerperfect/source/filter/InternalHandler.hxx b/writerperfect/source/filter/InternalHandler.hxx new file mode 100644 index 000000000000..9913ac803652 --- /dev/null +++ b/writerperfect/source/filter/InternalHandler.hxx @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2007 Fridrich Strba .strba@bluewin.ch) + * + * 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. + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#ifndef _INTERNALHANDLER_H +#define _INTERNALHANDLER_H +#include <libwpd/libwpd.h> +#include <libwpd/WPXProperty.h> +#include <libwpd/WPXString.h> +#include "DocumentElement.hxx" +#include "DocumentHandlerInterface.hxx" + +class InternalHandler : public DocumentHandlerInterface +{ +public: + InternalHandler(std::vector<DocumentElement *> *elements); + ~InternalHandler() {}; + + void startDocument() {}; + void endDocument() {}; + void startElement(const char *psName, const WPXPropertyList &xPropList); + void endElement(const char *psName); + void characters(const WPXString &sCharacters); +private: + std::vector<DocumentElement *> *mpElements; +}; +#endif diff --git a/writerperfect/source/filter/ListStyle.cxx b/writerperfect/source/filter/ListStyle.cxx new file mode 100644 index 000000000000..c7fdc0d0a835 --- /dev/null +++ b/writerperfect/source/filter/ListStyle.cxx @@ -0,0 +1,185 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ListStyle: Stores (and writes) list-based information that is + * needed at the head of an OO document. + * + * Copyright (C) 2002-2003 William Lachance (william.lachance@sympatico.ca) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#include "FilterInternal.hxx" +#include "ListStyle.hxx" +#include "DocumentElement.hxx" + +OrderedListLevelStyle::OrderedListLevelStyle(const WPXPropertyList &xPropList) : + mPropList(xPropList) +{ +} + +void OrderedListStyle::updateListLevel(const int iLevel, const WPXPropertyList &xPropList) +{ + if (iLevel < 0) + return; + if (!isListLevelDefined(iLevel)) + setListLevel(iLevel, new OrderedListLevelStyle(xPropList)); +} + +void OrderedListLevelStyle::write(DocumentHandlerInterface *pHandler, int iLevel) const +{ + WPXString sLevel; + sLevel.sprintf("%i", (iLevel+1)); + + TagOpenElement listLevelStyleOpen("text:list-level-style-number"); + listLevelStyleOpen.addAttribute("text:level", sLevel); + listLevelStyleOpen.addAttribute("text:style-name", "Numbering_Symbols"); + if (mPropList["style:num-prefix"]) + { + WPXString sEscapedString(mPropList["style:num-prefix"]->getStr(), true); + listLevelStyleOpen.addAttribute("style:num-prefix", sEscapedString); + } + if (mPropList["style:num-suffix"]) + { + WPXString sEscapedString(mPropList["style:num-suffix"]->getStr(), true); + listLevelStyleOpen.addAttribute("style:num-suffix", sEscapedString); + } + if (mPropList["style:num-format"]) + listLevelStyleOpen.addAttribute("style:num-format", mPropList["style:num-format"]->getStr()); + if (mPropList["text:start-value"]) + { + // odf as to the version 1.1 does require the text:start-value to be a positive integer, means > 0 + if (mPropList["text:start-value"]->getInt() > 0) + listLevelStyleOpen.addAttribute("text:start-value", mPropList["text:start-value"]->getStr()); + else + listLevelStyleOpen.addAttribute("text:start-value", "1"); + } + listLevelStyleOpen.write(pHandler); + + TagOpenElement stylePropertiesOpen("style:list-level-properties"); + if (mPropList["text:space-before"] && mPropList["text:space-before"]->getDouble() > 0.0f) + stylePropertiesOpen.addAttribute("text:space-before", mPropList["text:space-before"]->getStr()); + if (mPropList["text:min-label-width"] && mPropList["text:min-label-width"]->getDouble() > 0.0f) + stylePropertiesOpen.addAttribute("text:min-label-width", mPropList["text:min-label-width"]->getStr()); + if (mPropList["text:min-label-distance"] && mPropList["text:min-label-distance"]->getDouble() > 0.0f) + stylePropertiesOpen.addAttribute("text:min-label-distance", mPropList["text:min-label-distance"]->getStr()); + stylePropertiesOpen.write(pHandler); + + pHandler->endElement("style:list-level-properties"); + pHandler->endElement("text:list-level-style-number"); +} + +UnorderedListLevelStyle::UnorderedListLevelStyle(const WPXPropertyList &xPropList) + : mPropList(xPropList) +{ +} + +void UnorderedListStyle::updateListLevel(const int iLevel, const WPXPropertyList &xPropList) +{ + if (iLevel < 0) + return; + if (!isListLevelDefined(iLevel)) + setListLevel(iLevel, new UnorderedListLevelStyle(xPropList)); +} + +void UnorderedListLevelStyle::write(DocumentHandlerInterface *pHandler, int iLevel) const +{ + WPXString sLevel; + sLevel.sprintf("%i", (iLevel+1)); + TagOpenElement listLevelStyleOpen("text:list-level-style-bullet"); + listLevelStyleOpen.addAttribute("text:level", sLevel); + listLevelStyleOpen.addAttribute("text:style-name", "Bullet_Symbols"); + if (mPropList["text:bullet-char"] && (mPropList["text:bullet-char"]->getStr().len())) + { + // The following is needed because the odf format does not accept bullet chars longer than one character + WPXString::Iter i(mPropList["text:bullet-char"]->getStr()); i.rewind(); + WPXString sEscapedString("."); + if (i.next()) + sEscapedString = WPXString(i(), true); + listLevelStyleOpen.addAttribute("text:bullet-char", sEscapedString); + + } + else + listLevelStyleOpen.addAttribute("text:bullet-char", "."); + listLevelStyleOpen.write(pHandler); + + TagOpenElement stylePropertiesOpen("style:list-level-properties"); + if (mPropList["text:space-before"] && mPropList["text:space-before"]->getDouble() > 0.0f) + stylePropertiesOpen.addAttribute("text:space-before", mPropList["text:space-before"]->getStr()); + if (mPropList["text:min-label-width"] && mPropList["text:min-label-width"]->getDouble() > 0.0f) + stylePropertiesOpen.addAttribute("text:min-label-width", mPropList["text:min-label-width"]->getStr()); + if (mPropList["text:min-label-distance"] && mPropList["text:min-label-distance"]->getDouble() > 0.0f) + stylePropertiesOpen.addAttribute("text:min-label-distance", mPropList["text:min-label-distance"]->getStr()); + stylePropertiesOpen.addAttribute("style:font-name", "OpenSymbol"); + stylePropertiesOpen.write(pHandler); + + pHandler->endElement("style:list-level-properties"); + pHandler->endElement("text:list-level-style-bullet"); +} + +ListStyle::ListStyle(const char *psName, const int iListID) : + Style(psName), + miListID(iListID) +{ + for (int i=0; i<WP6_NUM_LIST_LEVELS; i++) + mppListLevels[i] = NULL; + +} + +ListStyle::~ListStyle() +{ + for (int i=0; i<WP6_NUM_LIST_LEVELS; i++) { + if (mppListLevels[i]) + delete(mppListLevels[i]); + } + +} + +bool ListStyle::isListLevelDefined(int iLevel) const +{ + if (mppListLevels[iLevel] == NULL) + return false; + + return true; +} + +void ListStyle::setListLevel(int iLevel, ListLevelStyle *iListLevelStyle) +{ + // can't uncomment this next line without adding some extra logic. + // figure out which is best: use the initial message, or constantly + // update? + if (mppListLevels[iLevel] == NULL) + mppListLevels[iLevel] = iListLevelStyle; +} + +void ListStyle::write(DocumentHandlerInterface *pHandler) const +{ + TagOpenElement listStyleOpenElement("text:list-style"); + listStyleOpenElement.addAttribute("style:name", getName()); + listStyleOpenElement.write(pHandler); + + for (int i=0; i<WP6_NUM_LIST_LEVELS; i++) { + if (mppListLevels[i] != NULL) + mppListLevels[i]->write(pHandler, i); + } + + pHandler->endElement("text:list-style"); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/ListStyle.hxx b/writerperfect/source/filter/ListStyle.hxx new file mode 100644 index 000000000000..cbba20a8352e --- /dev/null +++ b/writerperfect/source/filter/ListStyle.hxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ListStyle: Stores (and writes) list-based information that is + * needed at the head of an OO document. + * + * Copyright (C) 2002-2003 William Lachance (william.lachance@sympatico.ca) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef _LISTSTYLE_H +#define _LISTSTYLE_H +#include <libwpd/libwpd.h> + +#define WP6_NUM_LIST_LEVELS 8 // see WP6FileStructure.h (we shouldn't need to reference this) + +#include "Style.hxx" +#include "WriterProperties.hxx" +#include "DocumentHandlerInterface.hxx" + +class DocumentElement; + +class ListLevelStyle +{ +public: + virtual ~ListLevelStyle() {}; + virtual void write(DocumentHandlerInterface *pHandler, int iLevel) const = 0; +}; + +class OrderedListLevelStyle : public ListLevelStyle +{ +public: + OrderedListLevelStyle(const WPXPropertyList &xPropList); + void write(DocumentHandlerInterface *pHandler, int iLevel) const; +private: + WPXPropertyList mPropList; +}; + +class UnorderedListLevelStyle : public ListLevelStyle +{ +public: + UnorderedListLevelStyle(const WPXPropertyList &xPropList); + void write(DocumentHandlerInterface *pHandler, int iLevel) const; +private: + WPXPropertyList mPropList; +}; + +class ListStyle : public Style +{ +public: + ListStyle(const char *psName, const int iListID); + virtual ~ListStyle(); + virtual void updateListLevel(const int iLevel, const WPXPropertyList &xPropList) = 0; + virtual void write(DocumentHandlerInterface *pHandler) const; + int getListID() const { return miListID; } + bool isListLevelDefined(int iLevel) const; + +protected: + void setListLevel(int iLevel, ListLevelStyle *iListLevelStyle); + +private: + ListLevelStyle *mppListLevels[WP6_NUM_LIST_LEVELS]; + int miNumListLevels; + const int miListID; +}; + +class OrderedListStyle : public ListStyle +{ +public: + OrderedListStyle(const char *psName, const int iListID) : ListStyle(psName, iListID) {} + void updateListLevel(const int iLevel, const WPXPropertyList &xPropList); +}; + +class UnorderedListStyle : public ListStyle +{ +public: + UnorderedListStyle(const char *psName, const int iListID) : ListStyle(psName, iListID) {} + void updateListLevel(const int iLevel, const WPXPropertyList &xPropList); +}; +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/OdgExporter.cxx b/writerperfect/source/filter/OdgExporter.cxx new file mode 100644 index 000000000000..429fc8d10dd1 --- /dev/null +++ b/writerperfect/source/filter/OdgExporter.cxx @@ -0,0 +1,648 @@ +/* libwpg + * Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) + * Copyright (C) 2006 Fridrich Strba (fridrich.strba@bluewin.ch) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02111-1301 USA + * + * For further information visit http://libwpg.sourceforge.net + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#include "OdgExporter.hxx" +#include "DocumentElement.hxx" +#include "DocumentHandler.hxx" +#include <locale.h> +#include <math.h> +#include <string> + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +OdgExporter::OdgExporter(DocumentHandlerInterface *pHandler): + mpHandler(pHandler), + miGradientIndex(1), + miDashIndex(1), + miGraphicsStyleIndex(1), + mfWidth(0.0), + mfHeight(0.0) +{ +} + +OdgExporter::~OdgExporter() +{ + + for (std::vector<DocumentElement *>::iterator iterBody = mBodyElements.begin(); iterBody != mBodyElements.end(); iterBody++) + { + delete (*iterBody); + (*iterBody) = NULL; + } + + for (std::vector<DocumentElement *>::iterator iterGraphicsAutomaticStyles = mGraphicsAutomaticStyles.begin(); + iterGraphicsAutomaticStyles != mGraphicsAutomaticStyles.end(); iterGraphicsAutomaticStyles++) + { + delete((*iterGraphicsAutomaticStyles)); + } + + for (std::vector<DocumentElement *>::iterator iterGraphicsStrokeDashStyles = mGraphicsStrokeDashStyles.begin(); + iterGraphicsStrokeDashStyles != mGraphicsStrokeDashStyles.end(); iterGraphicsStrokeDashStyles++) + { + delete((*iterGraphicsStrokeDashStyles)); + } + + for (std::vector<DocumentElement *>::iterator iterGraphicsGradientStyles = mGraphicsGradientStyles.begin(); + iterGraphicsGradientStyles != mGraphicsGradientStyles.end(); iterGraphicsGradientStyles++) + { + delete((*iterGraphicsGradientStyles)); + } +} + +void OdgExporter::startGraphics(const ::WPXPropertyList &propList) +{ + miGradientIndex = 1; + miDashIndex = 1; + miGraphicsStyleIndex = 1; + mfWidth = 0.0; + mfHeight = 0.0; + + if (propList["svg:width"]) + mfWidth = propList["svg:width"]->getDouble(); + + if (propList["svg:height"]) + mfHeight = propList["svg:height"]->getDouble(); + + mpHandler->startDocument(); + TagOpenElement tmpOfficeDocumentContent("office:document"); + tmpOfficeDocumentContent.addAttribute("xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0"); + tmpOfficeDocumentContent.addAttribute("xmlns:style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0"); + tmpOfficeDocumentContent.addAttribute("xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0"); + tmpOfficeDocumentContent.addAttribute("xmlns:draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"); + tmpOfficeDocumentContent.addAttribute("xmlns:dc", "http://purl.org/dc/elements/1.1/"); + tmpOfficeDocumentContent.addAttribute("xmlns:svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"); + tmpOfficeDocumentContent.addAttribute("xmlns:fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"); + tmpOfficeDocumentContent.addAttribute("xmlns:config", "urn:oasis:names:tc:opendocument:xmlns:config:1.0"); + tmpOfficeDocumentContent.addAttribute("xmlns:ooo", "http://openoffice.org/2004/office"); + tmpOfficeDocumentContent.addAttribute("office:version", "1.0"); + tmpOfficeDocumentContent.addAttribute("office:mimetype", "application/vnd.oasis.opendocument.graphics"); + tmpOfficeDocumentContent.write(mpHandler); + + TagOpenElement("office:settings").write(mpHandler); + + TagOpenElement configItemSetOpenElement("config:config-item-set"); + configItemSetOpenElement.addAttribute("config:name", "ooo:view-settings"); + configItemSetOpenElement.write(mpHandler); + + TagOpenElement configItemOpenElement("config:config-item"); + + configItemOpenElement.addAttribute("config:name", "VisibleAreaTop"); + configItemOpenElement.addAttribute("config:type", "int"); + configItemOpenElement.write(mpHandler); + mpHandler->characters("0"); + mpHandler->endElement("config:config-item"); + + configItemOpenElement.addAttribute("config:name", "VisibleAreaLeft"); + configItemOpenElement.addAttribute("config:type", "int"); + configItemOpenElement.write(mpHandler); + mpHandler->characters("0"); + mpHandler->endElement("config:config-item"); + + configItemOpenElement.addAttribute("config:name", "VisibleAreaWidth"); + configItemOpenElement.addAttribute("config:type", "int"); + configItemOpenElement.write(mpHandler); + WPXString sWidth; sWidth.sprintf("%li", (unsigned long)(2540 * mfWidth)); + mpHandler->characters(sWidth); + mpHandler->endElement("config:config-item"); + + configItemOpenElement.addAttribute("config:name", "VisibleAreaHeight"); + configItemOpenElement.addAttribute("config:type", "int"); + configItemOpenElement.write(mpHandler); + WPXString sHeight; sHeight.sprintf("%li", (unsigned long)(2540 * mfHeight)); + mpHandler->characters(sHeight); + mpHandler->endElement("config:config-item"); + + mpHandler->endElement("config:config-item-set"); + + mpHandler->endElement("office:settings"); +} + +void OdgExporter::endGraphics() +{ + TagOpenElement("office:styles").write(mpHandler); + + for (std::vector<DocumentElement *>::const_iterator iterGraphicsStrokeDashStyles = mGraphicsStrokeDashStyles.begin(); + iterGraphicsStrokeDashStyles != mGraphicsStrokeDashStyles.end(); iterGraphicsStrokeDashStyles++) + { + (*iterGraphicsStrokeDashStyles)->write(mpHandler); + } + + for (std::vector<DocumentElement *>::const_iterator iterGraphicsGradientStyles = mGraphicsGradientStyles.begin(); + iterGraphicsGradientStyles != mGraphicsGradientStyles.end(); iterGraphicsGradientStyles++) + { + (*iterGraphicsGradientStyles)->write(mpHandler); + } + + mpHandler->endElement("office:styles"); + + TagOpenElement("office:automatic-styles").write(mpHandler); + + // writing out the graphics automatic styles + for (std::vector<DocumentElement *>::iterator iterGraphicsAutomaticStyles = mGraphicsAutomaticStyles.begin(); + iterGraphicsAutomaticStyles != mGraphicsAutomaticStyles.end(); iterGraphicsAutomaticStyles++) + { + (*iterGraphicsAutomaticStyles)->write(mpHandler); + } + + TagOpenElement tmpStylePageLayoutOpenElement("style:page-layout"); + tmpStylePageLayoutOpenElement.addAttribute("style:name", "PM0"); + tmpStylePageLayoutOpenElement.write(mpHandler); + + TagOpenElement tmpStylePageLayoutPropertiesOpenElement("style:page-layout-properties"); + tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:margin-top", "0in"); + tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:margin-bottom", "0in"); + tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:margin-left", "0in"); + tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:margin-right", "0in"); + WPXString sValue; + sValue = doubleToString(mfWidth); sValue.append("in"); + tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:page-width", sValue); + sValue = doubleToString(mfHeight); sValue.append("in"); + tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:page-height", sValue); + tmpStylePageLayoutPropertiesOpenElement.addAttribute("style:print-orientation", "portrait"); + tmpStylePageLayoutPropertiesOpenElement.write(mpHandler); + + mpHandler->endElement("style:page-layout-properties"); + + mpHandler->endElement("style:page-layout"); + + TagOpenElement tmpStyleStyleOpenElement("style:style"); + tmpStyleStyleOpenElement.addAttribute("style:name", "dp1"); + tmpStyleStyleOpenElement.addAttribute("style:family", "drawing-page"); + tmpStyleStyleOpenElement.write(mpHandler); + + TagOpenElement tmpStyleDrawingPagePropertiesOpenElement("style:drawing-page-properties"); + // tmpStyleDrawingPagePropertiesOpenElement.addAttribute("draw:background-size", "border"); + tmpStyleDrawingPagePropertiesOpenElement.addAttribute("draw:fill", "none"); + tmpStyleDrawingPagePropertiesOpenElement.write(mpHandler); + + mpHandler->endElement("style:drawing-page-properties"); + + mpHandler->endElement("style:style"); + + mpHandler->endElement("office:automatic-styles"); + + TagOpenElement("office:master-styles").write(mpHandler); + + TagOpenElement tmpStyleMasterPageOpenElement("style:master-page"); + tmpStyleMasterPageOpenElement.addAttribute("style:name", "Default"); + tmpStyleMasterPageOpenElement.addAttribute("style:page-layout-name", "PM0"); + tmpStyleMasterPageOpenElement.addAttribute("draw:style-name", "dp1"); + tmpStyleMasterPageOpenElement.write(mpHandler); + + mpHandler->endElement("style:master-page"); + + mpHandler->endElement("office:master-styles"); + + TagOpenElement("office:body").write(mpHandler); + + TagOpenElement("office:drawing").write(mpHandler); + + TagOpenElement tmpDrawPageOpenElement("draw:page"); + tmpDrawPageOpenElement.addAttribute("draw:name", "page1"); + tmpDrawPageOpenElement.addAttribute("draw:style-name", "dp1"); + tmpDrawPageOpenElement.addAttribute("draw:master-page-name", "Default"); + tmpDrawPageOpenElement.write(mpHandler); + + for (std::vector<DocumentElement *>::const_iterator bodyIter = mBodyElements.begin(); + bodyIter != mBodyElements.end(); bodyIter++) + { + (*bodyIter)->write(mpHandler); + } + + mpHandler->endElement("draw:page"); + mpHandler->endElement("office:drawing"); + mpHandler->endElement("office:body"); + + mpHandler->endElement("office:document"); + + mpHandler->endDocument(); +} + +void OdgExporter::setStyle(const ::WPXPropertyList & propList, const ::WPXPropertyListVector& gradient) +{ + mxStyle = propList; + mxGradient = gradient; +} + +void OdgExporter::startLayer(const ::WPXPropertyList & /* propList */) +{ +} + +void OdgExporter::endLayer() +{ +} + +void OdgExporter::drawRectangle(const ::WPXPropertyList &propList) +{ + writeGraphicsStyle(); + TagOpenElement *pDrawRectElement = new TagOpenElement("draw:rect"); + WPXString sValue; + sValue.sprintf("gr%i", miGraphicsStyleIndex-1); + pDrawRectElement->addAttribute("draw:style-name", sValue); + pDrawRectElement->addAttribute("svg:x", propList["svg:x"]->getStr()); + pDrawRectElement->addAttribute("svg:y", propList["svg:y"]->getStr()); + pDrawRectElement->addAttribute("svg:width", propList["svg:width"]->getStr()); + pDrawRectElement->addAttribute("svg:height", propList["svg:height"]->getStr()); + // FIXME: what to do when rx != ry ? + if (propList["svg:rx"]) + pDrawRectElement->addAttribute("draw:corner-radius", propList["svg:rx"]->getStr()); + else + pDrawRectElement->addAttribute("draw:corner-radius", "0.0000in"); + mBodyElements.push_back(pDrawRectElement); + mBodyElements.push_back(new TagCloseElement("draw:rect")); +} + +void OdgExporter::drawEllipse(const ::WPXPropertyList &propList) +{ + writeGraphicsStyle(); + TagOpenElement *pDrawEllipseElement = new TagOpenElement("draw:ellipse"); + WPXString sValue; + sValue.sprintf("gr%i", miGraphicsStyleIndex-1); + pDrawEllipseElement->addAttribute("draw:style-name", sValue); + sValue = doubleToString(2 * propList["svg:rx"]->getDouble()); sValue.append("in"); + pDrawEllipseElement->addAttribute("svg:width", sValue); + sValue = doubleToString(2 * propList["svg:ry"]->getDouble()); sValue.append("in"); + pDrawEllipseElement->addAttribute("svg:height", sValue); + if (propList["libwpg:rotate"] && propList["libwpg:rotate"]->getDouble() != 0.0) + { + double rotation = propList["libwpg:rotate"]->getDouble(); + while(rotation < -180) + rotation += 360; + while(rotation > 180) + rotation -= 360; + double radrotation = rotation*M_PI/180.0; + double deltax = sqrt(pow(propList["svg:rx"]->getDouble(), 2.0) + + pow(propList["svg:ry"]->getDouble(), 2.0))*cos(atan(propList["svg:ry"]->getDouble()/propList["svg:rx"]->getDouble()) + - radrotation ) - propList["svg:rx"]->getDouble(); + double deltay = sqrt(pow(propList["svg:rx"]->getDouble(), 2.0) + + pow(propList["svg:ry"]->getDouble(), 2.0))*sin(atan(propList["svg:ry"]->getDouble()/propList["svg:rx"]->getDouble()) + - radrotation ) - propList["svg:ry"]->getDouble(); + sValue = "rotate("; sValue.append(doubleToString(radrotation)); sValue.append(") "); + sValue.append("translate("); sValue.append(doubleToString(propList["svg:cx"]->getDouble() - propList["svg:rx"]->getDouble() - deltax)); + sValue.append("in, "); + sValue.append(doubleToString(propList["svg:cy"]->getDouble() - propList["svg:ry"]->getDouble() - deltay)); sValue.append("in)"); + pDrawEllipseElement->addAttribute("draw:transform", sValue); + } + else + { + sValue = doubleToString(propList["svg:cx"]->getDouble()-propList["svg:rx"]->getDouble()); sValue.append("in"); + pDrawEllipseElement->addAttribute("svg:x", sValue); + sValue = doubleToString(propList["svg:cy"]->getDouble()-propList["svg:ry"]->getDouble()); sValue.append("in"); + pDrawEllipseElement->addAttribute("svg:y", sValue); + } + mBodyElements.push_back(pDrawEllipseElement); + mBodyElements.push_back(new TagCloseElement("draw:ellipse")); +} + +void OdgExporter::drawPolyline(const ::WPXPropertyListVector& vertices) +{ + drawPolySomething(vertices, false); +} + +void OdgExporter::drawPolygon(const ::WPXPropertyListVector& vertices) +{ + drawPolySomething(vertices, true); +} + +void OdgExporter::drawPolySomething(const ::WPXPropertyListVector& vertices, bool isClosed) +{ + if(vertices.count() < 2) + return; + + if(vertices.count() == 2) + { + writeGraphicsStyle(); + TagOpenElement *pDrawLineElement = new TagOpenElement("draw:line"); + WPXString sValue; + sValue.sprintf("gr%i", miGraphicsStyleIndex-1); + pDrawLineElement->addAttribute("draw:style-name", sValue); + pDrawLineElement->addAttribute("draw:text-style-name", "P1"); + pDrawLineElement->addAttribute("draw:layer", "layout"); + pDrawLineElement->addAttribute("svg:x1", vertices[0]["svg:x"]->getStr()); + pDrawLineElement->addAttribute("svg:y1", vertices[0]["svg:y"]->getStr()); + pDrawLineElement->addAttribute("svg:x2", vertices[1]["svg:x"]->getStr()); + pDrawLineElement->addAttribute("svg:y2", vertices[1]["svg:y"]->getStr()); + mBodyElements.push_back(pDrawLineElement); + mBodyElements.push_back(new TagCloseElement("draw:line")); + } + else + { + ::WPXPropertyListVector path; + ::WPXPropertyList element; + + for (unsigned long ii = 0; ii < vertices.count(); ii++) + { + element = vertices[ii]; + if (ii == 0) + element.insert("libwpg:path-action", "M"); + else + element.insert("libwpg:path-action", "L"); + path.append(element); + element.clear(); + } + if (isClosed) + { + element.insert("libwpg:path-action", "Z"); + path.append(element); + } + drawPath(path); + } +} + +void OdgExporter::drawPath(const WPXPropertyListVector& path) +{ + if(path.count() == 0) + return; + + // try to find the bounding box + // this is simple convex hull technique, the bounding box might not be + // accurate but that should be enough for this purpose + double px = path[0]["svg:x"]->getDouble(); + double py = path[0]["svg:y"]->getDouble(); + double qx = path[0]["svg:x"]->getDouble(); + double qy = path[0]["svg:y"]->getDouble(); + for(unsigned k = 0; k < path.count(); k++) + { + if (!path[k]["svg:x"] || !path[k]["svg:y"]) + continue; + px = (px > path[k]["svg:x"]->getDouble()) ? path[k]["svg:x"]->getDouble() : px; + py = (py > path[k]["svg:y"]->getDouble()) ? path[k]["svg:y"]->getDouble() : py; + qx = (qx < path[k]["svg:x"]->getDouble()) ? path[k]["svg:x"]->getDouble() : qx; + qy = (qy < path[k]["svg:y"]->getDouble()) ? path[k]["svg:y"]->getDouble() : qy; + if(path[k]["libwpg:path-action"]->getStr() == "C") + { + px = (px > path[k]["svg:x1"]->getDouble()) ? path[k]["svg:x1"]->getDouble() : px; + py = (py > path[k]["svg:y1"]->getDouble()) ? path[k]["svg:y1"]->getDouble() : py; + qx = (qx < path[k]["svg:x1"]->getDouble()) ? path[k]["svg:x1"]->getDouble() : qx; + qy = (qy < path[k]["svg:y1"]->getDouble()) ? path[k]["svg:y1"]->getDouble() : qy; + px = (px > path[k]["svg:x2"]->getDouble()) ? path[k]["svg:x2"]->getDouble() : px; + py = (py > path[k]["svg:y2"]->getDouble()) ? path[k]["svg:y2"]->getDouble() : py; + qx = (qx < path[k]["svg:x2"]->getDouble()) ? path[k]["svg:x2"]->getDouble() : qx; + qy = (qy < path[k]["svg:y2"]->getDouble()) ? path[k]["svg:y2"]->getDouble() : qy; + } + if(path[k]["libwpg:path-action"]->getStr() == "A") + { + px = (px > path[k]["svg:x"]->getDouble()-2*path[k]["svg:rx"]->getDouble()) ? path[k]["svg:x"]->getDouble()-2*path[k]["svg:rx"]->getDouble() : px; + py = (py > path[k]["svg:y"]->getDouble()-2*path[k]["svg:ry"]->getDouble()) ? path[k]["svg:y"]->getDouble()-2*path[k]["svg:ry"]->getDouble() : py; + qx = (qx < path[k]["svg:x"]->getDouble()+2*path[k]["svg:rx"]->getDouble()) ? path[k]["svg:x"]->getDouble()+2*path[k]["svg:rx"]->getDouble() : qx; + qy = (qy < path[k]["svg:y"]->getDouble()+2*path[k]["svg:ry"]->getDouble()) ? path[k]["svg:y"]->getDouble()+2*path[k]["svg:ry"]->getDouble() : qy; + } + } + double vw = qx - px; + double vh = qy - py; + + writeGraphicsStyle(); + + TagOpenElement *pDrawPathElement = new TagOpenElement("draw:path"); + WPXString sValue; + sValue.sprintf("gr%i", miGraphicsStyleIndex-1); + pDrawPathElement->addAttribute("draw:style-name", sValue); + pDrawPathElement->addAttribute("draw:text-style-name", "P1"); + pDrawPathElement->addAttribute("draw:layer", "layout"); + sValue = doubleToString(px); sValue.append("in"); + pDrawPathElement->addAttribute("svg:x", sValue); + sValue = doubleToString(py); sValue.append("in"); + pDrawPathElement->addAttribute("svg:y", sValue); + sValue = doubleToString(vw); sValue.append("in"); + pDrawPathElement->addAttribute("svg:width", sValue); + sValue = doubleToString(vh); sValue.append("in"); + pDrawPathElement->addAttribute("svg:height", sValue); + sValue.sprintf("%i %i %i %i", 0, 0, (unsigned)(vw*2540), (unsigned)(vh*2540)); + pDrawPathElement->addAttribute("svg:viewBox", sValue); + + sValue.clear(); + for(unsigned i = 0; i < path.count(); i++) + { + WPXString sElement; + if (path[i]["libwpg:path-action"]->getStr() == "M") + { + // 2540 is 2.54*1000, 2.54 in = 1 inch + sElement.sprintf("M%i %i", (unsigned)((path[i]["svg:x"]->getDouble()-px)*2540), + (unsigned)((path[i]["svg:y"]->getDouble()-py)*2540)); + sValue.append(sElement); + } + else if (path[i]["libwpg:path-action"]->getStr() == "L") + { + sElement.sprintf("L%i %i", (unsigned)((path[i]["svg:x"]->getDouble()-px)*2540), + (unsigned)((path[i]["svg:y"]->getDouble()-py)*2540)); + sValue.append(sElement); + } + else if (path[i]["libwpg:path-action"]->getStr() == "C") + { + sElement.sprintf("C%i %i %i %i %i %i", (unsigned)((path[i]["svg:x1"]->getDouble()-px)*2540), + (int)((path[i]["svg:y1"]->getDouble()-py)*2540), (unsigned)((path[i]["svg:x2"]->getDouble()-px)*2540), + (int)((path[i]["svg:y2"]->getDouble()-py)*2540), (unsigned)((path[i]["svg:x"]->getDouble()-px)*2540), + (unsigned)((path[i]["svg:y"]->getDouble()-py)*2540)); + sValue.append(sElement); + } + else if (path[i]["libwpg:path-action"]->getStr() == "A") + { + sElement.sprintf("A%i %i %i %i %i %i %i", (unsigned)((path[i]["svg:rx"]->getDouble())*2540), + (int)((path[i]["svg:ry"]->getDouble())*2540), (path[i]["libwpg:rotate"] ? path[i]["libwpg:rotate"]->getInt() : 0), + 0, 0, (unsigned)((path[i]["svg:x"]->getDouble()-px)*2540), (unsigned)((path[i]["svg:y"]->getDouble()-py)*2540)); + sValue.append(sElement); + } + else if (path[i]["libwpg:path-action"]->getStr() == "Z" && i >= (path.count() - 1)) + sValue.append(" Z"); + } + pDrawPathElement->addAttribute("svg:d", sValue); + mBodyElements.push_back(pDrawPathElement); + mBodyElements.push_back(new TagCloseElement("draw:path")); +} + +void OdgExporter::drawGraphicObject(const ::WPXPropertyList &propList, const ::WPXBinaryData& binaryData) +{ + if (!propList["libwpg:mime-type"] && propList["libwpg:mime-type"]->getStr().len() <= 0) + return; + TagOpenElement *pDrawFrameElement = new TagOpenElement("draw:frame"); + + + WPXString sValue; + if (propList["svg:x"]) + pDrawFrameElement->addAttribute("svg:x", propList["svg:x"]->getStr()); + if (propList["svg:y"]) + pDrawFrameElement->addAttribute("svg:y", propList["svg:y"]->getStr()); + if (propList["svg:height"]) + pDrawFrameElement->addAttribute("svg:height", propList["svg:height"]->getStr()); + if (propList["svg:width"]) + pDrawFrameElement->addAttribute("svg:width", propList["svg:width"]->getStr()); + mBodyElements.push_back(pDrawFrameElement); + + mBodyElements.push_back(new TagOpenElement("draw:image")); + + mBodyElements.push_back(new TagOpenElement("office:binary-data")); + + ::WPXString base64Binary = binaryData.getBase64Data(); + mBodyElements.push_back(new CharDataElement(base64Binary.cstr())); + + mBodyElements.push_back(new TagCloseElement("office:binary-data")); + + mBodyElements.push_back(new TagCloseElement("draw:image")); + + mBodyElements.push_back(new TagCloseElement("draw:frame")); +} + +void OdgExporter::writeGraphicsStyle() +{ +#if 0 + if(mxStyle["libwpg:stroke-solid"] && !mxStyle["libwpg:stroke-solid"]->getInt() && (mxDashArray.count() >=2 ) ) + { + // ODG only supports dashes with the same length of spaces inbetween + // here we take the first space and assume everything else the same + // note that dash length is written in percentage ????????????????? + double distance = mxDashArray.at(1); + TagOpenElement *pDrawStrokeDashElement = new TagOpenElement("draw:stroke-dash"); + pDrawStrokeDashElement->addAttribute("draw:style", "rect"); + WPXString sValue; + sValue.sprintf("Dash_%i", miDashIndex++); + pDrawStrokeDashElement->addAttribute("draw:name", sValue); + sValue = doubleToString(distance); sValue.append("in"); + pDrawStrokeDashElement->addAttribute("draw:distance", sValue); + WPXString sName; + // We have to find out how to do this intelligently, since the ODF is allowing only + // two pairs draw:dots1 draw:dots1-length and draw:dots2 draw:dots2-length + for(unsigned i = 0; i < mxDashArray.count()/2 && i < 2; i++) + { + sName.sprintf("draw:dots%i", i+1); + pDrawStrokeDashElement->addAttribute(sName.cstr(), "1"); + sName.sprintf("draw:dots%i-length", i+1); + sValue = doubleToString(mxDashArray.at(i*2)); sValue.append("in"); + pDrawStrokeDashElement->addAttribute(sName.cstr(), sValue); + } + mGraphicsStrokeDashStyles.push_back(pDrawStrokeDashElement); + mGraphicsStrokeDashStyles.push_back(new TagCloseElement("draw:stroke-dash")); + } +#endif + if(mxStyle["draw:fill"] && mxStyle["draw:fill"]->getStr() == "gradient" && mxGradient.count() >= 2) + { + TagOpenElement *pDrawGradientElement = new TagOpenElement("draw:gradient"); + pDrawGradientElement->addAttribute("draw:style", "linear"); + WPXString sValue; + sValue.sprintf("Gradient_%i", miGradientIndex++); + pDrawGradientElement->addAttribute("draw:name", sValue); + + // ODG angle unit is 0.1 degree + double angle = mxStyle["draw:angle"] ? -mxStyle["draw:angle"]->getDouble() : 0.0; + while(angle < 0) + angle += 360; + while(angle > 360) + angle -= 360; + + sValue.sprintf("%i", (unsigned)(angle*10)); + pDrawGradientElement->addAttribute("draw:angle", sValue); + + pDrawGradientElement->addAttribute("draw:start-color", mxGradient[0]["svg:stop-color"]->getStr().cstr()); + pDrawGradientElement->addAttribute("draw:end-color", mxGradient[1]["svg:stop-color"]->getStr().cstr()); + pDrawGradientElement->addAttribute("draw:start-intensity", "100%"); + pDrawGradientElement->addAttribute("draw:end-intensity", "100%"); + pDrawGradientElement->addAttribute("draw:border", "0%"); + mGraphicsGradientStyles.push_back(pDrawGradientElement); + mGraphicsGradientStyles.push_back(new TagCloseElement("draw:gradient")); + } + + TagOpenElement *pStyleStyleElement = new TagOpenElement("style:style"); + WPXString sValue; + sValue.sprintf("gr%i", miGraphicsStyleIndex); + pStyleStyleElement->addAttribute("style:name", sValue); + pStyleStyleElement->addAttribute("style:family", "graphic"); + pStyleStyleElement->addAttribute("style:parent-style-name", "standard"); + mGraphicsAutomaticStyles.push_back(pStyleStyleElement); + + TagOpenElement *pStyleGraphicsPropertiesElement = new TagOpenElement("style:graphic-properties"); + + if(!(mxStyle["draw:stroke"] && mxStyle["draw:stroke"]->getStr() == "none") && mxStyle["svg:stroke-width"] && mxStyle["svg:stroke-width"]->getDouble() > 0.0) + { + if (mxStyle["svg:stroke-width"]) + pStyleGraphicsPropertiesElement->addAttribute("svg:stroke-width", mxStyle["svg:stroke-width"]->getStr()); + + if (mxStyle["svg:stroke-color"]) + pStyleGraphicsPropertiesElement->addAttribute("svg:stroke-color", mxStyle["svg:stroke-color"]->getStr()); + if (mxStyle["svg:stroke-opacity"] && mxStyle["svg:stroke-opacity"]->getDouble() != 1.0) + pStyleGraphicsPropertiesElement->addAttribute("svg:stroke-opacity", mxStyle["svg:stroke-opacity"]->getStr()); + + + if(mxStyle["libwpg:stroke-solid"] && mxStyle["libwpg:stroke-solid"]->getInt()) + pStyleGraphicsPropertiesElement->addAttribute("draw:stroke", "solid"); +#if 0 + else + { + pStyleGraphicsPropertiesElement->addAttribute("draw:stroke", "dash"); + sValue.sprintf("Dash_%i", miDashIndex-1); + pStyleGraphicsPropertiesElement->addAttribute("draw:stroke-dash", sValue); + } +#endif + } + else + pStyleGraphicsPropertiesElement->addAttribute("draw:stroke", "none"); + + if(mxStyle["draw:fill"] && mxStyle["draw:fill"]->getStr() == "none") + pStyleGraphicsPropertiesElement->addAttribute("draw:fill", "none"); + + if(mxStyle["draw:fill"] && mxStyle["draw:fill"]->getStr() == "solid") + { + pStyleGraphicsPropertiesElement->addAttribute("draw:fill", "solid"); + if (mxStyle["draw:fill-color"]) + pStyleGraphicsPropertiesElement->addAttribute("draw:fill-color", mxStyle["draw:fill-color"]->getStr()); + if (mxStyle["draw:opacity"] && mxStyle["draw:opacity"]->getDouble() != 1.0) + pStyleGraphicsPropertiesElement->addAttribute("draw:opacity", mxStyle["draw:opacity"]->getStr()); + } + + if(mxStyle["draw:fill"] && mxStyle["draw:fill"]->getStr() == "gradient") + { + if (mxGradient.count() >= 2) + { + pStyleGraphicsPropertiesElement->addAttribute("draw:fill", "gradient"); + sValue.sprintf("Gradient_%i", miGradientIndex-1); + pStyleGraphicsPropertiesElement->addAttribute("draw:fill-gradient-name", sValue); + } + else + pStyleGraphicsPropertiesElement->addAttribute("draw:fill", "none"); + } + + mGraphicsAutomaticStyles.push_back(pStyleGraphicsPropertiesElement); + mGraphicsAutomaticStyles.push_back(new TagCloseElement("style:graphic-properties")); + + mGraphicsAutomaticStyles.push_back(new TagCloseElement("style:style")); + miGraphicsStyleIndex++; +} + +WPXString OdgExporter::doubleToString(const double value) +{ + WPXString tempString; + tempString.sprintf("%.4f", value); + std::string decimalPoint(localeconv()->decimal_point); + if ((decimalPoint.size() == 0) || (decimalPoint == ".")) + return tempString; + std::string stringValue(tempString.cstr()); + if (!stringValue.empty()) + { + std::string::size_type pos; + while ((pos = stringValue.find(decimalPoint)) != std::string::npos) + stringValue.replace(pos,decimalPoint.size(),"."); + } + return WPXString(stringValue.c_str()); +} diff --git a/writerperfect/source/filter/OdgExporter.hxx b/writerperfect/source/filter/OdgExporter.hxx new file mode 100644 index 000000000000..948d3b87374c --- /dev/null +++ b/writerperfect/source/filter/OdgExporter.hxx @@ -0,0 +1,90 @@ +/* libwpg + * Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02111-1301 USA + * + * For further information visit http://libwpg.sourceforge.net + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef __ODGEXPORTER_HXX__ +#define __ODGEXPORTER_HXX__ + +#include <iostream> +#include <sstream> +#include <string> + +#include <libwpd/libwpd.h> +#include <libwpg/libwpg.h> +#include "DocumentElement.hxx" +#include "DocumentHandler.hxx" +#include "FilterInternal.hxx" + +class OdgExporter : public libwpg::WPGPaintInterface { +public: + OdgExporter(DocumentHandlerInterface *pHandler); + ~OdgExporter(); + + void startGraphics(const ::WPXPropertyList &propList); + void endGraphics(); + void startLayer(const ::WPXPropertyList &propList); + void endLayer(); + void startEmbeddedGraphics(const ::WPXPropertyList& /*propList*/) {} + void endEmbeddedGraphics() {} + + void setStyle(const ::WPXPropertyList &propList, const ::WPXPropertyListVector& gradient); + + void drawRectangle(const ::WPXPropertyList &propList); + void drawEllipse(const ::WPXPropertyList &propList); + void drawPolyline(const ::WPXPropertyListVector& vertices); + void drawPolygon(const ::WPXPropertyListVector& vertices); + void drawPath(const ::WPXPropertyListVector& path); + void drawGraphicObject(const ::WPXPropertyList &propList, const ::WPXBinaryData& binaryData); + void startTextObject(const ::WPXPropertyList & /*propList*/, const ::WPXPropertyListVector &/*path*/) {} + void endTextObject() {} + void startTextLine(const ::WPXPropertyList & /*propList*/) {} + void endTextLine() {} + void startTextSpan(const ::WPXPropertyList & /*propList*/) {} + void endTextSpan() {} + void insertText(const ::WPXString & /*str*/) {} + +private: + void writeGraphicsStyle(); + WPXString doubleToString(const double value); + void drawPolySomething(const ::WPXPropertyListVector& vertices, bool isClosed); + + // body elements + std::vector <DocumentElement *> mBodyElements; + + // graphics styles + std::vector<DocumentElement *> mGraphicsStrokeDashStyles; + std::vector<DocumentElement *> mGraphicsGradientStyles; + std::vector<DocumentElement *> mGraphicsAutomaticStyles; + + DocumentHandlerInterface *mpHandler; + + ::WPXPropertyList mxStyle; + ::WPXPropertyListVector mxGradient; + int miGradientIndex; + int miDashIndex; + int miGraphicsStyleIndex; + double mfWidth; + double mfHeight; +}; + +#endif // __ODGEXPORTER_HXX__ diff --git a/writerperfect/source/filter/PageSpan.cxx b/writerperfect/source/filter/PageSpan.cxx new file mode 100644 index 000000000000..7ff4d1ce6977 --- /dev/null +++ b/writerperfect/source/filter/PageSpan.cxx @@ -0,0 +1,276 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* SectionStyle: Stores (and writes) section-based information (e.g.: a column + * break needs a new section) that is needed at the head of an OO document and + * is referenced throughout the entire document + * + * Copyright (C) 2002-2003 William Lachance (william.lachance@sympatico.ca) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#include "FilterInternal.hxx" +#include "PageSpan.hxx" +#include "DocumentElement.hxx" +#include "DocumentHandler.hxx" + +PageSpan::PageSpan(const WPXPropertyList &xPropList) : + mxPropList(xPropList), + mpHeaderContent(NULL), + mpFooterContent(NULL), + mpHeaderLeftContent(NULL), + mpFooterLeftContent(NULL) +{ +} + +namespace { + typedef std::vector<DocumentElement *>::iterator DEVIter; +} + +PageSpan::~PageSpan() +{ + if (mpHeaderContent) + { + for (DEVIter iterHeaderContent = mpHeaderContent->begin(); + iterHeaderContent != mpHeaderContent->end(); + iterHeaderContent++) + delete(*iterHeaderContent); + delete mpHeaderContent; + } + + if (mpHeaderLeftContent) + { + for (DEVIter iterHeaderLeftContent = mpHeaderLeftContent->begin(); + iterHeaderLeftContent != mpHeaderLeftContent->end(); + iterHeaderLeftContent++) + delete(*iterHeaderLeftContent); + delete mpHeaderLeftContent; + } + + if (mpFooterContent) + { + for (DEVIter iterFooterContent = mpFooterContent->begin(); + iterFooterContent != mpFooterContent->end(); + iterFooterContent++) + delete(*iterFooterContent); + delete mpFooterContent; + } + + if (mpFooterLeftContent) + { + for (DEVIter iterFooterLeftContent = mpFooterLeftContent->begin(); + iterFooterLeftContent != mpFooterLeftContent->end(); + iterFooterLeftContent++) + delete(*iterFooterLeftContent); + delete mpFooterLeftContent; + } +} + +int PageSpan::getSpan() const +{ + if (mxPropList["libwpd:num-pages"]) + return mxPropList["libwpd:num-pages"]->getInt(); + + return 0; // should never happen +} + +double PageSpan::getMarginLeft() const +{ + if (mxPropList["fo:margin-left"]) + return mxPropList["fo:margin-left"]->getDouble(); + + return 0.0; +} + +double PageSpan::getMarginRight() const +{ + if (mxPropList["fo:margin-right"]) + return mxPropList["fo:margin-right"]->getDouble(); + + return 0.0; +} + +void PageSpan::setHeaderContent(std::vector<DocumentElement *> * pHeaderContent) +{ + if (mpHeaderContent) + { + for (DEVIter iterHeaderContent = mpHeaderContent->begin(); + iterHeaderContent != mpHeaderContent->end(); + iterHeaderContent++) + delete(*iterHeaderContent); + delete mpHeaderContent; + } + + mpHeaderContent = pHeaderContent; +} + +void PageSpan::setFooterContent(std::vector<DocumentElement *> * pFooterContent) +{ + if (mpFooterContent) + { + for (DEVIter iterFooterContent = mpFooterContent->begin(); + iterFooterContent != mpFooterContent->end(); + iterFooterContent++) + delete(*iterFooterContent); + delete mpFooterContent; + } + + mpFooterContent = pFooterContent; +} + +void PageSpan::setHeaderLeftContent(std::vector<DocumentElement *> * pHeaderContent) +{ + if (mpHeaderLeftContent) + { + for (DEVIter iterHeaderLeftContent = mpHeaderLeftContent->begin(); + iterHeaderLeftContent != mpHeaderLeftContent->end(); + iterHeaderLeftContent++) + delete(*iterHeaderLeftContent); + delete mpHeaderLeftContent; + } + + mpHeaderLeftContent = pHeaderContent; +} + +void PageSpan::setFooterLeftContent(std::vector<DocumentElement *> * pFooterContent) +{ + if (mpFooterLeftContent) + { + for (DEVIter iterFooterLeftContent = mpFooterLeftContent->begin(); + iterFooterLeftContent != mpFooterLeftContent->end(); + iterFooterLeftContent++) + delete(*iterFooterLeftContent); + delete mpFooterLeftContent; + } + + mpFooterLeftContent = pFooterContent; +} + +void PageSpan::writePageLayout(const int iNum, DocumentHandlerInterface *pHandler) const +{ + WPXPropertyList propList; + + WPXString sPageLayoutName; + sPageLayoutName.sprintf("PM%i", iNum+2); + propList.insert("style:name", sPageLayoutName); + pHandler->startElement("style:page-layout", propList); + + WPXPropertyList tempPropList = mxPropList; + if (!tempPropList["style:writing-mode"]) + tempPropList.insert("style:writing-mode", WPXString("lr-tb")); + if (!tempPropList["style:footnote-max-height"]) + tempPropList.insert("style:footnote-max-height", WPXString("0in")); + pHandler->startElement("style:page-layout-properties", tempPropList); + + WPXPropertyList footnoteSepPropList; + footnoteSepPropList.insert("style:width", WPXString("0.0071in")); + footnoteSepPropList.insert("style:distance-before-sep", WPXString("0.0398in")); + footnoteSepPropList.insert("style:distance-after-sep", WPXString("0.0398in")); + footnoteSepPropList.insert("style:adjustment", WPXString("left")); + footnoteSepPropList.insert("style:rel-width", WPXString("25%")); + footnoteSepPropList.insert("style:color", WPXString("#000000")); + pHandler->startElement("style:footnote-sep", footnoteSepPropList); + + pHandler->endElement("style:footnote-sep"); + pHandler->endElement("style:page-layout-properties"); + pHandler->endElement("style:page-layout"); +} + +void PageSpan::writeMasterPages(const int iStartingNum, const int iPageLayoutNum, const bool bLastPageSpan, + DocumentHandlerInterface *pHandler) const +{ + int iSpan = 0; + (bLastPageSpan) ? iSpan = 1 : iSpan = getSpan(); + + for (int i=iStartingNum; i<(iStartingNum+iSpan); i++) + { + TagOpenElement masterPageOpen("style:master-page"); + WPXString sMasterPageName, sMasterPageDisplayName; + sMasterPageName.sprintf("Page_Style_%i", i); + sMasterPageDisplayName.sprintf("Page Style %i", i); + WPXString sPageLayoutName; + WPXPropertyList propList; + sPageLayoutName.sprintf("PM%i", iPageLayoutNum+2); + propList.insert("style:name", sMasterPageName); + propList.insert("style:display-name", sMasterPageDisplayName); + propList.insert("style:page-layout-name", sPageLayoutName); + if (!bLastPageSpan) + { + WPXString sNextMasterPageName; + sNextMasterPageName.sprintf("Page_Style_%i", (i+1)); + propList.insert("style:next-style-name", sNextMasterPageName); + } + pHandler->startElement("style:master-page", propList); + + if (mpHeaderContent) + { + _writeHeaderFooter("style:header", *mpHeaderContent, pHandler); + pHandler->endElement("style:header"); + if (mpHeaderLeftContent) + { + _writeHeaderFooter("style:header-left", *mpHeaderLeftContent, pHandler); + pHandler->endElement("style:header-left"); + } + } + else if (mpHeaderLeftContent) + { + TagOpenElement("style:header").write(pHandler); + pHandler->endElement("style:header"); + _writeHeaderFooter("style:header-left", *mpHeaderLeftContent, pHandler); + pHandler->endElement("style:header-left"); + } + + if (mpFooterContent) + { + _writeHeaderFooter("style:footer", *mpFooterContent, pHandler); + pHandler->endElement("style:footer"); + if (mpFooterLeftContent) + { + _writeHeaderFooter("style:footer-left", *mpFooterLeftContent, pHandler); + pHandler->endElement("style:footer-left"); + } + } + else if (mpFooterLeftContent) + { + TagOpenElement("style:footer").write(pHandler); + pHandler->endElement("style:footer"); + _writeHeaderFooter("style:footer-left", *mpFooterLeftContent, pHandler); + pHandler->endElement("style:footer-left"); + } + + pHandler->endElement("style:master-page"); + } + +} + +void PageSpan::_writeHeaderFooter(const char *headerFooterTagName, + const std::vector<DocumentElement *> & headerFooterContent, + DocumentHandlerInterface *pHandler) const +{ + TagOpenElement headerFooterOpen(headerFooterTagName); + headerFooterOpen.write(pHandler); + for (std::vector<DocumentElement *>::const_iterator iter = headerFooterContent.begin(); + iter != headerFooterContent.end(); + ++iter) { + (*iter)->write(pHandler); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/PageSpan.hxx b/writerperfect/source/filter/PageSpan.hxx new file mode 100644 index 000000000000..92eba26fe4a4 --- /dev/null +++ b/writerperfect/source/filter/PageSpan.hxx @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* PageSpan: Stores (and writes) page-based information (e.g.: margins, + * headers/footers) + * + * Copyright (C) 2002-2004 William Lachance (william.lachance@sympatico.ca) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef _PAGESPAN_H +#define _PAGESPAN_H +#include <libwpd/libwpd.h> +#include <vector> + +class DocumentElement; +class DocumentHandlerInterface; + +class PageSpan +{ +public: + PageSpan(const WPXPropertyList &xPropList); + virtual ~PageSpan(); + void writePageLayout(const int iNum, DocumentHandlerInterface *pHandler) const; + void writeMasterPages(const int iStartingNum, const int iPageLayoutNum, const bool bLastPageSpan, DocumentHandlerInterface *pHandler) const; + int getSpan() const; + double getMarginLeft() const; + double getMarginRight() const; + + void setHeaderContent(std::vector<DocumentElement *> * pHeaderContent); + void setFooterContent(std::vector<DocumentElement *> * pFooterContent); + void setHeaderLeftContent(std::vector<DocumentElement *> * pHeaderContent); + void setFooterLeftContent(std::vector<DocumentElement *> * pFooterContent); +protected: + void _writeHeaderFooter(const char *headerFooterTagName, const std::vector<DocumentElement *> & headerFooterContent, + DocumentHandlerInterface *pHandler) const; +private: + WPXPropertyList mxPropList; + std::vector<DocumentElement *> * mpHeaderContent; + std::vector<DocumentElement *> * mpFooterContent; + std::vector<DocumentElement *> * mpHeaderLeftContent; + std::vector<DocumentElement *> * mpFooterLeftContent; +}; +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/SectionStyle.cxx b/writerperfect/source/filter/SectionStyle.cxx new file mode 100644 index 000000000000..1b65fc7eae38 --- /dev/null +++ b/writerperfect/source/filter/SectionStyle.cxx @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* SectionStyle: Stores (and writes) section-based information (e.g.: a column + * break needs a new section) that is needed at the head of an OO document and + * is referenced throughout the entire document + * + * Copyright (C) 2002-2003 William Lachance (william.lachance@sympatico.ca) + * Copyright (c) 2004 Fridrich Strba (fridrich.strba@bluewin.ch) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#include "FilterInternal.hxx" +#include "SectionStyle.hxx" +#include "DocumentElement.hxx" +#include <math.h> + +#ifdef _MSC_VER +double rint(double x); +#endif /* _WIN32 */ + +SectionStyle::SectionStyle(const WPXPropertyList &xPropList, + const WPXPropertyListVector &xColumns, + const char *psName) : + Style(psName), + mPropList(xPropList), + mColumns(xColumns) +{ +} + +void SectionStyle::write(DocumentHandlerInterface *pHandler) const +{ + TagOpenElement styleOpen("style:style"); + styleOpen.addAttribute("style:name", getName()); + styleOpen.addAttribute("style:family", "section"); + styleOpen.write(pHandler); + + // if the number of columns is <= 1, we will never come here. This is only an additional check + // style properties + pHandler->startElement("style:section-properties", mPropList); + + // column properties + WPXPropertyList columnProps; + + if (mColumns.count() > 1) + { + columnProps.insert("fo:column-count", (int)mColumns.count()); + pHandler->startElement("style:columns", columnProps); + + WPXPropertyListVector::Iter i(mColumns); + for (i.rewind(); i.next();) + { + pHandler->startElement("style:column", i()); + pHandler->endElement("style:column"); + } + } + else + { + columnProps.insert("fo:column-count", 0); + columnProps.insert("fo:column-gap", 0.0f); + pHandler->startElement("style:columns", columnProps); + } + + pHandler->endElement("style:columns"); + + + pHandler->endElement("style:section-properties"); + + pHandler->endElement("style:style"); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/SectionStyle.hxx b/writerperfect/source/filter/SectionStyle.hxx new file mode 100644 index 000000000000..ee7a003fffae --- /dev/null +++ b/writerperfect/source/filter/SectionStyle.hxx @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* SectionStyle: Stores (and writes) section-based information (e.g.: a column + * change needs a new section) that is needed at the head of an OO document. + * + * Copyright (C) 2002-2003 William Lachance (william.lachance@sympatico.ca) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef _SECTIONSTYLE_H +#define _SECTIONSTYLE_H +#include <libwpd/libwpd.h> +#include <libwpd/WPXPropertyListVector.h> + +#include "Style.hxx" +#include "WriterProperties.hxx" + + +class SectionStyle : public Style +{ +public: + SectionStyle(const WPXPropertyList &xPropList, const WPXPropertyListVector &xColumns, const char *psName); + virtual void write(DocumentHandlerInterface *pHandler) const; + +private: + WPXPropertyList mPropList; + WPXPropertyListVector mColumns; +}; +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/Style.hxx b/writerperfect/source/filter/Style.hxx new file mode 100644 index 000000000000..282041542017 --- /dev/null +++ b/writerperfect/source/filter/Style.hxx @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* Style: A base class from which all other styles are inherited, includes + * a name. + * + * Copyright (C) 2002-2003 William Lachance (william.lachance@sympatico.ca) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#ifndef _STYLE_H +#define _STYLE_H +#include <libwpd/libwpd.h> +#include "DocumentElement.hxx" + +class TopLevelElementStyle +{ +public: + TopLevelElementStyle() : mpsMasterPageName(NULL) { } + virtual ~TopLevelElementStyle() { if (mpsMasterPageName) delete mpsMasterPageName; } + void setMasterPageName(WPXString &sMasterPageName) { mpsMasterPageName = new WPXString(sMasterPageName); } + const WPXString * getMasterPageName() const { return mpsMasterPageName; } + +private: + WPXString *mpsMasterPageName; +}; + +class Style +{ + public: + Style(const WPXString &psName) : msName(psName) {} + virtual ~Style() {} + + virtual void write(DocumentHandlerInterface * /* pHandler */) const {}; + const WPXString &getName() const { return msName; } + + private: + WPXString msName; +}; +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/TableStyle.cxx b/writerperfect/source/filter/TableStyle.cxx new file mode 100644 index 000000000000..2fc66ed04841 --- /dev/null +++ b/writerperfect/source/filter/TableStyle.cxx @@ -0,0 +1,167 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* TableStyle: Stores (and writes) table-based information that is + * needed at the head of an OO document. + * + * Copyright (C) 2002-2004 William Lachance (william.lachance@sympatico.ca) + * Copyright (C) 2004 Net Integration Technologies, Inc. (http://www.net-itech.com) + * Copyright (C) 2004 Fridrich Strba (fridrich.strba@bluewin.ch) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#include <math.h> +#include "FilterInternal.hxx" +#include "TableStyle.hxx" +#include "DocumentElement.hxx" + +#ifdef _MSC_VER +#include <minmax.h> +#endif + +#include <string.h> + +TableCellStyle::TableCellStyle(const WPXPropertyList &xPropList, const char *psName) : + Style(psName), + mPropList(xPropList) +{ +} + +void TableCellStyle::write(DocumentHandlerInterface *pHandler) const +{ + TagOpenElement styleOpen("style:style"); + styleOpen.addAttribute("style:name", getName()); + styleOpen.addAttribute("style:family", "table-cell"); + styleOpen.write(pHandler); + + // WLACH_REFACTORING: Only temporary.. a much better solution is to + // generalize this sort of thing into the "Style" superclass + WPXPropertyList stylePropList; + WPXPropertyList::Iter i(mPropList); + for (i.rewind(); i.next();) + { + if (strlen(i.key()) > 2 && strncmp(i.key(), "fo", 2) == 0) + stylePropList.insert(i.key(), i()->clone()); + } + stylePropList.insert("fo:padding", "0.0382in"); + pHandler->startElement("style:table-cell-properties", stylePropList); + pHandler->endElement("style:table-cell-properties"); + + pHandler->endElement("style:style"); +} + +TableRowStyle::TableRowStyle(const WPXPropertyList &propList, const char *psName) : + Style(psName), + mPropList(propList) +{ +} + +void TableRowStyle::write(DocumentHandlerInterface *pHandler) const +{ + TagOpenElement styleOpen("style:style"); + styleOpen.addAttribute("style:name", getName()); + styleOpen.addAttribute("style:family", "table-row"); + styleOpen.write(pHandler); + + TagOpenElement stylePropertiesOpen("style:table-row-properties"); + if (mPropList["style:min-row-height"]) + stylePropertiesOpen.addAttribute("style:min-row-height", mPropList["style:min-row-height"]->getStr()); + else if (mPropList["style:row-height"]) + stylePropertiesOpen.addAttribute("style:row-height", mPropList["style:row-height"]->getStr()); + stylePropertiesOpen.addAttribute("fo:keep-together", "auto"); + stylePropertiesOpen.write(pHandler); + pHandler->endElement("style:table-row-properties"); + + pHandler->endElement("style:style"); +} + + +TableStyle::TableStyle(const WPXPropertyList &xPropList, const WPXPropertyListVector &columns, const char *psName) : + Style(psName), + mPropList(xPropList), + mColumns(columns) +{ +} + +TableStyle::~TableStyle() +{ + typedef std::vector<TableCellStyle *>::iterator TCSVIter; + typedef std::vector<TableRowStyle *>::iterator TRSVIter; + for (TCSVIter iterTableCellStyles = mTableCellStyles.begin() ; iterTableCellStyles != mTableCellStyles.end(); iterTableCellStyles++) + delete(*iterTableCellStyles); + for (TRSVIter iterTableRowStyles = mTableRowStyles.begin() ; iterTableRowStyles != mTableRowStyles.end(); iterTableRowStyles++) + delete(*iterTableRowStyles); +} + +void TableStyle::write(DocumentHandlerInterface *pHandler) const +{ + TagOpenElement styleOpen("style:style"); + styleOpen.addAttribute("style:name", getName()); + styleOpen.addAttribute("style:family", "table"); + if (getMasterPageName()) + styleOpen.addAttribute("style:master-page-name", getMasterPageName()->cstr()); + styleOpen.write(pHandler); + + TagOpenElement stylePropertiesOpen("style:table-properties"); + if (mPropList["table:align"]) + stylePropertiesOpen.addAttribute("table:align", mPropList["table:align"]->getStr()); + if (mPropList["fo:margin-left"]) + stylePropertiesOpen.addAttribute("fo:margin-left", mPropList["fo:margin-left"]->getStr()); + if (mPropList["fo:margin-right"]) + stylePropertiesOpen.addAttribute("fo:margin-right", mPropList["fo:margin-right"]->getStr()); + if (mPropList["style:width"]) + stylePropertiesOpen.addAttribute("style:width", mPropList["style:width"]->getStr()); + if (mPropList["fo:break-before"]) + stylePropertiesOpen.addAttribute("fo:break-before", mPropList["fo:break-before"]->getStr()); + stylePropertiesOpen.write(pHandler); + + pHandler->endElement("style:table-properties"); + + pHandler->endElement("style:style"); + + int i=1; + WPXPropertyListVector::Iter j(mColumns); + for (j.rewind(); j.next();) + { + TagOpenElement styleOpen2("style:style"); + WPXString sColumnName; + sColumnName.sprintf("%s.Column%i", getName().cstr(), i); + styleOpen2.addAttribute("style:name", sColumnName); + styleOpen2.addAttribute("style:family", "table-column"); + styleOpen2.write(pHandler); + + pHandler->startElement("style:table-column-properties", j()); + pHandler->endElement("style:table-column-properties"); + + pHandler->endElement("style:style"); + + i++; + } + + typedef std::vector<TableRowStyle *>::const_iterator TRSVIter; + for (TRSVIter iterTableRow = mTableRowStyles.begin() ; iterTableRow != mTableRowStyles.end(); iterTableRow++) + (*iterTableRow)->write(pHandler); + + typedef std::vector<TableCellStyle *>::const_iterator TCSVIter; + for (TCSVIter iterTableCell = mTableCellStyles.begin() ; iterTableCell != mTableCellStyles.end(); iterTableCell++) + (*iterTableCell)->write(pHandler); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/TableStyle.hxx b/writerperfect/source/filter/TableStyle.hxx new file mode 100644 index 000000000000..95c30892faf5 --- /dev/null +++ b/writerperfect/source/filter/TableStyle.hxx @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* TableStyle: Stores (and writes) table-based information that is + * needed at the head of an OO document. + * + * Copyright (C) 2002-2003 William Lachance (william.lachance@sympatico.ca) + * Copyright (C) 2004 Fridrich Strba (fridrich.strba@bluewin.ch) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef _TABLESTYLE_H +#define _TABLESTYLE_H +#if defined _MSC_VER +#pragma warning( push, 1 ) +#endif +#include <libwpd/libwpd.h> +#if defined _MSC_VER +#pragma warning( pop ) +#endif +#include <vector> + +#include "Style.hxx" +#include "WriterProperties.hxx" +#include "DocumentHandlerInterface.hxx" + +class DocumentElement; + +class TableCellStyle : public Style +{ +public: + virtual ~TableCellStyle() {}; + TableCellStyle(const WPXPropertyList &xPropList, const char *psName); + virtual void write(DocumentHandlerInterface *pHandler) const; +private: + WPXPropertyList mPropList; +}; + +class TableRowStyle : public Style +{ +public: + virtual ~TableRowStyle() {}; + TableRowStyle(const WPXPropertyList &propList, const char *psName); + virtual void write(DocumentHandlerInterface *pHandler) const; +private: + WPXPropertyList mPropList; +}; + +class TableStyle : public Style, public TopLevelElementStyle +{ +public: + TableStyle(const WPXPropertyList &xPropList, const WPXPropertyListVector &columns, const char *psName); + virtual ~TableStyle(); + virtual void write(DocumentHandlerInterface *pHandler) const; + int getNumColumns() const { return mColumns.count(); } + void addTableCellStyle(TableCellStyle *pTableCellStyle) { mTableCellStyles.push_back(pTableCellStyle); } + int getNumTableCellStyles() { return mTableCellStyles.size(); } + void addTableRowStyle(TableRowStyle *pTableRowStyle) { mTableRowStyles.push_back(pTableRowStyle); } + int getNumTableRowStyles() { return mTableRowStyles.size(); } +private: + WPXPropertyList mPropList; + WPXPropertyListVector mColumns; + std::vector<TableCellStyle *> mTableCellStyles; + std::vector<TableRowStyle *> mTableRowStyles; +}; +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/TextRunStyle.cxx b/writerperfect/source/filter/TextRunStyle.cxx new file mode 100644 index 000000000000..9b3bc9825fd9 --- /dev/null +++ b/writerperfect/source/filter/TextRunStyle.cxx @@ -0,0 +1,179 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* TextRunStyle: Stores (and writes) paragraph/span-style-based information + * (e.g.: a paragraph might be bold) that is needed at the head of an OO + * document. + * + * Copyright (C) 2002-2004 William Lachance (william.lachance@sympatico.ca) + * Copyright (C) 2004 Net Integration Technologies, Inc. (http://www.net-itech.com) + * Copyright (C) 2004 Fridrich Strba (fridrich.strba@bluewin.ch) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#include "FilterInternal.hxx" +#include "TextRunStyle.hxx" +#include "WriterProperties.hxx" +#include "DocumentElement.hxx" + +#ifdef _MSC_VER +#include <minmax.h> +#endif + +#include <string.h> + +ParagraphStyle::ParagraphStyle(WPXPropertyList *pPropList, const WPXPropertyListVector &xTabStops, const WPXString &sName) : + mpPropList(pPropList), + mxTabStops(xTabStops), + msName(sName) +{ +} + +ParagraphStyle::~ParagraphStyle() +{ + delete mpPropList; +} + +void ParagraphStyle::write(DocumentHandlerInterface *pHandler) const +{ + WRITER_DEBUG_MSG(("Writing a paragraph style..\n")); + + WPXPropertyList propList; + propList.insert("style:name", msName.cstr()); + propList.insert("style:family", "paragraph"); + propList.insert("style:parent-style-name", (*mpPropList)["style:parent-style-name"]->getStr()); + if ((*mpPropList)["style:master-page-name"]) + propList.insert("style:master-page-name", (*mpPropList)["style:master-page-name"]->getStr()); + pHandler->startElement("style:style", propList); + + propList.clear(); + WPXPropertyList::Iter i((*mpPropList)); + for (i.rewind(); i.next(); ) + { +#if 0 + if (strcmp(i.key(), "style:list-style-name") == 0) + propList.insert("style:list-style-name", i()->getStr()); +#endif + if (strcmp(i.key(), "fo:margin-left") == 0) + propList.insert("fo:margin-left", i()->getStr()); + if (strcmp(i.key(), "fo:margin-right") == 0) + propList.insert("fo:margin-right", i()->getStr()); + if (strcmp(i.key(), "fo:text-indent") == 0) + propList.insert("fo:text-indent", i()->getStr()); + if (strcmp(i.key(), "fo:margin-top") == 0) + propList.insert("fo:margin-top", i()->getStr()); + if (strcmp(i.key(), "fo:margin-bottom") == 0) + { + if (i()->getDouble() > 0.0f) + propList.insert("fo:margin-bottom", i()->getStr()); + else + propList.insert("fo:margin-bottom", 0.0f); + } + if (strcmp(i.key(), "fo:line-height") == 0) + propList.insert("fo:line-height", i()->getStr()); + if (strcmp(i.key(), "fo:break-before") == 0) + propList.insert("fo:break-before", i()->getStr()); + if (strcmp(i.key(), "fo:text-align") == 0) + propList.insert("fo:text-align", i()->getStr()); + if (strcmp(i.key(), "fo:text-align-last") == 0) + propList.insert("fo:text-align-last", i()->getStr()); + } + + propList.insert("style:justify-single-word", "false"); + pHandler->startElement("style:paragraph-properties", propList); + + if (mxTabStops.count() > 0) + { + TagOpenElement tabListOpen("style:tab-stops"); + tabListOpen.write(pHandler); + WPXPropertyListVector::Iter i2(mxTabStops); + for (i2.rewind(); i2.next();) + { + if (i2()["style:position"] && i2()["style:position"]->getDouble() < 0) + continue; + TagOpenElement tabStopOpen("style:tab-stop"); + + WPXPropertyList::Iter j(i2()); + for (j.rewind(); j.next(); ) + { + tabStopOpen.addAttribute(j.key(), j()->getStr().cstr()); + } + tabStopOpen.write(pHandler); + pHandler->endElement("style:tab-stop"); + } + pHandler->endElement("style:tab-stops"); + } + + pHandler->endElement("style:paragraph-properties"); + pHandler->endElement("style:style"); +} + +SpanStyle::SpanStyle(const char *psName, const WPXPropertyList &xPropList) : + Style(psName), + mPropList(xPropList) +{ +} + +void SpanStyle::write(DocumentHandlerInterface *pHandler) const +{ + WRITER_DEBUG_MSG(("Writing a span style..\n")); + WPXPropertyList styleOpenList; + styleOpenList.insert("style:name", getName()); + styleOpenList.insert("style:family", "text"); + pHandler->startElement("style:style", styleOpenList); + + WPXPropertyList propList(mPropList); + + if (mPropList["style:font-name"]) + { + propList.insert("style:font-name-asian", mPropList["style:font-name"]->getStr()); + propList.insert("style:font-name-complex", mPropList["style:font-name"]->getStr()); + } + + if (mPropList["fo:font-size"]) + { + if (mPropList["fo:font-size"]->getDouble() > 0.0f) + { + propList.insert("style:font-size-asian", mPropList["fo:font-size"]->getStr()); + propList.insert("style:font-size-complex", mPropList["fo:font-size"]->getStr()); + } + else + propList.remove("fo:font-size"); + } + + if (mPropList["fo:font-weight"]) + { + propList.insert("style:font-weight-asian", mPropList["fo:font-weight"]->getStr()); + propList.insert("style:font-weight-complex", mPropList["fo:font-weight"]->getStr()); + } + + if (mPropList["fo:font-style"]) + { + propList.insert("style:font-style-asian", mPropList["fo:font-style"]->getStr()); + propList.insert("style:font-style-complex", mPropList["fo:font-style"]->getStr()); + } + + pHandler->startElement("style:text-properties", propList); + + pHandler->endElement("style:text-properties"); + pHandler->endElement("style:style"); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/TextRunStyle.hxx b/writerperfect/source/filter/TextRunStyle.hxx new file mode 100644 index 000000000000..492132cfc54d --- /dev/null +++ b/writerperfect/source/filter/TextRunStyle.hxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* TextRunStyle: Stores (and writes) paragraph/span-style-based information + * (e.g.: a paragraph might be bold) that is needed at the head of an OO + * document. + * + * Copyright (C) 2002-2003 William Lachance (william.lachance@sympatico.ca) + * Copyright (C) 2004 Fridrich Strba (fridrich.strba@bluewin.ch) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#ifndef _TEXTRUNSTYLE_H +#define _TEXTRUNSTYLE_H +#include <libwpd/libwpd.h> + +#include "Style.hxx" + +class TagOpenElement; +class DocumentElement; + +class ParagraphStyle +{ +public: + ParagraphStyle(WPXPropertyList *propList, const WPXPropertyListVector &tabStops, const WPXString &sName); + virtual ~ParagraphStyle(); + virtual void write(DocumentHandlerInterface *pHandler) const; + WPXString getName() const { return msName; } +private: + WPXPropertyList *mpPropList; + WPXPropertyListVector mxTabStops; + WPXString msName; +}; + + +class SpanStyle : public Style +{ +public: + SpanStyle(const char *psName, const WPXPropertyList &xPropList); + virtual void write(DocumentHandlerInterface *pHandler) const; + +private: + WPXPropertyList mPropList; +}; +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/WriterProperties.hxx b/writerperfect/source/filter/WriterProperties.hxx new file mode 100644 index 000000000000..757807ef3977 --- /dev/null +++ b/writerperfect/source/filter/WriterProperties.hxx @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* WriterProperties: A grab bag of writer-specific properties which we use + * define here for later use. + * + * Copyright (C) 2002-2003 William Lachance (william.lachance@sympatico.ca) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef _WRITER_PROPERTIES_H +#define _WRITER_PROPERTIES_H + +#define IMP_DEFAULT_SUPER_SUB_SCRIPT "58%" +#define IMP_NUM_CENTIMETERES_PER_INCH 2.54f +#define IMP_DEFAULT_FONT_NAME "Times New Roman" +#define IMP_DEFAULT_FONT_SIZE 12.0f +#define IMP_DEFAULT_FONT_PITCH "variable" +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/makefile.mk b/writerperfect/source/filter/makefile.mk new file mode 100644 index 000000000000..f211101f706e --- /dev/null +++ b/writerperfect/source/filter/makefile.mk @@ -0,0 +1,38 @@ +PRJ=..$/.. + +PRJNAME=writerperfect +TARGET=filter +ENABLE_EXCEPTIONS=true + +.INCLUDE : settings.mk + +.IF "$(SYSTEM_LIBWPD)" == "YES" +INCPRE+=$(LIBWPD_CFLAGS) +.ENDIF + +.IF "$(SYSTEM_LIBWPG)" == "YES" +INCPRE+=$(LIBWPG_CFLAGS) +.ENDIF + +.IF "$(SYSTEM_LIBWPS)" == "YES" +INCPRE+=$(LIBWPS_CFLAGS) +.ENDIF + +# broken but ... necessary, internal include shafted ... +INCPRE+= -I.. + +SLOFILES= \ + $(SLO)$/DocumentCollector.obj \ + $(SLO)$/DocumentElement.obj \ + $(SLO)$/DocumentHandler.obj \ + $(SLO)$/FontStyle.obj \ + $(SLO)$/GraphicsStyle.obj \ + $(SLO)$/InternalHandler.obj \ + $(SLO)$/ListStyle.obj \ + $(SLO)$/OdgExporter.obj \ + $(SLO)$/PageSpan.obj \ + $(SLO)$/SectionStyle.obj \ + $(SLO)$/TableStyle.obj \ + $(SLO)$/TextRunStyle.obj + +.INCLUDE : target.mk diff --git a/writerperfect/source/stream/WPXSvStream.cxx b/writerperfect/source/stream/WPXSvStream.cxx new file mode 100644 index 000000000000..fd7d98604a07 --- /dev/null +++ b/writerperfect/source/stream/WPXSvStream.cxx @@ -0,0 +1,172 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#include "WPXSvStream.h" +#include "filter/FilterInternal.hxx" +#include <tools/stream.hxx> +#include <unotools/streamwrap.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <limits> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::io; + +WPXSvInputStream::WPXSvInputStream( Reference< XInputStream > xStream ) : + WPXInputStream(), + mxChildStorage(), + mxChildStream(), + mxStream(xStream), + mxSeekable(xStream, UNO_QUERY), + maData(0) +{ + if (!xStream.is() || !mxStream.is()) + mnLength = 0; + else + { + if (!mxSeekable.is()) + mnLength = 0; + else + { + try + { + mnLength = mxSeekable->getLength(); + } + catch ( ... ) + { + WRITER_DEBUG_MSG(("mnLength = mxSeekable->getLength() threw exception\n")); + mnLength = 0; + } + } + } +} + +WPXSvInputStream::~WPXSvInputStream() +{ +} + +const unsigned char * WPXSvInputStream::read(unsigned long numBytes, unsigned long &numBytesRead) +{ + numBytesRead = 0; + + if (numBytes == 0 || atEOS()) + return 0; + + numBytesRead = mxStream->readSomeBytes (maData, numBytes); + if (numBytesRead == 0) + return 0; + + return (const unsigned char *)maData.getConstArray(); +} + +long WPXSvInputStream::tell() +{ + if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is()) + return -1L; + else + { + sal_Int64 tmpPosition = mxSeekable->getPosition(); + if ((tmpPosition < 0) || (tmpPosition > (std::numeric_limits<long>::max)())) + return -1L; + return (long)tmpPosition; + } +} + +int WPXSvInputStream::seek(long offset, WPX_SEEK_TYPE seekType) +{ + if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is()) + return -1; + + sal_Int64 tmpPosition = mxSeekable->getPosition(); + if ((tmpPosition < 0) || (tmpPosition > (std::numeric_limits<long>::max)())) + return -1; + + sal_Int64 tmpOffset = offset; + if (seekType == WPX_SEEK_CUR) + tmpOffset += tmpPosition; + + int retVal = 0; + if (tmpOffset < 0) + { + tmpOffset = 0; + retVal = -1; + } + if (offset > mnLength) + { + tmpOffset = mnLength; + retVal = -1; + } + + try + { + mxSeekable->seek(tmpOffset); + return retVal; + } + catch (...) + { + WRITER_DEBUG_MSG(("mxSeekable->seek(offset) threw exception\n")); + return -1; + } +} + +bool WPXSvInputStream::atEOS() +{ + if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is()) + return true; + return (mxSeekable->getPosition() >= mnLength); +} + +bool WPXSvInputStream::isOLEStream() +{ + if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is()) + return false; + + sal_Int64 tmpPosition = mxSeekable->getPosition(); + mxSeekable->seek(0); + + SvStream *pStream = utl::UcbStreamHelper::CreateStream( mxStream ); + bool bAns = pStream && SotStorage::IsOLEStorage( pStream ); + if (pStream) + delete pStream; + + mxSeekable->seek(tmpPosition); + + return bAns; +} + +WPXInputStream * WPXSvInputStream::getDocumentOLEStream(const char * name) +{ + if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is()) + return 0; + + sal_Int64 tmpPosition = mxSeekable->getPosition(); + mxSeekable->seek(0); + + SvStream *pStream = utl::UcbStreamHelper::CreateStream( mxStream ); + + if (!pStream || !SotStorage::IsOLEStorage( pStream )) + { + mxSeekable->seek(tmpPosition); + return 0; + } + + mxChildStorage = new SotStorage( pStream, TRUE ); + + mxChildStream = mxChildStorage->OpenSotStream( + rtl::OUString::createFromAscii( name ), + STREAM_STD_READ ); + + mxSeekable->seek(tmpPosition); + + if ( !mxChildStream.Is() || mxChildStream->GetError() ) + { + mxSeekable->seek(tmpPosition); + return 0; + } + + Reference < XInputStream > xContents(new utl::OSeekableInputStreamWrapper( mxChildStream )); + mxSeekable->seek(tmpPosition); + if (xContents.is()) + return new WPXSvInputStream( xContents ); + else + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/stream/WPXSvStream.h b/writerperfect/source/stream/WPXSvStream.h new file mode 100644 index 000000000000..37d905adcc41 --- /dev/null +++ b/writerperfect/source/stream/WPXSvStream.h @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#ifndef WPXSVSTREAM_H +#define WPXSVSTREAM_H + +#include <sot/storage.hxx> +#include <com/sun/star/io/XInputStream.hpp> + +#ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_H_ +#include <com/sun/star/io/XSeekable.hpp> +#endif + + +#if defined _MSC_VER +#pragma warning( push, 1 ) +#endif +#include <libwpd-stream/WPXStream.h> +#if defined _MSC_VER +#pragma warning( pop ) +#endif + +class WPXSvInputStream : public WPXInputStream +{ +public: + WPXSvInputStream( ::com::sun::star::uno::Reference< + ::com::sun::star::io::XInputStream > xStream ); + virtual ~WPXSvInputStream(); + + virtual bool isOLEStream(); + virtual WPXInputStream * getDocumentOLEStream(const char *name); + + virtual const unsigned char *read(unsigned long numBytes, unsigned long &numBytesRead); + virtual int seek(long offset, WPX_SEEK_TYPE seekType); + virtual long tell(); + virtual bool atEOS(); + +private: + SotStorageRef mxChildStorage; + SotStorageStreamRef mxChildStream; + ::com::sun::star::uno::Reference< + ::com::sun::star::io::XInputStream > mxStream; + ::com::sun::star::uno::Reference< + ::com::sun::star::io::XSeekable > mxSeekable; + ::com::sun::star::uno::Sequence< sal_Int8 > maData; + sal_Int64 mnLength; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/stream/makefile.mk b/writerperfect/source/stream/makefile.mk new file mode 100644 index 000000000000..97262e7b7486 --- /dev/null +++ b/writerperfect/source/stream/makefile.mk @@ -0,0 +1,24 @@ +PRJ=..$/.. + +PRJNAME=writerperfect +TARGET=stream +ENABLE_EXCEPTIONS=true + +.INCLUDE : settings.mk + +.IF "$(SYSTEM_LIBWPD)" == "YES" +INCPRE+=$(LIBWPD_CFLAGS) +.ENDIF + +.IF "$(SYSTEM_LIBWPS)" == "YES" +INCPRE+=$(LIBWPS_CFLAGS) +.ELSE +INCPRE+=$(SOLARVER)$/$(UPD)$/$(INPATH)$/inc$/libwps +.ENDIF + +# broken but ... necessary, internal include shafted ... +INCPRE+= -I.. + +SLOFILES= $(SLO)$/WPXSvStream.obj + +.INCLUDE : target.mk diff --git a/writerperfect/source/wpdimp/WordPerfectCollector.cxx b/writerperfect/source/wpdimp/WordPerfectCollector.cxx new file mode 100644 index 000000000000..83fdec5ff9cd --- /dev/null +++ b/writerperfect/source/wpdimp/WordPerfectCollector.cxx @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* WordPerfectCollector: Collects sections and runs of text from a + * wordperfect file (and styles to go along with them) and writes them + * to a Writer target document + * + * Copyright (C) 2006 Fridrich Strba (fridrich.strba@bluewin.ch) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#if defined _MSC_VER +#pragma warning( push, 1 ) +#endif +#include "WordPerfectCollector.hxx" +#include <libwpd/WPDocument.h> +#if defined _MSC_VER +#pragma warning( pop ) +#endif + +WordPerfectCollector::WordPerfectCollector(WPXInputStream *pInput, DocumentHandlerInterface *pHandler, const rtl::OString& password) : + DocumentCollector(pInput, pHandler), + maUtf8Password(password) +{ +} + +WordPerfectCollector::~WordPerfectCollector() +{ +} + +bool WordPerfectCollector::parseSourceDocument(WPXInputStream &input) +{ + WPDResult result; + if (maUtf8Password.getLength()) + result = WPDocument::parse(&input, static_cast<WPXDocumentInterface *>(this), maUtf8Password.getStr()); + else + result = WPDocument::parse(&input, static_cast<WPXDocumentInterface *>(this), NULL); + if (result != WPD_OK) + return false; + + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpdimp/WordPerfectCollector.hxx b/writerperfect/source/wpdimp/WordPerfectCollector.hxx new file mode 100644 index 000000000000..fce25691e951 --- /dev/null +++ b/writerperfect/source/wpdimp/WordPerfectCollector.hxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* WordPerfectCollector: Collects sections and runs of text from a + * wordperfect file (and styles to go along with them) and writes them + * to a Writer target document + * + * Copyright (C) 2006 Fridrich Strba (fridrich.strba@bluewin.ch) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#ifndef _WORDPERFECTCOLLECTOR_HXX +#define _WORDPERFECTCOLLECTOR_HXX + +#include "filter/DocumentCollector.hxx" +#include "filter/DocumentHandlerInterface.hxx" +#include <rtl/ustring.hxx> + +class WordPerfectCollector : public DocumentCollector +{ +public: + WordPerfectCollector(WPXInputStream *pInput, DocumentHandlerInterface *pHandler, const rtl::OString& password); + virtual ~WordPerfectCollector(); + bool parseSourceDocument(WPXInputStream &pInput); +private: + rtl::OString maUtf8Password; +}; +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpdimp/WordPerfectImportFilter.cxx b/writerperfect/source/wpdimp/WordPerfectImportFilter.cxx new file mode 100644 index 000000000000..1bd7e16cd6fa --- /dev/null +++ b/writerperfect/source/wpdimp/WordPerfectImportFilter.cxx @@ -0,0 +1,434 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2000 by Sun Microsystems, Inc. + * Copyright (C) 2002-2004 William Lachance (wlach@interlog.com) + * Copyright (C) 2004 Net Integration Technologies (http://www.net-itech.com) + * Copyright (C) 2004 Fridrich Strba <fridrich.strba@bluewin.ch> + * + * 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. + * + * Contributor(s): Martin Gallwey (gallwey@sun.com) + * + */ +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#include <osl/diagnose.h> +#include <rtl/tencinfo.h> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/xml/sax/XAttributeList.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> + +#include <xmloff/attrlist.hxx> +#include <ucbhelper/content.hxx> +#include <sfx2/passwd.hxx> + +#include "filter/FilterInternal.hxx" +#include "filter/DocumentHandler.hxx" +#include "filter/DocumentCollector.hxx" +#include "stream/WPXSvStream.h" + +#if defined _MSC_VER +#pragma warning( push, 1 ) +#endif +#include <libwpd/WPDocument.h> +#if defined _MSC_VER +#pragma warning( pop ) +#endif + +#include "WordPerfectCollector.hxx" +#include "WordPerfectImportFilter.hxx" + +using namespace ::rtl; +using namespace ::com::sun::star; + +using rtl::OString; +using rtl::OUString; +using com::sun::star::uno::Sequence; +using com::sun::star::uno::Reference; +using com::sun::star::uno::Any; +using com::sun::star::uno::UNO_QUERY; +using com::sun::star::uno::XInterface; +using com::sun::star::uno::Exception; +using com::sun::star::uno::RuntimeException; +using com::sun::star::lang::XMultiServiceFactory; +using com::sun::star::beans::PropertyValue; +using com::sun::star::document::XFilter; +using com::sun::star::document::XExtendedFilterDetection; +using com::sun::star::ucb::XCommandEnvironment; + +using com::sun::star::io::XInputStream; +using com::sun::star::document::XImporter; +using com::sun::star::xml::sax::InputSource; +using com::sun::star::xml::sax::XAttributeList; +using com::sun::star::xml::sax::XDocumentHandler; +using com::sun::star::xml::sax::XParser; + +void callHandler(uno::Reference < XDocumentHandler > xDocHandler); + +sal_Bool SAL_CALL WordPerfectImportFilter::importImpl( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) + throw (RuntimeException) +{ + WRITER_DEBUG_MSG(("WordPerfectImportFilter::importImpl: Got here!\n")); + + sal_Int32 nLength = aDescriptor.getLength(); + const PropertyValue * pValue = aDescriptor.getConstArray(); + OUString sURL; + uno::Reference < XInputStream > xInputStream; + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "InputStream" ) ) ) + pValue[i].Value >>= xInputStream; + else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "URL" ) ) ) + pValue[i].Value >>= sURL; + } + if ( !xInputStream.is() ) + { + OSL_ASSERT( 0 ); + return sal_False; + } + + WPXSvInputStream input( xInputStream ); + + OString aUtf8Passwd; + +#if 1 + WPDConfidence confidence = WPDocument::isFileFormatSupported(&input); + + if (WPD_CONFIDENCE_SUPPORTED_ENCRYPTION == confidence) + { + int unsuccessfulAttempts = 0; + while (true ) + { + SfxPasswordDialog aPasswdDlg( 0 ); + aPasswdDlg.SetMinLen(0); + if(!aPasswdDlg.Execute()) + return sal_False; + String aPasswd = aPasswdDlg.GetPassword(); + OUString aUniPasswd(aPasswd.GetBuffer() /*, aPasswd.Len(), RTL_TEXTENCODING_UCS2 */); + aUtf8Passwd = OUStringToOString(aUniPasswd, RTL_TEXTENCODING_UTF8); + if (WPD_PASSWORD_MATCH_OK == WPDocument::verifyPassword(&input, aUtf8Passwd.getStr())) + break; + else + unsuccessfulAttempts++; + if (unsuccessfulAttempts == 3) // timeout after 3 password atempts + return sal_False; + } + } +#endif + + // An XML import service: what we push sax messages to.. + OUString sXMLImportService ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Writer.XMLOasisImporter" ) ); + uno::Reference < XDocumentHandler > xInternalHandler( mxMSF->createInstance( sXMLImportService ), UNO_QUERY ); + + // The XImporter sets up an empty target document for XDocumentHandler to write to.. + uno::Reference < XImporter > xImporter(xInternalHandler, UNO_QUERY); + xImporter->setTargetDocument(mxDoc); + + // OO Document Handler: abstract class to handle document SAX messages, concrete implementation here + // writes to in-memory target doc + DocumentHandler xHandler(xInternalHandler); + + WordPerfectCollector collector(&input, &xHandler, aUtf8Passwd); + collector.filter(); + + return true; +} + +sal_Bool SAL_CALL WordPerfectImportFilter::filter( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) + throw (RuntimeException) +{ + WRITER_DEBUG_MSG(("WordPerfectImportFilter::filter: Got here!\n")); + return importImpl ( aDescriptor ); +} +void SAL_CALL WordPerfectImportFilter::cancel( ) + throw (RuntimeException) +{ + WRITER_DEBUG_MSG(("WordPerfectImportFilter::cancel: Got here!\n")); +} + +// XImporter +void SAL_CALL WordPerfectImportFilter::setTargetDocument( const uno::Reference< ::com::sun::star::lang::XComponent >& xDoc ) + throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException) +{ + WRITER_DEBUG_MSG(("WordPerfectImportFilter::getTargetDocument: Got here!\n")); + meType = FILTER_IMPORT; + mxDoc = xDoc; +} + +// XExtendedFilterDetection +OUString SAL_CALL WordPerfectImportFilter::detect( com::sun::star::uno::Sequence< PropertyValue >& Descriptor ) + throw( com::sun::star::uno::RuntimeException ) +{ + WRITER_DEBUG_MSG(("WordPerfectImportFilter::detect: Got here!\n")); + + WPDConfidence confidence = WPD_CONFIDENCE_NONE; + OUString sTypeName = OUString( RTL_CONSTASCII_USTRINGPARAM ( "" ) ); + sal_Int32 nLength = Descriptor.getLength(); + sal_Int32 location = nLength; + OUString sURL; + const PropertyValue * pValue = Descriptor.getConstArray(); + uno::Reference < XInputStream > xInputStream; + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "TypeName" ) ) ) + location=i; + else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "InputStream" ) ) ) + pValue[i].Value >>= xInputStream; + else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "URL" ) ) ) + pValue[i].Value >>= sURL; + } + + uno::Reference< com::sun::star::ucb::XCommandEnvironment > xEnv; + if (!xInputStream.is()) + { + try + { + ::ucbhelper::Content aContent(sURL, xEnv); + xInputStream = aContent.openStream(); + } + catch ( ... ) + { + return ::rtl::OUString(); + } + + if (!xInputStream.is()) + return ::rtl::OUString(); + } + + WPXSvInputStream input( xInputStream ); + + if (input.atEOS()) + return ::rtl::OUString(); + + confidence = WPDocument::isFileFormatSupported(&input); + + if (confidence == WPD_CONFIDENCE_EXCELLENT || confidence == WPD_CONFIDENCE_SUPPORTED_ENCRYPTION) + sTypeName = OUString( RTL_CONSTASCII_USTRINGPARAM ( "writer_WordPerfect_Document" ) ); + + if (sTypeName.getLength()) + { + if ( location == Descriptor.getLength() ) + { + Descriptor.realloc(nLength+1); + Descriptor[location].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TypeName")); + } + + Descriptor[location].Value <<=sTypeName; + } + + return sTypeName; +} + + +// XInitialization +void SAL_CALL WordPerfectImportFilter::initialize( const Sequence< Any >& aArguments ) + throw (Exception, RuntimeException) +{ + WRITER_DEBUG_MSG(("WordPerfectImportFilter::initialize: Got here!\n")); + Sequence < PropertyValue > aAnySeq; + sal_Int32 nLength = aArguments.getLength(); + if ( nLength && ( aArguments[0] >>= aAnySeq ) ) + { + const PropertyValue * pValue = aAnySeq.getConstArray(); + nLength = aAnySeq.getLength(); + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "Type" ) ) ) + { + pValue[i].Value >>= msFilterName; + break; + } + } + } +} +OUString WordPerfectImportFilter_getImplementationName () + throw (RuntimeException) +{ + return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Writer.WordPerfectImportFilter" ) ); +} + +#define SERVICE_NAME1 "com.sun.star.document.ImportFilter" +#define SERVICE_NAME2 "com.sun.star.document.ExtendedTypeDetection" +sal_Bool SAL_CALL WordPerfectImportFilter_supportsService( const OUString& ServiceName ) + throw (RuntimeException) +{ + return (ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME1 ) ) || + ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME2 ) ) ); +} +Sequence< OUString > SAL_CALL WordPerfectImportFilter_getSupportedServiceNames( ) + throw (RuntimeException) +{ + Sequence < OUString > aRet(2); + OUString* pArray = aRet.getArray(); + pArray[0] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME1 ) ); + pArray[1] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME2 ) ); + return aRet; +} +#undef SERVICE_NAME2 +#undef SERVICE_NAME1 + +uno::Reference< XInterface > SAL_CALL WordPerfectImportFilter_createInstance( const uno::Reference< XMultiServiceFactory > & rSMgr) + throw( Exception ) +{ + return (cppu::OWeakObject*) new WordPerfectImportFilter( rSMgr ); +} + +// XServiceInfo +OUString SAL_CALL WordPerfectImportFilter::getImplementationName( ) + throw (RuntimeException) +{ + return WordPerfectImportFilter_getImplementationName(); +} +sal_Bool SAL_CALL WordPerfectImportFilter::supportsService( const OUString& rServiceName ) + throw (RuntimeException) +{ + return WordPerfectImportFilter_supportsService( rServiceName ); +} +Sequence< OUString > SAL_CALL WordPerfectImportFilter::getSupportedServiceNames( ) + throw (RuntimeException) +{ + return WordPerfectImportFilter_getSupportedServiceNames(); +} + + +WordPerfectImportFilterDialog::WordPerfectImportFilterDialog(const ::com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory > &r ) : + mxMSF( r ) {} + +WordPerfectImportFilterDialog::~WordPerfectImportFilterDialog() +{ +} + +void SAL_CALL WordPerfectImportFilterDialog::setTitle( const ::rtl::OUString& ) + throw (::com::sun::star::uno::RuntimeException) +{ +} + +sal_Int16 SAL_CALL WordPerfectImportFilterDialog::execute() + throw (::com::sun::star::uno::RuntimeException) +{ + WPXSvInputStream input( mxInputStream ); + + OString aUtf8Passwd; + + WPDConfidence confidence = WPDocument::isFileFormatSupported(&input); + + if (WPD_CONFIDENCE_SUPPORTED_ENCRYPTION == confidence) + { + int unsuccessfulAttempts = 0; + while (true ) + { + SfxPasswordDialog aPasswdDlg(0); + aPasswdDlg.SetMinLen(0); + if(!aPasswdDlg.Execute()) + return com::sun::star::ui::dialogs::ExecutableDialogResults::CANCEL; + msPassword = ::rtl::OUString(aPasswdDlg.GetPassword().GetBuffer()); + aUtf8Passwd = OUStringToOString(msPassword, RTL_TEXTENCODING_UTF8); + if (WPD_PASSWORD_MATCH_OK == WPDocument::verifyPassword(&input, aUtf8Passwd.getStr())) + break; + else + unsuccessfulAttempts++; + if (unsuccessfulAttempts == 3) // timeout after 3 password atempts + return com::sun::star::ui::dialogs::ExecutableDialogResults::CANCEL; + } + } + return com::sun::star::ui::dialogs::ExecutableDialogResults::OK; +} + +uno::Sequence<beans::PropertyValue> SAL_CALL WordPerfectImportFilterDialog::getPropertyValues() throw(uno::RuntimeException) +{ + uno::Sequence<beans::PropertyValue> aRet(1); + beans::PropertyValue* pArray = aRet.getArray(); + + pArray[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Password") ); + pArray[0].Value <<= msPassword; + + return aRet; +} + +void SAL_CALL WordPerfectImportFilterDialog::setPropertyValues( const uno::Sequence<beans::PropertyValue>& aProps) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException) +{ + const beans::PropertyValue* pPropArray = aProps.getConstArray(); + long nPropCount = aProps.getLength(); + for (long i = 0; i < nPropCount; i++) + { + const beans::PropertyValue& rProp = pPropArray[i]; + ::rtl::OUString aPropName = rProp.Name; + + if ( aPropName == ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Password")) ) + rProp.Value >>= msPassword; + else if ( aPropName.equalsAscii( "InputStream" ) ) + rProp.Value >>= mxInputStream; + } +} + + +// XServiceInfo +OUString SAL_CALL WordPerfectImportFilterDialog::getImplementationName( ) + throw (RuntimeException) +{ + return WordPerfectImportFilterDialog_getImplementationName(); +} + +sal_Bool SAL_CALL WordPerfectImportFilterDialog::supportsService( const OUString& rServiceName ) + throw (RuntimeException) +{ + return WordPerfectImportFilterDialog_supportsService( rServiceName ); +} + +Sequence< OUString > SAL_CALL WordPerfectImportFilterDialog::getSupportedServiceNames( ) + throw (RuntimeException) +{ + return WordPerfectImportFilterDialog_getSupportedServiceNames(); +} + +OUString WordPerfectImportFilterDialog_getImplementationName () + throw (RuntimeException) +{ + return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Writer.WordPerfectImportFilterDialog" ) ); +} + +#define SERVICE_NAME "com.sun.star.ui.dialogs.FilterOptionsDialog" +sal_Bool SAL_CALL WordPerfectImportFilterDialog_supportsService( const OUString& ServiceName ) + throw (RuntimeException) +{ + return ( ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) ) ); +} + +Sequence< OUString > SAL_CALL WordPerfectImportFilterDialog_getSupportedServiceNames( ) + throw (RuntimeException) +{ + Sequence < OUString > aRet(1); + OUString* pArray = aRet.getArray(); + pArray[0] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) ); + return aRet; +} +#undef SERVICE_NAME + +uno::Reference< XInterface > SAL_CALL WordPerfectImportFilterDialog_createInstance( const uno::Reference< XMultiServiceFactory > & rSMgr) + throw( Exception ) +{ + return (cppu::OWeakObject*) new WordPerfectImportFilterDialog( rSMgr ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpdimp/WordPerfectImportFilter.hxx b/writerperfect/source/wpdimp/WordPerfectImportFilter.hxx new file mode 100644 index 000000000000..50b995ff70bf --- /dev/null +++ b/writerperfect/source/wpdimp/WordPerfectImportFilter.hxx @@ -0,0 +1,178 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2000 by Sun Microsystems, Inc. + * Copyright (C) 2002-2004 William Lachance (wlach@interlog.com) + * Copyright (C) 2004 Net Integration Technologies (http://www.net-itech.com) + * Copyright (C) 2004 Fridrich Strba <fridrich.strba@bluewin.ch> + * + * 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. + * + * Contributor(s): Martin Gallwey (gallwey@sun.com) + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef _WORDPERFECTIMPORTFILTER_HXX +#define _WORDPERFECTIMPORTFILTER_HXX + +#include <com/sun/star/document/XFilter.hpp> +#include <com/sun/star/document/XImporter.hpp> +#include <com/sun/star/document/XExtendedFilterDetection.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <cppuhelper/implbase3.hxx> +#include <cppuhelper/implbase5.hxx> + +enum FilterType +{ + FILTER_IMPORT, + FILTER_EXPORT +}; +/* This component will be instantiated for both import or export. Whether it calls + * setSourceDocument or setTargetDocument determines which Impl function the filter + * member calls */ +class WordPerfectImportFilter : public cppu::WeakImplHelper5 +< + com::sun::star::document::XFilter, + com::sun::star::document::XImporter, + com::sun::star::document::XExtendedFilterDetection, + com::sun::star::lang::XInitialization, + com::sun::star::lang::XServiceInfo +> +{ +protected: + // oo.org declares + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMSF; + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > mxDoc; + ::rtl::OUString msFilterName; + ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XDocumentHandler > mxHandler; + + FilterType meType; + + sal_Bool SAL_CALL importImpl( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) + throw (::com::sun::star::uno::RuntimeException); + +public: + WordPerfectImportFilter( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > &rxMSF) + : mxMSF( rxMSF ) {} + virtual ~WordPerfectImportFilter() {} + + // XFilter + virtual sal_Bool SAL_CALL filter( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL cancel( ) + throw (::com::sun::star::uno::RuntimeException); + + // XImporter + virtual void SAL_CALL setTargetDocument( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& xDoc ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + //XExtendedFilterDetection + virtual ::rtl::OUString SAL_CALL detect( com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& Descriptor ) + throw( com::sun::star::uno::RuntimeException ); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw (::com::sun::star::uno::RuntimeException); + +}; + +::rtl::OUString WordPerfectImportFilter_getImplementationName() + throw ( ::com::sun::star::uno::RuntimeException ); + +sal_Bool SAL_CALL WordPerfectImportFilter_supportsService( const ::rtl::OUString& ServiceName ) + throw ( ::com::sun::star::uno::RuntimeException ); + +::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL WordPerfectImportFilter_getSupportedServiceNames( ) + throw ( ::com::sun::star::uno::RuntimeException ); + +::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > +SAL_CALL WordPerfectImportFilter_createInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & rSMgr) + throw ( ::com::sun::star::uno::Exception ); + + +class WordPerfectImportFilterDialog : public cppu::WeakImplHelper3 < + com::sun::star::ui::dialogs::XExecutableDialog, + com::sun::star::lang::XServiceInfo, + com::sun::star::beans::XPropertyAccess +> +{ + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMSF; + ::rtl::OUString msPassword; + ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > mxInputStream; + + ~WordPerfectImportFilterDialog(); + + // XExecutableDialog + virtual void SAL_CALL setTitle( const ::rtl::OUString& aTitle ) + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL execute() + throw (::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw (::com::sun::star::uno::RuntimeException); + + // XPropertyAccess + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > + SAL_CALL getPropertyValues() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setPropertyValues( const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::PropertyValue >& aProps ) + throw (::com::sun::star::beans::UnknownPropertyException, + ::com::sun::star::beans::PropertyVetoException, + ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + +public: + WordPerfectImportFilterDialog(const ::com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory > &r ); + +}; + +::rtl::OUString WordPerfectImportFilterDialog_getImplementationName() + throw ( ::com::sun::star::uno::RuntimeException ); + +sal_Bool SAL_CALL WordPerfectImportFilterDialog_supportsService( const ::rtl::OUString& ServiceName ) + throw ( ::com::sun::star::uno::RuntimeException ); + +::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL WordPerfectImportFilterDialog_getSupportedServiceNames( ) + throw ( ::com::sun::star::uno::RuntimeException ); + +::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > +SAL_CALL WordPerfectImportFilterDialog_createInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & rSMgr) + throw ( ::com::sun::star::uno::Exception ); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpdimp/makefile.mk b/writerperfect/source/wpdimp/makefile.mk new file mode 100644 index 000000000000..e2dd8d746546 --- /dev/null +++ b/writerperfect/source/wpdimp/makefile.mk @@ -0,0 +1,29 @@ +PRJ=..$/.. + +PRJNAME=writerperfect +TARGET=wpdimp +ENABLE_EXCEPTIONS=true + +.INCLUDE : settings.mk + +.IF "$(SYSTEM_LIBWPD)" == "YES" +INCPRE+=$(LIBWPD_CFLAGS) +.ENDIF + +.IF "$(SYSTEM_LIBWPG)" == "YES" +INCPRE+=$(LIBWPG_CFLAGS) +.ENDIF + +.IF "$(SYSTEM_LIBWPS)" == "YES" +INCPRE+=$(LIBWPS_CFLAGS) +.ENDIF + +# broken but ... necessary, internal include shafted ... +INCPRE+= -I.. + +SLOFILES= \ + $(SLO)$/WordPerfectCollector.obj \ + $(SLO)$/WordPerfectImportFilter.obj \ + $(SLO)$/wpft_genericfilter.obj + +.INCLUDE : target.mk diff --git a/writerperfect/source/wpdimp/wpft_genericfilter.cxx b/writerperfect/source/wpdimp/wpft_genericfilter.cxx new file mode 100644 index 000000000000..eb3cb035a001 --- /dev/null +++ b/writerperfect/source/wpdimp/wpft_genericfilter.cxx @@ -0,0 +1,124 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* genericfilter: mostly generic code for registering the filter + * + * Portions of this code Copyright 2000 by Sun Microsystems, Inc. + * Rest is Copyright (C) 2002 William Lachance (wlach@interlog.com) + * + * 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. + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#include <stdio.h> + +#include <osl/mutex.hxx> +#include <osl/thread.h> +#include <cppuhelper/factory.hxx> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> + +#include "WordPerfectImportFilter.hxx" + +using namespace ::rtl; +using namespace ::cppu; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; + +extern "C" +{ +//================================================================================================== +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} +//================================================================================================== +sal_Bool SAL_CALL component_writeInfo( + void * /* pServiceManager */, void * pRegistryKey ) +{ + if (pRegistryKey) + { + try + { + sal_Int32 nPos = 0; + Reference< XRegistryKey > xNewKey( + reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey( WordPerfectImportFilter_getImplementationName() ) ); + xNewKey = xNewKey->createKey( OUString(RTL_CONSTASCII_USTRINGPARAM("/UNO/SERVICES")) ); + + const Sequence< OUString > & rSNL = WordPerfectImportFilter_getSupportedServiceNames(); + const OUString * pArray = rSNL.getConstArray(); + for ( nPos = rSNL.getLength(); nPos--; ) + xNewKey->createKey( pArray[nPos] ); +#if 0 + xNewKey = reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey( WordPerfectImportFilterDialog_getImplementationName() ); + xNewKey = xNewKey->createKey( OUString(RTL_CONSTASCII_USTRINGPARAM("/UNO/SERVICES")) ); + + const Sequence< OUString > & rSNL2 = WordPerfectImportFilterDialog_getSupportedServiceNames(); + pArray = rSNL2.getConstArray(); + for ( nPos = rSNL2.getLength(); nPos--; ) + xNewKey->createKey( pArray[nPos] ); +#endif + return sal_True; + } + catch (InvalidRegistryException &) + { + OSL_ENSURE( sal_False, "### InvalidRegistryException!" ); + } + } + return sal_False; +} +//================================================================================================== +void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * /* pRegistryKey */ ) +{ + void * pRet = 0; + + OUString implName = OUString::createFromAscii( pImplName ); + if ( pServiceManager && implName.equals(WordPerfectImportFilter_getImplementationName()) ) + { + Reference< XSingleServiceFactory > xFactory( createSingleFactory( + reinterpret_cast< XMultiServiceFactory * >( pServiceManager ), + OUString::createFromAscii( pImplName ), + WordPerfectImportFilter_createInstance, WordPerfectImportFilter_getSupportedServiceNames() ) ); + + if (xFactory.is()) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } +#if 0 + else if ( pServiceManager && implName.equals(WordPerfectImportFilterDialog_getImplementationName()) ) + { + Reference< XSingleServiceFactory > xFactory( createSingleFactory( + reinterpret_cast< XMultiServiceFactory * >( pServiceManager ), + OUString::createFromAscii( pImplName ), + WordPerfectImportFilterDialog_createInstance, WordPerfectImportFilterDialog_getSupportedServiceNames() ) ); + + if (xFactory.is()) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } +#endif + + return pRet; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpgimp/WPGImportFilter.cxx b/writerperfect/source/wpgimp/WPGImportFilter.cxx new file mode 100644 index 000000000000..8a1f92d97041 --- /dev/null +++ b/writerperfect/source/wpgimp/WPGImportFilter.cxx @@ -0,0 +1,285 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* WPGImportFilter: Sets up the filter, and calls OdgExporter + * to do the actual filtering + * + * Copyright (C) 2000 by Sun Microsystems, Inc. + * Copyright (C) 2002-2004 William Lachance (wlach@interlog.com) + * Copyright (C) 2004 Net Integration Technologies (http://www.net-itech.com) + * Copyright (C) 2004-2006 Fridrich Strba <fridrich.strba@bluewin.ch> + * + * 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. + * + * Contributor(s): Martin Gallwey (gallwey@sun.com) + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#include <osl/diagnose.h> +#include <rtl/tencinfo.h> + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/xml/sax/XAttributeList.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/uno/Reference.h> + +#include <xmloff/attrlist.hxx> + +#include "filter/DocumentHandler.hxx" +#include "filter/OdgExporter.hxx" +#include "WPGImportFilter.hxx" +#include "stream/WPXSvStream.h" + +#include <iostream> + +using namespace ::com::sun::star::uno; +using com::sun::star::uno::Reference; +using com::sun::star::io::XInputStream; +using com::sun::star::io::XSeekable; +using com::sun::star::uno::Sequence; +using namespace ::rtl; +using rtl::OString; +using rtl::OUString; +using com::sun::star::uno::Sequence; +using com::sun::star::uno::Reference; +using com::sun::star::uno::Any; +using com::sun::star::uno::UNO_QUERY; +using com::sun::star::uno::XInterface; +using com::sun::star::uno::Exception; +using com::sun::star::uno::RuntimeException; +using com::sun::star::lang::XMultiServiceFactory; +using com::sun::star::beans::PropertyValue; +using com::sun::star::document::XFilter; +using com::sun::star::document::XExtendedFilterDetection; + +using com::sun::star::io::XInputStream; +using com::sun::star::document::XImporter; +using com::sun::star::xml::sax::InputSource; +using com::sun::star::xml::sax::XAttributeList; +using com::sun::star::xml::sax::XDocumentHandler; +using com::sun::star::xml::sax::XParser; + + +sal_Bool SAL_CALL WPGImportFilter::filter( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter::filter" << std::endl; +#endif + sal_Int32 nLength = aDescriptor.getLength(); + const PropertyValue * pValue = aDescriptor.getConstArray(); + OUString sURL; + Reference < XInputStream > xInputStream; + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "InputStream" ) ) ) + pValue[i].Value >>= xInputStream; + else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "URL" ) ) ) + pValue[i].Value >>= sURL; + } + if ( !xInputStream.is() ) + { + OSL_ASSERT( 0 ); + return sal_False; + } + OString sFileName; + sFileName = OUStringToOString(sURL, RTL_TEXTENCODING_INFO_ASCII); + + // An XML import service: what we push sax messages to.. + OUString sXMLImportService ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Draw.XMLOasisImporter" ) ); + Reference < XDocumentHandler > xInternalHandler( mxMSF->createInstance( sXMLImportService ), UNO_QUERY ); + + // The XImporter sets up an empty target document for XDocumentHandler to write to.. + Reference < XImporter > xImporter(xInternalHandler, UNO_QUERY); + xImporter->setTargetDocument( mxDoc ); + + // OO Graphics Handler: abstract class to handle document SAX messages, concrete implementation here + // writes to in-memory target doc + DocumentHandler xHandler(xInternalHandler); + + WPXInputStream* input = new WPXSvInputStream( xInputStream ); + + OdgExporter exporter(&xHandler); + bool tmpParseResult = libwpg::WPGraphics::parse(input, &exporter); + if (input) + delete input; + xInputStream->closeInput(); + return tmpParseResult; +} + +void SAL_CALL WPGImportFilter::cancel( ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter::cancel" << std::endl; +#endif +} + +// XImporter +void SAL_CALL WPGImportFilter::setTargetDocument( const Reference< ::com::sun::star::lang::XComponent >& xDoc ) + throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter::setTargetDocument" << std::endl; +#endif + meType = FILTER_IMPORT; + mxDoc = xDoc; +} + +// XExtendedFilterDetection +OUString SAL_CALL WPGImportFilter::detect( com::sun::star::uno::Sequence< PropertyValue >& Descriptor ) + throw( com::sun::star::uno::RuntimeException ) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter::detect" << std::endl; +#endif + OUString sTypeName = OUString( RTL_CONSTASCII_USTRINGPARAM ( "" ) ); + sal_Int32 nLength = Descriptor.getLength(); + sal_Int32 location = nLength; + const PropertyValue * pValue = Descriptor.getConstArray(); + Reference < XInputStream > xInputStream; + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "TypeName" ) ) ) + location=i; + else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "InputStream" ) ) ) + pValue[i].Value >>= xInputStream; + } + + WPXInputStream* input = new WPXSvInputStream( xInputStream ); + + if (libwpg::WPGraphics::isSupported(input)) + sTypeName = OUString( RTL_CONSTASCII_USTRINGPARAM ( "draw_WordPerfect_Graphics" ) ); + + if (input) + delete input; + + if (!sTypeName.equalsAscii("")) + { + if ( location == Descriptor.getLength() ) + { + Descriptor.realloc(nLength+1); + Descriptor[location].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TypeName")); + } + + Descriptor[location].Value <<=sTypeName; + } + return sTypeName; +} + + +// XInitialization +void SAL_CALL WPGImportFilter::initialize( const Sequence< Any >& aArguments ) + throw (Exception, RuntimeException) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter::initialize" << std::endl; +#endif + Sequence < PropertyValue > aAnySeq; + sal_Int32 nLength = aArguments.getLength(); + if ( nLength && ( aArguments[0] >>= aAnySeq ) ) + { + const PropertyValue * pValue = aAnySeq.getConstArray(); + nLength = aAnySeq.getLength(); + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "Type" ) ) ) + { + pValue[i].Value >>= msFilterName; + break; + } + } + } +} +OUString WPGImportFilter_getImplementationName () + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter_getImplementationName" << std::endl; +#endif + return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Draw.WPGImportFilter" ) ); +} + +#define SERVICE_NAME1 "com.sun.star.document.ImportFilter" +#define SERVICE_NAME2 "com.sun.star.document.ExtendedTypeDetection" +sal_Bool SAL_CALL WPGImportFilter_supportsService( const OUString& ServiceName ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter_supportsService" << std::endl; +#endif + return (ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME1 ) ) || + ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME2 ) ) ); +} +Sequence< OUString > SAL_CALL WPGImportFilter_getSupportedServiceNames( ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter_getSupportedServiceNames" << std::endl; +#endif + Sequence < OUString > aRet(2); + OUString* pArray = aRet.getArray(); + pArray[0] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME1 ) ); + pArray[1] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME2 ) ); + return aRet; +} +#undef SERVICE_NAME2 +#undef SERVICE_NAME1 + +Reference< XInterface > SAL_CALL WPGImportFilter_createInstance( const Reference< XMultiServiceFactory > & rSMgr) + throw( Exception ) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter_createInstance" << std::endl; +#endif + return (cppu::OWeakObject*) new WPGImportFilter( rSMgr ); +} + +// XServiceInfo +OUString SAL_CALL WPGImportFilter::getImplementationName( ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter::getImplementationName" << std::endl; +#endif + return WPGImportFilter_getImplementationName(); +} +sal_Bool SAL_CALL WPGImportFilter::supportsService( const OUString& rServiceName ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter::supportsService" << std::endl; +#endif + return WPGImportFilter_supportsService( rServiceName ); +} +Sequence< OUString > SAL_CALL WPGImportFilter::getSupportedServiceNames( ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter::getSupportedServiceNames" << std::endl; +#endif + return WPGImportFilter_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpgimp/WPGImportFilter.hxx b/writerperfect/source/wpgimp/WPGImportFilter.hxx new file mode 100644 index 000000000000..bab1fd474f3e --- /dev/null +++ b/writerperfect/source/wpgimp/WPGImportFilter.hxx @@ -0,0 +1,117 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2000 by Sun Microsystems, Inc. + * Copyright (C) 2002-2004 William Lachance (wlach@interlog.com) + * Copyright (C) 2004 Net Integration Technologies (http://www.net-itech.com) + * Copyright (C) 2004 Fridrich Strba <fridrich.strba@bluewin.ch> + * + * 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. + * + * Contributor(s): Martin Gallwey (gallwey@sun.com) + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef _WPGIMPORTFILTER_HXX +#define _WPGIMPORTFILTER_HXX + +#include <com/sun/star/document/XFilter.hpp> +#include <com/sun/star/document/XImporter.hpp> +#include <com/sun/star/document/XExtendedFilterDetection.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <cppuhelper/implbase5.hxx> + +#include <stdio.h> + +enum FilterType +{ + FILTER_IMPORT, + FILTER_EXPORT +}; +/* This component will be instantiated for both import or export. Whether it calls + * setSourceDocument or setTargetDocument determines which Impl function the filter + * member calls */ +class WPGImportFilter : public cppu::WeakImplHelper5 +< + com::sun::star::document::XFilter, + com::sun::star::document::XImporter, + com::sun::star::document::XExtendedFilterDetection, + com::sun::star::lang::XInitialization, + com::sun::star::lang::XServiceInfo +> +{ +protected: + // oo.org declares + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMSF; + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > mxDoc; + ::rtl::OUString msFilterName; + ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XDocumentHandler > mxHandler; + + FilterType meType; + +public: + WPGImportFilter( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > &rxMSF) + : mxMSF( rxMSF ) {} + virtual ~WPGImportFilter() {} + + // XFilter + virtual sal_Bool SAL_CALL filter( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL cancel( ) + throw (::com::sun::star::uno::RuntimeException); + + // XImporter + virtual void SAL_CALL setTargetDocument( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& xDoc ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + //XExtendedFilterDetection + virtual ::rtl::OUString SAL_CALL detect( com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& Descriptor ) + throw( com::sun::star::uno::RuntimeException ); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw (::com::sun::star::uno::RuntimeException); + +}; + +::rtl::OUString WPGImportFilter_getImplementationName() + throw ( ::com::sun::star::uno::RuntimeException ); + +sal_Bool SAL_CALL WPGImportFilter_supportsService( const ::rtl::OUString& ServiceName ) + throw ( ::com::sun::star::uno::RuntimeException ); + +::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL WPGImportFilter_getSupportedServiceNames( ) + throw ( ::com::sun::star::uno::RuntimeException ); + +::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > +SAL_CALL WPGImportFilter_createInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & rSMgr) + throw ( ::com::sun::star::uno::Exception ); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpgimp/makefile.mk b/writerperfect/source/wpgimp/makefile.mk new file mode 100644 index 000000000000..ccf1d7df9e34 --- /dev/null +++ b/writerperfect/source/wpgimp/makefile.mk @@ -0,0 +1,24 @@ +PRJ=..$/.. + +PRJNAME=writerperfect +TARGET=wpgimp +ENABLE_EXCEPTIONS=true + +.INCLUDE : settings.mk + +.IF "$(SYSTEM_LIBWPD)" == "YES" +INCPRE+=$(LIBWPD_CFLAGS) +.ENDIF + +.IF "$(SYSTEM_LIBWPG)" == "YES" +INCPRE+=$(LIBWPG_CFLAGS) +.ENDIF + +# broken but ... necessary, internal include shafted ... +INCPRE+= -I.. + +SLOFILES= \ + $(SLO)$/WPGImportFilter.obj \ + $(SLO)$/wpgimport_genericfilter.obj + +.INCLUDE : target.mk diff --git a/writerperfect/source/wpgimp/wpgimport_genericfilter.cxx b/writerperfect/source/wpgimp/wpgimport_genericfilter.cxx new file mode 100644 index 000000000000..d1686773ffe9 --- /dev/null +++ b/writerperfect/source/wpgimp/wpgimport_genericfilter.cxx @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* genericfilter: mostly generic code for registering the filter + * + * Portions of this code Copyright 2000 by Sun Microsystems, Inc. + * Rest is Copyright (C) 2002 William Lachance (wlach@interlog.com) + * + * 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. + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#include <stdio.h> + +#include <osl/mutex.hxx> +#include <osl/thread.h> +#include <cppuhelper/factory.hxx> + +#include <com/sun/star/lang/XSingleServiceFactory.hpp> + +#include "WPGImportFilter.hxx" + +using namespace ::rtl; +using namespace ::cppu; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; + +extern "C" +{ +//================================================================================================== +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} +//================================================================================================== +sal_Bool SAL_CALL component_writeInfo( + void * /* pServiceManager */, void * pRegistryKey ) +{ + if (pRegistryKey) + { + try + { + sal_Int32 nPos = 0; + Reference< XRegistryKey > xNewKey( + reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey( WPGImportFilter_getImplementationName() ) ); + xNewKey = xNewKey->createKey( OUString(RTL_CONSTASCII_USTRINGPARAM("/UNO/SERVICES")) ); + + const Sequence< OUString > & rSNL = WPGImportFilter_getSupportedServiceNames(); + const OUString * pArray = rSNL.getConstArray(); + for ( nPos = rSNL.getLength(); nPos--; ) + xNewKey->createKey( pArray[nPos] ); + + return sal_True; + } + catch (InvalidRegistryException &) + { + OSL_ENSURE( sal_False, "### InvalidRegistryException!" ); + } + } + return sal_False; +} +//================================================================================================== +void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * /* pRegistryKey */ ) +{ + void * pRet = 0; + + OUString implName = OUString::createFromAscii( pImplName ); + if ( pServiceManager && implName.equals(WPGImportFilter_getImplementationName()) ) + { + Reference< XSingleServiceFactory > xFactory( createSingleFactory( + reinterpret_cast< XMultiServiceFactory * >( pServiceManager ), + OUString::createFromAscii( pImplName ), + WPGImportFilter_createInstance, WPGImportFilter_getSupportedServiceNames() ) ); + + if (xFactory.is()) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } + + return pRet; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpsimp/MSWorksCollector.cxx b/writerperfect/source/wpsimp/MSWorksCollector.cxx new file mode 100644 index 000000000000..bed21d8bed73 --- /dev/null +++ b/writerperfect/source/wpsimp/MSWorksCollector.cxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* MSWorksCollector: Collects sections and runs of text from a + * wordperfect file (and styles to go along with them) and writes them + * to a Writer target document + * + * Copyright (C) 2006 Fridrich Strba (fridrich.strba@bluewin.ch) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#include "MSWorksCollector.hxx" +#include <libwps/WPSDocument.h> + +MSWorksCollector::MSWorksCollector(WPXInputStream *pInput, DocumentHandlerInterface *pHandler) : + DocumentCollector(pInput, pHandler) +{ +} + +MSWorksCollector::~MSWorksCollector() +{ +} + +bool MSWorksCollector::parseSourceDocument(WPXInputStream &input) +{ + WPSResult result = WPSDocument::parse(&input, static_cast<WPXDocumentInterface *>(this)); + if (result != WPS_OK) + return false; + + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpsimp/MSWorksCollector.hxx b/writerperfect/source/wpsimp/MSWorksCollector.hxx new file mode 100644 index 000000000000..9db02532a5f1 --- /dev/null +++ b/writerperfect/source/wpsimp/MSWorksCollector.hxx @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* MSWorksCollector: Collects sections and runs of text from a + * wordperfect file (and styles to go along with them) and writes them + * to a Writer target document + * + * Copyright (C) 2006 Fridrich Strba (fridrich.strba@bluewin.ch) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#ifndef _MSWORKSCOLLECTOR_HXX +#define _MSWORKSCOLLECTOR_HXX + +#include "filter/DocumentCollector.hxx" +#include "filter/DocumentHandlerInterface.hxx" + +class MSWorksCollector : public DocumentCollector +{ +public: + MSWorksCollector(WPXInputStream *pInput, DocumentHandlerInterface *pHandler); + virtual ~MSWorksCollector(); + bool parseSourceDocument(WPXInputStream &input); +}; +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpsimp/MSWorksImportFilter.cxx b/writerperfect/source/wpsimp/MSWorksImportFilter.cxx new file mode 100644 index 000000000000..211d3ae33fd3 --- /dev/null +++ b/writerperfect/source/wpsimp/MSWorksImportFilter.cxx @@ -0,0 +1,280 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* MSWorksImportFilter: Sets up the filter, and calls DocumentCollector + * to do the actual filtering + * + * Copyright (C) 2000 by Sun Microsystems, Inc. + * Copyright (C) 2002-2004 William Lachance (wlach@interlog.com) + * Copyright (C) 2004 Net Integration Technologies (http://www.net-itech.com) + * Copyright (C) 2004 Fridrich Strba <fridrich.strba@bluewin.ch> + * + * 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. + * + * Contributor(s): Martin Gallwey (gallwey@sun.com) + * + */ +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#include <osl/diagnose.h> +#include <rtl/tencinfo.h> + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/xml/sax/XAttributeList.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> + +#include <xmloff/attrlist.hxx> +#include <ucbhelper/content.hxx> + +#include "filter/FilterInternal.hxx" +#include "filter/DocumentHandler.hxx" +#include "filter/DocumentCollector.hxx" +#include "stream/WPXSvStream.h" + +#include <libwps/WPSDocument.h> +#include "MSWorksImportFilter.hxx" +#include "MSWorksCollector.hxx" + +// using namespace ::rtl; +using rtl::OString; +using rtl::OUString; +using com::sun::star::uno::Sequence; +using com::sun::star::uno::Reference; +using com::sun::star::uno::Any; +using com::sun::star::uno::UNO_QUERY; +using com::sun::star::uno::XInterface; +using com::sun::star::uno::Exception; +using com::sun::star::uno::RuntimeException; +using com::sun::star::lang::XMultiServiceFactory; +using com::sun::star::beans::PropertyValue; +using com::sun::star::document::XFilter; +using com::sun::star::document::XExtendedFilterDetection; +using com::sun::star::ucb::XCommandEnvironment; + +using com::sun::star::io::XInputStream; +using com::sun::star::document::XImporter; +using com::sun::star::xml::sax::InputSource; +using com::sun::star::xml::sax::XAttributeList; +using com::sun::star::xml::sax::XDocumentHandler; +using com::sun::star::xml::sax::XParser; + +void callHandler(Reference < XDocumentHandler > xDocHandler); + +sal_Bool SAL_CALL MSWorksImportFilter::importImpl( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) + throw (RuntimeException) +{ + WRITER_DEBUG_MSG(("MSWorksImportFilter::importImpl: Got here!\n")); + + sal_Int32 nLength = aDescriptor.getLength(); + const PropertyValue * pValue = aDescriptor.getConstArray(); + OUString sURL; + Reference < XInputStream > xInputStream; + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "InputStream" ) ) ) + pValue[i].Value >>= xInputStream; + else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "URL" ) ) ) + pValue[i].Value >>= sURL; + } + if ( !xInputStream.is() ) + { + OSL_ASSERT( 0 ); + return sal_False; + } + OString sFileName; + sFileName = OUStringToOString(sURL, RTL_TEXTENCODING_INFO_ASCII); + + // An XML import service: what we push sax messages to.. + OUString sXMLImportService ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Writer.XMLOasisImporter" ) ); + Reference < XDocumentHandler > xInternalHandler( mxMSF->createInstance( sXMLImportService ), UNO_QUERY ); + + // The XImporter sets up an empty target document for XDocumentHandler to write to.. + Reference < XImporter > xImporter(xInternalHandler, UNO_QUERY); + xImporter->setTargetDocument(mxDoc); + + // OO Document Handler: abstract class to handle document SAX messages, concrete implementation here + // writes to in-memory target doc + DocumentHandler xHandler(xInternalHandler); + + WPXSvInputStream input( xInputStream ); + + MSWorksCollector collector(&input, &xHandler); + collector.filter(); + + return true; +} + +sal_Bool SAL_CALL MSWorksImportFilter::filter( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) + throw (RuntimeException) +{ + WRITER_DEBUG_MSG(("MSWorksImportFilter::filter: Got here!\n")); + return importImpl ( aDescriptor ); +} +void SAL_CALL MSWorksImportFilter::cancel( ) + throw (RuntimeException) +{ + WRITER_DEBUG_MSG(("MSWorksImportFilter::cancel: Got here!\n")); +} + +// XImporter +void SAL_CALL MSWorksImportFilter::setTargetDocument( const Reference< ::com::sun::star::lang::XComponent >& xDoc ) + throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException) +{ + WRITER_DEBUG_MSG(("MSWorksImportFilter::getTargetDocument: Got here!\n")); + meType = FILTER_IMPORT; + mxDoc = xDoc; +} + +// XExtendedFilterDetection +OUString SAL_CALL MSWorksImportFilter::detect( com::sun::star::uno::Sequence< PropertyValue >& Descriptor ) + throw( com::sun::star::uno::RuntimeException ) +{ + WRITER_DEBUG_MSG(("MSWorksImportFilter::detect: Got here!\n")); + + WPSConfidence confidence = WPS_CONFIDENCE_NONE; + OUString sTypeName = OUString( RTL_CONSTASCII_USTRINGPARAM ( "" ) ); + sal_Int32 nLength = Descriptor.getLength(); + sal_Int32 location = nLength; + OUString sURL; + const PropertyValue * pValue = Descriptor.getConstArray(); + Reference < XInputStream > xInputStream; + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "TypeName" ) ) ) + location=i; + else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "InputStream" ) ) ) + pValue[i].Value >>= xInputStream; + else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "URL" ) ) ) + pValue[i].Value >>= sURL; + } + + Reference< com::sun::star::ucb::XCommandEnvironment > xEnv; + if (!xInputStream.is()) + { + try + { + ::ucbhelper::Content aContent(sURL, xEnv); + xInputStream = aContent.openStream(); + } + catch ( ... ) + { + return ::rtl::OUString(); + } + + if (!xInputStream.is()) + return ::rtl::OUString(); + } + + WPXSvInputStream input( xInputStream ); + + if (input.atEOS()) + return ::rtl::OUString(); + + confidence = WPSDocument::isFileFormatSupported(&input); + + if ((confidence == WPS_CONFIDENCE_EXCELLENT) || (confidence == WPS_CONFIDENCE_GOOD)) + sTypeName = OUString( RTL_CONSTASCII_USTRINGPARAM ( "writer_MS_Works_Document" ) ); + + if (sTypeName.getLength()) + { + if ( location == Descriptor.getLength() ) + { + Descriptor.realloc(nLength+1); + Descriptor[location].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TypeName")); + } + + Descriptor[location].Value <<=sTypeName; + } + + return sTypeName; +} + + +// XInitialization +void SAL_CALL MSWorksImportFilter::initialize( const Sequence< Any >& aArguments ) + throw (Exception, RuntimeException) +{ + WRITER_DEBUG_MSG(("MSWorksImportFilter::initialize: Got here!\n")); + Sequence < PropertyValue > aAnySeq; + sal_Int32 nLength = aArguments.getLength(); + if ( nLength && ( aArguments[0] >>= aAnySeq ) ) + { + const PropertyValue * pValue = aAnySeq.getConstArray(); + nLength = aAnySeq.getLength(); + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "Type" ) ) ) + { + pValue[i].Value >>= msFilterName; + break; + } + } + } +} +OUString MSWorksImportFilter_getImplementationName () + throw (RuntimeException) +{ + return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Writer.MSWorksImportFilter" ) ); +} + +#define SERVICE_NAME1 "com.sun.star.document.ImportFilter" +#define SERVICE_NAME2 "com.sun.star.document.ExtendedTypeDetection" +sal_Bool SAL_CALL MSWorksImportFilter_supportsService( const OUString& ServiceName ) + throw (RuntimeException) +{ + return (ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME1 ) ) || + ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME2 ) ) ); +} +Sequence< OUString > SAL_CALL MSWorksImportFilter_getSupportedServiceNames( ) + throw (RuntimeException) +{ + Sequence < OUString > aRet(2); + OUString* pArray = aRet.getArray(); + pArray[0] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME1 ) ); + pArray[1] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME2 ) ); + return aRet; +} +#undef SERVICE_NAME2 +#undef SERVICE_NAME1 + +Reference< XInterface > SAL_CALL MSWorksImportFilter_createInstance( const Reference< XMultiServiceFactory > & rSMgr) + throw( Exception ) +{ + return (cppu::OWeakObject*) new MSWorksImportFilter( rSMgr ); +} + +// XServiceInfo +OUString SAL_CALL MSWorksImportFilter::getImplementationName( ) + throw (RuntimeException) +{ + return MSWorksImportFilter_getImplementationName(); +} +sal_Bool SAL_CALL MSWorksImportFilter::supportsService( const OUString& rServiceName ) + throw (RuntimeException) +{ + return MSWorksImportFilter_supportsService( rServiceName ); +} +Sequence< OUString > SAL_CALL MSWorksImportFilter::getSupportedServiceNames( ) + throw (RuntimeException) +{ + return MSWorksImportFilter_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpsimp/MSWorksImportFilter.hxx b/writerperfect/source/wpsimp/MSWorksImportFilter.hxx new file mode 100644 index 000000000000..71e621298f35 --- /dev/null +++ b/writerperfect/source/wpsimp/MSWorksImportFilter.hxx @@ -0,0 +1,120 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2000 by Sun Microsystems, Inc. + * Copyright (C) 2002-2004 William Lachance (wlach@interlog.com) + * Copyright (C) 2004 Net Integration Technologies (http://www.net-itech.com) + * Copyright (C) 2004 Fridrich Strba <fridrich.strba@bluewin.ch> + * + * 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. + * + * Contributor(s): Martin Gallwey (gallwey@sun.com) + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef _WORDPERFECTIMPORTFILTER_HXX +#define _WORDPERFECTIMPORTFILTER_HXX + +#include <com/sun/star/document/XFilter.hpp> +#include <com/sun/star/document/XImporter.hpp> +#include <com/sun/star/document/XExtendedFilterDetection.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <cppuhelper/implbase5.hxx> + +enum FilterType +{ + FILTER_IMPORT, + FILTER_EXPORT +}; +/* This component will be instantiated for both import or export. Whether it calls + * setSourceDocument or setTargetDocument determines which Impl function the filter + * member calls */ +class MSWorksImportFilter : public cppu::WeakImplHelper5 +< + com::sun::star::document::XFilter, + com::sun::star::document::XImporter, + com::sun::star::document::XExtendedFilterDetection, + com::sun::star::lang::XInitialization, + com::sun::star::lang::XServiceInfo +> +{ +protected: + // oo.org declares + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMSF; + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > mxDoc; + ::rtl::OUString msFilterName; + ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XDocumentHandler > mxHandler; + + FilterType meType; + + sal_Bool SAL_CALL importImpl( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) + throw (::com::sun::star::uno::RuntimeException); + +public: + MSWorksImportFilter( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > &rxMSF) + : mxMSF( rxMSF ) + , meType( FILTER_IMPORT ) + {} + virtual ~MSWorksImportFilter() {} + + // XFilter + virtual sal_Bool SAL_CALL filter( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL cancel( ) + throw (::com::sun::star::uno::RuntimeException); + + // XImporter + virtual void SAL_CALL setTargetDocument( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& xDoc ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + //XExtendedFilterDetection + virtual ::rtl::OUString SAL_CALL detect( com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& Descriptor ) + throw( com::sun::star::uno::RuntimeException ); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw (::com::sun::star::uno::RuntimeException); + +}; + +::rtl::OUString MSWorksImportFilter_getImplementationName() + throw ( ::com::sun::star::uno::RuntimeException ); + +sal_Bool SAL_CALL MSWorksImportFilter_supportsService( const ::rtl::OUString& ServiceName ) + throw ( ::com::sun::star::uno::RuntimeException ); + +::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL MSWorksImportFilter_getSupportedServiceNames( ) + throw ( ::com::sun::star::uno::RuntimeException ); + +::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > +SAL_CALL MSWorksImportFilter_createInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & rSMgr) + throw ( ::com::sun::star::uno::Exception ); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpsimp/makefile.mk b/writerperfect/source/wpsimp/makefile.mk new file mode 100644 index 000000000000..da17e806f9b0 --- /dev/null +++ b/writerperfect/source/wpsimp/makefile.mk @@ -0,0 +1,29 @@ +PRJ=..$/.. + +PRJNAME=writerperfect +TARGET=wpsimp +ENABLE_EXCEPTIONS=true + +.INCLUDE : settings.mk + +.IF "$(SYSTEM_LIBWPD)" == "YES" +INCPRE+=$(LIBWPD_CFLAGS) +.ELSE +INCPRE+=$(SOLARVER)$/$(UPD)$/$(INPATH)$/inc$/libwpd +.ENDIF + +.IF "$(SYSTEM_LIBWPS)" == "YES" +INCPRE+=$(LIBWPS_CFLAGS) +.ELSE +INCPRE+=$(SOLARVER)$/$(UPD)$/$(INPATH)$/inc$/libwps +.ENDIF + +# broken but ... necessary, internal include shafted ... +INCPRE+= -I.. + +SLOFILES= \ + $(SLO)$/MSWorksCollector.obj \ + $(SLO)$/MSWorksImportFilter.obj \ + $(SLO)$/msworks_genericfilter.obj + +.INCLUDE : target.mk diff --git a/writerperfect/source/wpsimp/msworks_genericfilter.cxx b/writerperfect/source/wpsimp/msworks_genericfilter.cxx new file mode 100644 index 000000000000..695791431103 --- /dev/null +++ b/writerperfect/source/wpsimp/msworks_genericfilter.cxx @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* genericfilter: mostly generic code for registering the filter + * + * Portions of this code Copyright 2000 by Sun Microsystems, Inc. + * Rest is Copyright (C) 2002 William Lachance (wlach@interlog.com) + * + * 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. + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#include <stdio.h> + +#include <osl/mutex.hxx> +#include <osl/thread.h> +#include <cppuhelper/factory.hxx> + +#include <com/sun/star/lang/XSingleServiceFactory.hpp> + +#include "MSWorksImportFilter.hxx" + +using namespace ::rtl; +using namespace ::cppu; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; + +extern "C" +{ +//================================================================================================== +void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} +//================================================================================================== +sal_Bool SAL_CALL component_writeInfo( + void * /* pServiceManager */, void * pRegistryKey ) +{ + if (pRegistryKey) + { + try + { + sal_Int32 nPos = 0; + Reference< XRegistryKey > xNewKey( + reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey( MSWorksImportFilter_getImplementationName() ) ); + xNewKey = xNewKey->createKey( OUString(RTL_CONSTASCII_USTRINGPARAM("/UNO/SERVICES")) ); + + const Sequence< OUString > & rSNL = MSWorksImportFilter_getSupportedServiceNames(); + const OUString * pArray = rSNL.getConstArray(); + for ( nPos = rSNL.getLength(); nPos--; ) + xNewKey->createKey( pArray[nPos] ); + + return sal_True; + } + catch (InvalidRegistryException &) + { + OSL_ENSURE( sal_False, "### InvalidRegistryException!" ); + } + } + return sal_False; +} +//================================================================================================== +void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * /* pRegistryKey */ ) +{ + void * pRet = 0; + + OUString implName = OUString::createFromAscii( pImplName ); + if ( pServiceManager && implName.equals(MSWorksImportFilter_getImplementationName()) ) + { + Reference< XSingleServiceFactory > xFactory( createSingleFactory( + reinterpret_cast< XMultiServiceFactory * >( pServiceManager ), + OUString::createFromAscii( pImplName ), + MSWorksImportFilter_createInstance, MSWorksImportFilter_getSupportedServiceNames() ) ); + + if (xFactory.is()) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } + + return pRet; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |