1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: Os2Clipboard.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 //------------------------------------------------------------------------
33 //------------------------------------------------------------------------
35 #include "Os2Clipboard.hxx"
37 //------------------------------------------------------------------------
38 // namespace directives
39 //------------------------------------------------------------------------
41 using namespace com::sun::star::datatransfer
;
42 using namespace com::sun::star::datatransfer::clipboard
;
43 using namespace com::sun::star::datatransfer::clipboard::RenderingCapabilities
;
44 using namespace com::sun::star::lang
;
45 using namespace com::sun::star::uno
;
51 const Type CPPUTYPE_SEQINT8
= getCppuType( ( Sequence
< sal_Int8
>* )0 );
52 const Type CPPUTYPE_OUSTRING
= getCppuType( (OUString
*)0 );
54 #define DTRANS_OBJ_CLASSNAME "DTRANSOBJWND"
56 // -----------------------------------------------------------------------
58 inline void SetWindowPtr( HWND hWnd
, Os2Clipboard
* pThis
)
60 WinSetWindowULong( hWnd
, QWL_USER
, (ULONG
)pThis
);
63 inline Os2Clipboard
* GetWindowPtr( HWND hWnd
)
65 return (Os2Clipboard
*)WinQueryWindowULong( hWnd
, QWL_USER
);
68 // -----------------------------------------------------------------------
70 MRESULT EXPENTRY
DtransObjWndProc( HWND hWnd
, ULONG nMsg
, MPARAM nMP1
, MPARAM nMP2
)
75 case WM_DRAWCLIPBOARD
: // clipboard content has changed
77 Os2Clipboard
* os2Clipboard
= GetWindowPtr( hWnd
);
80 //MutexGuard aGuard(os2Clipboard->m_aMutex);
81 debug_printf("WM_DRAWCLIPBOARD os2Clipboard %08x\n", os2Clipboard
);
82 if (os2Clipboard
->m_bInSetClipboardData
)
84 debug_printf("WM_DRAWCLIPBOARD our change\n");
88 // notify listener for clipboard change
89 debug_printf("WM_DRAWCLIPBOARD notify change\n");
90 os2Clipboard
->notifyAllClipboardListener();
97 return WinDefWindowProc( hWnd
, nMsg
, nMP1
, nMP2
);
100 // -----------------------------------------------------------------------
102 Os2Clipboard::Os2Clipboard() :
104 WeakComponentImplHelper4
< XClipboardEx
, XClipboardNotifier
, XServiceInfo
, XInitialization
> (m_aMutex
),
105 m_bInitialized(sal_False
),
106 m_bInSetClipboardData(sal_False
)
108 MutexGuard
aGuard(m_aMutex
);
110 debug_printf("Os2Clipboard::Os2Clipboard\n");
111 hAB
= WinQueryAnchorBlock( HWND_DESKTOP
);
116 // register object class
117 if ( WinRegisterClass( hAB
, (PSZ
)DTRANS_OBJ_CLASSNAME
,
118 (PFNWP
)DtransObjWndProc
, 0, sizeof(ULONG
) ))
121 // create object window to get clip viewer messages
122 hObjWnd
= WinCreateWindow( HWND_OBJECT
, (PCSZ
)DTRANS_OBJ_CLASSNAME
,
123 (PCSZ
)"", 0, 0, 0, 0, 0,
124 HWND_OBJECT
, HWND_TOP
,
127 SetWindowPtr( hObjWnd
, this);
128 // register the viewer window
129 rc
= WinOpenClipbrd(hAB
);
130 rc
= WinSetClipbrdViewer(hAB
, hObjWnd
);
131 rc
= WinCloseClipbrd(hAB
);
137 Os2Clipboard::~Os2Clipboard()
139 debug_printf("Os2Clipboard::~Os2Clipboard\n");
142 void SAL_CALL
Os2Clipboard::initialize( const Sequence
< Any
>& aArguments
)
143 throw(Exception
, RuntimeException
)
147 for (sal_Int32 n
= 0, nmax
= aArguments
.getLength(); n
< nmax
; n
++)
148 if (aArguments
[n
].getValueType() == getCppuType((OUString
*) 0))
150 aArguments
[0] >>= m_aName
;
156 OUString SAL_CALL
Os2Clipboard::getImplementationName() throw( RuntimeException
)
158 debug_printf("Os2Clipboard::getImplementationName\n");
159 return OUString::createFromAscii( OS2_CLIPBOARD_IMPL_NAME
);
162 sal_Bool SAL_CALL
Os2Clipboard::supportsService( const OUString
& ServiceName
) throw( RuntimeException
)
164 debug_printf("Os2Clipboard::supportsService\n");
165 Sequence
< OUString
> SupportedServicesNames
= Os2Clipboard_getSupportedServiceNames();
167 for ( sal_Int32 n
= SupportedServicesNames
.getLength(); n
--; )
168 if (SupportedServicesNames
[n
].compareTo(ServiceName
) == 0)
174 Sequence
< OUString
> SAL_CALL
Os2Clipboard::getSupportedServiceNames() throw( RuntimeException
)
176 debug_printf("Os2Clipboard::getSupportedServiceNames\n");
177 return Os2Clipboard_getSupportedServiceNames();
180 Reference
< XTransferable
> SAL_CALL
Os2Clipboard::getContents() throw( RuntimeException
)
182 debug_printf("Os2Clipboard::getContents\n");
183 MutexGuard
aGuard(m_aMutex
);
185 // os2 can have only one viewer at time, and we don't get a notification
186 // when the viewer changes. So we need to check handles of clipboard
187 // data and compare with previous handles
188 if (UWinOpenClipbrd(hAB
)) {
189 sal_Bool fireChanged
= sal_False
;
190 ULONG handle
= UWinQueryClipbrdData( hAB
, UCLIP_CF_UNICODETEXT
);
192 if (handle
!= hText
) {
194 fireChanged
= sal_True
;
197 handle
= UWinQueryClipbrdData( hAB
, UCLIP_CF_BITMAP
);
199 if (handle
!= hBitmap
) {
201 fireChanged
= sal_True
;
204 UWinCloseClipbrd( hAB
);
207 // notify listener for clipboard change
208 debug_printf("Os2Clipboard::getContents notify change\n");
209 notifyAllClipboardListener();
213 if( ! m_aContents
.is() )
214 m_aContents
= new Os2Transferable( static_cast< OWeakObject
* >(this) );
219 void SAL_CALL
Os2Clipboard::setContents( const Reference
< XTransferable
>& xTrans
, const Reference
< XClipboardOwner
>& xClipboardOwner
) throw( RuntimeException
)
221 debug_printf("Os2Clipboard::setContents\n");
222 // remember old values for callbacks before setting the new ones.
223 ClearableMutexGuard
aGuard(m_aMutex
);
225 Reference
< XClipboardOwner
> oldOwner(m_aOwner
);
226 m_aOwner
= xClipboardOwner
;
228 Reference
< XTransferable
> oldContents(m_aContents
);
229 m_aContents
= xTrans
;
233 // notify old owner on loss of ownership
235 oldOwner
->lostOwnership(static_cast < XClipboard
* > (this), oldContents
);
237 // notify all listeners on content changes
238 OInterfaceContainerHelper
*pContainer
=
239 rBHelper
.aLC
.getContainer(getCppuType( (Reference
< XClipboardListener
> *) 0));
242 ClipboardEvent
aEvent(static_cast < XClipboard
* > (this), m_aContents
);
243 OInterfaceIteratorHelper
aIterator(*pContainer
);
245 while (aIterator
.hasMoreElements())
247 Reference
< XClipboardListener
> xListener(aIterator
.next(), UNO_QUERY
);
249 xListener
->changedContents(aEvent
);
253 #if OSL_DEBUG_LEVEL>0
254 // dump list of available mimetypes
255 Sequence
< DataFlavor
> aFlavors( m_aContents
->getTransferDataFlavors() );
256 for( int i
= 0; i
< aFlavors
.getLength(); i
++ )
257 debug_printf("Os2Clipboard::setContents available mimetype: %d %s\n",
258 i
, CHAR_POINTER(aFlavors
.getConstArray()[i
].MimeType
));
261 // we can only export text or bitmap
262 DataFlavor
nFlavorText( OUString::createFromAscii( "text/plain;charset=utf-16" ),
263 OUString::createFromAscii( "Unicode-Text" ), CPPUTYPE_OUSTRING
);
264 DataFlavor
nFlavorBitmap( OUString::createFromAscii( "application/x-openoffice-bitmap;windows_formatname=\"Bitmap\"" ),
265 OUString::createFromAscii( "Bitmap" ), CPPUTYPE_DEFAULT
);
267 // try text transfer data (if any)
268 PSZ pSharedText
= NULL
;
272 Any aAny
= m_aContents
->getTransferData( nFlavorText
);
276 // copy unicode text to clipboard
280 rc
= DosAllocSharedMem( (PPVOID
) &pSharedText
, NULL
,
281 aString
.getLength() * 2 + 2,
282 PAG_WRITE
| PAG_COMMIT
| OBJ_GIVEABLE
| OBJ_ANY
);
284 memcpy( pSharedText
, aString
.getStr(), aString
.getLength() * 2 + 2 );
287 debug_printf("Os2Clipboard::setContents SetClipbrdData text done\n");
289 } catch ( UnsupportedFlavorException
&) {
290 debug_printf("Os2Clipboard::setContents UnsupportedFlavorException (no text)\n");
293 // try bitmap transfer data (if any)
296 Any aAnyB
= m_aContents
->getTransferData( nFlavorBitmap
);
297 if (aAnyB
.hasValue())
299 hbm
= OOoBmpToOS2Handle( aAnyB
);
300 debug_printf("Os2Clipboard::setContents SetClipbrdData bitmap done\n");
302 } catch ( UnsupportedFlavorException
&) {
303 debug_printf("Os2Clipboard::setContents UnsupportedFlavorException (no bitmap)\n");
307 if ( UWinOpenClipbrd( hAB
) && (pSharedText
|| hbm
))
309 // set the flag, so we will ignore the next WM_DRAWCLIPBOARD
310 // since we generate it with following code.
311 m_bInSetClipboardData
= sal_True
;
312 UWinEmptyClipbrd( hAB
);
313 // give pointer to clipboard (it will become owner of pSharedText!)
315 UWinSetClipbrdData( hAB
, (ULONG
) pSharedText
, UCLIP_CF_UNICODETEXT
, CFI_POINTER
);
316 // update internal handle to avoid detection of this text as new data
317 hText
= (ULONG
)pSharedText
;
319 // give bitmap to clipboard
321 UWinSetClipbrdData( hAB
, (ULONG
) hbm
, UCLIP_CF_BITMAP
, CFI_HANDLE
);
322 // update internal handle to avoid detection of this bitmap as new data
325 // reset the flag, so we will not ignore next WM_DRAWCLIPBOARD
326 m_bInSetClipboardData
= sal_False
;
327 UWinCloseClipbrd( hAB
);
332 OUString SAL_CALL
Os2Clipboard::getName() throw( RuntimeException
)
334 debug_printf("Os2Clipboard::getName\n");
338 sal_Int8 SAL_CALL
Os2Clipboard::getRenderingCapabilities() throw( RuntimeException
)
340 debug_printf("Os2Clipboard::getRenderingCapabilities\n");
344 //========================================================================
345 // XClipboardNotifier
346 //========================================================================
348 void SAL_CALL
Os2Clipboard::addClipboardListener( const Reference
< XClipboardListener
>& listener
) throw( RuntimeException
)
350 debug_printf("Os2Clipboard::addClipboardListener\n");
351 MutexGuard
aGuard( rBHelper
.rMutex
);
352 OSL_ENSURE( !rBHelper
.bInDispose
, "do not add listeners in the dispose call" );
353 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
354 if (!rBHelper
.bInDispose
&& !rBHelper
.bDisposed
)
355 rBHelper
.aLC
.addInterface( getCppuType( (const ::com::sun::star::uno::Reference
< XClipboardListener
> *) 0), listener
);
358 void SAL_CALL
Os2Clipboard::removeClipboardListener( const Reference
< XClipboardListener
>& listener
) throw( RuntimeException
)
360 debug_printf("Os2Clipboard::removeClipboardListener\n");
361 MutexGuard
aGuard( rBHelper
.rMutex
);
362 OSL_ENSURE( !rBHelper
.bDisposed
, "object is disposed" );
363 if (!rBHelper
.bInDispose
&& !rBHelper
.bDisposed
)
364 rBHelper
.aLC
.removeInterface( getCppuType( (const Reference
< XClipboardListener
> *) 0 ), listener
); \
367 // ------------------------------------------------------------------------
369 void SAL_CALL
Os2Clipboard::notifyAllClipboardListener( )
371 if ( !rBHelper
.bDisposed
)
373 ClearableMutexGuard
aGuard( rBHelper
.rMutex
);
374 if ( !rBHelper
.bDisposed
)
378 ClearableMutexGuard
aGuard(m_aMutex
);
379 // copy member references on stack so they can be called
380 // without having the mutex
381 Reference
< XClipboardOwner
> xOwner( m_aOwner
);
382 Reference
< XTransferable
> xTrans( m_aContents
);
389 // inform previous owner of lost ownership
391 xOwner
->lostOwnership(static_cast < XClipboard
* > (this), m_aContents
);
393 OInterfaceContainerHelper
* pICHelper
= rBHelper
.aLC
.getContainer(
394 getCppuType( ( Reference
< XClipboardListener
> * ) 0 ) );
400 OInterfaceIteratorHelper
iter(*pICHelper
);
402 m_aContents
= new Os2Transferable( static_cast< OWeakObject
* >(this) );
403 ClipboardEvent
aClipbEvent(static_cast<XClipboard
*>(this), m_aContents
);
405 while(iter
.hasMoreElements())
409 Reference
<XClipboardListener
> xCBListener(iter
.next(), UNO_QUERY
);
410 if (xCBListener
.is())
411 xCBListener
->changedContents(aClipbEvent
);
413 catch(RuntimeException
&)
415 OSL_ENSURE( false, "RuntimeException caught" );
416 debug_printf( "RuntimeException caught" );
420 catch(const ::com::sun::star::lang::DisposedException
&)
422 OSL_ENSURE(false, "Service Manager disposed");
423 debug_printf( "Service Manager disposed");
425 // no further clipboard changed notifications
426 //m_pImpl->unregisterClipboardViewer();
434 // ------------------------------------------------------------------------
436 Sequence
< OUString
> SAL_CALL
Os2Clipboard_getSupportedServiceNames()
438 Sequence
< OUString
> aRet(1);
439 aRet
[0] = OUString::createFromAscii( OS2_CLIPBOARD_SERVICE_NAME
);
443 // ------------------------------------------------------------------------
445 Reference
< XInterface
> SAL_CALL
Os2Clipboard_createInstance(
446 const Reference
< XMultiServiceFactory
> & xMultiServiceFactory
)
448 return Reference
< XInterface
>( ( OWeakObject
* ) new Os2Clipboard());