1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
30 #include <com/sun/star/uno/Any.hxx>
31 #include <com/sun/star/uno/Reference.hxx>
32 #include <com/sun/star/util/XCloseable.hpp>
33 #include <com/sun/star/util/XCloseBroadcaster.hpp>
34 #include <com/sun/star/util/XCloseListener.hpp>
35 #include <com/sun/star/frame/XFrame.hpp>
36 #include <com/sun/star/frame/XDesktop.hpp>
37 #include <com/sun/star/beans/XPropertySet.hpp>
38 #include <cppuhelper/implbase1.hxx>
39 #include <comphelper/processfactory.hxx>
42 #include <tools/svwin.h>
43 #include <tools/stream.hxx>
44 #include <vos/mutex.hxx>
45 #include <vos/module.hxx>
46 #include <vcl/svapp.hxx>
47 #include <vcl/wrkwin.hxx>
48 #include <vcl/sysdata.hxx>
49 #include <vcl/salbtype.hxx>
50 #include "scanner.hxx"
52 #pragma warning (push,1)
53 #pragma warning (disable:4668)
54 #include "twain/twain.h"
57 using namespace ::com::sun::star
;
63 #define TWAIN_SELECT 0x00000001UL
64 #define TWAIN_ACQUIRE 0x00000002UL
65 #define TWAIN_TERMINATE 0xFFFFFFFFUL
67 #define TWAIN_EVENT_NONE 0x00000000UL
68 #define TWAIN_EVENT_QUIT 0x00000001UL
69 #define TWAIN_EVENT_SCANNING 0x00000002UL
70 #define TWAIN_EVENT_XFER 0x00000004UL
73 #define PTWAINMSG MSG*
74 #define FIXTODOUBLE( nFix ) ((double)nFix.Whole+(double)nFix.Frac/65536.)
75 #define FIXTOLONG( nFix ) ((long)floor(FIXTODOUBLE(nFix)+0.5))
78 #define TWAIN_LIBNAME "TWAIN.DLL"
79 #define TWAIN_FUNCNAME "DSM_Entry"
81 #define TWAIN_LIBNAME "TWAIN_32.DLL"
82 #define TWAIN_FUNCNAME "DSM_Entry"
92 TWAIN_STATE_SCANNING
= 1,
94 TWAIN_STATE_CANCELED
= 3
101 class ImpTwain
: public ::cppu::WeakImplHelper1
< util::XCloseListener
>
103 friend LRESULT CALLBACK
TwainMsgProc( int nCode
, WPARAM wParam
, LPARAM lParam
);
105 uno::Reference
< uno::XInterface
> mxSelfRef
;
106 uno::Reference
< scanner::XScannerManager
> mxMgr
;
107 ScannerManager
& mrMgr
;
108 TW_IDENTITY aAppIdent
;
109 TW_IDENTITY aSrcIdent
;
112 NAMESPACE_VOS( OModule
)* pMod
;
116 bool mbCloseFrameOnExit
;
118 bool ImplHandleMsg( void* pMsg
);
120 void ImplOpenSourceManager();
121 void ImplOpenSource();
122 bool ImplEnableSource();
124 void ImplFallback( ULONG nEvent
);
125 void ImplSendCloseEvent();
126 void ImplDeregisterCloseListener();
127 void ImplRegisterCloseListener();
128 uno::Reference
< frame::XFrame
> ImplGetActiveFrame();
129 uno::Reference
< util::XCloseBroadcaster
> ImplGetActiveFrameCloseBroadcaster();
131 DECL_LINK( ImplFallbackHdl
, void* );
132 DECL_LINK( ImplDestroyHdl
, void* );
134 // from util::XCloseListener
135 virtual void SAL_CALL
queryClosing( const lang::EventObject
& Source
, sal_Bool GetsOwnership
) throw (util::CloseVetoException
, uno::RuntimeException
);
136 virtual void SAL_CALL
notifyClosing( const lang::EventObject
& Source
) throw (uno::RuntimeException
);
138 // from lang::XEventListener
139 virtual void SAL_CALL
disposing( const lang::EventObject
& Source
) throw (uno::RuntimeException
);
143 ImpTwain( ScannerManager
& rMgr
, const Link
& rNotifyLink
);
156 static ImpTwain
* pImpTwainInstance
= NULL
;
158 // -------------------------------------------------------------------------
160 LRESULT CALLBACK
TwainWndProc( HWND hWnd
,UINT nMsg
, WPARAM nPar1
, LPARAM nPar2
)
162 return DefWindowProc( hWnd
, nMsg
, nPar1
, nPar2
);
165 // -------------------------------------------------------------------------
167 LRESULT CALLBACK
TwainMsgProc( int nCode
, WPARAM wParam
, LPARAM lParam
)
169 MSG
* pMsg
= (MSG
*) lParam
;
171 if( ( nCode
< 0 ) || ( pImpTwainInstance
->hTwainWnd
!= pMsg
->hwnd
) || !pImpTwainInstance
->ImplHandleMsg( (void*) lParam
) )
173 return CallNextHookEx( pImpTwainInstance
->hTwainHook
, nCode
, wParam
, lParam
);
177 pMsg
->message
= WM_USER
;
184 // -----------------------------------------------------------------------------
186 // #107835# hold reference to ScannerManager, to prevent premature death
187 ImpTwain::ImpTwain( ScannerManager
& rMgr
, const Link
& rNotifyLink
) :
189 mxMgr( uno::Reference
< scanner::XScannerManager
>( static_cast< OWeakObject
* >( &rMgr
), uno::UNO_QUERY
) ),
190 aNotifyLink( rNotifyLink
),
196 mbCloseFrameOnExit( false )
198 // setup TWAIN window
199 pImpTwainInstance
= this;
202 aAppIdent
.Version
.MajorNum
= 1;
203 aAppIdent
.Version
.MinorNum
= 0;
204 aAppIdent
.Version
.Language
= TWLG_USA
;
205 aAppIdent
.Version
.Country
= TWCY_USA
;
206 aAppIdent
.ProtocolMajor
= TWON_PROTOCOLMAJOR
;
207 aAppIdent
.ProtocolMinor
= TWON_PROTOCOLMINOR
;
208 aAppIdent
.SupportedGroups
= DG_IMAGE
| DG_CONTROL
;
209 strncpy( aAppIdent
.Version
.Info
, "8.0", 32 );
210 aAppIdent
.Version
.Info
[32] = aAppIdent
.Version
.Info
[33] = 0;
211 strncpy( aAppIdent
.Manufacturer
, "Sun Microsystems", 32 );
212 aAppIdent
.Manufacturer
[32] = aAppIdent
.Manufacturer
[33] = 0;
213 strncpy( aAppIdent
.ProductFamily
,"Office", 32 );
214 aAppIdent
.ProductFamily
[32] = aAppIdent
.ProductFamily
[33] = 0;
215 strncpy( aAppIdent
.ProductName
, "Office", 32 );
216 aAppIdent
.ProductName
[32] = aAppIdent
.ProductName
[33] = 0;
218 WNDCLASS aWc
= { 0, &TwainWndProc
, 0, sizeof( WNDCLASS
), GetModuleHandle( NULL
), NULL
, NULL
, NULL
, NULL
, "TwainClass" };
219 RegisterClass( &aWc
);
221 hTwainWnd
= CreateWindowEx( WS_EX_TOPMOST
, aWc
.lpszClassName
, "TWAIN", 0, 0, 0, 0, 0, HWND_DESKTOP
, NULL
, aWc
.hInstance
, 0 );
222 hTwainHook
= SetWindowsHookEx( WH_GETMESSAGE
, &TwainMsgProc
, NULL
, GetCurrentThreadId() );
224 // #107835# block destruction until ImplDestroyHdl is called
225 mxSelfRef
= static_cast< ::cppu::OWeakObject
* >( this );
228 // -----------------------------------------------------------------------------
230 ImpTwain::~ImpTwain()
232 // are we responsible for application shutdown?
233 if( mbCloseFrameOnExit
)
234 ImplSendCloseEvent();
237 // -----------------------------------------------------------------------------
239 void ImpTwain::Destroy()
241 ImplFallback( TWAIN_EVENT_NONE
);
242 Application::PostUserEvent( LINK( this, ImpTwain
, ImplDestroyHdl
), NULL
);
245 // -----------------------------------------------------------------------------
247 bool ImpTwain::SelectSource()
249 TW_UINT16 nRet
= TWRC_FAILURE
;
251 ImplOpenSourceManager();
257 aIdent
.Id
= 0, aIdent
.ProductName
[ 0 ] = '\0';
258 aNotifyLink
.Call( (void*) TWAIN_EVENT_SCANNING
);
259 nRet
= PFUNC( &aAppIdent
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_USERSELECT
, &aIdent
);
262 ImplFallback( TWAIN_EVENT_QUIT
);
264 return( TWRC_SUCCESS
== nRet
);
267 // -----------------------------------------------------------------------------
269 bool ImpTwain::InitXfer()
273 ImplOpenSourceManager();
280 bRet
= ImplEnableSource();
284 ImplFallback( TWAIN_EVENT_QUIT
);
289 // -----------------------------------------------------------------------------
291 void ImpTwain::ImplOpenSourceManager()
295 pMod
= new ::vos::OModule( ::rtl::OUString() );
297 if( pMod
->load( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( TWAIN_LIBNAME
) ) ) )
301 if( ( ( pDSM
= (DSMENTRYPROC
) pMod
->getSymbol( String( RTL_CONSTASCII_USTRINGPARAM( TWAIN_FUNCNAME
) ) ) ) != NULL
) &&
302 ( PFUNC( &aAppIdent
, NULL
, DG_CONTROL
, DAT_PARENT
, MSG_OPENDSM
, &hTwainWnd
) == TWRC_SUCCESS
) )
315 // -----------------------------------------------------------------------------
317 void ImpTwain::ImplOpenSource()
321 if( ( PFUNC( &aAppIdent
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_GETDEFAULT
, &aSrcIdent
) == TWRC_SUCCESS
) &&
322 ( PFUNC( &aAppIdent
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_OPENDS
, &aSrcIdent
) == TWRC_SUCCESS
) )
324 TW_CAPABILITY aCap
= { CAP_XFERCOUNT
, TWON_ONEVALUE
, GlobalAlloc( GHND
, sizeof( TW_ONEVALUE
) ) };
325 TW_ONEVALUE
* pVal
= (TW_ONEVALUE
*) GlobalLock( aCap
.hContainer
);
327 pVal
->ItemType
= TWTY_INT16
, pVal
->Item
= 1;
328 GlobalUnlock( aCap
.hContainer
);
329 PFUNC( &aAppIdent
, &aSrcIdent
, DG_CONTROL
, DAT_CAPABILITY
, MSG_SET
, &aCap
);
330 GlobalFree( aCap
.hContainer
);
336 // -----------------------------------------------------------------------------
338 bool ImpTwain::ImplEnableSource()
344 TW_USERINTERFACE aUI
= { true, true, hTwainWnd
};
346 aNotifyLink
.Call( (void*) TWAIN_EVENT_SCANNING
);
349 // #107835# register as vetoable close listener, to prevent application to die under us
350 ImplRegisterCloseListener();
352 if( PFUNC( &aAppIdent
, &aSrcIdent
, DG_CONTROL
, DAT_USERINTERFACE
, MSG_ENABLEDS
, &aUI
) == TWRC_SUCCESS
)
360 // #107835# deregister as vetoable close listener, dialog failed
361 ImplDeregisterCloseListener();
368 // -----------------------------------------------------------------------------
370 bool ImpTwain::ImplHandleMsg( void* pMsg
)
373 PTWAINMSG pMess
= (PTWAINMSG
) pMsg
;
374 TW_EVENT aEvt
= { pMess
, MSG_NULL
};
376 nRet
= PFUNC( &aAppIdent
, &aSrcIdent
, DG_CONTROL
, DAT_EVENT
, MSG_PROCESSEVENT
, &aEvt
);
378 if( aEvt
.TWMessage
!= MSG_NULL
)
380 switch( aEvt
.TWMessage
)
384 ULONG nEvent
= TWAIN_EVENT_QUIT
;
391 if( mrMgr
.GetData() )
392 nEvent
= TWAIN_EVENT_XFER
;
395 ImplFallback( nEvent
);
400 ImplFallback( TWAIN_EVENT_QUIT
);
408 nRet
= TWRC_NOTDSEVENT
;
410 return( TWRC_DSEVENT
== nRet
);
413 // -----------------------------------------------------------------------------
415 void ImpTwain::ImplXfer()
421 long nWidth
, nHeight
, nXRes
, nYRes
;
423 if( PFUNC( &aAppIdent
, &aSrcIdent
, DG_IMAGE
, DAT_IMAGEINFO
, MSG_GET
, &aInfo
) == TWRC_SUCCESS
)
425 nWidth
= aInfo
.ImageWidth
;
426 nHeight
= aInfo
.ImageLength
;
427 nXRes
= FIXTOLONG( aInfo
.XResolution
);
428 nYRes
= FIXTOLONG( aInfo
.YResolution
);
431 nWidth
= nHeight
= nXRes
= nYRes
= -1L;
433 switch( PFUNC( &aAppIdent
, &aSrcIdent
, DG_IMAGE
, DAT_IMAGENATIVEXFER
, MSG_GET
, &hDIB
) )
439 case( TWRC_XFERDONE
):
443 if( ( nXRes
!= -1 ) && ( nYRes
!= - 1 ) && ( nWidth
!= - 1 ) && ( nHeight
!= - 1 ) )
445 // set resolution of bitmap
446 BITMAPINFOHEADER
* pBIH
= (BITMAPINFOHEADER
*) GlobalLock( (HGLOBAL
) hDIB
);
447 static const double fFactor
= 100.0 / 2.54;
449 pBIH
->biXPelsPerMeter
= FRound( fFactor
* nXRes
);
450 pBIH
->biYPelsPerMeter
= FRound( fFactor
* nYRes
);
452 GlobalUnlock( (HGLOBAL
) hDIB
);
455 mrMgr
.SetData( (void*)(long) hDIB
);
458 GlobalFree( (HGLOBAL
) hDIB
);
470 // -----------------------------------------------------------------------------
472 void ImpTwain::ImplFallback( ULONG nEvent
)
474 Application::PostUserEvent( LINK( this, ImpTwain
, ImplFallbackHdl
), (void*) nEvent
);
477 // -----------------------------------------------------------------------------
479 IMPL_LINK( ImpTwain
, ImplFallbackHdl
, void*, pData
)
481 const ULONG nEvent
= (ULONG
) pData
;
482 bool bFallback
= true;
489 TW_PENDINGXFERS aXfers
;
491 if( PFUNC( &aAppIdent
, &aSrcIdent
, DG_CONTROL
, DAT_PENDINGXFERS
, MSG_ENDXFER
, &aXfers
) == TWRC_SUCCESS
)
493 if( aXfers
.Count
!= 0 )
494 PFUNC( &aAppIdent
, &aSrcIdent
, DG_CONTROL
, DAT_PENDINGXFERS
, MSG_RESET
, &aXfers
);
503 TW_USERINTERFACE aUI
= { true, true, hTwainWnd
};
505 PFUNC( &aAppIdent
, &aSrcIdent
, DG_CONTROL
, DAT_USERINTERFACE
, MSG_DISABLEDS
, &aUI
);
508 // #107835# deregister as vetoable close listener
509 ImplDeregisterCloseListener();
515 PFUNC( &aAppIdent
, NULL
, DG_CONTROL
, DAT_IDENTITY
, MSG_CLOSEDS
, &aSrcIdent
);
522 PFUNC( &aAppIdent
, NULL
, DG_CONTROL
, DAT_PARENT
, MSG_CLOSEDSM
, &hTwainWnd
);
537 if( nEvent
!= TWAIN_EVENT_NONE
)
538 aNotifyLink
.Call( (void*) nEvent
);
546 ImplFallback( nEvent
);
551 // -----------------------------------------------------------------------------
553 IMPL_LINK( ImpTwain
, ImplDestroyHdl
, void*, /*p*/ )
556 DestroyWindow( hTwainWnd
);
559 UnhookWindowsHookEx( hTwainHook
);
561 // #107835# permit destruction of ourselves (normally, refcount
562 // should drop to zero exactly here)
564 pImpTwainInstance
= NULL
;
569 // -----------------------------------------------------------------------------
571 uno::Reference
< frame::XFrame
> ImpTwain::ImplGetActiveFrame()
575 uno::Reference
< lang::XMultiServiceFactory
> xMgr( ::comphelper::getProcessServiceFactory() );
579 // query desktop instance
580 uno::Reference
< frame::XDesktop
> xDesktop( xMgr
->createInstance(
581 OUString::createFromAscii( "com.sun.star.frame.Desktop" ) ), uno::UNO_QUERY
);
585 // query property set from desktop, which contains the currently active frame
586 uno::Reference
< beans::XPropertySet
> xDesktopProps( xDesktop
, uno::UNO_QUERY
);
588 if( xDesktopProps
.is() )
590 uno::Any aActiveFrame
;
594 aActiveFrame
= xDesktopProps
->getPropertyValue(
595 OUString::createFromAscii( "ActiveFrame" ) );
597 catch( const beans::UnknownPropertyException
& )
600 DBG_ERROR("ImpTwain::ImplGetActiveFrame: ActiveFrame property unknown, cannot determine active frame!");
601 return uno::Reference
< frame::XFrame
>();
604 uno::Reference
< frame::XFrame
> xActiveFrame
;
606 if( (aActiveFrame
>>= xActiveFrame
) &&
615 catch( const uno::Exception
& )
619 DBG_ERROR("ImpTwain::ImplGetActiveFrame: Could not determine active frame!");
620 return uno::Reference
< frame::XFrame
>();
623 // -----------------------------------------------------------------------------
625 uno::Reference
< util::XCloseBroadcaster
> ImpTwain::ImplGetActiveFrameCloseBroadcaster()
629 return uno::Reference
< util::XCloseBroadcaster
>( ImplGetActiveFrame(), uno::UNO_QUERY
);
631 catch( const uno::Exception
& )
635 DBG_ERROR("ImpTwain::ImplGetActiveFrameCloseBroadcaster: Could determine close broadcaster on active frame!");
636 return uno::Reference
< util::XCloseBroadcaster
>();
639 // -----------------------------------------------------------------------------
641 void ImpTwain::ImplRegisterCloseListener()
645 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster( ImplGetActiveFrameCloseBroadcaster() );
647 if( xCloseBroadcaster
.is() )
649 xCloseBroadcaster
->addCloseListener(this);
650 return; // successfully registered as a close listener
654 // interface unknown. don't register, then
655 DBG_ERROR("ImpTwain::ImplRegisterCloseListener: XFrame has no XCloseBroadcaster!");
659 catch( const uno::Exception
& )
663 DBG_ERROR("ImpTwain::ImplRegisterCloseListener: Could not register as close listener!");
666 // -----------------------------------------------------------------------------
668 void ImpTwain::ImplDeregisterCloseListener()
672 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster(
673 ImplGetActiveFrameCloseBroadcaster() );
675 if( xCloseBroadcaster
.is() )
677 xCloseBroadcaster
->removeCloseListener(this);
678 return; // successfully deregistered as a close listener
682 // interface unknown. don't deregister, then
683 DBG_ERROR("ImpTwain::ImplDeregisterCloseListener: XFrame has no XCloseBroadcaster!");
687 catch( const uno::Exception
& )
691 DBG_ERROR("ImpTwain::ImplDeregisterCloseListener: Could not deregister as close listener!");
694 // -----------------------------------------------------------------------------
696 void SAL_CALL
ImpTwain::queryClosing( const lang::EventObject
& /*Source*/, sal_Bool GetsOwnership
) throw (util::CloseVetoException
, uno::RuntimeException
)
698 // shall we re-send the close query later on?
699 mbCloseFrameOnExit
= GetsOwnership
;
701 // the sole purpose of this listener is to forbid closing of the listened-at frame
702 throw util::CloseVetoException();
705 // -----------------------------------------------------------------------------
707 void SAL_CALL
ImpTwain::notifyClosing( const lang::EventObject
& /*Source*/ ) throw (uno::RuntimeException
)
710 DBG_ERROR("ImpTwain::notifyClosing called, but we vetoed the closing before!");
713 // -----------------------------------------------------------------------------
715 void SAL_CALL
ImpTwain::disposing( const lang::EventObject
& /*Source*/ ) throw (uno::RuntimeException
)
717 // we're not holding any references to the frame, thus noop
720 // -----------------------------------------------------------------------------
722 void ImpTwain::ImplSendCloseEvent()
726 uno::Reference
< util::XCloseable
> xCloseable( ImplGetActiveFrame(), uno::UNO_QUERY
);
728 if( xCloseable
.is() )
729 xCloseable
->close( true );
731 catch( const uno::Exception
& )
735 DBG_ERROR("ImpTwain::ImplSendCloseEvent: Could not send required close broadcast!");
745 uno::Reference
< lang::XEventListener
> mxListener
;
746 uno::Reference
< scanner::XScannerManager
> mxMgr
;
747 const ScannerManager
* mpCurMgr
;
748 ImpTwain
* mpImpTwain
;
751 DECL_LINK( ImpNotifyHdl
, ImpTwain
* );
758 bool SelectSource( ScannerManager
& rMgr
);
759 bool PerformTransfer( ScannerManager
& rMgr
, const uno::Reference
< lang::XEventListener
>& rxListener
);
761 TwainState
GetState() const { return meState
; }
764 // ------------------------------------------------------------------------
769 meState( TWAIN_STATE_NONE
)
773 // ------------------------------------------------------------------------
778 mpImpTwain
->Destroy();
781 // ------------------------------------------------------------------------
783 bool Twain::SelectSource( ScannerManager
& rMgr
)
789 // #107835# hold reference to ScannerManager, to prevent premature death
790 mxMgr
= uno::Reference
< scanner::XScannerManager
>( static_cast< OWeakObject
* >( const_cast< ScannerManager
* >( mpCurMgr
= &rMgr
) ),
793 meState
= TWAIN_STATE_NONE
;
794 mpImpTwain
= new ImpTwain( rMgr
, LINK( this, Twain
, ImpNotifyHdl
) );
795 bRet
= mpImpTwain
->SelectSource();
803 // ------------------------------------------------------------------------
805 bool Twain::PerformTransfer( ScannerManager
& rMgr
, const uno::Reference
< lang::XEventListener
>& rxListener
)
811 // #107835# hold reference to ScannerManager, to prevent premature death
812 mxMgr
= uno::Reference
< scanner::XScannerManager
>( static_cast< OWeakObject
* >( const_cast< ScannerManager
* >( mpCurMgr
= &rMgr
) ),
815 mxListener
= rxListener
;
816 meState
= TWAIN_STATE_NONE
;
817 mpImpTwain
= new ImpTwain( rMgr
, LINK( this, Twain
, ImpNotifyHdl
) );
818 bRet
= mpImpTwain
->InitXfer();
826 // ------------------------------------------------------------------------
828 IMPL_LINK( Twain
, ImpNotifyHdl
, ImpTwain
*, nEvent
)
830 switch( (ULONG
)(void*) nEvent
)
832 case( TWAIN_EVENT_SCANNING
):
833 meState
= TWAIN_STATE_SCANNING
;
836 case( TWAIN_EVENT_QUIT
):
838 if( meState
!= TWAIN_STATE_DONE
)
839 meState
= TWAIN_STATE_CANCELED
;
843 mpImpTwain
->Destroy();
848 if( mxListener
.is() )
849 mxListener
->disposing( lang::EventObject( mxMgr
) );
855 case( TWAIN_EVENT_XFER
):
859 meState
= ( mpCurMgr
->GetData() ? TWAIN_STATE_DONE
: TWAIN_STATE_CANCELED
);
861 mpImpTwain
->Destroy();
865 if( mxListener
.is() )
866 mxListener
->disposing( lang::EventObject( mxMgr
) );
886 // ------------------
887 // - ScannerManager -
888 // ------------------
890 void ScannerManager::DestroyData()
894 GlobalFree( (HGLOBAL
)(long) mpData
);
899 // -----------------------------------------------------------------------------
901 AWT::Size
ScannerManager::getSize() throw()
904 HGLOBAL hDIB
= (HGLOBAL
)(long) mpData
;
908 BITMAPINFOHEADER
* pBIH
= (BITMAPINFOHEADER
*) GlobalLock( hDIB
);
912 aRet
.Width
= pBIH
->biWidth
;
913 aRet
.Height
= pBIH
->biHeight
;
916 aRet
.Width
= aRet
.Height
= 0;
918 GlobalUnlock( hDIB
);
921 aRet
.Width
= aRet
.Height
= 0;
926 // -----------------------------------------------------------------------------
928 SEQ( sal_Int8
) ScannerManager::getDIB() throw()
930 SEQ( sal_Int8
) aRet
;
934 HGLOBAL hDIB
= (HGLOBAL
)(long) mpData
;
935 const sal_uInt32 nDIBSize
= GlobalSize( hDIB
);
936 BITMAPINFOHEADER
* pBIH
= (BITMAPINFOHEADER
*) GlobalLock( hDIB
);
940 sal_uInt32 nColEntries
;
942 switch( pBIH
->biBitCount
)
947 nColEntries
= pBIH
->biClrUsed
? pBIH
->biClrUsed
: ( 1 << pBIH
->biBitCount
);
951 nColEntries
= pBIH
->biClrUsed
? pBIH
->biClrUsed
: 0;
957 nColEntries
= pBIH
->biClrUsed
;
959 if( pBIH
->biCompression
== BI_BITFIELDS
)
969 aRet
= SEQ( sal_Int8
)( sizeof( BITMAPFILEHEADER
) + nDIBSize
);
971 sal_Int8
* pBuf
= aRet
.getArray();
972 SvMemoryStream
* pMemStm
= new SvMemoryStream( (char*) pBuf
, sizeof( BITMAPFILEHEADER
), STREAM_WRITE
);
974 *pMemStm
<< 'B' << 'M' << (sal_uInt32
) 0 << (sal_uInt32
) 0;
975 *pMemStm
<< (sal_uInt32
) ( sizeof( BITMAPFILEHEADER
) + pBIH
->biSize
+ ( nColEntries
* sizeof( RGBQUAD
) ) );
978 memcpy( pBuf
+ sizeof( BITMAPFILEHEADER
), pBIH
, nDIBSize
);
981 GlobalUnlock( hDIB
);
988 // -----------------------------------------------------------------------------
990 SEQ( ScannerContext
) SAL_CALL
ScannerManager::getAvailableScanners() throw()
992 vos::OGuard
aGuard( maProtector
);
993 SEQ( ScannerContext
) aRet( 1 );
995 aRet
.getArray()[0].ScannerName
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) );
996 aRet
.getArray()[0].InternalData
= 0;
1001 // -----------------------------------------------------------------------------
1003 BOOL SAL_CALL
ScannerManager::configureScanner( ScannerContext
& rContext
)
1004 throw( ScannerException
)
1006 vos::OGuard
aGuard( maProtector
);
1007 uno::Reference
< XScannerManager
> xThis( this );
1009 if( rContext
.InternalData
!= 0 || rContext
.ScannerName
!= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) ) )
1010 throw ScannerException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scanner does not exist" ) ), xThis
, ScanError_InvalidContext
);
1014 return aTwain
.SelectSource( *this );
1017 // -----------------------------------------------------------------------------
1019 void SAL_CALL
ScannerManager::startScan( const ScannerContext
& rContext
, const uno::Reference
< lang::XEventListener
>& rxListener
)
1020 throw( ScannerException
)
1022 vos::OGuard
aGuard( maProtector
);
1023 uno::Reference
< XScannerManager
> xThis( this );
1025 if( rContext
.InternalData
!= 0 || rContext
.ScannerName
!= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) ) )
1026 throw ScannerException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scanner does not exist" ) ), xThis
, ScanError_InvalidContext
);
1029 aTwain
.PerformTransfer( *this, rxListener
);
1032 // -----------------------------------------------------------------------------
1034 ScanError SAL_CALL
ScannerManager::getError( const ScannerContext
& rContext
)
1035 throw( ScannerException
)
1037 vos::OGuard
aGuard( maProtector
);
1038 uno::Reference
< XScannerManager
> xThis( this );
1040 if( rContext
.InternalData
!= 0 || rContext
.ScannerName
!= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TWAIN" ) ) )
1041 throw ScannerException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Scanner does not exist" ) ), xThis
, ScanError_InvalidContext
);
1043 return( ( aTwain
.GetState() == TWAIN_STATE_CANCELED
) ? ScanError_ScanCanceled
: ScanError_ScanErrorNone
);
1046 // -----------------------------------------------------------------------------
1048 uno::Reference
< awt::XBitmap
> SAL_CALL
ScannerManager::getBitmap( const ScannerContext
& /*rContext*/ )
1049 throw( ScannerException
)
1051 vos::OGuard
aGuard( maProtector
);
1052 return uno::Reference
< awt::XBitmap
>( this );