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