diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /framework/source/xml | |
parent | Initial commit. (diff) | |
download | libreoffice-upstream.tar.xz libreoffice-upstream.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'framework/source/xml')
-rw-r--r-- | framework/source/xml/acceleratorconfigurationreader.cxx | 262 | ||||
-rw-r--r-- | framework/source/xml/acceleratorconfigurationwriter.cxx | 124 | ||||
-rw-r--r-- | framework/source/xml/imagesconfiguration.cxx | 107 | ||||
-rw-r--r-- | framework/source/xml/imagesdocumenthandler.cxx | 386 |
4 files changed, 879 insertions, 0 deletions
diff --git a/framework/source/xml/acceleratorconfigurationreader.cxx b/framework/source/xml/acceleratorconfigurationreader.cxx new file mode 100644 index 000000000..2ff467f68 --- /dev/null +++ b/framework/source/xml/acceleratorconfigurationreader.cxx @@ -0,0 +1,262 @@ +/* -*- 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> + +#include <rtl/ustrbuf.hxx> + +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(const OUString& sElement) +{ + AcceleratorConfigurationReader::EXMLElement eElement; + + if (sElement == "http://openoffice.org/2001/accel^acceleratorlist") + eElement = E_ELEMENT_ACCELERATORLIST; + else if (sElement == "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(const OUString& sAttribute) +{ + AcceleratorConfigurationReader::EXMLAttribute eAttribute; + + if (sAttribute == "http://openoffice.org/2001/accel^code") + eAttribute = E_ATTRIBUTE_KEYCODE; + else if (sAttribute == "http://openoffice.org/2001/accel^shift") + eAttribute = E_ATTRIBUTE_MOD_SHIFT; + else if (sAttribute == "http://openoffice.org/2001/accel^mod1") + eAttribute = E_ATTRIBUTE_MOD_MOD1; + else if (sAttribute == "http://openoffice.org/2001/accel^mod2") + eAttribute = E_ATTRIBUTE_MOD_MOD2; + else if (sAttribute == "http://openoffice.org/2001/accel^mod3") + eAttribute = E_ATTRIBUTE_MOD_MOD3; + else if (sAttribute == "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 ...)"; + + OUStringBuffer sMsg(256); + sMsg.append("Error during parsing XML in\nline = "); + sMsg.append (m_xLocator->getLineNumber() ); + sMsg.append("\ncolumn = " ); + sMsg.append (m_xLocator->getColumnNumber() ); + sMsg.append("." ); + return sMsg.makeStringAndClear(); +} + +} // 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..c94501ad1 --- /dev/null +++ b/framework/source/xml/acceleratorconfigurationwriter.cxx @@ -0,0 +1,124 @@ +/* -*- 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 <xml/acceleratorconfigurationwriter.hxx> + +#include <acceleratorconst.h> + +#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> +#include <com/sun/star/xml/sax/XAttributeList.hpp> +#include <com/sun/star/awt/KeyModifier.hpp> + +#include <comphelper/attributelist.hxx> + +namespace framework{ + +AcceleratorConfigurationWriter::AcceleratorConfigurationWriter(const AcceleratorCache& rContainer, + const css::uno::Reference< css::xml::sax::XDocumentHandler >& xConfig ) + : m_xConfig (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 + ::comphelper::AttributeList* pAttribs = new ::comphelper::AttributeList; + css::uno::Reference< css::xml::sax::XAttributeList > xAttribs(static_cast< css::xml::sax::XAttributeList* >(pAttribs), css::uno::UNO_QUERY); + + 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, xAttribs); + 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 ) +{ + ::comphelper::AttributeList* pAttribs = new ::comphelper::AttributeList; + css::uno::Reference< css::xml::sax::XAttributeList > xAttribs (static_cast< css::xml::sax::XAttributeList* >(pAttribs) , css::uno::UNO_QUERY_THROW); + + 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, xAttribs); + 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..5c31414c7 --- /dev/null +++ b/framework/source/xml/imagesconfiguration.cxx @@ -0,0 +1,107 @@ +/* -*- 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..51352b029 --- /dev/null +++ b/framework/source/xml/imagesdocumenthandler.cxx @@ -0,0 +1,386 @@ +/* -*- 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 <vcl/svapp.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" + +#define ELEMENT_NS_IMAGESCONTAINER "image:imagescontainer" +#define ELEMENT_NS_IMAGES "image:images" +#define ELEMENT_NS_ENTRY "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" +#define ATTRIBUTE_TYPE_CDATA "CDATA" + +#define ATTRIBUTE_XMLNS_IMAGE "xmlns:image" +#define ATTRIBUTE_XMLNS_XLINK "xmlns:xlink" + +#define ATTRIBUTE_XLINK_TYPE "xlink:type" +#define ATTRIBUTE_XLINK_TYPE_VALUE "simple" + +#define XMLNS_IMAGE "http://openoffice.org/2001/image" +#define XMLNS_XLINK "http://www.w3.org/1999/xlink" +#define XMLNS_IMAGE_PREFIX "image:" + +#define XMLNS_FILTER_SEPARATOR "^" + +#define IMAGES_DOCTYPE "<!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 < int(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() +{ + SolarMutexGuard g; + + 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 ) +{ + SolarMutexGuard g; + + 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) +{ + SolarMutexGuard g; + + 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) +{ + SolarMutexGuard g; + m_xLocator = xLocator; +} + +OUString OReadImagesDocumentHandler::getErrorLineString() +{ + SolarMutexGuard g; + if ( m_xLocator.is() ) + { + OUStringBuffer buffer("Line: "); + buffer.append(m_xLocator->getLineNumber()); + buffer.append(" - "); + return buffer.makeStringAndClear(); + } + else + return OUString(); +} + +// OWriteImagesDocumentHandler + +OWriteImagesDocumentHandler::OWriteImagesDocumentHandler( + const ImageItemDescriptorList& rItems, + Reference< XDocumentHandler > const & rWriteDocumentHandler ) : + m_rImageItemList( rItems ), + m_xWriteDocumentHandler( rWriteDocumentHandler ) +{ + ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; + m_xEmptyList.set( static_cast<XAttributeList *>(pList), UNO_QUERY ); + 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() +{ + SolarMutexGuard g; + + 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.get() ); + 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 ) +{ + ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; + Reference< XAttributeList > xList( static_cast<XAttributeList *>(pList) , UNO_QUERY ); + + // save required attributes + pList->AddAttribute( m_aAttributeXlinkType, + m_aAttributeType, + m_aAttributeValueSimple ); + + m_xWriteDocumentHandler->startElement( ELEMENT_NS_IMAGES, xList ); + 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 ) +{ + ::comphelper::AttributeList* pList = new ::comphelper::AttributeList; + Reference< XAttributeList > xList( static_cast<XAttributeList *>(pList) , UNO_QUERY ); + + pList->AddAttribute( m_aXMLImageNS + ATTRIBUTE_COMMAND, + m_aAttributeType, + pImage->aCommandURL ); + + m_xWriteDocumentHandler->startElement( ELEMENT_NS_ENTRY, xList ); + m_xWriteDocumentHandler->ignorableWhitespace( OUString() ); + + m_xWriteDocumentHandler->endElement( ELEMENT_NS_ENTRY ); + m_xWriteDocumentHandler->ignorableWhitespace( OUString() ); +} + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |