diff options
Diffstat (limited to 'writerperfect')
54 files changed, 7605 insertions, 0 deletions
diff --git a/writerperfect/Library_msworks.mk b/writerperfect/Library_msworks.mk new file mode 100644 index 000000000000..a00106c810c5 --- /dev/null +++ b/writerperfect/Library_msworks.mk @@ -0,0 +1,68 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2011 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +$(eval $(call gb_Library_Library,msworks)) + +$(eval $(call gb_Library_set_componentfile,msworks,writerperfect/util/msworksfilter)) + +$(eval $(call gb_Library_set_include,msworks,\ + $$(INCLUDE) \ + -I$(realpath $(SRCDIR)/writerperfect/source) \ +)) + +$(eval $(call gb_Library_add_api,msworks,\ + offapi \ + udkapi \ +)) + +$(eval $(call gb_Library_add_linked_libs,msworks,\ + cppu \ + cppuhelper \ + sal \ + sot \ + ucbhelper \ + tl \ + utl \ + xo \ +)) + +$(eval $(call gb_Library_add_linked_static_libs,msworks,\ + writerperfect \ +)) + +$(eval $(call gb_Library_use_externals,msworks,\ + wpd \ + wps \ +)) + +$(eval $(call gb_Library_add_exception_objects,msworks,\ + writerperfect/source/wpsimp/MSWorksImportFilter \ + writerperfect/source/wpsimp/msworks_genericfilter \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/writerperfect/Library_visioimport.mk b/writerperfect/Library_visioimport.mk new file mode 100644 index 000000000000..e32ea32ddf2a --- /dev/null +++ b/writerperfect/Library_visioimport.mk @@ -0,0 +1,68 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2011 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +$(eval $(call gb_Library_Library,visioimport)) + +$(eval $(call gb_Library_set_componentfile,visioimport,writerperfect/util/visiofilter)) + +$(eval $(call gb_Library_set_include,visioimport,\ + $$(INCLUDE) \ + -I$(realpath $(SRCDIR)/writerperfect/source) \ +)) + +$(eval $(call gb_Library_add_api,visioimport,\ + offapi \ + udkapi \ +)) + +$(eval $(call gb_Library_add_linked_libs,visioimport,\ + cppu \ + cppuhelper \ + sal \ + sot \ + tl \ + utl \ + xo \ +)) + +$(eval $(call gb_Library_add_linked_static_libs,visioimport,\ + writerperfect \ +)) + +$(eval $(call gb_Library_use_externals,visioimport,\ + wpd \ + wpg \ + visio \ +)) + +$(eval $(call gb_Library_add_exception_objects,visioimport,\ + writerperfect/source/vsdimp/VisioImportFilter \ + writerperfect/source/vsdimp/visioimport_genericfilter \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/writerperfect/Library_wpft.mk b/writerperfect/Library_wpft.mk new file mode 100644 index 000000000000..ecc43862437d --- /dev/null +++ b/writerperfect/Library_wpft.mk @@ -0,0 +1,70 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2011 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +$(eval $(call gb_Library_Library,wpft)) + +$(eval $(call gb_Library_set_componentfile,wpft,writerperfect/util/wpft)) + +$(eval $(call gb_Library_set_include,wpft,\ + $$(INCLUDE) \ + -I$(realpath $(SRCDIR)/writerperfect/source) \ +)) + +$(eval $(call gb_Library_add_api,wpft,\ + offapi \ + udkapi \ +)) + +$(eval $(call gb_Library_add_linked_libs,wpft,\ + cppu \ + cppuhelper \ + vcl \ + sal \ + sfx \ + sot \ + tl \ + ucbhelper \ + utl \ + xo \ +)) + +$(eval $(call gb_Library_add_linked_static_libs,wpft,\ + writerperfect \ +)) + +$(eval $(call gb_Library_use_externals,wpft,\ + wpd \ + wpg \ +)) + +$(eval $(call gb_Library_add_exception_objects,wpft,\ + writerperfect/source/wpdimp/WordPerfectImportFilter \ + writerperfect/source/wpdimp/wpft_genericfilter \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/writerperfect/Library_wpgimport.mk b/writerperfect/Library_wpgimport.mk new file mode 100644 index 000000000000..d83cc98f29d7 --- /dev/null +++ b/writerperfect/Library_wpgimport.mk @@ -0,0 +1,67 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2011 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +$(eval $(call gb_Library_Library,wpgimport)) + +$(eval $(call gb_Library_set_componentfile,wpgimport,writerperfect/util/wpgfilter)) + +$(eval $(call gb_Library_set_include,wpgimport,\ + $$(INCLUDE) \ + -I$(realpath $(SRCDIR)/writerperfect/source) \ +)) + +$(eval $(call gb_Library_add_api,wpgimport,\ + offapi \ + udkapi \ +)) + +$(eval $(call gb_Library_add_linked_libs,wpgimport,\ + cppu \ + cppuhelper \ + sal \ + sot \ + tl \ + utl \ + xo \ +)) + +$(eval $(call gb_Library_add_linked_static_libs,wpgimport,\ + writerperfect \ +)) + +$(eval $(call gb_Library_use_externals,wpgimport,\ + wpd \ + wpg \ +)) + +$(eval $(call gb_Library_add_exception_objects,wpgimport,\ + writerperfect/source/wpgimp/WPGImportFilter \ + writerperfect/source/wpgimp/wpgimport_genericfilter \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/writerperfect/Makefile b/writerperfect/Makefile new file mode 100644 index 000000000000..3abf1ae8b6bb --- /dev/null +++ b/writerperfect/Makefile @@ -0,0 +1,39 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2011 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +ifeq ($(strip $(SOLARENV)),) +$(error No environment set!) +endif + +gb_PARTIALBUILD := T +GBUILDDIR := $(SOLARENV)/gbuild +include $(GBUILDDIR)/gbuild.mk + +$(eval $(call gb_Module_make_global_targets,$(shell ls $(dir $(realpath $(firstword $(MAKEFILE_LIST))))/Module*.mk))) + +# vim: set noet sw=4 ts=4: diff --git a/writerperfect/Module_writerperfect.mk b/writerperfect/Module_writerperfect.mk new file mode 100644 index 000000000000..9d0c77ad3f51 --- /dev/null +++ b/writerperfect/Module_writerperfect.mk @@ -0,0 +1,39 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2011 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +$(eval $(call gb_Module_Module,writerperfect)) + +$(eval $(call gb_Module_add_targets,writerperfect,\ + Library_msworks \ + Library_visioimport \ + Library_wpft \ + Library_wpgimport \ + StaticLibrary_writerperfect \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/writerperfect/StaticLibrary_writerperfect.mk b/writerperfect/StaticLibrary_writerperfect.mk new file mode 100644 index 000000000000..a31e4da1b980 --- /dev/null +++ b/writerperfect/StaticLibrary_writerperfect.mk @@ -0,0 +1,61 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2011 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +$(eval $(call gb_StaticLibrary_StaticLibrary,writerperfect)) + +$(eval $(call gb_StaticLibrary_set_include,writerperfect,\ + $$(INCLUDE) \ + -I$(realpath $(SRCDIR)/writerperfect/source) \ +)) + +$(echo $(call gb_StaticLibrary_use_externals,writerperfect,\ + wpd \ + wpg \ +)) + +$(eval $(call gb_StaticLibrary_add_api,writerperfect,\ + offapi \ + udkapi \ +)) + +$(eval $(call gb_StaticLibrary_add_exception_objects,writerperfect,\ + writerperfect/source/filter/DocumentElement \ + writerperfect/source/filter/DocumentHandler \ + writerperfect/source/filter/FontStyle \ + writerperfect/source/filter/InternalHandler \ + writerperfect/source/filter/ListStyle \ + writerperfect/source/filter/OdgGenerator \ + writerperfect/source/filter/OdtGenerator \ + writerperfect/source/filter/PageSpan \ + writerperfect/source/filter/SectionStyle \ + writerperfect/source/filter/TableStyle \ + writerperfect/source/filter/TextRunStyle \ + writerperfect/source/stream/WPXSvStream \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/writerperfect/prj/build.lst b/writerperfect/prj/build.lst new file mode 100644 index 000000000000..23f35dcc25cf --- /dev/null +++ b/writerperfect/prj/build.lst @@ -0,0 +1,3 @@ +wp writerperfect : LIBWPG:libwpg LIBWPS:libwps LIBWPD:libwpd LIBVISIO:libvisio sot comphelper xmloff svtools sfx2 LIBXSLT:libxslt NULL +wp writerperfect usr1 - all wp_mkout NULL +wp writerperfect\prj nmake - all wp_prj NULL diff --git a/writerperfect/prj/d.lst b/writerperfect/prj/d.lst new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/writerperfect/prj/d.lst diff --git a/writerperfect/prj/makefile.mk b/writerperfect/prj/makefile.mk new file mode 100644 index 000000000000..85b25665cc83 --- /dev/null +++ b/writerperfect/prj/makefile.mk @@ -0,0 +1,40 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=.. +TARGET=prj + +.INCLUDE : settings.mk + +.IF "$(VERBOSE)"!="" +VERBOSEFLAG := +.ELSE +VERBOSEFLAG := -s +.ENDIF + +all: + cd $(PRJ) && $(GNUMAKE) $(VERBOSEFLAG) -r -j$(GMAKE_MODULE_PARALLELISM) $(gb_MAKETARGET) && $(GNUMAKE) $(VERBOSEFLAG) -r deliverlog diff --git a/writerperfect/source/filter/DocumentElement.cxx b/writerperfect/source/filter/DocumentElement.cxx new file mode 100644 index 000000000000..f42331c527bc --- /dev/null +++ b/writerperfect/source/filter/DocumentElement.cxx @@ -0,0 +1,73 @@ +/* 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 (wrlach@gmail.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 + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#include "DocumentElement.hxx" +#include "OdfDocumentHandler.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(OdfDocumentHandler *pHandler) const +{ + pHandler->startElement(getTagName().cstr(), maAttrList); +} + +void TagOpenElement::print() const +{ + TagElement::print(); +} + +void TagOpenElement::addAttribute(const WPXString &szAttributeName, const WPXString &sAttributeValue) +{ + maAttrList.insert(szAttributeName.cstr(), sAttributeValue); +} + +void TagCloseElement::write(OdfDocumentHandler *pHandler) const +{ + WRITER_DEBUG_MSG(("TagCloseElement: write (%s)\n", getTagName().cstr())); + + pHandler->endElement(getTagName().cstr()); +} + +void CharDataElement::write(OdfDocumentHandler *pHandler) const +{ + WRITER_DEBUG_MSG(("TextElement: write\n")); + pHandler->characters(msData); +} + +void TextElement::write(OdfDocumentHandler *pHandler) const +{ + if (msTextBuf.len() <= 0) + return; + pHandler->characters(msTextBuf); +} diff --git a/writerperfect/source/filter/DocumentElement.hxx b/writerperfect/source/filter/DocumentElement.hxx new file mode 100644 index 000000000000..6de5db3d8eb2 --- /dev/null +++ b/writerperfect/source/filter/DocumentElement.hxx @@ -0,0 +1,97 @@ +/* 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 (wrlach@gmail.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 + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#ifndef _DOCUMENTELEMENT_H +#define _DOCUMENTELEMENT_H +#include <libwpd/libwpd.h> +#include <libwpd/WPXProperty.h> +#include <libwpd/WPXString.h> +#include <vector> + +#include "OdfDocumentHandler.hxx" + +class DocumentElement +{ +public: + virtual ~DocumentElement() {} + virtual void write(OdfDocumentHandler *pHandler) const = 0; + virtual void print() const {} +}; + +class TagElement : public DocumentElement +{ +public: + virtual ~TagElement() {} + TagElement(const WPXString &szTagName) : msTagName(szTagName) {} + const WPXString & getTagName() const { return msTagName; } + virtual void print() const; +private: + WPXString msTagName; +}; + +class TagOpenElement : public TagElement +{ +public: + TagOpenElement(const WPXString &szTagName) : TagElement(szTagName) {} + virtual ~TagOpenElement() {} + void addAttribute(const WPXString &szAttributeName, const WPXString &sAttributeValue); + virtual void write(OdfDocumentHandler *pHandler) const; + virtual void print () const; +private: + WPXPropertyList maAttrList; +}; + +class TagCloseElement : public TagElement +{ +public: + TagCloseElement(const WPXString &szTagName) : TagElement(szTagName) {} + virtual ~TagCloseElement() {} + virtual void write(OdfDocumentHandler *pHandler) const; +}; + +class CharDataElement : public DocumentElement +{ +public: + CharDataElement(const WPXString &sData) : DocumentElement(), msData(sData) {} + virtual ~CharDataElement() {} + virtual void write(OdfDocumentHandler *pHandler) const; +private: + WPXString msData; +}; + +class TextElement : public DocumentElement +{ +public: + TextElement(const WPXString &sTextBuf) : DocumentElement(), msTextBuf(sTextBuf, false) {} + virtual ~TextElement() {} + virtual void write(OdfDocumentHandler *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..c61ffc0c19c5 --- /dev/null +++ b/writerperfect/source/filter/DocumentHandler.cxx @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2004 William Lachance (william.lachance@sympatico.ca) + * Copyright (C) 2004 Net Integration Technologies (http://www.net-itech.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ +#include "DocumentHandler.hxx" +#include "FilterInternal.hxx" + +#include <string.h> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XAttributeList.hpp> + +#include <xmloff/attrlist.hxx> + +// #define DEBUG_XML 1 + +using namespace ::rtl; +using rtl::OUString; + +using com::sun::star::xml::sax::XAttributeList; + +DocumentHandler::DocumentHandler(Reference < XDocumentHandler > &xHandler) : + mxHandler(xHandler) +{ +} + +void DocumentHandler::startDocument() +{ + mxHandler->startDocument(); +} + +void DocumentHandler::endDocument() +{ + mxHandler->endDocument(); +} + +void DocumentHandler::startElement(const char *psName, const WPXPropertyList &xPropList) +{ +#ifdef DEBUG_XML + printf("<%s", psName); +#endif + SvXMLAttributeList *pAttrList = new SvXMLAttributeList(); + Reference < XAttributeList > xAttrList(pAttrList); + WPXPropertyList::Iter i(xPropList); + for (i.rewind(); i.next(); ) + { + // filter out libwpd elements + if (strncmp(i.key(), "libwpd", 6) != 0) + { + pAttrList->AddAttribute(OUString::createFromAscii(i.key()), + OUString::createFromAscii(i()->getStr().cstr())); +#ifdef DEBUG_XML + printf(" %s=\"%s\"", i.key(), i()->getStr().cstr()); +#endif + } + } +#ifdef DEBUG_XML + printf(">"); +#endif + + mxHandler->startElement(OUString::createFromAscii(psName), xAttrList); +} + +void DocumentHandler::endElement(const char *psName) +{ +#ifdef DEBUG_XML + printf("</%s>", psName); +#endif + mxHandler->endElement(OUString::createFromAscii(psName)); +} + +void DocumentHandler::characters(const WPXString &sCharacters) +{ + OUString sCharU16(sCharacters.cstr(), strlen(sCharacters.cstr()), RTL_TEXTENCODING_UTF8); +#ifdef DEBUG_XML + WPXString sEscapedCharacters(sCharacters, true); + printf("%s", sEscapedCharacters.cstr()); +#endif + mxHandler->characters(sCharU16); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/DocumentHandler.hxx b/writerperfect/source/filter/DocumentHandler.hxx new file mode 100644 index 000000000000..692c35e3b462 --- /dev/null +++ b/writerperfect/source/filter/DocumentHandler.hxx @@ -0,0 +1,36 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#ifndef _OODOCUMENTHANDLER_HXX_ +#define _OODOCUMENTHANDLER_HXX_ + +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> + +#if defined _MSC_VER +#pragma warning( push, 1 ) +#endif +#include <libwpd/libwpd.h> +#if defined _MSC_VER +#pragma warning( pop ) +#endif + +#include "OdfDocumentHandler.hxx" + +using com::sun::star::uno::Reference; +using com::sun::star::xml::sax::XDocumentHandler; + +class DocumentHandler: public OdfDocumentHandler +{ +public: + DocumentHandler(Reference < XDocumentHandler > &xHandler); + void startDocument(); + void endDocument(); + void startElement(const char *psName, const WPXPropertyList &xPropList); + void endElement(const char *psName); + void characters(const WPXString &sCharacters); + +private: + Reference < XDocumentHandler > mxHandler; +}; + +#endif // _OODOCUMENTHANDLER_HXX_ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/filter/FilterInternal.hxx b/writerperfect/source/filter/FilterInternal.hxx new file mode 100644 index 000000000000..1b806337fffa --- /dev/null +++ b/writerperfect/source/filter/FilterInternal.hxx @@ -0,0 +1,36 @@ +/* FilterInternal: Debugging information + * + * Copyright (C) 2002-2003 William Lachance (wrlach@gmail.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 + * + */ +#ifndef __FILTERINTERNAL_HXX__ +#define __FILTERINTERNAL_HXX__ + +#ifdef DEBUG +#include <stdio.h> +#define WRITER_DEBUG_MSG(M) printf M +#else +#define WRITER_DEBUG_MSG(M) +#endif + +const double fDefaultSideMargin = 1.0; // inches +const double fDefaultPageWidth = 8.5f; // inches (OOo required default: we will handle this later) +const double fDefaultPageHeight = 11.0; // inches + +#endif diff --git a/writerperfect/source/filter/FontStyle.cxx b/writerperfect/source/filter/FontStyle.cxx new file mode 100644 index 000000000000..509fa16e02ec --- /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 (wrlach@gmail.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 + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#include "FontStyle.hxx" +#include "WriterProperties.hxx" +#include "DocumentElement.hxx" + +FontStyle::FontStyle(const char *psName, const char *psFontFamily) : Style(psName), + msFontFamily(psFontFamily, true), + msFontPitch(IMP_DEFAULT_FONT_PITCH) +{ +} + +FontStyle::~FontStyle() +{ +} + +void FontStyle::write(OdfDocumentHandler *pHandler) const +{ + TagOpenElement styleOpen("style:font-face"); + styleOpen.addAttribute("style:name", getName()); + styleOpen.addAttribute("svg:font-family", msFontFamily); +// styleOpen.addAttribute("style:font-pitch", msFontPitch); + styleOpen.write(pHandler); + TagCloseElement styleClose("style:font-face"); + styleClose.write(pHandler); +} diff --git a/writerperfect/source/filter/FontStyle.hxx b/writerperfect/source/filter/FontStyle.hxx new file mode 100644 index 000000000000..7f1a44e3f613 --- /dev/null +++ b/writerperfect/source/filter/FontStyle.hxx @@ -0,0 +1,46 @@ +/* FontStyle: Stores (and writes) font-based information that is needed at + * the head of an OO document. + * + * Copyright (C) 2002-2003 William Lachance (wrlach@gmail.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 + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef _FONTSTYLE_H +#define _FONTSTYLE_H +#include <libwpd/libwpd.h> + +#include "Style.hxx" +#include "WriterProperties.hxx" + +class FontStyle : public Style +{ +public: + FontStyle(const char *psName, const char *psFontFamily); + ~FontStyle(); + virtual void write(OdfDocumentHandler *pHandler) const; + const WPXString &getFontFamily() const { return msFontFamily; } + +private: + WPXString msFontFamily; + WPXString msFontPitch; +}; +#endif diff --git a/writerperfect/source/filter/InternalHandler.cxx b/writerperfect/source/filter/InternalHandler.cxx new file mode 100644 index 000000000000..8582047f0b0b --- /dev/null +++ b/writerperfect/source/filter/InternalHandler.cxx @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2007 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. + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#include "InternalHandler.hxx" + +#include <string.h> + +InternalHandler::InternalHandler(std::vector<DocumentElement *> *elements): + mpElements(elements) +{ +} + +void InternalHandler::startElement(const char *psName, const WPXPropertyList &xPropList) +{ + TagOpenElement *element = new TagOpenElement(psName); + WPXPropertyList::Iter i(xPropList); + for (i.rewind(); i.next(); ) + { + // filter out libwpd elements + if (strncmp(i.key(), "libwpd", 6) != 0) + element->addAttribute(i.key(), i()->getStr()); + } + mpElements->push_back(element); +} + +void InternalHandler::endElement(const char *psName) +{ + mpElements->push_back(new TagCloseElement(psName)); +} + +void InternalHandler::characters(const WPXString &sCharacters) +{ + mpElements->push_back(new CharDataElement(sCharacters.cstr())); +} diff --git a/writerperfect/source/filter/InternalHandler.hxx b/writerperfect/source/filter/InternalHandler.hxx new file mode 100644 index 000000000000..a0f16382e347 --- /dev/null +++ b/writerperfect/source/filter/InternalHandler.hxx @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2007 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. + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#ifndef _INTERNALHANDLER_H +#define _INTERNALHANDLER_H +#include <libwpd/libwpd.h> +#include <libwpd/WPXProperty.h> +#include <libwpd/WPXString.h> +#include "DocumentElement.hxx" +#include "OdfDocumentHandler.hxx" + +class InternalHandler : public OdfDocumentHandler +{ +public: + InternalHandler(std::vector<DocumentElement *> *elements); + ~InternalHandler() {}; + + void startDocument() {}; + void endDocument() {}; + void startElement(const char *psName, const WPXPropertyList &xPropList); + void endElement(const char *psName); + void characters(const WPXString &sCharacters); +private: + std::vector<DocumentElement *> *mpElements; +}; +#endif diff --git a/writerperfect/source/filter/ListStyle.cxx b/writerperfect/source/filter/ListStyle.cxx new file mode 100644 index 000000000000..f9720b9010c4 --- /dev/null +++ b/writerperfect/source/filter/ListStyle.cxx @@ -0,0 +1,183 @@ +/* ListStyle: Stores (and writes) list-based information that is + * needed at the head of an OO document. + * + * Copyright (C) 2002-2003 William Lachance (wrlach@gmail.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 + * + */ + +/* "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(OdfDocumentHandler *pHandler, int iLevel) const +{ + WPXString sLevel; + sLevel.sprintf("%i", (iLevel+1)); + + TagOpenElement listLevelStyleOpen("text:list-level-style-number"); + listLevelStyleOpen.addAttribute("text:level", sLevel); + listLevelStyleOpen.addAttribute("text:style-name", "Numbering_Symbols"); + if (mPropList["style:num-prefix"]) + { + WPXString sEscapedString(mPropList["style:num-prefix"]->getStr(), true); + listLevelStyleOpen.addAttribute("style:num-prefix", sEscapedString); + } + if (mPropList["style:num-suffix"]) + { + WPXString sEscapedString(mPropList["style:num-suffix"]->getStr(), true); + listLevelStyleOpen.addAttribute("style:num-suffix", sEscapedString); + } + if (mPropList["style:num-format"]) + listLevelStyleOpen.addAttribute("style:num-format", mPropList["style:num-format"]->getStr()); + if (mPropList["text:start-value"]) + { + // odf as to the version 1.1 does require the text:start-value to be a positive integer, means > 0 + if (mPropList["text:start-value"]->getInt() > 0) + listLevelStyleOpen.addAttribute("text:start-value", mPropList["text:start-value"]->getStr()); + else + listLevelStyleOpen.addAttribute("text:start-value", "1"); + } + listLevelStyleOpen.write(pHandler); + + TagOpenElement stylePropertiesOpen("style:list-level-properties"); + if (mPropList["text:space-before"] && mPropList["text:space-before"]->getDouble() > 0.0) + stylePropertiesOpen.addAttribute("text:space-before", mPropList["text:space-before"]->getStr()); + if (mPropList["text:min-label-width"] && mPropList["text:min-label-width"]->getDouble() > 0.0) + stylePropertiesOpen.addAttribute("text:min-label-width", mPropList["text:min-label-width"]->getStr()); + if (mPropList["text:min-label-distance"] && mPropList["text:min-label-distance"]->getDouble() > 0.0) + stylePropertiesOpen.addAttribute("text:min-label-distance", mPropList["text:min-label-distance"]->getStr()); + stylePropertiesOpen.write(pHandler); + + pHandler->endElement("style:list-level-properties"); + pHandler->endElement("text:list-level-style-number"); +} + +UnorderedListLevelStyle::UnorderedListLevelStyle(const WPXPropertyList &xPropList) + : mPropList(xPropList) +{ +} + +void UnorderedListStyle::updateListLevel(const int iLevel, const WPXPropertyList &xPropList) +{ + if (iLevel < 0) + return; + if (!isListLevelDefined(iLevel)) + setListLevel(iLevel, new UnorderedListLevelStyle(xPropList)); +} + +void UnorderedListLevelStyle::write(OdfDocumentHandler *pHandler, int iLevel) const +{ + WPXString sLevel; + sLevel.sprintf("%i", (iLevel+1)); + TagOpenElement listLevelStyleOpen("text:list-level-style-bullet"); + listLevelStyleOpen.addAttribute("text:level", sLevel); + listLevelStyleOpen.addAttribute("text:style-name", "Bullet_Symbols"); + if (mPropList["text:bullet-char"] && (mPropList["text:bullet-char"]->getStr().len())) + { + // The following is needed because the odf format does not accept bullet chars longer than one character + WPXString::Iter i(mPropList["text:bullet-char"]->getStr()); i.rewind(); + WPXString sEscapedString("."); + if (i.next()) + sEscapedString = WPXString(i(), true); + listLevelStyleOpen.addAttribute("text:bullet-char", sEscapedString); + + } + else + listLevelStyleOpen.addAttribute("text:bullet-char", "."); + listLevelStyleOpen.write(pHandler); + + TagOpenElement stylePropertiesOpen("style:list-level-properties"); + if (mPropList["text:space-before"] && mPropList["text:space-before"]->getDouble() > 0.0) + stylePropertiesOpen.addAttribute("text:space-before", mPropList["text:space-before"]->getStr()); + if (mPropList["text:min-label-width"] && mPropList["text:min-label-width"]->getDouble() > 0.0) + stylePropertiesOpen.addAttribute("text:min-label-width", mPropList["text:min-label-width"]->getStr()); + if (mPropList["text:min-label-distance"] && mPropList["text:min-label-distance"]->getDouble() > 0.0) + stylePropertiesOpen.addAttribute("text:min-label-distance", mPropList["text:min-label-distance"]->getStr()); + stylePropertiesOpen.addAttribute("style:font-name", "OpenSymbol"); + stylePropertiesOpen.write(pHandler); + + pHandler->endElement("style:list-level-properties"); + pHandler->endElement("text:list-level-style-bullet"); +} + +ListStyle::ListStyle(const char *psName, const int iListID) : + Style(psName), + miNumListLevels(0), + 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(OdfDocumentHandler *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..32f2d9c65a3d --- /dev/null +++ b/writerperfect/source/filter/ListStyle.hxx @@ -0,0 +1,95 @@ +/* ListStyle: Stores (and writes) list-based information that is + * needed at the head of an OO document. + * + * Copyright (C) 2002-2003 William Lachance (wrlach@gmail.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 + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef _LISTSTYLE_H +#define _LISTSTYLE_H +#include <libwpd/libwpd.h> + +#define WP6_NUM_LIST_LEVELS 8 // see WP6FileStructure.h (we shouldn't need to reference this) + +#include "Style.hxx" +#include "WriterProperties.hxx" + +class DocumentElement; + +class ListLevelStyle +{ +public: + virtual ~ListLevelStyle() {}; + virtual void write(OdfDocumentHandler *pHandler, int iLevel) const = 0; +}; + +class OrderedListLevelStyle : public ListLevelStyle +{ +public: + OrderedListLevelStyle(const WPXPropertyList &xPropList); + void write(OdfDocumentHandler *pHandler, int iLevel) const; +private: + WPXPropertyList mPropList; +}; + +class UnorderedListLevelStyle : public ListLevelStyle +{ +public: + UnorderedListLevelStyle(const WPXPropertyList &xPropList); + void write(OdfDocumentHandler *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(OdfDocumentHandler *pHandler) const; + int getListID() { 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/OdfDocumentHandler.hxx b/writerperfect/source/filter/OdfDocumentHandler.hxx new file mode 100644 index 000000000000..0b7288cb09ef --- /dev/null +++ b/writerperfect/source/filter/OdfDocumentHandler.hxx @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2004 William Lachance (wlach@interlog.com) + * Copyright (C) 2004 Net Integration Technologies (http://www.net-itech.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Contributor(s): Martin Gallwey (gallwey@sun.com) + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef _DOCUMENTHANDLER_H +#define _DOCUMENTHANDLER_H +#include <libwpd/libwpd.h> + +enum OdfStreamType { ODF_FLAT_XML, ODF_CONTENT_XML, ODF_STYLES_XML, ODF_SETTINGS_XML, ODF_META_XML }; + +class OdfDocumentHandler +{ +public: + OdfDocumentHandler() {}; + virtual ~OdfDocumentHandler() {}; + + virtual void startDocument() = 0; + virtual void endDocument() = 0; + virtual void startElement(const char *psName, const WPXPropertyList &xPropList) = 0; + virtual void endElement(const char *psName) = 0; + virtual void characters(const WPXString &sCharacters) = 0; +}; +#endif diff --git a/writerperfect/source/filter/OdgGenerator.cxx b/writerperfect/source/filter/OdgGenerator.cxx new file mode 100644 index 000000000000..e4404e8e7f51 --- /dev/null +++ b/writerperfect/source/filter/OdgGenerator.cxx @@ -0,0 +1,1206 @@ +/* libwpg + * Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) + * Copyright (C) 2006 Fridrich Strba (fridrich.strba@bluewin.ch) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02111-1301 USA + * + * For further information visit http://libwpg.sourceforge.net + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#include "OdgGenerator.hxx" +#include "DocumentElement.hxx" +#include "OdfDocumentHandler.hxx" +#include <locale.h> +#include <math.h> +#include <string> + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +// Workaround for the incapacity of draw to have multiple page +// sizes in the same document. Once that limitation is lifted, +// remove this +#define MULTIPAGE_WORKAROUND 1 + +static inline double getAngle(double bx, double by) +{ + return fmod(2*M_PI + (by > 0.0 ? 1.0 : -1.0) * acos( bx / sqrt(bx * bx + by * by) ), 2*M_PI); +} + +static void getEllipticalArcBBox(double x1, double y1, + double rx, double ry, double phi, bool largeArc, bool sweep, double x2, double y2, + double &xmin, double &ymin, double &xmax, double &ymax) +{ + phi *= M_PI/180; + if (rx < 0.0) + rx *= -1.0; + if (ry < 0.0) + ry *= -1.0; + + if (rx == 0.0 || ry == 0.0) + { + xmin = (x1 < x2 ? x1 : x2); + xmax = (x1 > x2 ? x1 : x2); + ymin = (y1 < y2 ? y1 : y2); + ymax = (y1 > y2 ? y1 : y2); + return; + } + + // F.6.5.1 + const double x1prime = cos(phi)*(x1 - x2)/2 + sin(phi)*(y1 - y2)/2; + const double y1prime = -sin(phi)*(x1 - x2)/2 + cos(phi)*(y1 - y2)/2; + + // F.6.5.2 + double radicant = (rx*rx*ry*ry - rx*rx*y1prime*y1prime - ry*ry*x1prime*x1prime)/(rx*rx*y1prime*y1prime + ry*ry*x1prime*x1prime); + double cxprime = 0.0; + double cyprime = 0.0; + if (radicant < 0.0) + { + double ratio = rx/ry; + radicant = y1prime*y1prime + x1prime*x1prime/(ratio*ratio); + if (radicant < 0.0) + { + xmin = (x1 < x2 ? x1 : x2); + xmax = (x1 > x2 ? x1 : x2); + ymin = (y1 < y2 ? y1 : y2); + ymax = (y1 > y2 ? y1 : y2); + return; + } + ry=sqrt(radicant); + rx=ratio*ry; + } + else + { + double factor = (largeArc==sweep ? -1.0 : 1.0)*sqrt(radicant); + + cxprime = factor*rx*y1prime/ry; + cyprime = -factor*ry*x1prime/rx; + } + + // F.6.5.3 + double cx = cxprime*cos(phi) - cyprime*sin(phi) + (x1 + x2)/2; + double cy = cxprime*sin(phi) + cyprime*cos(phi) + (y1 + y2)/2; + + // now compute bounding box of the whole ellipse + + // Parametric equation of an ellipse: + // x(theta) = cx + rx*cos(theta)*cos(phi) - ry*sin(theta)*sin(phi) + // y(theta) = cy + rx*cos(theta)*sin(phi) + ry*sin(theta)*cos(phi) + + // Compute local extrems + // 0 = -rx*sin(theta)*cos(phi) - ry*cos(theta)*sin(phi) + // 0 = -rx*sin(theta)*sin(phi) - ry*cos(theta)*cos(phi) + + // Local extrems for X: + // theta = -atan(ry*tan(phi)/rx) + // and + // theta = M_PI -atan(ry*tan(phi)/rx) + + // Local extrems for Y: + // theta = atan(ry/(tan(phi)*rx)) + // and + // theta = M_PI + atan(ry/(tan(phi)*rx)) + + double txmin, txmax, tymin, tymax; + + // First handle special cases + if (phi == 0 || phi == M_PI) + { + xmin = cx - rx; + txmin = getAngle(-rx, 0); + xmax = cx + rx; + txmax = getAngle(rx, 0); + ymin = cy - ry; + tymin = getAngle(0, -ry); + ymax = cy + ry; + tymax = getAngle(0, ry); + } + else if (phi == M_PI / 2.0 || phi == 3.0*M_PI/2.0) + { + xmin = cx - ry; + txmin = getAngle(-ry, 0); + xmax = cx + ry; + txmax = getAngle(ry, 0); + ymin = cy - rx; + tymin = getAngle(0, -rx); + ymax = cy + rx; + tymax = getAngle(0, rx); + } + else + { + txmin = -atan(ry*tan(phi)/rx); + txmax = M_PI - atan (ry*tan(phi)/rx); + xmin = cx + rx*cos(txmin)*cos(phi) - ry*sin(txmin)*sin(phi); + xmax = cx + rx*cos(txmax)*cos(phi) - ry*sin(txmax)*sin(phi); + double tmpY = cy + rx*cos(txmin)*sin(phi) + ry*sin(txmin)*cos(phi); + txmin = getAngle(xmin - cx, tmpY - cy); + tmpY = cy + rx*cos(txmax)*sin(phi) + ry*sin(txmax)*cos(phi); + txmax = getAngle(xmax - cx, tmpY - cy); + + tymin = atan(ry/(tan(phi)*rx)); + tymax = atan(ry/(tan(phi)*rx))+M_PI; + ymin = cy + rx*cos(tymin)*sin(phi) + ry*sin(tymin)*cos(phi); + ymax = cy + rx*cos(tymax)*sin(phi) + ry*sin(tymax)*cos(phi); + double tmpX = cx + rx*cos(tymin)*cos(phi) - ry*sin(tymin)*sin(phi); + tymin = getAngle(tmpX - cx, ymin - cy); + tmpX = cx + rx*cos(tymax)*cos(phi) - ry*sin(tymax)*sin(phi); + tymax = getAngle(tmpX - cx, ymax - cy); + } + if (xmin > xmax) + { + std::swap(xmin,xmax); + std::swap(txmin,txmax); + } + if (ymin > ymax) + { + std::swap(ymin,ymax); + std::swap(tymin,tymax); + } + double angle1 = getAngle(x1 - cx, y1 - cy); + double angle2 = getAngle(x2 - cx, y2 - cy); + + // for sweep == 0 it is normal to have delta theta < 0 + // but we don't care about the rotation direction for bounding box + if (!sweep) + std::swap(angle1, angle2); + + // We cannot check directly for whether an angle is included in + // an interval of angles that cross the 360/0 degree boundary + // So here we will have to check for their absence in the complementary + // angle interval + bool otherArc = false; + if (angle1 > angle2) + { + std::swap(angle1, angle2); + otherArc = true; + } + + // Check txmin + if ((!otherArc && (angle1 > txmin || angle2 < txmin)) || (otherArc && !(angle1 > txmin || angle2 < txmin))) + xmin = x1 < x2 ? x1 : x2; + // Check txmax + if ((!otherArc && (angle1 > txmax || angle2 < txmax)) || (otherArc && !(angle1 > txmax || angle2 < txmax))) + xmax = x1 > x2 ? x1 : x2; + // Check tymin + if ((!otherArc && (angle1 > tymin || angle2 < tymin)) || (otherArc && !(angle1 > tymin || angle2 < tymin))) + ymin = y1 < y2 ? y1 : y2; + // Check tymax + if ((!otherArc && (angle1 > tymax || angle2 < tymax)) || (otherArc && !(angle1 > tymax || angle2 < tymax))) + ymax = y1 > y2 ? y1 : y2; +} + +static WPXString doubleToString(const double value) +{ + WPXString tempString; + tempString.sprintf("%.4f", value); +#ifndef __ANDROID__ + std::string decimalPoint(localeconv()->decimal_point); +#else + std::string decimalPoint("."); +#endif + if ((decimalPoint.size() == 0) || (decimalPoint == ".")) + return tempString; + std::string stringValue(tempString.cstr()); + if (!stringValue.empty()) + { + std::string::size_type pos; + while ((pos = stringValue.find(decimalPoint)) != std::string::npos) + stringValue.replace(pos,decimalPoint.size(),"."); + } + return WPXString(stringValue.c_str()); +} + +class OdgGeneratorPrivate +{ +public: + OdgGeneratorPrivate(OdfDocumentHandler *pHandler, const OdfStreamType streamType); + ~OdgGeneratorPrivate(); + void _writeGraphicsStyle(); + void _drawPolySomething(const ::WPXPropertyListVector& vertices, bool isClosed); + void _drawPath(const WPXPropertyListVector& path); + // body elements + std::vector <DocumentElement *> mBodyElements; + + // graphics styles + std::vector<DocumentElement *> mGraphicsStrokeDashStyles; + std::vector<DocumentElement *> mGraphicsGradientStyles; + std::vector<DocumentElement *> mGraphicsAutomaticStyles; + + // page styles + std::vector<DocumentElement *> mPageAutomaticStyles; + std::vector<DocumentElement *> mPageMasterStyles; + + OdfDocumentHandler *mpHandler; + + ::WPXPropertyList mxStyle; + ::WPXPropertyListVector mxGradient; + int miGradientIndex; + int miDashIndex; + int miGraphicsStyleIndex; + int miPageIndex; + double mfWidth, mfMaxWidth; + double mfHeight, mfMaxHeight; + + const OdfStreamType mxStreamType; +}; + +OdgGeneratorPrivate::OdgGeneratorPrivate(OdfDocumentHandler *pHandler, const OdfStreamType streamType): + mpHandler(pHandler), + miGradientIndex(1), + miDashIndex(1), + miGraphicsStyleIndex(1), + miPageIndex(1), + mfWidth(0.0), + mfMaxWidth(0.0), + mfHeight(0.0), + mfMaxHeight(0.0), + mxStreamType(streamType) +{ +} + +OdgGeneratorPrivate::~OdgGeneratorPrivate() +{ + + for (std::vector<DocumentElement *>::iterator iterBody = mBodyElements.begin(); iterBody != mBodyElements.end(); ++iterBody) + { + delete (*iterBody); + (*iterBody) = NULL; + } + + for (std::vector<DocumentElement *>::iterator iterGraphicsAutomaticStyles = mGraphicsAutomaticStyles.begin(); + iterGraphicsAutomaticStyles != mGraphicsAutomaticStyles.end(); ++iterGraphicsAutomaticStyles) + { + delete((*iterGraphicsAutomaticStyles)); + } + + for (std::vector<DocumentElement *>::iterator iterGraphicsStrokeDashStyles = mGraphicsStrokeDashStyles.begin(); + iterGraphicsStrokeDashStyles != mGraphicsStrokeDashStyles.end(); ++iterGraphicsStrokeDashStyles) + { + delete((*iterGraphicsStrokeDashStyles)); + } + + for (std::vector<DocumentElement *>::iterator iterGraphicsGradientStyles = mGraphicsGradientStyles.begin(); + iterGraphicsGradientStyles != mGraphicsGradientStyles.end(); ++iterGraphicsGradientStyles) + { + delete((*iterGraphicsGradientStyles)); + } + + for (std::vector<DocumentElement *>::iterator iterPageAutomaticStyles = mPageAutomaticStyles.begin(); + iterPageAutomaticStyles != mPageAutomaticStyles.end(); ++iterPageAutomaticStyles) + { + delete((*iterPageAutomaticStyles)); + } + + for (std::vector<DocumentElement *>::iterator iterPageMasterStyles = mPageMasterStyles.begin(); + iterPageMasterStyles != mPageMasterStyles.end(); ++iterPageMasterStyles) + { + delete((*iterPageMasterStyles)); + } +} + +OdgGenerator::OdgGenerator(OdfDocumentHandler *pHandler, const OdfStreamType streamType): + mpImpl(new OdgGeneratorPrivate(pHandler, streamType)) +{ + mpImpl->mpHandler->startDocument(); + TagOpenElement tmpOfficeDocumentContent( + (mpImpl->mxStreamType == ODF_FLAT_XML) ? "office:document" : ( + (mpImpl->mxStreamType == ODF_CONTENT_XML) ? "office:document-content" : ( + (mpImpl->mxStreamType == ODF_STYLES_XML) ? "office:document-styles" : ( + (mpImpl->mxStreamType == ODF_SETTINGS_XML) ? "office:document-settings" : ( + (mpImpl->mxStreamType == ODF_META_XML) ? "office:document-meta" : "office:document" ))))); + tmpOfficeDocumentContent.addAttribute("xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0"); + tmpOfficeDocumentContent.addAttribute("xmlns:style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0"); + tmpOfficeDocumentContent.addAttribute("xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0"); + tmpOfficeDocumentContent.addAttribute("xmlns:draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"); + tmpOfficeDocumentContent.addAttribute("xmlns:dc", "http://purl.org/dc/elements/1.1/"); + tmpOfficeDocumentContent.addAttribute("xmlns:svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"); + tmpOfficeDocumentContent.addAttribute("xmlns:fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"); + tmpOfficeDocumentContent.addAttribute("xmlns:config", "urn:oasis:names:tc:opendocument:xmlns:config:1.0"); + tmpOfficeDocumentContent.addAttribute("xmlns:ooo", "http://openoffice.org/2004/office"); + tmpOfficeDocumentContent.addAttribute("office:version", "1.0"); + if (mpImpl->mxStreamType == ODF_FLAT_XML) + tmpOfficeDocumentContent.addAttribute("office:mimetype", "application/vnd.oasis.opendocument.graphics"); + tmpOfficeDocumentContent.write(mpImpl->mpHandler); +} + +OdgGenerator::~OdgGenerator() +{ + if ((mpImpl->mxStreamType == ODF_FLAT_XML) || (mpImpl->mxStreamType == ODF_SETTINGS_XML)) + { + TagOpenElement("office:settings").write(mpImpl->mpHandler); + + TagOpenElement configItemSetOpenElement("config:config-item-set"); + configItemSetOpenElement.addAttribute("config:name", "ooo:view-settings"); + configItemSetOpenElement.write(mpImpl->mpHandler); + + TagOpenElement configItemOpenElement("config:config-item"); + + configItemOpenElement.addAttribute("config:name", "VisibleAreaTop"); + configItemOpenElement.addAttribute("config:type", "int"); + configItemOpenElement.write(mpImpl->mpHandler); + mpImpl->mpHandler->characters("0"); + mpImpl->mpHandler->endElement("config:config-item"); + + configItemOpenElement.addAttribute("config:name", "VisibleAreaLeft"); + configItemOpenElement.addAttribute("config:type", "int"); + configItemOpenElement.write(mpImpl->mpHandler); + mpImpl->mpHandler->characters("0"); + mpImpl->mpHandler->endElement("config:config-item"); + + configItemOpenElement.addAttribute("config:name", "VisibleAreaWidth"); + configItemOpenElement.addAttribute("config:type", "int"); + configItemOpenElement.write(mpImpl->mpHandler); + WPXString sWidth; sWidth.sprintf("%li", (unsigned long)(2540 * mpImpl->mfMaxWidth)); + mpImpl->mpHandler->characters(sWidth); + mpImpl->mpHandler->endElement("config:config-item"); + + configItemOpenElement.addAttribute("config:name", "VisibleAreaHeight"); + configItemOpenElement.addAttribute("config:type", "int"); + configItemOpenElement.write(mpImpl->mpHandler); + WPXString sHeight; sHeight.sprintf("%li", (unsigned long)(2540 * mpImpl->mfMaxHeight)); + mpImpl->mpHandler->characters(sHeight); + mpImpl->mpHandler->endElement("config:config-item"); + + mpImpl->mpHandler->endElement("config:config-item-set"); + + mpImpl->mpHandler->endElement("office:settings"); + } + + + if ((mpImpl->mxStreamType == ODF_FLAT_XML) || (mpImpl->mxStreamType == ODF_STYLES_XML)) + { + TagOpenElement("office:styles").write(mpImpl->mpHandler); + + for (std::vector<DocumentElement *>::const_iterator iterGraphicsStrokeDashStyles = mpImpl->mGraphicsStrokeDashStyles.begin(); + iterGraphicsStrokeDashStyles != mpImpl->mGraphicsStrokeDashStyles.end(); ++iterGraphicsStrokeDashStyles) + { + (*iterGraphicsStrokeDashStyles)->write(mpImpl->mpHandler); + } + + for (std::vector<DocumentElement *>::const_iterator iterGraphicsGradientStyles = mpImpl->mGraphicsGradientStyles.begin(); + iterGraphicsGradientStyles != mpImpl->mGraphicsGradientStyles.end(); ++iterGraphicsGradientStyles) + { + (*iterGraphicsGradientStyles)->write(mpImpl->mpHandler); + } + + mpImpl->mpHandler->endElement("office:styles"); + } + + + if ((mpImpl->mxStreamType == ODF_FLAT_XML) || (mpImpl->mxStreamType == ODF_CONTENT_XML) || (mpImpl->mxStreamType == ODF_STYLES_XML)) + { + TagOpenElement("office:automatic-styles").write(mpImpl->mpHandler); + } + + if ((mpImpl->mxStreamType == ODF_FLAT_XML) || (mpImpl->mxStreamType == ODF_CONTENT_XML)) + { + // writing out the graphics automatic styles + for (std::vector<DocumentElement *>::iterator iterGraphicsAutomaticStyles = mpImpl->mGraphicsAutomaticStyles.begin(); + iterGraphicsAutomaticStyles != mpImpl->mGraphicsAutomaticStyles.end(); ++iterGraphicsAutomaticStyles) + { + (*iterGraphicsAutomaticStyles)->write(mpImpl->mpHandler); + } + } +#ifdef MULTIPAGE_WORKAROUND + if ((mpImpl->mxStreamType == ODF_FLAT_XML) || (mpImpl->mxStreamType == ODF_STYLES_XML)) + { + TagOpenElement tmpStylePageLayoutOpenElement("style:page-layout"); + tmpStylePageLayoutOpenElement.addAttribute("style:name", "PM0"); + tmpStylePageLayoutOpenElement.write(mpImpl->mpHandler); + + TagOpenElement tmpStylePageLayoutPropertiesOpenElement("style:page-layout-properties"); + tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:margin-top", "0in"); + tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:margin-bottom", "0in"); + tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:margin-left", "0in"); + tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:margin-right", "0in"); + WPXString sValue; + sValue = doubleToString(mpImpl->mfMaxWidth); sValue.append("in"); + tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:page-width", sValue); + sValue = doubleToString(mpImpl->mfMaxHeight); sValue.append("in"); + tmpStylePageLayoutPropertiesOpenElement.addAttribute("fo:page-height", sValue); + tmpStylePageLayoutPropertiesOpenElement.addAttribute("style:print-orientation", "portrait"); + tmpStylePageLayoutPropertiesOpenElement.write(mpImpl->mpHandler); + + mpImpl->mpHandler->endElement("style:page-layout-properties"); + + mpImpl->mpHandler->endElement("style:page-layout"); + + TagOpenElement tmpStyleStyleOpenElement("style:style"); + tmpStyleStyleOpenElement.addAttribute("style:name", "dp1"); + tmpStyleStyleOpenElement.addAttribute("style:family", "drawing-page"); + tmpStyleStyleOpenElement.write(mpImpl->mpHandler); + + TagOpenElement tmpStyleDrawingPagePropertiesOpenElement("style:drawing-page-properties"); + // tmpStyleDrawingPagePropertiesOpenElement.addAttribute("draw:background-size", "border"); + tmpStyleDrawingPagePropertiesOpenElement.addAttribute("draw:fill", "none"); + tmpStyleDrawingPagePropertiesOpenElement.write(mpImpl->mpHandler); + + mpImpl->mpHandler->endElement("style:drawing-page-properties"); + + mpImpl->mpHandler->endElement("style:style"); + } +#else + if ((mpImpl->mxStreamType == ODF_FLAT_XML) || (mpImpl->mxStreamType == ODF_STYLES_XML)) + { + // writing out the page automatic styles + for (std::vector<DocumentElement *>::iterator iterPageAutomaticStyles = mpImpl->mPageAutomaticStyles.begin(); + iterPageAutomaticStyles != mpImpl->mPageAutomaticStyles.end(); iterPageAutomaticStyles++) + { + (*iterPageAutomaticStyles)->write(mpImpl->mpHandler); + } + } +#endif + if ((mpImpl->mxStreamType == ODF_FLAT_XML) || (mpImpl->mxStreamType == ODF_CONTENT_XML) || (mpImpl->mxStreamType == ODF_STYLES_XML)) + { + mpImpl->mpHandler->endElement("office:automatic-styles"); + } + + if ((mpImpl->mxStreamType == ODF_FLAT_XML) || (mpImpl->mxStreamType == ODF_STYLES_XML)) + { + TagOpenElement("office:master-styles").write(mpImpl->mpHandler); + + for (std::vector<DocumentElement *>::const_iterator pageMasterIter = mpImpl->mPageMasterStyles.begin(); + pageMasterIter != mpImpl->mPageMasterStyles.end(); ++pageMasterIter) + { + (*pageMasterIter)->write(mpImpl->mpHandler); + } + mpImpl->mpHandler->endElement("office:master-styles"); + } + + if ((mpImpl->mxStreamType == ODF_FLAT_XML) || (mpImpl->mxStreamType == ODF_CONTENT_XML)) + { + TagOpenElement("office:body").write(mpImpl->mpHandler); + + TagOpenElement("office:drawing").write(mpImpl->mpHandler); + + for (std::vector<DocumentElement *>::const_iterator bodyIter = mpImpl->mBodyElements.begin(); + bodyIter != mpImpl->mBodyElements.end(); ++bodyIter) + { + (*bodyIter)->write(mpImpl->mpHandler); + } + + mpImpl->mpHandler->endElement("office:drawing"); + mpImpl->mpHandler->endElement("office:body"); + } + + mpImpl->mpHandler->endElement( + (mpImpl->mxStreamType == ODF_FLAT_XML) ? "office:document" : ( + (mpImpl->mxStreamType == ODF_CONTENT_XML) ? "office:document-content" : ( + (mpImpl->mxStreamType == ODF_STYLES_XML) ? "office:document-styles" : ( + (mpImpl->mxStreamType == ODF_SETTINGS_XML) ? "office:document-settings" : ( + (mpImpl->mxStreamType == ODF_META_XML) ? "office:document-meta" : "office:document" ))))); + + mpImpl->mpHandler->endDocument(); + + if (mpImpl) + delete mpImpl; +} + +void OdgGenerator::startGraphics(const ::WPXPropertyList &propList) +{ + if (propList["svg:width"]) + { + mpImpl->mfWidth = propList["svg:width"]->getDouble(); + mpImpl->mfMaxWidth = mpImpl->mfMaxWidth < mpImpl->mfWidth ? mpImpl->mfWidth : mpImpl->mfMaxWidth; + } + + if (propList["svg:height"]) + { + mpImpl->mfHeight = propList["svg:height"]->getDouble(); + mpImpl->mfMaxHeight = mpImpl->mfMaxHeight < mpImpl->mfHeight ? mpImpl->mfHeight : mpImpl->mfMaxHeight; + } + + TagOpenElement *pStyleMasterPageOpenElement = new TagOpenElement("style:master-page"); + + TagOpenElement *pDrawPageOpenElement = new TagOpenElement("draw:page"); + + TagOpenElement *pStylePageLayoutOpenElement = new TagOpenElement("style:page-layout"); + + WPXString sValue; + sValue.sprintf("page%i", mpImpl->miPageIndex); + pDrawPageOpenElement->addAttribute("draw:name", sValue); +#ifdef MULTIPAGE_WORKAROUND + pStyleMasterPageOpenElement->addAttribute("style:page-layout-name", "PM0"); + pStylePageLayoutOpenElement->addAttribute("style:page-layout-name", "PM0"); +#else + sValue.sprintf("PM%i", mpImpl->miPageIndex); + pStyleMasterPageOpenElement->addAttribute("style:page-layout-name", sValue); + pStylePageLayoutOpenElement->addAttribute("style:name", sValue); +#endif + + mpImpl->mPageAutomaticStyles.push_back(pStylePageLayoutOpenElement); + + TagOpenElement *pStylePageLayoutPropertiesOpenElement = new TagOpenElement("style:page-layout-properties"); + pStylePageLayoutPropertiesOpenElement->addAttribute("fo:margin-top", "0in"); + pStylePageLayoutPropertiesOpenElement->addAttribute("fo:margin-bottom", "0in"); + pStylePageLayoutPropertiesOpenElement->addAttribute("fo:margin-left", "0in"); + pStylePageLayoutPropertiesOpenElement->addAttribute("fo:margin-right", "0in"); + sValue.sprintf("%s%s", doubleToString(mpImpl->mfWidth).cstr(), "in"); + pStylePageLayoutPropertiesOpenElement->addAttribute("fo:page-width", sValue); + sValue.sprintf("%s%s", doubleToString(mpImpl->mfHeight).cstr(), "in"); + pStylePageLayoutPropertiesOpenElement->addAttribute("fo:page-height", sValue); + pStylePageLayoutPropertiesOpenElement->addAttribute("style:print-orientation", "portrait"); + mpImpl->mPageAutomaticStyles.push_back(pStylePageLayoutPropertiesOpenElement); + + mpImpl->mPageAutomaticStyles.push_back(new TagCloseElement("style:page-layout-properties")); + + mpImpl->mPageAutomaticStyles.push_back(new TagCloseElement("style:page-layout")); + +#ifdef MULTIPAGE_WORKAROUND + pDrawPageOpenElement->addAttribute("draw:style-name", "dp1"); + pStyleMasterPageOpenElement->addAttribute("draw:style-name", "dp1"); +#else + sValue.sprintf("dp%i", mpImpl->miPageIndex); + pDrawPageOpenElement->addAttribute("draw:style-name", sValue); + pStyleMasterPageOpenElement->addAttribute("draw:style-name", sValue); +#endif + + TagOpenElement *pStyleStyleOpenElement = new TagOpenElement("style:style"); + pStyleStyleOpenElement->addAttribute("style:name", sValue); + pStyleStyleOpenElement->addAttribute("style:family", "drawing-page"); + mpImpl->mPageAutomaticStyles.push_back(pStyleStyleOpenElement); + +#ifdef MULTIPAGE_WORKAROUND + pDrawPageOpenElement->addAttribute("draw:master-page-name", "Default"); + pStyleMasterPageOpenElement->addAttribute("style:name", "Default"); +#else + sValue.sprintf("Page%i", mpImpl->miPageIndex); + pDrawPageOpenElement->addAttribute("draw:master-page-name", sValue); + pStyleMasterPageOpenElement->addAttribute("style:name", sValue); +#endif + + mpImpl->mBodyElements.push_back(pDrawPageOpenElement); + + mpImpl->mPageMasterStyles.push_back(pStyleMasterPageOpenElement); + mpImpl->mPageMasterStyles.push_back(new TagCloseElement("style:master-page")); + + + TagOpenElement *pStyleDrawingPagePropertiesOpenElement = new TagOpenElement("style:drawing-page-properties"); + // pStyleDrawingPagePropertiesOpenElement->addAttribute("draw:background-size", "border"); + pStyleDrawingPagePropertiesOpenElement->addAttribute("draw:fill", "none"); + mpImpl->mPageAutomaticStyles.push_back(pStyleDrawingPagePropertiesOpenElement); + + mpImpl->mPageAutomaticStyles.push_back(new TagCloseElement("style:drawing-page-properties")); + + mpImpl->mPageAutomaticStyles.push_back(new TagCloseElement("style:style")); +} + +void OdgGenerator::endGraphics() +{ + mpImpl->mBodyElements.push_back(new TagCloseElement("draw:page")); + mpImpl->miPageIndex++; +} + +void OdgGenerator::setStyle(const ::WPXPropertyList & propList, const ::WPXPropertyListVector& gradient) +{ + mpImpl->mxStyle.clear(); + mpImpl->mxStyle = propList; + mpImpl->mxGradient = gradient; +} + +void OdgGenerator::startLayer(const ::WPXPropertyList & /* propList */) +{ +} + +void OdgGenerator::endLayer() +{ +} + +void OdgGenerator::drawRectangle(const ::WPXPropertyList &propList) +{ + mpImpl->_writeGraphicsStyle(); + TagOpenElement *pDrawRectElement = new TagOpenElement("draw:rect"); + WPXString sValue; + sValue.sprintf("gr%i", mpImpl->miGraphicsStyleIndex-1); + pDrawRectElement->addAttribute("draw:style-name", sValue); + pDrawRectElement->addAttribute("svg:x", propList["svg:x"]->getStr()); + pDrawRectElement->addAttribute("svg:y", propList["svg:y"]->getStr()); + pDrawRectElement->addAttribute("svg:width", propList["svg:width"]->getStr()); + pDrawRectElement->addAttribute("svg:height", propList["svg:height"]->getStr()); + // FIXME: what to do when rx != ry ? + if (propList["svg:rx"]) + pDrawRectElement->addAttribute("draw:corner-radius", propList["svg:rx"]->getStr()); + else + pDrawRectElement->addAttribute("draw:corner-radius", "0.0000in"); + mpImpl->mBodyElements.push_back(pDrawRectElement); + mpImpl->mBodyElements.push_back(new TagCloseElement("draw:rect")); +} + +void OdgGenerator::drawEllipse(const ::WPXPropertyList &propList) +{ + mpImpl->_writeGraphicsStyle(); + TagOpenElement *pDrawEllipseElement = new TagOpenElement("draw:ellipse"); + WPXString sValue; + sValue.sprintf("gr%i", mpImpl->miGraphicsStyleIndex-1); + pDrawEllipseElement->addAttribute("draw:style-name", sValue); + sValue = doubleToString(2 * propList["svg:rx"]->getDouble()); sValue.append("in"); + pDrawEllipseElement->addAttribute("svg:width", sValue); + sValue = doubleToString(2 * propList["svg:ry"]->getDouble()); sValue.append("in"); + pDrawEllipseElement->addAttribute("svg:height", sValue); + if (propList["libwpg:rotate"] && propList["libwpg:rotate"]->getDouble() != 0.0) + { + double rotation = propList["libwpg:rotate"]->getDouble(); + while(rotation < -180) + rotation += 360; + while(rotation > 180) + rotation -= 360; + double radrotation = rotation*M_PI/180.0; + double deltax = sqrt(pow(propList["svg:rx"]->getDouble(), 2.0) + + pow(propList["svg:ry"]->getDouble(), 2.0))*cos(atan(propList["svg:ry"]->getDouble()/propList["svg:rx"]->getDouble()) + - radrotation ) - propList["svg:rx"]->getDouble(); + double deltay = sqrt(pow(propList["svg:rx"]->getDouble(), 2.0) + + pow(propList["svg:ry"]->getDouble(), 2.0))*sin(atan(propList["svg:ry"]->getDouble()/propList["svg:rx"]->getDouble()) + - radrotation ) - propList["svg:ry"]->getDouble(); + sValue = "rotate("; sValue.append(doubleToString(radrotation)); sValue.append(") "); + sValue.append("translate("); sValue.append(doubleToString(propList["svg:cx"]->getDouble() - propList["svg:rx"]->getDouble() - deltax)); + sValue.append("in, "); + sValue.append(doubleToString(propList["svg:cy"]->getDouble() - propList["svg:ry"]->getDouble() - deltay)); sValue.append("in)"); + pDrawEllipseElement->addAttribute("draw:transform", sValue); + } + else + { + sValue = doubleToString(propList["svg:cx"]->getDouble()-propList["svg:rx"]->getDouble()); sValue.append("in"); + pDrawEllipseElement->addAttribute("svg:x", sValue); + sValue = doubleToString(propList["svg:cy"]->getDouble()-propList["svg:ry"]->getDouble()); sValue.append("in"); + pDrawEllipseElement->addAttribute("svg:y", sValue); + } + mpImpl->mBodyElements.push_back(pDrawEllipseElement); + mpImpl->mBodyElements.push_back(new TagCloseElement("draw:ellipse")); +} + +void OdgGenerator::drawPolyline(const ::WPXPropertyListVector& vertices) +{ + mpImpl->_drawPolySomething(vertices, false); +} + +void OdgGenerator::drawPolygon(const ::WPXPropertyListVector& vertices) +{ + mpImpl->_drawPolySomething(vertices, true); +} + +void OdgGeneratorPrivate::_drawPolySomething(const ::WPXPropertyListVector& vertices, bool isClosed) +{ + if(vertices.count() < 2) + return; + + if(vertices.count() == 2) + { + _writeGraphicsStyle(); + TagOpenElement *pDrawLineElement = new TagOpenElement("draw:line"); + WPXString sValue; + sValue.sprintf("gr%i", miGraphicsStyleIndex-1); + pDrawLineElement->addAttribute("draw:style-name", sValue); + pDrawLineElement->addAttribute("draw:text-style-name", "P1"); + pDrawLineElement->addAttribute("draw:layer", "layout"); + pDrawLineElement->addAttribute("svg:x1", vertices[0]["svg:x"]->getStr()); + pDrawLineElement->addAttribute("svg:y1", vertices[0]["svg:y"]->getStr()); + pDrawLineElement->addAttribute("svg:x2", vertices[1]["svg:x"]->getStr()); + pDrawLineElement->addAttribute("svg:y2", vertices[1]["svg:y"]->getStr()); + mBodyElements.push_back(pDrawLineElement); + mBodyElements.push_back(new TagCloseElement("draw:line")); + } + else + { + ::WPXPropertyListVector path; + ::WPXPropertyList element; + + for (unsigned long ii = 0; ii < vertices.count(); ii++) + { + element = vertices[ii]; + if (ii == 0) + element.insert("libwpg:path-action", "M"); + else + element.insert("libwpg:path-action", "L"); + path.append(element); + element.clear(); + } + if (isClosed) + { + element.insert("libwpg:path-action", "Z"); + path.append(element); + } + _drawPath(path); + } +} + +void OdgGeneratorPrivate::_drawPath(const WPXPropertyListVector& path) +{ + if(path.count() == 0) + return; + // This must be a mistake and we do not want to crash lower + if(path[0]["libwpg:path-action"]->getStr() == "Z") + return; + + // try to find the bounding box + // this is simple convex hull technique, the bounding box might not be + // accurate but that should be enough for this purpose + bool isFirstPoint = true; + + double px = 0.0, py = 0.0, qx = 0.0, qy = 0.0; + double lastX = 0.0; + double lastY = 0.0; + + for(unsigned k = 0; k < path.count(); k++) + { + if (!path[k]["svg:x"] || !path[k]["svg:y"]) + continue; + if (isFirstPoint) + { + px = path[k]["svg:x"]->getDouble(); + py = path[k]["svg:y"]->getDouble(); + qx = px; + qy = py; + lastX = px; + lastY = py; + isFirstPoint = false; + } + px = (px > path[k]["svg:x"]->getDouble()) ? path[k]["svg:x"]->getDouble() : px; + py = (py > path[k]["svg:y"]->getDouble()) ? path[k]["svg:y"]->getDouble() : py; + qx = (qx < path[k]["svg:x"]->getDouble()) ? path[k]["svg:x"]->getDouble() : qx; + qy = (qy < path[k]["svg:y"]->getDouble()) ? path[k]["svg:y"]->getDouble() : qy; + + if(path[k]["libwpg:path-action"]->getStr() == "C") + { + px = (px > path[k]["svg:x1"]->getDouble()) ? path[k]["svg:x1"]->getDouble() : px; + py = (py > path[k]["svg:y1"]->getDouble()) ? path[k]["svg:y1"]->getDouble() : py; + qx = (qx < path[k]["svg:x1"]->getDouble()) ? path[k]["svg:x1"]->getDouble() : qx; + qy = (qy < path[k]["svg:y1"]->getDouble()) ? path[k]["svg:y1"]->getDouble() : qy; + px = (px > path[k]["svg:x2"]->getDouble()) ? path[k]["svg:x2"]->getDouble() : px; + py = (py > path[k]["svg:y2"]->getDouble()) ? path[k]["svg:y2"]->getDouble() : py; + qx = (qx < path[k]["svg:x2"]->getDouble()) ? path[k]["svg:x2"]->getDouble() : qx; + qy = (qy < path[k]["svg:y2"]->getDouble()) ? path[k]["svg:y2"]->getDouble() : qy; + } + if(path[k]["libwpg:path-action"]->getStr() == "A") + { + double xmin, xmax, ymin, ymax; + + getEllipticalArcBBox(lastX, lastY, path[k]["svg:rx"]->getDouble(), path[k]["svg:ry"]->getDouble(), + path[k]["libwpg:rotate"] ? path[k]["libwpg:rotate"]->getDouble() : 0.0, + path[k]["libwpg:large-arc"] ? path[k]["libwpg:large-arc"]->getInt() : 1, + path[k]["libwpg:sweep"] ? path[k]["libwpg:sweep"]->getInt() : 1, + path[k]["svg:x"]->getDouble(), path[k]["svg:y"]->getDouble(), xmin, ymin, xmax, ymax); + + px = (px > xmin ? xmin : px); + py = (py > ymin ? ymin : py); + qx = (qx < xmax ? xmax : qx); + qy = (qy < ymax ? ymax : qy); + } + lastX = path[k]["svg:x"]->getDouble(); + lastY = path[k]["svg:y"]->getDouble(); + } + + + WPXString sValue; + _writeGraphicsStyle(); + TagOpenElement *pDrawPathElement = new TagOpenElement("draw:path"); + sValue.sprintf("gr%i", miGraphicsStyleIndex-1); + pDrawPathElement->addAttribute("draw:style-name", sValue); + pDrawPathElement->addAttribute("draw:text-style-name", "P1"); + pDrawPathElement->addAttribute("draw:layer", "layout"); + sValue = doubleToString(px); sValue.append("in"); + pDrawPathElement->addAttribute("svg:x", sValue); + sValue = doubleToString(py); sValue.append("in"); + pDrawPathElement->addAttribute("svg:y", sValue); + sValue = doubleToString((qx - px)); sValue.append("in"); + pDrawPathElement->addAttribute("svg:width", sValue); + sValue = doubleToString((qy - py)); sValue.append("in"); + pDrawPathElement->addAttribute("svg:height", sValue); + sValue.sprintf("%i %i %i %i", 0, 0, (unsigned)(2540*(qx - px)), (unsigned)(2540*(qy - py))); + pDrawPathElement->addAttribute("svg:viewBox", sValue); + + sValue.clear(); + for(unsigned i = 0; i < path.count(); i++) + { + WPXString sElement; + if (path[i]["libwpg:path-action"]->getStr() == "M") + { + // 2540 is 2.54*1000, 2.54 in = 1 inch + sElement.sprintf("M%i %i", (unsigned)((path[i]["svg:x"]->getDouble()-px)*2540), + (unsigned)((path[i]["svg:y"]->getDouble()-py)*2540)); + sValue.append(sElement); + } + else if (path[i]["libwpg:path-action"]->getStr() == "L") + { + sElement.sprintf("L%i %i", (unsigned)((path[i]["svg:x"]->getDouble()-px)*2540), + (unsigned)((path[i]["svg:y"]->getDouble()-py)*2540)); + sValue.append(sElement); + } + else if (path[i]["libwpg:path-action"]->getStr() == "C") + { + sElement.sprintf("C%i %i %i %i %i %i", (unsigned)((path[i]["svg:x1"]->getDouble()-px)*2540), + (unsigned)((path[i]["svg:y1"]->getDouble()-py)*2540), (unsigned)((path[i]["svg:x2"]->getDouble()-px)*2540), + (unsigned)((path[i]["svg:y2"]->getDouble()-py)*2540), (unsigned)((path[i]["svg:x"]->getDouble()-px)*2540), + (unsigned)((path[i]["svg:y"]->getDouble()-py)*2540)); + sValue.append(sElement); + } + else if (path[i]["libwpg:path-action"]->getStr() == "A") + { + sElement.sprintf("A%i %i %i %i %i %i %i", (unsigned)((path[i]["svg:rx"]->getDouble())*2540), + (unsigned)((path[i]["svg:ry"]->getDouble())*2540), (path[i]["libwpg:rotate"] ? path[i]["libwpg:rotate"]->getInt() : 0), + (path[i]["libwpg:large-arc"] ? path[i]["libwpg:large-arc"]->getInt() : 1), + (path[i]["libwpg:sweep"] ? path[i]["libwpg:sweep"]->getInt() : 1), + (unsigned)((path[i]["svg:x"]->getDouble()-px)*2540), (unsigned)((path[i]["svg:y"]->getDouble()-py)*2540)); + sValue.append(sElement); + } + else if (path[i]["libwpg:path-action"]->getStr() == "Z") + sValue.append(" Z"); + } + pDrawPathElement->addAttribute("svg:d", sValue); + mBodyElements.push_back(pDrawPathElement); + mBodyElements.push_back(new TagCloseElement("draw:path")); +} + +void OdgGenerator::drawPath(const WPXPropertyListVector& path) +{ + mpImpl->_drawPath(path); +} + +void OdgGenerator::drawGraphicObject(const ::WPXPropertyList &propList, const ::WPXBinaryData& binaryData) +{ + if (!propList["libwpg:mime-type"] && propList["libwpg:mime-type"]->getStr().len() <= 0) + return; + TagOpenElement *pDrawFrameElement = new TagOpenElement("draw:frame"); + + + WPXString sValue; + if (propList["svg:x"]) + pDrawFrameElement->addAttribute("svg:x", propList["svg:x"]->getStr()); + if (propList["svg:y"]) + pDrawFrameElement->addAttribute("svg:y", propList["svg:y"]->getStr()); + if (propList["svg:height"]) + pDrawFrameElement->addAttribute("svg:height", propList["svg:height"]->getStr()); + if (propList["svg:width"]) + pDrawFrameElement->addAttribute("svg:width", propList["svg:width"]->getStr()); + mpImpl->mBodyElements.push_back(pDrawFrameElement); + + mpImpl->mBodyElements.push_back(new TagOpenElement("draw:image")); + + mpImpl->mBodyElements.push_back(new TagOpenElement("office:binary-data")); + + ::WPXString base64Binary = binaryData.getBase64Data(); + mpImpl->mBodyElements.push_back(new CharDataElement(base64Binary.cstr())); + + mpImpl->mBodyElements.push_back(new TagCloseElement("office:binary-data")); + + mpImpl->mBodyElements.push_back(new TagCloseElement("draw:image")); + + mpImpl->mBodyElements.push_back(new TagCloseElement("draw:frame")); +} + +void OdgGeneratorPrivate::_writeGraphicsStyle() +{ + bool bUseOpacityGradient = false; +#if 0 + if(mxStyle["libwpg:stroke-solid"] && !mxStyle["libwpg:stroke-solid"]->getInt() && (mxDashArray.count() >=2 ) ) + { + // ODG only supports dashes with the same length of spaces inbetween + // here we take the first space and assume everything else the same + // note that dash length is written in percentage ????????????????? + double distance = mxDashArray.at(1); + TagOpenElement *pDrawStrokeDashElement = new TagOpenElement("draw:stroke-dash"); + pDrawStrokeDashElement->addAttribute("draw:style", "rect"); + WPXString sValue; + sValue.sprintf("Dash_%i", miDashIndex++); + pDrawStrokeDashElement->addAttribute("draw:name", sValue); + sValue = doubleToString(distance); sValue.append("in"); + pDrawStrokeDashElement->addAttribute("draw:distance", sValue); + WPXString sName; + // We have to find out how to do this intelligently, since the ODF is allowing only + // two pairs draw:dots1 draw:dots1-length and draw:dots2 draw:dots2-length + for(unsigned i = 0; i < mxDashArray.count()/2 && i < 2; i++) + { + sName.sprintf("draw:dots%i", i+1); + pDrawStrokeDashElement->addAttribute(sName.cstr(), "1"); + sName.sprintf("draw:dots%i-length", i+1); + sValue = doubleToString(mxDashArray.at(i*2)); sValue.append("in"); + pDrawStrokeDashElement->addAttribute(sName.cstr(), sValue); + } + mGraphicsStrokeDashStyles.push_back(pDrawStrokeDashElement); + mGraphicsStrokeDashStyles.push_back(new TagCloseElement("draw:stroke-dash")); + } +#endif + if(mxStyle["draw:fill"] && mxStyle["draw:fill"]->getStr() == "gradient") + { + bUseOpacityGradient = true; + TagOpenElement *pDrawGradientElement = new TagOpenElement("draw:gradient"); + TagOpenElement *pDrawOpacityElement = new TagOpenElement("draw:opacity"); + if (mxStyle["draw:style"]) + { + pDrawGradientElement->addAttribute("draw:style", mxStyle["draw:style"]->getStr()); + pDrawOpacityElement->addAttribute("draw:style", mxStyle["draw:style"]->getStr()); + } + WPXString sValue; + sValue.sprintf("Gradient_%i", miGradientIndex); + pDrawGradientElement->addAttribute("draw:name", sValue); + sValue.sprintf("Transparency_%i", miGradientIndex++); + pDrawOpacityElement->addAttribute("draw:name", sValue); + + // ODG angle unit is 0.1 degree + double angle = mxStyle["draw:angle"] ? mxStyle["draw:angle"]->getDouble() : 0.0; + while(angle < 0) + angle += 360; + while(angle > 360) + angle -= 360; + sValue.sprintf("%i", (unsigned)(angle*10)); + pDrawGradientElement->addAttribute("draw:angle", sValue); + pDrawOpacityElement->addAttribute("draw:angle", sValue); + + if (!mxGradient.count()) + { + if (mxStyle["draw:start-color"]) + pDrawGradientElement->addAttribute("draw:start-color", mxStyle["draw:start-color"]->getStr()); + if (mxStyle["draw:end-color"]) + pDrawGradientElement->addAttribute("draw:end-color", mxStyle["draw:end-color"]->getStr()); + + if (mxStyle["draw:border"]) + { + pDrawGradientElement->addAttribute("draw:border", mxStyle["draw:border"]->getStr()); + pDrawOpacityElement->addAttribute("draw:border", mxStyle["draw:border"]->getStr()); + } + else + { + pDrawGradientElement->addAttribute("draw:border", "0%"); + pDrawOpacityElement->addAttribute("draw:border", "0%"); + } + + if (mxStyle["svg:cx"]) + { + pDrawGradientElement->addAttribute("draw:cx", mxStyle["svg:cx"]->getStr()); + pDrawOpacityElement->addAttribute("draw:cx", mxStyle["svg:cx"]->getStr()); + } + else if (mxStyle["draw:cx"]) + { + pDrawGradientElement->addAttribute("draw:cx", mxStyle["draw:cx"]->getStr()); + pDrawOpacityElement->addAttribute("draw:cx", mxStyle["draw:cx"]->getStr()); + } + + if (mxStyle["svg:cy"]) + { + pDrawGradientElement->addAttribute("draw:cy", mxStyle["svg:cy"]->getStr()); + pDrawOpacityElement->addAttribute("draw:cy", mxStyle["svg:cy"]->getStr()); + } + else if (mxStyle["draw:cx"]) + { + pDrawGradientElement->addAttribute("draw:cx", mxStyle["svg:cx"]->getStr()); + pDrawOpacityElement->addAttribute("draw:cx", mxStyle["svg:cx"]->getStr()); + } + + if (mxStyle["draw:start-intensity"]) + pDrawGradientElement->addAttribute("draw:start-intensity", mxStyle["draw:start-intensity"]->getStr()); + else + pDrawGradientElement->addAttribute("draw:start-intensity", "100%"); + + if (mxStyle["draw:end-intensity"]) + pDrawGradientElement->addAttribute("draw:end-intensity", mxStyle["draw:end-intensity"]->getStr()); + else + pDrawGradientElement->addAttribute("draw:end-intensity", "100%"); + + if (mxStyle["libwpg:start-opacity"]) + pDrawOpacityElement->addAttribute("draw:start", mxStyle["libwpg:start-opacity"]->getStr()); + else + pDrawOpacityElement->addAttribute("draw:start", "100%"); + + if (mxStyle["libwpg:end-opacity"]) + pDrawOpacityElement->addAttribute("draw:end", mxStyle["libwpg:end-opacity"]->getStr()); + else + pDrawOpacityElement->addAttribute("draw:end", "100%"); + + mGraphicsGradientStyles.push_back(pDrawGradientElement); + mGraphicsGradientStyles.push_back(new TagCloseElement("draw:gradient")); + + // Work around a mess in LibreOffice where both opacities of 100% are interpreted as complete transparency + // Nevertheless, when one is different, immediately, they are interpreted correctly + if (!(mxStyle["libwpg:start-opacity"] && mxStyle["libwpg:end-opacity"]) || (mxStyle["libwpg:start-opacity"]->getDouble() == 1.0 && mxStyle["libwpg:end-opacity"]->getDouble() == 1.0)) + { + delete pDrawOpacityElement; + bUseOpacityGradient = false; + } + else + { + mGraphicsGradientStyles.push_back(pDrawOpacityElement); + mGraphicsGradientStyles.push_back(new TagCloseElement("draw:opacity")); + } + } + else if(mxGradient.count() >= 2) + { + sValue.sprintf("%i", (unsigned)(angle*10)); + pDrawGradientElement->addAttribute("draw:angle", sValue); + + pDrawGradientElement->addAttribute("draw:start-color", mxGradient[1]["svg:stop-color"]->getStr()); + pDrawGradientElement->addAttribute("draw:end-color", mxGradient[0]["svg:stop-color"]->getStr()); + if (mxStyle["svg:cx"]) + pDrawGradientElement->addAttribute("draw:cx", mxStyle["svg:cx"]->getStr()); + if (mxStyle["svg:cy"]) + pDrawGradientElement->addAttribute("draw:cy", mxStyle["svg:cy"]->getStr()); + if (mxGradient[1]["svg:stop-opacity"]) + pDrawGradientElement->addAttribute("draw:start-intensity", mxGradient[1]["svg:stop-opacity"]->getStr()); + else + pDrawGradientElement->addAttribute("draw:start-intensity", "100%"); + if (mxGradient[0]["svg:stop-opacity"]) + pDrawGradientElement->addAttribute("draw:end-intensity", mxGradient[0]["svg:stop-opacity"]->getStr()); + else + pDrawGradientElement->addAttribute("draw:end-intensity", "100%"); + pDrawGradientElement->addAttribute("draw:border", "0%"); + mGraphicsGradientStyles.push_back(pDrawGradientElement); + mGraphicsGradientStyles.push_back(new TagCloseElement("draw:gradient")); + } + } + + TagOpenElement *pStyleStyleElement = new TagOpenElement("style:style"); + WPXString sValue; + sValue.sprintf("gr%i", miGraphicsStyleIndex); + pStyleStyleElement->addAttribute("style:name", sValue); + pStyleStyleElement->addAttribute("style:family", "graphic"); + pStyleStyleElement->addAttribute("style:parent-style-name", "standard"); + mGraphicsAutomaticStyles.push_back(pStyleStyleElement); + + TagOpenElement *pStyleGraphicsPropertiesElement = new TagOpenElement("style:graphic-properties"); + + if((mxStyle["draw:stroke"] && mxStyle["draw:stroke"]->getStr() == "none") || + (mxStyle["svg:stroke-width"] && mxStyle["svg:stroke-width"]->getDouble() == 0.0) || + (mxStyle["svg:stroke-color"] && mxStyle["svg:stroke-color"]->getStr() == "none")) + pStyleGraphicsPropertiesElement->addAttribute("draw:stroke", "none"); + else + { + if (mxStyle["svg:stroke-width"]) + pStyleGraphicsPropertiesElement->addAttribute("svg:stroke-width", mxStyle["svg:stroke-width"]->getStr()); + + if (mxStyle["svg:stroke-color"]) + pStyleGraphicsPropertiesElement->addAttribute("svg:stroke-color", mxStyle["svg:stroke-color"]->getStr()); + + if (mxStyle["svg:stroke-opacity"]) + pStyleGraphicsPropertiesElement->addAttribute("svg:stroke-opacity", mxStyle["svg:stroke-opacity"]->getStr()); + + if (mxStyle["svg:stroke-linejoin"]) + pStyleGraphicsPropertiesElement->addAttribute("draw:stroke-linejoin", mxStyle["svg:stroke-linejoin"]->getStr()); + + if (mxStyle["svg:stroke-linecap"]) + pStyleGraphicsPropertiesElement->addAttribute("svg:stoke-linecap", mxStyle["svg:stroke-linecap"]->getStr()); + + if(mxStyle["libwpg:stroke-solid"] && mxStyle["libwpg:stroke-solid"]->getInt()) + pStyleGraphicsPropertiesElement->addAttribute("draw:stroke", "solid"); +#if 0 + else + { + pStyleGraphicsPropertiesElement->addAttribute("draw:stroke", "dash"); + sValue.sprintf("Dash_%i", miDashIndex-1); + pStyleGraphicsPropertiesElement->addAttribute("draw:stroke-dash", sValue); + } +#endif + } + + if(mxStyle["draw:fill"] && mxStyle["draw:fill"]->getStr() == "none") + pStyleGraphicsPropertiesElement->addAttribute("draw:fill", "none"); + else + { + if (mxStyle["draw:shadow"]) + pStyleGraphicsPropertiesElement->addAttribute("draw:shadow", mxStyle["draw:shadow"]->getStr()); + else + pStyleGraphicsPropertiesElement->addAttribute("draw:shadow", "hidden"); + if (mxStyle["draw:shadow-offset-x"]) + pStyleGraphicsPropertiesElement->addAttribute("draw:shadow-offset-x", mxStyle["draw:shadow-offset-x"]->getStr()); + if (mxStyle["draw:shadow-offset-y"]) + pStyleGraphicsPropertiesElement->addAttribute("draw:shadow-offset-y", mxStyle["draw:shadow-offset-y"]->getStr()); + if (mxStyle["draw:shadow-color"]) + pStyleGraphicsPropertiesElement->addAttribute("draw:shadow-color", mxStyle["draw:shadow-color"]->getStr()); + if (mxStyle["draw:shadow-opacity"]) + pStyleGraphicsPropertiesElement->addAttribute("draw:shadow-opacity", mxStyle["draw:shadow-opacity"]->getStr()); + if (mxStyle["svg:fill-rule"]) + pStyleGraphicsPropertiesElement->addAttribute("svg:fill-rule", mxStyle["svg:fill-rule"]->getStr()); + } + + if(mxStyle["draw:fill"] && mxStyle["draw:fill"]->getStr() == "solid") + { + pStyleGraphicsPropertiesElement->addAttribute("draw:fill", "solid"); + if (mxStyle["draw:fill-color"]) + pStyleGraphicsPropertiesElement->addAttribute("draw:fill-color", mxStyle["draw:fill-color"]->getStr()); + if (mxStyle["draw:opacity"]) + pStyleGraphicsPropertiesElement->addAttribute("draw:opacity", mxStyle["draw:opacity"]->getStr()); + } + + if(mxStyle["draw:fill"] && mxStyle["draw:fill"]->getStr() == "gradient") + { + if (!mxGradient.count() || mxGradient.count() >= 2) + { + pStyleGraphicsPropertiesElement->addAttribute("draw:fill", "gradient"); + sValue.sprintf("Gradient_%i", miGradientIndex-1); + pStyleGraphicsPropertiesElement->addAttribute("draw:fill-gradient-name", sValue); + if (bUseOpacityGradient) + { + sValue.sprintf("Transparency_%i", miGradientIndex-1); + pStyleGraphicsPropertiesElement->addAttribute("draw:opacity-name", sValue); + } + } + else + { + if (mxGradient[0]["svg:stop-color"]) + { + pStyleGraphicsPropertiesElement->addAttribute("draw:fill", "solid"); + pStyleGraphicsPropertiesElement->addAttribute("draw:fill-color", mxGradient[0]["svg:stop-color"]->getStr()); + } + else + pStyleGraphicsPropertiesElement->addAttribute("draw:fill", "solid"); + } + } + + mGraphicsAutomaticStyles.push_back(pStyleGraphicsPropertiesElement); + mGraphicsAutomaticStyles.push_back(new TagCloseElement("style:graphic-properties")); + + mGraphicsAutomaticStyles.push_back(new TagCloseElement("style:style")); + miGraphicsStyleIndex++; +} + +void OdgGenerator::startEmbeddedGraphics(WPXPropertyList const&) +{ +} + +void OdgGenerator::endEmbeddedGraphics() +{ +} + +void OdgGenerator::startTextObject(WPXPropertyList const&, WPXPropertyListVector const&) +{ +} + +void OdgGenerator::endTextObject() +{ +} + +void OdgGenerator::startTextLine(WPXPropertyList const&) +{ +} + +void OdgGenerator::endTextLine() +{ +} + +void OdgGenerator::startTextSpan(WPXPropertyList const&) +{ +} + +void OdgGenerator::endTextSpan() +{ +} + +void OdgGenerator::insertText(WPXString const&) +{ +} + diff --git a/writerperfect/source/filter/OdgGenerator.hxx b/writerperfect/source/filter/OdgGenerator.hxx new file mode 100644 index 000000000000..7296935b8ae1 --- /dev/null +++ b/writerperfect/source/filter/OdgGenerator.hxx @@ -0,0 +1,67 @@ +/* libwpg + * Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02111-1301 USA + * + * For further information visit http://libwpg.sourceforge.net + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef __ODGEXPORTER_HXX__ +#define __ODGEXPORTER_HXX__ + +#include <libwpd/libwpd.h> +#include <libwpg/libwpg.h> +#include "OdfDocumentHandler.hxx" + +class OdgGeneratorPrivate; + +class OdgGenerator : public libwpg::WPGPaintInterface { +public: + OdgGenerator(OdfDocumentHandler *pHandler, const OdfStreamType streamType); + ~OdgGenerator(); + + void startGraphics(const ::WPXPropertyList &propList); + void endGraphics(); + void startLayer(const ::WPXPropertyList &propList); + void endLayer(); + void startEmbeddedGraphics(const ::WPXPropertyList&propList); + void endEmbeddedGraphics(); + + void setStyle(const ::WPXPropertyList &propList, const ::WPXPropertyListVector& gradient); + + void drawRectangle(const ::WPXPropertyList &propList); + void drawEllipse(const ::WPXPropertyList &propList); + void drawPolyline(const ::WPXPropertyListVector& vertices); + void drawPolygon(const ::WPXPropertyListVector& vertices); + void drawPath(const ::WPXPropertyListVector& path); + void drawGraphicObject(const ::WPXPropertyList &propList, const ::WPXBinaryData& binaryData); + + void startTextObject(const ::WPXPropertyList &propList, const ::WPXPropertyListVector &path); + void endTextObject(); + void startTextLine(const ::WPXPropertyList &propList); + void endTextLine(); + void startTextSpan(const ::WPXPropertyList &propList); + void endTextSpan(); + void insertText(const ::WPXString &str); + +private: + OdgGeneratorPrivate *mpImpl; +}; + +#endif // __ODGEXPORTER_HXX__ diff --git a/writerperfect/source/filter/OdtGenerator.cxx b/writerperfect/source/filter/OdtGenerator.cxx new file mode 100644 index 000000000000..1ef6371a8a9b --- /dev/null +++ b/writerperfect/source/filter/OdtGenerator.cxx @@ -0,0 +1,1490 @@ +/* OdtGenerator: 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) 2002-2004 William Lachance (wrlach@gmail.com) + * 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." + */ + +#include <libwpd/libwpd.h> +#include <vector> +#include <map> +#include <stack> +#include <string.h> // for strcmp +#include <string> + +#include "OdtGenerator.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" +#include "InternalHandler.hxx" + +// the state we use for writing the final document +typedef struct _WriterDocumentState WriterDocumentState; +struct _WriterDocumentState +{ + _WriterDocumentState(); + + bool mbFirstElement; + bool mbFirstParagraphInPageSpan; + bool mbInFakeSection; + bool mbListElementOpenedAtCurrentLevel; + bool mbTableCellOpened; + bool mbHeaderRow; + bool mbInNote; + bool mbInTextBox; + bool mbInFrame; +}; + +// list state +typedef struct _WriterListState WriterListState; +struct _WriterListState +{ + _WriterListState(); + + ListStyle *mpCurrentListStyle; + unsigned int miCurrentListLevel; + unsigned int miLastListLevel; + unsigned int miLastListNumber; + bool mbListContinueNumbering; + bool mbListElementParagraphOpened; + std::stack<bool> mbListElementOpened; +}; + +enum WriterListType { unordered, ordered }; + +struct ltstr +{ + bool operator()(const WPXString & s1, const WPXString & s2) const + { + return strcmp(s1.cstr(), s2.cstr()) < 0; + } +}; + +_WriterDocumentState::_WriterDocumentState() : + mbFirstElement(true), + mbFirstParagraphInPageSpan(true), + mbInFakeSection(false), + mbListElementOpenedAtCurrentLevel(false), + mbTableCellOpened(false), + mbHeaderRow(false), + mbInNote(false), + mbInTextBox(false), + mbInFrame(false) +{ +} + +_WriterListState::_WriterListState() : + mpCurrentListStyle(NULL), + miCurrentListLevel(0), + miLastListLevel(0), + miLastListNumber(0), + mbListContinueNumbering(false), + mbListElementParagraphOpened(false), + mbListElementOpened() +{ +} + +class OdtGeneratorPrivate +{ +public: + OdtGeneratorPrivate(OdfDocumentHandler *pHandler, const OdfStreamType streamType); + ~OdtGeneratorPrivate(); + void _resetDocumentState(); + bool _parseSourceDocument(WPXInputStream &input, const char *password); + bool _writeTargetDocument(OdfDocumentHandler *pHandler); + void _writeBegin(); + void _writeDefaultStyles(OdfDocumentHandler *pHandler); + void _writeMasterPages(OdfDocumentHandler *pHandler); + void _writePageLayouts(OdfDocumentHandler *pHandler); + void _allocateFontName(const WPXString &); + + void _openListLevel(TagOpenElement *pListLevelOpenElement); + void _closeListLevel(); + + OdfEmbeddedObject _findEmbeddedObjectHandler(const WPXString& mimeType); + + WPXInputStream *mpInput; + OdfDocumentHandler *mpHandler; + bool mbUsed; // whether or not it has been before (you can only use me once!) + + std::stack<WriterDocumentState> mWriterDocumentStates; + + std::stack<WriterListState> mWriterListStates; + + // paragraph styles + std::map<WPXString, ParagraphStyle *, ltstr> mTextStyleHash; + + // span styles + std::map<WPXString, SpanStyle *, ltstr> mSpanStyleHash; + + // font styles + std::map<WPXString, FontStyle *, ltstr> mFontHash; + + // embedded object handlers + std::map<WPXString, OdfEmbeddedObject, ltstr > mObjectHandlers; + + // section styles + std::vector<SectionStyle *> mSectionStyles; + double mfSectionSpaceAfter; + + // table styles + std::vector<TableStyle *> mTableStyles; + + // frame styles + std::vector<DocumentElement *> mFrameStyles; + + std::vector<DocumentElement *> mFrameAutomaticStyles; + + // metadata + std::vector<DocumentElement *> mMetaData; + + // list styles + unsigned int miNumListStyles; + + // style elements + std::vector<DocumentElement *> mStylesElements; + // content elements + std::vector<DocumentElement *> mBodyElements; + // the current set of elements that we're writing to + std::vector<DocumentElement *> * mpCurrentContentElements; + + // page state + std::vector<PageSpan *> mPageSpans; + PageSpan *mpCurrentPageSpan; + int miNumPageStyles; + + // list styles + std::vector<ListStyle *> mListStyles; + + // object state + unsigned miObjectNumber; + + // table state + TableStyle *mpCurrentTableStyle; + + const OdfStreamType mxStreamType; + + const char * mpPassword; + +}; + +OdtGeneratorPrivate::OdtGeneratorPrivate(OdfDocumentHandler *pHandler, const OdfStreamType streamType) : + mpInput(NULL), + mpHandler(pHandler), + mbUsed(false), + mWriterDocumentStates(), + mWriterListStates(), + mfSectionSpaceAfter(0.0), + miNumListStyles(0), + mpCurrentContentElements(&mBodyElements), + mpCurrentPageSpan(NULL), + miNumPageStyles(0), + miObjectNumber(0), + mpCurrentTableStyle(NULL), + mxStreamType(streamType), + mpPassword(NULL) +{ + mWriterDocumentStates.push(WriterDocumentState()); + mWriterListStates.push(WriterListState()); +} + +OdtGeneratorPrivate::~OdtGeneratorPrivate() +{ + // clean up the mess we made + WRITER_DEBUG_MSG(("WriterWordPerfect: Cleaning up our mess..\n")); + + WRITER_DEBUG_MSG(("Destroying the body elements\n")); + for (std::vector<DocumentElement *>::iterator iterBody = mBodyElements.begin(); iterBody != mBodyElements.end(); ++iterBody) { + delete (*iterBody); + (*iterBody) = NULL; + } + + WRITER_DEBUG_MSG(("Destroying the styles elements\n")); + for (std::vector<DocumentElement *>::iterator iterStyles = mStylesElements.begin(); iterStyles != mStylesElements.end(); ++iterStyles) { + delete (*iterStyles); + (*iterStyles) = NULL; // we may pass over the same element again (in the case of headers/footers spanning multiple pages) + // so make sure we don't do a double del + } + + WRITER_DEBUG_MSG(("Destroying the rest of the styles elements\n")); + for (std::map<WPXString, ParagraphStyle *, ltstr>::iterator iterTextStyle = mTextStyleHash.begin(); + iterTextStyle != mTextStyleHash.end(); ++iterTextStyle) { + delete (iterTextStyle->second); + } + + for (std::map<WPXString, SpanStyle *, ltstr>::iterator iterSpanStyle = mSpanStyleHash.begin(); + iterSpanStyle != mSpanStyleHash.end(); ++iterSpanStyle) { + delete(iterSpanStyle->second); + } + + for (std::map<WPXString, FontStyle *, ltstr>::iterator iterFont = mFontHash.begin(); + iterFont != mFontHash.end(); ++iterFont) { + delete(iterFont->second); + } + + for (std::vector<ListStyle *>::iterator iterListStyles = mListStyles.begin(); + iterListStyles != mListStyles.end(); ++iterListStyles) { + delete(*iterListStyles); + } + for (std::vector<SectionStyle *>::iterator iterSectionStyles = mSectionStyles.begin(); + iterSectionStyles != mSectionStyles.end(); ++iterSectionStyles) { + delete(*iterSectionStyles); + } + for (std::vector<TableStyle *>::iterator iterTableStyles = mTableStyles.begin(); + iterTableStyles != mTableStyles.end(); ++iterTableStyles) { + delete((*iterTableStyles)); + } + + for (std::vector<PageSpan *>::iterator iterPageSpans = mPageSpans.begin(); + iterPageSpans != mPageSpans.end(); ++iterPageSpans) { + delete(*iterPageSpans); + } + for (std::vector<DocumentElement *>::iterator iterFrameStyles = mFrameStyles.begin(); + iterFrameStyles != mFrameStyles.end(); ++iterFrameStyles) { + delete(*iterFrameStyles); + } + for (std::vector<DocumentElement *>::iterator iterFrameAutomaticStyles = mFrameAutomaticStyles.begin(); + iterFrameAutomaticStyles != mFrameAutomaticStyles.end(); ++iterFrameAutomaticStyles) { + delete(*iterFrameAutomaticStyles); + } + for (std::vector<DocumentElement *>::iterator iterMetaData = mMetaData.begin(); + iterMetaData != mMetaData.end(); ++iterMetaData) { + delete(*iterMetaData); + } +} + +OdfEmbeddedObject OdtGeneratorPrivate::_findEmbeddedObjectHandler(const WPXString& mimeType) +{ + std::map<WPXString, OdfEmbeddedObject, ltstr>::iterator i = mObjectHandlers.find(mimeType); + if (i != mObjectHandlers.end()) + return i->second; + + return 0; +} + +OdtGenerator::OdtGenerator(OdfDocumentHandler *pHandler, const OdfStreamType streamType) : + mpImpl(new OdtGeneratorPrivate(pHandler, streamType)) +{ +} + +OdtGenerator::~OdtGenerator() +{ + if (mpImpl) + delete mpImpl; +} + +void OdtGeneratorPrivate::_writeDefaultStyles(OdfDocumentHandler *pHandler) +{ + TagOpenElement("office:styles").write(pHandler); + + TagOpenElement defaultParagraphStyleOpenElement("style:default-style"); + defaultParagraphStyleOpenElement.addAttribute("style:family", "paragraph"); + defaultParagraphStyleOpenElement.write(pHandler); + + TagOpenElement defaultParagraphStylePropertiesOpenElement("style:paragraph-properties"); + defaultParagraphStylePropertiesOpenElement.addAttribute("style:tab-stop-distance", "0.5in"); + defaultParagraphStylePropertiesOpenElement.write(pHandler); + TagCloseElement defaultParagraphStylePropertiesCloseElement("style:paragraph-properties"); + defaultParagraphStylePropertiesCloseElement.write(pHandler); + + pHandler->endElement("style:default-style"); + + TagOpenElement defaultTableRowStyleOpenElement("style:default-style"); + defaultTableRowStyleOpenElement.addAttribute("style:family", "table-row"); + defaultTableRowStyleOpenElement.write(pHandler); + + TagOpenElement defaultTableRowPropertiesOpenElement("style:table-row-properties"); + defaultTableRowPropertiesOpenElement.addAttribute("fo:keep-together", "auto"); + defaultTableRowPropertiesOpenElement.write(pHandler); + + pHandler->endElement("style:table-row-properties"); + pHandler->endElement("style:default-style"); + + TagOpenElement standardStyleOpenElement("style:style"); + standardStyleOpenElement.addAttribute("style:name", "Standard"); + standardStyleOpenElement.addAttribute("style:family", "paragraph"); + standardStyleOpenElement.addAttribute("style:class", "text"); + standardStyleOpenElement.write(pHandler); + + pHandler->endElement("style:style"); + + TagOpenElement textBodyStyleOpenElement("style:style"); + textBodyStyleOpenElement.addAttribute("style:name", "Text_Body"); + textBodyStyleOpenElement.addAttribute("style:display-name", "Text Body"); + textBodyStyleOpenElement.addAttribute("style:family", "paragraph"); + textBodyStyleOpenElement.addAttribute("style:parent-style-name", "Standard"); + textBodyStyleOpenElement.addAttribute("style:class", "text"); + textBodyStyleOpenElement.write(pHandler); + + pHandler->endElement("style:style"); + + TagOpenElement tableContentsStyleOpenElement("style:style"); + tableContentsStyleOpenElement.addAttribute("style:name", "Table_Contents"); + tableContentsStyleOpenElement.addAttribute("style:display-name", "Table Contents"); + tableContentsStyleOpenElement.addAttribute("style:family", "paragraph"); + tableContentsStyleOpenElement.addAttribute("style:parent-style-name", "Text_Body"); + tableContentsStyleOpenElement.addAttribute("style:class", "extra"); + tableContentsStyleOpenElement.write(pHandler); + + pHandler->endElement("style:style"); + + TagOpenElement tableHeadingStyleOpenElement("style:style"); + tableHeadingStyleOpenElement.addAttribute("style:name", "Table_Heading"); + tableHeadingStyleOpenElement.addAttribute("style:display-name", "Table Heading"); + tableHeadingStyleOpenElement.addAttribute("style:family", "paragraph"); + tableHeadingStyleOpenElement.addAttribute("style:parent-style-name", "Table_Contents"); + tableHeadingStyleOpenElement.addAttribute("style:class", "extra"); + tableHeadingStyleOpenElement.write(pHandler); + + pHandler->endElement("style:style"); + + for (std::vector<DocumentElement *>::const_iterator iter = mFrameStyles.begin(); + iter != mFrameStyles.end(); ++iter) + (*iter)->write(pHandler); + + pHandler->endElement("office:styles"); +} + +// writes everything up to the automatic styles declarations.. +void OdtGeneratorPrivate::_writeBegin() +{ +} + +void OdtGeneratorPrivate::_writeMasterPages(OdfDocumentHandler *pHandler) +{ + TagOpenElement("office:master-styles").write(mpHandler); + int pageNumber = 1; + for (unsigned int i=0; i<mPageSpans.size(); ++i) + { + bool bLastPage; + (i == (mPageSpans.size() - 1)) ? bLastPage = true : bLastPage = false; + mPageSpans[i]->writeMasterPages(pageNumber, i, bLastPage, pHandler); + pageNumber += mPageSpans[i]->getSpan(); + } + pHandler->endElement("office:master-styles"); +} + +void OdtGeneratorPrivate::_writePageLayouts(OdfDocumentHandler *pHandler) +{ + for (unsigned int i=0; i<mPageSpans.size(); i++) + { + mPageSpans[i]->writePageLayout(i, pHandler); + } +} + +bool OdtGeneratorPrivate::_writeTargetDocument(OdfDocumentHandler *pHandler) +{ + WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: Printing out the header stuff..\n")); + + WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: Start Document\n")); + mpHandler->startDocument(); + + WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: preamble\n")); + WPXPropertyList docContentPropList; + docContentPropList.insert("xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0"); + docContentPropList.insert("xmlns:meta", "urn:oasis:names:tc:opendocument:xmlns:meta:1.0"); + docContentPropList.insert("xmlns:dc", "http://purl.org/dc/elements/1.1/"); + docContentPropList.insert("xmlns:config", "urn:oasis:names:tc:opendocument:xmlns:config:1.0"); + docContentPropList.insert("xmlns:text", "urn:oasis:names:tc:opendocument:xmlns:text:1.0"); + docContentPropList.insert("xmlns:table", "urn:oasis:names:tc:opendocument:xmlns:table:1.0"); + docContentPropList.insert("xmlns:draw", "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"); + docContentPropList.insert("xmlns:fo", "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"); + docContentPropList.insert("xmlns:xlink", "http://www.w3.org/1999/xlink"); + docContentPropList.insert("xmlns:number", "http://openoffice.org/2000/datastyle"); + docContentPropList.insert("xmlns:svg", "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"); + docContentPropList.insert("xmlns:chart", "urn:oasis:names:tc:opendocument:xmlns:chart:1.0"); + docContentPropList.insert("xmlns:dr3d", "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"); + docContentPropList.insert("xmlns:math", "http://www.w3.org/1998/Math/MathML"); + docContentPropList.insert("xmlns:form", "urn:oasis:names:tc:opendocument:xmlns:form:1.0"); + docContentPropList.insert("xmlns:script", "urn:oasis:names:tc:opendocument:xmlns:script:1.0"); + docContentPropList.insert("xmlns:style", "urn:oasis:names:tc:opendocument:xmlns:style:1.0"); + docContentPropList.insert("office:version", "1.0"); + if (mxStreamType == ODF_FLAT_XML) + { + docContentPropList.insert("office:mimetype", "application/vnd.oasis.opendocument.text"); + mpHandler->startElement("office:document", docContentPropList); + } + else + mpHandler->startElement("office:document-content", docContentPropList); + + // write out the metadata + TagOpenElement("office:meta").write(mpHandler); + for (std::vector<DocumentElement *>::const_iterator iterMetaData = mMetaData.begin(); iterMetaData != mMetaData.end(); ++iterMetaData) { + (*iterMetaData)->write(mpHandler); + } + mpHandler->endElement("office:meta"); + + // write out the font styles + TagOpenElement("office:font-face-decls").write(mpHandler); + for (std::map<WPXString, FontStyle *, ltstr>::iterator iterFont = mFontHash.begin(); iterFont != mFontHash.end(); ++iterFont) { + iterFont->second->write(mpHandler); + } + TagOpenElement symbolFontOpen("style:font-face"); + symbolFontOpen.addAttribute("style:name", "StarSymbol"); + symbolFontOpen.addAttribute("svg:font-family", "StarSymbol"); + symbolFontOpen.addAttribute("style:font-charset", "x-symbol"); + symbolFontOpen.write(mpHandler); + mpHandler->endElement("style:font-face"); + + mpHandler->endElement("office:font-face-decls"); + + WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: Writing out the styles..\n")); + + // write default styles + _writeDefaultStyles(mpHandler); + + TagOpenElement("office:automatic-styles").write(mpHandler); + + for (std::vector<DocumentElement *>::const_iterator iterFrameAutomaticStyles = mFrameAutomaticStyles.begin(); + iterFrameAutomaticStyles != mFrameAutomaticStyles.end(); ++iterFrameAutomaticStyles) + { + (*iterFrameAutomaticStyles)->write(pHandler); + } + + for (std::map<WPXString, ParagraphStyle *, ltstr>::const_iterator iterTextStyle = mTextStyleHash.begin(); + iterTextStyle != mTextStyleHash.end(); ++iterTextStyle) + { + // writing out the paragraph styles + if (strcmp((iterTextStyle->second)->getName().cstr(), "Standard")) + { + // don't write standard paragraph "no styles" style + (iterTextStyle->second)->write(pHandler); + } + } + + // span styles.. + for (std::map<WPXString, SpanStyle *, ltstr>::const_iterator iterSpanStyle = mSpanStyleHash.begin(); + iterSpanStyle != mSpanStyleHash.end(); ++iterSpanStyle) + { + (iterSpanStyle->second)->write(pHandler); + } + + // writing out the sections styles + for (std::vector<SectionStyle *>::const_iterator iterSectionStyles = mSectionStyles.begin(); iterSectionStyles != mSectionStyles.end(); ++iterSectionStyles) { + (*iterSectionStyles)->write(pHandler); + } + + // writing out the lists styles + for (std::vector<ListStyle *>::const_iterator iterListStyles = mListStyles.begin(); iterListStyles != mListStyles.end(); ++iterListStyles) { + (*iterListStyles)->write(pHandler); + } + + // writing out the table styles + for (std::vector<TableStyle *>::const_iterator iterTableStyles = mTableStyles.begin(); iterTableStyles != mTableStyles.end(); ++iterTableStyles) { + (*iterTableStyles)->write(pHandler); + } + + // writing out the page masters + _writePageLayouts(pHandler); + + + pHandler->endElement("office:automatic-styles"); + + _writeMasterPages(pHandler); + + WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: Writing out the document..\n")); + // writing out the document + TagOpenElement("office:body").write(mpHandler); + TagOpenElement("office:text").write(mpHandler); + + for (std::vector<DocumentElement *>::const_iterator iterBodyElements = mBodyElements.begin(); iterBodyElements != mBodyElements.end(); ++iterBodyElements) { + (*iterBodyElements)->write(pHandler); + } + WRITER_DEBUG_MSG(("WriterWordPerfect: Document Body: Finished writing all doc els..\n")); + + pHandler->endElement("office:text"); + pHandler->endElement("office:body"); + if (mxStreamType == ODF_FLAT_XML) + pHandler->endElement("office:document"); + else + 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 OdtGeneratorPrivate::_allocateFontName(const WPXString & sFontName) +{ + if (mFontHash.find(sFontName) == mFontHash.end()) + { + FontStyle *pFontStyle = new FontStyle(sFontName.cstr(), sFontName.cstr()); + mFontHash[sFontName] = pFontStyle; + } +} + +void OdtGenerator::setDocumentMetaData(const WPXPropertyList &propList) +{ + WPXPropertyList::Iter i(propList); + for (i.rewind(); i.next(); ) + { + // filter out libwpd elements + if (strncmp(i.key(), "libwpd", 6) != 0 && strncmp(i.key(), "dcterms", 7) != 0) + { + mpImpl->mMetaData.push_back(new TagOpenElement(i.key())); + WPXString sStringValue(i()->getStr(), true); + mpImpl->mMetaData.push_back(new CharDataElement(sStringValue.cstr())); + mpImpl->mMetaData.push_back(new TagCloseElement(i.key())); + } + } + +} + +void OdtGenerator::openPageSpan(const WPXPropertyList &propList) +{ + PageSpan *pPageSpan = new PageSpan(propList); + mpImpl->mPageSpans.push_back(pPageSpan); + mpImpl->mpCurrentPageSpan = pPageSpan; + mpImpl->miNumPageStyles++; + + mpImpl->mWriterDocumentStates.top().mbFirstParagraphInPageSpan = true; +} + +void OdtGenerator::openHeader(const WPXPropertyList &propList) +{ + std::vector<DocumentElement *> * pHeaderFooterContentElements = new std::vector<DocumentElement *>; + + if (propList["libwpd:occurence"]->getStr() == "even") + mpImpl->mpCurrentPageSpan->setHeaderLeftContent(pHeaderFooterContentElements); + else + mpImpl->mpCurrentPageSpan->setHeaderContent(pHeaderFooterContentElements); + + mpImpl->mpCurrentContentElements = pHeaderFooterContentElements; +} + +void OdtGenerator::closeHeader() +{ + mpImpl->mpCurrentContentElements = &(mpImpl->mBodyElements); +} + +void OdtGenerator::openFooter(const WPXPropertyList &propList) +{ + std::vector<DocumentElement *> * pHeaderFooterContentElements = new std::vector<DocumentElement *>; + + if (propList["libwpd:occurence"]->getStr() == "even") + mpImpl->mpCurrentPageSpan->setFooterLeftContent(pHeaderFooterContentElements); + else + mpImpl->mpCurrentPageSpan->setFooterContent(pHeaderFooterContentElements); + + mpImpl->mpCurrentContentElements = pHeaderFooterContentElements; +} + +void OdtGenerator::closeFooter() +{ + mpImpl->mpCurrentContentElements = &(mpImpl->mBodyElements); +} + +void OdtGenerator::openSection(const WPXPropertyList &propList, const WPXPropertyListVector &columns) +{ + int iNumColumns = columns.count(); + double fSectionMarginLeft = 0.0; + double fSectionMarginRight = 0.0; + if (propList["fo:margin-left"]) + fSectionMarginLeft = propList["fo:margin-left"]->getDouble(); + if (propList["fo:margin-right"]) + fSectionMarginRight = propList["fo:margin-right"]->getDouble(); + + if (iNumColumns > 1 || fSectionMarginLeft != 0 || fSectionMarginRight != 0) + { + if (propList["fo:margin-bottom"]) + mpImpl->mfSectionSpaceAfter = propList["fo:margin-bottom"]->getDouble(); + else if (propList["libwpd:margin-bottom"]) + mpImpl->mfSectionSpaceAfter = propList["libwpd:margin-bottom"]->getDouble(); + + WPXString sSectionName; + sSectionName.sprintf("Section%i", mpImpl->mSectionStyles.size()); + + SectionStyle *pSectionStyle = new SectionStyle(propList, columns, sSectionName.cstr()); + mpImpl->mSectionStyles.push_back(pSectionStyle); + + TagOpenElement *pSectionOpenElement = new TagOpenElement("text:section"); + pSectionOpenElement->addAttribute("text:style-name", pSectionStyle->getName()); + pSectionOpenElement->addAttribute("text:name", pSectionStyle->getName()); + mpImpl->mpCurrentContentElements->push_back(pSectionOpenElement); + } + else + mpImpl->mWriterDocumentStates.top().mbInFakeSection = true; +} + +void OdtGenerator::closeSection() +{ + if (!mpImpl->mWriterDocumentStates.top().mbInFakeSection) + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:section")); + else + mpImpl->mWriterDocumentStates.top().mbInFakeSection = false; + + mpImpl->mfSectionSpaceAfter = 0.0; +} + +void OdtGenerator::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 (mpImpl->mWriterDocumentStates.top().mbFirstElement && mpImpl->mpCurrentContentElements == &(mpImpl->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); + mpImpl->mTextStyleHash[sParagraphHashKey] = pStyle; + mpImpl->mWriterDocumentStates.top().mbFirstElement = false; + mpImpl->mWriterDocumentStates.top().mbFirstParagraphInPageSpan = false; + } + else + { + if (mpImpl->mWriterDocumentStates.top().mbFirstParagraphInPageSpan && mpImpl->mpCurrentContentElements == &(mpImpl->mBodyElements)) + { + WPXString sPageStyleName; + sPageStyleName.sprintf("Page_Style_%i", mpImpl->miNumPageStyles); + pPersistPropList->insert("style:master-page-name", sPageStyleName); + mpImpl->mWriterDocumentStates.top().mbFirstParagraphInPageSpan = false; + } + + if (mpImpl->mWriterDocumentStates.top().mbTableCellOpened) + { + if (mpImpl->mWriterDocumentStates.top().mbHeaderRow) + pPersistPropList->insert("style:parent-style-name", "Table_Heading"); + else + pPersistPropList->insert("style:parent-style-name", "Table_Contents"); + } + else + pPersistPropList->insert("style:parent-style-name", "Standard"); + + WPXString sKey = getParagraphStyleKey(*pPersistPropList, tabStops); + + if (mpImpl->mTextStyleHash.find(sKey) == mpImpl->mTextStyleHash.end()) + { + WPXString sName; + sName.sprintf("S%i", mpImpl->mTextStyleHash.size()); + + pStyle = new ParagraphStyle(pPersistPropList, tabStops, sName); + + mpImpl->mTextStyleHash[sKey] = pStyle; + } + else + { + pStyle = mpImpl->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()); + mpImpl->mpCurrentContentElements->push_back(pParagraphOpenElement); +} + +void OdtGenerator::closeParagraph() +{ + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:p")); +} + +void OdtGenerator::openSpan(const WPXPropertyList &propList) +{ + if (propList["style:font-name"]) + mpImpl->_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 (mpImpl->mSpanStyleHash.find(sSpanHashKey) == mpImpl->mSpanStyleHash.end()) + { + // allocate a new paragraph style + sName.sprintf("Span%i", mpImpl->mSpanStyleHash.size()); + SpanStyle *pStyle = new SpanStyle(sName.cstr(), propList); + + mpImpl->mSpanStyleHash[sSpanHashKey] = pStyle; + } + else + { + sName.sprintf("%s", mpImpl->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()); + mpImpl->mpCurrentContentElements->push_back(pSpanOpenElement); +} + +void OdtGenerator::closeSpan() +{ + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:span")); +} + +void OdtGenerator::defineOrderedListLevel(const WPXPropertyList &propList) +{ + int id = 0; + if (propList["libwpd:id"]) + id = propList["libwpd:id"]->getInt(); + + OrderedListStyle *pOrderedListStyle = NULL; + if (mpImpl->mWriterListStates.top().mpCurrentListStyle && mpImpl->mWriterListStates.top().mpCurrentListStyle->getListID() == id) + pOrderedListStyle = static_cast<OrderedListStyle *>(mpImpl->mWriterListStates.top().mpCurrentListStyle); // FIXME: using a dynamic cast here causes oo to crash?! + + // this rather appalling conditional makes sure we only start a new list (rather than continue an old + // one) if: (1) we have no prior list OR (2) the prior list is actually definitively different + // from the list that is just being defined (listIDs differ) OR (3) we can tell that the user actually + // is starting a new list at level 1 (and only level 1) + if (pOrderedListStyle == NULL || pOrderedListStyle->getListID() != id || + (propList["libwpd:level"] && propList["libwpd:level"]->getInt()==1 && + (propList["text:start-value"] && static_cast<unsigned>(propList["text:start-value"]->getInt()) != (mpImpl->mWriterListStates.top().miLastListNumber+1)))) + { + WRITER_DEBUG_MSG(("Attempting to create a new ordered list style (listid: %i)\n", id)); + WPXString sName; + sName.sprintf("OL%i", mpImpl->miNumListStyles); + mpImpl->miNumListStyles++; + pOrderedListStyle = new OrderedListStyle(sName.cstr(), id); + mpImpl->mListStyles.push_back(pOrderedListStyle); + mpImpl->mWriterListStates.top().mpCurrentListStyle = pOrderedListStyle; + mpImpl->mWriterListStates.top().mbListContinueNumbering = false; + mpImpl->mWriterListStates.top().miLastListNumber = 0; + } + else + mpImpl->mWriterListStates.top().mbListContinueNumbering = true; + + // Iterate through ALL list styles with the same WordPerfect list id and define a level if it is not already defined + // This solves certain problems with lists that start and finish without reaching certain levels and then begin again + // and reach those levels. See gradguide0405_PC.wpd in the regression suite + for (std::vector<ListStyle *>::iterator iterOrderedListStyles = mpImpl->mListStyles.begin(); iterOrderedListStyles != mpImpl->mListStyles.end(); ++iterOrderedListStyles) + { + if ((* iterOrderedListStyles)->getListID() == id) + (* iterOrderedListStyles)->updateListLevel((propList["libwpd:level"]->getInt() - 1), propList); + } +} + +void OdtGenerator::defineUnorderedListLevel(const WPXPropertyList &propList) +{ + int id = 0; + if (propList["libwpd:id"]) + id = propList["libwpd:id"]->getInt(); + + UnorderedListStyle *pUnorderedListStyle = NULL; + if (mpImpl->mWriterListStates.top().mpCurrentListStyle && mpImpl->mWriterListStates.top().mpCurrentListStyle->getListID() == id) + pUnorderedListStyle = static_cast<UnorderedListStyle *>(mpImpl->mWriterListStates.top().mpCurrentListStyle); // FIXME: using a dynamic cast here causes oo to crash?! + + if (pUnorderedListStyle == NULL) { + WRITER_DEBUG_MSG(("Attempting to create a new unordered list style (listid: %i)\n", id)); + WPXString sName; + sName.sprintf("UL%i", mpImpl->miNumListStyles); + mpImpl->miNumListStyles++; + pUnorderedListStyle = new UnorderedListStyle(sName.cstr(), id); + mpImpl->mListStyles.push_back(pUnorderedListStyle); + mpImpl->mWriterListStates.top().mpCurrentListStyle = pUnorderedListStyle; + } + + // See comment in OdtGenerator::defineOrderedListLevel + for (std::vector<ListStyle *>::iterator iterUnorderedListStyles = mpImpl->mListStyles.begin(); iterUnorderedListStyles != mpImpl->mListStyles.end(); ++iterUnorderedListStyles) + { + if ((* iterUnorderedListStyles)->getListID() == id) + (* iterUnorderedListStyles)->updateListLevel((propList["libwpd:level"]->getInt() - 1), propList); + } +} + +void OdtGenerator::openOrderedListLevel(const WPXPropertyList&) +{ + if (mpImpl->mWriterListStates.top().mbListElementParagraphOpened) + { + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:p")); + mpImpl->mWriterListStates.top().mbListElementParagraphOpened = false; + } + TagOpenElement *pListLevelOpenElement = new TagOpenElement("text:list"); + mpImpl->_openListLevel(pListLevelOpenElement); + + if (mpImpl->mWriterListStates.top().mbListContinueNumbering) { + pListLevelOpenElement->addAttribute("text:continue-numbering", "true"); + } + + mpImpl->mpCurrentContentElements->push_back(pListLevelOpenElement); +} + +void OdtGenerator::openUnorderedListLevel(const WPXPropertyList&) +{ + if (mpImpl->mWriterListStates.top().mbListElementParagraphOpened) + { + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:p")); + mpImpl->mWriterListStates.top().mbListElementParagraphOpened = false; + } + TagOpenElement *pListLevelOpenElement = new TagOpenElement("text:list"); + mpImpl->_openListLevel(pListLevelOpenElement); + + mpImpl->mpCurrentContentElements->push_back(pListLevelOpenElement); +} + +void OdtGeneratorPrivate::_openListLevel(TagOpenElement *pListLevelOpenElement) +{ + if (!mWriterListStates.top().mbListElementOpened.empty() && + !mWriterListStates.top().mbListElementOpened.top()) + { + mpCurrentContentElements->push_back(new TagOpenElement("text:list-item")); + mWriterListStates.top().mbListElementOpened.top() = true; + } + + mWriterListStates.top().mbListElementOpened.push(false); + if (mWriterListStates.top().mbListElementOpened.size() == 1) { + pListLevelOpenElement->addAttribute("text:style-name", mWriterListStates.top().mpCurrentListStyle->getName()); + } +} + +void OdtGenerator::closeOrderedListLevel() +{ + mpImpl->_closeListLevel(); +} + +void OdtGenerator::closeUnorderedListLevel() +{ + mpImpl->_closeListLevel(); +} + +void OdtGeneratorPrivate::_closeListLevel() +{ + if (mWriterListStates.top().mbListElementOpened.top()) + { + mpCurrentContentElements->push_back(new TagCloseElement("text:list-item")); + mWriterListStates.top().mbListElementOpened.top() = false; + } + + mpCurrentContentElements->push_back(new TagCloseElement("text:list")); + + if (!mWriterListStates.top().mbListElementOpened.empty()) + { + mWriterListStates.top().mbListElementOpened.pop(); + } +} + +void OdtGenerator::openListElement(const WPXPropertyList &propList, const WPXPropertyListVector &tabStops) +{ + mpImpl->mWriterListStates.top().miLastListLevel = mpImpl->mWriterListStates.top().miCurrentListLevel; + if (mpImpl->mWriterListStates.top().miCurrentListLevel == 1) + mpImpl->mWriterListStates.top().miLastListNumber++; + + if (mpImpl->mWriterListStates.top().mbListElementOpened.top()) + { + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:list-item")); + mpImpl->mWriterListStates.top().mbListElementOpened.top() = false; + } + + ParagraphStyle *pStyle = NULL; + + WPXPropertyList *pPersistPropList = new WPXPropertyList(propList); + pPersistPropList->insert("style:list-style-name", mpImpl->mWriterListStates.top().mpCurrentListStyle->getName()); + pPersistPropList->insert("style:parent-style-name", "Standard"); + + WPXString sKey = getParagraphStyleKey(*pPersistPropList, tabStops); + + if (mpImpl->mTextStyleHash.find(sKey) == mpImpl->mTextStyleHash.end()) + { + WPXString sName; + sName.sprintf("S%i", mpImpl->mTextStyleHash.size()); + + pStyle = new ParagraphStyle(pPersistPropList, tabStops, sName); + + mpImpl->mTextStyleHash[sKey] = pStyle; + } + else + { + pStyle = mpImpl->mTextStyleHash[sKey]; + delete pPersistPropList; + } + + mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("text:list-item")); + + TagOpenElement *pOpenListElementParagraph = new TagOpenElement("text:p"); + pOpenListElementParagraph->addAttribute("text:style-name", pStyle->getName()); + mpImpl->mpCurrentContentElements->push_back(pOpenListElementParagraph); + + if (mpImpl->mpCurrentContentElements == &(mpImpl->mBodyElements)) + mpImpl->mWriterDocumentStates.top().mbFirstParagraphInPageSpan = false; + + mpImpl->mWriterListStates.top().mbListElementOpened.top() = true; + mpImpl->mWriterListStates.top().mbListElementParagraphOpened = true; + mpImpl->mWriterListStates.top().mbListContinueNumbering = false; +} + +void OdtGenerator::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 (mpImpl->mWriterListStates.top().mbListElementParagraphOpened) + { + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:p")); + mpImpl->mWriterListStates.top().mbListElementParagraphOpened = false; + } +} + +void OdtGenerator::openFootnote(const WPXPropertyList &propList) +{ + mpImpl->mWriterListStates.push(WriterListState()); + TagOpenElement *pOpenFootNote = new TagOpenElement("text:note"); + pOpenFootNote->addAttribute("text:note-class", "footnote"); + if (propList["libwpd:number"]) + { + WPXString tmpString("ftn"); + tmpString.append(propList["libwpd:number"]->getStr()); + pOpenFootNote->addAttribute("text:id", tmpString); + } + mpImpl->mpCurrentContentElements->push_back(pOpenFootNote); + + mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("text:note-citation")); + if (propList["libwpd:number"]) + mpImpl->mpCurrentContentElements->push_back(new CharDataElement(propList["libwpd:number"]->getStr().cstr())); + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:note-citation")); + + mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("text:note-body")); + + mpImpl->mWriterDocumentStates.top().mbInNote = true; +} + +void OdtGenerator::closeFootnote() +{ + mpImpl->mWriterDocumentStates.top().mbInNote = false; + if (mpImpl->mWriterListStates.size() > 1) + mpImpl->mWriterListStates.pop(); + + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:note-body")); + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:note")); +} + +void OdtGenerator::openEndnote(const WPXPropertyList &propList) +{ + mpImpl->mWriterListStates.push(WriterListState()); + TagOpenElement *pOpenEndNote = new TagOpenElement("text:note"); + pOpenEndNote->addAttribute("text:note-class", "endnote"); + if (propList["libwpd:number"]) + { + WPXString tmpString("edn"); + tmpString.append(propList["libwpd:number"]->getStr()); + pOpenEndNote->addAttribute("text:id", tmpString); + } + mpImpl->mpCurrentContentElements->push_back(pOpenEndNote); + + mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("text:note-citation")); + if (propList["libwpd:number"]) + mpImpl->mpCurrentContentElements->push_back(new CharDataElement(propList["libwpd:number"]->getStr().cstr())); + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:note-citation")); + + mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("text:note-body")); + + mpImpl->mWriterDocumentStates.top().mbInNote = true; +} + +void OdtGenerator::closeEndnote() +{ + mpImpl->mWriterDocumentStates.top().mbInNote = false; + if (mpImpl->mWriterListStates.size() > 1) + mpImpl->mWriterListStates.pop(); + + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:note-body")); + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:note")); +} + +void OdtGenerator::openComment(const WPXPropertyList &) +{ + mpImpl->mWriterListStates.push(WriterListState()); + mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("office:annotation")); + + mpImpl->mWriterDocumentStates.top().mbInNote = true; +} + +void OdtGenerator::closeComment() +{ + mpImpl->mWriterDocumentStates.top().mbInNote = false; + if (mpImpl->mWriterListStates.size() > 1) + mpImpl->mWriterListStates.pop(); + + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("office:annotation")); +} + +void OdtGenerator::openTable(const WPXPropertyList &propList, const WPXPropertyListVector &columns) +{ + if (!mpImpl->mWriterDocumentStates.top().mbInNote) + { + WPXString sTableName; + sTableName.sprintf("Table%i", mpImpl->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 (mpImpl->mWriterDocumentStates.top().mbFirstElement && mpImpl->mpCurrentContentElements == &(mpImpl->mBodyElements)) + { + WPXString sMasterPageName("Page_Style_1"); + pTableStyle->setMasterPageName(sMasterPageName); + mpImpl->mWriterDocumentStates.top().mbFirstElement = false; + } + + mpImpl->mTableStyles.push_back(pTableStyle); + + mpImpl->mpCurrentTableStyle = pTableStyle; + + TagOpenElement *pTableOpenElement = new TagOpenElement("table:table"); + + pTableOpenElement->addAttribute("table:name", sTableName.cstr()); + pTableOpenElement->addAttribute("table:style-name", sTableName.cstr()); + mpImpl->mpCurrentContentElements->push_back(pTableOpenElement); + + for (int i=0; i<pTableStyle->getNumColumns(); i++) + { + TagOpenElement *pTableColumnOpenElement = new TagOpenElement("table:table-column"); + WPXString sColumnStyleName; + sColumnStyleName.sprintf("%s.Column%i", sTableName.cstr(), (i+1)); + pTableColumnOpenElement->addAttribute("table:style-name", sColumnStyleName.cstr()); + mpImpl->mpCurrentContentElements->push_back(pTableColumnOpenElement); + + TagCloseElement *pTableColumnCloseElement = new TagCloseElement("table:table-column"); + mpImpl->mpCurrentContentElements->push_back(pTableColumnCloseElement); + } + } +} + +void OdtGenerator::openTableRow(const WPXPropertyList &propList) +{ + if (!mpImpl->mWriterDocumentStates.top().mbInNote) + { + if (propList["libwpd:is-header-row"] && (propList["libwpd:is-header-row"]->getInt())) + { + mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("table:table-header-rows")); + mpImpl->mWriterDocumentStates.top().mbHeaderRow = true; + } + + WPXString sTableRowStyleName; + sTableRowStyleName.sprintf("%s.Row%i", mpImpl->mpCurrentTableStyle->getName().cstr(), mpImpl->mpCurrentTableStyle->getNumTableRowStyles()); + TableRowStyle *pTableRowStyle = new TableRowStyle(propList, sTableRowStyleName.cstr()); + mpImpl->mpCurrentTableStyle->addTableRowStyle(pTableRowStyle); + + TagOpenElement *pTableRowOpenElement = new TagOpenElement("table:table-row"); + pTableRowOpenElement->addAttribute("table:style-name", sTableRowStyleName); + mpImpl->mpCurrentContentElements->push_back(pTableRowOpenElement); + } +} + +void OdtGenerator::closeTableRow() +{ + if (!mpImpl->mWriterDocumentStates.top().mbInNote) + { + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("table:table-row")); + if (mpImpl->mWriterDocumentStates.top().mbHeaderRow) + { + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("table:table-header-rows")); + mpImpl->mWriterDocumentStates.top().mbHeaderRow = false; + } + } +} + +void OdtGenerator::openTableCell(const WPXPropertyList &propList) +{ + if (!mpImpl->mWriterDocumentStates.top().mbInNote) + { + WPXString sTableCellStyleName; + sTableCellStyleName.sprintf( "%s.Cell%i", mpImpl->mpCurrentTableStyle->getName().cstr(), mpImpl->mpCurrentTableStyle->getNumTableCellStyles()); + TableCellStyle *pTableCellStyle = new TableCellStyle(propList, sTableCellStyleName.cstr()); + mpImpl->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"); + mpImpl->mpCurrentContentElements->push_back(pTableCellOpenElement); + + mpImpl->mWriterDocumentStates.top().mbTableCellOpened = true; + } +} + +void OdtGenerator::closeTableCell() +{ + if (!mpImpl->mWriterDocumentStates.top().mbInNote) + { + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("table:table-cell")); + mpImpl->mWriterDocumentStates.top().mbTableCellOpened = false; + } +} + +void OdtGenerator::insertCoveredTableCell(const WPXPropertyList &) +{ + if (!mpImpl->mWriterDocumentStates.top().mbInNote) + { + mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("table:covered-table-cell")); + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("table:covered-table-cell")); + } +} + +void OdtGenerator::closeTable() +{ + if (!mpImpl->mWriterDocumentStates.top().mbInNote) + { + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("table:table")); + } +} + + +void OdtGenerator::insertTab() +{ + mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("text:tab")); + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:tab")); +} + +void OdtGenerator::insertSpace() +{ + mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("text:s")); + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:s")); +} + +void OdtGenerator::insertLineBreak() +{ + mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("text:line-break")); + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("text:line-break")); +} + +void OdtGenerator::insertField(const WPXString &type, const WPXPropertyList &propList) +{ + if (!type.len()) + return; + + TagOpenElement *openElement = new TagOpenElement(type); + if (type == "text:page-number") + openElement->addAttribute("text:select-page", "current"); + + if (propList["style:num-format"]) + openElement->addAttribute("style:num-format", propList["style:num-format"]->getStr()); + + mpImpl->mpCurrentContentElements->push_back(openElement); + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement(type)); +} + +void OdtGenerator::insertText(const WPXString &text) +{ + DocumentElement *pText = new TextElement(text); + mpImpl->mpCurrentContentElements->push_back(pText); +} + +void OdtGenerator::openFrame(const WPXPropertyList &propList) +{ + mpImpl->mWriterListStates.push(WriterListState()); + + // First, let's create a Frame Style for this box + TagOpenElement *frameStyleOpenElement = new TagOpenElement("style:style"); + WPXString frameStyleName; + frameStyleName.sprintf("GraphicFrame_%i", mpImpl->miObjectNumber); + frameStyleOpenElement->addAttribute("style:name", frameStyleName); + frameStyleOpenElement->addAttribute("style:family", "graphic"); + + mpImpl->mFrameStyles.push_back(frameStyleOpenElement); + + TagOpenElement *frameStylePropertiesOpenElement = new TagOpenElement("style:graphic-properties"); + + if (propList["text:anchor-type"]) + frameStylePropertiesOpenElement->addAttribute("text:anchor-type", propList["text:anchor-type"]->getStr()); + else + frameStylePropertiesOpenElement->addAttribute("text:anchor-type","paragraph"); + + if (propList["text:anchor-page-number"]) + frameStylePropertiesOpenElement->addAttribute("text:anchor-page-number", propList["text:anchor-page-number"]->getStr()); + + if (propList["svg:x"]) + frameStylePropertiesOpenElement->addAttribute("svg:x", propList["svg:x"]->getStr()); + + if (propList["svg:y"]) + frameStylePropertiesOpenElement->addAttribute("svg:y", propList["svg:y"]->getStr()); + + if (propList["svg:width"]) + frameStylePropertiesOpenElement->addAttribute("svg:width", propList["svg:width"]->getStr()); + + if (propList["svg:height"]) + frameStylePropertiesOpenElement->addAttribute("svg:height", propList["svg:height"]->getStr()); + + if (propList["style:rel-width"]) + frameStylePropertiesOpenElement->addAttribute("style:rel-width", propList["style:rel-width"]->getStr()); + + if (propList["style:rel-height"]) + frameStylePropertiesOpenElement->addAttribute("style:rel-height", propList["style:rel-height"]->getStr()); + + if (propList["fo:max-width"]) + frameStylePropertiesOpenElement->addAttribute("fo:max-width", propList["fo:max-width"]->getStr()); + + if (propList["fo:max-height"]) + frameStylePropertiesOpenElement->addAttribute("fo:max-height", propList["fo:max-height"]->getStr()); + + if (propList["style:wrap"]) + frameStylePropertiesOpenElement->addAttribute("style:wrap", propList["style:wrap"]->getStr()); + + mpImpl->mFrameStyles.push_back(frameStylePropertiesOpenElement); + + mpImpl->mFrameStyles.push_back(new TagCloseElement("style:graphic-properties")); + + mpImpl->mFrameStyles.push_back(new TagCloseElement("style:style")); + + // Now, let's create an automatic style for this frame + TagOpenElement *frameAutomaticStyleElement = new TagOpenElement("style:style"); + WPXString frameAutomaticStyleName; + frameAutomaticStyleName.sprintf("fr%i", mpImpl->miObjectNumber); + frameAutomaticStyleElement->addAttribute("style:name", frameAutomaticStyleName); + frameAutomaticStyleElement->addAttribute("style:family", "graphic"); + frameAutomaticStyleElement->addAttribute("style:parent-style-name", frameStyleName); + + mpImpl->mFrameAutomaticStyles.push_back(frameAutomaticStyleElement); + + TagOpenElement *frameAutomaticStylePropertiesElement = new TagOpenElement("style:graphic-properties"); + if (propList["style:horizontal-pos"]) + frameAutomaticStylePropertiesElement->addAttribute("style:horizontal-pos", propList["style:horizontal-pos"]->getStr()); + else + frameAutomaticStylePropertiesElement->addAttribute("style:horizontal-pos", "left"); + + if (propList["style:horizontal-rel"]) + frameAutomaticStylePropertiesElement->addAttribute("style:horizontal-rel", propList["style:horizontal-rel"]->getStr()); + else + frameAutomaticStylePropertiesElement->addAttribute("style:horizontal-rel", "paragraph"); + + if (propList["style:vertical-pos"]) + frameAutomaticStylePropertiesElement->addAttribute("style:vertical-pos", propList["style:vertical-pos"]->getStr()); + else + frameAutomaticStylePropertiesElement->addAttribute("style:vertical-pos", "top"); + + if (propList["style:vertical-rel"]) + frameAutomaticStylePropertiesElement->addAttribute("style:vertical-rel", propList["style:vertical-rel"]->getStr()); + else + frameAutomaticStylePropertiesElement->addAttribute("style:vertical-rel", "page-content"); + + if (propList["fo:max-width"]) + frameAutomaticStylePropertiesElement->addAttribute("fo:max-width", propList["fo:max-width"]->getStr()); + + if (propList["fo:max-height"]) + frameAutomaticStylePropertiesElement->addAttribute("fo:max-height", propList["fo:max-height"]->getStr()); + + frameAutomaticStylePropertiesElement->addAttribute("draw:ole-draw-aspect", "1"); + + mpImpl->mFrameAutomaticStyles.push_back(frameAutomaticStylePropertiesElement); + + mpImpl->mFrameAutomaticStyles.push_back(new TagCloseElement("style:graphic-properties")); + + mpImpl->mFrameAutomaticStyles.push_back(new TagCloseElement("style:style")); + + // And write the frame itself + TagOpenElement *drawFrameOpenElement = new TagOpenElement("draw:frame"); + + drawFrameOpenElement->addAttribute("draw:style-name", frameAutomaticStyleName); + WPXString objectName; + objectName.sprintf("Object%i", mpImpl->miObjectNumber++); + drawFrameOpenElement->addAttribute("draw:name", objectName); + if (propList["text:anchor-type"]) + drawFrameOpenElement->addAttribute("text:anchor-type", propList["text:anchor-type"]->getStr()); + else + drawFrameOpenElement->addAttribute("text:anchor-type","paragraph"); + + if (propList["text:anchor-page-number"]) + drawFrameOpenElement->addAttribute("text:anchor-page-number", propList["text:anchor-page-number"]->getStr()); + + if (propList["svg:x"]) + drawFrameOpenElement->addAttribute("svg:x", propList["svg:x"]->getStr()); + + if (propList["svg:y"]) + drawFrameOpenElement->addAttribute("svg:y", propList["svg:y"]->getStr()); + + if (propList["svg:width"]) + drawFrameOpenElement->addAttribute("svg:width", propList["svg:width"]->getStr()); + + if (propList["svg:height"]) + drawFrameOpenElement->addAttribute("svg:height", propList["svg:height"]->getStr()); + + if (propList["style:rel-width"]) + drawFrameOpenElement->addAttribute("style:rel-width", propList["style:rel-width"]->getStr()); + + if (propList["style:rel-height"]) + drawFrameOpenElement->addAttribute("style:rel-height", propList["style:rel-height"]->getStr()); + + mpImpl->mpCurrentContentElements->push_back(drawFrameOpenElement); + + mpImpl->mWriterDocumentStates.top().mbInFrame = true; +} + +void OdtGenerator::closeFrame() +{ + if (mpImpl->mWriterListStates.size() > 1) + mpImpl->mWriterListStates.pop(); + + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("draw:frame")); + + mpImpl->mWriterDocumentStates.top().mbInFrame = false; +} + +void OdtGenerator::insertBinaryObject(const WPXPropertyList &propList, const WPXBinaryData &data) +{ + if (!data.size()) + return; + if (!mpImpl->mWriterDocumentStates.top().mbInFrame) // Embedded objects without a frame simply don't make sense for us + return; + if (!propList["libwpd:mimetype"]) + return; + + OdfEmbeddedObject tmpObjectHandler = mpImpl->_findEmbeddedObjectHandler(propList["libwpd:mimetype"]->getStr()); + + if (tmpObjectHandler) + { + std::vector<DocumentElement *> tmpContentElements; + InternalHandler tmpHandler(&tmpContentElements); + + if (tmpObjectHandler(data, &tmpHandler, ODF_FLAT_XML) && !tmpContentElements.empty()) + { + mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("draw:object")); + for (std::vector<DocumentElement *>::const_iterator iter = tmpContentElements.begin(); iter != tmpContentElements.end(); ++iter) + mpImpl->mpCurrentContentElements->push_back(*iter); + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("draw:object")); + } + } + else + // assuming we have a binary image that we can just insert as it is + { + mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("draw:image")); + + mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("office:binary-data")); + + WPXString binaryBase64Data = data.getBase64Data(); + + mpImpl->mpCurrentContentElements->push_back(new CharDataElement(binaryBase64Data.cstr())); + + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("office:binary-data")); + + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("draw:image")); + } +} + +void OdtGenerator::openTextBox(const WPXPropertyList &) +{ + if (!mpImpl->mWriterDocumentStates.top().mbInFrame) // Text box without a frame simply doesn't make sense for us + return; + mpImpl->mWriterListStates.push(WriterListState()); + mpImpl->mWriterDocumentStates.push(WriterDocumentState()); + mpImpl->mpCurrentContentElements->push_back(new TagOpenElement("draw:text-box")); + mpImpl->mWriterDocumentStates.top().mbInTextBox = true; + mpImpl->mWriterDocumentStates.top().mbFirstElement = false; +} + +void OdtGenerator::closeTextBox() +{ + if (!mpImpl->mWriterDocumentStates.top().mbInTextBox) + return; + if (mpImpl->mWriterListStates.size() > 1) + mpImpl->mWriterListStates.pop(); + if (mpImpl->mWriterDocumentStates.size() > 1) + mpImpl->mWriterDocumentStates.pop(); + + mpImpl->mpCurrentContentElements->push_back(new TagCloseElement("draw:text-box")); +} + +void OdtGenerator::defineSectionStyle(WPXPropertyList const&, WPXPropertyListVector const&) +{ +} + +void OdtGenerator::insertEquation(WPXPropertyList const&, WPXString const&) +{ +} + +void OdtGenerator::endDocument() +{ + // Write out the collected document + mpImpl->_writeTargetDocument(mpImpl->mpHandler); +} + +void OdtGenerator::startDocument() +{ +} + +void OdtGenerator::closePageSpan() +{ +} + +void OdtGenerator::definePageStyle(WPXPropertyList const&) +{ +} + +void OdtGenerator::defineParagraphStyle(WPXPropertyList const&, WPXPropertyListVector const&) +{ +} + +void OdtGenerator::defineCharacterStyle(WPXPropertyList const&) +{ +} + +void OdtGenerator::registerEmbeddedObjectHandler(const WPXString &mimeType, OdfEmbeddedObject objectHandler) +{ + mpImpl->mObjectHandlers[mimeType] = objectHandler; +} diff --git a/writerperfect/source/filter/OdtGenerator.hxx b/writerperfect/source/filter/OdtGenerator.hxx new file mode 100644 index 000000000000..1b7f5268f88b --- /dev/null +++ b/writerperfect/source/filter/OdtGenerator.hxx @@ -0,0 +1,119 @@ +/* OdtGenerator: Collects sections and runs of text from a + * wordperfect file (and styles to go along with them) and writes them + * to a target file + * + * Copyright (C) 2002-2004 William Lachance (wrlach@gmail.com) + * 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 _ODTGENERATOR_H +#define _ODTGENERATOR_H + +#include <libwpd/libwpd.h> + +#include "OdfDocumentHandler.hxx" + + +typedef bool (*OdfEmbeddedObject)(const WPXBinaryData &data, OdfDocumentHandler *pHandler, const OdfStreamType streamType); + +class OdtGeneratorPrivate; + +class OdtGenerator : public WPXDocumentInterface +{ +public: + OdtGenerator(OdfDocumentHandler *pHandler, const OdfStreamType streamType); + ~OdtGenerator(); + + // WPXDocumentInterface's implementation + void setDocumentMetaData(const WPXPropertyList &propList); + void startDocument(); + void endDocument(); + + void definePageStyle(const WPXPropertyList&); + void openPageSpan(const WPXPropertyList &propList); + void closePageSpan(); + + void defineSectionStyle(const WPXPropertyList&, const WPXPropertyListVector&); + void openSection(const WPXPropertyList &propList, const WPXPropertyListVector &columns); + void closeSection(); + + void openHeader(const WPXPropertyList &propList); + void closeHeader(); + void openFooter(const WPXPropertyList &propList); + void closeFooter(); + + void defineParagraphStyle(const WPXPropertyList&, const WPXPropertyListVector&); + void openParagraph(const WPXPropertyList &propList, const WPXPropertyListVector &tabStops); + void closeParagraph(); + + void defineCharacterStyle(const WPXPropertyList&); + void openSpan(const WPXPropertyList &propList); + void closeSpan(); + + void insertTab(); + void insertSpace(); + void insertText(const WPXString &text); + void insertLineBreak(); + void insertField(const WPXString &type, const WPXPropertyList &propList); + + void defineOrderedListLevel(const WPXPropertyList &propList); + void defineUnorderedListLevel(const WPXPropertyList &propList); + void openOrderedListLevel(const WPXPropertyList &propList); + void openUnorderedListLevel(const WPXPropertyList &propList); + void closeOrderedListLevel(); + void closeUnorderedListLevel(); + void openListElement(const WPXPropertyList &propList, const WPXPropertyListVector &tabStops); + void closeListElement(); + + void openFootnote(const WPXPropertyList &propList); + void closeFootnote(); + void openEndnote(const WPXPropertyList &propList); + void closeEndnote(); + void openComment(const WPXPropertyList &propList); + void closeComment(); + void openTextBox(const WPXPropertyList &propList); + void closeTextBox(); + + void openTable(const WPXPropertyList &propList, const WPXPropertyListVector &columns); + void openTableRow(const WPXPropertyList &propList); + void closeTableRow(); + void openTableCell(const WPXPropertyList &propList); + void closeTableCell(); + void insertCoveredTableCell(const WPXPropertyList &propList); + void closeTable(); + + void openFrame(const WPXPropertyList & propList); + void closeFrame(); + + void insertBinaryObject(const WPXPropertyList &propList, const WPXBinaryData &data); + void insertEquation(const WPXPropertyList &propList, const WPXString &data); + + // Register special converter for certain embedded binary objects + void registerEmbeddedObjectHandler(const WPXString &mimeType, OdfEmbeddedObject objectHandler); + +private: + OdtGeneratorPrivate *mpImpl; +}; +#endif diff --git a/writerperfect/source/filter/PageSpan.cxx b/writerperfect/source/filter/PageSpan.cxx new file mode 100644 index 000000000000..277537e57450 --- /dev/null +++ b/writerperfect/source/filter/PageSpan.cxx @@ -0,0 +1,274 @@ +/* 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 (wrlach@gmail.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 + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#include <stdlib.h> + +#include "FilterInternal.hxx" +#include "PageSpan.hxx" +#include "DocumentElement.hxx" + +PageSpan::PageSpan(const WPXPropertyList &xPropList) : + mxPropList(xPropList), + mpHeaderContent(NULL), + mpFooterContent(NULL), + mpHeaderLeftContent(NULL), + mpFooterLeftContent(NULL) +{ +} + +namespace { + typedef std::vector<DocumentElement *>::iterator DEVIter; +} + +PageSpan::~PageSpan() +{ + if (mpHeaderContent) + { + for (DEVIter iterHeaderContent = mpHeaderContent->begin(); + iterHeaderContent != mpHeaderContent->end(); + iterHeaderContent++) + delete(*iterHeaderContent); + delete mpHeaderContent; + } + + if (mpHeaderLeftContent) + { + for (DEVIter iterHeaderLeftContent = mpHeaderLeftContent->begin(); + iterHeaderLeftContent != mpHeaderLeftContent->end(); + iterHeaderLeftContent++) + delete(*iterHeaderLeftContent); + delete mpHeaderLeftContent; + } + + if (mpFooterContent) + { + for (DEVIter iterFooterContent = mpFooterContent->begin(); + iterFooterContent != mpFooterContent->end(); + iterFooterContent++) + delete(*iterFooterContent); + delete mpFooterContent; + } + + if (mpFooterLeftContent) + { + for (DEVIter iterFooterLeftContent = mpFooterLeftContent->begin(); + iterFooterLeftContent != mpFooterLeftContent->end(); + iterFooterLeftContent++) + delete(*iterFooterLeftContent); + delete mpFooterLeftContent; + } +} + +int PageSpan::getSpan() const +{ + if (mxPropList["libwpd:num-pages"]) + return mxPropList["libwpd:num-pages"]->getInt(); + + return 0; // should never happen +} + +double PageSpan::getMarginLeft() const +{ + if (mxPropList["fo:margin-left"]) + return mxPropList["fo:margin-left"]->getDouble(); + + return 0.0; +} + +double PageSpan::getMarginRight() const +{ + if (mxPropList["fo:margin-right"]) + return mxPropList["fo:margin-right"]->getDouble(); + + return 0.0; +} + +void PageSpan::setHeaderContent(std::vector<DocumentElement *> * pHeaderContent) +{ + if (mpHeaderContent) + { + for (DEVIter iterHeaderContent = mpHeaderContent->begin(); + iterHeaderContent != mpHeaderContent->end(); + iterHeaderContent++) + delete(*iterHeaderContent); + delete mpHeaderContent; + } + + mpHeaderContent = pHeaderContent; +} + +void PageSpan::setFooterContent(std::vector<DocumentElement *> * pFooterContent) +{ + if (mpFooterContent) + { + for (DEVIter iterFooterContent = mpFooterContent->begin(); + iterFooterContent != mpFooterContent->end(); + iterFooterContent++) + delete(*iterFooterContent); + delete mpFooterContent; + } + + mpFooterContent = pFooterContent; +} + +void PageSpan::setHeaderLeftContent(std::vector<DocumentElement *> * pHeaderContent) +{ + if (mpHeaderLeftContent) + { + for (DEVIter iterHeaderLeftContent = mpHeaderLeftContent->begin(); + iterHeaderLeftContent != mpHeaderLeftContent->end(); + iterHeaderLeftContent++) + delete(*iterHeaderLeftContent); + delete mpHeaderLeftContent; + } + + mpHeaderLeftContent = pHeaderContent; +} + +void PageSpan::setFooterLeftContent(std::vector<DocumentElement *> * pFooterContent) +{ + if (mpFooterLeftContent) + { + for (DEVIter iterFooterLeftContent = mpFooterLeftContent->begin(); + iterFooterLeftContent != mpFooterLeftContent->end(); + iterFooterLeftContent++) + delete(*iterFooterLeftContent); + delete mpFooterLeftContent; + } + + mpFooterLeftContent = pFooterContent; +} + +void PageSpan::writePageLayout(const int iNum, OdfDocumentHandler *pHandler) const +{ + WPXPropertyList propList; + + WPXString sPageLayoutName; + sPageLayoutName.sprintf("PM%i", iNum+2); + propList.insert("style:name", sPageLayoutName); + pHandler->startElement("style:page-layout", propList); + + WPXPropertyList tempPropList = mxPropList; + if (!tempPropList["style:writing-mode"]) + tempPropList.insert("style:writing-mode", WPXString("lr-tb")); + if (!tempPropList["style:footnote-max-height"]) + tempPropList.insert("style:footnote-max-height", WPXString("0in")); + pHandler->startElement("style:page-layout-properties", tempPropList); + + WPXPropertyList footnoteSepPropList; + footnoteSepPropList.insert("style:width", WPXString("0.0071in")); + footnoteSepPropList.insert("style:distance-before-sep", WPXString("0.0398in")); + footnoteSepPropList.insert("style:distance-after-sep", WPXString("0.0398in")); + footnoteSepPropList.insert("style:adjustment", WPXString("left")); + footnoteSepPropList.insert("style:rel-width", WPXString("25%")); + footnoteSepPropList.insert("style:color", WPXString("#000000")); + pHandler->startElement("style:footnote-sep", footnoteSepPropList); + + pHandler->endElement("style:footnote-sep"); + pHandler->endElement("style:page-layout-properties"); + pHandler->endElement("style:page-layout"); +} + +void PageSpan::writeMasterPages(const int iStartingNum, const int iPageLayoutNum, const bool bLastPageSpan, + OdfDocumentHandler *pHandler) const +{ + int iSpan = 0; + (bLastPageSpan) ? iSpan = 1 : iSpan = getSpan(); + + for (int i=iStartingNum; i<(iStartingNum+iSpan); i++) + { + TagOpenElement masterPageOpen("style:master-page"); + WPXString sMasterPageName, sMasterPageDisplayName; + sMasterPageName.sprintf("Page_Style_%i", i); + sMasterPageDisplayName.sprintf("Page Style %i", i); + WPXString sPageLayoutName; + WPXPropertyList propList; + sPageLayoutName.sprintf("PM%i", iPageLayoutNum+2); + propList.insert("style:name", sMasterPageName); + propList.insert("style:display-name", sMasterPageDisplayName); + propList.insert("style:page-layout-name", sPageLayoutName); + if (!bLastPageSpan) + { + WPXString sNextMasterPageName; + sNextMasterPageName.sprintf("Page_Style_%i", (i+1)); + propList.insert("style:next-style-name", sNextMasterPageName); + } + pHandler->startElement("style:master-page", propList); + + if (mpHeaderContent) + { + _writeHeaderFooter("style:header", *mpHeaderContent, pHandler); + pHandler->endElement("style:header"); + if (mpHeaderLeftContent) + { + _writeHeaderFooter("style:header-left", *mpHeaderLeftContent, pHandler); + pHandler->endElement("style:header-left"); + } + } + else if (mpHeaderLeftContent) + { + TagOpenElement("style:header").write(pHandler); + pHandler->endElement("style:header"); + _writeHeaderFooter("style:header-left", *mpHeaderLeftContent, pHandler); + pHandler->endElement("style:header-left"); + } + + if (mpFooterContent) + { + _writeHeaderFooter("style:footer", *mpFooterContent, pHandler); + pHandler->endElement("style:footer"); + if (mpFooterLeftContent) + { + _writeHeaderFooter("style:footer-left", *mpFooterLeftContent, pHandler); + pHandler->endElement("style:footer-left"); + } + } + else if (mpFooterLeftContent) + { + TagOpenElement("style:footer").write(pHandler); + pHandler->endElement("style:footer"); + _writeHeaderFooter("style:footer-left", *mpFooterLeftContent, pHandler); + pHandler->endElement("style:footer-left"); + } + + pHandler->endElement("style:master-page"); + } +} + +void PageSpan::_writeHeaderFooter(const char *headerFooterTagName, + const std::vector<DocumentElement *> & headerFooterContent, + OdfDocumentHandler *pHandler) const +{ + TagOpenElement headerFooterOpen(headerFooterTagName); + headerFooterOpen.write(pHandler); + for (std::vector<DocumentElement *>::const_iterator iter = headerFooterContent.begin(); + iter != headerFooterContent.end(); + ++iter) { + (*iter)->write(pHandler); + } +} diff --git a/writerperfect/source/filter/PageSpan.hxx b/writerperfect/source/filter/PageSpan.hxx new file mode 100644 index 000000000000..c991fd41f0ff --- /dev/null +++ b/writerperfect/source/filter/PageSpan.hxx @@ -0,0 +1,60 @@ +/* PageSpan: Stores (and writes) page-based information (e.g.: margins, + * headers/footers) + * + * Copyright (C) 2002-2004 William Lachance (wrlach@gmail.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 + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef _PAGESPAN_H +#define _PAGESPAN_H +#include <libwpd/libwpd.h> +#include <vector> + +class DocumentElement; +class OdfDocumentHandler; + +class PageSpan +{ +public: + PageSpan(const WPXPropertyList &xPropList); + virtual ~PageSpan(); + void writePageLayout(const int iNum, OdfDocumentHandler *pHandler) const; + void writeMasterPages(const int iStartingNum, const int iPageLayoutNum, const bool bLastPageSpan, OdfDocumentHandler *pHandler) const; + int getSpan() const; + double getMarginLeft() const; + double getMarginRight() const; + + void setHeaderContent(std::vector<DocumentElement *> * pHeaderContent); + void setFooterContent(std::vector<DocumentElement *> * pFooterContent); + void setHeaderLeftContent(std::vector<DocumentElement *> * pHeaderContent); + void setFooterLeftContent(std::vector<DocumentElement *> * pFooterContent); +protected: + void _writeHeaderFooter(const char *headerFooterTagName, const std::vector<DocumentElement *> & headerFooterContent, + OdfDocumentHandler *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..8d49ef5004c3 --- /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 (wrlach@gmail.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 "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(OdfDocumentHandler *pHandler) const +{ + TagOpenElement styleOpen("style:style"); + styleOpen.addAttribute("style:name", getName()); + styleOpen.addAttribute("style:family", "section"); + styleOpen.write(pHandler); + + // if the number of columns is <= 1, we will never come here. This is only an additional check + // style properties + pHandler->startElement("style:section-properties", mPropList); + + // column properties + WPXPropertyList columnProps; + + if (mColumns.count() > 1) + { + columnProps.insert("fo:column-count", (int)mColumns.count()); + pHandler->startElement("style:columns", columnProps); + + WPXPropertyListVector::Iter i(mColumns); + for (i.rewind(); i.next();) + { + pHandler->startElement("style:column", i()); + pHandler->endElement("style:column"); + } + } + else + { + columnProps.insert("fo:column-count", 0); + columnProps.insert("fo:column-gap", 0.0); + pHandler->startElement("style:columns", columnProps); + } + + pHandler->endElement("style:columns"); + + + pHandler->endElement("style:section-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..7b5379af29be --- /dev/null +++ b/writerperfect/source/filter/SectionStyle.hxx @@ -0,0 +1,46 @@ +/* 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 (wrlach@gmail.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 + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef _SECTIONSTYLE_H +#define _SECTIONSTYLE_H +#include <libwpd/libwpd.h> +#include <libwpd/WPXPropertyListVector.h> + +#include "Style.hxx" +#include "WriterProperties.hxx" + + +class SectionStyle : public Style +{ +public: + SectionStyle(const WPXPropertyList &xPropList, const WPXPropertyListVector &xColumns, const char *psName); + virtual void write(OdfDocumentHandler *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..d68ed26fc6da --- /dev/null +++ b/writerperfect/source/filter/Style.hxx @@ -0,0 +1,58 @@ +/* Style: A base class from which all other styles are inherited, includes + * a name. + * + * Copyright (C) 2002-2003 William Lachance (wrlach@gmail.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 + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#ifndef _STYLE_H +#define _STYLE_H +#include <cstdlib> +#include <libwpd/libwpd.h> +#include "DocumentElement.hxx" + +class TopLevelElementStyle +{ +public: + TopLevelElementStyle() : mpsMasterPageName(NULL) { } + virtual ~TopLevelElementStyle() { if (mpsMasterPageName) delete mpsMasterPageName; } + void setMasterPageName(WPXString &sMasterPageName) { mpsMasterPageName = new WPXString(sMasterPageName); } + const WPXString * getMasterPageName() const { return mpsMasterPageName; } + +private: + WPXString *mpsMasterPageName; +}; + +class Style +{ + public: + Style(const WPXString &psName) : msName(psName) {} + virtual ~Style() {} + + virtual void write(OdfDocumentHandler *) 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..6bb4bb95a7c4 --- /dev/null +++ b/writerperfect/source/filter/TableStyle.cxx @@ -0,0 +1,164 @@ +/* TableStyle: Stores (and writes) table-based information that is + * needed at the head of an OO document. + * + * Copyright (C) 2002-2004 William Lachance (wrlach@gmail.com) + * Copyright (C) 2004 Net Integration Technologies, Inc. (http://www.net-itech.com) + * Copyright (C) 2004 Fridrich Strba (fridrich.strba@bluewin.ch) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * For further information visit http://libwpd.sourceforge.net + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#include <math.h> +#include "FilterInternal.hxx" +#include "TableStyle.hxx" +#include "DocumentElement.hxx" + +#ifdef _MSC_VER +#include <minmax.h> +#endif + +#include <string.h> + +TableCellStyle::TableCellStyle(const WPXPropertyList &xPropList, const char *psName) : + Style(psName), + mPropList(xPropList) +{ +} + +void TableCellStyle::write(OdfDocumentHandler *pHandler) const +{ + TagOpenElement styleOpen("style:style"); + styleOpen.addAttribute("style:name", getName()); + styleOpen.addAttribute("style:family", "table-cell"); + styleOpen.write(pHandler); + + // WLACH_REFACTORING: Only temporary.. a much better solution is to + // generalize this sort of thing into the "Style" superclass + WPXPropertyList stylePropList; + WPXPropertyList::Iter i(mPropList); + for (i.rewind(); i.next();) + { + if (strlen(i.key()) > 2 && strncmp(i.key(), "fo", 2) == 0) + stylePropList.insert(i.key(), i()->clone()); + } + stylePropList.insert("fo:padding", "0.0382in"); + pHandler->startElement("style:table-cell-properties", stylePropList); + pHandler->endElement("style:table-cell-properties"); + + pHandler->endElement("style:style"); +} + +TableRowStyle::TableRowStyle(const WPXPropertyList &propList, const char *psName) : + Style(psName), + mPropList(propList) +{ +} + +void TableRowStyle::write(OdfDocumentHandler *pHandler) const +{ + TagOpenElement styleOpen("style:style"); + styleOpen.addAttribute("style:name", getName()); + styleOpen.addAttribute("style:family", "table-row"); + styleOpen.write(pHandler); + + TagOpenElement stylePropertiesOpen("style:table-row-properties"); + if (mPropList["style:min-row-height"]) + stylePropertiesOpen.addAttribute("style:min-row-height", mPropList["style:min-row-height"]->getStr()); + else if (mPropList["style:row-height"]) + stylePropertiesOpen.addAttribute("style:row-height", mPropList["style:row-height"]->getStr()); + stylePropertiesOpen.addAttribute("fo:keep-together", "auto"); + stylePropertiesOpen.write(pHandler); + pHandler->endElement("style:table-row-properties"); + + pHandler->endElement("style:style"); +} + + +TableStyle::TableStyle(const WPXPropertyList &xPropList, const WPXPropertyListVector &columns, const char *psName) : + Style(psName), + mPropList(xPropList), + mColumns(columns) +{ +} + +TableStyle::~TableStyle() +{ + typedef std::vector<TableCellStyle *>::iterator TCSVIter; + typedef std::vector<TableRowStyle *>::iterator TRSVIter; + for (TCSVIter iterTableCellStyles = mTableCellStyles.begin() ; iterTableCellStyles != mTableCellStyles.end(); ++iterTableCellStyles) + delete(*iterTableCellStyles); + for (TRSVIter iterTableRowStyles = mTableRowStyles.begin() ; iterTableRowStyles != mTableRowStyles.end(); ++iterTableRowStyles) + delete(*iterTableRowStyles); +} + +void TableStyle::write(OdfDocumentHandler *pHandler) const +{ + TagOpenElement styleOpen("style:style"); + styleOpen.addAttribute("style:name", getName()); + styleOpen.addAttribute("style:family", "table"); + if (getMasterPageName()) + styleOpen.addAttribute("style:master-page-name", getMasterPageName()->cstr()); + styleOpen.write(pHandler); + + TagOpenElement stylePropertiesOpen("style:table-properties"); + if (mPropList["table:align"]) + stylePropertiesOpen.addAttribute("table:align", mPropList["table:align"]->getStr()); + if (mPropList["fo:margin-left"]) + stylePropertiesOpen.addAttribute("fo:margin-left", mPropList["fo:margin-left"]->getStr()); + if (mPropList["fo:margin-right"]) + stylePropertiesOpen.addAttribute("fo:margin-right", mPropList["fo:margin-right"]->getStr()); + if (mPropList["style:width"]) + stylePropertiesOpen.addAttribute("style:width", mPropList["style:width"]->getStr()); + if (mPropList["fo:break-before"]) + stylePropertiesOpen.addAttribute("fo:break-before", mPropList["fo:break-before"]->getStr()); + stylePropertiesOpen.write(pHandler); + + pHandler->endElement("style:table-properties"); + + pHandler->endElement("style:style"); + + int i=1; + WPXPropertyListVector::Iter j(mColumns); + for (j.rewind(); j.next();) + { + TagOpenElement columnStyleOpen("style:style"); + WPXString sColumnName; + sColumnName.sprintf("%s.Column%i", getName().cstr(), i); + columnStyleOpen.addAttribute("style:name", sColumnName); + columnStyleOpen.addAttribute("style:family", "table-column"); + columnStyleOpen.write(pHandler); + + pHandler->startElement("style:table-column-properties", j()); + pHandler->endElement("style:table-column-properties"); + + pHandler->endElement("style:style"); + + i++; + } + + typedef std::vector<TableRowStyle *>::const_iterator TRSVIter; + for (TRSVIter iterTableRow = mTableRowStyles.begin() ; iterTableRow != mTableRowStyles.end(); ++iterTableRow) + (*iterTableRow)->write(pHandler); + + typedef std::vector<TableCellStyle *>::const_iterator TCSVIter; + for (TCSVIter iterTableCell = mTableCellStyles.begin() ; iterTableCell != mTableCellStyles.end(); ++iterTableCell) + (*iterTableCell)->write(pHandler); +} diff --git a/writerperfect/source/filter/TableStyle.hxx b/writerperfect/source/filter/TableStyle.hxx new file mode 100644 index 000000000000..f60993d7ea38 --- /dev/null +++ b/writerperfect/source/filter/TableStyle.hxx @@ -0,0 +1,76 @@ +/* TableStyle: Stores (and writes) table-based information that is + * needed at the head of an OO document. + * + * Copyright (C) 2002-2003 William Lachance (wrlach@gmail.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 _TABLESTYLE_H +#define _TABLESTYLE_H +#include <libwpd/libwpd.h> +#include <vector> + +#include "Style.hxx" +#include "WriterProperties.hxx" + +class DocumentElement; +class OdfDocumentHandler; + +class TableCellStyle : public Style +{ +public: + virtual ~TableCellStyle() {}; + TableCellStyle(const WPXPropertyList &xPropList, const char *psName); + virtual void write(OdfDocumentHandler *pHandler) const; +private: + WPXPropertyList mPropList; +}; + +class TableRowStyle : public Style +{ +public: + virtual ~TableRowStyle() {}; + TableRowStyle(const WPXPropertyList &propList, const char *psName); + virtual void write(OdfDocumentHandler *pHandler) const; +private: + WPXPropertyList mPropList; +}; + +class TableStyle : public Style, public TopLevelElementStyle +{ +public: + TableStyle(const WPXPropertyList &xPropList, const WPXPropertyListVector &columns, const char *psName); + virtual ~TableStyle(); + virtual void write(OdfDocumentHandler *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..4b169883c392 --- /dev/null +++ b/writerperfect/source/filter/TextRunStyle.cxx @@ -0,0 +1,179 @@ +/* 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 (wrlach@gmail.com) + * 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(OdfDocumentHandler *pHandler) const +{ + WRITER_DEBUG_MSG(("Writing a paragraph style..\n")); + + WPXPropertyList propList; + propList.insert("style:name", msName.cstr()); + propList.insert("style:family", "paragraph"); + propList.insert("style:parent-style-name", (*mpPropList)["style:parent-style-name"]->getStr()); + if ((*mpPropList)["style:master-page-name"]) + propList.insert("style:master-page-name", (*mpPropList)["style:master-page-name"]->getStr()); + pHandler->startElement("style:style", propList); + + propList.clear(); + WPXPropertyList::Iter i((*mpPropList)); + for (i.rewind(); i.next(); ) + { +#if 0 + if (strcmp(i.key(), "style:list-style-name") == 0) + propList.insert("style:list-style-name", i()->getStr()); +#endif + if (strcmp(i.key(), "fo:margin-left") == 0) + propList.insert("fo:margin-left", i()->getStr()); + if (strcmp(i.key(), "fo:margin-right") == 0) + propList.insert("fo:margin-right", i()->getStr()); + if (strcmp(i.key(), "fo:text-indent") == 0) + propList.insert("fo:text-indent", i()->getStr()); + if (strcmp(i.key(), "fo:margin-top") == 0) + propList.insert("fo:margin-top", i()->getStr()); + if (strcmp(i.key(), "fo:margin-bottom") == 0) + { + if (i()->getDouble() > 0.0) + propList.insert("fo:margin-bottom", i()->getStr()); + else + propList.insert("fo:margin-bottom", 0.0); + } + if (strcmp(i.key(), "fo:line-height") == 0) + propList.insert("fo:line-height", i()->getStr()); + if (strcmp(i.key(), "fo:break-before") == 0) + propList.insert("fo:break-before", i()->getStr()); + if (strcmp(i.key(), "fo:text-align") == 0) + propList.insert("fo:text-align", i()->getStr()); + if (strcmp(i.key(), "fo:text-align-last") == 0) + propList.insert("fo:text-align-last", i()->getStr()); + if (strcmp(i.key(), "style:page-number") == 0) + propList.insert("style:page-number", i()->getStr()); + + } + + propList.insert("style:justify-single-word", "false"); + pHandler->startElement("style:paragraph-properties", propList); + + if (mxTabStops.count() > 0) + { + TagOpenElement tabListOpen("style:tab-stops"); + tabListOpen.write(pHandler); + WPXPropertyListVector::Iter k(mxTabStops); + for (k.rewind(); k.next();) + { + if (k()["style:position"] && k()["style:position"]->getDouble() < 0.0) + continue; + TagOpenElement tabStopOpen("style:tab-stop"); + + WPXPropertyList::Iter j(k()); + for (j.rewind(); j.next(); ) + { + tabStopOpen.addAttribute(j.key(), j()->getStr().cstr()); + } + tabStopOpen.write(pHandler); + pHandler->endElement("style:tab-stop"); + } + pHandler->endElement("style:tab-stops"); + } + + pHandler->endElement("style:paragraph-properties"); + pHandler->endElement("style:style"); +} + +SpanStyle::SpanStyle(const char *psName, const WPXPropertyList &xPropList) : + Style(psName), + mPropList(xPropList) +{ +} + +void SpanStyle::write(OdfDocumentHandler *pHandler) const +{ + WRITER_DEBUG_MSG(("Writing a span style..\n")); + WPXPropertyList styleOpenList; + styleOpenList.insert("style:name", getName()); + styleOpenList.insert("style:family", "text"); + pHandler->startElement("style:style", styleOpenList); + + WPXPropertyList propList(mPropList); + + if (mPropList["style:font-name"]) + { + propList.insert("style:font-name-asian", mPropList["style:font-name"]->getStr()); + propList.insert("style:font-name-complex", mPropList["style:font-name"]->getStr()); + } + + if (mPropList["fo:font-size"]) + { + if (mPropList["fo:font-size"]->getDouble() > 0.0) + { + propList.insert("style:font-size-asian", mPropList["fo:font-size"]->getStr()); + propList.insert("style:font-size-complex", mPropList["fo:font-size"]->getStr()); + } + else + propList.remove("fo:font-size"); + } + + if (mPropList["fo:font-weight"]) + { + propList.insert("style:font-weight-asian", mPropList["fo:font-weight"]->getStr()); + propList.insert("style:font-weight-complex", mPropList["fo:font-weight"]->getStr()); + } + + if (mPropList["fo:font-style"]) + { + propList.insert("style:font-style-asian", mPropList["fo:font-style"]->getStr()); + propList.insert("style:font-style-complex", mPropList["fo:font-style"]->getStr()); + } + + pHandler->startElement("style:text-properties", propList); + + pHandler->endElement("style:text-properties"); + pHandler->endElement("style:style"); +} diff --git a/writerperfect/source/filter/TextRunStyle.hxx b/writerperfect/source/filter/TextRunStyle.hxx new file mode 100644 index 000000000000..b9b5763805b3 --- /dev/null +++ b/writerperfect/source/filter/TextRunStyle.hxx @@ -0,0 +1,63 @@ +/* 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 (wrlach@gmail.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 _TEXTRUNSTYLE_H +#define _TEXTRUNSTYLE_H +#include <libwpd/libwpd.h> + +#include "Style.hxx" + +class TagOpenElement; +class DocumentElement; +class OdfDocumentHandler; + +class ParagraphStyle +{ +public: + ParagraphStyle(WPXPropertyList *propList, const WPXPropertyListVector &tabStops, const WPXString &sName); + virtual ~ParagraphStyle(); + virtual void write(OdfDocumentHandler *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(OdfDocumentHandler *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..8b61b65ced43 --- /dev/null +++ b/writerperfect/source/filter/WriterProperties.hxx @@ -0,0 +1,35 @@ +/* WriterProperties: A grab bag of writer-specific properties which we use + * define here for later use. + * + * Copyright (C) 2002-2003 William Lachance (wrlach@gmail.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 + * + */ + +/* "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.0 +#define IMP_DEFAULT_FONT_PITCH "variable" +#endif diff --git a/writerperfect/source/stream/WPXSvStream.cxx b/writerperfect/source/stream/WPXSvStream.cxx new file mode 100644 index 000000000000..594944e63cf5 --- /dev/null +++ b/writerperfect/source/stream/WPXSvStream.cxx @@ -0,0 +1,172 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#include "WPXSvStream.h" +#include "filter/FilterInternal.hxx" +#include <tools/stream.hxx> +#include <unotools/streamwrap.hxx> +#include <unotools/ucbstreamhelper.hxx> +#include <limits> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::io; + +WPXSvInputStream::WPXSvInputStream( Reference< XInputStream > xStream ) : + WPXInputStream(), + mxChildStorage(), + mxChildStream(), + mxStream(xStream), + mxSeekable(xStream, UNO_QUERY), + maData(0) +{ + if (!xStream.is() || !mxStream.is()) + mnLength = 0; + else + { + if (!mxSeekable.is()) + mnLength = 0; + else + { + try + { + mnLength = mxSeekable->getLength(); + } + catch ( ... ) + { + WRITER_DEBUG_MSG(("mnLength = mxSeekable->getLength() threw exception\n")); + mnLength = 0; + } + } + } +} + +WPXSvInputStream::~WPXSvInputStream() +{ +} + +const unsigned char * WPXSvInputStream::read(unsigned long numBytes, unsigned long &numBytesRead) +{ + numBytesRead = 0; + + if (numBytes == 0 || atEOS()) + return 0; + + numBytesRead = mxStream->readSomeBytes (maData, numBytes); + if (numBytesRead == 0) + return 0; + + return (const unsigned char *)maData.getConstArray(); +} + +long WPXSvInputStream::tell() +{ + if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is()) + return -1L; + else + { + sal_Int64 tmpPosition = mxSeekable->getPosition(); + if ((tmpPosition < 0) || (tmpPosition > (std::numeric_limits<long>::max)())) + return -1L; + return (long)tmpPosition; + } +} + +int WPXSvInputStream::seek(long offset, WPX_SEEK_TYPE seekType) +{ + if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is()) + return -1; + + sal_Int64 tmpPosition = mxSeekable->getPosition(); + if ((tmpPosition < 0) || (tmpPosition > (std::numeric_limits<long>::max)())) + return -1; + + sal_Int64 tmpOffset = offset; + if (seekType == WPX_SEEK_CUR) + tmpOffset += tmpPosition; + + int retVal = 0; + if (tmpOffset < 0) + { + tmpOffset = 0; + retVal = -1; + } + if (offset > mnLength) + { + tmpOffset = mnLength; + retVal = -1; + } + + try + { + mxSeekable->seek(tmpOffset); + return retVal; + } + catch (...) + { + WRITER_DEBUG_MSG(("mxSeekable->seek(offset) threw exception\n")); + return -1; + } +} + +bool WPXSvInputStream::atEOS() +{ + if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is()) + return true; + return (mxSeekable->getPosition() >= mnLength); +} + +bool WPXSvInputStream::isOLEStream() +{ + if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is()) + return false; + + sal_Int64 tmpPosition = mxSeekable->getPosition(); + mxSeekable->seek(0); + + SvStream *pStream = utl::UcbStreamHelper::CreateStream( mxStream ); + bool bAns = pStream && SotStorage::IsOLEStorage( pStream ); + if (pStream) + delete pStream; + + mxSeekable->seek(tmpPosition); + + return bAns; +} + +WPXInputStream * WPXSvInputStream::getDocumentOLEStream(const char * name) +{ + if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is()) + return 0; + + sal_Int64 tmpPosition = mxSeekable->getPosition(); + mxSeekable->seek(0); + + SvStream *pStream = utl::UcbStreamHelper::CreateStream( mxStream ); + + if (!pStream || !SotStorage::IsOLEStorage( pStream )) + { + mxSeekable->seek(tmpPosition); + return 0; + } + + mxChildStorage = new SotStorage( pStream, sal_True ); + + mxChildStream = mxChildStorage->OpenSotStream( + rtl::OUString::createFromAscii( name ), + STREAM_STD_READ ); + + mxSeekable->seek(tmpPosition); + + if ( !mxChildStream.Is() || mxChildStream->GetError() ) + { + mxSeekable->seek(tmpPosition); + return 0; + } + + Reference < XInputStream > xContents(new utl::OSeekableInputStreamWrapper( mxChildStream )); + mxSeekable->seek(tmpPosition); + if (xContents.is()) + return new WPXSvInputStream( xContents ); + else + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/stream/WPXSvStream.h b/writerperfect/source/stream/WPXSvStream.h new file mode 100644 index 000000000000..37d905adcc41 --- /dev/null +++ b/writerperfect/source/stream/WPXSvStream.h @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +#ifndef WPXSVSTREAM_H +#define WPXSVSTREAM_H + +#include <sot/storage.hxx> +#include <com/sun/star/io/XInputStream.hpp> + +#ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_H_ +#include <com/sun/star/io/XSeekable.hpp> +#endif + + +#if defined _MSC_VER +#pragma warning( push, 1 ) +#endif +#include <libwpd-stream/WPXStream.h> +#if defined _MSC_VER +#pragma warning( pop ) +#endif + +class WPXSvInputStream : public WPXInputStream +{ +public: + WPXSvInputStream( ::com::sun::star::uno::Reference< + ::com::sun::star::io::XInputStream > xStream ); + virtual ~WPXSvInputStream(); + + virtual bool isOLEStream(); + virtual WPXInputStream * getDocumentOLEStream(const char *name); + + virtual const unsigned char *read(unsigned long numBytes, unsigned long &numBytesRead); + virtual int seek(long offset, WPX_SEEK_TYPE seekType); + virtual long tell(); + virtual bool atEOS(); + +private: + SotStorageRef mxChildStorage; + SotStorageStreamRef mxChildStream; + ::com::sun::star::uno::Reference< + ::com::sun::star::io::XInputStream > mxStream; + ::com::sun::star::uno::Reference< + ::com::sun::star::io::XSeekable > mxSeekable; + ::com::sun::star::uno::Sequence< sal_Int8 > maData; + sal_Int64 mnLength; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/vsdimp/VisioImportFilter.cxx b/writerperfect/source/vsdimp/VisioImportFilter.cxx new file mode 100644 index 000000000000..cfc507d89dff --- /dev/null +++ b/writerperfect/source/vsdimp/VisioImportFilter.cxx @@ -0,0 +1,280 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* VisioImportFilter: Sets up the filter, and calls OdgExporter + * to do the actual filtering + * + * Copyright (C) 2000 by Sun Microsystems, Inc. + * Copyright (C) 2002-2004 William Lachance (wlach@interlog.com) + * Copyright (C) 2004 Net Integration Technologies (http://www.net-itech.com) + * Copyright (C) 2004-2006 Fridrich Strba <fridrich.strba@bluewin.ch> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Contributor(s): Martin Gallwey (gallwey@sun.com) + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#include <osl/diagnose.h> +#include <rtl/tencinfo.h> + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/xml/sax/XAttributeList.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/uno/Reference.h> + +#include <xmloff/attrlist.hxx> + +#include <libvisio/libvisio.h> +#include "filter/DocumentHandler.hxx" +#include "filter/OdgGenerator.hxx" +#include "VisioImportFilter.hxx" +#include "stream/WPXSvStream.h" + +#include <iostream> + +using namespace ::com::sun::star::uno; +using com::sun::star::uno::Reference; +using com::sun::star::io::XInputStream; +using com::sun::star::io::XSeekable; +using com::sun::star::uno::Sequence; +using namespace ::rtl; +using rtl::OString; +using rtl::OUString; +using com::sun::star::uno::Sequence; +using com::sun::star::uno::Reference; +using com::sun::star::uno::Any; +using com::sun::star::uno::UNO_QUERY; +using com::sun::star::uno::XInterface; +using com::sun::star::uno::Exception; +using com::sun::star::uno::RuntimeException; +using com::sun::star::lang::XMultiServiceFactory; +using com::sun::star::beans::PropertyValue; +using com::sun::star::document::XFilter; +using com::sun::star::document::XExtendedFilterDetection; + +using com::sun::star::io::XInputStream; +using com::sun::star::document::XImporter; +using com::sun::star::xml::sax::InputSource; +using com::sun::star::xml::sax::XAttributeList; +using com::sun::star::xml::sax::XDocumentHandler; +using com::sun::star::xml::sax::XParser; + + +sal_Bool SAL_CALL VisioImportFilter::filter( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "VisioImportFilter::filter" << std::endl; +#endif + sal_Int32 nLength = aDescriptor.getLength(); + const PropertyValue * pValue = aDescriptor.getConstArray(); + OUString sURL; + Reference < XInputStream > xInputStream; + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "InputStream" ) ) ) + pValue[i].Value >>= xInputStream; + else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "URL" ) ) ) + pValue[i].Value >>= sURL; + } + if ( !xInputStream.is() ) + { + OSL_ASSERT( 0 ); + return sal_False; + } + OString sFileName; + sFileName = OUStringToOString(sURL, RTL_TEXTENCODING_INFO_ASCII); + + // An XML import service: what we push sax messages to.. + OUString sXMLImportService ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Draw.XMLOasisImporter" ) ); + Reference < XDocumentHandler > xInternalHandler( mxMSF->createInstance( sXMLImportService ), UNO_QUERY ); + + // The XImporter sets up an empty target document for XDocumentHandler to write to.. + Reference < XImporter > xImporter(xInternalHandler, UNO_QUERY); + xImporter->setTargetDocument( mxDoc ); + + // OO Graphics Handler: abstract class to handle document SAX messages, concrete implementation here + // writes to in-memory target doc + DocumentHandler xHandler(xInternalHandler); + + WPXSvInputStream input( xInputStream ); + + OdgGenerator exporter(&xHandler, ODF_FLAT_XML); + bool tmpParseResult = libvisio::VisioDocument::parse(&input, &exporter); + return tmpParseResult; +} + +void SAL_CALL VisioImportFilter::cancel( ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "VisioImportFilter::cancel" << std::endl; +#endif +} + +// XImporter +void SAL_CALL VisioImportFilter::setTargetDocument( const Reference< ::com::sun::star::lang::XComponent >& xDoc ) + throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException) +{ +#ifdef DEBUG + std::cerr << "VisioImportFilter::setTargetDocument" << std::endl; +#endif + meType = FILTER_IMPORT; + mxDoc = xDoc; +} + +// XExtendedFilterDetection +OUString SAL_CALL VisioImportFilter::detect( com::sun::star::uno::Sequence< PropertyValue >& Descriptor ) + throw( com::sun::star::uno::RuntimeException ) +{ +#ifdef DEBUG + std::cerr << "VisioImportFilter::detect" << std::endl; +#endif + OUString sTypeName; + sal_Int32 nLength = Descriptor.getLength(); + sal_Int32 location = nLength; + const PropertyValue * pValue = Descriptor.getConstArray(); + Reference < XInputStream > xInputStream; + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "TypeName" ) ) ) + location=i; + else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "InputStream" ) ) ) + pValue[i].Value >>= xInputStream; + } + + WPXSvInputStream input( xInputStream ); + + if (libvisio::VisioDocument::isSupported(&input)) + sTypeName = OUString( RTL_CONSTASCII_USTRINGPARAM ( "draw_Visio_Document" ) ); + + if (sTypeName.getLength()) + { + if ( location == Descriptor.getLength() ) + { + Descriptor.realloc(nLength+1); + Descriptor[location].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TypeName")); + } + + Descriptor[location].Value <<=sTypeName; + } + return sTypeName; +} + + +// XInitialization +void SAL_CALL VisioImportFilter::initialize( const Sequence< Any >& aArguments ) + throw (Exception, RuntimeException) +{ +#ifdef DEBUG + std::cerr << "VisioImportFilter::initialize" << std::endl; +#endif + Sequence < PropertyValue > aAnySeq; + sal_Int32 nLength = aArguments.getLength(); + if ( nLength && ( aArguments[0] >>= aAnySeq ) ) + { + const PropertyValue * pValue = aAnySeq.getConstArray(); + nLength = aAnySeq.getLength(); + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "Type" ) ) ) + { + pValue[i].Value >>= msFilterName; + break; + } + } + } +} +OUString VisioImportFilter_getImplementationName () + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "VisioImportFilter_getImplementationName" << std::endl; +#endif + return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Draw.VisioImportFilter" ) ); +} + +#define SERVICE_NAME1 "com.sun.star.document.ImportFilter" +#define SERVICE_NAME2 "com.sun.star.document.ExtendedTypeDetection" +sal_Bool SAL_CALL VisioImportFilter_supportsService( const OUString& ServiceName ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "VisioImportFilter_supportsService" << std::endl; +#endif + return (ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME1 ) ) || + ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME2 ) ) ); +} +Sequence< OUString > SAL_CALL VisioImportFilter_getSupportedServiceNames( ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "VisioImportFilter_getSupportedServiceNames" << std::endl; +#endif + Sequence < OUString > aRet(2); + OUString* pArray = aRet.getArray(); + pArray[0] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME1 ) ); + pArray[1] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME2 ) ); + return aRet; +} +#undef SERVICE_NAME2 +#undef SERVICE_NAME1 + +Reference< XInterface > SAL_CALL VisioImportFilter_createInstance( const Reference< XMultiServiceFactory > & rSMgr) + throw( Exception ) +{ +#ifdef DEBUG + std::cerr << "VisioImportFilter_createInstance" << std::endl; +#endif + return (cppu::OWeakObject*) new VisioImportFilter( rSMgr ); +} + +// XServiceInfo +OUString SAL_CALL VisioImportFilter::getImplementationName( ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "VisioImportFilter::getImplementationName" << std::endl; +#endif + return VisioImportFilter_getImplementationName(); +} +sal_Bool SAL_CALL VisioImportFilter::supportsService( const OUString& rServiceName ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "VisioImportFilter::supportsService" << std::endl; +#endif + return VisioImportFilter_supportsService( rServiceName ); +} +Sequence< OUString > SAL_CALL VisioImportFilter::getSupportedServiceNames( ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "VisioImportFilter::getSupportedServiceNames" << std::endl; +#endif + return VisioImportFilter_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/vsdimp/VisioImportFilter.hxx b/writerperfect/source/vsdimp/VisioImportFilter.hxx new file mode 100644 index 000000000000..7bfa5e8bedf1 --- /dev/null +++ b/writerperfect/source/vsdimp/VisioImportFilter.hxx @@ -0,0 +1,117 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2000 by Sun Microsystems, Inc. + * Copyright (C) 2002-2004 William Lachance (wlach@interlog.com) + * Copyright (C) 2004 Net Integration Technologies (http://www.net-itech.com) + * Copyright (C) 2004 Fridrich Strba <fridrich.strba@bluewin.ch> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Contributor(s): Martin Gallwey (gallwey@sun.com) + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef _VISIOIMPORTFILTER_HXX +#define _VISIOIMPORTFILTER_HXX + +#include <com/sun/star/document/XFilter.hpp> +#include <com/sun/star/document/XImporter.hpp> +#include <com/sun/star/document/XExtendedFilterDetection.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <cppuhelper/implbase5.hxx> + +#include <stdio.h> + +enum FilterType +{ + FILTER_IMPORT, + FILTER_EXPORT +}; +/* This component will be instantiated for both import or export. Whether it calls + * setSourceDocument or setTargetDocument determines which Impl function the filter + * member calls */ +class VisioImportFilter : public cppu::WeakImplHelper5 +< + com::sun::star::document::XFilter, + com::sun::star::document::XImporter, + com::sun::star::document::XExtendedFilterDetection, + com::sun::star::lang::XInitialization, + com::sun::star::lang::XServiceInfo +> +{ +protected: + // oo.org declares + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMSF; + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > mxDoc; + ::rtl::OUString msFilterName; + ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XDocumentHandler > mxHandler; + + FilterType meType; + +public: + VisioImportFilter( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > &rxMSF) + : mxMSF( rxMSF ), meType((FilterType)0) {} + virtual ~VisioImportFilter() {} + + // 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 VisioImportFilter_getImplementationName() + throw ( ::com::sun::star::uno::RuntimeException ); + +sal_Bool SAL_CALL VisioImportFilter_supportsService( const ::rtl::OUString& ServiceName ) + throw ( ::com::sun::star::uno::RuntimeException ); + +::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL VisioImportFilter_getSupportedServiceNames( ) + throw ( ::com::sun::star::uno::RuntimeException ); + +::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > +SAL_CALL VisioImportFilter_createInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & rSMgr) + throw ( ::com::sun::star::uno::Exception ); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/vsdimp/visioimport_genericfilter.cxx b/writerperfect/source/vsdimp/visioimport_genericfilter.cxx new file mode 100644 index 000000000000..ddc3f25fcb09 --- /dev/null +++ b/writerperfect/source/vsdimp/visioimport_genericfilter.cxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* genericfilter: mostly generic code for registering the filter + * + * Portions of this code Copyright 2000 by Sun Microsystems, Inc. + * Rest is Copyright (C) 2002 William Lachance (wlach@interlog.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#include <stdio.h> + +#include <osl/mutex.hxx> +#include <osl/thread.h> +#include <cppuhelper/factory.hxx> + +#include <com/sun/star/lang/XSingleServiceFactory.hpp> + +#include "VisioImportFilter.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" +{ +SAL_DLLPUBLIC_EXPORT 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(VisioImportFilter_getImplementationName()) ) + { + Reference< XSingleServiceFactory > xFactory( createSingleFactory( + reinterpret_cast< XMultiServiceFactory * >( pServiceManager ), + OUString::createFromAscii( pImplName ), + VisioImportFilter_createInstance, VisioImportFilter_getSupportedServiceNames() ) ); + + if (xFactory.is()) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } + + return pRet; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpdimp/WordPerfectImportFilter.cxx b/writerperfect/source/wpdimp/WordPerfectImportFilter.cxx new file mode 100644 index 000000000000..4c82715b17f2 --- /dev/null +++ b/writerperfect/source/wpdimp/WordPerfectImportFilter.cxx @@ -0,0 +1,446 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2000 by Sun Microsystems, Inc. + * Copyright (C) 2002-2004 William Lachance (wlach@interlog.com) + * Copyright (C) 2004 Net Integration Technologies (http://www.net-itech.com) + * Copyright (C) 2004 Fridrich Strba <fridrich.strba@bluewin.ch> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Contributor(s): Martin Gallwey (gallwey@sun.com) + * + */ +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#include <osl/diagnose.h> +#include <rtl/tencinfo.h> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/xml/sax/XAttributeList.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> + +#include <xmloff/attrlist.hxx> +#include <ucbhelper/content.hxx> +#include <sfx2/passwd.hxx> + +#include "filter/FilterInternal.hxx" +#include "filter/DocumentHandler.hxx" +#include "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 "filter/OdtGenerator.hxx" +#include "filter/OdgGenerator.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); + + +static bool handleEmbeddedWPG(const WPXBinaryData &data, OdfDocumentHandler *pHandler, const OdfStreamType streamType) +{ + OdgGenerator exporter(pHandler, streamType); + + libwpg::WPGFileFormat fileFormat = libwpg::WPG_AUTODETECT; + + if (!libwpg::WPGraphics::isSupported(const_cast<WPXInputStream *>(data.getDataStream()))) + fileFormat = libwpg::WPG_WPG1; + + return libwpg::WPGraphics::parse(const_cast<WPXInputStream *>(data.getDataStream()), &exporter, fileFormat); +} + +sal_Bool SAL_CALL WordPerfectImportFilter::importImpl( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) + throw (RuntimeException) +{ + WRITER_DEBUG_MSG(("WordPerfectImportFilter::importImpl: Got here!\n")); + + sal_Int32 nLength = aDescriptor.getLength(); + const PropertyValue * pValue = aDescriptor.getConstArray(); + OUString sURL; + uno::Reference < XInputStream > xInputStream; + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "InputStream" ) ) ) + pValue[i].Value >>= xInputStream; + else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "URL" ) ) ) + pValue[i].Value >>= sURL; + } + if ( !xInputStream.is() ) + { + OSL_ASSERT( 0 ); + return sal_False; + } + + WPXSvInputStream input( xInputStream ); + + OString aUtf8Passwd; + + WPDConfidence confidence = WPDocument::isFileFormatSupported(&input); + + if (WPD_CONFIDENCE_SUPPORTED_ENCRYPTION == confidence) + { + int unsuccessfulAttempts = 0; + while (true ) + { + SfxPasswordDialog aPasswdDlg( 0 ); + aPasswdDlg.SetMinLen(0); + if(!aPasswdDlg.Execute()) + return sal_False; + String aPasswd = aPasswdDlg.GetPassword(); + OUString aUniPasswd(aPasswd.GetBuffer() /*, aPasswd.Len(), RTL_TEXTENCODING_UCS2 */); + aUtf8Passwd = OUStringToOString(aUniPasswd, RTL_TEXTENCODING_UTF8); + if (WPD_PASSWORD_MATCH_OK == WPDocument::verifyPassword(&input, aUtf8Passwd.getStr())) + break; + else + unsuccessfulAttempts++; + if (unsuccessfulAttempts == 3) // timeout after 3 password atempts + return sal_False; + } + } + + // An XML import service: what we push sax messages to.. + OUString sXMLImportService ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Writer.XMLOasisImporter" ) ); + uno::Reference < XDocumentHandler > xInternalHandler( mxMSF->createInstance( sXMLImportService ), UNO_QUERY ); + + // The XImporter sets up an empty target document for XDocumentHandler to write to.. + uno::Reference < XImporter > xImporter(xInternalHandler, UNO_QUERY); + xImporter->setTargetDocument(mxDoc); + + // OO Document Handler: abstract class to handle document SAX messages, concrete implementation here + // writes to in-memory target doc + DocumentHandler xHandler(xInternalHandler); + + OdtGenerator collector(&xHandler, ODF_FLAT_XML); + collector.registerEmbeddedObjectHandler("image/x-wpg", &handleEmbeddedWPG); + if (WPD_OK == WPDocument::parse(&input, &collector, aUtf8Passwd.getLength() ? aUtf8Passwd.getStr() : 0)) + return sal_True; + return sal_False; +} + +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; + sal_Int32 nLength = Descriptor.getLength(); + sal_Int32 location = nLength; + OUString sURL; + const PropertyValue * pValue = Descriptor.getConstArray(); + uno::Reference < XInputStream > xInputStream; + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "TypeName" ) ) ) + location=i; + else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "InputStream" ) ) ) + pValue[i].Value >>= xInputStream; + else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "URL" ) ) ) + pValue[i].Value >>= sURL; + } + + uno::Reference< com::sun::star::ucb::XCommandEnvironment > xEnv; + if (!xInputStream.is()) + { + try + { + ::ucbhelper::Content aContent(sURL, xEnv); + xInputStream = aContent.openStream(); + } + catch ( ... ) + { + return ::rtl::OUString(); + } + + if (!xInputStream.is()) + return ::rtl::OUString(); + } + + WPXSvInputStream input( xInputStream ); + + if (input.atEOS()) + return ::rtl::OUString(); + + confidence = WPDocument::isFileFormatSupported(&input); + + if (confidence == WPD_CONFIDENCE_EXCELLENT || confidence == WPD_CONFIDENCE_SUPPORTED_ENCRYPTION) + sTypeName = OUString( RTL_CONSTASCII_USTRINGPARAM ( "writer_WordPerfect_Document" ) ); + + if (sTypeName.getLength()) + { + if ( location == Descriptor.getLength() ) + { + Descriptor.realloc(nLength+1); + Descriptor[location].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TypeName")); + } + + Descriptor[location].Value <<=sTypeName; + } + + return sTypeName; +} + + +// XInitialization +void SAL_CALL WordPerfectImportFilter::initialize( const Sequence< Any >& aArguments ) + throw (Exception, RuntimeException) +{ + WRITER_DEBUG_MSG(("WordPerfectImportFilter::initialize: Got here!\n")); + Sequence < PropertyValue > aAnySeq; + sal_Int32 nLength = aArguments.getLength(); + if ( nLength && ( aArguments[0] >>= aAnySeq ) ) + { + const PropertyValue * pValue = aAnySeq.getConstArray(); + nLength = aAnySeq.getLength(); + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "Type" ) ) ) + { + pValue[i].Value >>= msFilterName; + break; + } + } + } +} +OUString WordPerfectImportFilter_getImplementationName () + throw (RuntimeException) +{ + return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Writer.WordPerfectImportFilter" ) ); +} + +#define SERVICE_NAME1 "com.sun.star.document.ImportFilter" +#define SERVICE_NAME2 "com.sun.star.document.ExtendedTypeDetection" +sal_Bool SAL_CALL WordPerfectImportFilter_supportsService( const OUString& ServiceName ) + throw (RuntimeException) +{ + return (ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME1 ) ) || + ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME2 ) ) ); +} +Sequence< OUString > SAL_CALL WordPerfectImportFilter_getSupportedServiceNames( ) + throw (RuntimeException) +{ + Sequence < OUString > aRet(2); + OUString* pArray = aRet.getArray(); + pArray[0] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME1 ) ); + pArray[1] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME2 ) ); + return aRet; +} +#undef SERVICE_NAME2 +#undef SERVICE_NAME1 + +uno::Reference< XInterface > SAL_CALL WordPerfectImportFilter_createInstance( const uno::Reference< XMultiServiceFactory > & rSMgr) + throw( Exception ) +{ + return (cppu::OWeakObject*) new WordPerfectImportFilter( rSMgr ); +} + +// XServiceInfo +OUString SAL_CALL WordPerfectImportFilter::getImplementationName( ) + throw (RuntimeException) +{ + return WordPerfectImportFilter_getImplementationName(); +} +sal_Bool SAL_CALL WordPerfectImportFilter::supportsService( const OUString& rServiceName ) + throw (RuntimeException) +{ + return WordPerfectImportFilter_supportsService( rServiceName ); +} +Sequence< OUString > SAL_CALL WordPerfectImportFilter::getSupportedServiceNames( ) + throw (RuntimeException) +{ + return WordPerfectImportFilter_getSupportedServiceNames(); +} + + +WordPerfectImportFilterDialog::WordPerfectImportFilterDialog(const ::com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory > &r ) : + mxMSF( r ) {} + +WordPerfectImportFilterDialog::~WordPerfectImportFilterDialog() +{ +} + +void SAL_CALL WordPerfectImportFilterDialog::setTitle( const ::rtl::OUString& ) + throw (::com::sun::star::uno::RuntimeException) +{ +} + +sal_Int16 SAL_CALL WordPerfectImportFilterDialog::execute() + throw (::com::sun::star::uno::RuntimeException) +{ + WPXSvInputStream input( mxInputStream ); + + OString aUtf8Passwd; + + WPDConfidence confidence = WPDocument::isFileFormatSupported(&input); + + if (WPD_CONFIDENCE_SUPPORTED_ENCRYPTION == confidence) + { + int unsuccessfulAttempts = 0; + while (true ) + { + SfxPasswordDialog aPasswdDlg(0); + aPasswdDlg.SetMinLen(0); + if(!aPasswdDlg.Execute()) + return com::sun::star::ui::dialogs::ExecutableDialogResults::CANCEL; + msPassword = ::rtl::OUString(aPasswdDlg.GetPassword().GetBuffer()); + aUtf8Passwd = OUStringToOString(msPassword, RTL_TEXTENCODING_UTF8); + if (WPD_PASSWORD_MATCH_OK == WPDocument::verifyPassword(&input, aUtf8Passwd.getStr())) + break; + else + unsuccessfulAttempts++; + if (unsuccessfulAttempts == 3) // timeout after 3 password atempts + return com::sun::star::ui::dialogs::ExecutableDialogResults::CANCEL; + } + } + return com::sun::star::ui::dialogs::ExecutableDialogResults::OK; +} + +uno::Sequence<beans::PropertyValue> SAL_CALL WordPerfectImportFilterDialog::getPropertyValues() throw(uno::RuntimeException) +{ + uno::Sequence<beans::PropertyValue> aRet(1); + beans::PropertyValue* pArray = aRet.getArray(); + + pArray[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Password") ); + pArray[0].Value <<= msPassword; + + return aRet; +} + +void SAL_CALL WordPerfectImportFilterDialog::setPropertyValues( const uno::Sequence<beans::PropertyValue>& aProps) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException) +{ + const beans::PropertyValue* pPropArray = aProps.getConstArray(); + long nPropCount = aProps.getLength(); + for (long i = 0; i < nPropCount; i++) + { + const beans::PropertyValue& rProp = pPropArray[i]; + ::rtl::OUString aPropName = rProp.Name; + + if ( aPropName == ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Password")) ) + rProp.Value >>= msPassword; + else if ( aPropName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "InputStream" ) ) ) + rProp.Value >>= mxInputStream; + } +} + + +// XServiceInfo +OUString SAL_CALL WordPerfectImportFilterDialog::getImplementationName( ) + throw (RuntimeException) +{ + return WordPerfectImportFilterDialog_getImplementationName(); +} + +sal_Bool SAL_CALL WordPerfectImportFilterDialog::supportsService( const OUString& rServiceName ) + throw (RuntimeException) +{ + return WordPerfectImportFilterDialog_supportsService( rServiceName ); +} + +Sequence< OUString > SAL_CALL WordPerfectImportFilterDialog::getSupportedServiceNames( ) + throw (RuntimeException) +{ + return WordPerfectImportFilterDialog_getSupportedServiceNames(); +} + +OUString WordPerfectImportFilterDialog_getImplementationName () + throw (RuntimeException) +{ + return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Writer.WordPerfectImportFilterDialog" ) ); +} + +#define SERVICE_NAME "com.sun.star.ui.dialogs.FilterOptionsDialog" +sal_Bool SAL_CALL WordPerfectImportFilterDialog_supportsService( const OUString& ServiceName ) + throw (RuntimeException) +{ + return ( ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME ) ) ); +} + +Sequence< OUString > SAL_CALL WordPerfectImportFilterDialog_getSupportedServiceNames( ) + throw (RuntimeException) +{ + Sequence < OUString > aRet(1); + OUString* pArray = aRet.getArray(); + pArray[0] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME ) ); + return aRet; +} +#undef SERVICE_NAME + +uno::Reference< XInterface > SAL_CALL WordPerfectImportFilterDialog_createInstance( const uno::Reference< XMultiServiceFactory > & rSMgr) + throw( Exception ) +{ + return (cppu::OWeakObject*) new WordPerfectImportFilterDialog( rSMgr ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpdimp/WordPerfectImportFilter.hxx b/writerperfect/source/wpdimp/WordPerfectImportFilter.hxx new file mode 100644 index 000000000000..9f73d8f231d1 --- /dev/null +++ b/writerperfect/source/wpdimp/WordPerfectImportFilter.hxx @@ -0,0 +1,178 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2000 by Sun Microsystems, Inc. + * Copyright (C) 2002-2004 William Lachance (wlach@interlog.com) + * Copyright (C) 2004 Net Integration Technologies (http://www.net-itech.com) + * Copyright (C) 2004 Fridrich Strba <fridrich.strba@bluewin.ch> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Contributor(s): Martin Gallwey (gallwey@sun.com) + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef _WORDPERFECTIMPORTFILTER_HXX +#define _WORDPERFECTIMPORTFILTER_HXX + +#include <com/sun/star/document/XFilter.hpp> +#include <com/sun/star/document/XImporter.hpp> +#include <com/sun/star/document/XExtendedFilterDetection.hpp> +#include <com/sun/star/beans/XPropertyAccess.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <cppuhelper/implbase3.hxx> +#include <cppuhelper/implbase5.hxx> + +enum FilterType +{ + FILTER_IMPORT, + FILTER_EXPORT +}; +/* This component will be instantiated for both import or export. Whether it calls + * setSourceDocument or setTargetDocument determines which Impl function the filter + * member calls */ +class WordPerfectImportFilter : public cppu::WeakImplHelper5 +< + com::sun::star::document::XFilter, + com::sun::star::document::XImporter, + com::sun::star::document::XExtendedFilterDetection, + com::sun::star::lang::XInitialization, + com::sun::star::lang::XServiceInfo +> +{ +protected: + // oo.org declares + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMSF; + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > mxDoc; + ::rtl::OUString msFilterName; + ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XDocumentHandler > mxHandler; + + FilterType meType; + + sal_Bool SAL_CALL importImpl( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) + throw (::com::sun::star::uno::RuntimeException); + +public: + WordPerfectImportFilter( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > &rxMSF) + : mxMSF( rxMSF ), meType((FilterType)0) {} + virtual ~WordPerfectImportFilter() {} + + // XFilter + virtual sal_Bool SAL_CALL filter( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL cancel( ) + throw (::com::sun::star::uno::RuntimeException); + + // XImporter + virtual void SAL_CALL setTargetDocument( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& xDoc ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + //XExtendedFilterDetection + virtual ::rtl::OUString SAL_CALL detect( com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& Descriptor ) + throw( com::sun::star::uno::RuntimeException ); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw (::com::sun::star::uno::RuntimeException); + +}; + +::rtl::OUString WordPerfectImportFilter_getImplementationName() + throw ( ::com::sun::star::uno::RuntimeException ); + +sal_Bool SAL_CALL WordPerfectImportFilter_supportsService( const ::rtl::OUString& ServiceName ) + throw ( ::com::sun::star::uno::RuntimeException ); + +::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL WordPerfectImportFilter_getSupportedServiceNames( ) + throw ( ::com::sun::star::uno::RuntimeException ); + +::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > +SAL_CALL WordPerfectImportFilter_createInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & rSMgr) + throw ( ::com::sun::star::uno::Exception ); + + +class WordPerfectImportFilterDialog : public cppu::WeakImplHelper3 < + com::sun::star::ui::dialogs::XExecutableDialog, + com::sun::star::lang::XServiceInfo, + com::sun::star::beans::XPropertyAccess +> +{ + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMSF; + ::rtl::OUString msPassword; + ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > mxInputStream; + + ~WordPerfectImportFilterDialog(); + + // XExecutableDialog + virtual void SAL_CALL setTitle( const ::rtl::OUString& aTitle ) + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL execute() + throw (::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw (::com::sun::star::uno::RuntimeException); + + // XPropertyAccess + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > + SAL_CALL getPropertyValues() throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setPropertyValues( const ::com::sun::star::uno::Sequence< + ::com::sun::star::beans::PropertyValue >& aProps ) + throw (::com::sun::star::beans::UnknownPropertyException, + ::com::sun::star::beans::PropertyVetoException, + ::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException); + +public: + WordPerfectImportFilterDialog(const ::com::sun::star::uno::Reference<com::sun::star::lang::XMultiServiceFactory > &r ); + +}; + +::rtl::OUString WordPerfectImportFilterDialog_getImplementationName() + throw ( ::com::sun::star::uno::RuntimeException ); + +sal_Bool SAL_CALL WordPerfectImportFilterDialog_supportsService( const ::rtl::OUString& ServiceName ) + throw ( ::com::sun::star::uno::RuntimeException ); + +::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL WordPerfectImportFilterDialog_getSupportedServiceNames( ) + throw ( ::com::sun::star::uno::RuntimeException ); + +::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > +SAL_CALL WordPerfectImportFilterDialog_createInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & rSMgr) + throw ( ::com::sun::star::uno::Exception ); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpdimp/wpft_genericfilter.cxx b/writerperfect/source/wpdimp/wpft_genericfilter.cxx new file mode 100644 index 000000000000..240707e796c8 --- /dev/null +++ b/writerperfect/source/wpdimp/wpft_genericfilter.cxx @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* genericfilter: mostly generic code for registering the filter + * + * Portions of this code Copyright 2000 by Sun Microsystems, Inc. + * Rest is Copyright (C) 2002 William Lachance (wlach@interlog.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#include <stdio.h> + +#include <osl/mutex.hxx> +#include <osl/thread.h> +#include <cppuhelper/factory.hxx> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> + +#include "WordPerfectImportFilter.hxx" + +using namespace ::rtl; +using namespace ::cppu; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; + +extern "C" +{ +SAL_DLLPUBLIC_EXPORT 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; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpgimp/WPGImportFilter.cxx b/writerperfect/source/wpgimp/WPGImportFilter.cxx new file mode 100644 index 000000000000..9674e79e136e --- /dev/null +++ b/writerperfect/source/wpgimp/WPGImportFilter.cxx @@ -0,0 +1,279 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* WPGImportFilter: Sets up the filter, and calls OdgExporter + * to do the actual filtering + * + * Copyright (C) 2000 by Sun Microsystems, Inc. + * Copyright (C) 2002-2004 William Lachance (wlach@interlog.com) + * Copyright (C) 2004 Net Integration Technologies (http://www.net-itech.com) + * Copyright (C) 2004-2006 Fridrich Strba <fridrich.strba@bluewin.ch> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Contributor(s): Martin Gallwey (gallwey@sun.com) + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#include <osl/diagnose.h> +#include <rtl/tencinfo.h> + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/xml/sax/XAttributeList.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XSeekable.hpp> +#include <com/sun/star/uno/Reference.h> + +#include <xmloff/attrlist.hxx> + +#include "filter/DocumentHandler.hxx" +#include "filter/OdgGenerator.hxx" +#include "WPGImportFilter.hxx" +#include "stream/WPXSvStream.h" + +#include <iostream> + +using namespace ::com::sun::star::uno; +using com::sun::star::uno::Reference; +using com::sun::star::io::XInputStream; +using com::sun::star::io::XSeekable; +using com::sun::star::uno::Sequence; +using namespace ::rtl; +using rtl::OString; +using rtl::OUString; +using com::sun::star::uno::Sequence; +using com::sun::star::uno::Reference; +using com::sun::star::uno::Any; +using com::sun::star::uno::UNO_QUERY; +using com::sun::star::uno::XInterface; +using com::sun::star::uno::Exception; +using com::sun::star::uno::RuntimeException; +using com::sun::star::lang::XMultiServiceFactory; +using com::sun::star::beans::PropertyValue; +using com::sun::star::document::XFilter; +using com::sun::star::document::XExtendedFilterDetection; + +using com::sun::star::io::XInputStream; +using com::sun::star::document::XImporter; +using com::sun::star::xml::sax::InputSource; +using com::sun::star::xml::sax::XAttributeList; +using com::sun::star::xml::sax::XDocumentHandler; +using com::sun::star::xml::sax::XParser; + + +sal_Bool SAL_CALL WPGImportFilter::filter( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter::filter" << std::endl; +#endif + sal_Int32 nLength = aDescriptor.getLength(); + const PropertyValue * pValue = aDescriptor.getConstArray(); + OUString sURL; + Reference < XInputStream > xInputStream; + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "InputStream" ) ) ) + pValue[i].Value >>= xInputStream; + else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "URL" ) ) ) + pValue[i].Value >>= sURL; + } + if ( !xInputStream.is() ) + { + OSL_ASSERT( 0 ); + return sal_False; + } + OString sFileName; + sFileName = OUStringToOString(sURL, RTL_TEXTENCODING_INFO_ASCII); + + // An XML import service: what we push sax messages to.. + OUString sXMLImportService ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Draw.XMLOasisImporter" ) ); + Reference < XDocumentHandler > xInternalHandler( mxMSF->createInstance( sXMLImportService ), UNO_QUERY ); + + // The XImporter sets up an empty target document for XDocumentHandler to write to.. + Reference < XImporter > xImporter(xInternalHandler, UNO_QUERY); + xImporter->setTargetDocument( mxDoc ); + + // OO Graphics Handler: abstract class to handle document SAX messages, concrete implementation here + // writes to in-memory target doc + DocumentHandler xHandler(xInternalHandler); + + WPXSvInputStream input( xInputStream ); + + OdgGenerator exporter(&xHandler, ODF_FLAT_XML); + bool tmpParseResult = libwpg::WPGraphics::parse(&input, &exporter); + return tmpParseResult; +} + +void SAL_CALL WPGImportFilter::cancel( ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter::cancel" << std::endl; +#endif +} + +// XImporter +void SAL_CALL WPGImportFilter::setTargetDocument( const Reference< ::com::sun::star::lang::XComponent >& xDoc ) + throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter::setTargetDocument" << std::endl; +#endif + meType = FILTER_IMPORT; + mxDoc = xDoc; +} + +// XExtendedFilterDetection +OUString SAL_CALL WPGImportFilter::detect( com::sun::star::uno::Sequence< PropertyValue >& Descriptor ) + throw( com::sun::star::uno::RuntimeException ) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter::detect" << std::endl; +#endif + OUString sTypeName; + sal_Int32 nLength = Descriptor.getLength(); + sal_Int32 location = nLength; + const PropertyValue * pValue = Descriptor.getConstArray(); + Reference < XInputStream > xInputStream; + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "TypeName" ) ) ) + location=i; + else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "InputStream" ) ) ) + pValue[i].Value >>= xInputStream; + } + + WPXSvInputStream input( xInputStream ); + + if (libwpg::WPGraphics::isSupported(&input)) + sTypeName = OUString( RTL_CONSTASCII_USTRINGPARAM ( "draw_WordPerfect_Graphics" ) ); + + if (sTypeName.getLength()) + { + if ( location == Descriptor.getLength() ) + { + Descriptor.realloc(nLength+1); + Descriptor[location].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TypeName")); + } + + Descriptor[location].Value <<=sTypeName; + } + return sTypeName; +} + + +// XInitialization +void SAL_CALL WPGImportFilter::initialize( const Sequence< Any >& aArguments ) + throw (Exception, RuntimeException) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter::initialize" << std::endl; +#endif + Sequence < PropertyValue > aAnySeq; + sal_Int32 nLength = aArguments.getLength(); + if ( nLength && ( aArguments[0] >>= aAnySeq ) ) + { + const PropertyValue * pValue = aAnySeq.getConstArray(); + nLength = aAnySeq.getLength(); + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "Type" ) ) ) + { + pValue[i].Value >>= msFilterName; + break; + } + } + } +} +OUString WPGImportFilter_getImplementationName () + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter_getImplementationName" << std::endl; +#endif + return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Draw.WPGImportFilter" ) ); +} + +#define SERVICE_NAME1 "com.sun.star.document.ImportFilter" +#define SERVICE_NAME2 "com.sun.star.document.ExtendedTypeDetection" +sal_Bool SAL_CALL WPGImportFilter_supportsService( const OUString& ServiceName ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter_supportsService" << std::endl; +#endif + return (ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME1 ) ) || + ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME2 ) ) ); +} +Sequence< OUString > SAL_CALL WPGImportFilter_getSupportedServiceNames( ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter_getSupportedServiceNames" << std::endl; +#endif + Sequence < OUString > aRet(2); + OUString* pArray = aRet.getArray(); + pArray[0] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME1 ) ); + pArray[1] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME2 ) ); + return aRet; +} +#undef SERVICE_NAME2 +#undef SERVICE_NAME1 + +Reference< XInterface > SAL_CALL WPGImportFilter_createInstance( const Reference< XMultiServiceFactory > & rSMgr) + throw( Exception ) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter_createInstance" << std::endl; +#endif + return (cppu::OWeakObject*) new WPGImportFilter( rSMgr ); +} + +// XServiceInfo +OUString SAL_CALL WPGImportFilter::getImplementationName( ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter::getImplementationName" << std::endl; +#endif + return WPGImportFilter_getImplementationName(); +} +sal_Bool SAL_CALL WPGImportFilter::supportsService( const OUString& rServiceName ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter::supportsService" << std::endl; +#endif + return WPGImportFilter_supportsService( rServiceName ); +} +Sequence< OUString > SAL_CALL WPGImportFilter::getSupportedServiceNames( ) + throw (RuntimeException) +{ +#ifdef DEBUG + std::cerr << "WPGImportFilter::getSupportedServiceNames" << std::endl; +#endif + return WPGImportFilter_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpgimp/WPGImportFilter.hxx b/writerperfect/source/wpgimp/WPGImportFilter.hxx new file mode 100644 index 000000000000..2b5385103fb4 --- /dev/null +++ b/writerperfect/source/wpgimp/WPGImportFilter.hxx @@ -0,0 +1,117 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2000 by Sun Microsystems, Inc. + * Copyright (C) 2002-2004 William Lachance (wlach@interlog.com) + * Copyright (C) 2004 Net Integration Technologies (http://www.net-itech.com) + * Copyright (C) 2004 Fridrich Strba <fridrich.strba@bluewin.ch> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Contributor(s): Martin Gallwey (gallwey@sun.com) + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef _WPGIMPORTFILTER_HXX +#define _WPGIMPORTFILTER_HXX + +#include <com/sun/star/document/XFilter.hpp> +#include <com/sun/star/document/XImporter.hpp> +#include <com/sun/star/document/XExtendedFilterDetection.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <cppuhelper/implbase5.hxx> + +#include <stdio.h> + +enum FilterType +{ + FILTER_IMPORT, + FILTER_EXPORT +}; +/* This component will be instantiated for both import or export. Whether it calls + * setSourceDocument or setTargetDocument determines which Impl function the filter + * member calls */ +class WPGImportFilter : public cppu::WeakImplHelper5 +< + com::sun::star::document::XFilter, + com::sun::star::document::XImporter, + com::sun::star::document::XExtendedFilterDetection, + com::sun::star::lang::XInitialization, + com::sun::star::lang::XServiceInfo +> +{ +protected: + // oo.org declares + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMSF; + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > mxDoc; + ::rtl::OUString msFilterName; + ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XDocumentHandler > mxHandler; + + FilterType meType; + +public: + WPGImportFilter( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > &rxMSF) + : mxMSF( rxMSF ), meType((FilterType)0) {} + virtual ~WPGImportFilter() {} + + // XFilter + virtual sal_Bool SAL_CALL filter( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL cancel( ) + throw (::com::sun::star::uno::RuntimeException); + + // XImporter + virtual void SAL_CALL setTargetDocument( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& xDoc ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + //XExtendedFilterDetection + virtual ::rtl::OUString SAL_CALL detect( com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& Descriptor ) + throw( com::sun::star::uno::RuntimeException ); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw (::com::sun::star::uno::RuntimeException); + +}; + +::rtl::OUString WPGImportFilter_getImplementationName() + throw ( ::com::sun::star::uno::RuntimeException ); + +sal_Bool SAL_CALL WPGImportFilter_supportsService( const ::rtl::OUString& ServiceName ) + throw ( ::com::sun::star::uno::RuntimeException ); + +::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL WPGImportFilter_getSupportedServiceNames( ) + throw ( ::com::sun::star::uno::RuntimeException ); + +::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > +SAL_CALL WPGImportFilter_createInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & rSMgr) + throw ( ::com::sun::star::uno::Exception ); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpgimp/wpgimport_genericfilter.cxx b/writerperfect/source/wpgimp/wpgimport_genericfilter.cxx new file mode 100644 index 000000000000..4a7f97a0dd1a --- /dev/null +++ b/writerperfect/source/wpgimp/wpgimport_genericfilter.cxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* genericfilter: mostly generic code for registering the filter + * + * Portions of this code Copyright 2000 by Sun Microsystems, Inc. + * Rest is Copyright (C) 2002 William Lachance (wlach@interlog.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#include <stdio.h> + +#include <osl/mutex.hxx> +#include <osl/thread.h> +#include <cppuhelper/factory.hxx> + +#include <com/sun/star/lang/XSingleServiceFactory.hpp> + +#include "WPGImportFilter.hxx" + +using namespace ::rtl; +using namespace ::cppu; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; + +extern "C" +{ +SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * /* pRegistryKey */ ) +{ + void * pRet = 0; + + OUString implName = OUString::createFromAscii( pImplName ); + if ( pServiceManager && implName.equals(WPGImportFilter_getImplementationName()) ) + { + Reference< XSingleServiceFactory > xFactory( createSingleFactory( + reinterpret_cast< XMultiServiceFactory * >( pServiceManager ), + OUString::createFromAscii( pImplName ), + WPGImportFilter_createInstance, WPGImportFilter_getSupportedServiceNames() ) ); + + if (xFactory.is()) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } + + return pRet; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpsimp/MSWorksImportFilter.cxx b/writerperfect/source/wpsimp/MSWorksImportFilter.cxx new file mode 100644 index 000000000000..55bd83d118d7 --- /dev/null +++ b/writerperfect/source/wpsimp/MSWorksImportFilter.cxx @@ -0,0 +1,279 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* MSWorksImportFilter: Sets up the filter, and calls DocumentCollector + * to do the actual filtering + * + * Copyright (C) 2000 by Sun Microsystems, Inc. + * Copyright (C) 2002-2004 William Lachance (wlach@interlog.com) + * Copyright (C) 2004 Net Integration Technologies (http://www.net-itech.com) + * Copyright (C) 2004 Fridrich Strba <fridrich.strba@bluewin.ch> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Contributor(s): Martin Gallwey (gallwey@sun.com) + * + */ +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ + +#include <osl/diagnose.h> +#include <rtl/tencinfo.h> + +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/xml/sax/XAttributeList.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <com/sun/star/xml/sax/InputSource.hpp> +#include <com/sun/star/xml/sax/XParser.hpp> +#include <com/sun/star/ucb/XCommandEnvironment.hpp> + +#include <xmloff/attrlist.hxx> +#include <ucbhelper/content.hxx> + +#include "filter/FilterInternal.hxx" +#include "filter/DocumentHandler.hxx" +#include "filter/OdtGenerator.hxx" +#include "stream/WPXSvStream.h" + +#include <libwps/WPSDocument.h> +#include "MSWorksImportFilter.hxx" + +// using namespace ::rtl; +using rtl::OString; +using rtl::OUString; +using com::sun::star::uno::Sequence; +using com::sun::star::uno::Reference; +using com::sun::star::uno::Any; +using com::sun::star::uno::UNO_QUERY; +using com::sun::star::uno::XInterface; +using com::sun::star::uno::Exception; +using com::sun::star::uno::RuntimeException; +using com::sun::star::lang::XMultiServiceFactory; +using com::sun::star::beans::PropertyValue; +using com::sun::star::document::XFilter; +using com::sun::star::document::XExtendedFilterDetection; +using com::sun::star::ucb::XCommandEnvironment; + +using com::sun::star::io::XInputStream; +using com::sun::star::document::XImporter; +using com::sun::star::xml::sax::InputSource; +using com::sun::star::xml::sax::XAttributeList; +using com::sun::star::xml::sax::XDocumentHandler; +using com::sun::star::xml::sax::XParser; + +void callHandler(Reference < XDocumentHandler > xDocHandler); + +sal_Bool SAL_CALL MSWorksImportFilter::importImpl( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) + throw (RuntimeException) +{ + WRITER_DEBUG_MSG(("MSWorksImportFilter::importImpl: Got here!\n")); + + sal_Int32 nLength = aDescriptor.getLength(); + const PropertyValue * pValue = aDescriptor.getConstArray(); + OUString sURL; + Reference < XInputStream > xInputStream; + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "InputStream" ) ) ) + pValue[i].Value >>= xInputStream; + else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "URL" ) ) ) + pValue[i].Value >>= sURL; + } + if ( !xInputStream.is() ) + { + OSL_ASSERT( 0 ); + return sal_False; + } + OString sFileName; + sFileName = OUStringToOString(sURL, RTL_TEXTENCODING_INFO_ASCII); + + // An XML import service: what we push sax messages to.. + OUString sXMLImportService ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Writer.XMLOasisImporter" ) ); + Reference < XDocumentHandler > xInternalHandler( mxMSF->createInstance( sXMLImportService ), UNO_QUERY ); + + // The XImporter sets up an empty target document for XDocumentHandler to write to.. + Reference < XImporter > xImporter(xInternalHandler, UNO_QUERY); + xImporter->setTargetDocument(mxDoc); + + // OO Document Handler: abstract class to handle document SAX messages, concrete implementation here + // writes to in-memory target doc + DocumentHandler xHandler(xInternalHandler); + + WPXSvInputStream input( xInputStream ); + + OdtGenerator collector(&xHandler, ODF_FLAT_XML); + if (WPS_OK == WPSDocument::parse(&input, &collector)) + return sal_True; + return sal_False; +} + +sal_Bool SAL_CALL MSWorksImportFilter::filter( const Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) + throw (RuntimeException) +{ + WRITER_DEBUG_MSG(("MSWorksImportFilter::filter: Got here!\n")); + return importImpl ( aDescriptor ); +} +void SAL_CALL MSWorksImportFilter::cancel( ) + throw (RuntimeException) +{ + WRITER_DEBUG_MSG(("MSWorksImportFilter::cancel: Got here!\n")); +} + +// XImporter +void SAL_CALL MSWorksImportFilter::setTargetDocument( const Reference< ::com::sun::star::lang::XComponent >& xDoc ) + throw (::com::sun::star::lang::IllegalArgumentException, RuntimeException) +{ + WRITER_DEBUG_MSG(("MSWorksImportFilter::getTargetDocument: Got here!\n")); + meType = FILTER_IMPORT; + mxDoc = xDoc; +} + +// XExtendedFilterDetection +OUString SAL_CALL MSWorksImportFilter::detect( com::sun::star::uno::Sequence< PropertyValue >& Descriptor ) + throw( com::sun::star::uno::RuntimeException ) +{ + WRITER_DEBUG_MSG(("MSWorksImportFilter::detect: Got here!\n")); + + WPSConfidence confidence = WPS_CONFIDENCE_NONE; + OUString sTypeName; + sal_Int32 nLength = Descriptor.getLength(); + sal_Int32 location = nLength; + OUString sURL; + const PropertyValue * pValue = Descriptor.getConstArray(); + Reference < XInputStream > xInputStream; + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "TypeName" ) ) ) + location=i; + else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "InputStream" ) ) ) + pValue[i].Value >>= xInputStream; + else if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "URL" ) ) ) + pValue[i].Value >>= sURL; + } + + Reference< com::sun::star::ucb::XCommandEnvironment > xEnv; + if (!xInputStream.is()) + { + try + { + ::ucbhelper::Content aContent(sURL, xEnv); + xInputStream = aContent.openStream(); + } + catch ( ... ) + { + return ::rtl::OUString(); + } + + if (!xInputStream.is()) + return ::rtl::OUString(); + } + + WPXSvInputStream input( xInputStream ); + + if (input.atEOS()) + return ::rtl::OUString(); + + confidence = WPSDocument::isFileFormatSupported(&input); + + if ((confidence == WPS_CONFIDENCE_EXCELLENT) || (confidence == WPS_CONFIDENCE_GOOD)) + sTypeName = OUString( RTL_CONSTASCII_USTRINGPARAM ( "writer_MS_Works_Document" ) ); + + if (sTypeName.getLength()) + { + if ( location == Descriptor.getLength() ) + { + Descriptor.realloc(nLength+1); + Descriptor[location].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TypeName")); + } + + Descriptor[location].Value <<=sTypeName; + } + + return sTypeName; +} + + +// XInitialization +void SAL_CALL MSWorksImportFilter::initialize( const Sequence< Any >& aArguments ) + throw (Exception, RuntimeException) +{ + WRITER_DEBUG_MSG(("MSWorksImportFilter::initialize: Got here!\n")); + Sequence < PropertyValue > aAnySeq; + sal_Int32 nLength = aArguments.getLength(); + if ( nLength && ( aArguments[0] >>= aAnySeq ) ) + { + const PropertyValue * pValue = aAnySeq.getConstArray(); + nLength = aAnySeq.getLength(); + for ( sal_Int32 i = 0 ; i < nLength; i++) + { + if ( pValue[i].Name.equalsAsciiL ( RTL_CONSTASCII_STRINGPARAM ( "Type" ) ) ) + { + pValue[i].Value >>= msFilterName; + break; + } + } + } +} +OUString MSWorksImportFilter_getImplementationName () + throw (RuntimeException) +{ + return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.comp.Writer.MSWorksImportFilter" ) ); +} + +#define SERVICE_NAME1 "com.sun.star.document.ImportFilter" +#define SERVICE_NAME2 "com.sun.star.document.ExtendedTypeDetection" +sal_Bool SAL_CALL MSWorksImportFilter_supportsService( const OUString& ServiceName ) + throw (RuntimeException) +{ + return (ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME1 ) ) || + ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SERVICE_NAME2 ) ) ); +} +Sequence< OUString > SAL_CALL MSWorksImportFilter_getSupportedServiceNames( ) + throw (RuntimeException) +{ + Sequence < OUString > aRet(2); + OUString* pArray = aRet.getArray(); + pArray[0] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME1 ) ); + pArray[1] = OUString ( RTL_CONSTASCII_USTRINGPARAM ( SERVICE_NAME2 ) ); + return aRet; +} +#undef SERVICE_NAME2 +#undef SERVICE_NAME1 + +Reference< XInterface > SAL_CALL MSWorksImportFilter_createInstance( const Reference< XMultiServiceFactory > & rSMgr) + throw( Exception ) +{ + return (cppu::OWeakObject*) new MSWorksImportFilter( rSMgr ); +} + +// XServiceInfo +OUString SAL_CALL MSWorksImportFilter::getImplementationName( ) + throw (RuntimeException) +{ + return MSWorksImportFilter_getImplementationName(); +} +sal_Bool SAL_CALL MSWorksImportFilter::supportsService( const OUString& rServiceName ) + throw (RuntimeException) +{ + return MSWorksImportFilter_supportsService( rServiceName ); +} +Sequence< OUString > SAL_CALL MSWorksImportFilter::getSupportedServiceNames( ) + throw (RuntimeException) +{ + return MSWorksImportFilter_getSupportedServiceNames(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpsimp/MSWorksImportFilter.hxx b/writerperfect/source/wpsimp/MSWorksImportFilter.hxx new file mode 100644 index 000000000000..71e621298f35 --- /dev/null +++ b/writerperfect/source/wpsimp/MSWorksImportFilter.hxx @@ -0,0 +1,120 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * Copyright (C) 2000 by Sun Microsystems, Inc. + * Copyright (C) 2002-2004 William Lachance (wlach@interlog.com) + * Copyright (C) 2004 Net Integration Technologies (http://www.net-itech.com) + * Copyright (C) 2004 Fridrich Strba <fridrich.strba@bluewin.ch> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Contributor(s): Martin Gallwey (gallwey@sun.com) + * + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#ifndef _WORDPERFECTIMPORTFILTER_HXX +#define _WORDPERFECTIMPORTFILTER_HXX + +#include <com/sun/star/document/XFilter.hpp> +#include <com/sun/star/document/XImporter.hpp> +#include <com/sun/star/document/XExtendedFilterDetection.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/xml/sax/XDocumentHandler.hpp> +#include <cppuhelper/implbase5.hxx> + +enum FilterType +{ + FILTER_IMPORT, + FILTER_EXPORT +}; +/* This component will be instantiated for both import or export. Whether it calls + * setSourceDocument or setTargetDocument determines which Impl function the filter + * member calls */ +class MSWorksImportFilter : public cppu::WeakImplHelper5 +< + com::sun::star::document::XFilter, + com::sun::star::document::XImporter, + com::sun::star::document::XExtendedFilterDetection, + com::sun::star::lang::XInitialization, + com::sun::star::lang::XServiceInfo +> +{ +protected: + // oo.org declares + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > mxMSF; + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > mxDoc; + ::rtl::OUString msFilterName; + ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XDocumentHandler > mxHandler; + + FilterType meType; + + sal_Bool SAL_CALL importImpl( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) + throw (::com::sun::star::uno::RuntimeException); + +public: + MSWorksImportFilter( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > &rxMSF) + : mxMSF( rxMSF ) + , meType( FILTER_IMPORT ) + {} + virtual ~MSWorksImportFilter() {} + + // XFilter + virtual sal_Bool SAL_CALL filter( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor ) + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL cancel( ) + throw (::com::sun::star::uno::RuntimeException); + + // XImporter + virtual void SAL_CALL setTargetDocument( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& xDoc ) + throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + + //XExtendedFilterDetection + virtual ::rtl::OUString SAL_CALL detect( com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& Descriptor ) + throw( com::sun::star::uno::RuntimeException ); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) + throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) + throw (::com::sun::star::uno::RuntimeException); + +}; + +::rtl::OUString MSWorksImportFilter_getImplementationName() + throw ( ::com::sun::star::uno::RuntimeException ); + +sal_Bool SAL_CALL MSWorksImportFilter_supportsService( const ::rtl::OUString& ServiceName ) + throw ( ::com::sun::star::uno::RuntimeException ); + +::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL MSWorksImportFilter_getSupportedServiceNames( ) + throw ( ::com::sun::star::uno::RuntimeException ); + +::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > +SAL_CALL MSWorksImportFilter_createInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & rSMgr) + throw ( ::com::sun::star::uno::Exception ); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/source/wpsimp/msworks_genericfilter.cxx b/writerperfect/source/wpsimp/msworks_genericfilter.cxx new file mode 100644 index 000000000000..87dc407c9a81 --- /dev/null +++ b/writerperfect/source/wpsimp/msworks_genericfilter.cxx @@ -0,0 +1,68 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* genericfilter: mostly generic code for registering the filter + * + * Portions of this code Copyright 2000 by Sun Microsystems, Inc. + * Rest is Copyright (C) 2002 William Lachance (wlach@interlog.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +/* "This product is not manufactured, approved, or supported by + * Corel Corporation or Corel Corporation Limited." + */ +#include <stdio.h> + +#include <osl/mutex.hxx> +#include <osl/thread.h> +#include <cppuhelper/factory.hxx> + +#include <com/sun/star/lang/XSingleServiceFactory.hpp> + +#include "MSWorksImportFilter.hxx" + +using namespace ::rtl; +using namespace ::cppu; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::registry; + +extern "C" +{ +SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * /* pRegistryKey */ ) +{ + void * pRet = 0; + + OUString implName = OUString::createFromAscii( pImplName ); + if ( pServiceManager && implName.equals(MSWorksImportFilter_getImplementationName()) ) + { + Reference< XSingleServiceFactory > xFactory( createSingleFactory( + reinterpret_cast< XMultiServiceFactory * >( pServiceManager ), + OUString::createFromAscii( pImplName ), + MSWorksImportFilter_createInstance, MSWorksImportFilter_getSupportedServiceNames() ) ); + + if (xFactory.is()) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + } + + return pRet; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerperfect/util/msworksfilter.component b/writerperfect/util/msworksfilter.component new file mode 100644 index 000000000000..769eaf388f16 --- /dev/null +++ b/writerperfect/util/msworksfilter.component @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.Writer.MSWorksImportFilter"> + <service name="com.sun.star.document.ImportFilter"/> + <service name="com.sun.star.document.ExtendedTypeDetection"/> + </implementation> +</component> diff --git a/writerperfect/util/visiofilter.component b/writerperfect/util/visiofilter.component new file mode 100644 index 000000000000..6b19b2801f06 --- /dev/null +++ b/writerperfect/util/visiofilter.component @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.Draw.VisioImportFilter"> + <service name="com.sun.star.document.ImportFilter"/> + <service name="com.sun.star.document.ExtendedTypeDetection"/> + </implementation> +</component> diff --git a/writerperfect/util/wpft.component b/writerperfect/util/wpft.component new file mode 100644 index 000000000000..2d8a013606a9 --- /dev/null +++ b/writerperfect/util/wpft.component @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!--********************************************************************** +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2000, 2010 Oracle and/or its affiliates. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org 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 Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +* +**********************************************************************--> + +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.Writer.WordPerfectImportFilter"> + <service name="com.sun.star.document.ExtendedTypeDetection"/> + <service name="com.sun.star.document.ImportFilter"/> + </implementation> +</component> diff --git a/writerperfect/util/wpgfilter.component b/writerperfect/util/wpgfilter.component new file mode 100644 index 000000000000..f571959c0521 --- /dev/null +++ b/writerperfect/util/wpgfilter.component @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<component loader="com.sun.star.loader.SharedLibrary" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.Draw.WPGImportFilter"> + <service name="com.sun.star.document.ImportFilter"/> + <service name="com.sun.star.document.ExtendedTypeDetection"/> + </implementation> +</component> |