1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_framework.hxx" 30 #include <xml/acceleratorconfigurationreader.hxx> 31 32 //_______________________________________________ 33 // own includes 34 35 #ifndef __FRAMEWORK_ACCELERATORCONST_H_ 36 #include <acceleratorconst.h> 37 #endif 38 39 //_______________________________________________ 40 // interface includes 41 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp> 42 #include <com/sun/star/awt/KeyModifier.hpp> 43 #include <com/sun/star/awt/KeyEvent.hpp> 44 #include <com/sun/star/awt/Key.hpp> 45 #include <com/sun/star/container/ElementExistException.hpp> 46 47 //_______________________________________________ 48 // other includes 49 #include <vcl/svapp.hxx> 50 #include <rtl/ustrbuf.hxx> 51 52 //_______________________________________________ 53 // namespace 54 55 namespace framework{ 56 57 //----------------------------------------------- 58 /* Throws a SaxException in case a wrong formated XML 59 structure was detected. 60 61 This macro combined the given comment with a generic 62 way to find out the XML line (where the error occured) 63 to format a suitable message. 64 65 @param COMMENT 66 an ascii string, which describe the problem. 67 */ 68 #define THROW_PARSEEXCEPTION(COMMENT) \ 69 { \ 70 ::rtl::OUStringBuffer sMessage(256); \ 71 sMessage.append (implts_getErrorLineString()); \ 72 sMessage.appendAscii(COMMENT ); \ 73 \ 74 throw css::xml::sax::SAXException( \ 75 sMessage.makeStringAndClear(), \ 76 static_cast< css::xml::sax::XDocumentHandler* >(this), \ 77 css::uno::Any()); \ 78 } 79 80 //----------------------------------------------- 81 // XInterface 82 DEFINE_XINTERFACE_1(AcceleratorConfigurationReader , 83 OWeakObject , 84 DIRECT_INTERFACE(css::xml::sax::XDocumentHandler)) 85 86 //----------------------------------------------- 87 AcceleratorConfigurationReader::AcceleratorConfigurationReader(AcceleratorCache& rContainer) 88 : ThreadHelpBase (&Application::GetSolarMutex()) 89 , OWeakObject ( ) 90 , m_rContainer (rContainer ) 91 , m_bInsideAcceleratorList(sal_False ) 92 , m_bInsideAcceleratorItem(sal_False ) 93 { 94 } 95 96 //----------------------------------------------- 97 AcceleratorConfigurationReader::~AcceleratorConfigurationReader() 98 { 99 } 100 101 //----------------------------------------------- 102 void SAL_CALL AcceleratorConfigurationReader::startDocument() 103 throw(css::xml::sax::SAXException, 104 css::uno::RuntimeException ) 105 { 106 } 107 108 //----------------------------------------------- 109 void SAL_CALL AcceleratorConfigurationReader::endDocument() 110 throw(css::xml::sax::SAXException, 111 css::uno::RuntimeException ) 112 { 113 // The xml file seems to be corrupted. 114 // Because we found no end-tags ... at least for 115 // one list or item. 116 if ( 117 (m_bInsideAcceleratorList) || 118 (m_bInsideAcceleratorItem) 119 ) 120 { 121 THROW_PARSEEXCEPTION("No matching start or end element 'acceleratorlist' found!") 122 } 123 } 124 125 //----------------------------------------------- 126 void SAL_CALL AcceleratorConfigurationReader::startElement(const ::rtl::OUString& sElement , 127 const css::uno::Reference< css::xml::sax::XAttributeList >& xAttributeList) 128 throw(css::xml::sax::SAXException, 129 css::uno::RuntimeException ) 130 { 131 EXMLElement eElement = AcceleratorConfigurationReader::implst_classifyElement(sElement); 132 133 // Note: We handle "accel:item" before "accel:acceleratorlist" to perform this operation. 134 // Because an item occures very often ... a list should occure one times only! 135 if (eElement == E_ELEMENT_ITEM) 136 { 137 if (!m_bInsideAcceleratorList) 138 THROW_PARSEEXCEPTION("An element \"accel:item\" must be embeded into 'accel:acceleratorlist'.") 139 if (m_bInsideAcceleratorItem) 140 THROW_PARSEEXCEPTION("An element \"accel:item\" is not a container.") 141 m_bInsideAcceleratorItem = sal_True; 142 143 ::rtl::OUString sCommand; 144 css::awt::KeyEvent aEvent ; 145 146 sal_Int16 c = xAttributeList->getLength(); 147 sal_Int16 i = 0; 148 for (i=0; i<c; ++i) 149 { 150 ::rtl::OUString sAttribute = xAttributeList->getNameByIndex(i); 151 ::rtl::OUString sValue = xAttributeList->getValueByIndex(i); 152 EXMLAttribute eAttribute = AcceleratorConfigurationReader::implst_classifyAttribute(sAttribute); 153 switch(eAttribute) 154 { 155 case E_ATTRIBUTE_URL : 156 sCommand = sValue.intern(); 157 break; 158 159 case E_ATTRIBUTE_KEYCODE : 160 aEvent.KeyCode = m_rKeyMapping->mapIdentifierToCode(sValue); 161 break; 162 163 case E_ATTRIBUTE_MOD_SHIFT : 164 aEvent.Modifiers |= css::awt::KeyModifier::SHIFT; 165 break; 166 167 case E_ATTRIBUTE_MOD_MOD1 : 168 aEvent.Modifiers |= css::awt::KeyModifier::MOD1; 169 break; 170 171 case E_ATTRIBUTE_MOD_MOD2 : 172 aEvent.Modifiers |= css::awt::KeyModifier::MOD2; 173 break; 174 175 case E_ATTRIBUTE_MOD_MOD3 : 176 aEvent.Modifiers |= css::awt::KeyModifier::MOD3; 177 } 178 } 179 180 // validate command and key event. 181 if ( 182 (!sCommand.getLength()) || 183 (aEvent.KeyCode == 0 ) 184 ) 185 { 186 THROW_PARSEEXCEPTION("XML element does not describe a valid accelerator nor a valid command.") 187 } 188 189 // register key event + command inside cache ... 190 // Check for already existing items there. 191 if (!m_rContainer.hasKey(aEvent)) 192 m_rContainer.setKeyCommandPair(aEvent, sCommand); 193 #ifdef ENABLE_WARNINGS 194 else 195 { 196 // Attention: Its not realy a reason to throw an exception and kill the office, if the configuration contains 197 // multiple registrations for the same key :-) Show a warning ... and ignore the second item. 198 // THROW_PARSEEXCEPTION("Command is registered for the same key more then once.") 199 ::rtl::OUStringBuffer sMsg(256); 200 sMsg.appendAscii("Double registration detected.\nCommand = \""); 201 sMsg.append (sCommand ); 202 sMsg.appendAscii("\"\nKeyCode = " ); 203 sMsg.append ((sal_Int32)aEvent.KeyCode ); 204 sMsg.appendAscii("\nModifiers = " ); 205 sMsg.append ((sal_Int32)aEvent.Modifiers ); 206 sMsg.appendAscii("\nIgnore this item!" ); 207 LOG_WARNING("AcceleratorConfigurationReader::startElement()", U2B(sMsg.makeStringAndClear())) 208 } 209 #endif // ENABLE_WARNINGS 210 } 211 212 if (eElement == E_ELEMENT_ACCELERATORLIST) 213 { 214 if (m_bInsideAcceleratorList) 215 THROW_PARSEEXCEPTION("An element \"accel:acceleratorlist\" cannot be used recursive.") 216 m_bInsideAcceleratorList = sal_True; 217 return; 218 } 219 } 220 221 //----------------------------------------------- 222 void SAL_CALL AcceleratorConfigurationReader::endElement(const ::rtl::OUString& sElement) 223 throw(css::xml::sax::SAXException, 224 css::uno::RuntimeException ) 225 { 226 EXMLElement eElement = AcceleratorConfigurationReader::implst_classifyElement(sElement); 227 228 // Note: We handle "accel:item" before "accel:acceleratorlist" to perform this operation. 229 // Because an item occures very often ... a list should occure one times only! 230 if (eElement == E_ELEMENT_ITEM) 231 { 232 if (!m_bInsideAcceleratorItem) 233 THROW_PARSEEXCEPTION("Found end element 'accel:item', but no start element.") 234 m_bInsideAcceleratorItem = sal_False; 235 } 236 237 if (eElement == E_ELEMENT_ACCELERATORLIST) 238 { 239 if (!m_bInsideAcceleratorList) 240 THROW_PARSEEXCEPTION("Found end element 'accel:acceleratorlist', but no start element.") 241 m_bInsideAcceleratorList = sal_False; 242 } 243 } 244 245 //----------------------------------------------- 246 void SAL_CALL AcceleratorConfigurationReader::characters(const ::rtl::OUString&) 247 throw(css::xml::sax::SAXException, 248 css::uno::RuntimeException ) 249 { 250 } 251 252 //----------------------------------------------- 253 void SAL_CALL AcceleratorConfigurationReader::ignorableWhitespace(const ::rtl::OUString&) 254 throw(css::xml::sax::SAXException, 255 css::uno::RuntimeException ) 256 { 257 } 258 259 //----------------------------------------------- 260 void SAL_CALL AcceleratorConfigurationReader::processingInstruction(const ::rtl::OUString& /*sTarget*/, 261 const ::rtl::OUString& /*sData*/ ) 262 throw(css::xml::sax::SAXException, 263 css::uno::RuntimeException ) 264 { 265 } 266 267 //----------------------------------------------- 268 void SAL_CALL AcceleratorConfigurationReader::setDocumentLocator(const css::uno::Reference< css::xml::sax::XLocator >& xLocator) 269 throw(css::xml::sax::SAXException, 270 css::uno::RuntimeException ) 271 { 272 m_xLocator = xLocator; 273 } 274 275 //----------------------------------------------- 276 AcceleratorConfigurationReader::EXMLElement AcceleratorConfigurationReader::implst_classifyElement(const ::rtl::OUString& sElement) 277 { 278 AcceleratorConfigurationReader::EXMLElement eElement; 279 280 if (sElement.equals(NS_ELEMENT_ACCELERATORLIST)) 281 eElement = E_ELEMENT_ACCELERATORLIST; 282 else 283 if (sElement.equals(NS_ELEMENT_ITEM)) 284 eElement = E_ELEMENT_ITEM; 285 else 286 throw css::uno::RuntimeException( 287 DECLARE_ASCII("Unknown XML element detected!"), 288 css::uno::Reference< css::xml::sax::XDocumentHandler >()); 289 290 return eElement; 291 } 292 293 //----------------------------------------------- 294 AcceleratorConfigurationReader::EXMLAttribute AcceleratorConfigurationReader::implst_classifyAttribute(const ::rtl::OUString& sAttribute) 295 { 296 AcceleratorConfigurationReader::EXMLAttribute eAttribute; 297 298 if (sAttribute.equals(NS_ATTRIBUTE_KEYCODE)) 299 eAttribute = E_ATTRIBUTE_KEYCODE; 300 else 301 if (sAttribute.equals(NS_ATTRIBUTE_MOD_SHIFT)) 302 eAttribute = E_ATTRIBUTE_MOD_SHIFT; 303 else 304 if (sAttribute.equals(NS_ATTRIBUTE_MOD_MOD1)) 305 eAttribute = E_ATTRIBUTE_MOD_MOD1; 306 else 307 if (sAttribute.equals(NS_ATTRIBUTE_MOD_MOD2)) 308 eAttribute = E_ATTRIBUTE_MOD_MOD2; 309 else 310 if (sAttribute.equals(NS_ATTRIBUTE_MOD_MOD3)) 311 eAttribute = E_ATTRIBUTE_MOD_MOD3; 312 else 313 if (sAttribute.equals(NS_ATTRIBUTE_URL)) 314 eAttribute = E_ATTRIBUTE_URL; 315 else 316 throw css::uno::RuntimeException( 317 DECLARE_ASCII("Unknown XML attribute detected!"), 318 css::uno::Reference< css::xml::sax::XDocumentHandler >()); 319 320 return eAttribute; 321 } 322 323 //----------------------------------------------- 324 ::rtl::OUString AcceleratorConfigurationReader::implts_getErrorLineString() 325 { 326 if (!m_xLocator.is()) 327 return DECLARE_ASCII("Error during parsing XML. (No further info available ...)"); 328 329 ::rtl::OUStringBuffer sMsg(256); 330 sMsg.appendAscii("Error during parsing XML in\nline = "); 331 sMsg.append (m_xLocator->getLineNumber() ); 332 sMsg.appendAscii("\ncolumn = " ); 333 sMsg.append (m_xLocator->getColumnNumber() ); 334 sMsg.appendAscii("." ); 335 return sMsg.makeStringAndClear(); 336 } 337 338 } // namespace framework 339