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_dtrans.hxx"
30 
31 //------------------------------------------------------------------------
32 // includes
33 //------------------------------------------------------------------------
34 #include <osl/diagnose.h>
35 #include "WinClipboard.hxx"
36 #include <com/sun/star/datatransfer/clipboard/ClipboardEvent.hpp>
37 #include <com/sun/star/lang/DisposedException.hpp>
38 #include <com/sun/star/lang/IllegalArgumentException.hpp>
39 #include "WinClipbImpl.hxx"
40 
41 //------------------------------------------------------------------------
42 // namespace directives
43 //------------------------------------------------------------------------
44 
45 using namespace rtl;
46 using namespace osl;
47 using namespace std;
48 using namespace cppu;
49 
50 using namespace com::sun::star::uno;
51 using namespace com::sun::star::datatransfer;
52 using namespace com::sun::star::datatransfer::clipboard;
53 using namespace com::sun::star::lang;
54 
55 //------------------------------------------------------------------------
56 // defines
57 //------------------------------------------------------------------------
58 
59 #define WINCLIPBOARD_IMPL_NAME  "com.sun.star.datatransfer.clipboard.ClipboardW32"
60 
61 //------------------------------------------------------------------------
62 // helper functions
63 //------------------------------------------------------------------------
64 
65 namespace
66 {
67 	Sequence< OUString > SAL_CALL WinClipboard_getSupportedServiceNames()
68 	{
69 		Sequence< OUString > aRet(1);
70 		aRet[0] = OUString::createFromAscii("com.sun.star.datatransfer.clipboard.SystemClipboard");
71 		return aRet;
72 	}
73 }
74 
75 //------------------------------------------------------------------------
76 // ctor
77 //------------------------------------------------------------------------
78 /*XEventListener,*/
79 CWinClipboard::CWinClipboard( const Reference< XMultiServiceFactory >& rServiceManager, const OUString& aClipboardName ) :
80 	WeakComponentImplHelper4< XClipboardEx, XFlushableClipboard, XClipboardNotifier, XServiceInfo >( m_aCbListenerMutex ),
81 	m_SrvMgr( rServiceManager )
82 {
83 	m_pImpl.reset( new CWinClipbImpl( aClipboardName, this ) );
84 }
85 
86 //========================================================================
87 // XClipboard
88 //========================================================================
89 
90 //------------------------------------------------------------------------
91 // getContent
92 // to avoid unecessary traffic we check first if there is a clipboard
93 // content which was set via setContent, in this case we don't need
94 // to query the content from the clipboard, create a new wrapper object
95 // and so on, we simply return the orignial XTransferable instead of our
96 // DOTransferable
97 //------------------------------------------------------------------------
98 
99 Reference< XTransferable > SAL_CALL CWinClipboard::getContents( ) throw( RuntimeException )
100 {
101 	MutexGuard aGuard( m_aMutex );
102 
103 	if ( rBHelper.bDisposed )
104 		throw DisposedException( OUString::createFromAscii( "object is already disposed" ),
105 								 static_cast< XClipboardEx* >( this ) );
106 
107 	if ( NULL != m_pImpl.get( ) )
108 		return m_pImpl->getContents( );
109 
110 	return Reference< XTransferable >( );
111 }
112 
113 //------------------------------------------------------------------------
114 // setContent
115 //------------------------------------------------------------------------
116 
117 void SAL_CALL CWinClipboard::setContents( const Reference< XTransferable >& xTransferable,
118 										  const Reference< XClipboardOwner >& xClipboardOwner )
119 										  throw( RuntimeException )
120 {
121 	MutexGuard aGuard( m_aMutex );
122 
123 	if ( rBHelper.bDisposed )
124 		throw DisposedException( OUString::createFromAscii( "object is already disposed" ),
125 								 static_cast< XClipboardEx* >( this ) );
126 
127 	if ( NULL != m_pImpl.get( ) )
128 		m_pImpl->setContents( xTransferable, xClipboardOwner );
129 }
130 
131 //------------------------------------------------------------------------
132 // getName
133 //------------------------------------------------------------------------
134 
135 OUString SAL_CALL CWinClipboard::getName(  ) throw( RuntimeException )
136 {
137 	if ( rBHelper.bDisposed )
138 		throw DisposedException( OUString::createFromAscii( "object is already disposed" ),
139 								 static_cast< XClipboardEx* >( this ) );
140 
141 	if ( NULL != m_pImpl.get( ) )
142 		return m_pImpl->getName( );
143 
144 	return OUString::createFromAscii( "" );
145 }
146 
147 //========================================================================
148 // XFlushableClipboard
149 //========================================================================
150 
151 void SAL_CALL CWinClipboard::flushClipboard( ) throw( RuntimeException )
152 {
153 	MutexGuard aGuard( m_aMutex );
154 
155 	if ( rBHelper.bDisposed )
156 		throw DisposedException( OUString::createFromAscii( "object is already disposed" ),
157 								 static_cast< XClipboardEx* >( this ) );
158 
159 	if ( NULL != m_pImpl.get( ) )
160 		m_pImpl->flushClipboard( );
161 }
162 
163 //========================================================================
164 // XClipboardEx
165 //========================================================================
166 
167 sal_Int8 SAL_CALL CWinClipboard::getRenderingCapabilities(  ) throw( RuntimeException )
168 {
169 	if ( rBHelper.bDisposed )
170 		throw DisposedException( OUString::createFromAscii( "object is already disposed" ),
171 								 static_cast< XClipboardEx* >( this ) );
172 
173 	if ( NULL != m_pImpl.get( ) )
174 		return m_pImpl->getRenderingCapabilities( );
175 
176 	return 0;
177 }
178 
179 //========================================================================
180 // XClipboardNotifier
181 //========================================================================
182 
183 //------------------------------------------------------------------------
184 // getName
185 //------------------------------------------------------------------------
186 
187 void SAL_CALL CWinClipboard::addClipboardListener( const Reference< XClipboardListener >& listener )
188 	throw( RuntimeException )
189 {
190 	if ( rBHelper.bDisposed )
191 		throw DisposedException( OUString::createFromAscii( "object is already disposed" ),
192 								 static_cast< XClipboardEx* >( this ) );
193 
194 	// check input parameter
195 	if ( !listener.is( ) )
196 		throw IllegalArgumentException( OUString::createFromAscii( "empty reference" ),
197 										static_cast< XClipboardEx* >( this ),
198 										1 );
199 
200 	rBHelper.aLC.addInterface( getCppuType( &listener ), listener );
201 }
202 
203 //------------------------------------------------------------------------
204 // getName
205 //------------------------------------------------------------------------
206 
207 void SAL_CALL CWinClipboard::removeClipboardListener( const Reference< XClipboardListener >& listener )
208 	throw( RuntimeException )
209 {
210 	if ( rBHelper.bDisposed )
211 		throw DisposedException( OUString::createFromAscii( "object is already disposed" ),
212 								 static_cast< XClipboardEx* >( this ) );
213 
214 	// check input parameter
215 	if ( !listener.is( ) )
216 		throw IllegalArgumentException( OUString::createFromAscii( "empty reference" ),
217 										static_cast< XClipboardEx* >( this ),
218 										1 );
219 
220 	rBHelper.aLC.removeInterface( getCppuType( &listener ), listener );
221 }
222 
223 //------------------------------------------------------------------------
224 // getName
225 //------------------------------------------------------------------------
226 
227 void SAL_CALL CWinClipboard::notifyAllClipboardListener( )
228 {
229 	if ( !rBHelper.bDisposed )
230 	{
231 		ClearableMutexGuard aGuard( rBHelper.rMutex );
232 		if ( !rBHelper.bDisposed )
233 		{
234 			aGuard.clear( );
235 
236 			OInterfaceContainerHelper* pICHelper = rBHelper.aLC.getContainer(
237 				getCppuType( ( Reference< XClipboardListener > * ) 0 ) );
238 
239 			if ( pICHelper )
240 			{
241 			    try
242 			    {
243 				    OInterfaceIteratorHelper iter(*pICHelper);
244 				    Reference<XTransferable> rXTransf(m_pImpl->getContents());
245 				    ClipboardEvent aClipbEvent(static_cast<XClipboard*>(this), rXTransf);
246 
247 				    while(iter.hasMoreElements())
248 				    {
249 					    try
250 					    {
251 						    Reference<XClipboardListener> xCBListener(iter.next(), UNO_QUERY);
252 						    if (xCBListener.is())
253 							    xCBListener->changedContents(aClipbEvent);
254 					    }
255 					    catch(RuntimeException&)
256 					    {
257 						    OSL_ENSURE( false, "RuntimeException caught" );
258 					    }
259 				    }
260 				}
261 			    catch(const ::com::sun::star::lang::DisposedException&)
262 			    {
263 			        OSL_ENSURE(false, "Service Manager disposed");
264 
265 			        // no further clipboard changed notifications
266 			        m_pImpl->unregisterClipboardViewer();
267 			    }
268 
269 			} // end if
270 		} // end if
271 	} // end if
272 }
273 
274 //------------------------------------------------
275 // overwritten base class method which will be
276 // called by the base class dispose method
277 //------------------------------------------------
278 
279 void SAL_CALL CWinClipboard::disposing()
280 {
281 	// do my own stuff
282 	m_pImpl->dispose( );
283 
284 	// force destruction of the impl class
285 	m_pImpl.reset( NULL );
286 }
287 
288 // -------------------------------------------------
289 // XServiceInfo
290 // -------------------------------------------------
291 
292 OUString SAL_CALL CWinClipboard::getImplementationName(  )
293 	throw(RuntimeException)
294 {
295 	return OUString::createFromAscii( WINCLIPBOARD_IMPL_NAME );
296 }
297 
298 // -------------------------------------------------
299 //	XServiceInfo
300 // -------------------------------------------------
301 
302 sal_Bool SAL_CALL CWinClipboard::supportsService( const OUString& ServiceName )
303 	throw(RuntimeException)
304 {
305 	Sequence < OUString > SupportedServicesNames = WinClipboard_getSupportedServiceNames();
306 
307 	for ( sal_Int32 n = SupportedServicesNames.getLength(); n--; )
308 		if (SupportedServicesNames[n].compareTo(ServiceName) == 0)
309 			return sal_True;
310 
311 	return sal_False;
312 }
313 
314 // -------------------------------------------------
315 //	XServiceInfo
316 // -------------------------------------------------
317 
318 Sequence< OUString > SAL_CALL CWinClipboard::getSupportedServiceNames(	 )
319 	throw(RuntimeException)
320 {
321 	return WinClipboard_getSupportedServiceNames();
322 }
323