diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /framework/source/xml | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'framework/source/xml')
-rw-r--r-- | framework/source/xml/acceleratorconfigurationreader.cxx | 258 | ||||
-rw-r--r-- | framework/source/xml/acceleratorconfigurationwriter.cxx | 123 | ||||
-rw-r--r-- | framework/source/xml/imagesconfiguration.cxx | 104 | ||||
-rw-r--r-- | framework/source/xml/imagesdocumenthandler.cxx | 372 |
4 files changed, 857 insertions, 0 deletions
diff --git a/framework/source/xml/acceleratorconfigurationreader.cxx b/framework/source/xml/acceleratorconfigurationreader.cxx new file mode 100644 index 000000000..ad6bc7259 --- /dev/null +++ b/framework/source/xml/acceleratorconfigurationreader.cxx @@ -0,0 +1,258 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> +#include <sal/log.hxx> + +#include <accelerators/keymapping.hxx> +#include <xml/acceleratorconfigurationreader.hxx> + +#include <com/sun/star/xml/sax/SAXException.hpp> +#include <com/sun/star/awt/KeyModifier.hpp> +#include <com/sun/star/awt/KeyEvent.hpp> + +namespace framework{ + +/* Throws a SaxException in case a wrong formatted XML + structure was detected. + + This macro combined the given comment with a generic + way to find out the XML line (where the error occurred) + to format a suitable message. + + @param COMMENT + an ascii string, which describe the problem. + */ +#define THROW_PARSEEXCEPTION(COMMENT) \ + { \ + throw css::xml::sax::SAXException( \ + implts_getErrorLineString() + COMMENT, \ + static_cast< css::xml::sax::XDocumentHandler* >(this), \ + css::uno::Any()); \ + } + +AcceleratorConfigurationReader::AcceleratorConfigurationReader(AcceleratorCache& rContainer) + : m_rContainer (rContainer ) + , m_bInsideAcceleratorList(false ) + , m_bInsideAcceleratorItem(false ) +{ +} + +AcceleratorConfigurationReader::~AcceleratorConfigurationReader() +{ +} + +void SAL_CALL AcceleratorConfigurationReader::startDocument() +{ +} + +void SAL_CALL AcceleratorConfigurationReader::endDocument() +{ + // The xml file seems to be corrupted. + // Because we found no end-tags ... at least for + // one list or item. + if (m_bInsideAcceleratorList || m_bInsideAcceleratorItem) + { + THROW_PARSEEXCEPTION("No matching start or end element 'acceleratorlist' found!") + } +} + +void SAL_CALL AcceleratorConfigurationReader::startElement(const OUString& sElement , + const css::uno::Reference< css::xml::sax::XAttributeList >& xAttributeList) +{ + EXMLElement eElement = AcceleratorConfigurationReader::implst_classifyElement(sElement); + + // Note: We handle "accel:item" before "accel:acceleratorlist" to perform this operation. + // Because an item occurs very often ... a list should occur one times only! + if (eElement == E_ELEMENT_ITEM) + { + if (!m_bInsideAcceleratorList) + THROW_PARSEEXCEPTION("An element \"accel:item\" must be embedded into 'accel:acceleratorlist'.") + if (m_bInsideAcceleratorItem) + THROW_PARSEEXCEPTION("An element \"accel:item\" is not a container.") + m_bInsideAcceleratorItem = true; + + OUString sCommand; + css::awt::KeyEvent aEvent; + + sal_Int16 c = xAttributeList->getLength(); + sal_Int16 i = 0; + for (i=0; i<c; ++i) + { + OUString sAttribute = xAttributeList->getNameByIndex(i); + OUString sValue = xAttributeList->getValueByIndex(i); + EXMLAttribute eAttribute = AcceleratorConfigurationReader::implst_classifyAttribute(sAttribute); + switch(eAttribute) + { + case E_ATTRIBUTE_URL : + sCommand = sValue.intern(); + break; + + case E_ATTRIBUTE_KEYCODE : + aEvent.KeyCode = KeyMapping::get().mapIdentifierToCode(sValue); + break; + + case E_ATTRIBUTE_MOD_SHIFT : + aEvent.Modifiers |= css::awt::KeyModifier::SHIFT; + break; + + case E_ATTRIBUTE_MOD_MOD1 : + aEvent.Modifiers |= css::awt::KeyModifier::MOD1; + break; + + case E_ATTRIBUTE_MOD_MOD2 : + aEvent.Modifiers |= css::awt::KeyModifier::MOD2; + break; + + case E_ATTRIBUTE_MOD_MOD3 : + aEvent.Modifiers |= css::awt::KeyModifier::MOD3; + } + } + + // validate command and key event. + if ( + sCommand.isEmpty() || + (aEvent.KeyCode == 0 ) + ) + { + THROW_PARSEEXCEPTION("XML element does not describe a valid accelerator nor a valid command.") + } + + // register key event + command inside cache ... + // Check for already existing items there. + if (!m_rContainer.hasKey(aEvent)) + m_rContainer.setKeyCommandPair(aEvent, sCommand); + else + { + // Attention: It's not really a reason to throw an exception and kill the office, if the configuration contains + // multiple registrations for the same key :-) Show a warning ... and ignore the second item. + // THROW_PARSEEXCEPTION("Command is registered for the same key more than once.") + SAL_INFO("fwk", + "AcceleratorConfigurationReader::startElement(): Double registration detected. Command=\"" << + sCommand << + "\" KeyCode=" << + aEvent.KeyCode << + "Modifiers=" << + aEvent.Modifiers); + } + } + + if (eElement == E_ELEMENT_ACCELERATORLIST) + { + if (m_bInsideAcceleratorList) + THROW_PARSEEXCEPTION("An element \"accel:acceleratorlist\" cannot be used recursive.") + m_bInsideAcceleratorList = true; + return; + } +} + +void SAL_CALL AcceleratorConfigurationReader::endElement(const OUString& sElement) +{ + EXMLElement eElement = AcceleratorConfigurationReader::implst_classifyElement(sElement); + + // Note: We handle "accel:item" before "accel:acceleratorlist" to perform this operation. + // Because an item occurs very often ... a list should occur one times only! + if (eElement == E_ELEMENT_ITEM) + { + if (!m_bInsideAcceleratorItem) + THROW_PARSEEXCEPTION("Found end element 'accel:item', but no start element.") + m_bInsideAcceleratorItem = false; + } + + if (eElement == E_ELEMENT_ACCELERATORLIST) + { + if (!m_bInsideAcceleratorList) + THROW_PARSEEXCEPTION("Found end element 'accel:acceleratorlist', but no start element.") + m_bInsideAcceleratorList = false; + } +} + +void SAL_CALL AcceleratorConfigurationReader::characters(const OUString&) +{ +} + +void SAL_CALL AcceleratorConfigurationReader::ignorableWhitespace(const OUString&) +{ +} + +void SAL_CALL AcceleratorConfigurationReader::processingInstruction(const OUString& /*sTarget*/, + const OUString& /*sData*/ ) +{ +} + +void SAL_CALL AcceleratorConfigurationReader::setDocumentLocator(const css::uno::Reference< css::xml::sax::XLocator >& xLocator) +{ + m_xLocator = xLocator; +} + +AcceleratorConfigurationReader::EXMLElement AcceleratorConfigurationReader::implst_classifyElement(std::u16string_view sElement) +{ + AcceleratorConfigurationReader::EXMLElement eElement; + + if (sElement == u"http://openoffice.org/2001/accel^acceleratorlist") + eElement = E_ELEMENT_ACCELERATORLIST; + else if (sElement == u"http://openoffice.org/2001/accel^item") + eElement = E_ELEMENT_ITEM; + else + throw css::uno::RuntimeException( + "Unknown XML element detected!", + css::uno::Reference< css::xml::sax::XDocumentHandler >()); + + return eElement; +} + +AcceleratorConfigurationReader::EXMLAttribute AcceleratorConfigurationReader::implst_classifyAttribute(std::u16string_view sAttribute) +{ + AcceleratorConfigurationReader::EXMLAttribute eAttribute; + + if (sAttribute == u"http://openoffice.org/2001/accel^code") + eAttribute = E_ATTRIBUTE_KEYCODE; + else if (sAttribute == u"http://openoffice.org/2001/accel^shift") + eAttribute = E_ATTRIBUTE_MOD_SHIFT; + else if (sAttribute == u"http://openoffice.org/2001/accel^mod1") + eAttribute = E_ATTRIBUTE_MOD_MOD1; + else if (sAttribute == u"http://openoffice.org/2001/accel^mod2") + eAttribute = E_ATTRIBUTE_MOD_MOD2; + else if (sAttribute == u"http://openoffice.org/2001/accel^mod3") + eAttribute = E_ATTRIBUTE_MOD_MOD3; + else if (sAttribute == u"http://www.w3.org/1999/xlink^href") + eAttribute = E_ATTRIBUTE_URL; + else + throw css::uno::RuntimeException( + "Unknown XML attribute detected!", + css::uno::Reference< css::xml::sax::XDocumentHandler >()); + + return eAttribute; +} + +OUString AcceleratorConfigurationReader::implts_getErrorLineString() +{ + if (!m_xLocator.is()) + return "Error during parsing XML. (No further info available ...)"; + + return "Error during parsing XML in\nline = " + + OUString::number(m_xLocator->getLineNumber()) + + "\ncolumn = " + + OUString::number(m_xLocator->getColumnNumber()) + + "."; +} + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/xml/acceleratorconfigurationwriter.cxx b/framework/source/xml/acceleratorconfigurationwriter.cxx new file mode 100644 index 000000000..04e50f5ae --- /dev/null +++ b/framework/source/xml/acceleratorconfigurationwriter.cxx @@ -0,0 +1,123 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <accelerators/keymapping.hxx> +#include <utility> +#include <xml/acceleratorconfigurationwriter.hxx> + +#include <acceleratorconst.h> + +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> +#include <com/sun/star/awt/KeyModifier.hpp> + +#include <comphelper/attributelist.hxx> +#include <rtl/ref.hxx> + +namespace framework{ + +AcceleratorConfigurationWriter::AcceleratorConfigurationWriter(const AcceleratorCache& rContainer, + css::uno::Reference< css::xml::sax::XDocumentHandler > xConfig ) + : m_xConfig (std::move(xConfig )) + , m_rContainer (rContainer ) +{ +} + +AcceleratorConfigurationWriter::~AcceleratorConfigurationWriter() +{ +} + +void AcceleratorConfigurationWriter::flush() +{ + css::uno::Reference< css::xml::sax::XExtendedDocumentHandler > xExtendedCFG(m_xConfig, css::uno::UNO_QUERY_THROW); + + // prepare attribute list + rtl::Reference<::comphelper::AttributeList> pAttribs = new ::comphelper::AttributeList; + + pAttribs->AddAttribute( + "xmlns:accel", ATTRIBUTE_TYPE_CDATA, + "http://openoffice.org/2001/accel"); + pAttribs->AddAttribute( + "xmlns:xlink", ATTRIBUTE_TYPE_CDATA, "http://www.w3.org/1999/xlink"); + + // generate xml + xExtendedCFG->startDocument(); + + xExtendedCFG->unknown( + "<!DOCTYPE accel:acceleratorlist PUBLIC \"-//OpenOffice.org//DTD" + " OfficeDocument 1.0//EN\" \"accelerator.dtd\">"); + xExtendedCFG->ignorableWhitespace(OUString()); + + xExtendedCFG->startElement(AL_ELEMENT_ACCELERATORLIST, pAttribs); + xExtendedCFG->ignorableWhitespace(OUString()); + + // TODO think about threadsafe using of cache + AcceleratorCache::TKeyList lKeys = m_rContainer.getAllKeys(); + for (auto const& lKey : lKeys) + { + const OUString& rCommand = m_rContainer.getCommandByKey(lKey); + impl_ts_writeKeyCommandPair(lKey, rCommand, xExtendedCFG); + } + + /* TODO write key-command list + for (auto const& writeAccelerator : m_aWriteAcceleratorList) + WriteAcceleratorItem(writeAccelerator); + */ + + xExtendedCFG->ignorableWhitespace(OUString()); + xExtendedCFG->endElement(AL_ELEMENT_ACCELERATORLIST); + xExtendedCFG->ignorableWhitespace(OUString()); + xExtendedCFG->endDocument(); +} + +void AcceleratorConfigurationWriter::impl_ts_writeKeyCommandPair(const css::awt::KeyEvent& aKey , + const OUString& sCommand, + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xConfig ) +{ + rtl::Reference<::comphelper::AttributeList> pAttribs = new ::comphelper::AttributeList; + + OUString sKey = KeyMapping::get().mapCodeToIdentifier(aKey.KeyCode); + // TODO check if key is empty! + + pAttribs->AddAttribute("accel:code", ATTRIBUTE_TYPE_CDATA, sKey ); + pAttribs->AddAttribute("xlink:href", ATTRIBUTE_TYPE_CDATA, sCommand); + + if ((aKey.Modifiers & css::awt::KeyModifier::SHIFT) == css::awt::KeyModifier::SHIFT) + pAttribs->AddAttribute("accel:shift", ATTRIBUTE_TYPE_CDATA, "true"); + + if ((aKey.Modifiers & css::awt::KeyModifier::MOD1) == css::awt::KeyModifier::MOD1) + pAttribs->AddAttribute("accel:mod1", ATTRIBUTE_TYPE_CDATA, "true"); + + if ((aKey.Modifiers & css::awt::KeyModifier::MOD2) == css::awt::KeyModifier::MOD2) + pAttribs->AddAttribute("accel:mod2", ATTRIBUTE_TYPE_CDATA, "true"); + + if ((aKey.Modifiers & css::awt::KeyModifier::MOD3) == css::awt::KeyModifier::MOD3) + pAttribs->AddAttribute("accel:mod3", ATTRIBUTE_TYPE_CDATA, "true"); + + xConfig->ignorableWhitespace(OUString()); + xConfig->startElement(AL_ELEMENT_ITEM, pAttribs); + xConfig->ignorableWhitespace(OUString()); + xConfig->endElement(AL_ELEMENT_ITEM); + xConfig->ignorableWhitespace(OUString()); +} + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/xml/imagesconfiguration.cxx b/framework/source/xml/imagesconfiguration.cxx new file mode 100644 index 000000000..6b4773c21 --- /dev/null +++ b/framework/source/xml/imagesconfiguration.cxx @@ -0,0 +1,104 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <xml/imagesconfiguration.hxx> + +#include <xml/imagesdocumenthandler.hxx> +#include <xml/saxnamespacefilter.hxx> + +#include <com/sun/star/xml/sax/Parser.hpp> +#include <com/sun/star/xml/sax/Writer.hpp> +#include <com/sun/star/xml/sax/SAXException.hpp> +#include <com/sun/star/io/IOException.hpp> +#include <com/sun/star/io/XInputStream.hpp> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::io; + +namespace framework +{ +bool ImagesConfiguration::LoadImages( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::io::XInputStream>& rInputStream, ImageItemDescriptorList& rItems) +{ + Reference<XParser> xParser = Parser::create(rxContext); + + // connect stream to input stream to the parser + InputSource aInputSource; + + aInputSource.aInputStream = rInputStream; + + // create namespace filter and set document handler inside to support xml namespaces + Reference<XDocumentHandler> xDocHandler(new OReadImagesDocumentHandler(rItems)); + Reference<XDocumentHandler> xFilter(new SaxNamespaceFilter(xDocHandler)); + + // connect parser and filter + xParser->setDocumentHandler(xFilter); + + try + { + xParser->parseStream(aInputSource); + return true; + } + catch (const RuntimeException&) + { + return false; + } + catch (const SAXException&) + { + return false; + } + catch (const css::io::IOException&) + { + return false; + } +} + +bool ImagesConfiguration::StoreImages( + const css::uno::Reference<css::uno::XComponentContext>& rxContext, + const css::uno::Reference<css::io::XOutputStream>& rOutputStream, + const ImageItemDescriptorList& rItems) +{ + Reference<XWriter> xWriter = Writer::create(rxContext); + xWriter->setOutputStream(rOutputStream); + + try + { + OWriteImagesDocumentHandler aWriteImagesDocumentHandler(rItems, xWriter); + aWriteImagesDocumentHandler.WriteImagesDocument(); + return true; + } + catch (const RuntimeException&) + { + return false; + } + catch (const SAXException&) + { + return false; + } + catch (const css::io::IOException&) + { + return false; + } +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/xml/imagesdocumenthandler.cxx b/framework/source/xml/imagesdocumenthandler.cxx new file mode 100644 index 000000000..ebdd5366f --- /dev/null +++ b/framework/source/xml/imagesdocumenthandler.cxx @@ -0,0 +1,372 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <xml/imagesdocumenthandler.hxx> + +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> +#include <com/sun/star/xml/sax/SAXException.hpp> + +#include <rtl/ref.hxx> +#include <rtl/ustrbuf.hxx> + +#include <comphelper/attributelist.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::xml::sax; + +#define ELEMENT_IMAGECONTAINER "imagescontainer" +#define ELEMENT_IMAGES "images" +#define ELEMENT_ENTRY "entry" +#define ELEMENT_EXTERNALIMAGES "externalimages" +#define ELEMENT_EXTERNALENTRY "externalentry" + +constexpr OUStringLiteral ELEMENT_NS_IMAGESCONTAINER = u"image:imagescontainer"; +constexpr OUStringLiteral ELEMENT_NS_IMAGES = u"image:images"; +constexpr OUStringLiteral ELEMENT_NS_ENTRY = u"image:entry"; + +#define ATTRIBUTE_HREF "href" +#define ATTRIBUTE_MASKCOLOR "maskcolor" +#define ATTRIBUTE_COMMAND "command" +#define ATTRIBUTE_BITMAPINDEX "bitmap-index" +#define ATTRIBUTE_MASKURL "maskurl" +#define ATTRIBUTE_MASKMODE "maskmode" +#define ATTRIBUTE_HIGHCONTRASTURL "highcontrasturl" +#define ATTRIBUTE_HIGHCONTRASTMASKURL "highcontrastmaskurl" +constexpr OUStringLiteral ATTRIBUTE_TYPE_CDATA = u"CDATA"; + +constexpr OUStringLiteral ATTRIBUTE_XMLNS_IMAGE = u"xmlns:image"; +constexpr OUStringLiteral ATTRIBUTE_XMLNS_XLINK = u"xmlns:xlink"; + +constexpr OUStringLiteral ATTRIBUTE_XLINK_TYPE = u"xlink:type"; +constexpr OUStringLiteral ATTRIBUTE_XLINK_TYPE_VALUE = u"simple"; + +constexpr OUStringLiteral XMLNS_IMAGE = u"http://openoffice.org/2001/image"; +constexpr OUStringLiteral XMLNS_XLINK = u"http://www.w3.org/1999/xlink"; +constexpr OUStringLiteral XMLNS_IMAGE_PREFIX = u"image:"; + +constexpr OUStringLiteral XMLNS_FILTER_SEPARATOR = u"^"; + +constexpr OUStringLiteral IMAGES_DOCTYPE = u"<!DOCTYPE image:imagecontainer PUBLIC \"-//OpenOffice.org//DTD OfficeDocument 1.0//EN\" \"image.dtd\">"; + +namespace framework +{ + +namespace { + +struct ImageXMLEntryProperty +{ + OReadImagesDocumentHandler::Image_XML_Namespace nNamespace; + char aEntryName[20]; +}; + +} + +ImageXMLEntryProperty const ImagesEntries[OReadImagesDocumentHandler::IMG_XML_ENTRY_COUNT] = +{ + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ELEMENT_IMAGECONTAINER }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ELEMENT_IMAGES }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ELEMENT_ENTRY }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ELEMENT_EXTERNALIMAGES }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ELEMENT_EXTERNALENTRY }, + { OReadImagesDocumentHandler::IMG_NS_XLINK, ATTRIBUTE_HREF }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ATTRIBUTE_MASKCOLOR }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ATTRIBUTE_COMMAND }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ATTRIBUTE_BITMAPINDEX }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ATTRIBUTE_MASKURL }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ATTRIBUTE_MASKMODE }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ATTRIBUTE_HIGHCONTRASTURL }, + { OReadImagesDocumentHandler::IMG_NS_IMAGE, ATTRIBUTE_HIGHCONTRASTMASKURL } +}; + +OReadImagesDocumentHandler::OReadImagesDocumentHandler( ImageItemDescriptorList& rItems ) : + m_rImageList( rItems ) +{ + // create hash map to speed up lookup + for ( int i = 0; i < IMG_XML_ENTRY_COUNT; i++ ) + { + OUStringBuffer temp( 20 ); + + if ( ImagesEntries[i].nNamespace == IMG_NS_IMAGE ) + temp.append( XMLNS_IMAGE ); + else + temp.append( XMLNS_XLINK ); + + temp.append( XMLNS_FILTER_SEPARATOR ); + temp.appendAscii( ImagesEntries[i].aEntryName ); + m_aImageMap.emplace( temp.makeStringAndClear(), static_cast<Image_XML_Entry>(i) ); + } + + // reset states + m_bImageContainerStartFound = false; + m_bImageContainerEndFound = false; + m_bImagesStartFound = false; +} + +OReadImagesDocumentHandler::~OReadImagesDocumentHandler() +{ +} + +// XDocumentHandler +void SAL_CALL OReadImagesDocumentHandler::startDocument() +{ +} + +void SAL_CALL OReadImagesDocumentHandler::endDocument() +{ + if (m_bImageContainerStartFound != m_bImageContainerEndFound) + { + OUString aErrorMessage = getErrorLineString() + "No matching start or end element 'image:imagecontainer' found!"; + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } +} + +void SAL_CALL OReadImagesDocumentHandler::startElement( + const OUString& aName, const Reference< XAttributeList > &xAttribs ) +{ + ImageHashMap::const_iterator pImageEntry = m_aImageMap.find( aName ); + if ( pImageEntry == m_aImageMap.end() ) + return; + + switch ( pImageEntry->second ) + { + case IMG_ELEMENT_IMAGECONTAINER: + { + // image:imagecontainer element (container element for all further image elements) + if ( m_bImageContainerStartFound ) + { + OUString aErrorMessage = getErrorLineString() + "Element 'image:imagecontainer' cannot be embedded into 'image:imagecontainer'!"; + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_bImageContainerStartFound = true; + } + break; + + case IMG_ELEMENT_IMAGES: + { + if ( !m_bImageContainerStartFound ) + { + OUString aErrorMessage = getErrorLineString() + "Element 'image:images' must be embedded into element 'image:imagecontainer'!"; + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + if ( m_bImagesStartFound ) + { + OUString aErrorMessage = getErrorLineString() + "Element 'image:images' cannot be embedded into 'image:images'!"; + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_bImagesStartFound = true; + } + break; + + case IMG_ELEMENT_ENTRY: + { + // Check that image:entry is embedded into image:images! + if ( !m_bImagesStartFound ) + { + OUString aErrorMessage = getErrorLineString() + "Element 'image:entry' must be embedded into element 'image:images'!"; + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + // Create new image item descriptor + ImageItemDescriptor aItem; + + // Read attributes for this image definition + for ( sal_Int16 n = 0; n < xAttribs->getLength(); n++ ) + { + pImageEntry = m_aImageMap.find( xAttribs->getNameByIndex( n ) ); + if ( pImageEntry != m_aImageMap.end() ) + { + switch ( pImageEntry->second ) + { + case IMG_ATTRIBUTE_COMMAND: + { + aItem.aCommandURL = xAttribs->getValueByIndex( n ); + } + break; + + default: + break; + } + } + } + + // Check required attribute "command" + if ( aItem.aCommandURL.isEmpty() ) + { + OUString aErrorMessage = getErrorLineString() + "Required attribute 'image:command' must have a value!"; + throw SAXException( aErrorMessage, Reference< XInterface >(), Any() ); + } + + m_rImageList.push_back( aItem ); + } + break; + + default: + break; + } +} + +void SAL_CALL OReadImagesDocumentHandler::endElement(const OUString& aName) +{ + ImageHashMap::const_iterator pImageEntry = m_aImageMap.find( aName ); + if ( pImageEntry == m_aImageMap.end() ) + return; + + switch ( pImageEntry->second ) + { + case IMG_ELEMENT_IMAGECONTAINER: + { + m_bImageContainerEndFound = true; + } + break; + + case IMG_ELEMENT_IMAGES: + { + m_bImagesStartFound = false; + } + break; + + default: break; + } +} + +void SAL_CALL OReadImagesDocumentHandler::characters(const OUString&) +{ +} + +void SAL_CALL OReadImagesDocumentHandler::ignorableWhitespace(const OUString&) +{ +} + +void SAL_CALL OReadImagesDocumentHandler::processingInstruction( + const OUString& /*aTarget*/, const OUString& /*aData*/ ) +{ +} + +void SAL_CALL OReadImagesDocumentHandler::setDocumentLocator( + const Reference< XLocator > &xLocator) +{ + m_xLocator = xLocator; +} + +OUString OReadImagesDocumentHandler::getErrorLineString() +{ + if ( m_xLocator.is() ) + { + return "Line: " + + OUString::number(m_xLocator->getLineNumber()) + + " - "; + } + else + return OUString(); +} + +// OWriteImagesDocumentHandler + +OWriteImagesDocumentHandler::OWriteImagesDocumentHandler( + const ImageItemDescriptorList& rItems, + Reference< XDocumentHandler > const & rWriteDocumentHandler ) : + m_rImageItemList( rItems ), + m_xWriteDocumentHandler( rWriteDocumentHandler ) +{ + m_xEmptyList = new ::comphelper::AttributeList; + m_aAttributeType = ATTRIBUTE_TYPE_CDATA; + m_aXMLImageNS = XMLNS_IMAGE_PREFIX; + m_aAttributeXlinkType = ATTRIBUTE_XLINK_TYPE; + m_aAttributeValueSimple = ATTRIBUTE_XLINK_TYPE_VALUE; +} + +OWriteImagesDocumentHandler::~OWriteImagesDocumentHandler() +{ +} + +void OWriteImagesDocumentHandler::WriteImagesDocument() +{ + m_xWriteDocumentHandler->startDocument(); + + // write DOCTYPE line! + Reference< XExtendedDocumentHandler > xExtendedDocHandler( m_xWriteDocumentHandler, UNO_QUERY ); + if ( xExtendedDocHandler.is() ) + { + xExtendedDocHandler->unknown( IMAGES_DOCTYPE ); + m_xWriteDocumentHandler->ignorableWhitespace( OUString() ); + } + + rtl::Reference<::comphelper::AttributeList> pList = new ::comphelper::AttributeList; + + pList->AddAttribute( ATTRIBUTE_XMLNS_IMAGE, + m_aAttributeType, + XMLNS_IMAGE ); + + pList->AddAttribute( ATTRIBUTE_XMLNS_XLINK, + m_aAttributeType, + XMLNS_XLINK ); + + m_xWriteDocumentHandler->startElement( ELEMENT_NS_IMAGESCONTAINER, pList ); + m_xWriteDocumentHandler->ignorableWhitespace( OUString() ); + + WriteImageList( &m_rImageItemList ); + + m_xWriteDocumentHandler->ignorableWhitespace( OUString() ); + m_xWriteDocumentHandler->endElement( ELEMENT_NS_IMAGESCONTAINER ); + m_xWriteDocumentHandler->ignorableWhitespace( OUString() ); + m_xWriteDocumentHandler->endDocument(); +} + +// protected member functions + +void OWriteImagesDocumentHandler::WriteImageList( const ImageItemDescriptorList* pImageList ) +{ + rtl::Reference<::comphelper::AttributeList> pList = new ::comphelper::AttributeList; + + // save required attributes + pList->AddAttribute( m_aAttributeXlinkType, + m_aAttributeType, + m_aAttributeValueSimple ); + + m_xWriteDocumentHandler->startElement( ELEMENT_NS_IMAGES, pList ); + m_xWriteDocumentHandler->ignorableWhitespace( OUString() ); + + for (const ImageItemDescriptor & i : *pImageList) + WriteImage( &i ); + + m_xWriteDocumentHandler->endElement( ELEMENT_NS_IMAGES ); + m_xWriteDocumentHandler->ignorableWhitespace( OUString() ); +} + +void OWriteImagesDocumentHandler::WriteImage( const ImageItemDescriptor* pImage ) +{ + rtl::Reference<::comphelper::AttributeList> pList = new ::comphelper::AttributeList; + + pList->AddAttribute( m_aXMLImageNS + ATTRIBUTE_COMMAND, + m_aAttributeType, + pImage->aCommandURL ); + + m_xWriteDocumentHandler->startElement( ELEMENT_NS_ENTRY, pList ); + m_xWriteDocumentHandler->ignorableWhitespace( OUString() ); + + m_xWriteDocumentHandler->endElement( ELEMENT_NS_ENTRY ); + m_xWriteDocumentHandler->ignorableWhitespace( OUString() ); +} + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |