/************************************************************************* * * $RCSfile: acceleratorconfigurationreader.cxx,v $ * * $Revision: 1.2 $ * * last change: $Author: rt $ $Date: 2004-09-20 10:09:32 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses * * - GNU Lesser General Public License Version 2.1 * - Sun Industry Standards Source License Version 1.1 * * Sun Microsystems Inc., October, 2000 * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2000 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 * * * Sun Industry Standards Source License Version 1.1 * ================================================= * The contents of this file are subject to the Sun Industry Standards * Source License Version 1.1 (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.openoffice.org/license.html. * * Software provided under this License is provided on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. * See the License for the specific provisions governing your rights and * obligations concerning the Software. * * The Initial Developer of the Original Code is: Sun Microsystems, Inc. * * Copyright: 2000 by Sun Microsystems, Inc. * * All Rights Reserved. * * Contributor(s): _______________________________________ * * ************************************************************************/ #ifndef _FRAMEWORK_XML_ACCELERATORCONFIGURATIONREADER_HXX_ #include #endif //_______________________________________________ // own includes #ifndef __FRAMEWORK_ACCELERATORCONST_H_ #include #endif //_______________________________________________ // interface includes #ifndef _COM_SUN_STAR_XML_SAX_XEXTENDEDDOCUMENTHANDLER_HPP_ #include #endif #ifndef _COM_SUN_STAR_AWT_KEYMODIFIER_HPP_ #include #endif #ifndef _COM_SUN_STAR_AWT_KEYEVENT_HPP_ #include #endif #ifndef _COM_SUN_STAR_AWT_KEY_HPP_ #include #endif #ifndef _COM_SUN_STAR_CONTAINER_ELEMENTEXISTEXCEPTION_HPP_ #include #endif //_______________________________________________ // other includes #ifndef _SV_SVAPP_HXX #include #endif #ifndef _RTL_USTRBUF_HXX_ #include #endif //_______________________________________________ // namespace namespace framework{ //----------------------------------------------- /* Throws a SaxException in case a wrong formated XML structure was detected. This macro combined the given comment with a generic way to find out the XML line (where the error occured) to format a suitable message. @param COMMENT an ascii string, which describe the problem. */ #define THROW_PARSEEXCEPTION(COMMENT) \ { \ ::rtl::OUStringBuffer sMessage(256); \ sMessage.append (implts_getErrorLineString()); \ sMessage.appendAscii(COMMENT ); \ \ throw css::xml::sax::SAXException( \ sMessage.makeStringAndClear(), \ static_cast< css::xml::sax::XDocumentHandler* >(this), \ css::uno::Any()); \ } //----------------------------------------------- // XInterface DEFINE_XINTERFACE_1(AcceleratorConfigurationReader , OWeakObject , DIRECT_INTERFACE(css::xml::sax::XDocumentHandler)) //----------------------------------------------- AcceleratorConfigurationReader::AcceleratorConfigurationReader(AcceleratorCache& rContainer) : ThreadHelpBase (&Application::GetSolarMutex()) , OWeakObject ( ) , m_rContainer (rContainer ) , m_bInsideAcceleratorList(sal_False ) , m_bInsideAcceleratorItem(sal_False ) { } //----------------------------------------------- AcceleratorConfigurationReader::~AcceleratorConfigurationReader() { } //----------------------------------------------- void SAL_CALL AcceleratorConfigurationReader::startDocument() throw(css::xml::sax::SAXException, css::uno::RuntimeException ) { } //----------------------------------------------- void SAL_CALL AcceleratorConfigurationReader::endDocument() throw(css::xml::sax::SAXException, css::uno::RuntimeException ) { // 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 ::rtl::OUString& sElement , const css::uno::Reference< css::xml::sax::XAttributeList >& xAttributeList) throw(css::xml::sax::SAXException, css::uno::RuntimeException ) { EXMLElement eElement = AcceleratorConfigurationReader::implst_classifyElement(sElement); // Note: We handle "accel:item" before "accel:acceleratorlist" to perform this operation. // Because an item occures very often ... a list should occure one times only! if (eElement == E_ELEMENT_ITEM) { if (!m_bInsideAcceleratorList) THROW_PARSEEXCEPTION("An element \"accel:item\" must be embeded into 'accel:acceleratorlist'.") if (m_bInsideAcceleratorItem) THROW_PARSEEXCEPTION("An element \"accel:item\" is not a container.") m_bInsideAcceleratorItem = sal_True; ::rtl::OUString sCommand; css::awt::KeyEvent aEvent ; sal_Int16 c = xAttributeList->getLength(); sal_Int16 i = 0; for (i=0; igetNameByIndex(i); ::rtl::OUString sValue = xAttributeList->getValueByIndex(i); EXMLAttribute eAttribute = AcceleratorConfigurationReader::implst_classifyAttribute(sAttribute); switch(eAttribute) { case E_ATTRIBUTE_URL : sCommand = sValue; break; case E_ATTRIBUTE_KEYCODE : aEvent.KeyCode = m_rKeyMapping->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; } } // validate command and key event. if ( (!sCommand.getLength()) || (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); #ifdef ENABLE_WARNINGS else { // Attention: Its not realy 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 then once.") ::rtl::OUStringBuffer sMsg(256); sMsg.appendAscii("Double registration detected.\nCommand = \""); sMsg.append (sCommand ); sMsg.appendAscii("\"\nKeyCode = " ); sMsg.append ((sal_Int32)aEvent.KeyCode ); sMsg.appendAscii("\nModifiers = " ); sMsg.append ((sal_Int32)aEvent.Modifiers ); sMsg.appendAscii("\nIgnore this item!" ); LOG_WARNING("AcceleratorConfigurationReader::startElement()", U2B(sMsg.makeStringAndClear())) } #endif // ENABLE_WARNINGS } if (eElement == E_ELEMENT_ACCELERATORLIST) { if (m_bInsideAcceleratorList) THROW_PARSEEXCEPTION("An element \"accel:acceleratorlist\" cannot be used recursive.") m_bInsideAcceleratorList = sal_True; return; } } //----------------------------------------------- void SAL_CALL AcceleratorConfigurationReader::endElement(const ::rtl::OUString& sElement) throw(css::xml::sax::SAXException, css::uno::RuntimeException ) { EXMLElement eElement = AcceleratorConfigurationReader::implst_classifyElement(sElement); // Note: We handle "accel:item" before "accel:acceleratorlist" to perform this operation. // Because an item occures very often ... a list should occure one times only! if (eElement == E_ELEMENT_ITEM) { if (!m_bInsideAcceleratorItem) THROW_PARSEEXCEPTION("Found end element 'accel:item', but no start element.") m_bInsideAcceleratorItem = sal_False; } if (eElement == E_ELEMENT_ACCELERATORLIST) { if (!m_bInsideAcceleratorList) THROW_PARSEEXCEPTION("Found end element 'accel:acceleratorlist', but no start element.") m_bInsideAcceleratorList = sal_False; } } //----------------------------------------------- void SAL_CALL AcceleratorConfigurationReader::characters(const ::rtl::OUString& sChars) throw(css::xml::sax::SAXException, css::uno::RuntimeException ) { } //----------------------------------------------- void SAL_CALL AcceleratorConfigurationReader::ignorableWhitespace(const ::rtl::OUString& sWhitespaces) throw(css::xml::sax::SAXException, css::uno::RuntimeException ) { } //----------------------------------------------- void SAL_CALL AcceleratorConfigurationReader::processingInstruction(const ::rtl::OUString& sTarget, const ::rtl::OUString& sData ) throw(css::xml::sax::SAXException, css::uno::RuntimeException ) { } //----------------------------------------------- void SAL_CALL AcceleratorConfigurationReader::setDocumentLocator(const css::uno::Reference< css::xml::sax::XLocator >& xLocator) throw(css::xml::sax::SAXException, css::uno::RuntimeException ) { m_xLocator = xLocator; } //----------------------------------------------- AcceleratorConfigurationReader::EXMLElement AcceleratorConfigurationReader::implst_classifyElement(const ::rtl::OUString& sElement) { AcceleratorConfigurationReader::EXMLElement eElement; if (sElement.equals(NS_ELEMENT_ACCELERATORLIST)) eElement = E_ELEMENT_ACCELERATORLIST; else if (sElement.equals(NS_ELEMENT_ITEM)) eElement = E_ELEMENT_ITEM; else throw css::uno::RuntimeException( DECLARE_ASCII("Unknown XML element detected!"), css::uno::Reference< css::xml::sax::XDocumentHandler >()); return eElement; } //----------------------------------------------- AcceleratorConfigurationReader::EXMLAttribute AcceleratorConfigurationReader::implst_classifyAttribute(const ::rtl::OUString& sAttribute) { AcceleratorConfigurationReader::EXMLAttribute eAttribute; if (sAttribute.equals(NS_ATTRIBUTE_KEYCODE)) eAttribute = E_ATTRIBUTE_KEYCODE; else if (sAttribute.equals(NS_ATTRIBUTE_MOD_SHIFT)) eAttribute = E_ATTRIBUTE_MOD_SHIFT; else if (sAttribute.equals(NS_ATTRIBUTE_MOD_MOD1)) eAttribute = E_ATTRIBUTE_MOD_MOD1; else if (sAttribute.equals(NS_ATTRIBUTE_MOD_MOD2)) eAttribute = E_ATTRIBUTE_MOD_MOD2; else if (sAttribute.equals(NS_ATTRIBUTE_URL)) eAttribute = E_ATTRIBUTE_URL; else throw css::uno::RuntimeException( DECLARE_ASCII("Unknown XML attribute detected!"), css::uno::Reference< css::xml::sax::XDocumentHandler >()); return eAttribute; } //----------------------------------------------- ::rtl::OUString AcceleratorConfigurationReader::implts_getErrorLineString() { if (!m_xLocator.is()) return DECLARE_ASCII("Error during parsing XML. (No further info available ...)"); ::rtl::OUStringBuffer sMsg(256); sMsg.appendAscii("Error during parsing XML in\nline = "); sMsg.append (m_xLocator->getLineNumber() ); sMsg.appendAscii("\ncolumn = " ); sMsg.append (m_xLocator->getColumnNumber() ); sMsg.appendAscii("." ); return sMsg.makeStringAndClear(); } } // namespace framework