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 formatted 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 occurred) 59 to format a suitable message. 60 61 @param COMMENT 62 an ascii string, which describes 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 { 100 } 101 102 //----------------------------------------------- 103 void SAL_CALL AcceleratorConfigurationReader::endDocument() 104 { 105 // The xml file seems to be corrupted. 106 // Because we found no end-tags... at least for 107 // one list or item. 108 if ( 109 (m_bInsideAcceleratorList) || 110 (m_bInsideAcceleratorItem) 111 ) 112 { 113 THROW_PARSEEXCEPTION("No matching start or end element 'acceleratorlist' found!") 114 } 115 } 116 117 //----------------------------------------------- 118 void SAL_CALL AcceleratorConfigurationReader::startElement(const ::rtl::OUString& sElement , 119 const css::uno::Reference< css::xml::sax::XAttributeList >& xAttributeList) 120 { 121 EXMLElement eElement = AcceleratorConfigurationReader::implst_classifyElement(sElement); 122 123 // Note: We handle "accel:item" before "accel:acceleratorlist" to perform this operation. 124 // Because an item occurs very often... a list should occur one time only! 125 if (eElement == E_ELEMENT_ITEM) 126 { 127 if (!m_bInsideAcceleratorList) 128 THROW_PARSEEXCEPTION("An element \"accel:item\" must be embedded into 'accel:acceleratorlist'.") 129 if (m_bInsideAcceleratorItem) 130 THROW_PARSEEXCEPTION("An element \"accel:item\" is not a container.") 131 m_bInsideAcceleratorItem = sal_True; 132 133 ::rtl::OUString sCommand; 134 css::awt::KeyEvent aEvent ; 135 136 sal_Int16 c = xAttributeList->getLength(); 137 sal_Int16 i = 0; 138 for (i=0; i<c; ++i) 139 { 140 ::rtl::OUString sAttribute = xAttributeList->getNameByIndex(i); 141 ::rtl::OUString sValue = xAttributeList->getValueByIndex(i); 142 EXMLAttribute eAttribute = AcceleratorConfigurationReader::implst_classifyAttribute(sAttribute); 143 switch(eAttribute) 144 { 145 case E_ATTRIBUTE_URL : 146 sCommand = sValue.intern(); 147 break; 148 149 case E_ATTRIBUTE_KEYCODE : 150 aEvent.KeyCode = m_rKeyMapping->mapIdentifierToCode(sValue); 151 break; 152 153 case E_ATTRIBUTE_MOD_SHIFT : 154 aEvent.Modifiers |= css::awt::KeyModifier::SHIFT; 155 break; 156 157 case E_ATTRIBUTE_MOD_MOD1 : 158 aEvent.Modifiers |= css::awt::KeyModifier::MOD1; 159 break; 160 161 case E_ATTRIBUTE_MOD_MOD2 : 162 aEvent.Modifiers |= css::awt::KeyModifier::MOD2; 163 break; 164 165 case E_ATTRIBUTE_MOD_MOD3 : 166 aEvent.Modifiers |= css::awt::KeyModifier::MOD3; 167 } 168 } 169 170 // validate command and key event. 171 if ( 172 (!sCommand.getLength()) || 173 (aEvent.KeyCode == 0 ) 174 ) 175 { 176 THROW_PARSEEXCEPTION("XML element does not describe a valid accelerator nor a valid command.") 177 } 178 179 // register key event + command inside cache... 180 // Check for already existing items there. 181 if (!m_rContainer.hasKey(aEvent)) 182 m_rContainer.setKeyCommandPair(aEvent, sCommand); 183 #ifdef ENABLE_WARNINGS 184 else 185 { 186 // Attention: It's not really a reason to throw an exception and kill the office, if the configuration contains 187 // multiple registrations for the same key :-) Show a warning... and ignore the second item. 188 // THROW_PARSEEXCEPTION("Command is registered for the same key more than once.") 189 ::rtl::OUStringBuffer sMsg(256); 190 sMsg.appendAscii("Double registration detected.\nCommand = \""); 191 sMsg.append (sCommand ); 192 sMsg.appendAscii("\"\nKeyCode = " ); 193 sMsg.append ((sal_Int32)aEvent.KeyCode ); 194 sMsg.appendAscii("\nModifiers = " ); 195 sMsg.append ((sal_Int32)aEvent.Modifiers ); 196 sMsg.appendAscii("\nIgnore this item!" ); 197 LOG_WARNING("AcceleratorConfigurationReader::startElement()", U2B(sMsg.makeStringAndClear())) 198 } 199 #endif // ENABLE_WARNINGS 200 } 201 202 if (eElement == E_ELEMENT_ACCELERATORLIST) 203 { 204 if (m_bInsideAcceleratorList) 205 THROW_PARSEEXCEPTION("An element \"accel:acceleratorlist\" cannot be used recursive.") 206 m_bInsideAcceleratorList = sal_True; 207 return; 208 } 209 } 210 211 //----------------------------------------------- 212 void SAL_CALL AcceleratorConfigurationReader::endElement(const ::rtl::OUString& sElement) 213 { 214 EXMLElement eElement = AcceleratorConfigurationReader::implst_classifyElement(sElement); 215 216 // Note: We handle "accel:item" before "accel:acceleratorlist" to perform this operation. 217 // Because an item occurs very often... a list should occur one time only! 218 if (eElement == E_ELEMENT_ITEM) 219 { 220 if (!m_bInsideAcceleratorItem) 221 THROW_PARSEEXCEPTION("Found end element 'accel:item', but no start element.") 222 m_bInsideAcceleratorItem = sal_False; 223 } 224 225 if (eElement == E_ELEMENT_ACCELERATORLIST) 226 { 227 if (!m_bInsideAcceleratorList) 228 THROW_PARSEEXCEPTION("Found end element 'accel:acceleratorlist', but no start element.") 229 m_bInsideAcceleratorList = sal_False; 230 } 231 } 232 233 //----------------------------------------------- 234 void SAL_CALL AcceleratorConfigurationReader::characters(const ::rtl::OUString&) 235 { 236 } 237 238 //----------------------------------------------- 239 void SAL_CALL AcceleratorConfigurationReader::ignorableWhitespace(const ::rtl::OUString&) 240 { 241 } 242 243 //----------------------------------------------- 244 void SAL_CALL AcceleratorConfigurationReader::processingInstruction(const ::rtl::OUString& /*sTarget*/, 245 const ::rtl::OUString& /*sData*/ ) 246 { 247 } 248 249 //----------------------------------------------- 250 void SAL_CALL AcceleratorConfigurationReader::setDocumentLocator(const css::uno::Reference< css::xml::sax::XLocator >& xLocator) 251 { 252 m_xLocator = xLocator; 253 } 254 255 //----------------------------------------------- 256 AcceleratorConfigurationReader::EXMLElement AcceleratorConfigurationReader::implst_classifyElement(const ::rtl::OUString& sElement) 257 { 258 AcceleratorConfigurationReader::EXMLElement eElement; 259 260 if (sElement.equals(NS_ELEMENT_ACCELERATORLIST)) 261 eElement = E_ELEMENT_ACCELERATORLIST; 262 else 263 if (sElement.equals(NS_ELEMENT_ITEM)) 264 eElement = E_ELEMENT_ITEM; 265 else 266 throw css::uno::RuntimeException( 267 DECLARE_ASCII("Unknown XML element detected!"), 268 css::uno::Reference< css::xml::sax::XDocumentHandler >()); 269 270 return eElement; 271 } 272 273 //----------------------------------------------- 274 AcceleratorConfigurationReader::EXMLAttribute AcceleratorConfigurationReader::implst_classifyAttribute(const ::rtl::OUString& sAttribute) 275 { 276 AcceleratorConfigurationReader::EXMLAttribute eAttribute; 277 278 if (sAttribute.equals(NS_ATTRIBUTE_KEYCODE)) 279 eAttribute = E_ATTRIBUTE_KEYCODE; 280 else 281 if (sAttribute.equals(NS_ATTRIBUTE_MOD_SHIFT)) 282 eAttribute = E_ATTRIBUTE_MOD_SHIFT; 283 else 284 if (sAttribute.equals(NS_ATTRIBUTE_MOD_MOD1)) 285 eAttribute = E_ATTRIBUTE_MOD_MOD1; 286 else 287 if (sAttribute.equals(NS_ATTRIBUTE_MOD_MOD2)) 288 eAttribute = E_ATTRIBUTE_MOD_MOD2; 289 else 290 if (sAttribute.equals(NS_ATTRIBUTE_MOD_MOD3)) 291 eAttribute = E_ATTRIBUTE_MOD_MOD3; 292 else 293 if (sAttribute.equals(NS_ATTRIBUTE_URL)) 294 eAttribute = E_ATTRIBUTE_URL; 295 else 296 throw css::uno::RuntimeException( 297 DECLARE_ASCII("Unknown XML attribute detected!"), 298 css::uno::Reference< css::xml::sax::XDocumentHandler >()); 299 300 return eAttribute; 301 } 302 303 //----------------------------------------------- 304 ::rtl::OUString AcceleratorConfigurationReader::implts_getErrorLineString() 305 { 306 if (!m_xLocator.is()) 307 return DECLARE_ASCII("Error during parsing XML. (No further info available...)"); 308 309 ::rtl::OUStringBuffer sMsg(256); 310 sMsg.appendAscii("Error during parsing XML in\nline = "); 311 sMsg.append (m_xLocator->getLineNumber() ); 312 sMsg.appendAscii("\ncolumn = " ); 313 sMsg.append (m_xLocator->getColumnNumber() ); 314 sMsg.appendAscii("." ); 315 return sMsg.makeStringAndClear(); 316 } 317 318 } // namespace framework 319