diff options
Diffstat (limited to 'writerperfect/source')
31 files changed, 3681 insertions, 0 deletions
diff --git a/writerperfect/source/filter/DocumentCollector.cxx b/writerperfect/source/filter/DocumentCollector.cxx new file mode 100644 index 000000000000..e258d2212518 --- /dev/null +++ b/writerperfect/source/filter/DocumentCollector.cxx @@ -0,0 +1,931 @@ +/* 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 "TextRunStyle.hxx" +#include "FontStyle.hxx" +#include "ListStyle.hxx" +#include "PageSpan.hxx" +#include "SectionStyle.hxx" +#include "TableStyle.hxx" +#include "FilterInternal.hxx" +#include "WriterProperties.hxx" + +_WriterDocumentState::_WriterDocumentState() : + mbFirstElement(true), + mbInFakeSection(false), + mbListElementOpenedAtCurrentLevel(false), + mbTableCellOpened(false), + mbHeaderRow(false), + mbInNote(false) +{ +} + +DocumentCollector::DocumentCollector(WPXInputStream *pInput, DocumentHandler *pHandler) : + mpInput(pInput), + mpHandler(pHandler), + mbUsed(false), + mfSectionSpaceAfter(0.0f), + miNumListStyles(0), + mpCurrentContentElements(&mBodyElements), + mpCurrentPageSpan(NULL), + miNumPageStyles(0), + mpCurrentListStyle(NULL), + miCurrentListLevel(0), + miLastListLevel(0), + miLastListNumber(0), + mbListContinueNumbering(false), + mbListElementOpened(false), + mbListElementParagraphOpened(false) +{ +} + +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); + } + + return true; +} + +void DocumentCollector::_writeDefaultStyles(DocumentHandler *pHandler) +{ + TagOpenElement stylesOpenElement("office:styles"); + stylesOpenElement.write(pHandler); + + TagOpenElement defaultParagraphStyleOpenElement("style:default-style"); + defaultParagraphStyleOpenElement.addAttribute("style:family", "paragraph"); + defaultParagraphStyleOpenElement.write(pHandler); + + TagOpenElement defaultParagraphStylePropertiesOpenElement("style:properties"); + defaultParagraphStylePropertiesOpenElement.addAttribute("style:family", "paragraph"); + defaultParagraphStylePropertiesOpenElement.addAttribute("style:tab-stop-distance", "0.5inch"); + defaultParagraphStylePropertiesOpenElement.write(pHandler); + TagCloseElement defaultParagraphStylePropertiesCloseElement("style:properties"); + defaultParagraphStylePropertiesCloseElement.write(pHandler); + + TagCloseElement defaultParagraphStyleCloseElement("style:default-style"); + defaultParagraphStyleCloseElement.write(pHandler); + + TagOpenElement standardStyleOpenElement("style:style"); + standardStyleOpenElement.addAttribute("style:name", "Standard"); + standardStyleOpenElement.addAttribute("style:family", "paragraph"); + standardStyleOpenElement.addAttribute("style:class", "text"); + standardStyleOpenElement.write(pHandler); + TagCloseElement standardStyleCloseElement("style:style"); + standardStyleCloseElement.write(pHandler); + + TagOpenElement textBodyStyleOpenElement("style:style"); + textBodyStyleOpenElement.addAttribute("style:name", "Text Body"); + textBodyStyleOpenElement.addAttribute("style:family", "paragraph"); + textBodyStyleOpenElement.addAttribute("style:parent-style-name", "Standard"); + textBodyStyleOpenElement.addAttribute("style:class", "text"); + textBodyStyleOpenElement.write(pHandler); + TagCloseElement textBodyStyleCloseElement("style:style"); + textBodyStyleCloseElement.write(pHandler); + + TagOpenElement tableContentsStyleOpenElement("style:style"); + tableContentsStyleOpenElement.addAttribute("style:name", "Table Contents"); + tableContentsStyleOpenElement.addAttribute("style:family", "paragraph"); + tableContentsStyleOpenElement.addAttribute("style:parent-style-name", "Text Body"); + tableContentsStyleOpenElement.addAttribute("style:class", "extra"); + tableContentsStyleOpenElement.write(pHandler); + TagCloseElement tableContentsStyleCloseElement("style:style"); + tableContentsStyleCloseElement.write(pHandler); + + TagOpenElement tableHeadingStyleOpenElement("style:style"); + tableHeadingStyleOpenElement.addAttribute("style:name", "Table Heading"); + tableHeadingStyleOpenElement.addAttribute("style:family", "paragraph"); + tableHeadingStyleOpenElement.addAttribute("style:parent-style-name", "Table Contents"); + tableHeadingStyleOpenElement.addAttribute("style:class", "extra"); + tableHeadingStyleOpenElement.write(pHandler); + TagCloseElement tableHeadingStyleCloseElement("style:style"); + tableHeadingStyleCloseElement.write(pHandler); + + TagCloseElement stylesCloseElement("office:styles"); + stylesCloseElement.write(pHandler); + +} + +void DocumentCollector::_writeMasterPages(DocumentHandler *pHandler) +{ + WPXPropertyList xBlankAttrList; + + pHandler->startElement("office:master-styles", xBlankAttrList); + 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::_writePageMasters(DocumentHandler *pHandler) +{ + for (unsigned int i=0; i<mPageSpans.size(); i++) + { + mPageSpans[i]->writePageMaster(i, pHandler); + } +} + +bool DocumentCollector::_writeTargetDocument(DocumentHandler *pHandler) +{ + WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: Printing out the header stuff..\n")); + WPXPropertyList xBlankAttrList; + + 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", "http://openoffice.org/2000/office"); + docContentPropList.insert("xmlns:style", "http://openoffice.org/2000/style"); + docContentPropList.insert("xmlns:text", "http://openoffice.org/2000/text"); + docContentPropList.insert("xmlns:table", "http://openoffice.org/2000/table"); + docContentPropList.insert("xmlns:draw", "http://openoffice.org/2000/draw"); + docContentPropList.insert("xmlns:fo", "http://www.w3.org/1999/XSL/Format"); + docContentPropList.insert("xmlns:xlink", "http://www.w3.org/1999/xlink"); + docContentPropList.insert("xmlns:number", "http://openoffice.org/2000/datastyle"); + docContentPropList.insert("xmlns:svg", "http://www.w3.org/2000/svg"); + docContentPropList.insert("xmlns:chart", "http://openoffice.org/2000/chart"); + docContentPropList.insert("xmlns:dr3d", "http://openoffice.org/2000/dr3d"); + docContentPropList.insert("xmlns:math", "http://www.w3.org/1998/Math/MathML"); + docContentPropList.insert("xmlns:form", "http://openoffice.org/2000/form"); + docContentPropList.insert("xmlns:script", "http://openoffice.org/2000/script"); + docContentPropList.insert("office:class", "text"); + docContentPropList.insert("office:version", "1.0"); + mpHandler->startElement("office:document-content", docContentPropList); + + // write out the font styles + mpHandler->startElement("office:font-decls", xBlankAttrList); + for (std::map<WPXString, FontStyle *, ltstr>::iterator iterFont = mFontHash.begin(); iterFont != mFontHash.end(); iterFont++) { + iterFont->second->write(mpHandler); + } + TagOpenElement symbolFontOpen("style:font-decl"); + symbolFontOpen.addAttribute("style:name", "StarSymbol"); + symbolFontOpen.addAttribute("fo:font-family", "StarSymbol"); + symbolFontOpen.addAttribute("style:font-charset", "x-symbol"); + symbolFontOpen.write(mpHandler); + mpHandler->endElement("style:font-decl"); + + mpHandler->endElement("office:font-decls"); + + + WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: Writing out the styles..\n")); + + // write default styles + _writeDefaultStyles(mpHandler); + + mpHandler->startElement("office:automatic-styles", xBlankAttrList); + + for (std::map<WPXString, ParagraphStyle *, ltstr>::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>::iterator iterSpanStyle = mSpanStyleHash.begin(); + iterSpanStyle != mSpanStyleHash.end(); iterSpanStyle++) + { + (iterSpanStyle->second)->write(pHandler); + } + + // writing out the sections styles + for (std::vector<SectionStyle *>::iterator iterSectionStyles = mSectionStyles.begin(); iterSectionStyles != mSectionStyles.end(); iterSectionStyles++) { + (*iterSectionStyles)->write(pHandler); + } + + // writing out the lists styles + for (std::vector<ListStyle *>::iterator iterListStyles = mListStyles.begin(); iterListStyles != mListStyles.end(); iterListStyles++) { + (*iterListStyles)->write(pHandler); + } + + // writing out the table styles + for (std::vector<TableStyle *>::iterator iterTableStyles = mTableStyles.begin(); iterTableStyles != mTableStyles.end(); iterTableStyles++) { + (*iterTableStyles)->write(pHandler); + } + + // writing out the page masters + _writePageMasters(pHandler); + + + pHandler->endElement("office:automatic-styles"); + + _writeMasterPages(pHandler); + + WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: Writing out the document..\n")); + // writing out the document + pHandler->startElement("office:body", xBlankAttrList); + + for (std::vector<DocumentElement *>::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:body"); + pHandler->endElement("office:document-content"); + + 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::openPageSpan(const WPXPropertyList &propList) +{ + PageSpan *pPageSpan = new PageSpan(propList); + mPageSpans.push_back(pPageSpan); + mpCurrentPageSpan = pPageSpan; +} + +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(); + float fSectionMarginLeft = 0.0f; + float fSectionMarginRight = 0.0f; + if (propList["fo:margin-left"]) + fSectionMarginLeft = propList["fo:margin-left"]->getFloat(); + if (propList["fo:margin-right"]) + fSectionMarginRight = propList["fo:margin-right"]->getFloat(); + + if (iNumColumns > 1 || fSectionMarginLeft != 0 || fSectionMarginRight != 0) + { + mfSectionSpaceAfter = propList["fo:margin-bottom"]->getFloat(); + 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(static_cast<DocumentElement *>(pSectionOpenElement)); + } + else + mWriterDocumentState.mbInFakeSection = true; +} + +void DocumentCollector::closeSection() +{ + if (!mWriterDocumentState.mbInFakeSection) + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagCloseElement("text:section"))); + else + mWriterDocumentState.mbInFakeSection = false; + + // open as many paragraphs as needed to simulate section space after + // WLACH_REFACTORING: disable this for now.. + #if 0 + for (float f=0.0f; f<mfSectionSpaceAfter; f+=1.0f) { + vector<WPXTabStop> dummyTabStops; + openParagraph(WPX_PARAGRAPH_JUSTIFICATION_LEFT, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, dummyTabStops, false, false); + closeParagraph(); + } + #endif + mfSectionSpaceAfter = 0.0f; +} + +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 (mWriterDocumentState.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; + mWriterDocumentState.mbFirstElement = false; + } + else + { + if (mWriterDocumentState.mbTableCellOpened) + { + if (mWriterDocumentState.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(static_cast<DocumentElement *>(pParagraphOpenElement)); +} + +void DocumentCollector::closeParagraph() +{ + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(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(static_cast<DocumentElement *>(pSpanOpenElement)); +} + +void DocumentCollector::closeSpan() +{ + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(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 (mpCurrentListStyle && mpCurrentListStyle->getListID() == id) + pOrderedListStyle = static_cast<OrderedListStyle *>(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"] && (unsigned int)(propList["text:start-value"]->getInt()) != (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(), propList["libwpd:id"]->getInt()); + mListStyles.push_back(static_cast<ListStyle *>(pOrderedListStyle)); + mpCurrentListStyle = static_cast<ListStyle *>(pOrderedListStyle); + mbListContinueNumbering = false; + miLastListNumber = 0; + } + else + 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() == propList["libwpd:id"]->getInt()) + (* 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 (mpCurrentListStyle && mpCurrentListStyle->getListID() == id) + pUnorderedListStyle = static_cast<UnorderedListStyle *>(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); + pUnorderedListStyle = new UnorderedListStyle(sName.cstr(), id); + mListStyles.push_back(static_cast<ListStyle *>(pUnorderedListStyle)); + mpCurrentListStyle = static_cast<ListStyle *>(pUnorderedListStyle); + } + + // See comment in DocumentCollector::defineOrderedListLevel + for (std::vector<ListStyle *>::iterator iterUnorderedListStyles = mListStyles.begin(); iterUnorderedListStyles != mListStyles.end(); iterUnorderedListStyles++) + { + if ((* iterUnorderedListStyles)->getListID() == propList["libwpd:id"]->getInt()) + (* iterUnorderedListStyles)->updateListLevel((propList["libwpd:level"]->getInt() - 1), propList); + } +} + +void DocumentCollector::openOrderedListLevel(const WPXPropertyList & /* propList */) +{ + miCurrentListLevel++; + TagOpenElement *pListLevelOpenElement = new TagOpenElement("text:ordered-list"); + _openListLevel(pListLevelOpenElement); + + if (mbListContinueNumbering) { + pListLevelOpenElement->addAttribute("text:continue-numbering", "true"); + } + + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(pListLevelOpenElement)); +} + +void DocumentCollector::openUnorderedListLevel(const WPXPropertyList & /* propList */) +{ + miCurrentListLevel++; + TagOpenElement *pListLevelOpenElement = new TagOpenElement("text:unordered-list"); + _openListLevel(pListLevelOpenElement); + + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(pListLevelOpenElement)); +} + +void DocumentCollector::_openListLevel(TagOpenElement *pListLevelOpenElement) +{ + if (!mbListElementOpened && miCurrentListLevel > 1) + { + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagOpenElement("text:list-item"))); + } + else if (mbListElementParagraphOpened) + { + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagCloseElement("text:p"))); + mbListElementParagraphOpened = false; + } + + if (miCurrentListLevel==1) { + pListLevelOpenElement->addAttribute("text:style-name", mpCurrentListStyle->getName()); + } + + mbListElementOpened = false; +} + +void DocumentCollector::closeOrderedListLevel() +{ + _closeListLevel("ordered-list"); +} + +void DocumentCollector::closeUnorderedListLevel() +{ + _closeListLevel("unordered-list"); +} + +void DocumentCollector::_closeListLevel(const char *szListType) +{ + if (mbListElementOpened) + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagCloseElement("text:list-item"))); + + miCurrentListLevel--; + + WPXString sCloseElement; + sCloseElement.sprintf("text:%s", szListType); + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagCloseElement(sCloseElement.cstr()))); + + if (miCurrentListLevel > 0) + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagCloseElement("text:list-item"))); + mbListElementOpened = false; +} + +void DocumentCollector::openListElement(const WPXPropertyList &propList, const WPXPropertyListVector &tabStops) +{ + miLastListLevel = miCurrentListLevel; + if (miCurrentListLevel == 1) + miLastListNumber++; + + if (mbListElementOpened) + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagCloseElement("text:list-item"))); + + ParagraphStyle *pStyle = NULL; + + WPXPropertyList *pPersistPropList = new WPXPropertyList(propList); + pPersistPropList->insert("style:list-style-name", 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; + } + + TagOpenElement *pOpenListElement = new TagOpenElement("text:list-item"); + TagOpenElement *pOpenListElementParagraph = new TagOpenElement("text:p"); + + pOpenListElementParagraph->addAttribute("text:style-name", pStyle->getName()); + + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(pOpenListElement)); + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(pOpenListElementParagraph)); + + mbListElementOpened = true; + mbListElementParagraphOpened = true; + 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 (mbListElementParagraphOpened) + { + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagCloseElement("text:p"))); + mbListElementParagraphOpened = false; + } +} + +void DocumentCollector::openFootnote(const WPXPropertyList &propList) +{ + TagOpenElement *pOpenFootNote = new TagOpenElement("text:footnote"); + if (propList["libwpd:number"]) + { + WPXString tmpString("ftn"); + tmpString.append(propList["libwpd:number"]->getStr()); + pOpenFootNote->addAttribute("text:id", tmpString); + } + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(pOpenFootNote)); + + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagOpenElement("text:footnote-citation"))); + if (propList["libwpd:number"]) + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new CharDataElement(propList["libwpd:number"]->getStr().cstr()))); + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagCloseElement("text:footnote-citation"))); + + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagOpenElement("text:footnote-body"))); + + mWriterDocumentState.mbInNote = true; +} + +void DocumentCollector::closeFootnote() +{ + mWriterDocumentState.mbInNote = false; + + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagCloseElement("text:footnote-body"))); + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagCloseElement("text:footnote"))); +} + +void DocumentCollector::openEndnote(const WPXPropertyList &propList) +{ + TagOpenElement *pOpenEndNote = new TagOpenElement("text:endnote"); + if (propList["libwpd:number"]) + { + WPXString tmpString("edn"); + tmpString.append(propList["libwpd:number"]->getStr()); + pOpenEndNote->addAttribute("text:id", tmpString); + } + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(pOpenEndNote)); + + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagOpenElement("text:endnote-citation"))); + if (propList["libwpd:number"]) + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new CharDataElement(propList["libwpd:number"]->getStr().cstr()))); + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagCloseElement("text:endnote-citation"))); + + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagOpenElement("text:endnote-body"))); + +} +void DocumentCollector::closeEndnote() +{ + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagCloseElement("text:endnote-body"))); + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagCloseElement("text:endnote"))); +} + +void DocumentCollector::openTable(const WPXPropertyList &propList, const WPXPropertyListVector &columns) +{ + 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 (mWriterDocumentState.mbFirstElement && mpCurrentContentElements == &mBodyElements) + { + WPXString sMasterPageName("Page Style 1"); + pTableStyle->setMasterPageName(sMasterPageName); + mWriterDocumentState.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(static_cast<DocumentElement *>(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 (propList["libwpd:is-header-row"] && (propList["libwpd:is-header-row"]->getInt())) + { + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagOpenElement("table:table-header-rows"))); + mWriterDocumentState.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(static_cast<DocumentElement *>(pTableRowOpenElement)); +} + +void DocumentCollector::closeTableRow() +{ + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagCloseElement("table:table-row"))); + if (mWriterDocumentState.mbHeaderRow) + { + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagCloseElement("table:table-header-rows"))); + mWriterDocumentState.mbHeaderRow = false; + } +} + +void DocumentCollector::openTableCell(const WPXPropertyList &propList) +{ + 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(static_cast<DocumentElement *>(pTableCellOpenElement)); + + mWriterDocumentState.mbTableCellOpened = true; +} + +void DocumentCollector::closeTableCell() +{ + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagCloseElement("table:table-cell"))); + mWriterDocumentState.mbTableCellOpened = false; +} + +void DocumentCollector::insertCoveredTableCell(const WPXPropertyList & /* propList */) +{ + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagOpenElement("table:covered-table-cell"))); + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagCloseElement("table:covered-table-cell"))); +} + +void DocumentCollector::closeTable() +{ + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagCloseElement("table:table"))); +} + +void DocumentCollector::insertTab() +{ + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagOpenElement("text:tab-stop"))); + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagCloseElement("text:tab-stop"))); +} + +void DocumentCollector::insertLineBreak() +{ + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagOpenElement("text:line-break"))); + mpCurrentContentElements->push_back(static_cast<DocumentElement *>(new TagCloseElement("text:line-break"))); +} + +void DocumentCollector::insertText(const WPXString &text) +{ + DocumentElement *pText = new TextElement(text); + mpCurrentContentElements->push_back(pText); +} diff --git a/writerperfect/source/filter/DocumentCollector.hxx b/writerperfect/source/filter/DocumentCollector.hxx new file mode 100644 index 000000000000..18ebcdb43418 --- /dev/null +++ b/writerperfect/source/filter/DocumentCollector.hxx @@ -0,0 +1,201 @@ +/* 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 <libwpd/libwpd.h> +#if defined _MSC_VER +#pragma warning( pop ) +#endif +#include <vector> +#include <map> +#include <stack> +#include <string.h> + +class DocumentElement; +class DocumentHandler; +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 mbInFakeSection; + bool mbListElementOpenedAtCurrentLevel; + bool mbTableCellOpened; + bool mbHeaderRow; + bool mbInNote; +}; + +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 WPXHLListenerImpl +{ +public: + DocumentCollector(WPXInputStream *pInput, DocumentHandler *pHandler); + virtual ~DocumentCollector(); + bool filter(); + + virtual void setDocumentMetaData(const WPXPropertyList & /* propList */) {} + virtual void startDocument() {} + virtual void endDocument() {} + + virtual void openPageSpan(const WPXPropertyList &propList); + virtual void closePageSpan() {} + + 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 openParagraph(const WPXPropertyList &propList, const WPXPropertyListVector &tabStops); + virtual void closeParagraph(); + + virtual void openSpan(const WPXPropertyList &propList); + virtual void closeSpan(); + + + virtual void insertTab(); + virtual void insertText(const WPXString &text); + virtual void insertLineBreak(); + + 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 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 bool parseSourceDocument(WPXInputStream &input) = 0; + +protected: + void _resetDocumentState(); + bool _writeTargetDocument(DocumentHandler *pHandler); + void _writeDefaultStyles(DocumentHandler *pHandler); + void _writeMasterPages(DocumentHandler *pHandler); + void _writePageMasters(DocumentHandler *pHandler); + void _allocateFontName(const WPXString &); + +private: + void _openListLevel(TagOpenElement *pListLevelOpenElement); + void _closeListLevel(const char *szListType); + + WPXInputStream *mpInput; + DocumentHandler *mpHandler; + bool mbUsed; // whether or not it has been before (you can only use me once!) + + WriterDocumentState mWriterDocumentState; + + // 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; + + // 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 / state + ListStyle *mpCurrentListStyle; + unsigned int miCurrentListLevel; + unsigned int miLastListLevel; + unsigned int miLastListNumber; + std::vector<ListStyle *> mListStyles; + bool mbListContinueNumbering; + bool mbListElementOpened; + bool mbListElementParagraphOpened; + + // table state + TableStyle *mpCurrentTableStyle; +}; + +#endif diff --git a/writerperfect/source/filter/DocumentElement.cxx b/writerperfect/source/filter/DocumentElement.cxx new file mode 100644 index 000000000000..38caf5780e15 --- /dev/null +++ b/writerperfect/source/filter/DocumentElement.cxx @@ -0,0 +1,102 @@ +/* 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 "FilterInternal.hxx" +#include <string.h> + +#define ASCII_SPACE 0x0020 + +void TagElement::print() const +{ + WRITER_DEBUG_MSG(("%s\n", msTagName.cstr())); +} + +void TagOpenElement::write(DocumentHandler *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(DocumentHandler *pHandler) const +{ + WRITER_DEBUG_MSG(("TagCloseElement: write (%s)\n", getTagName().cstr())); + + pHandler->endElement(getTagName().cstr()); +} + +void CharDataElement::write(DocumentHandler *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(DocumentHandler *pHandler) const +{ + 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); +} diff --git a/writerperfect/source/filter/DocumentElement.hxx b/writerperfect/source/filter/DocumentElement.hxx new file mode 100644 index 000000000000..bcfabd8015d8 --- /dev/null +++ b/writerperfect/source/filter/DocumentElement.hxx @@ -0,0 +1,99 @@ +/* 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 +#if defined _MSC_VER +#pragma warning( push, 1 ) +#endif +#include <libwpd/libwpd.h> +#include <libwpd/WPXProperty.h> +#include <libwpd/WPXString.h> +#if defined _MSC_VER +#pragma warning( pop ) +#endif +#include <vector> + +#include "DocumentHandler.hxx" + +class DocumentElement +{ +public: + virtual ~DocumentElement() {} + virtual void write(DocumentHandler *pHandler) const = 0; + virtual void print() const {} +}; + +class TagElement : public DocumentElement +{ +public: + 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) {} + ~TagOpenElement() {} + void addAttribute(const char *szAttributeName, const WPXString &sAttributeValue); + virtual void write(DocumentHandler *pHandler) const; + virtual void print () const; +private: + WPXPropertyList maAttrList; +}; + +class TagCloseElement : public TagElement +{ +public: + TagCloseElement(const char *szTagName) : TagElement(szTagName) {} + virtual void write(DocumentHandler *pHandler) const; +}; + +class CharDataElement : public DocumentElement +{ +public: + CharDataElement(const char *sData) : DocumentElement(), msData(sData) {} + virtual void write(DocumentHandler *pHandler) const; +private: + WPXString msData; +}; + +class TextElement : public DocumentElement +{ +public: + TextElement(const WPXString & sTextBuf); + virtual void write(DocumentHandler *pHandler) const; + +private: + WPXString msTextBuf; +}; + +#endif diff --git a/writerperfect/source/filter/DocumentHandler.cxx b/writerperfect/source/filter/DocumentHandler.cxx new file mode 100644 index 000000000000..5877b8acd5df --- /dev/null +++ b/writerperfect/source/filter/DocumentHandler.cxx @@ -0,0 +1,83 @@ +/* + * 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> + +#ifndef _ATTRLIST_HPP_ +#include <xmloff/attrlist.hxx> +#endif + +using namespace ::rtl; +using rtl::OUString; + +using com::sun::star::xml::sax::XAttributeList; + +DocumentHandler::DocumentHandler(Reference < XDocumentHandler > &xHandler) : + mxHandler(xHandler) +{ +} + +void DocumentHandler::startDocument() +{ + WRITER_DEBUG_MSG(("DocumentHandler::startDocument")); + mxHandler->startDocument(); +} + +void DocumentHandler::endDocument() +{ + WRITER_DEBUG_MSG(("DocumentHandler::endDocument")); + mxHandler->endDocument(); +} + +void DocumentHandler::startElement(const char *psName, const WPXPropertyList &xPropList) +{ + WRITER_DEBUG_MSG(("DocumentHandler::startElement")); + SvXMLAttributeList *pAttrList = new SvXMLAttributeList(); + Reference < XAttributeList > xAttrList(pAttrList); + WPXPropertyList::Iter i(xPropList); + for (i.rewind(); i.next(); ) + { + // filter out libwpd elements + if (strlen(i.key()) > 6 && strncmp(i.key(), "libwpd", 6) != 0) + pAttrList->AddAttribute(OUString::createFromAscii(i.key()), + OUString::createFromAscii(i()->getStr().cstr())); + } + + mxHandler->startElement(OUString::createFromAscii(psName), xAttrList); +} + +void DocumentHandler::endElement(const char *psName) +{ + WRITER_DEBUG_MSG(("DocumentHandler::endElement")); + mxHandler->endElement(OUString::createFromAscii(psName)); +} + +void DocumentHandler::characters(const WPXString &sCharacters) +{ + WRITER_DEBUG_MSG(("DocumentHandler::characters")); + OUString sCharU16(sCharacters.cstr(), strlen(sCharacters.cstr()), RTL_TEXTENCODING_UTF8); + mxHandler->characters(sCharU16); +} diff --git a/writerperfect/source/filter/DocumentHandler.hxx b/writerperfect/source/filter/DocumentHandler.hxx new file mode 100644 index 000000000000..350157d17aa8 --- /dev/null +++ b/writerperfect/source/filter/DocumentHandler.hxx @@ -0,0 +1,31 @@ +#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 + +using com::sun::star::uno::Reference; +using com::sun::star::xml::sax::XDocumentHandler; + +class DocumentHandler +{ +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_ diff --git a/writerperfect/source/filter/FilterInternal.hxx b/writerperfect/source/filter/FilterInternal.hxx new file mode 100644 index 000000000000..adc993c6d9d3 --- /dev/null +++ b/writerperfect/source/filter/FilterInternal.hxx @@ -0,0 +1,31 @@ +/* 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 + * + */ +#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 diff --git a/writerperfect/source/filter/FontStyle.cxx b/writerperfect/source/filter/FontStyle.cxx new file mode 100644 index 000000000000..de7cc47002dc --- /dev/null +++ b/writerperfect/source/filter/FontStyle.cxx @@ -0,0 +1,50 @@ +/* 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), + msFontPitch(IMP_DEFAULT_FONT_PITCH) +{ +} + +FontStyle::~FontStyle() +{ +} + +void FontStyle::write(DocumentHandler *pHandler) const +{ + TagOpenElement styleOpen("style:font-decl"); + styleOpen.addAttribute("style:name", getName()); + styleOpen.addAttribute("fo:font-family", msFontFamily); + styleOpen.addAttribute("style:font-pitch", msFontPitch); + styleOpen.write(pHandler); + TagCloseElement styleClose("style:font-decl"); + styleClose.write(pHandler); +} diff --git a/writerperfect/source/filter/FontStyle.hxx b/writerperfect/source/filter/FontStyle.hxx new file mode 100644 index 000000000000..be44cf140471 --- /dev/null +++ b/writerperfect/source/filter/FontStyle.hxx @@ -0,0 +1,52 @@ +/* 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 +#if defined _MSC_VER +#pragma warning( push, 1 ) +#endif +#include <libwpd/libwpd.h> +#if defined _MSC_VER +#pragma warning( pop ) +#endif + +#include "Style.hxx" +#include "WriterProperties.hxx" + +class FontStyle : public Style +{ +public: + FontStyle(const char *psName, const char *psFontFamily); + ~FontStyle(); + virtual void write(DocumentHandler *pHandler) const; + const WPXString &getFontFamily() const { return msFontFamily; } + +private: + WPXString msFontFamily; + WPXString msFontPitch; +}; +#endif diff --git a/writerperfect/source/filter/ListStyle.cxx b/writerperfect/source/filter/ListStyle.cxx new file mode 100644 index 000000000000..b320022caf56 --- /dev/null +++ b/writerperfect/source/filter/ListStyle.cxx @@ -0,0 +1,161 @@ +/* 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(DocumentHandler *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"]) + listLevelStyleOpen.addAttribute("style:num-prefix", mPropList["style:num-prefix"]->getStr()); + if (mPropList["style:num-suffix"]) + listLevelStyleOpen.addAttribute("style:num-suffix", mPropList["style:num-suffix"]->getStr()); + if (mPropList["style:num-format"]) + listLevelStyleOpen.addAttribute("style:num-format", mPropList["style:num-format"]->getStr()); + if (mPropList["text:start-value"]) + listLevelStyleOpen.addAttribute("text:start-value", mPropList["text:start-value"]->getStr()); + listLevelStyleOpen.write(pHandler); + + TagOpenElement stylePropertiesOpen("style:properties"); + if (mPropList["text:space-before"]) + stylePropertiesOpen.addAttribute("text:space-before", mPropList["text:space-before"]->getStr()); + if (mPropList["text:min-label-width"]) + stylePropertiesOpen.addAttribute("text:min-label-width", mPropList["text:min-label-width"]->getStr()); + if (mPropList["text:min-label-distance"]) + stylePropertiesOpen.addAttribute("text:min-label-distance", mPropList["text:min-label-distance"]->getStr()); + stylePropertiesOpen.write(pHandler); + + pHandler->endElement("style: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(DocumentHandler *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"); + listLevelStyleOpen.addAttribute("style:num-suffice", "."); + if (mPropList["text:bullet-char"]) + listLevelStyleOpen.addAttribute("text:bullet-char", mPropList["text:bullet-char"]->getStr()); + listLevelStyleOpen.write(pHandler); + + TagOpenElement stylePropertiesOpen("style:properties"); + if (mPropList["text:space-before"]) + stylePropertiesOpen.addAttribute("text:space-before", mPropList["text:space-before"]->getStr()); + if (mPropList["text:min-label-width"]) + stylePropertiesOpen.addAttribute("text:min-label-width", mPropList["text:min-label-width"]->getStr()); + if (mPropList["text:min-label-distance"]) + stylePropertiesOpen.addAttribute("text:min-label-distance", mPropList["text:min-label-distance"]->getStr()); + stylePropertiesOpen.addAttribute("style:font-name", "OpenSymbol"); + stylePropertiesOpen.write(pHandler); + + pHandler->endElement("style: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(DocumentHandler *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"); +} diff --git a/writerperfect/source/filter/ListStyle.hxx b/writerperfect/source/filter/ListStyle.hxx new file mode 100644 index 000000000000..b2ebb07ef799 --- /dev/null +++ b/writerperfect/source/filter/ListStyle.hxx @@ -0,0 +1,101 @@ +/* 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 +#if defined _MSC_VER +#pragma warning( push, 1 ) +#endif +#include <libwpd/libwpd.h> +#if defined _MSC_VER +#pragma warning( pop ) +#endif + +#define WP6_NUM_LIST_LEVELS 8 // see WP6FileStructure.h (we shouldn't need to reference this) + +#include "Style.hxx" +#include "WriterProperties.hxx" + +class DocumentElement; + +class ListLevelStyle +{ +public: + virtual ~ListLevelStyle() {}; + virtual void write(DocumentHandler *pHandler, int iLevel) const = 0; +}; + +class OrderedListLevelStyle : public ListLevelStyle +{ +public: + OrderedListLevelStyle(const WPXPropertyList &xPropList); + void write(DocumentHandler *pHandler, int iLevel) const; +private: + WPXPropertyList mPropList; +}; + +class UnorderedListLevelStyle : public ListLevelStyle +{ +public: + UnorderedListLevelStyle(const WPXPropertyList &xPropList); + void write(DocumentHandler *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(DocumentHandler *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 diff --git a/writerperfect/source/filter/PageSpan.cxx b/writerperfect/source/filter/PageSpan.cxx new file mode 100644 index 000000000000..4ac5797e6d01 --- /dev/null +++ b/writerperfect/source/filter/PageSpan.cxx @@ -0,0 +1,173 @@ +/* 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" + +PageSpan::PageSpan(const WPXPropertyList &xPropList) : + mxPropList(xPropList), + mpHeaderContent(NULL), + mpFooterContent(NULL), + mpHeaderLeftContent(NULL), + mpFooterLeftContent(NULL) +{ +} + +PageSpan::~PageSpan() +{ + typedef std::vector<DocumentElement *>::iterator DEVIter; + + 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 +} + +void PageSpan::writePageMaster(const int iNum, DocumentHandler *pHandler) const +{ + WPXPropertyList propList; + + WPXString sPageMasterName; + sPageMasterName.sprintf("PM%i", iNum /* +2 */); + propList.insert("style:name", sPageMasterName); + + pHandler->startElement("style:page-master", 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("0inch")); + pHandler->startElement("style:properties", tempPropList); + + WPXPropertyList footnoteSepPropList; + footnoteSepPropList.insert("style:width", WPXString("0.0071inch")); + footnoteSepPropList.insert("style:distance-before-sep", WPXString("0.0398inch")); + footnoteSepPropList.insert("style:distance-after-sep", WPXString("0.0398inch")); + 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:properties"); + pHandler->endElement("style:page-master"); +} + +void PageSpan::writeMasterPages(const int iStartingNum, const int iPageMasterNum, const bool bLastPageSpan, + DocumentHandler *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; + sMasterPageName.sprintf("Page Style %i", i); + WPXString sPageMasterName; + sPageMasterName.sprintf("PM%i", iPageMasterNum /* +2 */); + WPXPropertyList propList; + propList.insert("style:name", sMasterPageName); + propList.insert("style:page-master-name", sPageMasterName); + 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); + if (mpHeaderLeftContent) + _writeHeaderFooter("style:header-left", *mpHeaderLeftContent, pHandler); + if (mpFooterContent) + _writeHeaderFooter("style:footer", *mpFooterContent, pHandler); + if (mpFooterLeftContent) + _writeHeaderFooter("style:footer-left", *mpFooterLeftContent, pHandler); + + pHandler->endElement("style:master-page"); + } + +} + +void PageSpan::_writeHeaderFooter(const char *headerFooterTagName, + const std::vector<DocumentElement *> & headerFooterContent, + DocumentHandler *pHandler) const +{ + TagOpenElement headerFooterOpen(headerFooterTagName); + headerFooterOpen.write(pHandler); + for (std::vector<DocumentElement *>::const_iterator iter = headerFooterContent.begin(); + iter != headerFooterContent.end(); + iter++) { + (*iter)->write(pHandler); + } + TagCloseElement headerFooterClose(headerFooterTagName); + headerFooterClose.write(pHandler); +} + diff --git a/writerperfect/source/filter/PageSpan.hxx b/writerperfect/source/filter/PageSpan.hxx new file mode 100644 index 000000000000..7edbfaee8002 --- /dev/null +++ b/writerperfect/source/filter/PageSpan.hxx @@ -0,0 +1,65 @@ +/* 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 +#if defined _MSC_VER +#pragma warning( push, 1 ) +#endif +#include <libwpd/libwpd.h> +#if defined _MSC_VER +#pragma warning( pop ) +#endif +#include <vector> + +class DocumentElement; +class DocumentHandler; + +class PageSpan +{ +public: + PageSpan(const WPXPropertyList &xPropList); + virtual ~PageSpan(); + void writePageMaster(const int iNum, DocumentHandler *pHandler) const; + void writeMasterPages(const int iStartingNum, const int iPageMasterNum, const bool bLastPageSpan, DocumentHandler *pHandler) const; + int getSpan() const; + + const std::vector<DocumentElement *> * getHeaderContent() const { return mpHeaderContent; } + void setHeaderContent(std::vector<DocumentElement *> * pHeaderContent) { mpHeaderContent = pHeaderContent; } + void setFooterContent(std::vector<DocumentElement *> * pFooterContent) { mpFooterContent = pFooterContent; } + void setHeaderLeftContent(std::vector<DocumentElement *> * pHeaderContent) { mpHeaderLeftContent = pHeaderContent; } + void setFooterLeftContent(std::vector<DocumentElement *> * pFooterContent) { mpFooterLeftContent = pFooterContent; } +protected: + void _writeHeaderFooter(const char *headerFooterTagName, const std::vector<DocumentElement *> & headerFooterContent, + DocumentHandler *pHandler) const; +private: + WPXPropertyList mxPropList; + std::vector<DocumentElement *> * mpHeaderContent; + std::vector<DocumentElement *> * mpFooterContent; + std::vector<DocumentElement *> * mpHeaderLeftContent; + std::vector<DocumentElement *> * mpFooterLeftContent; +}; +#endif diff --git a/writerperfect/source/filter/SectionStyle.cxx b/writerperfect/source/filter/SectionStyle.cxx new file mode 100644 index 000000000000..51dd9fc398f1 --- /dev/null +++ b/writerperfect/source/filter/SectionStyle.cxx @@ -0,0 +1,86 @@ +/* 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(DocumentHandler *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: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:properties"); + + pHandler->endElement("style:style"); +} diff --git a/writerperfect/source/filter/SectionStyle.hxx b/writerperfect/source/filter/SectionStyle.hxx new file mode 100644 index 000000000000..2e914824b550 --- /dev/null +++ b/writerperfect/source/filter/SectionStyle.hxx @@ -0,0 +1,52 @@ +/* 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 +#if defined _MSC_VER +#pragma warning( push, 1 ) +#endif +#include <libwpd/libwpd.h> +#include <libwpd/WPXPropertyListVector.h> +#if defined _MSC_VER +#pragma warning( pop ) +#endif + +#include "Style.hxx" +#include "WriterProperties.hxx" + + +class SectionStyle : public Style +{ +public: + SectionStyle(const WPXPropertyList &xPropList, const WPXPropertyListVector &xColumns, const char *psName); + virtual void write(DocumentHandler *pHandler) const; + +private: + WPXPropertyList mPropList; + WPXPropertyListVector mColumns; +}; +#endif diff --git a/writerperfect/source/filter/Style.hxx b/writerperfect/source/filter/Style.hxx new file mode 100644 index 000000000000..f7e2233e0b80 --- /dev/null +++ b/writerperfect/source/filter/Style.hxx @@ -0,0 +1,63 @@ +/* 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 +#if defined _MSC_VER +#pragma warning( push, 1 ) +#endif +#include <libwpd/libwpd.h> +#if defined _MSC_VER +#pragma warning( pop ) +#endif +#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(DocumentHandler * /* pHandler */) const {}; + const WPXString &getName() const { return msName; } + + private: + WPXString msName; +}; +#endif diff --git a/writerperfect/source/filter/TableStyle.cxx b/writerperfect/source/filter/TableStyle.cxx new file mode 100644 index 000000000000..8d12427ba87b --- /dev/null +++ b/writerperfect/source/filter/TableStyle.cxx @@ -0,0 +1,163 @@ +/* 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 <string.h> +#include "FilterInternal.hxx" +#include "TableStyle.hxx" +#include "DocumentElement.hxx" + +#ifdef _MSC_VER +#include <minmax.h> +#endif + +TableCellStyle::TableCellStyle(const WPXPropertyList &xPropList, const char *psName) : + Style(psName), + mPropList(xPropList) +{ +} + +void TableCellStyle::write(DocumentHandler *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.0382inch"); + pHandler->startElement("style:properties", stylePropList); + pHandler->endElement("style:properties"); + + pHandler->endElement("style:style"); +} + +TableRowStyle::TableRowStyle(const WPXPropertyList &propList, const char *psName) : + Style(psName), + mPropList(propList) +{ +} + +void TableRowStyle::write(DocumentHandler *pHandler) const +{ + TagOpenElement styleOpen("style:style"); + styleOpen.addAttribute("style:name", getName()); + styleOpen.addAttribute("style:family", "table-row"); + styleOpen.write(pHandler); + + TagOpenElement stylePropertiesOpen("style: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.write(pHandler); + pHandler->endElement("style: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(DocumentHandler *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: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:properties"); + + pHandler->endElement("style:style"); + + int i=1; + WPXPropertyListVector::Iter j(mColumns); + for (j.rewind(); j.next();) + { + TagOpenElement styleNestedOpen("style:style"); + WPXString sColumnName; + sColumnName.sprintf("%s.Column%i", getName().cstr(), i); + styleNestedOpen.addAttribute("style:name", sColumnName); + styleNestedOpen.addAttribute("style:family", "table-column"); + styleNestedOpen.write(pHandler); + + pHandler->startElement("style:properties", j()); + pHandler->endElement("style: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); +} diff --git a/writerperfect/source/filter/TableStyle.hxx b/writerperfect/source/filter/TableStyle.hxx new file mode 100644 index 000000000000..a4c7116edb6d --- /dev/null +++ b/writerperfect/source/filter/TableStyle.hxx @@ -0,0 +1,80 @@ +/* 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" + +class DocumentElement; +class DocumentHandler; + +class TableCellStyle : public Style +{ +public: + TableCellStyle(const WPXPropertyList &xPropList, const char *psName); + virtual void write(DocumentHandler *pHandler) const; +private: + WPXPropertyList mPropList; +}; + +class TableRowStyle : public Style +{ +public: + TableRowStyle(const WPXPropertyList &propList, const char *psName); + virtual void write(DocumentHandler *pHandler) const; +private: + WPXPropertyList mPropList; +}; + +class TableStyle : public Style, public TopLevelElementStyle +{ +public: + TableStyle(const WPXPropertyList &xPropList, const WPXPropertyListVector &columns, const char *psName); + ~TableStyle(); + virtual void write(DocumentHandler *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 diff --git a/writerperfect/source/filter/TextRunStyle.cxx b/writerperfect/source/filter/TextRunStyle.cxx new file mode 100644 index 000000000000..f3e8b0499956 --- /dev/null +++ b/writerperfect/source/filter/TextRunStyle.cxx @@ -0,0 +1,162 @@ +/* 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(DocumentHandler *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 k((*mpPropList)); + for (k.rewind(); k.next(); ) + { + if (strcmp(k.key(), "style:list-style-name") == 0) + propList.insert("style:list-style-name", k()->getStr()); + if (strcmp(k.key(), "fo:margin-left") == 0) + propList.insert("fo:margin-left", k()->getStr()); + if (strcmp(k.key(), "fo:margin-right") == 0) + propList.insert("fo:margin-right", k()->getStr()); + if (strcmp(k.key(), "fo:text-indent") == 0) + propList.insert("fo:text-indent", k()->getStr()); + if (strcmp(k.key(), "fo:margin-top") == 0) + propList.insert("fo:margin-top", k()->getStr()); + if (strcmp(k.key(), "fo:margin-bottom") == 0) + propList.insert("fo:margin-bottom", k()->getStr()); + if (strcmp(k.key(), "fo:line-height") == 0) + propList.insert("fo:line-height", k()->getStr()); + if (strcmp(k.key(), "fo:break-before") == 0) + propList.insert("fo:break-before", k()->getStr()); + if (strcmp(k.key(), "fo:text-align") == 0) + propList.insert("fo:text-align", k()->getStr()); + if (strcmp(k.key(), "fo:text-align-last") == 0) + propList.insert("fo:text-align-last", k()->getStr()); + } + + propList.insert("style:justify-single-word", "false"); + pHandler->startElement("style:properties", propList); + + if (mxTabStops.count() > 0) + { + TagOpenElement tabListOpen("style:tab-stops"); + tabListOpen.write(pHandler); + WPXPropertyListVector::Iter i(mxTabStops); + for (i.rewind(); i.next();) + { + TagOpenElement tabStopOpen("style:tab-stop"); + + WPXPropertyList::Iter j(i()); + 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:properties"); + pHandler->endElement("style:style"); +} + +SpanStyle::SpanStyle(const char *psName, const WPXPropertyList &xPropList) : + Style(psName), + mPropList(xPropList) +{ +} + +void SpanStyle::write(DocumentHandler *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"]) + { + propList.insert("style:font-size-asian", mPropList["fo:font-size"]->getStr()); + propList.insert("style:font-size-complex", mPropList["fo:font-size"]->getStr()); + } + + 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:properties", propList); + + pHandler->endElement("style:properties"); + pHandler->endElement("style:style"); +} diff --git a/writerperfect/source/filter/TextRunStyle.hxx b/writerperfect/source/filter/TextRunStyle.hxx new file mode 100644 index 000000000000..7d5905e9d412 --- /dev/null +++ b/writerperfect/source/filter/TextRunStyle.hxx @@ -0,0 +1,69 @@ +/* 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 +#if defined _MSC_VER +#pragma warning( push, 1 ) +#endif +#include <libwpd/libwpd.h> +#if defined _MSC_VER +#pragma warning( pop ) +#endif + +#include "Style.hxx" + +class TagOpenElement; +class DocumentElement; +class DocumentHandler; + +class ParagraphStyle +{ +public: + ParagraphStyle(WPXPropertyList *propList, const WPXPropertyListVector &tabStops, const WPXString &sName); + virtual ~ParagraphStyle(); + virtual void write(DocumentHandler *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(DocumentHandler *pHandler) const; + +private: + WPXPropertyList mPropList; +}; +#endif diff --git a/writerperfect/source/filter/WriterProperties.hxx b/writerperfect/source/filter/WriterProperties.hxx new file mode 100644 index 000000000000..8b6466ac406c --- /dev/null +++ b/writerperfect/source/filter/WriterProperties.hxx @@ -0,0 +1,36 @@ +/* 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" +#define IMP_DEFAULT_FONT_COLOR (new RGBSColor(0x00,0x00,0x00,0x64)) +#endif diff --git a/writerperfect/source/filter/makefile.mk b/writerperfect/source/filter/makefile.mk new file mode 100644 index 000000000000..e535d2aebbe0 --- /dev/null +++ b/writerperfect/source/filter/makefile.mk @@ -0,0 +1,27 @@ +PRJ=..$/.. + +PRJNAME=writerperfect +TARGET=filter +ENABLE_EXCEPTIONS=true + +.INCLUDE : settings.mk + +.IF "$(SYSTEM_LIBWPD)" == "YES" +INCPRE+=$(LIBWPD_CFLAGS) -I.. +.ELSE +# broken but ... necessary, internal include shafted ... +INCPRE+=-I.. +.ENDIF + +SLOFILES= \ + $(SLO)$/DocumentElement.obj \ + $(SLO)$/FontStyle.obj \ + $(SLO)$/ListStyle.obj \ + $(SLO)$/DocumentHandler.obj \ + $(SLO)$/PageSpan.obj \ + $(SLO)$/SectionStyle.obj \ + $(SLO)$/TableStyle.obj \ + $(SLO)$/TextRunStyle.obj \ + $(SLO)$/DocumentCollector.obj + +.INCLUDE : target.mk diff --git a/writerperfect/source/stream/WPXSvStream.cxx b/writerperfect/source/stream/WPXSvStream.cxx new file mode 100644 index 000000000000..973fb5ab31d9 --- /dev/null +++ b/writerperfect/source/stream/WPXSvStream.cxx @@ -0,0 +1,174 @@ +#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(true), + 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 uint8_t * WPXSvInputStream::read(size_t numBytes, size_t &numBytesRead) +{ + numBytesRead = 0; + + if (numBytes == 0 || atEOS()) + return 0; + + numBytesRead = mxStream->readSomeBytes (maData, numBytes); + if (numBytesRead == 0) + return 0; + + return (const uint8_t *)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; +} + +WPXInputStream * WPXSvInputStream::getDocumentOLEStream() +{ + return getDocumentOLEStream( "PerfectOffice_MAIN" ); +} diff --git a/writerperfect/source/stream/WPXSvStream.h b/writerperfect/source/stream/WPXSvStream.h new file mode 100644 index 000000000000..099c5a76eccf --- /dev/null +++ b/writerperfect/source/stream/WPXSvStream.h @@ -0,0 +1,47 @@ +#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/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(); + virtual WPXInputStream * getDocumentOLEStream(const char *name); + + virtual const uint8_t *read(size_t numBytes, size_t &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 diff --git a/writerperfect/source/stream/makefile.mk b/writerperfect/source/stream/makefile.mk new file mode 100644 index 000000000000..7e684b71bdb1 --- /dev/null +++ b/writerperfect/source/stream/makefile.mk @@ -0,0 +1,18 @@ +PRJ=..$/.. + +PRJNAME=writerperfect +TARGET=stream +ENABLE_EXCEPTIONS=true + +.INCLUDE : settings.mk + +.IF "$(SYSTEM_LIBWPD)" == "YES" +INCPRE+=$(LIBWPD_CFLAGS) +.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..0bc10cc0ba5b --- /dev/null +++ b/writerperfect/source/wpdimp/WordPerfectCollector.cxx @@ -0,0 +1,53 @@ +/* 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" +#if defined _MSC_VER +#pragma warning( pop ) +#endif + +WordPerfectCollector::WordPerfectCollector(WPXInputStream *pInput, DocumentHandler *pHandler) : + DocumentCollector(pInput, pHandler) +{ +} + +WordPerfectCollector::~WordPerfectCollector() +{ +} + +bool WordPerfectCollector::parseSourceDocument(WPXInputStream &input) +{ + WPDResult result = WPDocument::parse(&input, static_cast<WPXHLListenerImpl *>(this)); + if (result != WPD_OK) + return false; + + return true; +} diff --git a/writerperfect/source/wpdimp/WordPerfectCollector.hxx b/writerperfect/source/wpdimp/WordPerfectCollector.hxx new file mode 100644 index 000000000000..400a5ca8c856 --- /dev/null +++ b/writerperfect/source/wpdimp/WordPerfectCollector.hxx @@ -0,0 +1,41 @@ +/* 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" + +class WordPerfectCollector : public DocumentCollector +{ +public: + WordPerfectCollector(WPXInputStream *pInput, DocumentHandler *pHandler); + virtual ~WordPerfectCollector(); + bool parseSourceDocument(WPXInputStream &pInput); +}; +#endif diff --git a/writerperfect/source/wpdimp/WordPerfectImportFilter.cxx b/writerperfect/source/wpdimp/WordPerfectImportFilter.cxx new file mode 100644 index 000000000000..a6cdba08616c --- /dev/null +++ b/writerperfect/source/wpdimp/WordPerfectImportFilter.cxx @@ -0,0 +1,296 @@ +/* WordPerfectImportFilter: 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> +#ifndef _RTL_TENCINFO_H_ +#include <rtl/tencinfo.h> +#endif +#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> + +#ifndef _COM_SUN_STAR_UCB_XCOMMANDENVIRONMENT_HPP +#include <com/sun/star/ucb/XCommandEnvironment.hpp> +#endif + +#ifndef _ATTRLIST_HPP_ +#include <xmloff/attrlist.hxx> +#endif +#ifndef _XMLKYWD_HPP +#include <xmloff/xmlkywd.hxx> +#endif +#include <ucbhelper/content.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; + } + 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.XMLImporter" ) ); + 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); + + WPXSvInputStream input( xInputStream ); + + WordPerfectCollector collector(&input, &xHandler); + 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, false); + + if (confidence == WPD_CONFIDENCE_EXCELLENT) + sTypeName = OUString( RTL_CONSTASCII_USTRINGPARAM ( "writer_WordPerfect_Document" ) ); + + if (sTypeName.getLength()) + { + if ( location == Descriptor.getLength() ) + { + Descriptor.realloc(nLength+1); + Descriptor[location].Name = ::rtl::OUString::createFromAscii( "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); +// Sequence < OUString > aRet(1); + 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(); +} diff --git a/writerperfect/source/wpdimp/WordPerfectImportFilter.hxx b/writerperfect/source/wpdimp/WordPerfectImportFilter.hxx new file mode 100644 index 000000000000..4276329b960a --- /dev/null +++ b/writerperfect/source/wpdimp/WordPerfectImportFilter.hxx @@ -0,0 +1,115 @@ +/* + * 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 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 ); + +#endif diff --git a/writerperfect/source/wpdimp/makefile.mk b/writerperfect/source/wpdimp/makefile.mk new file mode 100644 index 000000000000..bc2a3cda544b --- /dev/null +++ b/writerperfect/source/wpdimp/makefile.mk @@ -0,0 +1,21 @@ +PRJ=..$/.. + +PRJNAME=writerperfect +TARGET=wpdimp +ENABLE_EXCEPTIONS=true + +.INCLUDE : settings.mk + +.IF "$(SYSTEM_LIBWPD)" == "YES" +INCPRE+=$(LIBWPD_CFLAGS) -I.. +.ELSE +# broken but ... necessary, internal include shafted ... +INCPRE+=-I.. +.ENDIF + +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..c117b93af3c7 --- /dev/null +++ b/writerperfect/source/wpdimp/wpft_genericfilter.cxx @@ -0,0 +1,98 @@ +/* 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::createFromAscii( "/UNO/SERVICES" ) ); + + const Sequence< OUString > & rSNL = WordPerfectImportFilter_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(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(); + } + } + + return pRet; +} +} |