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_unotools.hxx"
30 
31 #include <unotools/xmlaccelcfg.hxx>
32 
33 #include <vector>
34 #include <com/sun/star/xml/sax/XAttributeList.hpp>
35 #include <cppuhelper/implbase1.hxx>
36 
37 using namespace rtl;
38 using namespace com::sun::star::uno;
39 using namespace com::sun::star::xml::sax;
40 
41 #define	ELEMENT_ACCELERATORLIST		"acceleratorlist"
42 #define ELEMENT_ACCELERATORITEM		"item"
43 
44 #define ATTRIBUTE_KEYCODE			"code"
45 #define ATTRIBUTE_MODIFIER			"modifier"
46 #define ATTRIBUTE_URL				"url"
47 
48 #define ATTRIBUTE_TYPE_CDATA		"CDATA"
49 
50 // ------------------------------------------------------------------
51 
52 struct AttributeListImpl_impl;
53 class AttributeListImpl : public ::cppu::WeakImplHelper1< ::com::sun::star::xml::sax::XAttributeList >
54 {
55 protected:
56 	~AttributeListImpl();
57 
58 public:
59 	AttributeListImpl();
60 	AttributeListImpl( const AttributeListImpl & );
61 
62 public:
63     virtual sal_Int16 SAL_CALL getLength(void) throw (::com::sun::star::uno::RuntimeException);
64     virtual ::rtl::OUString  SAL_CALL getNameByIndex(sal_Int16 i) throw (::com::sun::star::uno::RuntimeException);
65     virtual ::rtl::OUString  SAL_CALL getTypeByIndex(sal_Int16 i) throw (::com::sun::star::uno::RuntimeException);
66     virtual ::rtl::OUString  SAL_CALL getTypeByName(const ::rtl::OUString& aName) throw (::com::sun::star::uno::RuntimeException);
67     virtual ::rtl::OUString  SAL_CALL getValueByIndex(sal_Int16 i) throw (::com::sun::star::uno::RuntimeException);
68     virtual ::rtl::OUString  SAL_CALL getValueByName(const ::rtl::OUString& aName) throw (::com::sun::star::uno::RuntimeException);
69 
70 public:
71 	void addAttribute( const ::rtl::OUString &sName , const ::rtl::OUString &sType , const ::rtl::OUString &sValue );
72 	void clear();
73 
74 private:
75 	struct AttributeListImpl_impl *m_pImpl;
76 };
77 
78 struct TagAttribute
79 {
80 	TagAttribute(){}
81 	TagAttribute( const OUString &aName, const OUString &aType , const OUString &aValue )
82 	{
83 		sName 	= aName;
84 		sType 	= aType;
85 		sValue 	= aValue;
86 	}
87 
88 	OUString sName;
89 	OUString sType;
90 	OUString sValue;
91 };
92 
93 struct AttributeListImpl_impl
94 {
95 	AttributeListImpl_impl()
96 	{
97 		// performance improvement during adding
98 		vecAttribute.reserve(20);
99 	}
100 	::std::vector<struct TagAttribute> vecAttribute;
101 };
102 
103 
104 
105 sal_Int16 SAL_CALL AttributeListImpl::getLength(void) throw (RuntimeException)
106 {
107 	return sal::static_int_cast< sal_Int16 >(m_pImpl->vecAttribute.size());
108 }
109 
110 
111 AttributeListImpl::AttributeListImpl( const AttributeListImpl &r ) :
112     cppu::WeakImplHelper1<com::sun::star::xml::sax::XAttributeList>(r)
113 {
114 	m_pImpl = new AttributeListImpl_impl;
115 	*m_pImpl = *(r.m_pImpl);
116 }
117 
118 OUString AttributeListImpl::getNameByIndex(sal_Int16 i) throw (RuntimeException)
119 {
120 	if( i < sal::static_int_cast<sal_Int16>(m_pImpl->vecAttribute.size()) ) {
121 		return m_pImpl->vecAttribute[i].sName;
122 	}
123 	return OUString();
124 }
125 
126 
127 OUString AttributeListImpl::getTypeByIndex(sal_Int16 i) throw (RuntimeException)
128 {
129 	if( i < sal::static_int_cast<sal_Int16>(m_pImpl->vecAttribute.size()) ) {
130 		return m_pImpl->vecAttribute[i].sType;
131 	}
132 	return OUString();
133 }
134 
135 OUString AttributeListImpl::getValueByIndex(sal_Int16 i) throw (RuntimeException)
136 {
137 	if( i < sal::static_int_cast<sal_Int16>(m_pImpl->vecAttribute.size()) ) {
138 		return m_pImpl->vecAttribute[i].sValue;
139 	}
140 	return OUString();
141 
142 }
143 
144 OUString AttributeListImpl::getTypeByName( const OUString& sName ) throw (RuntimeException)
145 {
146 	::std::vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin();
147 
148 	for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) {
149 		if( (*ii).sName == sName ) {
150 			return (*ii).sType;
151 		}
152 	}
153 	return OUString();
154 }
155 
156 OUString AttributeListImpl::getValueByName(const OUString& sName) throw (RuntimeException)
157 {
158 	::std::vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin();
159 
160 	for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) {
161 		if( (*ii).sName == sName ) {
162 			return (*ii).sValue;
163 		}
164 	}
165 	return OUString();
166 }
167 
168 
169 AttributeListImpl::AttributeListImpl()
170 {
171 	m_pImpl = new AttributeListImpl_impl;
172 }
173 
174 
175 
176 AttributeListImpl::~AttributeListImpl()
177 {
178 	delete m_pImpl;
179 }
180 
181 
182 void AttributeListImpl::addAttribute( 	const OUString &sName ,
183 										const OUString &sType ,
184 										const OUString &sValue )
185 {
186 	m_pImpl->vecAttribute.push_back( TagAttribute( sName , sType , sValue ) );
187 }
188 
189 void AttributeListImpl::clear()
190 {
191 	::std::vector<struct TagAttribute> dummy;
192 	m_pImpl->vecAttribute.swap( dummy );
193 
194 	OSL_ASSERT( ! getLength() );
195 }
196 
197 // ------------------------------------------------------------------
198 
199 Any SAL_CALL OReadAccelatorDocumentHandler::queryInterface( const Type & rType ) throw( RuntimeException )
200 {
201 	Any a = ::cppu::queryInterface( rType ,SAL_STATIC_CAST( XDocumentHandler*, this ));
202 	if ( a.hasValue() )
203 		return a;
204 	else
205 		return OWeakObject::queryInterface( rType );
206 }
207 
208 void SAL_CALL OReadAccelatorDocumentHandler::ignorableWhitespace(
209 	const OUString& )
210 throw( SAXException, RuntimeException )
211 {
212 }
213 
214 void SAL_CALL OReadAccelatorDocumentHandler::processingInstruction(
215 	const OUString&, const OUString& )
216 throw( SAXException, RuntimeException )
217 {
218 }
219 
220 void SAL_CALL OReadAccelatorDocumentHandler::setDocumentLocator(
221 	const Reference< XLocator > &xLocator)
222 throw(	SAXException, RuntimeException )
223 {
224 	m_xLocator = xLocator;
225 }
226 
227 ::rtl::OUString OReadAccelatorDocumentHandler::getErrorLineString()
228 {
229 	char buffer[32];
230 
231 	if ( m_xLocator.is() )
232 	{
233 		return OUString::createFromAscii( buffer );
234 	}
235 	else
236 		return OUString();
237 }
238 
239 void SAL_CALL OReadAccelatorDocumentHandler::startDocument(void)
240 	throw ( SAXException, RuntimeException )
241 {
242 }
243 
244 void SAL_CALL OReadAccelatorDocumentHandler::endDocument(void)
245 	throw( SAXException, RuntimeException )
246 {
247 	if ( m_nElementDepth > 0 )
248 	{
249 		OUString aErrorMessage = getErrorLineString();
250 		aErrorMessage += OUString( RTL_CONSTASCII_USTRINGPARAM( "A closing element is missing!" ));
251 		throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
252 	}
253 }
254 
255 
256 void SAL_CALL OReadAccelatorDocumentHandler::startElement(
257 	const OUString& aElementName, const Reference< XAttributeList > &xAttrList )
258 throw( SAXException, RuntimeException )
259 {
260 	m_nElementDepth++;
261 
262 	if ( aElementName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_ACCELERATORLIST )))
263 	{
264 		// acceleratorlist
265 		if ( m_bAcceleratorMode )
266 		{
267 			OUString aErrorMessage = getErrorLineString();
268 			aErrorMessage += OUString( RTL_CONSTASCII_USTRINGPARAM( "Accelerator list used twice!" ));
269 			throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
270 		}
271 		else
272 			m_bAcceleratorMode = sal_True;
273 	}
274 	else if ( aElementName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_ACCELERATORITEM )))
275 	{
276 		// accelerator item
277 		if ( !m_bAcceleratorMode )
278 		{
279 			OUString aErrorMessage = getErrorLineString();
280 			aErrorMessage += OUString( RTL_CONSTASCII_USTRINGPARAM( "Accelerator list element has to be used before!" ));
281 			throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
282 		}
283 		else
284 		{
285 			// read accelerator item
286 			m_bItemCloseExpected = sal_True;
287 
288 			SvtAcceleratorConfigItem aItem;
289 
290 			// read attributes for accelerator
291 			for ( sal_Int16 i=0; i< xAttrList->getLength(); i++ )
292 			{
293 				OUString aName = xAttrList->getNameByIndex( i );
294 				OUString aValue = xAttrList->getValueByIndex( i );
295 
296 				if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_URL )))
297                     aItem.aCommand = aValue;
298 				else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_MODIFIER )))
299 					aItem.nModifier = (sal_uInt16)aValue.toInt32();
300 				else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ATTRIBUTE_KEYCODE )))
301 					aItem.nCode = (sal_uInt16)aValue.toInt32();
302 			}
303 
304 			m_aReadAcceleratorList.push_back( aItem );
305 		}
306 	}
307 	else
308 	{
309 		OUString aErrorMessage = getErrorLineString();
310 		aErrorMessage += OUString( RTL_CONSTASCII_USTRINGPARAM( "Unknown element found!" ));
311 		throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
312 	}
313 }
314 
315 
316 void SAL_CALL OReadAccelatorDocumentHandler::characters(const rtl::OUString&)
317 throw(	SAXException, RuntimeException )
318 {
319 }
320 
321 
322 void SAL_CALL OReadAccelatorDocumentHandler::endElement( const OUString& aName )
323 	throw( SAXException, RuntimeException )
324 {
325 	m_nElementDepth--;
326 
327 	if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_ACCELERATORLIST )))
328 	{
329 		// acceleratorlist
330 		if ( !m_bAcceleratorMode )
331 		{
332 			OUString aErrorMessage = getErrorLineString();
333 			aErrorMessage += OUString( RTL_CONSTASCII_USTRINGPARAM( "Accelerator list used twice!" ));
334 			throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
335 		}
336 	}
337 	else if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ELEMENT_ACCELERATORITEM )))
338 	{
339 		if ( !m_bItemCloseExpected )
340 		{
341 			OUString aErrorMessage = getErrorLineString();
342 			aErrorMessage += OUString( RTL_CONSTASCII_USTRINGPARAM( "Closing accelerator item element expected!" ));
343 			throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
344 		}
345 	}
346 	else
347 	{
348 		OUString aErrorMessage = getErrorLineString();
349 		aErrorMessage += OUString( RTL_CONSTASCII_USTRINGPARAM( "Unknown closing element found!" ));
350 		throw SAXException( aErrorMessage, Reference< XInterface >(), Any() );
351 	}
352 }
353 
354 // ------------------------------------------------------------------
355 
356 OWriteAccelatorDocumentHandler::OWriteAccelatorDocumentHandler(
357 	const SvtAcceleratorItemList& aWriteAcceleratorList, Reference< XDocumentHandler > xDocumentHandler ) :
358 	m_xWriteDocumentHandler( xDocumentHandler ),
359 	m_aWriteAcceleratorList( aWriteAcceleratorList )
360 {
361 	m_aAttributeType = OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_TYPE_CDATA ));
362 }
363 
364 OWriteAccelatorDocumentHandler::~OWriteAccelatorDocumentHandler()
365 {
366 }
367 
368 void OWriteAccelatorDocumentHandler::WriteAcceleratorDocument()
369 	throw ( SAXException, RuntimeException )
370 {
371 	AttributeListImpl* pList = new AttributeListImpl;
372 	Reference< XAttributeList > rList( (XAttributeList *)pList , UNO_QUERY );
373 
374 	m_xWriteDocumentHandler->startDocument();
375 	m_xWriteDocumentHandler->startElement( OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_ACCELERATORLIST )), rList );
376 	m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
377 
378 	std::list< SvtAcceleratorConfigItem>::const_iterator p;
379 	for ( p = m_aWriteAcceleratorList.begin(); p != m_aWriteAcceleratorList.end(); p++ )
380 		WriteAcceleratorItem( *p );
381 
382 	m_xWriteDocumentHandler->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_ACCELERATORLIST )) );
383 	m_xWriteDocumentHandler->endDocument();
384 }
385 
386 void OWriteAccelatorDocumentHandler::WriteAcceleratorItem(
387 	const SvtAcceleratorConfigItem& aAcceleratorItem )
388 	throw( SAXException, RuntimeException )
389 {
390 	AttributeListImpl* pAcceleratorAttributes = new AttributeListImpl;
391 	Reference< XAttributeList > xAcceleratorAttrList( (XAttributeList *)pAcceleratorAttributes , UNO_QUERY );
392 
393 	// set attributes
394 	pAcceleratorAttributes->addAttribute(
395 		OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_KEYCODE )),
396 		m_aAttributeType,
397 		OUString::valueOf( aAcceleratorItem.nCode ));
398 
399 	pAcceleratorAttributes->addAttribute(
400 		OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_MODIFIER )),
401 		m_aAttributeType,
402 		OUString::valueOf( aAcceleratorItem.nModifier ));
403 
404 	pAcceleratorAttributes->addAttribute(
405 		OUString( RTL_CONSTASCII_USTRINGPARAM( ATTRIBUTE_URL )),
406 		m_aAttributeType,
407         aAcceleratorItem.aCommand );
408 
409 	// write start element
410 	m_xWriteDocumentHandler->startElement(
411 		OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_ACCELERATORITEM )),
412 		xAcceleratorAttrList );
413 	m_xWriteDocumentHandler->ignorableWhitespace( OUString() );
414 	m_xWriteDocumentHandler->endElement( OUString( RTL_CONSTASCII_USTRINGPARAM( ELEMENT_ACCELERATORITEM )) );
415 }
416