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 #ifndef GCC
31 #endif
32 #include "rtl/instance.hxx"
33 #include <com/sun/star/uno/Any.hxx>
34 #include <com/sun/star/uno/Sequence.hxx>
35 #include <com/sun/star/io/XActiveDataSource.hpp>
36 #include <com/sun/star/io/XInputStream.hpp>
37 #include <com/sun/star/io/XOutputStream.hpp>
38 #include <com/sun/star/xml/sax/XParser.hpp>
39 #include <unotools/configmgr.hxx>
40 #include <unotools/configitem.hxx>
41 #include <tools/debug.hxx>
42 
43 #include <osl/mutex.hxx>
44 #include <tools/string.hxx>
45 #include <tools/urlobj.hxx>
46 #include <unotools/streamwrap.hxx>
47 #include <unotools/ucbstreamhelper.hxx>
48 #include <comphelper/processfactory.hxx>
49 
50 #include <unotools/accelcfg.hxx>
51 #include <unotools/xmlaccelcfg.hxx>
52 #include <unotools/pathoptions.hxx>
53 #include "itemholder1.hxx"
54 
55 
56 using namespace utl;
57 using namespace rtl;
58 using namespace com::sun::star::uno;
59 using namespace com::sun::star::io;
60 using namespace com::sun::star::xml::sax;
61 
62 
63 static SvtAcceleratorConfig_Impl* pOptions = NULL;
64 static sal_Int32           nRefCount = 0;
65 
66 class SvtAcceleratorConfig_Impl
67 {
68 public:
69 
70     SvtAcceleratorItemList aList;
71 	bool			bModified;
72 
73                     SvtAcceleratorConfig_Impl()
74                         : bModified( sal_False )
75                     {}
76 
77 					SvtAcceleratorConfig_Impl( Reference< XInputStream >& xInputStream );
78 	bool			Commit( Reference< XOutputStream >& xOutputStream );
79 };
80 
81 // -----------------------------------------------------------------------
82 
83 SvtAcceleratorConfig_Impl::SvtAcceleratorConfig_Impl( Reference< XInputStream >& rInputStream )
84 		: bModified( false )
85 {
86 	Reference< XParser > xParser( ::comphelper::getProcessServiceFactory()->createInstance(
87 									::rtl::OUString::createFromAscii( "com.sun.star.xml.sax.Parser" )),
88 								  UNO_QUERY);
89 
90 	// connect stream to input stream to the parser
91 	InputSource aInputSource;
92 	aInputSource.aInputStream = rInputStream;
93 
94 	// get filter
95 	Reference< XDocumentHandler > xFilter( new OReadAccelatorDocumentHandler( aList ));
96 
97 	// connect parser and filter
98 	xParser->setDocumentHandler( xFilter );
99     xParser->parseStream( aInputSource );
100 }
101 
102 bool SvtAcceleratorConfig_Impl::Commit( Reference< XOutputStream >& rOutputStream )
103 {
104 	Reference< XDocumentHandler > xWriter;
105 
106 	xWriter = Reference< XDocumentHandler >( ::comphelper::getProcessServiceFactory()->createInstance(
107 			::rtl::OUString::createFromAscii( "com.sun.star.xml.sax.Writer" )), UNO_QUERY) ;
108 
109 	Reference< ::com::sun::star::io::XActiveDataSource> xDataSource( xWriter , UNO_QUERY );
110 	xDataSource->setOutputStream( rOutputStream );
111 	try
112 	{
113 		OWriteAccelatorDocumentHandler aWriteHandler( aList, xWriter );
114 		aWriteHandler.WriteAcceleratorDocument();
115 		rOutputStream->flush();
116 		return true;
117 	}
118 	catch ( RuntimeException& )
119 	{
120 	}
121 	catch ( SAXException& )
122 	{
123 	}
124 	catch ( ::com::sun::star::io::IOException& )
125 	{
126 	}
127 
128 	return false;
129 }
130 
131 namespace
132 {
133     class LocalSingleton : public rtl::Static< osl::Mutex, LocalSingleton >
134     {
135     };
136 }
137 
138 SvtAcceleratorConfiguration::SvtAcceleratorConfiguration()
139 {
140     // Global access, must be guarded (multithreading)
141     ::osl::MutexGuard aGuard( LocalSingleton::get() );
142     if ( !pOptions )
143 	{
144         SvStream* pStream = GetDefaultStream( STREAM_STD_READ );
145     	::utl::OInputStreamWrapper aHelper( *pStream );
146 		com::sun::star::uno::Reference < ::com::sun::star::io::XInputStream > xOut( &aHelper );
147 
148         try
149         {
150             pOptions = new SvtAcceleratorConfig_Impl( xOut );
151         }
152         catch ( RuntimeException& )
153         {
154             pOptions = new SvtAcceleratorConfig_Impl();
155         }
156         catch( SAXException& )
157         {
158             pOptions = new SvtAcceleratorConfig_Impl();
159         }
160         catch( ::com::sun::star::io::IOException& )
161         {
162             pOptions = new SvtAcceleratorConfig_Impl();
163         }
164 
165 		if (pOptions)
166 			ItemHolder1::holdConfigItem(E_ACCELCFG);
167 
168         delete pStream;
169     }
170 
171     ++nRefCount;
172     pImp = pOptions;
173 }
174 
175 SvtAcceleratorConfiguration* SvtAcceleratorConfiguration::CreateFromStream( SvStream& rStream )
176 {
177     SvtAcceleratorConfiguration* pRet = new SvtAcceleratorConfiguration;
178     ::utl::OInputStreamWrapper aHelper( rStream );
179     com::sun::star::uno::Reference < ::com::sun::star::io::XInputStream > xOut( &aHelper );
180     try
181     {
182         pRet->pImp = new SvtAcceleratorConfig_Impl( xOut );
183     }
184     catch ( RuntimeException& )
185     {
186         DELETEZ( pRet );
187     }
188     catch( SAXException& )
189     {
190         DELETEZ( pRet );
191     }
192     catch( ::com::sun::star::io::IOException& )
193     {
194         DELETEZ( pRet );
195     }
196 
197     return pRet;
198 }
199 
200 // -----------------------------------------------------------------------
201 
202 SvtAcceleratorConfiguration::~SvtAcceleratorConfiguration()
203 {
204     if ( pImp == pOptions )
205     {
206         // Global access, must be guarded (multithreading)
207         ::osl::MutexGuard aGuard( LocalSingleton::get() );
208         if ( !--nRefCount )
209         {
210 			if ( pImp->bModified )
211 			{
212     			String aUserConfig = SvtPathOptions().GetUserConfigPath();
213     			INetURLObject aObj( aUserConfig );
214     			aObj.insertName( String::CreateFromAscii("GlobalKeyBindings.xml") );
215     			SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( aObj.GetMainURL( INetURLObject::NO_DECODE ), STREAM_STD_READWRITE|STREAM_TRUNC );
216     			::utl::OOutputStreamWrapper aHelper( *pStream );
217 				com::sun::star::uno::Reference < ::com::sun::star::io::XOutputStream > xOut( &aHelper );
218 				pImp->Commit( xOut );
219 				delete pStream;
220 			}
221 
222             DELETEZ( pOptions );
223         }
224     }
225     else
226     {
227         delete pImp;
228     }
229 }
230 
231 ::rtl::OUString SvtAcceleratorConfiguration::GetCommand( const ::com::sun::star::awt::KeyEvent& rKeyEvent )
232 {
233     sal_Int16 nCode=rKeyEvent.KeyCode, nModifier=rKeyEvent.Modifiers;
234     if ( !nCode )
235         nCode = rKeyEvent.KeyFunc;
236 
237 	std::list< SvtAcceleratorConfigItem>::const_iterator p;
238 	for ( p = pImp->aList.begin(); p != pImp->aList.end(); p++ )
239 		if ( p->nCode == nCode && p->nModifier == nModifier )
240             return p->aCommand;
241 
242 	return ::rtl::OUString();
243 }
244 
245 const SvtAcceleratorItemList& SvtAcceleratorConfiguration::GetItems()
246 {
247 	return pImp->aList;
248 }
249 
250 void SvtAcceleratorConfiguration::SetCommand( const SvtAcceleratorConfigItem& rItem )
251 {
252 	std::list< SvtAcceleratorConfigItem>::iterator p;
253 	for ( p = pImp->aList.begin(); p != pImp->aList.end(); p++ )
254 		if ( p->nCode == rItem.nCode && p->nModifier == rItem.nModifier )
255 		{
256             p->aCommand = rItem.aCommand;
257 			return;
258 		}
259 
260 	pImp->aList.push_back( rItem );
261 
262 }
263 
264 void SvtAcceleratorConfiguration::SetItems( const SvtAcceleratorItemList& rItems, bool bClear )
265 {
266 	if ( bClear )
267 	{
268 		pImp->aList = rItems;
269 	}
270 	else
271 	{
272 		std::list< SvtAcceleratorConfigItem>::const_iterator p;
273 		for ( p = rItems.begin(); p != rItems.end(); p++ )
274             SetCommand( *p );
275 	}
276 }
277 
278 String SvtAcceleratorConfiguration::GetStreamName()
279 {
280     return String::CreateFromAscii("KeyBindings.xml");
281 }
282 
283 SvStream* SvtAcceleratorConfiguration::GetDefaultStream( StreamMode nMode )
284 {
285 	String aUserConfig = SvtPathOptions().GetUserConfigPath();
286     INetURLObject aObj( aUserConfig );
287     aObj.insertName( GetStreamName() );
288     return ::utl::UcbStreamHelper::CreateStream( aObj.GetMainURL( INetURLObject::NO_DECODE ), nMode );
289 }
290